00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdWait41CVSID = "$Id: XrdWait41.cc 30949 2009-11-02 16:37:58Z ganis $";
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
00078
00079
00080 namespace XrdWait41
00081 {
00082 void *GateWait(void *parg)
00083 {
00084 XrdOucTList *fP = (XrdOucTList *)parg;
00085
00086
00087
00088 XrdW41Gate::Serialize(fP);
00089 return (void *)0;
00090 }
00091 }
00092
00093 using namespace XrdWait41;
00094
00095
00096
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
00109
00110 signal(SIGPIPE, SIG_IGN);
00111 sigemptyset(&myset);
00112 sigaddset(&myset, SIGPIPE);
00113 sigaddset(&myset, SIGCHLD);
00114 pthread_sigmask(SIG_BLOCK, &myset, NULL);
00115
00116
00117
00118 if (sizeof(long) > 4) XrdSysThread::setStackSize((size_t)1048576);
00119 else XrdSysThread::setStackSize((size_t)786432);
00120
00121
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
00136
00137 if (!gateFiles)
00138 {cerr <<"wait41: Nothing to wait on!" <<endl;
00139 cout <<"BAD\n" <<endl;
00140 _exit(1);
00141 }
00142
00143
00144
00145 eText = (XrdW41Gate::Wait41(gateFiles) ? "OK\n" : "BAD\n");
00146 cout <<eText <<endl;
00147
00148
00149
00150 if (read(STDIN_FILENO, buff, sizeof(buff))) {}
00151 exit(0);
00152 }
00153
00154
00155
00156
00157
00158
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
00202
00203
00204
00205
00206
00207 void XrdW41Gate::Serialize(XrdOucTList *gfP, int Wait)
00208 {
00209 FLOCK_t lock_args;
00210 int Act, rc;
00211
00212
00213
00214 bzero(&lock_args, sizeof(lock_args));
00215 lock_args.l_type = F_WRLCK;
00216 Act = (Wait ? F_SETLKW : F_SETLK);
00217
00218
00219
00220 do {rc = fcntl(gfP->val, Act, &lock_args);} while(rc == -1 && errno == EINTR);
00221
00222
00223
00224 if (rc != -1) rc = 0;
00225 else {rc = errno;
00226 cerr <<"Serialize: " <<strerror(rc) <<" locking FD " <<gfP->text <<endl;
00227 }
00228
00229
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
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
00250
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
00273
00274 while(Num--)
00275 {gateSem.Wait();
00276 gateMutex.Lock();
00277 if (gateOpen) {gateMutex.UnLock(); return 1;}
00278 gateMutex.UnLock();
00279 }
00280
00281
00282
00283 return 0;
00284 }