XrdXrootdPrepare.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                   X r d X r o o t d P r e p a r e . c c                    */
00004 /*                                                                            */
00005 /* (c) 2004 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-AC03-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //         $Id: XrdXrootdPrepare.cc 35287 2010-09-14 21:19:35Z ganis $
00012 
00013 const char *XrdXrootdPrepareCVSID = "$Id: XrdXrootdPrepare.cc 35287 2010-09-14 21:19:35Z ganis $";
00014   
00015 #include <dirent.h>
00016 #include <fcntl.h>
00017 #include <unistd.h>
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <strings.h>
00021 #include <sys/param.h>
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include <sys/uio.h>
00025 
00026 #ifdef __linux__
00027 #include <syscall.h>
00028 #define getdents(fd, dirp, cnt) syscall(SYS_getdents, fd, dirp, cnt)
00029 #endif
00030 
00031 #include "XrdSys/XrdSysError.hh"
00032 #include "XrdSys/XrdSysPlatform.hh"
00033 #include "XrdOuc/XrdOucTList.hh"
00034 #include "XrdXrootd/XrdXrootdPrepare.hh"
00035 #include "XrdXrootd/XrdXrootdTrace.hh"
00036 
00037 /******************************************************************************/
00038 /*                        G l o b a l   O b j e c t s                         */
00039 /******************************************************************************/
00040 
00041 /******************************************************************************/
00042 /*                               G l o b a l s                                */
00043 /******************************************************************************/
00044 
00045 #ifndef NODEBUG  
00046 extern XrdOucTrace     *XrdXrootdTrace;
00047 #endif
00048 
00049        XrdScheduler    *XrdXrootdPrepare::SchedP;
00050 
00051        XrdSysError     *XrdXrootdPrepare::eDest;     // Error message handler
00052 
00053        int              XrdXrootdPrepare::scrubtime = 60*60;
00054        int              XrdXrootdPrepare::scrubkeep = 60*60*24;
00055        char            *XrdXrootdPrepare::LogDir = 0;
00056        int              XrdXrootdPrepare::LogDirLen = 0;
00057 const  char            *XrdXrootdPrepare::TraceID = "Prepare";
00058 
00059 /******************************************************************************/
00060 /*                           C o n s t r u c t o r                            */
00061 /******************************************************************************/
00062   
00063 XrdXrootdPrepare::XrdXrootdPrepare(XrdSysError *errp, XrdScheduler *sp)
00064                  : XrdJob("Prep log scrubber")
00065 {eDest    = errp;
00066  SchedP   = sp;
00067  if (LogDir) SchedP->Schedule((XrdJob *)this, scrubtime+time(0));
00068     else eDest->Say("Config warning: 'xrootd.prepare logdir' not specified; "
00069                     "prepare tracking disabled.");
00070 }
00071   
00072 /******************************************************************************/
00073 /*                                  L i s t                                   */
00074 /******************************************************************************/
00075   
00076 int XrdXrootdPrepare::List(XrdXrootdPrepArgs &pargs, char *resp, int resplen)
00077 {
00078    char *up, path[2048];
00079    struct dirent *dp;
00080    struct stat buf;
00081    int rc;
00082 
00083 // If logging is not supported, return eof
00084 //
00085    if (!LogDir) return -1;
00086 
00087 // Check if this is the first call
00088 //
00089    if (!pargs.dirP)
00090       {if (!(pargs.dirP = opendir((const char *)LogDir)))
00091           {eDest->Emsg("List", errno, "open prep log directory", LogDir);
00092            return -1;
00093           }
00094        if (pargs.reqid) pargs.reqlen = strlen(pargs.reqid);
00095        if (pargs.user)  pargs.usrlen = strlen(pargs.user);
00096       }
00097 
00098 // Find the next entry that satisfies the search criteria
00099 //
00100    errno = 0;
00101    while((dp = readdir(pargs.dirP)))
00102      {if (!(up = (char *) index((const char *)dp->d_name, '_'))) continue;
00103          if (pargs.reqlen && strncmp(dp->d_name, pargs.reqid, pargs.reqlen))
00104             continue;
00105          if (pargs.usrlen)
00106             if (!up || strcmp((const char *)up+1,(const char *)pargs.user))
00107                continue;
00108          strcpy(path, (const char *)LogDir);
00109          strcpy(path+LogDirLen, (const char *)dp->d_name);
00110          if (stat((const char *)path, &buf)) continue;
00111          *up = ' ';
00112          if ((up = (char *) index((const char *)(up+1), (int)'_'))) *up = ' ';
00113             else continue;
00114          if ((up = (char *) index((const char *)(up+1), (int)'_'))) *up = ' ';
00115             else continue;
00116          return snprintf(resp, resplen-1, "%s %ld", dp->d_name, buf.st_mtime);
00117         }
00118 
00119 // Completed
00120 //
00121    if ((rc = errno))
00122       eDest->Emsg("List", errno, "read prep log directory", LogDir);
00123    closedir(pargs.dirP);
00124    pargs.dirP = 0;
00125    return (rc ? -1 : 0);
00126 }
00127   
00128 /******************************************************************************/
00129 /*                                   L o g                                    */
00130 /******************************************************************************/
00131   
00132 void XrdXrootdPrepare::Log(XrdXrootdPrepArgs &pargs)
00133 {
00134    int rc, pnum = 0, xfd;
00135    XrdOucTList *tp = pargs.paths;
00136    char buff[2048], blink[2048];
00137    struct iovec iovec[2];
00138 
00139 // If logging not enabled, return
00140 //
00141    if (!LogDir) return;
00142 
00143 // Count number of paths in the list
00144 //
00145    while(tp) {pnum++; tp = tp->next;}
00146 
00147 // Construct the file name: <reqid>_<user>_<prty>_<numpaths>
00148 //
00149    snprintf(buff, sizeof(buff)-1, "%s%s_%s_%d_%d", LogDir,
00150                                   pargs.reqid, pargs.user, pargs.prty, pnum);
00151 
00152 // Create the file
00153 //
00154     if ((xfd = open(buff, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0)
00155        {eDest->Emsg("Log", errno, "open prep log file", buff);
00156         return;
00157        }
00158 
00159 // Write all the paths into the file, separating each by a space
00160 //
00161    iovec[1].iov_base = (char *)" ";
00162    iovec[1].iov_len  = 1;
00163    tp = pargs.paths;
00164    while(tp)
00165         {if (tp->next == 0) iovec[1].iov_base = (char *)"\n";
00166          iovec[0].iov_base = tp->text;
00167          iovec[0].iov_len  = strlen(tp->text);
00168          do {rc = writev(xfd, (const struct iovec *)iovec, 2);}
00169              while(rc < 0 && errno == EINTR);
00170          if (rc < 0)
00171             {eDest->Emsg("Log", errno, "write prep log file", buff);
00172              close(xfd);
00173              return;
00174             }
00175          tp = tp->next;
00176         }
00177 
00178 // Create a symlink to the file
00179 //
00180    close(xfd);
00181    strcpy(blink, LogDir); 
00182    strlcpy(blink+LogDirLen, pargs.reqid, sizeof(blink)-1);
00183    if (symlink((const char *)buff, (const char *)blink))
00184       {eDest->Emsg("Log", errno, "create symlink to prep log file", buff);
00185        return;
00186       }
00187 }
00188   
00189 /******************************************************************************/
00190 /*                                L o g d e l                                 */
00191 /******************************************************************************/
00192   
00193 void XrdXrootdPrepare::Logdel(char *reqid)
00194 {
00195    int rc;
00196    char path[MAXPATHLEN+256], buff[MAXPATHLEN+1];
00197 
00198 // If logging not enabled, return
00199 //
00200    if (!LogDir || strlen(reqid) > 255) return;
00201 
00202 // Construct the file name of the symlink
00203 //
00204    strcpy(path, (const char *)LogDir);
00205    strcpy(&path[LogDirLen], (const char *)reqid);
00206 
00207 // Read the symlink contents for this request
00208 //
00209    if ((rc = readlink((const char *)path, buff, sizeof(buff)-1)) < 0)
00210       {if (errno != ENOENT) eDest->Emsg("Logdel",errno,"read symlink",path);
00211        return;
00212       }
00213 
00214 // Delete the file, then the symlink
00215 //
00216    buff[rc] = '\0';
00217    if (unlink((const char *)buff)
00218    &&  errno != ENOENT) eDest->Emsg("Logdel",errno,"remove",buff);
00219       else TRACE(DEBUG, "Logdel removed " <<buff);
00220    if (unlink((const char *)path)
00221    &&  errno != ENOENT) eDest->Emsg("Logdel", errno, "remove", path);
00222       else TRACE(DEBUG, "Logdel removed " <<path);
00223 }
00224 
00225 /******************************************************************************/
00226 /*                                  O p e n                                   */
00227 /******************************************************************************/
00228   
00229 int XrdXrootdPrepare::Open(const char *reqid, int &fsz)
00230 {
00231    int fd;
00232    char path[MAXPATHLEN+264];
00233    struct stat buf;
00234 
00235 // If logging is not supported, indicate so
00236 //
00237    if (!LogDir) return -ENOTSUP;
00238 
00239 // Construct the file name
00240 //
00241    strcpy(path, (const char *)LogDir);
00242    strcpy(path+LogDirLen, reqid);
00243 
00244 // Get the file size
00245 //
00246    if (stat((const char *)path, &buf)) return -errno;
00247    fsz = buf.st_size;
00248 
00249 // Open the file and return the file descriptor
00250 //
00251    if ((fd = open((const char *)path, O_RDONLY)) < 0) return -errno;
00252    return fd;
00253 }
00254   
00255 /******************************************************************************/
00256 /*                                 S c r u b                                  */
00257 /******************************************************************************/
00258   
00259 void XrdXrootdPrepare::Scrub()
00260 {
00261    DIR *prepD;
00262    time_t stale = time(0) - scrubkeep;
00263    char *up, path[2048], *fn = path+LogDirLen;
00264    struct dirent *dp;
00265    struct stat buf;
00266 
00267 // If logging is not supported, return eof
00268 //
00269    if (!LogDir) return;
00270 
00271 // Open the log directory
00272 //
00273    if (!(prepD = opendir((const char *)LogDir)))
00274       {eDest->Emsg("Scrub", errno, "open prep log directory", LogDir);
00275        return;
00276       }
00277    strcpy(path, (const char *)LogDir);
00278 
00279 // Delete all stale entries
00280 //
00281    errno = 0;
00282    while((dp = readdir(prepD)))
00283      {if (!(up = (char *) index((const char *)dp->d_name, '_'))) continue;
00284          strcpy(fn, (const char *)dp->d_name);
00285          if (stat((const char *)path, &buf)) continue;
00286          if (buf.st_mtime <= stale)
00287             {TRACE(DEBUG, "Scrub removed stale prep log " <<path);
00288              unlink((const char *)path);
00289              *(fn+(up-dp->d_name)) = '\0';
00290              unlink((const char *)path);
00291              errno = 0;
00292             }
00293         }
00294 
00295 // All done
00296 //
00297    if (errno)
00298       eDest->Emsg("List", errno, "read prep log directory", LogDir);
00299    closedir(prepD);
00300 }
00301  
00302 /******************************************************************************/
00303 /*                              s e t P a r m s                               */
00304 /******************************************************************************/
00305   
00306 int XrdXrootdPrepare::setParms(int stime, int keep)
00307 {if (stime > 0) scrubtime = stime;
00308  if (keep  > 0) scrubkeep = keep;
00309  return 0;
00310 }
00311 
00312 int XrdXrootdPrepare::setParms(char *ldir)
00313 {
00314    char path[2048];
00315    struct stat buf;
00316    int plen;
00317 
00318 // If parm not supplied, ignore call
00319 //
00320    if (!ldir) return 0;
00321 
00322 // Make sure we have appropriate permissions for this directory
00323 //
00324    if (access((const char *)ldir, X_OK | W_OK | R_OK) || stat(ldir, &buf))
00325       return -errno;
00326    if ((buf.st_mode & S_IFMT) != S_IFDIR) return -ENOTDIR;
00327 
00328 // Create the path name
00329 //
00330    if (LogDir) free(LogDir);
00331    LogDir = 0;
00332    plen = strlen(ldir);
00333    strcpy(path, ldir);
00334    if (path[plen-1] != '/') path[plen++] = '/';
00335    path[plen] = '\0';
00336 
00337 // Save the path and return
00338 //
00339    LogDir    = strdup(path);
00340    LogDirLen = strlen(LogDir);
00341    return 0;
00342 }

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