00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdFrmCIDCVSID = "$Id: XrdFrmCID.cc 35287 2010-09-14 21:19:35Z ganis $";
00014
00015 #include <string.h>
00016 #include <strings.h>
00017 #include <stdio.h>
00018 #include <fcntl.h>
00019 #include <unistd.h>
00020 #include <errno.h>
00021 #include <sys/param.h>
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include <sys/uio.h>
00025
00026 #include "XrdFrm/XrdFrmCID.hh"
00027 #include "XrdFrm/XrdFrmTrace.hh"
00028 #include "XrdOuc/XrdOucEnv.hh"
00029 #include "XrdOuc/XrdOucStream.hh"
00030 #include "XrdSys/XrdSysError.hh"
00031 #include "XrdSys/XrdSysPlatform.hh"
00032
00033 using namespace XrdFrm;
00034
00035
00036
00037
00038
00039 XrdFrmCID XrdFrm::CID;
00040
00041 XrdSysMutex XrdFrmCID::cidMon::cidMutex;
00042
00043
00044
00045
00046
00047 int XrdFrmCID::Add(const char *iName, const char *cName, time_t addT, pid_t Pid)
00048 {
00049 cidMon cidMonitor;
00050 cidEnt *cP;
00051 int ckp = 0;
00052
00053
00054
00055 if (!(cP = Find(iName)))
00056 {First = new cidEnt(First, iName, cName, addT, Pid);
00057 if (!strcmp(iName, "anon")) Dflt = First;
00058 Update();
00059 return 1;
00060 }
00061
00062
00063
00064 if (cP->addT >= addT) return 0;
00065
00066
00067
00068 if (strcmp(cP->cName, cName))
00069 {free(cP->cName);
00070 cP->cName = strdup(cName);
00071 cP->cNLen = strlen(cName);
00072 ckp = 1;
00073 }
00074 if (cP->Pid != Pid) {cP->Pid = Pid; ckp = 1;}
00075 cP->addT = addT;
00076 if (ckp) Update();
00077 return ckp;
00078 }
00079
00080
00081
00082
00083
00084 XrdFrmCID::cidEnt *XrdFrmCID::Find(const char *iName)
00085 {
00086 cidEnt *cP;
00087
00088
00089
00090 if (!iName || !(*iName)) return Dflt;
00091
00092
00093
00094
00095 cP = First;
00096 while(cP && strcmp(iName, cP->iName)) cP = cP->Next;
00097
00098
00099
00100 return cP;
00101 }
00102
00103
00104
00105
00106
00107 int XrdFrmCID::Get(const char *iName, char *buff, int blen)
00108 {
00109 cidMon cidMonitor;
00110 cidEnt *cP;
00111
00112
00113
00114 if (!(cP = Find(iName))) {*buff = 0; return 0;}
00115
00116
00117
00118 strlcpy(buff, cP->cName, blen);
00119 return 1;
00120 }
00121
00122
00123 int XrdFrmCID::Get(const char *iName, const char *vName, XrdOucEnv *evP)
00124 {
00125 cidMon cidMonitor;
00126 cidEnt *cP;
00127
00128
00129
00130 if (!(cP = Find(iName))) return 0;
00131
00132
00133
00134 if (vName && evP) evP->Put(vName, cP->cName);
00135 return 1;
00136 }
00137
00138
00139
00140
00141
00142 int XrdFrmCID::Init(const char *aPath)
00143 {
00144 EPNAME("Init");
00145 XrdOucStream cidFile(&Say);
00146 char Path[1024], *lP, *Pfn;
00147 int cidFD, n, NoGo = 0;
00148
00149
00150
00151 strcpy(Path, aPath);
00152 n = strlen(aPath);
00153 if (Path[n-1] != '/') Path[n++] = '/';
00154 Pfn = Path+n;
00155 strcpy(Pfn, "CIDS.new"); cidFN2 = strdup(Path);
00156 strcpy(Pfn, "CIDS"); cidFN = strdup(Path);
00157
00158
00159
00160 if ( (cidFD = open(cidFN, O_RDONLY, 0)) < 0)
00161 {if (errno == ENOENT) return 0;
00162 Say.Emsg("Init", errno, "open cluster chkpnt file", cidFN);
00163 return 1;
00164 }
00165 cidFile.Attach(cidFD);
00166
00167
00168
00169 while((lP = cidFile.GetLine()))
00170 if (*lP)
00171 {DEBUG("Recovering cid entry: " <<lP);
00172 NoGo |= Init(cidFile);
00173 }
00174
00175
00176
00177 if (NoGo) Say.Emsg("Init", "Errors processing chkpnt file", cidFN);
00178 else if ((n = cidFile.LastError()))
00179 NoGo = Say.Emsg("Init", n, "read cluster chkpnt file", cidFN);
00180 cidFile.Close();
00181
00182
00183
00184 return NoGo;
00185 }
00186
00187
00188
00189 int XrdFrmCID::Init(XrdOucStream &cidFile)
00190 {
00191 EPNAME("Init");
00192 char *iP, *cP, *tP, *uP;
00193 time_t addT;
00194 pid_t Pid;
00195
00196
00197
00198 if (!(iP = cidFile.GetToken()))
00199 {Say.Emsg("Init","Missing cluster instance name."); return 1;}
00200 if (!(cP = cidFile.GetToken()))
00201 {Say.Emsg("Init","Missing cluster name for", iP); return 1;}
00202 if (!(tP = cidFile.GetToken()))
00203 {Say.Emsg("Init","Missing timestamp for", iP); return 1;}
00204 addT = static_cast<time_t>(strtoll(tP, &uP, 10));
00205 if (!addT || *uP)
00206 {Say.Emsg("Init","Invalid timestamp for", iP); return 1;}
00207 if (!(tP = cidFile.GetToken()))
00208 {Say.Emsg("Init","Missing process id for", iP); return 1;}
00209 Pid = static_cast<pid_t>(strtol(tP, &uP, 10));
00210 if (*uP)
00211 {Say.Emsg("Init","Invalid process id for", iP); return 1;}
00212
00213
00214
00215 if (Pid && kill(Pid, 0) < 0 && errno == ESRCH)
00216 {DEBUG("Process " <<Pid <<" not found for instance " <<iP);
00217 Pid = 0;
00218 }
00219
00220
00221
00222 First = new cidEnt(First, iP, cP, addT, Pid);
00223 if (!strcmp(iP, "anon")) Dflt = First;
00224 return 0;
00225 }
00226
00227
00228
00229
00230
00231 void XrdFrmCID::Ref(const char *iName)
00232 {
00233 cidMon cidMonitor;
00234 cidEnt *cP;
00235
00236
00237
00238 if ((cP = Find(iName))) cP->useCnt = 1;
00239 }
00240
00241
00242
00243
00244
00245 int XrdFrmCID::Update()
00246 {
00247 EPNAME("Update");
00248 static char buff[40];
00249 static const int Mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
00250 static struct iovec iov[] = {{0,0}, {(char *)" ", 1},
00251 {0,0},
00252 {buff, 0}};
00253 static const int iovn = sizeof(iov)/sizeof(struct iovec);
00254 FLOCK_t lock_args;
00255 cidEnt *cP = First, *cPP = 0, *cPN;
00256 int rc, cidFD;
00257
00258
00259
00260 if ((cidFD = open(cidFN2, O_RDWR|O_CREAT, Mode)) < 0)
00261 {Say.Emsg("Init",errno,"open",cidFN2);
00262 return 0;
00263 }
00264 fcntl(cidFD, F_SETFD, FD_CLOEXEC);
00265
00266
00267
00268 bzero(&lock_args, sizeof(lock_args));
00269 lock_args.l_type = F_WRLCK;
00270 do {rc = fcntl(cidFD,F_SETLKW,&lock_args);} while(rc < 0 && errno == EINTR);
00271 if (rc < 0)
00272 {Say.Emsg("Update", errno, "lock", cidFN2);
00273 close(cidFD);
00274 return 0;
00275 }
00276
00277
00278
00279 if (ftruncate(cidFD, 0) < 0)
00280 {Say.Emsg("Update", errno, "truncate", cidFN2);
00281 close(cidFD);
00282 return 0;
00283 }
00284
00285
00286
00287 while(cP)
00288 {if (!(cP->Pid) && !(cP->useCnt) && strcmp(cP->iName, "anon"))
00289 {DEBUG("Removing dead instance " <<cP->iName);
00290 if (cPP) cPN = cPP->Next = cP->Next;
00291 else cPN = First = cP->Next;
00292 delete cP;
00293 cP = cPN;
00294 continue;
00295 }
00296 iov[0].iov_base = cP->iName; iov[0].iov_len = cP->iNLen;
00297 iov[2].iov_base = cP->cName; iov[2].iov_len = cP->cNLen;
00298 iov[3].iov_len = sprintf(buff, " %ld %d",
00299 static_cast<long>(cP->addT),
00300 static_cast<int> (cP->Pid)) + 1;
00301 if (writev(cidFD, iov, iovn) < 0)
00302 {Say.Emsg("Update", errno, "writing", cidFN2);
00303 close(cidFD);
00304 return 0;
00305 }
00306 cPP = cP; cP = cP->Next;
00307 }
00308
00309
00310
00311 if (rename(cidFN2, cidFN) < 0)
00312 {Say.Emsg("Update", errno, "rename", cidFN2);
00313 close(cidFD);
00314 return 0;
00315 }
00316
00317
00318
00319 close(cidFD);
00320 return 1;
00321 }