#include "TProofDataSetManagerFile.h"
#include "Riostream.h"
#include "TEnv.h"
#include "TFileCollection.h"
#include "TFileInfo.h"
#include "TFile.h"
#include "TFileStager.h"
#include "TLockFile.h"
#include "TMap.h"
#include "TRegexp.h"
#include "TMD5.h"
#include "TMessage.h"
#include "TSystem.h"
#include "TError.h"
#include "TPRegexp.h"
#include "TVirtualMonitoring.h"
#include "TObjArray.h"
#include "THashList.h"
#include "TKey.h"
#include "TTree.h"
#include "TParameter.h"
ClassImp(TProofDataSetManagerFile)
TProofDataSetManagerFile::TProofDataSetManagerFile(const char *group,
const char *user,
const char *ins)
: TProofDataSetManager(group, user, ins)
{
ParseInitOpts(ins);
if (!fUser.IsNull() && !fGroup.IsNull() && !fDataSetDir.IsNull()) {
TString dir(Form("%s/%s/%s", fDataSetDir.Data(), fGroup.Data(), fUser.Data()));
if (gSystem->AccessPathName(dir)) {
if (gSystem->mkdir(dir, kTRUE) != 0) {
Error("TProofDataSetManagerFile", "could not create the dataset dir");
SetBit(TObject::kInvalidObject);
return;
}
}
if (!TestBit(TProofDataSetManager::kIsSandbox))
fBase.SetUri(TString(Form("/%s/%s/", fGroup.Data(), fUser.Data())));
fDataSetLockFile = Form("%s-dataset-lock", fDataSetDir.Data());
fDataSetLockFile.ReplaceAll("/","%");
fDataSetLockFile.ReplaceAll(":","%");
fDataSetLockFile.Insert(0, Form("%s/", gSystem->TempDirectory()));
fLockFileTimeLimit = 120;
}
if (fMSSUrl.IsNull())
fMSSUrl = gEnv->GetValue("ProofDataSet.MSSUrl", "");
}
void TProofDataSetManagerFile::ParseInitOpts(const char *ins)
{
SetBit(TObject::kInvalidObject);
if (!ins || strlen(ins) <= 0) return;
Int_t from = 0;
TString s(ins), tok;
while (s.Tokenize(tok, from, " ")) {
if (tok.BeginsWith("dir:"))
fDataSetDir = tok(4, tok.Length());
if (tok.BeginsWith("mss:"))
fMSSUrl = tok(4, tok.Length());
}
if (fDataSetDir.IsNull()) return;
ResetBit(TObject::kInvalidObject);
}
const char *TProofDataSetManagerFile::GetDataSetPath(const char *group,
const char *user,
const char *dsName)
{
if (fgCommonDataSetTag == group)
group = fCommonGroup;
if (fgCommonDataSetTag == user)
user = fCommonUser;
static TString result;
result.Form("%s/%s/%s/%s.root", fDataSetDir.Data(), group, user, dsName);
if (gDebug > 0)
Info("GetDataSetPath","path: %s", result.Data());
return result;
}
Bool_t TProofDataSetManagerFile::BrowseDataSets(const char *group,
const char *user,
UInt_t option, TObject *target)
{
TString userDirPath;
userDirPath.Form("%s/%s/%s", fDataSetDir.Data(), group, user);
void *userDir = gSystem->OpenDirectory(userDirPath);
if (!userDir)
return kFALSE;
Bool_t printing = (option & kPrint) ? kTRUE : kFALSE;
Bool_t exporting = (option & kExport) ? kTRUE : kFALSE;
Bool_t updating = (option & kQuotaUpdate) ? kTRUE : kFALSE;
if (printing || updating)
option |= kReadShort;
if (((Int_t)printing + (Int_t)exporting + (Int_t)updating) > 1) {
Error("BrowseDataSets",
"only one of kPrint, kQuotaUpdate or kExport can be specified at once");
return kFALSE;
}
Bool_t fillmap = (!exporting && !printing && !updating) ? kTRUE : kFALSE;
TMap *outmap = (fillmap || exporting) ? (TMap *)target : (TMap *)0;
TList *outlist = (printing) ? (TList *)target : (TList *)0;
TRegexp rg("^[^./][^/]*.root$");
TMap *userMap = 0, *datasetMap = 0;
const char *dsEnt = 0;
while ((dsEnt = gSystem->GetDirEntry(userDir))) {
TString datasetFile(dsEnt);
if (datasetFile.Index(rg) != kNPOS) {
TString datasetName(datasetFile(0, datasetFile.Length()-5));
if (gDebug > 0)
Info("GetDataSets", "found dataset %s of user %s in group %s",
datasetName.Data(), user, group);
TFileCollection *fileList = GetDataSet(group, user, datasetName, option);
if (!fileList) {
Error("GetDataSets", "dataset %s (user %s, group %s) could not be opened",
datasetName.Data(), user, group);
continue;
}
if (gDebug > 0)
fileList->Print();
const char *mapGroup = group;
if (fCommonGroup == mapGroup)
mapGroup = fgCommonDataSetTag.Data();
const char *mapUser = user;
if (fCommonUser == mapUser)
mapUser = fgCommonDataSetTag.Data();
if (fillmap && outmap) {
if (!(userMap = dynamic_cast<TMap*> (outmap->GetValue(mapGroup)))) {
userMap = new TMap;
userMap->SetOwner();
outmap->Add(new TObjString(mapGroup), userMap);
}
if (!(datasetMap = dynamic_cast<TMap*> (userMap->GetValue(mapUser)))) {
datasetMap = new TMap;
datasetMap->SetOwner();
userMap->Add(new TObjString(mapUser), datasetMap);
}
}
if (exporting) {
TString dsNameFormatted(Form("/%s/%s/%s", mapGroup,
mapUser, datasetName.Data()));
if (outmap)
outmap->Add(new TObjString(dsNameFormatted), fileList);
} else if (updating) {
GetQuota(mapGroup, mapUser, datasetName.Data(), fileList);
} else if (printing) {
if (outlist) {
TString dsNameFormatted(Form("/%s/%s/%s", mapGroup,
mapUser, datasetName.Data()));
if (dsNameFormatted.Length() < 42)
dsNameFormatted.Resize(42);
outlist->Add(fileList->ExportInfo(dsNameFormatted));
}
} else {
if (fillmap && datasetMap)
datasetMap->Add(new TObjString(datasetName), fileList);
}
}
}
gSystem->FreeDirectory(userDir);
return kTRUE;
}
TMap *TProofDataSetManagerFile::GetDataSets(const char *group, const char *user,
UInt_t option)
{
if (group && fgCommonDataSetTag == group)
group = fCommonGroup;
if (user && fgCommonDataSetTag == user)
user = fCommonUser;
if (group && (strcmp(group, "*") == 0 || strlen(group) == 0))
group = 0;
if (user && (strcmp(user, "*") == 0 || strlen(user) == 0))
user = 0;
Bool_t printing = (option & kPrint) ? kTRUE : kFALSE;
Bool_t exporting = (option & kExport) ? kTRUE : kFALSE;
Bool_t updating = (option & kQuotaUpdate) ? kTRUE : kFALSE;
if (((Int_t)printing + (Int_t)exporting + (Int_t)updating) > 1) {
Error("GetDataSets", "only one of '?P', '?Q' or '?E' can be specified at once");
return 0;
}
TObject *result = 0;
if (printing) {
TList *ol = new TList();
ol->SetOwner();
result = ol;
} else if (exporting || !updating) {
TMap *om = new TMap;
om->SetOwner();
result = om;
}
if (gDebug > 0)
Info("GetDataSets", "opening dir %s", fDataSetDir.Data());
if (option & kShowDefault) {
BrowseDataSets(fCommonGroup, fCommonUser, option, result);
user = 0;
}
if (user && group) {
BrowseDataSets(group, user, option, result);
return (TMap *)result;
}
void *dataSetDir = 0;
if ((dataSetDir = gSystem->OpenDirectory(fDataSetDir))) {
const char *currentGroup = 0;
while ((currentGroup = gSystem->GetDirEntry(dataSetDir))) {
if (strcmp(currentGroup, ".") == 0 || strcmp(currentGroup, "..") == 0)
continue;
if (group && strcmp(group, currentGroup))
continue;
TString groupDirPath;
groupDirPath.Form("%s/%s", fDataSetDir.Data(), currentGroup);
void *groupDir = gSystem->OpenDirectory(groupDirPath);
if (!groupDir)
continue;
const char *currentUser = 0;
while ((currentUser = gSystem->GetDirEntry(groupDir))) {
if (strcmp(currentUser, ".") == 0 || strcmp(currentUser, "..") == 0)
continue;
if (user && strcmp(user, currentUser))
continue;
BrowseDataSets(currentGroup, currentUser, option, result);
}
gSystem->FreeDirectory(groupDir);
}
gSystem->FreeDirectory(dataSetDir);
}
if (printing) {
TList *output = (TList *)result;
output->Sort();
Printf("Dataset URI | # Files | Default tree | # Events | Disk | Staged");
TIter iter4(output);
TObjString* formattedLine = 0;
while ((formattedLine = dynamic_cast<TObjString*> (iter4())))
Printf("%s", formattedLine->String().Data());
SafeDelete(output);
result = 0;
}
return (TMap *)result;
}
TFileCollection *TProofDataSetManagerFile::GetDataSet(const char *group,
const char *user,
const char *dsName,
UInt_t option,
TMD5 **checksum)
{
TLockFile lock(fDataSetLockFile, fLockFileTimeLimit);
TString path(GetDataSetPath(group, user, dsName));
if (gSystem->AccessPathName(path) != kFALSE) {
Info("GetDataSet", "dataset %s does not exist", path.Data());
return 0;
}
TMD5 *retrievedChecksum = 0;
if (checksum) {
retrievedChecksum = TMD5::FileChecksum(path);
if (!retrievedChecksum) {
Error("GetDataSet", "could not get checksum of %s", path.Data());
return 0;
}
}
TFile *f = TFile::Open(path.Data());
if (!f) {
Error("GetDataSet", "Could not open file %s", path.Data());
if (retrievedChecksum)
delete retrievedChecksum;
return 0;
}
TFileCollection *fileList = 0;
if (option & kReadShort)
fileList = dynamic_cast<TFileCollection*> (f->Get("dataset_short"));
if (!fileList)
fileList = dynamic_cast<TFileCollection*> (f->Get("dataset"));
f->Close();
delete f;
if (checksum)
*checksum = retrievedChecksum;
return fileList;
}
Int_t TProofDataSetManagerFile::WriteDataSet(const char *group, const char *user,
const char *dsName, TFileCollection *dataset,
UInt_t option, TMD5 *checksum)
{
TLockFile lock(fDataSetLockFile, fLockFileTimeLimit);
Bool_t checkIfExists = ((option & kFileMustExist) || checksum) ? kTRUE : kFALSE;
TString path(GetDataSetPath(group, user, dsName));
if (checkIfExists) {
Long_t tmp;
if (gSystem->GetPathInfo(path, 0, (Long_t*) 0, 0, &tmp) != 0) {
if (gDebug > 0)
Info("WriteDataSet", "Dataset disappeared. Discarding update.");
return 3;
}
}
if (checksum) {
TMD5 *checksum2 = TMD5::FileChecksum(path);
if (!checksum2) {
Error("WriteDataSet", "Could not get checksum of %s", path.Data());
return 0;
}
Bool_t checksumAgrees = (*checksum == *checksum2);
delete checksum2;
if (!checksumAgrees) {
if (gDebug > 0)
Info("WriteDataSet", "Dataset changed. Discarding update.");
return 2;
}
}
TString tempFile(path);
Int_t index = -1;
while (tempFile.Index("/", index+1) >= 0)
index = tempFile.Index("/", index+1);
tempFile.Insert(index+1, ".");
TFile *f = TFile::Open(tempFile, "RECREATE");
if (!f) {
Error("WriteDataSet", "Could not open dataset for writing %s", tempFile.Data());
return 0;
}
dataset->Write("dataset", TObject::kSingleKey);
THashList *list = dataset->GetList();
dataset->SetList(0);
dataset->Write("dataset_short", TObject::kSingleKey);
f->Close();
delete f;
dataset->SetList(list);
if (gSystem->Rename(tempFile, path) != 0) {
Error("WriteDataSet", "Renaming %s to %s failed. Dataset might be corrupted.",
tempFile.Data(), path.Data());
return 0;
}
return 1;
}
Bool_t TProofDataSetManagerFile::RemoveDataSet(const char *group, const char *user,
const char *dsName)
{
TLockFile lock(fDataSetLockFile, fLockFileTimeLimit);
TString path(GetDataSetPath(group, user, dsName));
return (gSystem->Unlink(path) == 0);
}
Bool_t TProofDataSetManagerFile::ExistsDataSet(const char *group, const char *user,
const char *dsName)
{
TLockFile lock(fDataSetLockFile, fLockFileTimeLimit);
TString path(GetDataSetPath(group, user, dsName));
return (gSystem->AccessPathName(path) == kFALSE);
}
Int_t TProofDataSetManagerFile::RegisterDataSet(const char *uri,
TFileCollection *dataSet,
const char *opts)
{
if (!TestBit(TProofDataSetManager::kAllowRegister))
return -1;
TString dsName;
if (ParseUri(uri, 0, 0, &dsName, 0, kTRUE) == kFALSE) {
Error("RegisterDataSet", "problem parsing uri: %s", uri);
return -1;
}
TString opt(opts);
if (!opt.Contains("O", TString::kIgnoreCase)) {
if (ExistsDataSet(fGroup, fUser, dsName)) {
return -1;
}
}
dataSet->Sort();
TList *uniqueFileList = new TList();
TIter nextFile(dataSet->GetList());
TFileInfo *prevFile = (TFileInfo*)nextFile();
uniqueFileList->Add(prevFile);
while (TFileInfo *obj = (TFileInfo*)nextFile()) {
if (prevFile->Compare(obj)) {
uniqueFileList->Add(obj);
prevFile = obj;
}
}
dataSet->GetList()->SetOwner(0);
dataSet->GetList()->Clear("nodelete");
dataSet->GetList()->SetOwner(1);
dataSet->GetList()->AddAll(uniqueFileList);
uniqueFileList->SetOwner(kFALSE);
delete uniqueFileList;
dataSet->SetName(dsName);
dataSet->ResetBitAll(TFileInfo::kStaged);
dataSet->ResetBitAll(TFileInfo::kCorrupted);
dataSet->RemoveMetaData();
if (opt.Contains("V", TString::kIgnoreCase)) {
if (ScanDataSet(dataSet, (UInt_t)(kReopen | kDebug)) < 0) {
Error("RegisterDataSet", "problems verifying the dataset");
return -1;
}
}
dataSet->Update(fAvgFileSize);
if (TestBit(TProofDataSetManager::kCheckQuota)) {
if (dataSet->GetTotalSize() <= 0) {
Error("RegisterDataSet", "datasets without size information are not accepted:");
if (fAvgFileSize < 0) {
Error("RegisterDataSet", "you may want to define an average"
" file size to get an estimated dataset size");
}
return -1;
}
UpdateUsedSpace();
Long64_t used = GetGroupUsed(fGroup) + dataSet->GetTotalSize();
Info("RegisterDataSet", "your group %s uses %.1f GB + %.1f GB for the new dataset; "
"the available quota is %.1f GB", fGroup.Data(),
(Float_t) GetGroupUsed(fGroup) / 1073741824,
(Float_t) dataSet->GetTotalSize() / 1073741824,
(Float_t) GetGroupQuota(fGroup) / 1073741824);
if (used > GetGroupQuota(fGroup)) {
Error("RegisterDataSet", "quota exceeded");
return -1;
}
}
Bool_t success = WriteDataSet(fGroup, fUser, dsName, dataSet);
if (!success)
Error("RegisterDataSet", "could not write dataset: %s", dsName.Data());
return ((success) ? 0 : -1);
}
Int_t TProofDataSetManagerFile::ScanDataSet(const char *uri, UInt_t)
{
TString dsName;
if (TestBit(TProofDataSetManager::kAllowVerify)) {
if (ParseUri(uri, 0, 0, &dsName, 0, kTRUE)) {
if (ScanDataSet(fGroup, fUser, dsName, (UInt_t)(kReopen | kDebug)) > 0)
return GetNDisapparedFiles();
}
}
return -1;
}
Int_t TProofDataSetManagerFile::ScanDataSet(const char *group, const char *user,
const char *dsName, UInt_t option)
{
if (!TestBit(TProofDataSetManager::kAllowVerify))
return -1;
TFileCollection *dataset = GetDataSet(group, user, dsName);
if (!dataset)
return -1;
Int_t result = ScanDataSet(dataset, option);
if (result == 2)
if (WriteDataSet(group, user, dsName, dataset) == 0)
return -2;
delete dataset;
return result;
}
Int_t TProofDataSetManagerFile::ScanDataSet(TFileCollection *dataset,
UInt_t option, Int_t filesmax)
{
if (!TestBit(TProofDataSetManager::kAllowVerify))
return -1;
Bool_t notify = (gDebug > 0 || (option & kDebug)) ? kTRUE : kFALSE;
Int_t maxFiles = ((option & kMaxFiles) && (filesmax > -1)) ? filesmax : -1;
if (maxFiles > -1 && notify)
Info("ScanDataSet", "processing a maximum of %d files", maxFiles);
Bool_t reopen = ((option & kReopen) || (option & kTouch)) ? kTRUE : kFALSE;
Bool_t touch = ((option & kTouch)) ? kTRUE : kFALSE;
fNTouchedFiles = 0;
fNOpenedFiles = 0;
fNDisappearedFiles = 0;
Bool_t changed = kFALSE;
TFileStager *stager = (!fMSSUrl.IsNull()) ? TFileStager::Open(fMSSUrl) : 0;
Bool_t createStager = (stager) ? kFALSE : kTRUE;
TList newStagedFiles;
TIter iter2(dataset->GetList());
TFileInfo *fileInfo = 0;
while ((fileInfo = dynamic_cast<TFileInfo*> (iter2.Next()))) {
fileInfo->ResetUrl();
if (!fileInfo->GetCurrentUrl()) {
Error("ScanDataSet", "GetCurrentUrl() is 0 for %s",
fileInfo->GetFirstUrl()->GetUrl());
continue;
}
if (fileInfo->TestBit(TFileInfo::kStaged)) {
if (fileInfo->TestBit(TFileInfo::kCorrupted)) continue;
if (!reopen) continue;
TUrl url(*(fileInfo->GetCurrentUrl()));
url.SetAnchor("");
if (notify && (fNTouchedFiles+fNDisappearedFiles) % 100 == 0)
Info("ScanDataSet",
"opening %d. file: %s", fNTouchedFiles+fNDisappearedFiles,
fileInfo->GetCurrentUrl()->GetUrl());
TFile *file = TFile::Open(Form("%s?filetype=raw&mxredir=2", url.GetUrl()));
if (file) {
if (touch) {
char tmpChar = 0;
file->ReadBuffer(&tmpChar, 1);
}
file->Close();
delete file;
fNTouchedFiles++;
} else {
if (notify)
Info("ScanDataSet", "file %s disappeared", url.GetUrl());
fileInfo->ResetBit(TFileInfo::kStaged);
fNDisappearedFiles++;
changed = kTRUE;
if (fileInfo->GetNUrls() > 1)
fileInfo->RemoveUrl(fileInfo->GetCurrentUrl()->GetUrl());
}
continue;
}
if (!TestBit(TProofDataSetManager::kAllowStaging)) continue;
if (maxFiles > 0 && newStagedFiles.GetEntries() >= maxFiles)
continue;
TUrl url(*(fileInfo->GetCurrentUrl()));
url.SetAnchor("");
stager = createStager ? TFileStager::Open(url.GetUrl()) : stager;
Bool_t result = kFALSE;
if (stager) {
result = stager->IsStaged(url.GetUrl());
if (notify && gDebug > 0)
Info("ScanDataSet", "IsStaged: %s: %d", url.GetUrl(), result);
if (createStager)
SafeDelete(stager);
} else {
Warning("ScanDataSet",
"could not get stager instance for '%s'", url.GetUrl());
}
if (!result) continue;
newStagedFiles.Add(fileInfo);
}
SafeDelete(stager);
if (notify && newStagedFiles.GetEntries() > 0)
Info("ScanDataSet",
"opening %d files that appear to be newly staged.",
newStagedFiles.GetEntries());
Bool_t oldStatus = TFile::GetOnlyStaged();
TFile::SetOnlyStaged(kTRUE);
Int_t count = 0;
TIter iter3(&newStagedFiles);
while ((fileInfo = dynamic_cast<TFileInfo*> (iter3.Next()))) {
if (notify && count++ % 100 == 0)
Info("ScanDataSet", "processing %d.'new' file: %s",
count, fileInfo->GetCurrentUrl()->GetUrl());
TUrl *url = fileInfo->GetCurrentUrl();
TFile *file = 0;
TUrl urlNoAnchor(*url);
urlNoAnchor.SetAnchor("");
urlNoAnchor.SetOptions("filetype=raw");
if (!(file = TFile::Open(urlNoAnchor.GetUrl())))
continue;
changed = kTRUE;
fileInfo->SetBit(TFileInfo::kStaged);
TUrl urlDiskServer(*url);
urlDiskServer.SetHost(file->GetEndpointUrl()->GetHost());
fileInfo->AddUrl(urlDiskServer.GetUrl(), kTRUE);
if (notify)
Info("ScanDataSet", "added URL %s", urlDiskServer.GetUrl());
if (file->GetSize() > 0)
fileInfo->SetSize(file->GetSize());
file->Close();
delete file;
if (!(file = TFile::Open(url->GetUrl()))) {
if (notify)
Info("ScanDataSet", "marking %s as corrupt", url->GetUrl());
fileInfo->SetBit(TFileInfo::kCorrupted);
continue;
}
Int_t oldLevel = gErrorIgnoreLevel;
gErrorIgnoreLevel = kError+1;
if (file->GetListOfKeys()) {
TIter keyIter(file->GetListOfKeys());
TKey *key = 0;
while ((key = dynamic_cast<TKey*> (keyIter.Next()))) {
if (strcmp(key->GetClassName(), "TTree"))
continue;
TString keyStr;
keyStr.Form("/%s", key->GetName());
TFileInfoMeta *metaData = fileInfo->GetMetaData(keyStr);
if (!metaData) {
metaData = new TFileInfoMeta(keyStr, key->GetClassName());
fileInfo->AddMetaData(metaData);
if (notify)
Info("ScanDataSet", "created meta data for tree %s", keyStr.Data());
}
TTree *tree = dynamic_cast<TTree*> (file->Get(key->GetName()));
if (tree) {
if (tree->GetEntries() > 0)
metaData->SetEntries(tree->GetEntries());
if (tree->GetTotBytes() > 0)
metaData->SetTotBytes(tree->GetTotBytes());
if (tree->GetZipBytes() > 0)
metaData->SetZipBytes(tree->GetZipBytes());
}
}
}
gErrorIgnoreLevel = oldLevel;
file->Close();
delete file;
fNOpenedFiles++;
}
TFile::SetOnlyStaged(oldStatus);
dataset->Update(fAvgFileSize);
Int_t result = (changed) ? 2 : 1;
if (result > 0 && notify)
Info("ScanDataSet", "%d files 'new'; %d files touched; %d files disappeared",
GetNOpenedFiles(), GetNTouchedFiles(), GetNDisapparedFiles());
return result;
}
TMap *TProofDataSetManagerFile::GetDataSets(const char *uri, UInt_t option)
{
TString dsUser, dsGroup;
if (((option & kPrint) || (option & kExport)) && strlen(uri) <= 0)
option |= kShowDefault;
if (ParseUri(uri, &dsGroup, &dsUser, 0, 0, kFALSE, kTRUE))
return GetDataSets(dsGroup, dsUser, option);
return (TMap *)0;
}
TFileCollection *TProofDataSetManagerFile::GetDataSet(const char *uri)
{
TString dsUser, dsGroup, dsName;
if (ParseUri(uri, &dsGroup, &dsUser, &dsName))
return GetDataSet(dsGroup, dsUser, dsName);
return (TFileCollection *)0;
}
Bool_t TProofDataSetManagerFile::RemoveDataSet(const char *uri)
{
TString dsName;
if (TestBit(TProofDataSetManager::kAllowRegister)) {
if (ParseUri(uri, 0, 0, &dsName, 0, kTRUE)) {
Bool_t rc = RemoveDataSet(fGroup, fUser, dsName);
if (rc) return kTRUE;
Error("RemoveDataSet", "error removing dataset %s", dsName.Data());
}
}
return kFALSE;
}
Bool_t TProofDataSetManagerFile::ExistsDataSet(const char *uri)
{
TString dsUser, dsGroup, dsName;
if (ParseUri(uri, &dsGroup, &dsUser, &dsName))
return ExistsDataSet(dsGroup, dsUser, dsName);
return kFALSE;
}
void TProofDataSetManagerFile::UpdateUsedSpace()
{
fGroupUsed.DeleteAll();
fUserUsed.DeleteAll();
GetDataSets(0, 0, (UInt_t)kQuotaUpdate);
}
Last change: Wed Oct 22 12:04:02 2008
Last generated: 2008-10-22 12:04
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.