00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <sys/stat.h>
00021
00022 #include "TDataSetManagerFile.h"
00023
00024 #include "Riostream.h"
00025 #include "TDatime.h"
00026 #include "TEnv.h"
00027 #include "TFileCollection.h"
00028 #include "TFileInfo.h"
00029 #include "TFile.h"
00030 #include "TFileStager.h"
00031 #include "TLockFile.h"
00032 #include "TMap.h"
00033 #include "TRegexp.h"
00034 #include "TMD5.h"
00035 #include "TMacro.h"
00036 #include "TMessage.h"
00037 #include "TSystem.h"
00038 #include "TError.h"
00039 #include "TPRegexp.h"
00040 #include "TVirtualMonitoring.h"
00041 #include "TObjArray.h"
00042 #include "THashList.h"
00043 #include "TKey.h"
00044 #include "TTree.h"
00045 #include "TParameter.h"
00046
00047 struct LsTreeEntry_t {
00048 TObjString *fGrp;
00049 TObjString *fUsr;
00050 TObjString *fMd5;
00051 TObjString *fLss;
00052 Long64_t fMtime;
00053 LsTreeEntry_t(const char *g, const char *u, const char *cs, const char *ls, Long64_t m) :
00054 fMtime(m) { fGrp = new TObjString(g); fUsr = new TObjString(u);
00055 fMd5 = new TObjString(cs); fLss = new TObjString(ls); }
00056 ~LsTreeEntry_t() { SafeDelete(fGrp); SafeDelete(fUsr); SafeDelete(fMd5); SafeDelete(fLss);}
00057 };
00058
00059 ClassImp(TDataSetManagerFile)
00060
00061
00062 TDataSetManagerFile::TDataSetManagerFile(const char *group,
00063 const char *user, const char *ins)
00064 : TDataSetManager(group, user, ins)
00065 {
00066
00067
00068
00069
00070 ParseInitOpts(ins);
00071
00072
00073 Init();
00074 }
00075
00076
00077 TDataSetManagerFile::TDataSetManagerFile(const char *ins)
00078 : TDataSetManager("", "", ins)
00079 {
00080
00081
00082
00083
00084 ParseInitOpts(ins);
00085
00086
00087 Init();
00088 }
00089
00090
00091 void TDataSetManagerFile::Init()
00092 {
00093
00094
00095 fIsRemote = kFALSE;
00096 if (!fUser.IsNull() && !fGroup.IsNull() && !fDataSetDir.IsNull()) {
00097
00098
00099 TString dir;
00100 dir.Form("%s/%s/%s", fDataSetDir.Data(), fGroup.Data(), fUser.Data());
00101 if (gSystem->AccessPathName(dir)) {
00102 if (gSystem->mkdir(dir, kTRUE) != 0) {
00103 TString emsg = dir;
00104
00105 fUser = fCommonUser;
00106 fGroup = fCommonGroup;
00107 ResetBit(TDataSetManager::kCheckQuota);
00108 ResetBit(TDataSetManager::kAllowRegister);
00109 ResetBit(TDataSetManager::kAllowVerify);
00110 ResetBit(TDataSetManager::kTrustInfo);
00111 dir.Form("%s/%s/%s", fDataSetDir.Data(), fGroup.Data(), fUser.Data());
00112 if (gSystem->AccessPathName(dir)) {
00113 Error("Init",
00114 "could not attach to a valid the dataset dir; paths tried:");
00115 Error("Init", " %s", emsg.Data());
00116 Error("Init", " %s", dir.Data());
00117 SetBit(TObject::kInvalidObject);
00118 return;
00119 }
00120 }
00121 }
00122
00123
00124
00125 if (!TestBit(TDataSetManager::kIsSandbox))
00126 fBase.SetUri(TString(Form("/%s/%s/", fGroup.Data(), fUser.Data())));
00127
00128
00129 TString locPath;
00130 TFile::EFileType pathType = TFile::GetType(fDataSetDir, "READ", &locPath);
00131 if (pathType == TFile::kLocal) {
00132
00133 fDataSetDir = locPath;
00134 if (gDebug > 0)
00135 Info("Init", "repository '%s' is local", fDataSetDir.Data());
00136 } else if (pathType != TFile::kDefault && pathType != TFile::kFile) {
00137 fIsRemote = kTRUE;
00138 if (gDebug > 0)
00139 Info("Init", "repository '%s' is remote", fDataSetDir.Data());
00140 }
00141
00142
00143 TString lockloc = TString::Format("%s/%s", fDataSetDir.Data(), kDataSet_LockLocation);
00144 if (!gSystem->AccessPathName(lockloc, kReadPermission)) {
00145
00146 lockloc += "?filetype=raw";
00147 TFile *f = TFile::Open(lockloc);
00148 if (f && !(f->IsZombie())) {
00149 const Int_t blen = 8192;
00150 char buf[blen];
00151 Long64_t rest = f->GetSize();
00152 while (rest > 0) {
00153 Long64_t len = (rest > blen - 1) ? blen - 1 : rest;
00154 if (f->ReadBuffer(buf, len)) {
00155 fDataSetLockFile = "";
00156 break;
00157 }
00158 buf[len] = '\0';
00159 fDataSetLockFile += buf;
00160 rest -= len;
00161 }
00162 f->Close();
00163 SafeDelete(f);
00164 fDataSetLockFile.ReplaceAll("\n","");
00165 } else {
00166 lockloc.ReplaceAll("?filetype=raw", "");
00167 Warning("Init", "could not open remore file '%s' with the lock location", lockloc.Data());
00168 }
00169 }
00170 if (fDataSetLockFile.IsNull()) {
00171 fDataSetLockFile.Form("%s-dataset-lock", fDataSetDir.Data());
00172 fDataSetLockFile.ReplaceAll("/","%");
00173 fDataSetLockFile.ReplaceAll(":","%");
00174 fDataSetLockFile.Insert(0, TString::Format("%s/", gSystem->TempDirectory()));
00175 }
00176 if (!fDataSetLockFile.IsNull() && fIsRemote) {
00177 TUrl lu(fDataSetLockFile, kTRUE);
00178 if (!strcmp(lu.GetProtocol(), "file")) {
00179
00180 TUrl u(fDataSetDir);
00181 TString srv(fDataSetDir);
00182 srv.Remove(srv.Index(u.GetFile()));
00183 fDataSetLockFile.Insert(0, srv);
00184 }
00185 }
00186 }
00187
00188
00189 fLockFileTimeLimit = 120;
00190
00191
00192 fCacheUpdatePeriod = gEnv->GetValue("ProofDataSet.CacheUpdatePeriod", 0);
00193
00194
00195 if (fMSSUrl.IsNull())
00196 fMSSUrl = gEnv->GetValue("ProofDataSet.MSSUrl", "");
00197
00198 fStageOpts = gEnv->GetValue("DataSet.StageOpts", "p=3");
00199
00200
00201 fListFile.Form("%s/%s", fDataSetDir.Data(), kDataSet_DataSetList);
00202
00203
00204 fUseCache = kFALSE;
00205 fLocalCacheDir = "";
00206 InitLocalCache();
00207 }
00208
00209 void TDataSetManagerFile::InitLocalCache()
00210 {
00211
00212
00213 fUseCache = (fIsRemote) ? kTRUE : kFALSE;
00214
00215
00216 TString useCache;
00217 if (TestBit(TDataSetManager::kUseCache)) useCache = "yes";
00218 if (TestBit(TDataSetManager::kDoNotUseCache)) useCache = "no";
00219 if (useCache.IsNull()) useCache = gEnv->GetValue("DataSet.UseCache", "");
00220 if (useCache.IsNull() && gSystem->Getenv("DATASETCACHE"))
00221 useCache = gSystem->Getenv("DATASETCACHE");
00222 useCache.ToLower();
00223 if (!useCache.IsNull())
00224 fUseCache = (useCache == "no" || useCache == "0") ? kFALSE : kTRUE;
00225
00226 if (fUseCache) {
00227 fLocalCacheDir = gSystem->Getenv("DATASETLOCALCACHEDIR");
00228 if (fLocalCacheDir.IsNull())
00229 fLocalCacheDir = gEnv->GetValue("DataSet.LocalCacheDir", "");
00230 if (!fLocalCacheDir.IsNull()) {
00231
00232 if (gSystem->AccessPathName(fLocalCacheDir)) {
00233 if (gSystem->mkdir(fLocalCacheDir, kTRUE) != 0) {
00234
00235 Warning("InitLocalCache",
00236 "non-default local cache directory '%s' could not be created"
00237 " - switching to default", fLocalCacheDir.Data());
00238 fLocalCacheDir = "";
00239 }
00240 }
00241 if (!fLocalCacheDir.IsNull() &&
00242 gSystem->AccessPathName(fLocalCacheDir, kWritePermission)) {
00243 Warning("InitLocalCache",
00244 "non-default local cache directory '%s' is not writable"
00245 " - switching to default",
00246 fDataSetDir.Data());
00247 fLocalCacheDir = "";
00248 }
00249 }
00250
00251 if (fLocalCacheDir.IsNull()) {
00252
00253 TString uds(fDataSetDir.Data());
00254 uds.ReplaceAll("/","%");
00255 uds.ReplaceAll(":","%");
00256 if (TString(gSystem->TempDirectory()).EndsWith(fUser.Data())) {
00257 fLocalCacheDir.Form("%s/%s/%s", gSystem->TempDirectory(),
00258 kDataSet_LocalCache, uds.Data());
00259 } else {
00260 fLocalCacheDir.Form("%s/%s/%s/%s", gSystem->TempDirectory(),
00261 fUser.Data(), kDataSet_LocalCache, uds.Data());
00262 }
00263
00264 if (gSystem->AccessPathName(fLocalCacheDir) && gSystem->mkdir(fLocalCacheDir, kTRUE) != 0) {
00265
00266 Warning("InitLocalCache",
00267 "local cache directory '%s' could not be created"
00268 " - disabling cache", fLocalCacheDir.Data());
00269 fUseCache = kFALSE;
00270 }
00271 if (!fLocalCacheDir.IsNull() &&
00272 gSystem->AccessPathName(fLocalCacheDir, kWritePermission)) {
00273 Warning("InitLocalCache",
00274 "local cache directory '%s' is not writable - disabling cache",
00275 fDataSetDir.Data());
00276 fUseCache = kFALSE;
00277 }
00278 if (!fUseCache) fLocalCacheDir = "";
00279 }
00280 }
00281
00282 return;
00283 }
00284
00285
00286 void TDataSetManagerFile::ParseInitOpts(const char *ins)
00287 {
00288
00289
00290
00291
00292
00293
00294
00295
00296 SetBit(TObject::kInvalidObject);
00297
00298
00299 if (!ins || strlen(ins) <= 0) return;
00300
00301
00302 Int_t from = 0;
00303 TString s(ins), tok;
00304 while (s.Tokenize(tok, from, " ")) {
00305 if (tok.BeginsWith("dir:"))
00306 fDataSetDir = tok(4, tok.Length());
00307 if (tok.BeginsWith("mss:"))
00308 fMSSUrl = tok(4, tok.Length());
00309 }
00310
00311
00312 if (fDataSetDir.IsNull()) return;
00313
00314
00315 ResetBit(TObject::kInvalidObject);
00316 }
00317
00318
00319 const char *TDataSetManagerFile::GetDataSetPath(const char *group,
00320 const char *user,
00321 const char *dsName,
00322 TString &md5path, Bool_t local)
00323 {
00324
00325
00326
00327
00328
00329
00330 if (fgCommonDataSetTag == group)
00331 group = fCommonGroup;
00332
00333 if (fgCommonDataSetTag == user)
00334 user = fCommonUser;
00335
00336 const char *ext = (!strcmp(dsName, "ls")) ? ".txt" : ".root";
00337 static TString result;
00338 if (local) {
00339 result.Form("%s/%s.%s.%s%s", fLocalCacheDir.Data(), group, user, dsName, ext);
00340 md5path.Form("%s/%s.%s.%s.md5sum", fLocalCacheDir.Data(), group, user, dsName);
00341 } else {
00342 result.Form("%s/%s/%s/%s%s", fDataSetDir.Data(), group, user, dsName, ext);
00343 md5path.Form("%s/%s/%s/%s.md5sum", fDataSetDir.Data(), group, user, dsName);
00344 }
00345 if (gDebug > 0)
00346 Info("GetDataSetPath","paths: %s, %s ", result.Data(), md5path.Data());
00347 return result;
00348 }
00349
00350
00351 Int_t TDataSetManagerFile::NotifyUpdate(const char *group, const char *user,
00352 const char *dsName, Long_t mtime, const char *checksum)
00353 {
00354
00355
00356
00357
00358
00359
00360 Long_t lsmtime = 0;
00361 TString lschecksum;
00362 Int_t lsrc = -1;
00363 if ((lsrc = CreateLsFile(group, user, lsmtime, lschecksum)) < 0) {
00364 Warning("NotifyUpdate", "problems (re-)creating the dataset lists for '/%s/%s'",
00365 group, user);
00366 }
00367
00368 { TLockFile lock(fDataSetLockFile, fLockFileTimeLimit);
00369 TString dspath = TString::Format("/%s/%s/%s", group, user, dsName);
00370
00371 Bool_t hasListFile = gSystem->AccessPathName(fListFile) ? kFALSE : kTRUE;
00372
00373 TMD5 *oldMd5 = 0, *newMd5 = 0;
00374 if (hasListFile && !(oldMd5 = TMD5::FileChecksum(fListFile.Data()))) {
00375 Error("NotifyUpdate", "problems calculating old checksum of %s", fListFile.Data());
00376 return -1;
00377 }
00378
00379 TMacro mac;
00380 if (hasListFile) mac.ReadFile(fListFile.Data());
00381
00382 TObjString *os = mac.GetLineWith(dspath);
00383 if (os) {
00384
00385 if (!strcmp(checksum, "removed")) {
00386 mac.GetListOfLines()->Remove(os);
00387 SafeDelete(os);
00388 } else {
00389
00390 os->SetString(TString::Format("%ld %s %s", mtime, dspath.Data(), checksum));
00391 }
00392 } else {
00393 if (!strcmp(checksum, "removed")) {
00394 Warning("NotifyUpdate", "entry for removed dataset '%s' not found!", dspath.Data());
00395 } else {
00396
00397 mac.AddLine(TString::Format("%ld %s %s", mtime, dspath.Data(), checksum));
00398 }
00399 }
00400
00401 TString lspath = TString::Format("/%s/%s/ls", group, user);
00402 os = mac.GetLineWith(lspath);
00403 if (os) {
00404
00405 if (lsrc == 1) {
00406 mac.GetListOfLines()->Remove(os);
00407 SafeDelete(os);
00408 } else {
00409
00410 os->SetString(TString::Format("%ld %s %s", lsmtime, lspath.Data(), lschecksum.Data()));
00411 }
00412 } else {
00413 if (lsrc == 0) {
00414
00415 mac.AddLine(TString::Format("%ld %s %s", lsmtime, lspath.Data(), lschecksum.Data()));
00416 }
00417 }
00418
00419 mac.SaveSource(fListFile.Data());
00420 if (!(newMd5 = TMD5::FileChecksum(fListFile.Data()))) {
00421 Error("NotifyUpdate", "problems calculating new checksum of %s", fListFile.Data());
00422 SafeDelete(oldMd5);
00423 return -1;
00424 }
00425 if (oldMd5 && (*newMd5 == *oldMd5))
00426 Warning("NotifyUpdate", "checksum for %s did not change!", fListFile.Data());
00427
00428 SafeDelete(oldMd5);
00429 SafeDelete(newMd5);
00430 }
00431
00432 return 0;
00433 }
00434
00435
00436 Int_t TDataSetManagerFile::CreateLsFile(const char *group, const char *user,
00437 Long_t &mtime, TString &checksum)
00438 {
00439
00440
00441
00442
00443
00444 mtime = 0;
00445 checksum = "";
00446
00447
00448 TString tmpfile;
00449 tmpfile.Form("%s/%s/%s/ls.tmp.txt", fDataSetDir.Data(), group, user);
00450
00451
00452 RedirectHandle_t rh;
00453 if (gSystem->RedirectOutput(tmpfile.Data(), "w", &rh) != 0) {
00454 Error("CreateLsFile", "problems redirecting output to %s (errno: %d)",
00455 tmpfile.Data(), TSystem::GetErrno());
00456 return -1;
00457 }
00458
00459 TString uri;
00460 uri.Form("/%s/%s", group, user);
00461 ShowDataSets(uri, "forcescan:noheader:");
00462
00463 if (gSystem->RedirectOutput(0, 0, &rh) != 0) {
00464 Error("CreateLsFile", "problems restoring output to standard streams (errno: %d)",
00465 TSystem::GetErrno());
00466 return -1;
00467 }
00468
00469 TLockFile lock(fDataSetLockFile, fLockFileTimeLimit);
00470
00471 TString lsfile;
00472 lsfile.Form("%s/%s/%s/ls.txt", fDataSetDir.Data(), group, user);
00473
00474 if (!gSystem->AccessPathName(lsfile) && gSystem->Unlink(lsfile) != 0) {
00475 Error("CreateLsFile", "problems unlinking old file '%s' (errno: %d)",
00476 lsfile.Data(), TSystem::GetErrno());
00477 return -1;
00478 }
00479
00480 FileStat_t st;
00481 if (gSystem->GetPathInfo(tmpfile, st) == 0 && st.fSize > 0) {
00482 if (gSystem->Rename(tmpfile, lsfile) != 0) {
00483 Error("CreateLsFile", "problems renaming '%s' to '%s' (errno: %d)",
00484 tmpfile.Data(), lsfile.Data(), TSystem::GetErrno());
00485 return -1;
00486 }
00487 #ifndef WIN32
00488
00489 FileStat_t udirst;
00490 if (!fIsRemote && gSystem->GetPathInfo(gSystem->DirName(tmpfile), udirst) == 0) {
00491 if (chown(lsfile.Data(), udirst.fUid, udirst.fGid) != 0) {
00492 Warning("CreateLsFile", "problems setting ownership on file '%s' (errno: %d)",
00493 lsfile.Data(), TSystem::GetErrno());
00494 }
00495 if (chmod(lsfile.Data(), 0644) != 0) {
00496 Warning("CreateLsFile", "problems setting permissions on file '%s' (errno: %d)",
00497 lsfile.Data(), TSystem::GetErrno());
00498 }
00499 }
00500 #endif
00501 mtime = st.fMtime;
00502 TMD5 *md5 = TMD5::FileChecksum(lsfile);
00503 if (!md5) {
00504 Error("CreateLsFile", "problems calculating checksum for '%s'", lsfile.Data());
00505 } else {
00506 checksum = md5->AsString();
00507 SafeDelete(md5);
00508 }
00509 } else {
00510 if (!gSystem->AccessPathName(tmpfile) && gSystem->Unlink(tmpfile) != 0) {
00511 Error("CreateLsFile", "problems unlinking temp file '%s' (errno: %d)",
00512 tmpfile.Data(), TSystem::GetErrno());
00513 return -1;
00514 }
00515
00516 return 1;
00517 }
00518
00519 return 0;
00520 }
00521
00522
00523 Bool_t TDataSetManagerFile::BrowseDataSets(const char *group, const char *user,
00524 const char *dsName,
00525 UInt_t option, TObject *target)
00526 {
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 TString userDirPath;
00542 userDirPath.Form("%s/%s/%s", fDataSetDir.Data(), group, user);
00543 void *userDir = gSystem->OpenDirectory(userDirPath);
00544 if (!userDir)
00545 return kFALSE;
00546
00547
00548 Bool_t printing = (option & kPrint) ? kTRUE : kFALSE;
00549 Bool_t exporting = (option & kExport) ? kTRUE : kFALSE;
00550 Bool_t updating = (option & kQuotaUpdate) ? kTRUE : kFALSE;
00551 Bool_t printout = (printing && (option & kDebug)) ? kTRUE : kFALSE;
00552 Bool_t listing = (option & kList) ? kTRUE : kFALSE;
00553
00554
00555 if (printing || updating)
00556 option |= kReadShort;
00557
00558
00559 if (((Int_t)printing + (Int_t)exporting + (Int_t)updating + (Int_t)listing) > 1) {
00560 Error("BrowseDataSets",
00561 "only one of kPrint, kQuotaUpdate, kExport or kList can be specified at once");
00562 return kFALSE;
00563 }
00564 Bool_t fillmap = (!exporting && !printing && !updating) ? kTRUE : kFALSE;
00565
00566
00567 TMap *outmap = (fillmap || exporting || listing) ? (TMap *)target : (TMap *)0;
00568 TList *outlist = (printing) ? (TList *)target : (TList *)0;
00569
00570 TRegexp rg("^[^./][^/]*.root$");
00571
00572 TRegexp *reds = 0;
00573 if (dsName && strlen(dsName) > 0) reds = new TRegexp(dsName, kTRUE);
00574
00575 TMap *userMap = 0, *datasetMap = 0;
00576
00577 const char *dsEnt = 0;
00578 while ((dsEnt = gSystem->GetDirEntry(userDir))) {
00579 TString datasetFile(dsEnt);
00580 if (datasetFile.Index(rg) != kNPOS) {
00581 TString datasetName(datasetFile(0, datasetFile.Length()-5));
00582
00583
00584 if (reds && datasetName.Index(*reds) == kNPOS) continue;
00585
00586 if (gDebug > 0)
00587 Info("GetDataSets", "found dataset %s of user %s in group %s",
00588 datasetName.Data(), user, group);
00589
00590 TFileCollection *fileList = GetDataSet(group, user, datasetName, option);
00591 if (!fileList) {
00592 Error("GetDataSets", "dataset %s (user %s, group %s) could not be opened",
00593 datasetName.Data(), user, group);
00594 continue;
00595 }
00596 if (gDebug > 0)
00597 fileList->Print();
00598
00599
00600
00601
00602 const char *mapGroup = group;
00603 if (fCommonGroup == mapGroup)
00604 mapGroup = fgCommonDataSetTag.Data();
00605 const char *mapUser = user;
00606 if (fCommonUser == mapUser)
00607 mapUser = fgCommonDataSetTag.Data();
00608
00609 if (fillmap && !listing && outmap) {
00610 if (!(userMap = dynamic_cast<TMap*> (outmap->GetValue(mapGroup)))) {
00611 userMap = new TMap;
00612 userMap->SetOwner();
00613 outmap->Add(new TObjString(mapGroup), userMap);
00614 }
00615
00616 if (!(datasetMap = dynamic_cast<TMap*> (userMap->GetValue(mapUser)))) {
00617 datasetMap = new TMap;
00618 datasetMap->SetOwner();
00619 userMap->Add(new TObjString(mapUser), datasetMap);
00620 }
00621 }
00622
00623
00624 if (exporting) {
00625
00626
00627 TString dsNameFormatted(Form("/%s/%s/%s", mapGroup,
00628 mapUser, datasetName.Data()));
00629 if (outmap)
00630 outmap->Add(new TObjString(dsNameFormatted), fileList);
00631
00632 } else if (updating) {
00633
00634
00635 GetQuota(mapGroup, mapUser, datasetName.Data(), fileList);
00636
00637 } else if (printing) {
00638
00639
00640 if (outlist) {
00641 TString dsNameFormatted(Form("/%s/%s/%s", mapGroup,
00642 mapUser, datasetName.Data()));
00643
00644 if (dsNameFormatted.Length() < 42)
00645 dsNameFormatted.Resize(42);
00646
00647
00648 outlist->Add(fileList->ExportInfo(dsNameFormatted));
00649 if (printout) {
00650
00651 TObjString *os = (TObjString *) outlist->Last();
00652 if (os) Printf("%s", os->GetName());
00653 }
00654 }
00655 } else if (listing) {
00656
00657
00658 if (outmap) {
00659 outmap->Add(new TObjString(TString::Format("/%s/%s/%s", mapGroup, mapUser, datasetName.Data())),
00660 new TObjString(""));
00661 }
00662 } else {
00663 if (fillmap && datasetMap)
00664 datasetMap->Add(new TObjString(datasetName), fileList);
00665 }
00666 }
00667 }
00668 gSystem->FreeDirectory(userDir);
00669 SafeDelete(reds);
00670
00671 return kTRUE;
00672 }
00673
00674
00675 TMap *TDataSetManagerFile::GetDataSets(const char *group, const char *user,
00676 const char *dsName, UInt_t option)
00677 {
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 if (group && fgCommonDataSetTag == group)
00706 group = fCommonGroup;
00707
00708 if (user && fgCommonDataSetTag == user)
00709 user = fCommonUser;
00710
00711
00712 Bool_t notCommonUser = kTRUE;
00713 if ((user && fCommonUser == user) &&
00714 (group && fCommonGroup == group)) notCommonUser = kFALSE;
00715
00716
00717 if (group && (strcmp(group, "*") == 0 || strlen(group) == 0))
00718 group = 0;
00719 if (user && (strcmp(user, "*") == 0 || strlen(user) == 0))
00720 user = 0;
00721
00722 Bool_t printing = (option & kPrint) ? kTRUE : kFALSE;
00723 Bool_t forcescan = (option & kForceScan) ? kTRUE : kFALSE;
00724 Bool_t printheader = (option & kNoHeaderPrint) ? kFALSE : kTRUE;
00725 Bool_t exporting = (option & kExport) ? kTRUE : kFALSE;
00726 Bool_t updating = (option & kQuotaUpdate) ? kTRUE : kFALSE;
00727 Bool_t refreshingls = (option & kRefreshLs) ? kTRUE : kFALSE;
00728 Bool_t listing = (option & kList) ? kTRUE : kFALSE;
00729
00730
00731 if (((Int_t)printing + (Int_t)exporting + (Int_t)updating + (Int_t)listing) > 1) {
00732 Error("GetDataSets", "only one of '?P', '?Q', '?E' or '?L' can be specified at once");
00733 return 0;
00734 }
00735
00736 TObject *result = 0;
00737 if (printing) {
00738
00739 TList *ol = new TList();
00740 ol->SetOwner();
00741 result = ol;
00742 } else if (exporting || !updating || listing) {
00743 TMap *om = new TMap;
00744 om->SetOwner();
00745 result = om;
00746 }
00747
00748 if (gDebug > 0)
00749 Info("GetDataSets", "opening dir %s", fDataSetDir.Data());
00750
00751 Long_t m;
00752 TString s;
00753 if (option & kShowDefault) {
00754
00755 if (refreshingls) {
00756 if (CreateLsFile(fCommonGroup, fCommonUser, m, s) != 0)
00757 Warning("GetDataSets", "problems recreating 'ls' info for {%s,%s}",
00758 fCommonGroup.Data(), fCommonUser.Data());
00759 } else if (!printing || forcescan || (printing &&
00760 FillLsDataSet(fCommonGroup, fCommonUser, dsName, (TList *)result, option) != 0)) {
00761 BrowseDataSets(fCommonGroup, fCommonUser, dsName, option, result);
00762 }
00763 user = 0;
00764 } else {
00765
00766 if (!notCommonUser) notCommonUser = kTRUE;
00767 }
00768
00769
00770 if (notCommonUser) {
00771
00772 if (user && group && strchr(user, '*') && strchr(group, '*')) {
00773 if (refreshingls) {
00774 if (CreateLsFile(group, user, m, s) != 0)
00775 Warning("GetDataSets", "problems recreating 'ls' info for {%s,%s}",
00776 group, user);
00777 } else if (!printing || forcescan || (printing &&
00778 FillLsDataSet(group, user, dsName, (TList *)result, option) != 0)) {
00779 BrowseDataSets(group, user, dsName, option, result);
00780 }
00781 if (!printing) return (TMap *)result;
00782 } else {
00783 TRegexp *reg = (group && strlen(group) > 0) ? new TRegexp(group, kTRUE) : 0;
00784 TRegexp *reu = (user && strlen(user) > 0) ? new TRegexp(user, kTRUE) : 0;
00785
00786 if (printing && !forcescan &&
00787 fUseCache && CheckLocalCache(group, user, 0, option) == 0) {
00788
00789 Int_t from = 0;
00790 TString locupdate, dsn, grp, usr;
00791 locupdate.Form("%s/%s", fLocalCacheDir.Data(), kDataSet_DataSetList);
00792 TMacro uptmac(locupdate);
00793 TIter nxl(uptmac.GetListOfLines());
00794 TObjString *os = 0;
00795 while ((os = (TObjString *) nxl())) {
00796 if (!(os->GetString().Contains("/ls"))) continue;
00797 from = 0;
00798 if (!(os->GetString().Tokenize(dsn, from, " "))) continue;
00799 if (!(os->GetString().Tokenize(dsn, from, " "))) continue;
00800 from = 0;
00801
00802 if (!(dsn.Tokenize(grp, from, "/")) || (reg && (grp.Index(*reg) == kNPOS))) continue;
00803
00804 if (!(dsn.Tokenize(usr, from, "/")) || (reu && (usr.Index(*reu) == kNPOS))) continue;
00805
00806 if (FillLsDataSet(grp, usr, dsName, (TList *)result, option) != 0) {
00807
00808 BrowseDataSets(grp, usr, dsName, option, result);
00809 }
00810 }
00811 } else {
00812
00813 void *dataSetDir = 0;
00814 if ((dataSetDir = gSystem->OpenDirectory(fDataSetDir))) {
00815
00816 const char *eg = 0;
00817 while ((eg = gSystem->GetDirEntry(dataSetDir))) {
00818
00819 if (strcmp(eg, ".") == 0 || strcmp(eg, "..") == 0)
00820 continue;
00821
00822 if (reg && (TString(eg).Index(*reg) == kNPOS))
00823 continue;
00824
00825 TString groupDirPath;
00826 groupDirPath.Form("%s/%s", fDataSetDir.Data(), eg);
00827
00828
00829 FileStat_t dirSt;
00830 if (gSystem->GetPathInfo(groupDirPath, dirSt) != 0 || !R_ISDIR(dirSt.fMode))
00831 continue;
00832
00833 void *groupDir = gSystem->OpenDirectory(groupDirPath);
00834 if (!groupDir)
00835 continue;
00836
00837
00838 const char *eu = 0;
00839 while ((eu = gSystem->GetDirEntry(groupDir))) {
00840
00841 if (strcmp(eu, ".") == 0 || strcmp(eu, "..") == 0)
00842 continue;
00843
00844 if (reu && (TString(eu).Index(*reu) == kNPOS))
00845 continue;
00846
00847
00848 if (refreshingls) {
00849 if (CreateLsFile(eg, eu, m, s) != 0)
00850 Warning("GetDataSets", "problems recreating 'ls' info for {%s,%s}",
00851 eg, eu);
00852 } else if (!printing || forcescan || (printing &&
00853 FillLsDataSet(eg, eu, dsName, (TList *)result, option) != 0)) {
00854
00855 BrowseDataSets(eg, eu, dsName, option, result);
00856 }
00857 }
00858 gSystem->FreeDirectory(groupDir);
00859 }
00860 gSystem->FreeDirectory(dataSetDir);
00861 }
00862 }
00863 SafeDelete(reg);
00864 SafeDelete(reu);
00865 }
00866 }
00867
00868 if (printing) {
00869 TList *output = (TList *)result;
00870 output->Sort();
00871 if (printheader) {
00872 Printf("Dataset repository: %s", fDataSetDir.Data());
00873 Printf("Dataset URI | # Files | Default tree | # Events | Disk | Staged");
00874 }
00875 TIter iter4(output);
00876 TObjString *os = 0;
00877 while ((os = dynamic_cast<TObjString*> (iter4()))) {
00878 if (os->GetString().BeginsWith("file:")) {
00879
00880 TString path(os->GetString()(5, os->GetString().Length()));
00881 RedirectHandle_t rh(path.Data());
00882 gSystem->ShowOutput(&rh);
00883 fflush(stderr);
00884 } else {
00885
00886 Printf("%s", os->String().Data());
00887 }
00888 }
00889
00890 SafeDelete(output);
00891 result = 0;
00892 }
00893
00894 return (TMap *)result;
00895 }
00896
00897
00898 Int_t TDataSetManagerFile::FillLsDataSet(const char *group, const char *user,
00899 const char *dsname, TList *out, UInt_t option)
00900 {
00901
00902
00903
00904
00905
00906
00907 if (!group || strlen(group) <= 0 || !user || strlen(user) <= 0 || !out) {
00908 Error("FillLsDataSet", "at least one of the inputs is invalid (%s,%s,%p)", group, user, out);
00909 return -1;
00910 }
00911
00912
00913 Int_t crc = -1;
00914 TString lsfile, lsmd5file;
00915 if (!fUseCache || (fUseCache && (crc = CheckLocalCache(group, user, "ls", option)) <= 0)) {
00916 Bool_t local = (crc == 0) ? kTRUE : kFALSE;
00917 lsfile = GetDataSetPath(group, user, "ls", lsmd5file, local);
00918 } else {
00919
00920 return 0;
00921 }
00922
00923 if (gSystem->AccessPathName(lsfile, kFileExists)) {
00924 if (gDebug > 0)
00925 Info("FillLsDataSet", "file '%s' does not exists", lsfile.Data());
00926 return -1;
00927 }
00928 if (gSystem->AccessPathName(lsfile, kReadPermission)) {
00929 Warning("FillLsDataSet", "file '%s' exists cannot be read (permission denied)", lsfile.Data());
00930 return -1;
00931 }
00932
00933 if (dsname && strlen(dsname) > 0) {
00934
00935 TMacro *mac = new TMacro(lsfile.Data());
00936 if (!mac) {
00937 Error("FillLsDataSet", "could not initialize TMacro from '%s'", lsfile.Data());
00938 return -1;
00939 }
00940
00941 TString fullname = TString::Format("/%s/%s/%s", group, user, dsname);
00942 Bool_t wc = (fullname.Contains("*")) ? kTRUE : kFALSE;
00943 if (wc) fullname.ReplaceAll("*", ".*");
00944 TRegexp reds(fullname);
00945 TIter nxl(mac->GetListOfLines());
00946 TObjString *o;
00947 Int_t nf = 0;
00948 while ((o = (TObjString *) nxl())) {
00949 if (o->GetString().Index(reds) != kNPOS) {
00950 out->Add(o->Clone());
00951 nf++;
00952 if (!wc) break;
00953 }
00954 }
00955 if (nf > 0 && gDebug > 0)
00956 Info("FillLsDataSet", "no match for dataset uri '/%s/%s/%s'", group, user, dsname);
00957
00958 SafeDelete(mac);
00959 } else {
00960
00961 out->Add(new TObjString(TString::Format("file:%s", lsfile.Data())));
00962 }
00963
00964 return 0;
00965 }
00966
00967
00968 TFileCollection *TDataSetManagerFile::GetDataSet(const char *group,
00969 const char *user,
00970 const char *dsName,
00971 UInt_t option,
00972 TMD5 **checksum)
00973 {
00974
00975
00976
00977
00978
00979
00980
00981 TFileCollection *fileList = 0;
00982 Bool_t readshort = (option & kReadShort) ? kTRUE : kFALSE;
00983
00984 Int_t crc = -1;
00985 TString path, md5path;
00986 if (readshort || !fUseCache ||
00987 (!readshort && fUseCache && (crc = CheckLocalCache(group, user, dsName, option)) <= 0)) {
00988 Bool_t local = (crc == 0) ? kTRUE : kFALSE;
00989 path = GetDataSetPath(group, user, dsName, md5path, local);
00990 } else {
00991
00992 if (gDebug > 0)
00993 Info("GetDataSet", "dataset %s does not exist", path.Data());
00994 return fileList;
00995 }
00996
00997
00998 TLockFile lock(fDataSetLockFile, fLockFileTimeLimit);
00999
01000
01001 if (gSystem->AccessPathName(path, kFileExists)) {
01002 if (gDebug > 0)
01003 Info("GetDataSet", "file '%s' does not exists", path.Data());
01004 return fileList;
01005 }
01006 if (gSystem->AccessPathName(path, kReadPermission)) {
01007 Warning("GetDataSet", "file '%s' exists cannot be read (permission denied)", path.Data());
01008 return fileList;
01009 }
01010
01011
01012 if (checksum) {
01013
01014 *checksum = TMD5::ReadChecksum(md5path);
01015 if (!(*checksum)) {
01016 Error("GetDataSet", "could not get checksum of %s from %s", path.Data(), md5path.Data());
01017 return fileList;
01018 }
01019 }
01020
01021 TFile *f = TFile::Open(path.Data());
01022 if (!f) {
01023 Error("GetDataSet", "could not open file %s", path.Data());
01024 if (checksum) SafeDelete(*checksum);
01025 return fileList;
01026 }
01027
01028 if (option & kReadShort)
01029 fileList = dynamic_cast<TFileCollection*> (f->Get("dataset_short"));
01030
01031 if (!fileList)
01032 fileList = dynamic_cast<TFileCollection*> (f->Get("dataset"));
01033
01034 f->Close();
01035 SafeDelete(f);
01036
01037 return fileList;
01038 }
01039
01040
01041 Int_t TDataSetManagerFile::CheckLocalCache(const char *group, const char *user,
01042 const char *dsName, UInt_t option)
01043 {
01044
01045
01046
01047
01048
01049 static TMacro *uptmac = 0;
01050 Bool_t need_last_update = (option & kNoCacheUpdate) ? kFALSE : kTRUE;
01051 TString locupdtim, locupdate, remupdate;
01052 locupdtim.Form("%s/%s.update", fLocalCacheDir.Data(), kDataSet_DataSetList);
01053 locupdate.Form("%s/%s", fLocalCacheDir.Data(), kDataSet_DataSetList);
01054 remupdate.Form("%s/%s", fDataSetDir.Data(), kDataSet_DataSetList);
01055 need_last_update = (gSystem->AccessPathName(locupdate)) ? kTRUE : need_last_update;
01056 TDatime now;
01057 UInt_t tnow = now.Convert();
01058 FileStat_t timst, locst, remst;
01059 if (need_last_update && !gSystem->AccessPathName(locupdtim)) {
01060 if (gSystem->GetPathInfo(locupdtim, timst) == 0) {
01061 need_last_update = kFALSE;
01062 if ((Int_t)tnow > timst.fMtime + fCacheUpdatePeriod) need_last_update = kTRUE;
01063 }
01064 }
01065 if (need_last_update) {
01066 if (gSystem->GetPathInfo(remupdate, remst) != 0) {
01067 Error("CheckLocalCache", "cannot get info for remote file '%s' - ignoring", remupdate.Data());
01068 return -1;
01069 }
01070 if (gSystem->GetPathInfo(locupdate, locst) == 0) {
01071 need_last_update = kFALSE;
01072 if (remst.fMtime > locst.fMtime) {
01073 need_last_update = kTRUE;
01074 } else {
01075 if (!gSystem->AccessPathName(locupdtim))
01076 if (gSystem->Utime(locupdtim, tnow, 0) != 0)
01077 Warning("CheckLocalCache",
01078 "cannot set modification time on file '%s' (errno: %d)",
01079 locupdtim.Data(), TSystem::GetErrno());
01080 }
01081 }
01082 }
01083
01084 if (need_last_update) {
01085 if (!TFile::Cp(remupdate, locupdate, kFALSE)) {
01086 Error("CheckLocalCache", "cannot get remote file '%s' - ignoring", remupdate.Data());
01087 return -1;
01088 }
01089
01090 if (gSystem->Utime(locupdate, remst.fMtime, 0) != 0) {
01091 Warning("CheckLocalCache", "cannot set modification time on file '%s' (errno: %d)",
01092 locupdate.Data(), TSystem::GetErrno());
01093 }
01094
01095 if (gSystem->AccessPathName(locupdtim)) {
01096 FILE *ftim = fopen(locupdtim.Data(), "w");
01097 if (!ftim) {
01098 Warning("CheckLocalCache", "problems create file '%s' (errno: %d)",
01099 locupdtim.Data(), TSystem::GetErrno());
01100 } else {
01101 if (fclose(ftim) != 0)
01102 Warning("CheckLocalCache", "problems close file '%s' (errno: %d)",
01103 locupdtim.Data(), TSystem::GetErrno());
01104 if (gSystem->Utime(locupdtim, now.Convert(), 0) != 0)
01105 Warning("CheckLocalCache",
01106 "cannot set modification time on file '%s' (errno: %d)",
01107 locupdtim.Data(), TSystem::GetErrno());
01108 }
01109 }
01110
01111 SafeDelete(uptmac);
01112 uptmac = new TMacro(locupdate);
01113 } else {
01114
01115 if (gSystem->AccessPathName(locupdtim)) {
01116 FILE *ftim = fopen(locupdtim.Data(), "w");
01117 if (!ftim) {
01118 Warning("CheckLocalCache", "problems create file '%s' (errno: %d)",
01119 locupdtim.Data(), TSystem::GetErrno());
01120 } else {
01121 if (fclose(ftim) != 0)
01122 Warning("CheckLocalCache", "problems close file '%s' (errno: %d)",
01123 locupdtim.Data(), TSystem::GetErrno());
01124 if (gSystem->GetPathInfo(locupdate, locst) == 0) {
01125 if (gSystem->Utime(locupdtim, locst.fMtime, 0) != 0)
01126 Warning("CheckLocalCache",
01127 "cannot set modification time on file '%s' (errno: %d)",
01128 locupdtim.Data(), TSystem::GetErrno());
01129 } else {
01130 Warning("CheckLocalCache", "cannot get info for file '%s'"
01131 " - will not touch '%s'", locupdate.Data(), locupdtim.Data());
01132 }
01133 }
01134 }
01135 if (!uptmac) uptmac = new TMacro(locupdate);
01136 }
01137
01138
01139 if (!dsName || strlen(dsName) <= 0)
01140 return 0;
01141
01142
01143 TString ds, locpath, path, locmd5path, md5path, remmd5s;
01144 TMD5 *locmd5 = 0;
01145
01146 path = GetDataSetPath(group, user, dsName, md5path);
01147 locpath = GetDataSetPath(group, user, dsName, locmd5path, kTRUE);
01148 ds.Form("/%s/%s/%s", group, user, dsName);
01149 TObjString *os = uptmac->GetLineWith(ds);
01150 if (!os) {
01151
01152 if (strcmp(dsName, "ls"))
01153 Warning("CheckLocalCache", "dataset '%s' does not exists anymore", ds.Data());
01154 return 1;
01155 }
01156
01157 TString s;
01158 Int_t from = 0;
01159 while (os->GetString().Tokenize(s, from, " ")) {
01160 if (!s.IsDigit() && s != ds) {
01161 remmd5s = s;
01162 }
01163 }
01164 if (remmd5s == "---") {
01165
01166 if (strcmp(dsName, "ls"))
01167 Warning("CheckLocalCache", "dataset '%s' does not exists anymore", ds.Data());
01168 return 1;
01169 }
01170 Bool_t need_update = (option & kNoCacheUpdate) ? kFALSE : kTRUE;
01171 if (!gSystem->AccessPathName(locpath)) {
01172 if (need_update) {
01173 need_update = kFALSE;
01174 locmd5 = TMD5::ReadChecksum(locmd5path);
01175 if (!locmd5 && !(locmd5 = TMD5::FileChecksum(locpath))) {
01176 Warning("CheckLocalCache", "cannot get checksum of '%s' - assuming match failed", ds.Data());
01177 need_update = kTRUE;
01178 } else {
01179 if (remmd5s != locmd5->AsString()) need_update = kTRUE;
01180 }
01181 }
01182 } else {
01183 need_update = kTRUE;
01184 }
01185
01186 if (need_update) {
01187 SafeDelete(locmd5);
01188 if (!TFile::Cp(path, locpath, kFALSE)) {
01189 Error("CheckLocalCache", "cannot get remote file '%s' - ignoring", path.Data());
01190 return -1;
01191 }
01192
01193 locmd5 = TMD5::FileChecksum(locpath);
01194 if (locmd5) {
01195 if (remmd5s != locmd5->AsString())
01196 Warning("CheckLocalCache", "checksum for freshly downloaded file '%s' does not match the"
01197 " one posted in '%s'", locpath.Data(), kDataSet_DataSetList);
01198 if (TMD5::WriteChecksum(locmd5path, locmd5) != 0)
01199 Warning("CheckLocalCache", "problems saving checksum to '%s' (errno: %d)",
01200 locmd5path.Data(), TSystem::GetErrno());
01201 } else {
01202 Warning("CheckLocalCache", "problems calculating checksum for '%s'", locpath.Data());
01203 }
01204 }
01205 SafeDelete(locmd5);
01206
01207 return 0;
01208 }
01209
01210
01211 Int_t TDataSetManagerFile::ClearCache(const char *uri)
01212 {
01213
01214
01215
01216 void *dirp = gSystem->OpenDirectory(fLocalCacheDir.Data());
01217 if (!dirp) {
01218 Error("ClearCache", "cannot open directory '%s' (errno: %d)",
01219 fLocalCacheDir.Data(), TSystem::GetErrno());
01220 return -1;
01221 }
01222 TRegexp *re = 0;
01223 if (uri && strlen(uri) > 0) {
01224 if (strcmp(uri, "*") && strcmp(uri, "/*") && strcmp(uri, "/*/") &&
01225 strcmp(uri, "/*/*") && strcmp(uri, "/*/*/") && strcmp(uri, "/*/*/*")) {
01226 TString u(uri);
01227
01228 if (u(0) == '/') u.Remove(0,1);
01229
01230 u.ReplaceAll("/", ".");
01231
01232 u.ReplaceAll("*", ".*");
01233 re = new TRegexp(u.Data());
01234 }
01235 }
01236
01237 Printf(" Dataset repository: %s", fDataSetDir.Data());
01238 Printf(" Local cache directory: %s", fLocalCacheDir.Data());
01239
01240 Long64_t totsz = 0, nf = 0;
01241 FileStat_t st;
01242 TString path;
01243 const char *e = 0;
01244 while ((e = gSystem->GetDirEntry(dirp))) {
01245
01246 if (!strcmp(e,".") || !strcmp(e,"..")) continue;
01247
01248 if (re && TString(e).Index(*re) == kNPOS) continue;
01249
01250 path.Form("%s/%s", fLocalCacheDir.Data(), e);
01251
01252 if (gSystem->GetPathInfo(path, st) != 0) {
01253 Warning("ShowCache", "problems 'stat'-ing '%s' (errno: %d)",
01254 path.Data(), TSystem::GetErrno());
01255 continue;
01256 }
01257
01258 totsz += st.fSize;
01259 nf++;
01260
01261 if (gSystem->Unlink(path) != 0) {
01262 Warning("ClearCache", "problems unlinking '%s' (errno: %d)",
01263 path.Data(), TSystem::GetErrno());
01264 }
01265 }
01266 gSystem->FreeDirectory(dirp);
01267 SafeDelete(re);
01268
01269
01270 Printf(" %lld bytes (%lld files) have been freed", totsz, nf);
01271
01272
01273 return 0;
01274 }
01275
01276
01277 Int_t TDataSetManagerFile::ShowCache(const char *uri)
01278 {
01279
01280
01281
01282 void *dirp = gSystem->OpenDirectory(fLocalCacheDir.Data());
01283 if (!dirp) {
01284 Error("ShowCache", "cannot open directory '%s' (errno: %d)",
01285 fLocalCacheDir.Data(), TSystem::GetErrno());
01286 return -1;
01287 }
01288 TRegexp *re = 0;
01289 if (uri && strlen(uri) > 0) {
01290 if (strcmp(uri, "*") && strcmp(uri, "/*") && strcmp(uri, "/*/") &&
01291 strcmp(uri, "/*/*") && strcmp(uri, "/*/*/") && strcmp(uri, "/*/*/*")) {
01292 TString u(uri);
01293
01294 if (u(0) == '/') u.Remove(0,1);
01295
01296 u.ReplaceAll("/", ".");
01297
01298 u.ReplaceAll("*", ".*");
01299 re = new TRegexp(u.Data());
01300 }
01301 }
01302
01303 Printf(" Dataset repository: %s", fDataSetDir.Data());
01304 Printf(" Local cache directory: %s", fLocalCacheDir.Data());
01305 Printf(" Last modified Size(bytes) File");
01306
01307 Long64_t totsz = 0, nf = 0;
01308 FileStat_t st;
01309 TString path, sz;
01310 const char *e = 0;
01311 while ((e = gSystem->GetDirEntry(dirp))) {
01312
01313 if (!strcmp(e,".") || !strcmp(e,"..")) continue;
01314
01315 if (re && TString(e).Index(*re) == kNPOS) continue;
01316
01317 path.Form("%s/%s", fLocalCacheDir.Data(), e);
01318
01319 if (gSystem->GetPathInfo(path, st) != 0) {
01320 Warning("ShowCache", "problems 'stat'-ing '%s' (errno: %d)",
01321 path.Data(), TSystem::GetErrno());
01322 continue;
01323 }
01324
01325 totsz += st.fSize;
01326 nf++;
01327
01328 TDatime tmod(st.fMtime);
01329 sz.Form("%lld", st.fSize);
01330 sz.Resize(12);
01331 Printf(" %s %s %s", tmod.AsSQLString(), sz.Data(), e);
01332 }
01333 gSystem->FreeDirectory(dirp);
01334 SafeDelete(re);
01335
01336
01337 Printf(" %lld files, %lld bytes", nf, totsz);
01338
01339
01340 return 0;
01341 }
01342
01343
01344 Int_t TDataSetManagerFile::WriteDataSet(const char *group, const char *user,
01345 const char *dsName, TFileCollection *dataset,
01346 UInt_t option, TMD5 *checksum)
01347 {
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358 TString md5path, path, md5sum;
01359 Long_t mtime = 0;
01360 { TLockFile lock(fDataSetLockFile, fLockFileTimeLimit);
01361
01362 Bool_t checkIfExists = ((option & kFileMustExist) || checksum) ? kTRUE : kFALSE;
01363
01364 path = GetDataSetPath(group, user, dsName, md5path);
01365
01366 if (checkIfExists) {
01367
01368 Long_t tmp;
01369 if (gSystem->GetPathInfo(path, 0, (Long_t*) 0, 0, &tmp) != 0) {
01370 if (gDebug > 0)
01371 Info("WriteDataSet", "Dataset disappeared. Discarding update.");
01372 return 3;
01373 }
01374 }
01375
01376 if (checksum) {
01377
01378 TMD5 *checksum2 = TMD5::FileChecksum(path);
01379 if (!checksum2) {
01380 Error("WriteDataSet", "Could not get checksum of %s", path.Data());
01381 return 0;
01382 }
01383
01384 Bool_t checksumAgrees = (*checksum == *checksum2);
01385 delete checksum2;
01386
01387 if (!checksumAgrees) {
01388 if (gDebug > 0)
01389 Info("WriteDataSet", "Dataset changed. Discarding update.");
01390 return 2;
01391 }
01392 }
01393
01394
01395 TString tempFile(path);
01396 Int_t index = -1;
01397 while (tempFile.Index("/", index+1) >= 0)
01398 index = tempFile.Index("/", index+1);
01399
01400 tempFile.Insert(index+1, ".");
01401
01402 TFile *f = TFile::Open(tempFile, "RECREATE");
01403 if (!f) {
01404 Error("WriteDataSet", "Could not open dataset for writing %s", tempFile.Data());
01405 return 0;
01406 }
01407
01408
01409 dataset->Write("dataset", TObject::kSingleKey | TObject::kOverwrite);
01410
01411
01412 THashList *list = dataset->GetList();
01413 dataset->SetList(0);
01414 dataset->Write("dataset_short", TObject::kSingleKey | TObject::kOverwrite);
01415
01416 f->Close();
01417 delete f;
01418
01419
01420 dataset->SetList(list);
01421
01422
01423 if (gSystem->Rename(tempFile, path) != 0) {
01424 Error("WriteDataSet", "renaming %s to %s failed; dataset might be corrupted",
01425 tempFile.Data(), path.Data());
01426
01427 if (!gSystem->AccessPathName(md5path, kWritePermission) && gSystem->Unlink(md5path) != 0)
01428 Error("WriteDataSet", "unlink of %s failed", md5path.Data());
01429 return 0;
01430 }
01431
01432 if (ChecksumDataSet(path, md5path, md5sum) != 0) {
01433 Error("WriteDataSet", "problems calculating checksum of %s", path.Data());
01434 return 0;
01435 }
01436 FileStat_t st;
01437 if (gSystem->GetPathInfo(path, st) != 0) {
01438 Error("WriteDataSet", "could not 'stat' the version of '%s'!", path.Data());
01439 return 0;
01440 }
01441 mtime= st.fMtime;
01442 }
01443
01444
01445 if (NotifyUpdate(group, user, dsName, mtime, md5sum) != 0)
01446 Warning("WriteDataSet", "problems notifying update with 'NotifyUpdate'");
01447
01448 return 1;
01449 }
01450
01451
01452 Int_t TDataSetManagerFile::ChecksumDataSet(const char *path,
01453 const char *md5path, TString &checksum)
01454 {
01455
01456
01457
01458
01459 checksum = "";
01460
01461 if (!path || strlen(path) <= 0 || !md5path || strlen(md5path) <= 0) {
01462 Error("ChecksumDataSet", "one or more inputs are invalid ('%s','%s')",
01463 path, md5path);
01464 return -1;
01465 }
01466
01467 TMD5 *md5sum = TMD5::FileChecksum(path);
01468 if (!md5sum) {
01469 Error("ChecksumDataSet", "problems calculating checksum of '%s'", path);
01470 return -1;
01471 }
01472
01473 if (TMD5::WriteChecksum(md5path, md5sum) != 0) {
01474 Error("ChecksumDataSet", "problems saving checksum to '%s'", md5path);
01475 SafeDelete(md5sum);
01476 return -1;
01477 }
01478
01479 checksum = md5sum->AsString();
01480
01481 SafeDelete(md5sum);
01482 return 0;
01483 }
01484
01485
01486 Bool_t TDataSetManagerFile::RemoveDataSet(const char *group, const char *user,
01487 const char *dsName)
01488 {
01489
01490
01491 TString md5path, path;
01492 { TLockFile lock(fDataSetLockFile, fLockFileTimeLimit);
01493
01494 path = GetDataSetPath(group, user, dsName, md5path);
01495 Int_t rc = 0;
01496
01497 if ((rc = gSystem->Unlink(path)) != 0)
01498 Warning("RemoveDataSet", "problems removing main file '%s' (errno: %d)",
01499 path.Data(), TSystem::GetErrno());
01500
01501 if (gSystem->Unlink(md5path) != 0)
01502 Warning("RemoveDataSet", "problems removing chcksum file '%s' (errno: %d)",
01503 md5path.Data(), TSystem::GetErrno());
01504 }
01505
01506
01507 if (gSystem->AccessPathName(path, kFileExists)) {
01508 if (NotifyUpdate(group, user, dsName, 0, "removed") != 0)
01509 Warning("RemoveDataSet", "problems notifying update with 'NotifyUpdate'");
01510
01511 return kTRUE;
01512 }
01513
01514 return kFALSE;
01515 }
01516
01517
01518 Bool_t TDataSetManagerFile::ExistsDataSet(const char *group, const char *user,
01519 const char *dsName)
01520 {
01521
01522
01523 TLockFile lock(fDataSetLockFile, fLockFileTimeLimit);
01524
01525 TString md5path, path(GetDataSetPath(group, user, dsName, md5path));
01526
01527 return (gSystem->AccessPathName(path) == kFALSE);
01528 }
01529
01530
01531 Int_t TDataSetManagerFile::RegisterDataSet(const char *uri,
01532 TFileCollection *newDataSet,
01533 const char *opts)
01534 {
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546 if (!TestBit(TDataSetManager::kAllowRegister))
01547 return -1;
01548
01549
01550 TString dsName;
01551 if (ParseUri(uri, 0, 0, &dsName, 0, kTRUE) == kFALSE) {
01552 Error("RegisterDataSet", "problem parsing uri: %s", uri);
01553 return -1;
01554 }
01555
01556
01557 TFileCollection *dataSet = newDataSet;
01558
01559 TString opt(opts);
01560
01561 if (opt.Contains("U", TString::kIgnoreCase)) {
01562
01563 if (ExistsDataSet(fGroup, fUser, dsName)) {
01564
01565 if (!(dataSet = GetDataSet(fGroup, fUser, dsName))) {
01566
01567 Warning("RegisterDataSet",
01568 "dataset '%s' claimed to exists but retrieval failed - ignoring", uri);
01569 dataSet = newDataSet;
01570 } else {
01571
01572 dataSet->Add(newDataSet);
01573 }
01574 }
01575 } else if (!opt.Contains("O", TString::kIgnoreCase)) {
01576
01577 if (ExistsDataSet(fGroup, fUser, dsName)) {
01578
01579 Error("RegisterDataSet", "dataset '%s' exists already", uri);
01580 return -1;
01581 }
01582 }
01583
01584
01585 dataSet->Sort();
01586
01587
01588 TList *uniqueFileList = new TList();
01589 TIter nextFile(dataSet->GetList());
01590 TFileInfo *prevFile = (TFileInfo*)nextFile();
01591 uniqueFileList->Add(prevFile);
01592 while (TFileInfo *obj = (TFileInfo*)nextFile()) {
01593
01594 if (prevFile->Compare(obj)) {
01595 uniqueFileList->Add(obj);
01596 prevFile = obj;
01597 }
01598 }
01599
01600
01601
01602 dataSet->GetList()->SetOwner(0);
01603 dataSet->GetList()->Clear("nodelete");
01604 dataSet->GetList()->SetOwner(1);
01605 dataSet->GetList()->AddAll(uniqueFileList);
01606 uniqueFileList->SetOwner(kFALSE);
01607 delete uniqueFileList;
01608
01609
01610 Bool_t reset = kTRUE;
01611 if (opt.Contains("T", TString::kIgnoreCase)) {
01612 if (!TestBit(TDataSetManager::kTrustInfo)) {
01613 Warning("RegisterDataSet", "configured to not trust the information"
01614 " provided by users: ignoring request");
01615 } else {
01616 reset = kFALSE;
01617 }
01618 }
01619 if (reset) {
01620 dataSet->SetName(dsName);
01621 dataSet->ResetBitAll(TFileInfo::kStaged);
01622 dataSet->ResetBitAll(TFileInfo::kCorrupted);
01623 dataSet->RemoveMetaData();
01624 }
01625
01626
01627 if (opt.Contains("V", TString::kIgnoreCase)) {
01628 if (TestBit(TDataSetManager::kAllowVerify)) {
01629
01630 if (TDataSetManager::ScanDataSet(dataSet, 1, 0, 0, kTRUE ) < 0) {
01631 Error("RegisterDataSet", "problems verifying the dataset");
01632 return -1;
01633 }
01634 } else {
01635 Warning("RegisterDataSet", "user-driven verification not allowed: ignoring request");
01636 }
01637 }
01638
01639
01640 dataSet->Update(fAvgFileSize);
01641
01642 if (TestBit(TDataSetManager::kCheckQuota)) {
01643 if (dataSet->GetTotalSize() <= 0) {
01644 Error("RegisterDataSet", "datasets without size information are not accepted:");
01645 if (fAvgFileSize < 0) {
01646 Error("RegisterDataSet", "you may want to define an average"
01647 " file size to get an estimated dataset size");
01648 }
01649 return -1;
01650 }
01651
01652 UpdateUsedSpace();
01653 Long64_t used = GetGroupUsed(fGroup) + dataSet->GetTotalSize();
01654
01655 Info("RegisterDataSet", "your group %s uses %.1f GB + %.1f GB for the new dataset; "
01656 "the available quota is %.1f GB", fGroup.Data(),
01657 (Float_t) GetGroupUsed(fGroup) / 1073741824,
01658 (Float_t) dataSet->GetTotalSize() / 1073741824,
01659 (Float_t) GetGroupQuota(fGroup) / 1073741824);
01660 if (used > GetGroupQuota(fGroup)) {
01661 Error("RegisterDataSet", "quota exceeded");
01662 return -1;
01663 }
01664 }
01665
01666 Bool_t success = WriteDataSet(fGroup, fUser, dsName, dataSet);
01667 if (!success)
01668 Error("RegisterDataSet", "could not write dataset: %s", dsName.Data());
01669
01670
01671 return ((success) ? 0 : -1);
01672 }
01673
01674 Int_t TDataSetManagerFile::ScanDataSet(const char *uri, UInt_t opt)
01675 {
01676
01677
01678
01679
01680
01681 TString dsName, dsTree;
01682 if ((opt & kSetDefaultTree)) {
01683 if (TestBit(TDataSetManager::kAllowRegister)) {
01684 if (ParseUri(uri, 0, 0, &dsName, &dsTree, kTRUE)) {
01685 TFileCollection *dataset = GetDataSet(fGroup, fUser, dsName);
01686 if (!dataset) return -1;
01687 dataset->SetDefaultTreeName(dsTree.Data());
01688 Int_t rc = WriteDataSet(fGroup, fUser, dsName, dataset);
01689 delete dataset;
01690 return (rc == 0) ? -1 : 0;
01691 }
01692 }
01693 } else {
01694 if (TestBit(TDataSetManager::kAllowVerify)) {
01695 if (ParseUri(uri, 0, 0, &dsName, 0, kTRUE, kTRUE)) {
01696 if (!(dsName.Contains("*"))) {
01697 if (ScanDataSet(fGroup, fUser, dsName, opt) > 0)
01698 return GetNDisapparedFiles();
01699 } else {
01700 TString luri = TString::Format("/%s/%s/%s", fGroup.Data(), fUser.Data(), dsName.Data());
01701 TMap *fcs = GetDataSets(luri, kList);
01702 if (!fcs) return -1;
01703 fcs->Print();
01704 Int_t ndisappeared = 0;
01705 TIter nxd(fcs);
01706 TObjString *d = 0;
01707 while ((d = (TObjString *) nxd())) {
01708 if (!(d->GetString().IsNull())) {
01709 TString dsn(d->GetName());
01710 if (dsn.Contains("/")) dsn.Remove(0, dsn.Last('/') + 1);
01711 if (ScanDataSet(fGroup, fUser, dsn, opt) > 0) {
01712 ndisappeared += GetNDisapparedFiles();
01713 } else {
01714 Warning("ScanDataSet", "problems processing dataset: %s", d->GetName());
01715 }
01716 } else {
01717 Warning("ScanDataSet", "empty string found in map while processing: %s", uri);
01718 }
01719 }
01720 SafeDelete(fcs);
01721 return ndisappeared;
01722 }
01723 }
01724 }
01725 }
01726 return -1;
01727 }
01728
01729
01730 Int_t TDataSetManagerFile::ScanDataSet(const char *group, const char *user,
01731 const char *dsName, UInt_t option)
01732 {
01733
01734
01735 if (!TestBit(TDataSetManager::kAllowVerify))
01736 return -1;
01737
01738 TFileCollection *dataset = GetDataSet(group, user, dsName);
01739 if (!dataset)
01740 return -1;
01741
01742
01743 Int_t fopt = ((option & kAllFiles)) ? -1 : 0;
01744 if (fopt >= 0) {
01745 if ((option & kStagedFiles)) {
01746 fopt = 10;
01747 } else {
01748 if ((option & kReopen)) fopt++;
01749 if ((option & kTouch)) fopt++;
01750 }
01751 if ((option & kNoStagedCheck)) fopt += 100;
01752 } else {
01753 if ((option & kStagedFiles) || (option & kReopen) || (option & kTouch)) {
01754 Warning("ScanDataSet", "kAllFiles mode: ignoring kStagedFiles or kReopen"
01755 " or kTouch requests");
01756 }
01757 if ((option & kNoStagedCheck)) fopt -= 100;
01758 }
01759
01760
01761 Int_t sopt = ((option & kNoAction)) ? -1 : 0;
01762 if (sopt >= 0) {
01763 if ((option & kLocateOnly) && (option & kStageOnly)) {
01764 Error("ScanDataSet", "kLocateOnly and kStageOnly cannot be processed concurrently");
01765 return -1;
01766 }
01767 if ((option & kLocateOnly)) sopt = 1;
01768 if ((option & kStageOnly)) sopt = 2;
01769 } else if ((option & kLocateOnly) || (option & kStageOnly)) {
01770 Warning("ScanDataSet", "kNoAction mode: ignoring kLocateOnly or kStageOnly requests");
01771 }
01772
01773 Bool_t dbg = ((option & kDebug)) ? kTRUE : kFALSE;
01774
01775 Int_t result = TDataSetManager::ScanDataSet(dataset, fopt, sopt, 0, dbg,
01776 &fNTouchedFiles, &fNOpenedFiles, &fNDisappearedFiles,
01777 (TList *)0, fAvgFileSize, fMSSUrl.Data(), -1, fStageOpts.Data());
01778 if (result == 2) {
01779 if (WriteDataSet(group, user, dsName, dataset) == 0) {
01780 delete dataset;
01781 return -2;
01782 }
01783 }
01784 delete dataset;
01785
01786 return result;
01787 }
01788
01789
01790 TMap *TDataSetManagerFile::GetDataSets(const char *uri, UInt_t option)
01791 {
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810 TString dsUser, dsGroup, dsName;
01811
01812 if (((option & kPrint) || (option & kExport)) && strlen(uri) <= 0)
01813 option |= kShowDefault;
01814
01815 if (ParseUri(uri, &dsGroup, &dsUser, &dsName, 0, kFALSE, kTRUE))
01816 return GetDataSets(dsGroup, dsUser, dsName, option);
01817 return (TMap *)0;
01818 }
01819
01820
01821 TFileCollection *TDataSetManagerFile::GetDataSet(const char *uri, const char *opts)
01822 {
01823
01824
01825 TString dsUser, dsGroup, dsName, ss(opts);
01826
01827 TFileCollection *fc = 0;
01828 if (!strchr(uri, '*')) {
01829 if (!ParseUri(uri, &dsGroup, &dsUser, &dsName)) return fc;
01830 UInt_t opt = (ss.Contains("S:") || ss.Contains("short:")) ? kReadShort : 0;
01831 ss.ReplaceAll("S:","");
01832 ss.ReplaceAll("short:","");
01833 fc = GetDataSet(dsGroup, dsUser, dsName, opt);
01834 } else {
01835 TMap *fcs = GetDataSets(uri);
01836 if (!fcs) return fc;
01837 TIter nxd(fcs);
01838 TObject *k = 0;
01839 TFileCollection *xfc = 0;
01840 while ((k = nxd()) && (xfc = (TFileCollection *) fcs->GetValue(k))) {
01841 if (!fc) {
01842
01843 fc = xfc;
01844 fcs->Remove(k);
01845 } else {
01846
01847 fc->Add(xfc);
01848 }
01849 }
01850 }
01851
01852 if (fc && !ss.IsNull()) {
01853
01854 TFileCollection *sfc = 0;
01855 TString s;
01856 Int_t from = 0;
01857 while (ss.Tokenize(s, from, ",")) {
01858 TFileCollection *xfc = fc->GetFilesOnServer(s.Data());
01859 if (xfc) {
01860 if (sfc) {
01861 sfc->Add(xfc);
01862 delete xfc;
01863 } else {
01864 sfc = xfc;
01865 }
01866 }
01867 }
01868
01869 delete fc;
01870 fc = sfc;
01871 }
01872
01873 return fc;
01874 }
01875
01876
01877 Bool_t TDataSetManagerFile::RemoveDataSet(const char *uri)
01878 {
01879
01880
01881 TString dsName;
01882
01883 if (TestBit(TDataSetManager::kAllowRegister)) {
01884 if (ParseUri(uri, 0, 0, &dsName, 0, kTRUE)) {
01885 Bool_t rc = RemoveDataSet(fGroup, fUser, dsName);
01886 if (rc) return kTRUE;
01887 Error("RemoveDataSet", "error removing dataset %s", dsName.Data());
01888 }
01889 }
01890 return kFALSE;
01891 }
01892
01893
01894 Bool_t TDataSetManagerFile::ExistsDataSet(const char *uri)
01895 {
01896
01897
01898 TString dsUser, dsGroup, dsName;
01899
01900 if (ParseUri(uri, &dsGroup, &dsUser, &dsName))
01901 return ExistsDataSet(dsGroup, dsUser, dsName);
01902 return kFALSE;
01903 }
01904
01905
01906 void TDataSetManagerFile::UpdateUsedSpace()
01907 {
01908
01909
01910
01911 fGroupUsed.DeleteAll();
01912 fUserUsed.DeleteAll();
01913
01914
01915 GetDataSets(0, 0, 0, (UInt_t)kQuotaUpdate);
01916 }