00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00039
00040
00041
00042
00043
00044
00045 #ifndef NODEBUG
00046 extern XrdOucTrace *XrdXrootdTrace;
00047 #endif
00048
00049 XrdScheduler *XrdXrootdPrepare::SchedP;
00050
00051 XrdSysError *XrdXrootdPrepare::eDest;
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
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
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
00084
00085 if (!LogDir) return -1;
00086
00087
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
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
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
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
00140
00141 if (!LogDir) return;
00142
00143
00144
00145 while(tp) {pnum++; tp = tp->next;}
00146
00147
00148
00149 snprintf(buff, sizeof(buff)-1, "%s%s_%s_%d_%d", LogDir,
00150 pargs.reqid, pargs.user, pargs.prty, pnum);
00151
00152
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
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
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
00191
00192
00193 void XrdXrootdPrepare::Logdel(char *reqid)
00194 {
00195 int rc;
00196 char path[MAXPATHLEN+256], buff[MAXPATHLEN+1];
00197
00198
00199
00200 if (!LogDir || strlen(reqid) > 255) return;
00201
00202
00203
00204 strcpy(path, (const char *)LogDir);
00205 strcpy(&path[LogDirLen], (const char *)reqid);
00206
00207
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
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
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
00236
00237 if (!LogDir) return -ENOTSUP;
00238
00239
00240
00241 strcpy(path, (const char *)LogDir);
00242 strcpy(path+LogDirLen, reqid);
00243
00244
00245
00246 if (stat((const char *)path, &buf)) return -errno;
00247 fsz = buf.st_size;
00248
00249
00250
00251 if ((fd = open((const char *)path, O_RDONLY)) < 0) return -errno;
00252 return fd;
00253 }
00254
00255
00256
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
00268
00269 if (!LogDir) return;
00270
00271
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
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
00296
00297 if (errno)
00298 eDest->Emsg("List", errno, "read prep log directory", LogDir);
00299 closedir(prepD);
00300 }
00301
00302
00303
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
00319
00320 if (!ldir) return 0;
00321
00322
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
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
00338
00339 LogDir = strdup(path);
00340 LogDirLen = strlen(LogDir);
00341 return 0;
00342 }