00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <stdio.h>
00014 #include <string.h>
00015 #include <sys/param.h>
00016
00017 #include "XrdFrm/XrdFrmAdmin.hh"
00018 #include "XrdFrm/XrdFrmConfig.hh"
00019 #include "XrdFrm/XrdFrmFiles.hh"
00020 #include "XrdFrm/XrdFrmTrace.hh"
00021 #include "XrdFrm/XrdFrmUtils.hh"
00022 #include "XrdOss/XrdOssPath.hh"
00023 #include "XrdOss/XrdOssSpace.hh"
00024 #include "XrdOuc/XrdOucNSWalk.hh"
00025 #include "XrdOuc/XrdOucTList.hh"
00026
00027 const char *XrdFrmAdminAuditCVSID = "$Id: XrdFrmAdminAudit.cc 32231 2010-02-05 18:24:46Z ganis $";
00028
00029 using namespace XrdFrm;
00030
00031
00032
00033
00034
00035 int XrdFrmAdmin::AuditNameNB(XrdFrmFileset *sP)
00036 {
00037 char Resp, buff[80];
00038 int num = 0, rem;
00039
00040
00041
00042 if (sP->failFile())
00043 {num++; Msg("Orphaned fail file: ", sP->failPath());}
00044 if (sP->lockFile())
00045 {num++; Msg("Orphaned lock file: ", sP->lockPath());}
00046 if (sP->pfnFile() )
00047 {num++; Msg("Orphaned pfn file: ", sP->pfnPath());
00048 Msg("PFN file refers to: ", sP->pfnFile()->Link);
00049 }
00050 if (sP->pinFile() )
00051 {num++; Msg("Orphaned pin file: ", sP->pinPath());}
00052
00053
00054
00055 numProb += num;
00056 if (!Opt.Fix || !num) return 1;
00057 if (!Opt.Force)
00058 {Resp = XrdFrmUtils::Ask('n', "Remove orphaned files?");
00059 if (Resp != 'y') return Resp != 'a';
00060 }
00061
00062
00063
00064 rem = AuditRemove(sP);
00065 numFix += rem;
00066
00067
00068
00069 sprintf(buff, "%d of %d orphaned files removed.", rem, num);
00070 Msg(buff);
00071 return 1;
00072 }
00073
00074
00075
00076
00077
00078 int XrdFrmAdmin::AuditNameNF(XrdFrmFileset *sP)
00079 {
00080 char Resp;
00081
00082
00083
00084 Msg("Dangling link: ", sP->basePath());
00085 Msg("Missing target: ", sP->baseFile()->Link);
00086 numProb++;
00087
00088
00089
00090 if (!Opt.Fix) return 1;
00091 if (!Opt.Force)
00092 {Resp = XrdFrmUtils::Ask('n', "Remove symlink?");
00093 if (Resp != 'y') return Resp != 'a';
00094 }
00095
00096
00097
00098 if (unlink(sP->basePath()))
00099 Emsg(errno,"remove symlink", sP->basePath());
00100 else if (AuditRemove(sP))
00101 {Msg("Symlink removed.");
00102 numFix++;
00103 return 1;
00104 }
00105 return 1;
00106 }
00107
00108
00109
00110
00111
00112 int XrdFrmAdmin::AuditNameNL(XrdFrmFileset *sP)
00113 {
00114 char Resp;
00115
00116
00117
00118 Msg("Missing lock file: ", sP->basePath());
00119 numProb++;
00120
00121
00122
00123 if (!Opt.Fix) return -1;
00124 if (!Opt.Force)
00125 {Resp = XrdFrmUtils::Ask('y', "Create lock file?");
00126 if (Resp != 'y') return Resp != 'a';
00127 }
00128
00129
00130
00131 if (!mkFile(mkLF|isPFN, sP->basePath())) return 1;
00132 Msg("Lock file created.");
00133 numFix++;
00134 return 1;
00135 }
00136
00137
00138
00139
00140
00141 int XrdFrmAdmin::AuditNames()
00142 {
00143 XrdFrmFileset *sP;
00144 XrdFrmFiles *fP;
00145 char pDir[MAXPATHLEN], *lDir = Opt.Args[1];
00146 int opts = (Opt.Recurse ? XrdFrmFiles::Recursive : 0);
00147 int ec = 0, Act = 1;
00148
00149
00150
00151 numProb = 0; numFix = 0;
00152 if (VerifyMP("audit", lDir) != 'y') return 0;
00153
00154
00155
00156 if (!Config.LocalPath(lDir, pDir, sizeof(pDir))) {finalRC = 4; return 1;}
00157 fP = new XrdFrmFiles(pDir, opts);
00158 while(Act && (sP = fP->Get(ec,1)))
00159 {if (!(sP->baseFile())) Act = AuditNameNB(sP);
00160 else {if (sP->baseFile()->Type == XrdOucNSWalk::NSEnt::isLink)
00161 Act = AuditNameNF(sP);
00162 if (Act && Opt.MPType && !(sP->lockFile()))
00163 Act = AuditNameNL(sP);
00164 if (Act && sP->baseFile()->Link && isXA(sP->baseFile()))
00165 Act = AuditNameXA(sP);
00166 }
00167 }
00168 if (ec) finalRC = 4;
00169 delete fP;
00170
00171
00172
00173 if (!Act) Msg("Audit names aborted!");
00174 sprintf(pDir,"%d problem%s found; %d fixed.", numProb,
00175 (numProb == 1 ? "" : "s"), numFix);
00176 Msg(pDir);
00177 return !Act;
00178 }
00179
00180
00181
00182
00183
00184 int XrdFrmAdmin::AuditNameXA(XrdFrmFileset *sP)
00185 {
00186 struct stat buf;
00187 char Path[1032], lkbuff[1032];
00188 int n;
00189
00190
00191
00192 strcpy(Path, sP->baseFile()->Link); strcat(Path, ".pfn");
00193 if (lstat(Path,&buf))
00194 {if (errno != ENOENT)
00195 {Emsg(errno, "stat ", Path); return AuditNameXL(sP,-1);}
00196 Msg("Missing pfn link to ", sP->basePath());
00197 return AuditNameXL(sP,0);
00198 }
00199
00200
00201
00202 if ((buf.st_mode & S_IFMT) != S_IFLNK)
00203 {Msg("Invalid pfn file for ", sP->basePath());
00204 return AuditNameXL(sP,1);
00205 }
00206
00207
00208
00209 if ((n = readlink(Path, lkbuff, sizeof(lkbuff)-1)) < 0)
00210 {Emsg(errno, "read link from ", Path); return AuditNameXL(sP,-1);}
00211 lkbuff[n] = '\0';
00212 if (strcmp(sP->basePath(), lkbuff))
00213 {Msg("Incorrect pfn link to ", sP->basePath());
00214 return AuditNameXL(sP,1);
00215 }
00216
00217
00218
00219 return 1;
00220 }
00221
00222
00223
00224
00225
00226 int XrdFrmAdmin::AuditNameXL(XrdFrmFileset *sP, int dorm)
00227 {
00228 char Resp, Path[1032];
00229
00230
00231
00232 numProb++;
00233 if (!Opt.Fix || dorm < 0) return 1;
00234 if (!Opt.Force)
00235 {if (dorm)
00236 Resp = XrdFrmUtils::Ask('n', "Recreate pfn symlink?");
00237 else
00238 Resp = XrdFrmUtils::Ask('y', "Create pfn symlink?");
00239 if (Resp != 'y') return Resp != 'a';
00240 }
00241
00242
00243
00244 strcpy(Path, sP->baseFile()->Link); strcat(Path, ".pfn");
00245 if (dorm) unlink(Path);
00246 if (symlink(sP->basePath(), Path))
00247 {Emsg(errno, "create symlink ", Path); return 1;}
00248 Msg("pfn symlink created.");
00249 numFix++;
00250 return 1;
00251 }
00252
00253
00254
00255
00256
00257 int XrdFrmAdmin::AuditRemove(XrdFrmFileset *sP)
00258 {
00259 int rem = 0;
00260
00261
00262
00263 if (sP->failFile())
00264 {if (unlink(sP->failPath())) Emsg(errno,"remove fail file.");
00265 else rem++;
00266 }
00267 if (sP->lockFile())
00268 {if (unlink(sP->lockPath())) Emsg(errno,"remove lock file.");
00269 else rem++;
00270 }
00271 if (sP-> pinFile())
00272 {if (unlink(sP-> pinPath())) Emsg(errno,"remove pin file.");
00273 else rem++;
00274 }
00275 if (sP-> pfnFile())
00276 {if (unlink(sP-> pinPath())) Emsg(errno,"remove pfn file.");
00277 else rem++;
00278 }
00279
00280 return rem;
00281 }
00282
00283
00284
00285
00286
00287 int XrdFrmAdmin::AuditSpace()
00288 {
00289 XrdOucTList *pP;
00290 char buff[256], *Path = 0, *Space = Opt.Args[1];
00291 int Act;
00292
00293
00294
00295 if (!(pP = ParseSpace(Space, &Path))) return 4;
00296
00297
00298
00299 numBytes = 0; numFiles = 0; numProb = 0; numFix = 0;
00300
00301
00302
00303 do {Act = (pP->val ? AuditSpaceXA(Space, pP->text) : AuditSpaceAX(pP->text));
00304 pP = pP->next;
00305 } while(pP && !Path && Act);
00306
00307
00308
00309 sprintf(buff,"%d problem%s found; %d fixed.", numProb,
00310 (numProb == 1 ? "" : "s"), numFix);
00311 Msg(buff);
00312 if (!Act) Msg("Audit space aborted!");
00313 else {if (Path) *(--Path) = ':';
00314 sprintf(buff, "Space %s has %d file%s with %lld byte%s in use.",
00315 Space,
00316 numFiles, (numFiles == 1 ? "" : "s"),
00317 numBytes, (numBytes == 1 ? "" : "s"));
00318 Msg(buff);
00319 }
00320 return (Act ? 0 : 4);
00321 }
00322
00323
00324
00325
00326
00327 int XrdFrmAdmin::AuditSpaceAX(const char *Path)
00328 {
00329 XrdOucNSWalk nsWalk(&Say, Path, Config.lockFN, XrdOucNSWalk::retFile
00330 | XrdOucNSWalk::retStat
00331 | XrdOucNSWalk::skpErrs);
00332 XrdOucNSWalk::NSEnt *nP, *pP;
00333 char buff[1032];
00334 int ec, Act = 1;
00335
00336
00337
00338 if (!(nP = nsWalk.Index(ec))) {if (ec) finalRC = 4; return 1;}
00339 pP = nP;
00340
00341
00342
00343 while(nP && Act)
00344 {Act = (XrdOssPath::genPFN(buff, sizeof(buff), nP->Path)
00345 ? AuditSpaceAXDC(buff, nP) : AuditSpaceAXDB(nP->Path));
00346 nP = nP->Next;
00347 }
00348
00349
00350
00351 while(pP) {nP = pP; pP = pP->Next; delete nP;}
00352 return Act;
00353 }
00354
00355
00356
00357
00358
00359 int XrdFrmAdmin::AuditSpaceAXDB(const char *Path)
00360 {
00361 char Resp;
00362
00363
00364
00365 Msg("Invalid name for data file ", Path);
00366 numProb++;
00367
00368
00369
00370 if (Opt.Fix)
00371 {if (!Opt.Force)
00372 {Resp = XrdFrmUtils::Ask('n', "Delete file?");
00373 if (Resp != 'y') return Resp != 'a';
00374 }
00375 if (unlink(Path)) Emsg(errno, "remove ", Path);
00376 else numFix++;
00377 }
00378 return 1;
00379 }
00380
00381
00382
00383
00384
00385 int XrdFrmAdmin::AuditSpaceAXDC(const char *Path, XrdOucNSWalk::NSEnt *nP)
00386 {
00387 struct stat buf;
00388 char lkbuff[1032], *Dest = nP->Path;
00389 int n;
00390
00391
00392
00393 numProb++;
00394
00395
00396
00397 if (lstat(Path,&buf))
00398 {if (errno != ENOENT) {Emsg(errno, "stat ", Path); return 1;}
00399 Msg("Missing pfn data link ", Path);
00400 return AuditSpaceAXDL(0, Path, Dest);
00401 }
00402
00403
00404
00405 if ((buf.st_mode & S_IFMT) != S_IFLNK)
00406 {Msg("Invalid pfn data link ", Path);
00407 return AuditSpaceAXDL(1, Path, Dest);
00408 }
00409
00410
00411
00412 if ((n = readlink(Path, lkbuff, sizeof(lkbuff)-1)) < 0)
00413 {Emsg(errno, "read link from ", Path); return 1;}
00414 lkbuff[n] = '\0';
00415 if (strcmp(Path, lkbuff))
00416 {Msg("Incorrect pfn data link ", Path);
00417 return AuditSpaceAXDL(1, Path, Dest);
00418 }
00419
00420
00421
00422 numProb--; numFiles++; numBytes += nP->Stat.st_size;
00423 return 1;
00424 }
00425
00426
00427
00428
00429
00430 int XrdFrmAdmin::AuditSpaceAXDL(int dorm, const char *Path, const char *Dest)
00431 {
00432 char Resp;
00433
00434
00435
00436 if (!Opt.Fix) return -1;
00437 if (!Opt.Force)
00438 {if (dorm)
00439 Resp = XrdFrmUtils::Ask('n', "Recreate pfn symlink?");
00440 else
00441 Resp = XrdFrmUtils::Ask('y', "Create pfn symlink?");
00442 if (Resp != 'y') return Resp != 'a';
00443 }
00444
00445
00446
00447 if (dorm) unlink(Path);
00448 if (symlink(Dest, Path))
00449 {Emsg(errno, "create symlink ", Path); return 1;}
00450 Msg("pfn symlink created.");
00451 numFix++;
00452 return 1;
00453 }
00454
00455
00456
00457
00458
00459 int XrdFrmAdmin::AuditSpaceXA(const char *Space, const char *Path)
00460 {
00461 XrdFrmFileset *sP;
00462 XrdFrmFiles *fP;
00463 char tmpv[8], *buff;
00464 int ec = 0, Act = 1;
00465
00466
00467
00468 buff = XrdOssPath::genPath(Path, Space, tmpv);
00469 fP = new XrdFrmFiles(buff, XrdFrmFiles::Recursive);
00470
00471
00472
00473 while(Act && (sP = fP->Get(ec,1)))
00474 { if (!(sP->baseFile())) Act = AuditNameNB(sP);
00475 else if (!(sP-> pfnFile())) Act = AuditSpaceXANB(sP);
00476 else {numFiles++; numBytes += sP->baseFile()->Stat.st_size; continue;}
00477 }
00478
00479
00480
00481 if (ec) finalRC = 4;
00482 free(buff);
00483 delete fP;
00484 return Act;
00485 }
00486
00487
00488
00489
00490
00491 int XrdFrmAdmin::AuditSpaceXANB(XrdFrmFileset *sP)
00492 {
00493 char Resp;
00494
00495
00496
00497 numProb++; numFiles++; numBytes += sP->baseFile()->Stat.st_size;
00498
00499
00500
00501 Msg("Missing pfn file for data file ", sP->basePath());
00502
00503
00504
00505 if (!Opt.Fix) return -1;
00506 if (!Opt.Force)
00507 {Resp = XrdFrmUtils::Ask('n', "Remove data file?");
00508 if (Resp != 'y') return Resp != 'a';
00509 }
00510
00511
00512
00513 if (unlink(sP->basePath())) Emsg(errno,"remove data file ", sP->basePath());
00514 else {numFix++; numFiles--; numBytes -= sP->baseFile()->Stat.st_size;}
00515 return 1;
00516 }
00517
00518
00519
00520
00521
00522 int XrdFrmAdmin::AuditUsage()
00523 {
00524 XrdFrmConfig::VPInfo *vP = Config.VPList;
00525 char Sbuff[1024];
00526 int retval, rc;
00527
00528
00529
00530 if (Opt.Args[1]) return AuditUsage(Opt.Args[1]);
00531
00532
00533
00534 if (!vP) {Emsg("No outplace space has been configured."); return -1;}
00535
00536
00537
00538 retval = 1;
00539 while(vP)
00540 {strcpy(Sbuff, vP->Name);
00541 if (!(rc = AuditUsage(Sbuff))) return 0;
00542 if (rc < 0) retval = rc;
00543 vP = vP->Next;
00544 }
00545 return retval;
00546 }
00547
00548
00549
00550 int XrdFrmAdmin::AuditUsage(char *Space)
00551 {
00552 XrdOucTList *pP;
00553 const char *Sfx;
00554 char Resp, buff[256], *Path = 0;
00555 long long theClaim, theDiff;
00556 int haveUsage, Probs = 0;
00557
00558
00559
00560 if (!(pP = ParseSpace(Space, &Path))) return -1;
00561 if (Path) {Emsg("Path not allowed for audit usage."); return -1;}
00562
00563
00564
00565 numBytes = 0; numFiles = 0; numProb = 0;
00566 haveUsage = XrdOssSpace::Init();
00567
00568
00569
00570 do {Probs |= (pP->val ? AuditUsageXA(pP->text, Space)
00571 : AuditUsageAX(pP->text));
00572 pP = pP->next;
00573 } while(pP);
00574
00575
00576
00577 sprintf(buff, "Audit of %d file%s in %s space completed with %serrors.",
00578 numFiles, (numFiles == 1 ? "" : "s"), Space,
00579 (Probs ? "" : "no "));
00580 Msg(buff);
00581
00582
00583
00584 if (haveUsage)
00585 {XrdOssSpace::uEnt myEnt;
00586 XrdOssSpace::Usage(Space, myEnt);
00587 theClaim = myEnt.Bytes[XrdOssSpace::Serv]
00588 + myEnt.Bytes[XrdOssSpace::Pstg]
00589 - myEnt.Bytes[XrdOssSpace::Purg]
00590 + myEnt.Bytes[XrdOssSpace::Admin];
00591 sprintf(buff, "%12lld", theClaim);
00592 Msg("Claimed: ", buff);
00593 } else theClaim = numBytes;
00594
00595
00596
00597 sprintf(buff, "%12lld", numBytes);
00598 Msg("Actual: ", buff);
00599
00600
00601
00602 if (numBytes == theClaim || !Opt.Fix) return 1;
00603 if (!haveUsage)
00604 {Emsg(0, "No usage file present to fix!"); return -1;}
00605
00606
00607
00608 if (theClaim < numBytes) theDiff = numBytes - theClaim;
00609 else theDiff = theClaim - numBytes;
00610
00611
00612
00613 if (!Opt.Force)
00614 {if (theDiff < 500000) Sfx = "byte";
00615 {theDiff = (theDiff+512)/1024; Sfx = "KB";}
00616 sprintf(buff, "Fix %lld %s difference?", theDiff, Sfx);
00617 Resp = XrdFrmUtils::Ask('n', "Fix usage information?");
00618 if (Resp != 'y') return Resp != 'a';
00619 }
00620
00621
00622
00623 XrdOssSpace::Adjust(Space, numBytes-theClaim, XrdOssSpace::Admin);
00624 return 1;
00625 }
00626
00627
00628
00629
00630
00631 int XrdFrmAdmin::AuditUsageAX(const char *Path)
00632 {
00633 XrdOucNSWalk nsWalk(&Say, Path, Config.lockFN, XrdOucNSWalk::retFile
00634 | XrdOucNSWalk::retStat
00635 | XrdOucNSWalk::skpErrs);
00636 XrdOucNSWalk::NSEnt *nP, *pP;
00637 int ec;
00638
00639
00640
00641 if (!(nP = nsWalk.Index(ec))) {if (ec) finalRC = 4; return 1;}
00642
00643
00644
00645 while(nP)
00646 {numBytes += nP->Stat.st_size;
00647 numFiles++;
00648 pP = nP;
00649 nP = nP->Next;
00650 delete pP;
00651 }
00652
00653
00654
00655 return 0;
00656 }
00657
00658
00659
00660
00661
00662 int XrdFrmAdmin::AuditUsageXA(const char *Path, const char *Space)
00663 {
00664 XrdFrmFileset *sP;
00665 XrdFrmFiles *fP;
00666 char tmpv[8], *buff;
00667 int ec = 0;
00668
00669
00670
00671 buff = XrdOssPath::genPath(Path, Space, tmpv);
00672 fP = new XrdFrmFiles(buff, XrdFrmFiles::Recursive);
00673
00674
00675
00676 while((sP = fP->Get(ec)))
00677 {if ((sP->baseFile()))
00678 {numFiles++; numBytes += sP->baseFile()->Stat.st_size;}
00679 }
00680
00681
00682
00683 free(buff);
00684 delete fP;
00685 return ec;
00686 }
00687
00688
00689
00690
00691
00692 int XrdFrmAdmin::isXA(XrdOucNSWalk::NSEnt *nP)
00693 {
00694 char *lP;
00695
00696 if (!(nP->Link)) return 0;
00697 lP = nP->Link + nP->Lksz -1;
00698 return (*lP == XrdOssPath::xChar);
00699 }