XrdWait41.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                          X r d W a i t 4 1 . c c                           */
00004 /*                                                                            */
00005 /* (c) 2009 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*       All Rights Reserved. See XrdInfo.cc for complete License Terms       */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //           $Id: XrdWait41.cc 30949 2009-11-02 16:37:58Z ganis $
00012 
00013 const char *XrdWait41CVSID = "$Id: XrdWait41.cc 30949 2009-11-02 16:37:58Z ganis $";
00014 
00015 /* This unitily waits for the first of n file locks. The syntax is:
00016 
00017    wait41 <path> [<path> [. . .]]
00018 
00019 */
00020 
00021 /******************************************************************************/
00022 /*                         i n c l u d e   f i l e s                          */
00023 /******************************************************************************/
00024   
00025 #include <ctype.h>
00026 #include <dirent.h>
00027 #include <errno.h>
00028 #include <fcntl.h>
00029 #include <signal.h>
00030 #include <stdlib.h>
00031 #include <stdio.h>
00032 #include <string.h>
00033 #include <strings.h>
00034 #include <unistd.h>
00035 #include <sys/param.h>
00036 #include <sys/stat.h>
00037 #include <sys/types.h>
00038 
00039 #include "XrdOuc/XrdOucTList.hh"
00040 #include "XrdSys/XrdSysHeaders.hh"
00041 #include "XrdSys/XrdSysPlatform.hh"
00042 #include "XrdSys/XrdSysPthread.hh"
00043 
00044 /******************************************************************************/
00045 /*                         L o c a l   C l a s s e s                          */
00046 /******************************************************************************/
00047 
00048 class XrdW41Gate
00049 {
00050 public:
00051 
00052 static void   Serialize(XrdOucTList *gfP, int Wait=1);
00053 
00054 static int    Wait41(XrdOucTList *fP);
00055 
00056        XrdW41Gate() {}
00057       ~XrdW41Gate() {}
00058 
00059 private:
00060 static XrdSysMutex      gateMutex;
00061 static XrdSysSemaphore  gateSem;
00062 static int              gateOpen;
00063 };
00064 
00065 XrdSysMutex     XrdW41Gate::gateMutex;
00066 XrdSysSemaphore XrdW41Gate::gateSem(0);
00067 int             XrdW41Gate::gateOpen = 0;
00068 
00069 class XrdW41Dirs
00070 {
00071 public:
00072 
00073 static XrdOucTList *Expand(const char *Path, XrdOucTList *ptl);
00074 };
00075   
00076 /******************************************************************************/
00077 /*            E x t e r n a l   T h r e a d   I n t e r f a c e s             */
00078 /******************************************************************************/
00079 
00080 namespace XrdWait41
00081 {
00082 void *GateWait(void *parg)
00083 {
00084    XrdOucTList *fP = (XrdOucTList *)parg;
00085 
00086 // Serialize
00087 //
00088    XrdW41Gate::Serialize(fP);
00089    return (void *)0;
00090 }
00091 }
00092 
00093 using namespace XrdWait41;
00094 
00095 /******************************************************************************/
00096 /*                                  m a i n                                   */
00097 /******************************************************************************/
00098   
00099 int main(int argc, char *argv[])
00100 {
00101    sigset_t myset;
00102    XrdOucTList *gateFiles = 0;
00103    struct stat Stat;
00104    const char *eText;
00105    char buff[8];
00106    int i;
00107 
00108 // Turn off sigpipe and host a variety of others before we start any threads
00109 //
00110    signal(SIGPIPE, SIG_IGN);  // Solaris optimization
00111    sigemptyset(&myset);
00112    sigaddset(&myset, SIGPIPE);
00113    sigaddset(&myset, SIGCHLD);
00114    pthread_sigmask(SIG_BLOCK, &myset, NULL);
00115 
00116 // Set the default stack size here
00117 //
00118    if (sizeof(long) > 4) XrdSysThread::setStackSize((size_t)1048576);
00119       else               XrdSysThread::setStackSize((size_t)786432);
00120 
00121 // Construct a list of files. For each directory, expand that to a list
00122 //
00123    for (i = 1; i < argc; i++)
00124        {if (stat(argv[i], &Stat))
00125            {eText = strerror(errno);
00126             cerr <<"wait41: " <<eText <<" processing " <<argv[i] <<endl;
00127             continue;
00128            }
00129              if (S_ISREG(Stat.st_mode))
00130                 gateFiles =    new XrdOucTList(argv[i],0,gateFiles);
00131         else if (S_ISDIR(Stat.st_mode))
00132                 gateFiles = XrdW41Dirs::Expand(argv[i],  gateFiles);
00133        }
00134 
00135 // If we have no waiters then fail
00136 //
00137    if (!gateFiles)
00138       {cerr <<"wait41: Nothing to wait on!" <<endl;
00139        cout <<"BAD\n" <<endl;
00140        _exit(1);
00141       }
00142 
00143 // Now wait for the first lock
00144 //
00145    eText = (XrdW41Gate::Wait41(gateFiles) ? "OK\n" : "BAD\n");
00146    cout <<eText <<endl;
00147 
00148 // Now wait for the process to die
00149 //
00150    if (read(STDIN_FILENO, buff, sizeof(buff))) {}
00151    exit(0);
00152 }
00153 
00154 /******************************************************************************/
00155 /*       C l a s s   X r d W 4 1 D i r s   I m p l e m e n t a t i o n        */
00156 /******************************************************************************/
00157 /******************************************************************************/
00158 /*                                E x p a n d                                 */
00159 /******************************************************************************/
00160   
00161 XrdOucTList *XrdW41Dirs::Expand(const char *Path, XrdOucTList *ptl)
00162 {
00163     struct dirent *dp;
00164     struct stat Stat;
00165     const char *eText;
00166     char buff[1024], *sfxDir;
00167     DIR *DFD;
00168 
00169     if (!(DFD = opendir(Path)))
00170        {eText = strerror(errno);
00171         cerr <<"wait41: " <<eText <<" opening directory" <<Path <<endl;
00172         return ptl;
00173        }
00174 
00175     strcpy(buff, Path); sfxDir = buff + strlen(Path);
00176     if (*(sfxDir-1) != '/') *sfxDir++ = '/';
00177 
00178     errno = 0;
00179     while((dp = readdir(DFD)))
00180          {if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue;
00181           strcpy(sfxDir, dp->d_name);
00182           if (stat(buff, &Stat))
00183              {eText = strerror(errno);
00184               cerr <<"wait41: " <<eText <<" processing " <<buff <<endl;
00185               continue;
00186              }
00187           if (S_ISREG(Stat.st_mode)) ptl = new XrdOucTList(buff, 0, ptl);
00188           errno = 0;
00189          }
00190 
00191     if (errno)
00192        {eText = strerror(errno);
00193         cerr <<"wait41: " <<eText <<" reading directory" <<Path <<endl;
00194        }
00195 
00196     closedir(DFD);
00197     return ptl;
00198 }
00199 
00200 /******************************************************************************/
00201 /*       C l a s s   X r d W 4 1 G a t e   I m p l e m e n t a t i o n        */
00202 /******************************************************************************/
00203 /******************************************************************************/
00204 /*                             S e r i a l i z e                              */
00205 /******************************************************************************/
00206   
00207 void XrdW41Gate::Serialize(XrdOucTList *gfP, int Wait)
00208 {
00209    FLOCK_t lock_args;
00210    int Act, rc;
00211 
00212 // Establish locking options
00213 //
00214    bzero(&lock_args, sizeof(lock_args));
00215    lock_args.l_type = F_WRLCK;
00216    Act = (Wait ? F_SETLKW : F_SETLK);
00217 
00218 // Now perform the action
00219 //
00220    do {rc = fcntl(gfP->val, Act, &lock_args);} while(rc == -1 && errno == EINTR);
00221 
00222 // Determine result
00223 //
00224    if (rc != -1) rc = 0;
00225       else {rc = errno;
00226             cerr <<"Serialize: " <<strerror(rc) <<" locking FD " <<gfP->text <<endl;
00227            }
00228 
00229 // Reflect what happened here
00230 //
00231    gateMutex.Lock();
00232    if (rc || gateOpen) close(gfP->val);
00233       else gateOpen = 1;
00234    gateSem.Post();
00235    gateMutex.UnLock();
00236 }
00237 
00238 /******************************************************************************/
00239 /*                                W a i t 4 1                                 */
00240 /******************************************************************************/
00241   
00242 int XrdW41Gate::Wait41(XrdOucTList *gfP)
00243 {
00244    static const int AMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
00245    pthread_t tid;
00246    const char *eTxt;
00247    int rc, Num = 0;
00248   
00249 // Run through the chain of files setting up a wait. We try to do a fast
00250 // redispatch in case we get a lock early.
00251 //
00252    while(gfP)
00253         {if (Num)
00254             {gateMutex.Lock();
00255              if (gateOpen) {gateMutex.UnLock(); return 1;}
00256              gateMutex.UnLock();
00257             }
00258               if ((gfP->val = open(gfP->text, O_CREAT|O_RDWR, AMode)) < 0)
00259                  {eTxt = strerror(errno);
00260                   cerr <<"Wait41: " <<eTxt <<" opening " <<gfP->text <<endl;
00261                  }
00262          else if ((rc = XrdSysThread::Run(&tid, GateWait, (void *)gfP,
00263                                       XRDSYSTHREAD_BIND, "Gate Wait")))
00264                  {eTxt = strerror(errno);
00265                   cerr <<"Wait41: " <<eTxt <<" creating gate thread for "
00266                                     <<gfP->text <<endl;
00267                   close(gfP->val);
00268                  } else Num++;
00269           gfP = gfP->next;
00270          }
00271 
00272 // At this point we will have to wait for the lock if we have any threads
00273 //
00274    while(Num--)
00275         {gateSem.Wait();
00276          gateMutex.Lock();
00277          if (gateOpen) {gateMutex.UnLock(); return 1;}
00278          gateMutex.UnLock();
00279         }
00280 
00281 // No such luck, every thread failed
00282 //
00283    return 0;
00284 }

Generated on Tue Jul 5 14:46:16 2011 for ROOT_528-00b_version by  doxygen 1.5.1