XrdFrmCID.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                          X r d F r m C I D . c c                           */
00004 /*                                                                            */
00005 /* (c) 2010 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*                            All Rights Reserved                             */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //          $Id: XrdFrmCID.cc 35287 2010-09-14 21:19:35Z ganis $
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 /*                      S t a t i c   V a r i a b l e s                       */
00037 /******************************************************************************/
00038   
00039 XrdFrmCID   XrdFrm::CID;
00040 
00041 XrdSysMutex XrdFrmCID::cidMon::cidMutex;
00042   
00043 /******************************************************************************/
00044 /*                                   A d d                                    */
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 // If this is a new entry, create one
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 // Ignore this update if this request is older than the previous one
00063 //
00064    if (cP->addT >= addT) return 0;
00065 
00066 // Update existing entry
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 /* Private:                         F i n d                                   */
00082 /******************************************************************************/
00083 
00084 XrdFrmCID::cidEnt *XrdFrmCID::Find(const char *iName)
00085 {
00086    cidEnt *cP;
00087 
00088 // If no instance name, then return default
00089 //
00090    if (!iName || !(*iName)) return Dflt;
00091 
00092 
00093 // Prepare to find the name
00094 //
00095    cP = First;
00096    while(cP && strcmp(iName, cP->iName)) cP = cP->Next;
00097 
00098 // Return result
00099 //
00100    return cP;
00101 }
00102 
00103 /******************************************************************************/
00104 /* Public:                           G e t                                    */
00105 /******************************************************************************/
00106   
00107 int XrdFrmCID::Get(const char *iName, char *buff, int blen)
00108 {
00109    cidMon cidMonitor;
00110    cidEnt *cP;
00111 
00112 // Find the entry
00113 //
00114    if (!(cP = Find(iName))) {*buff = 0; return 0;}
00115 
00116 // Copy out the cluster name
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 // Find the entry
00129 //
00130    if (!(cP = Find(iName))) return 0;
00131 
00132 // Set cluster name in the environment
00133 //
00134    if (vName && evP) evP->Put(vName, cP->cName);
00135    return 1;
00136 }
00137   
00138 /******************************************************************************/
00139 /* Public:                          I n i t                                   */
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 // Construct the appropriate file names
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 // Try to open the cluster checkpoint file.
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 // Now start reading records until eof.
00168 //
00169    while((lP = cidFile.GetLine()))
00170         if (*lP)
00171            {DEBUG("Recovering cid entry: " <<lP);
00172             NoGo |= Init(cidFile);
00173            }
00174 
00175 // Now check if any errors occured during file i/o
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 // Return final return code
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 // The record is <iname> <cname> <addt> <pid>
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 // Validate the process ID
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 // Now add the entry
00221 //
00222    First = new cidEnt(First, iP, cP, addT, Pid);
00223    if (!strcmp(iP, "anon")) Dflt = First;
00224    return 0;
00225 }
00226 
00227 /******************************************************************************/
00228 /* Public:                           R e f                                    */
00229 /******************************************************************************/
00230   
00231 void XrdFrmCID::Ref(const char *iName)
00232 {
00233    cidMon cidMonitor;
00234    cidEnt *cP;
00235 
00236 // Find the entry
00237 //
00238    if ((cP = Find(iName))) cP->useCnt = 1;
00239 }
00240 
00241 /******************************************************************************/
00242 /* Private:                       U p d a t e                                 */
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}, // 0: Instance
00251                                 {0,0},                   // 2: Cluster
00252                                 {buff, 0}};              // 3: Timestamp pid
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 // Open the temp file first in r/w mode
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 // Lock the file
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 // Now truncate the file to zero
00278 //
00279    if (ftruncate(cidFD, 0) < 0)
00280       {Say.Emsg("Update", errno, "truncate", cidFN2);
00281        close(cidFD);
00282        return 0;
00283       }
00284 
00285 // Write out the cluster information
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 // Now rename the file to be the original while we hav the file open
00310 //
00311    if (rename(cidFN2, cidFN) < 0)
00312       {Say.Emsg("Update", errno, "rename", cidFN2);
00313        close(cidFD);
00314        return 0;
00315       }
00316 
00317 // All done
00318 //
00319    close(cidFD);
00320    return 1;
00321 }

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