00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <errno.h>
00014 #include <string.h>
00015 #include <strings.h>
00016 #include <unistd.h>
00017 #include <fcntl.h>
00018 #include <sys/param.h>
00019 #include <sys/stat.h>
00020 #include <sys/types.h>
00021
00022 #include "XrdFrm/XrdFrmConfig.hh"
00023 #include "XrdFrm/XrdFrmFiles.hh"
00024 #include "XrdFrm/XrdFrmTrace.hh"
00025 #include "XrdOuc/XrdOucTList.hh"
00026 #include "XrdSys/XrdSysPlatform.hh"
00027
00028 const char *XrdFrmFilesCVSID = "$Id: XrdFrmFiles.cc 35287 2010-09-14 21:19:35Z ganis $";
00029
00030 using namespace XrdFrm;
00031
00032
00033
00034
00035
00036
00037
00038
00039 XrdFrmFileset::XrdFrmFileset(XrdFrmFileset *sP, XrdOucTList *diP)
00040 : Next(sP), dInfo(diP), dlkFD(-1), flkFD(-1)
00041 { memset(File, 0, sizeof(File));
00042 if (diP) diP->ival[dRef]++;
00043 }
00044
00045
00046
00047
00048
00049 XrdFrmFileset::~XrdFrmFileset()
00050 {
00051 int i;
00052
00053
00054
00055 UnLock();
00056
00057
00058
00059 for (i = 0; i < XrdOssPath::sfxNum; i++) if(File[i]) delete File[i];
00060
00061
00062
00063 if (dInfo && ((dInfo->ival[dRef] -= 1) <= 0)) delete dInfo;
00064 }
00065
00066
00067
00068
00069
00070 int XrdFrmFileset::dirPath(char *dBuff, int dBlen)
00071 {
00072 char *dP = 0;
00073 int dN = 0, i;
00074
00075
00076
00077
00078 if (dInfo) {dP = dInfo->text; dN = dInfo->ival[dLen];}
00079 else {for (i = 0; i < XrdOssPath::sfxNum; i++)
00080 if (File[i])
00081 {dP = File[i]->Path;
00082 dN = File[i]->File - File[i]->Path;
00083 break;
00084 }
00085 }
00086
00087
00088
00089 if (dBlen > dN && dP) strncpy(dBuff, dP, dN);
00090 else dN = 0;
00091 *(dBuff+dN) = '\0';
00092 return dN;
00093 }
00094
00095
00096
00097
00098
00099 int XrdFrmFileset::Refresh(int isMig, int doLock)
00100 {
00101 XrdOucNSWalk::NSEnt *bP = baseFile(), *lP = lockFile();
00102 char pBuff[MAXPATHLEN+1], *fnP, *pnP = pBuff;
00103 int n;
00104
00105
00106
00107 if (!(n = dirPath(pBuff, sizeof(pBuff)-1))) return 0;
00108 fnP = pBuff+n;
00109
00110
00111
00112 if (doLock && bP)
00113 {strcpy(fnP, baseFile()->File);
00114 if (chkLock(pBuff)) return 0;
00115 if (lP && dlkFD < 0)
00116 {strcpy(fnP, Config.lockFN);
00117 if ((dlkFD = getLock(pBuff)) < 0) return 0;
00118 strcpy(fnP, lockFile()->File);
00119 if ((flkFD = getLock(pBuff,0,1)) < 0)
00120 {close(dlkFD); dlkFD = -1; return 0;}
00121 }
00122 }
00123
00124
00125
00126 if (bP)
00127 {if (bP->Link) pnP = bP->Link;
00128 else strcpy(fnP, bP->File);
00129 if (stat(pnP, &(bP->Stat)))
00130 {Say.Emsg("Refresh", errno, "stat", pnP); UnLock(); return 0;}
00131 }
00132
00133 if (lP)
00134 {strcpy(fnP, lP->File);
00135 if (stat(pBuff, &(lP->Stat)))
00136 {Say.Emsg("Refresh", errno, "stat", pBuff); UnLock(); return 0;}
00137 }
00138
00139 if (!isMig && (bP = pinFile()))
00140 {strcpy(fnP, bP->File);
00141 if (stat(pBuff, &(bP->Stat)) && errno == ENOENT)
00142 {delete bP; File[XrdOssPath::isPin] = 0;}
00143 }
00144
00145
00146
00147 return 1;
00148 }
00149
00150
00151
00152
00153
00154 void XrdFrmFileset::UnLock()
00155 {
00156 if (flkFD >= 0) {close(flkFD); flkFD = -1;}
00157 if (dlkFD >= 0) {close(dlkFD); dlkFD = -1;}
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 int XrdFrmFileset::chkLock(const char *Path)
00170 {
00171 FLOCK_t lock_args;
00172 int rc, lokFD;
00173
00174
00175
00176 if ((lokFD = open(Path, O_RDONLY)) < 0)
00177 {Say.Emsg("chkLock", errno, "open", Path); return -1;}
00178
00179
00180
00181 bzero(&lock_args, sizeof(lock_args));
00182 lock_args.l_type = F_WRLCK;
00183
00184
00185
00186 do {rc = fcntl(lokFD, F_GETLK, &lock_args);} while(rc < 0 && errno == EINTR);
00187
00188
00189
00190 if (rc) Say.Emsg("chkLock", errno, "lock", Path);
00191 else rc = (lock_args.l_type == F_UNLCK ? 0 : 1);
00192
00193
00194
00195 close(lokFD);
00196 return rc;
00197 }
00198
00199
00200
00201
00202
00203 int XrdFrmFileset::getLock(char *Path, int Shared, int noWait)
00204 {
00205 static const int AMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
00206 FLOCK_t lock_args;
00207 int oFlags = (Shared ? O_RDONLY : O_RDWR|O_CREAT);
00208 int rc, lokFD, Act;
00209
00210
00211
00212 if ((lokFD = open(Path, oFlags, AMode)) < 0)
00213 {Say.Emsg("getLock", errno, "open", Path); return -1;}
00214
00215
00216
00217 bzero(&lock_args, sizeof(lock_args));
00218 lock_args.l_type = (Shared ? F_RDLCK : F_WRLCK);
00219 Act = (noWait ? F_SETLK : F_SETLKW);
00220
00221
00222
00223 do {rc = fcntl(lokFD, Act, &lock_args);} while(rc < 0 && errno == EINTR);
00224
00225
00226
00227 if (rc)
00228 {if (errno != EAGAIN) Say.Emsg("getLock", errno, "lock", Path);
00229 close(lokFD); return -1;
00230 }
00231
00232
00233
00234 return lokFD;
00235 }
00236
00237
00238
00239
00240
00241 const char *XrdFrmFileset::Mkfn(XrdOucNSWalk::NSEnt *fP)
00242 {
00243
00244
00245
00246 if (!fP) return "";
00247
00248
00249
00250 if (!dInfo) return fP->Path;
00251
00252
00253
00254 strcpy(dInfo->text+dInfo->ival[dLen], fP->File);
00255 return dInfo->text;
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265 XrdFrmFiles::XrdFrmFiles(const char *dname, int opts,
00266 XrdOucTList *XList, XrdOucNSWalk::CallBack *cbP)
00267 : nsObj(&Say, dname, Config.lockFN,
00268 XrdOucNSWalk::retFile | XrdOucNSWalk::retLink
00269 |XrdOucNSWalk::retStat | XrdOucNSWalk::skpErrs
00270 |XrdOucNSWalk::retIILO
00271 | (opts & CompressD ? XrdOucNSWalk::noPath : 0)
00272 | (opts & Recursive ? XrdOucNSWalk::Recurse : 0), XList),
00273 fsList(0), manMem(opts & NoAutoDel ? Hash_keep : Hash_default),
00274 shareD(opts & CompressD)
00275 {
00276
00277
00278
00279 nsObj.setCallBack(cbP);
00280 }
00281
00282
00283
00284
00285
00286 XrdFrmFileset *XrdFrmFiles::Get(int &rc, int noBase)
00287 {
00288 XrdOucNSWalk::NSEnt *nP;
00289 XrdFrmFileset *fsetP;
00290 const char *dPath;
00291
00292
00293
00294 do{while ((fsetP = fsList))
00295 {fsList = fsetP->Next; fsetP->Next = 0;
00296 if (fsetP->File[XrdOssPath::isBase] || noBase) {rc = 0; return fsetP;}
00297 else if (manMem) delete fsetP;
00298 }
00299
00300
00301
00302 do {if (!(nP = nsObj.Index(rc, &dPath))) return 0;
00303 fsTab.Purge(); fsList = 0;
00304 } while(!Process(nP, dPath));
00305
00306 } while(1);
00307
00308
00309
00310 return 0;
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320 int XrdFrmFiles::Process(XrdOucNSWalk::NSEnt *nP, const char *dPath)
00321 {
00322 XrdOucNSWalk::NSEnt *fP;
00323 XrdFrmFileset *sP;
00324 XrdOucTList *dP = 0;
00325 char *dotP;
00326 int fType;
00327
00328
00329
00330
00331
00332 if (shareD)
00333 {int n = strlen(dPath);
00334 char *dBuff = (char *)malloc(n+264);
00335 strcpy(dBuff, dPath);
00336 dP = new XrdOucTList;
00337 dP->text = dBuff;
00338 dP->ival[XrdFrmFileset::dLen] = n;
00339 dP->ival[XrdFrmFileset::dRef] = 0;
00340 }
00341
00342
00343
00344 while((fP = nP))
00345 {nP = fP->Next; fP->Next = 0;
00346 if (!strcmp(fP->File, Config.lockFN)) {delete fP; continue;}
00347 if ((fType = (int)XrdOssPath::pathType(fP->File))
00348 && (dotP = rindex(fP->File, '.'))) *dotP = '\0';
00349 else dotP = 0;
00350 if (!(sP = fsTab.Find(fP->File)))
00351 {sP = fsList = new XrdFrmFileset(fsList, dP);
00352 fsTab.Add(fP->File, sP, 0, manMem);
00353 }
00354 if (dotP) *dotP = '.';
00355 sP->File[fType] = fP;
00356 }
00357
00358
00359
00360 if (fsList) return 1;
00361 if (dP) delete dP;
00362 return 0;
00363 }