ROOT logo
// @(#)root/base:$Id: TDataSetManager.cxx 30421 2009-09-24 17:20:09Z ganis $
// Author: Jan Fiete Grosse-Oetringhaus, 04.06.07

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TDataSetManager                                                 //
//                                                                      //
// This class contains functions to handle datasets in PROOF            //
// It is the layer between TProofServ and the file system that stores   //
// the datasets.                                                        //
//                                                                      //
//////////////////////////////////////////////////////////////////////////


#include "TDataSetManager.h"

#include "Riostream.h"

#include "TEnv.h"
#include "TFileCollection.h"
#include "TFileInfo.h"
#include "TMD5.h"
#include "THashList.h"
#include "TObjArray.h"
#include "TObjString.h"
#include "TParameter.h"
#include "TPRegexp.h"
#include "TRegexp.h"
#include "TSystem.h"
#include "TVirtualMonitoring.h"

// One Gigabyte
#define DSM_ONE_GB (1073741824)

// Name for common datasets
TString TDataSetManager::fgCommonDataSetTag = "COMMON";

ClassImp(TDataSetManager)

//_____________________________________________________________________________
TDataSetManager::TDataSetManager(const char *group, const char *user,
                                           const char *options)
                     : fGroup(group),
                       fUser(user), fCommonUser(), fCommonGroup(),
                       fGroupQuota(), fGroupUsed(),
                       fUserUsed(), fNTouchedFiles(0), fNOpenedFiles(0),
                       fNDisappearedFiles(0), fMTimeGroupConfig(-1)
{
   //
   // Main constructor

   // Fill default group and user if none is given
   if (fGroup.IsNull())
      fGroup = "default";
   if (fUser.IsNull()) {
      fUser = "--nouser--";
      // Get user logon name
      UserGroup_t *pw = gSystem->GetUserInfo();
      if (pw) {
         fUser = pw->fUser;
         delete pw;
      }
   }

   fGroupQuota.SetOwner();
   fGroupUsed.SetOwner();
   fUserUsed.SetOwner();

   fCommonUser = "COMMON";
   fCommonGroup = "COMMON";

   fNTouchedFiles = -1;
   fNOpenedFiles = -1;
   fNDisappearedFiles = -1;
   fMTimeGroupConfig = -1;

   fAvgFileSize = 50000000;  // Default 50 MB per file

   // Parse options
   ParseInitOpts(options);

   if (!fUser.IsNull() && !fGroup.IsNull()) {

      // If not in sandbox, construct the base URI using session defaults
      // (group, user) (syntax: /group/user/dsname[#[subdir/]objname])
      if (!TestBit(TDataSetManager::kIsSandbox))
         fBase.SetUri(TString(Form("/%s/%s/", fGroup.Data(), fUser.Data())));

   }

   // Read config file
   ReadGroupConfig(gEnv->GetValue("Proof.GroupFile", ""));
}

//______________________________________________________________________________
TDataSetManager::~TDataSetManager()
{
   // Destructor

   // Clear used space
   fGroupQuota.DeleteAll();
   fGroupUsed.DeleteAll();
   fUserUsed.DeleteAll();
}

//______________________________________________________________________________
void TDataSetManager::ParseInitOpts(const char *opts)
{
   // Parse the opts string and set the init bits accordingly
   // Available options:
   //    Cq:               set kCheckQuota
   //    Ar:               set kAllowRegister
   //    Av:               set kAllowVerify
   //    Ti:               set kTrustInfo
   //    Sb:               set kIsSandbox
   // The opts string may also contain additional unrelated info: in such a case
   // the field delimited by the prefix "opt:" is analyzed, e.g. if opts is
   // "/tmp/dataset  opt:Cq:-Ar: root://lxb6046.cern.ch" only the substring
   // "Cq:-Ar:" will be parsed .

   // Default option bits
   ResetBit(TDataSetManager::kCheckQuota);
   SetBit(TDataSetManager::kAllowRegister);
   SetBit(TDataSetManager::kAllowVerify);
   SetBit(TDataSetManager::kTrustInfo);
   ResetBit(TDataSetManager::kIsSandbox);

   if (opts && strlen(opts) > 0) {
      TString opt(opts);
      // If it contains the prefix "opt:", isolate the related field
      Int_t ip = opt.Index("opt:");
      if (ip != kNPOS) opt.Remove(0, ip + 4);
      ip = opt.Index(" ");
      if (ip != kNPOS) opt.Remove(ip);
      // Check the content, now
      if (opt.Contains("Cq:") && !opt.Contains("-Cq:"))
         SetBit(TDataSetManager::kCheckQuota);
      if (opt.Contains("-Ar:"))
         ResetBit(TDataSetManager::kAllowRegister);
      if (opt.Contains("-Av:"))
         ResetBit(TDataSetManager::kAllowVerify);
      if (opt.Contains("-Ti:"))
         ResetBit(TDataSetManager::kTrustInfo);
      if (opt.Contains("Sb:") && !opt.Contains("-Sb:"))
         SetBit(TDataSetManager::kIsSandbox);
   }

   // Check dependencies
   if (TestBit(TDataSetManager::kAllowVerify)) {
      // Dataset verification or requires registration permition
      SetBit(TDataSetManager::kAllowRegister);
   }
}

//______________________________________________________________________________
Bool_t TDataSetManager::ReadGroupConfig(const char *cf)
{
   // Read group config file 'cf'.
   // If cf == 0 re-read, if changed, the file pointed by fGroupConfigFile .
   //
   // expects the following directives:
   // Group definition:
   //   group <groupname> <user>+
   // disk quota
   //   property <groupname> diskquota <quota in GB>
   // average filesize (to be used when the file size is not available)
   //   averagefilesize <average size>{G,g,M,m,K,k}

   // Validate input
   FileStat_t st;
   if (!cf || (strlen(cf) <= 0) || !strcmp(cf, fGroupConfigFile.Data())) {
      // If this is the first time we cannot do anything
      if (fGroupConfigFile.IsNull()) {
         if (gDebug > 0)
            Info("ReadGroupConfig", "path to config file undefined - nothing to do");
         return kFALSE;
      }
      // Check if fGroupConfigFile has changed
      if (gSystem->GetPathInfo(fGroupConfigFile, st)) {
         Error("ReadGroupConfig", "could not stat %s", fGroupConfigFile.Data());
         return kFALSE;
      }
      if (st.fMtime <= fMTimeGroupConfig) {
         if (gDebug > 0)
            Info("ReadGroupConfig","file has not changed - do nothing");
         return kTRUE;
      }
   }

   // Either new file or the file has changed
   if (cf && (strlen(cf) > 0)) {
      // The file must exist and be readable
      if (gSystem->GetPathInfo(cf, st)) {
         Error("ReadGroupConfig", "could not stat %s", cf);
         return kFALSE;
      }
      if (gSystem->AccessPathName(cf, kReadPermission)) {
         Error("ReadGroupConfig", "cannot read %s", cf);
         return kFALSE;
      }
      // Ok
      fGroupConfigFile = cf;
      fMTimeGroupConfig = st.fMtime;
   }

   if (gDebug > 0)
      Info("ReadGroupConfig","reading group config from %s", cf);

   // Open the config file
   ifstream in;
   in.open(cf);
   if (!in.is_open()) {
      Error("ReadGroupConfig", "could not open config file %s", cf);
      return kFALSE;
   }

   // Container for the global common user
   TString tmpCommonUser;

   // Go through
   TString line;
   while (in.good()) {
      // Read new line
      line.ReadLine(in);
      // Parse it
      Ssiz_t from = 0;
      TString key;
      if (!line.Tokenize(key, from, " ")) // No token
         continue;
      // Parsing depends on the key
      if (key == "property") {
         // Read group
         TString grp;
         if (!line.Tokenize(grp, from, " ")) {// No token
            if (gDebug > 0)
               Info("ReadGroupConfig","incomplete line: '%s'", line.Data());
            continue;
         }
         // Read type of property
         TString type;
         if (!line.Tokenize(type, from, " ")) // No token
            continue;
         if (type == "diskquota") {
            // Read diskquota
            TString sdq;
            if (!line.Tokenize(sdq, from, " ")) // No token
               continue;
            // Enforce GigaBytes as default
            if (sdq.IsDigit()) sdq += "G";
            Long64_t quota = ToBytes(sdq);
            if (quota > -1) {
               fGroupQuota.Add(new TObjString(grp),
                               new TParameter<Long64_t> ("group quota", quota));
            } else {
               Warning("ReadGroupConfig",
                       "problems parsing string: wrong or unsupported suffix? %s",
                        sdq.Data());
            }
         } else if (type == "commonuser") {
            // Read common user for this group
            TString comusr;
            if (!line.Tokenize(comusr, from, " ")) // No token
               continue;

         }

      } else if (key == "dataset") {
         // Read type
         TString type;
         if (!line.Tokenize(type, from, " ")) {// No token
            if (gDebug > 0)
               Info("ReadGroupConfig","incomplete line: '%s'", line.Data());
            continue;
         }
         if (type == "commonuser") {
            // Read global common user
            TString comusr;
            if (!line.Tokenize(comusr, from, " ")) // No token
               continue;
            fCommonUser = comusr;
         } else if (type == "commongroup") {
            // Read global common group
            TString comgrp;
            if (!line.Tokenize(comgrp, from, " ")) // No token
               continue;
            fCommonGroup = comgrp;
         } else if (type == "diskquota") {
            // Quota check switch
            TString on;
            if (!line.Tokenize(on, from, " ")) // No token
               continue;
            if (on == "on") {
               SetBit(TDataSetManager::kCheckQuota);
            } else if (on == "off") {
               ResetBit(TDataSetManager::kCheckQuota);
            }
         }

      } else if (key == "averagefilesize") {

         // Read average size
         TString avgsize;
         if (!line.Tokenize(avgsize, from, " ")) {// No token
            if (gDebug > 0)
               Info("ReadGroupConfig","incomplete line: '%s'", line.Data());
            continue;
         }
         Long64_t avgsz = ToBytes(avgsize);
         if (avgsz > -1) {
            fAvgFileSize = avgsz;
         } else {
            Warning("ReadGroupConfig",
                    "problems parsing string: wrong or unsupported suffix? %s",
                    avgsize.Data());
         }
      }
   }
   in.close();

   return kTRUE;
}

//______________________________________________________________________________
Long64_t TDataSetManager::ToBytes(const char *size)
{
   // Static utility function to gt the number of bytes from a string
   // representation in the form "<digit><sfx>" with <sfx> = {"", "k", "M", "G",
   // "T", "P"} (case insensitive).
   // Returns -1 if the format is wrong.

   Long64_t lsize = -1;

   // Check if valid
   if (!size || strlen(size) <= 0) return lsize;

   TString s(size);
   // Determine factor
   Long64_t fact = 1;
   if (!s.IsDigit()) {
      const char *unit[5] = { "k", "M", "G", "T", "P"};
      fact = 1024;
      Int_t jj = 0;
      while (jj <= 4) {
         if (s.EndsWith(unit[jj], TString::kIgnoreCase)) {
            s.Remove(s.Length()-1);
            break;
         }
         fact *= 1024;
         jj++;
      }
   }
   // Apply factor now
   if (s.IsDigit())
      lsize = s.Atoi() * fact;

   // Done
   return lsize;
}

//______________________________________________________________________________
TFileCollection *TDataSetManager::GetDataSet(const char *, const char *)
{
   // Utility function used in various methods for user dataset upload.

   AbstractMethod("GetDataSet");
   return (TFileCollection *)0;
}

//______________________________________________________________________________
Bool_t TDataSetManager::RemoveDataSet(const char *)
{
   // Removes the indicated dataset

   AbstractMethod("RemoveDataSet");
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TDataSetManager::ExistsDataSet(const char *)
{
   // Checks if the indicated dataset exits

   AbstractMethod("ExistsDataSet");
   return kFALSE;
}

//______________________________________________________________________________
TMap *TDataSetManager::GetDataSets(const char *, UInt_t)
{
   //
   // Returns all datasets for the <group> and <user> specified by <uri>.
   // If <user> is 0, it returns all datasets for the given <group>.
   // If <group> is 0, it returns all datasets.
   // The returned TMap contains:
   //    <group> --> <map of users> --> <map of datasets> --> <dataset> (TFileCollection)
   //
   // The unsigned int 'option' is forwarded to GetDataSet and BrowseDataSet.
   // Available options (to be .or.ed):
   //    kShowDefault    a default selection is shown that include the ones from
   //                    the current user, the ones from the group and the common ones
   //    kPrint          print the dataset content
   //    kQuotaUpdate    update quotas
   //    kExport         use export naming
   //
   // NB1: options "kPrint", "kQuoatUpdate" and "kExport" are mutually exclusive
   // NB2: for options "kPrint" and "kQuoatUpdate" return is null.

   AbstractMethod("GetDataSets");

   return (TMap *)0;
}

//______________________________________________________________________________
Int_t TDataSetManager::ScanDataSet(const char *, UInt_t)
{
   // Scans the dataset indicated by <uri> and returns the number of missing files.
   // Returns -1 if any failure occurs.
   // For more details, see documentation of
   // ScanDataSet(TFileCollection *dataset, const char *option)

   AbstractMethod("ScanDataSet");

   return -1;
}

//______________________________________________________________________________
void TDataSetManager::GetQuota(const char *group, const char *user,
                                    const char *dsName, TFileCollection *dataset)
{
   //
   // Gets quota information from this dataset

   if (gDebug > 0)
      Info("GetQuota", "processing dataset %s %s %s", group, user, dsName);

   if (dataset->GetTotalSize() > 0) {
      TParameter<Long64_t> *size =
         dynamic_cast<TParameter<Long64_t>*> (fGroupUsed.GetValue(group));
      if (!size) {
         size = new TParameter<Long64_t> ("group used", 0);
         fGroupUsed.Add(new TObjString(group), size);
      }

      size->SetVal(size->GetVal() + dataset->GetTotalSize());

      TMap *userMap = dynamic_cast<TMap*> (fUserUsed.GetValue(group));
      if (!userMap) {
         userMap = new TMap;
         fUserUsed.Add(new TObjString(group), userMap);
      }

      size = dynamic_cast<TParameter<Long64_t>*> (userMap->GetValue(user));
      if (!size) {
         size = new TParameter<Long64_t> ("user used", 0);
         userMap->Add(new TObjString(user), size);
      }

      size->SetVal(size->GetVal() + dataset->GetTotalSize());
   }
}

//______________________________________________________________________________
void TDataSetManager::ShowQuota(const char *opt)
{
   // Display quota information

   UpdateUsedSpace();

   TMap *groupQuotaMap = GetGroupQuotaMap();
   TMap *userUsedMap = GetUserUsedMap();
   if (!groupQuotaMap || !userUsedMap)
      return;

   Bool_t noInfo = kTRUE;
   TIter iter(groupQuotaMap);
   TObjString *group = 0;
   while ((group = dynamic_cast<TObjString*> (iter.Next()))) {
      noInfo = kFALSE;
      Long64_t groupQuota = GetGroupQuota(group->String());
      Long64_t groupUsed = GetGroupUsed(group->String());

      Printf(" +++ Group %s uses %.1f GB out of %.1f GB", group->String().Data(),
                                        (Float_t) groupUsed / DSM_ONE_GB,
                                       (Float_t) groupQuota / DSM_ONE_GB);

      // display also user information
      if (opt && !TString(opt).Contains("U", TString::kIgnoreCase))
         continue;

      TMap *userMap = dynamic_cast<TMap*> (userUsedMap->GetValue(group->String()));
      if (!userMap)
         continue;

      TIter iter2(userMap);
      TObjString *user = 0;
      while ((user = dynamic_cast<TObjString*> (iter2.Next()))) {
         TParameter<Long64_t> *size2 =
            dynamic_cast<TParameter<Long64_t>*> (userMap->GetValue(user->String().Data()));
         if (!size2)
            continue;

         Printf(" +++  User %s uses %.1f GB", user->String().Data(),
                                  (Float_t) size2->GetVal() / DSM_ONE_GB);
      }

      Printf("------------------------------------------------------");
   }
   // Check if something has been printed
   if (noInfo) {
      Printf(" +++ Quota check enabled but no quota info available +++ ");
   }
}

//______________________________________________________________________________
void TDataSetManager::PrintUsedSpace()
{
   //
   // Prints the quota

   Info("PrintUsedSpace", "listing used space");

   TIter iter(&fUserUsed);
   TObjString *group = 0;
   while ((group = dynamic_cast<TObjString*> (iter.Next()))) {
      TMap *userMap = dynamic_cast<TMap*> (fUserUsed.GetValue(group->String()));

      TParameter<Long64_t> *size =
         dynamic_cast<TParameter<Long64_t>*> (fGroupUsed.GetValue(group->String()));

      if (userMap && size) {
         Printf("Group %s: %lld B = %.2f GB", group->String().Data(), size->GetVal(),
                                      (Float_t) size->GetVal() / DSM_ONE_GB);

         TIter iter2(userMap);
         TObjString *user = 0;
         while ((user = dynamic_cast<TObjString*> (iter2.Next()))) {
            TParameter<Long64_t> *size2 =
               dynamic_cast<TParameter<Long64_t>*> (userMap->GetValue(user->String().Data()));
            if (size2)
               Printf("  User %s: %lld B = %.2f GB", user->String().Data(), size2->GetVal(),
                                            (Float_t) size2->GetVal() / DSM_ONE_GB);
         }

         Printf("------------------------------------------------------");
      }
   }
}

//______________________________________________________________________________
void TDataSetManager::MonitorUsedSpace(TVirtualMonitoringWriter *monitoring)
{
   //
   // Log info to the monitoring server

   Info("MonitorUsedSpace", "sending used space to monitoring server");

   TIter iter(&fUserUsed);
   TObjString *group = 0;
   while ((group = dynamic_cast<TObjString*> (iter.Next()))) {
      TMap *userMap = dynamic_cast<TMap*> (fUserUsed.GetValue(group->String()));
      TParameter<Long64_t> *size =
         dynamic_cast<TParameter<Long64_t>*> (fGroupUsed.GetValue(group->String()));

      if (!userMap || !size)
         continue;

      TList *list = new TList;
      list->SetOwner();
      list->Add(new TParameter<Long64_t>("_TOTAL_", size->GetVal()));
      Long64_t groupQuota = GetGroupQuota(group->String());
      if (groupQuota != -1)
         list->Add(new TParameter<Long64_t>("_QUOTA_", groupQuota));

      TIter iter2(userMap);
      TObjString *user = 0;
      while ((user = dynamic_cast<TObjString*> (iter2.Next()))) {
         TParameter<Long64_t> *size2 =
            dynamic_cast<TParameter<Long64_t>*> (userMap->GetValue(user->String().Data()));
         if (!size2)
            continue;
         list->Add(new TParameter<Long64_t>(user->String().Data(), size2->GetVal()));
      }

      monitoring->SendParameters(list, group->String());
      delete list;
   }
}

//______________________________________________________________________________
Long64_t TDataSetManager::GetGroupUsed(const char *group)
{
   //
   // Returns the used space of that group

   if (fgCommonDataSetTag == group)
      group = fCommonGroup;

   TParameter<Long64_t> *size =
      dynamic_cast<TParameter<Long64_t>*> (fGroupUsed.GetValue(group));
   if (!size) {
      if (gDebug > 0)
         Info("GetGroupUsed", "group %s not found", group);
      return 0;
   }

   return size->GetVal();
}

//______________________________________________________________________________
Long64_t TDataSetManager::GetGroupQuota(const char *group)
{
   //
   // returns the quota a group is allowed to have

   if (fgCommonDataSetTag == group)
      group = fCommonGroup;

   TParameter<Long64_t> *value =
      dynamic_cast<TParameter<Long64_t>*> (fGroupQuota.GetValue(group));
   if (!value) {
      if (gDebug > 0)
         Info("GetGroupQuota", "group %s not found", group);
      return 0;
   }
   return value->GetVal();
}

//______________________________________________________________________________
void TDataSetManager::UpdateUsedSpace()
{
   // updates the used space maps

   AbstractMethod("UpdateUsedSpace");
}

//______________________________________________________________________________
Int_t TDataSetManager::RegisterDataSet(const char *,
                                            TFileCollection *,
                                            const char *)
{
   // Register a dataset, perfoming quota checkings, if needed.
   // Returns 0 on success, -1 on failure

   AbstractMethod("RegisterDataSet");
   return -1;
}

//______________________________________________________________________________
TString TDataSetManager::CreateUri(const char *dsGroup, const char *dsUser,
                                        const char *dsName, const char *dsObjPath)
{
   // Creates URI for the dataset manger in the form '[[/dsGroup/]dsUser/]dsName[#dsObjPath]',
   // The optional dsObjPath can be in the form [subdir/]objname]'.

   TString uri;

   if (dsGroup && strlen(dsGroup) > 0) {
      if (dsUser && strlen(dsUser) > 0) {
         uri += Form("/%s/%s/", dsGroup, dsUser);
      } else {
         uri += Form("/%s/*/", dsGroup);
      }
   } else if (dsUser && strlen(dsUser) > 0) {
      uri += Form("%s/", dsUser);
   }
   if (dsName && strlen(dsName) > 0)
      uri += dsName;
   if (dsObjPath && strlen(dsObjPath) > 0)
      uri += Form("#%s", dsObjPath);

   // Done
   return uri;
}

//______________________________________________________________________________
Bool_t TDataSetManager::ParseUri(const char *uri,
                                      TString *dsGroup, TString *dsUser,
                                      TString *dsName, TString *dsTree,
                                      Bool_t onlyCurrent, Bool_t wildcards)
{
   // Parses a (relative) URI that describes a DataSet on the cluster.
   // The input 'uri' should be in the form '[[/group/]user/]dsname[#[subdir/]objname]',
   //  where 'objname' is the name of the object (e.g. the tree name) and the 'subdir'
   // is the directory in the file wher it should be looked for.
   // After resolving against a base URI consisting of proof://masterhost/group/user/
   // - meaning masterhost, group and user of the current session -
   // the path is checked to contain exactly three elements separated by '/':
   // group/user/dsname
   // If wildcards, '*' is allowed in group and user and dsname is allowed to be empty.
   // If onlyCurrent, only group and user of current session are allowed.
   // Only non-null parameters are filled by this function.
   // Returns kTRUE in case of success.

   // Append trailing slash if missing when wildcards are enabled
   TString uristr(uri);
   if (wildcards && uristr.Length() > 0 && !uristr.EndsWith("/"))
      uristr += '/';

   // Resolve given URI agains the base
   TUri resolved = TUri::Transform(uristr, fBase);
   if (resolved.HasQuery())
      Info ("ParseUri", "URI query part <%s> ignored", resolved.GetQuery().Data());

   TString path(resolved.GetPath());
   // Must be in the form /group/user/dsname
   Int_t pc = path.CountChar('/');
   if (pc != 3) {
      if (!TestBit(TDataSetManager::kIsSandbox)) {
         Error ("ParseUri", "illegal dataset path: %s", uri);
         return kFALSE;
      } else if (pc >= 0 && pc < 3) {
         // Add missing slashes
         TString sls("/");
         if (pc == 2) {
            sls = "/";
         } else if (pc == 1) {
            sls = Form("/%s/", fGroup.Data());
         } else if (pc == 0) {
            sls = Form("/%s/%s/", fGroup.Data(), fUser.Data());
         }
         path.Insert(0, sls);
      }
   }
   if (gDebug > 1)
      Info("ParseUri", "path: '%s'", path.Data());

   // Get individual values from tokens
   Int_t from = 1;
   TString group, user, name;
   path.Tokenize(group, from, "/");
   path.Tokenize(user, from, "/");
   path.Tokenize(name, from, "/");

   // The fragment may contain the subdir and the object name in the form '[subdir/]objname'
   TString tree = resolved.GetFragment();
   if (tree.EndsWith("/"))
      tree.Remove(tree.Length()-1);

   if (gDebug > 1)
      Info("ParseUri", "group: '%s', user: '%s', dsname:'%s', seg: '%s'",
                              group.Data(), user.Data(), name.Data(), tree.Data());

   // Check for unwanted use of wildcards
   if ((user == "*" || group == "*") && !wildcards) {
      Error ("ParseUri", "no wildcards allowed for user/group in this context");
      return kFALSE;
   }

   // dsname may only be empty if wildcards expected
   if (name.IsNull() && !wildcards) {
      Error ("ParseUri", "DataSet name is empty");
      return kFALSE;
   }

   // Construct regexp whitelist for checking illegal characters in user/group
   TPRegexp wcExp (wildcards ? "^(?:[A-Za-z0-9-]*|[*])$" : "^[A-Za-z0-9-]*$");

   // Check for illegal characters in all components
   if (!wcExp.Match(group)) {
      Error("ParseUri", "illegal characters in group");
      return kFALSE;
   }

   if (!wcExp.Match(user)) {
      Error("ParseUri", "illegal characters in user");
      return kFALSE;
   }

   if (name.Contains(TRegexp("[^A-Za-z0-9-._]"))) {
      Error("ParseUri", "illegal characters in dataset name");
      return kFALSE;
   }

   if (tree.Contains(TRegexp("[^A-Za-z0-9-/_]"))) {
      Error("ParseUri", "Illegal characters in subdir/object name");
      return kFALSE;
   }

   // Check user & group
   if (onlyCurrent && (group.CompareTo(fGroup) || user.CompareTo(fUser))) {
      Error("ParseUri", "only datasets from your group/user allowed");
      return kFALSE;
   }

   // fill parameters passed by reference, if defined
   if (dsGroup)
      *dsGroup = group;
   if (dsUser)
      *dsUser = user;
   if (dsName)
      *dsName = name;
   if (dsTree)
      *dsTree = tree;

   return kTRUE;
}

//______________________________________________________________________________
TMap *TDataSetManager::GetSubDataSets(const char *ds, const char *exclude)
{
   // Partition dataset 'ds' accordingly to the servers.
   // The returned TMap contains:
   //                <server> --> <subdataset> (TFileCollection)
   // where <subdataset> is the subset of 'ds' on <server>
   // The partitioning is done using all the URLs in the TFileInfo's, so the
   // resulting datasets are not mutually exclusive.
   // The string 'exclude' contains a comma-separated list of servers to exclude
   // from the map.

   TMap *map = (TMap *)0;

   if (!ds || strlen(ds) <= 0) {
      Info("GetDataSets", "dataset name undefined!");
      return map;
   }

   // Get the dataset
   TFileCollection *fc = GetDataSet(ds);
   if (!fc) {
      Info("GetDataSets", "could not retrieve the dataset '%s'", ds);
      return map;
   }

   // Get the subset
   if (!(map = fc->GetFilesPerServer(exclude))) {
      if (gDebug > 0)
         Info("GetDataSets", "could not get map for '%s'", ds);
   }

   // Cleanup
   delete fc;

   // Done
   return map;
}

//______________________________________________________________________________
void TDataSetManager::PrintDataSet(TFileCollection *fc, Int_t popt)
{
   // Formatted printout of the content of TFileCollection 'fc'.
   // Options in the form
   //           popt = u * 10 + f
   //     f    0 => header only, 1 => header + files
   //   when printing files
   //     u    0 => print file name only, 1 => print full URL

   if (!fc) return;

   Int_t f = popt%10;
   Int_t u = popt - 10 * f;

   Printf("+++");
   if (fc->GetTitle() && (strlen(fc->GetTitle()) > 0)) {
      Printf("+++ Dumping: %s: ", fc->GetTitle());
   } else {
      Printf("+++ Dumping: %s: ", fc->GetName());
   }
   Printf("%s", fc->ExportInfo("+++ Summary:", 1)->GetName());
   if (f == 1) {
      Printf("+++ Files:");
      Int_t nf = 0;
      TIter nxfi(fc->GetList());
      TFileInfo *fi = 0;
      while ((fi = (TFileInfo *)nxfi())) {
         if (u == 1)
            Printf("+++ %5d. %s", ++nf, fi->GetCurrentUrl()->GetUrl());
         else
            Printf("+++ %5d. %s", ++nf, fi->GetCurrentUrl()->GetFile());
      }
   }
   Printf("+++");
}

//______________________________________________________________________________
void TDataSetManager::ShowDataSets(const char *uri, const char *opt)
{
   // Prints formatted information about the dataset 'uri'.
   // The type and format of output is driven by 'opt':
   //
   //   1. opt = "server:srv1[,srv2[,srv3[,...]]]"
   //            Print info about the subsets of 'uri' on servers srv1, srv2, ...
   //   2. opt = "servers[:exclude:srv1[,srv2[,srv3[,...]]]]"
   //            Print info about the subsets of 'uri' on all servers, except
   //            the ones in the exclude list srv1, srv2, ...
   //   3. opt = <any>
   //            Print info about all datasets matching 'uri'
   //
   //   If 'opt' contains 'full:' the list of files in the datasets are also printed.
   //   In case 3. this is enabled only if 'uri' matches a single dataset.


   TFileCollection *fc = 0;
   TString o(opt);
   Int_t popt = 0;
   if (o.Contains("full:")) {
      o.ReplaceAll("full:","");
      popt = 1;
   }
   if (o.BeginsWith("server:")) {
      o.ReplaceAll("server:", "");
      TString srv;
      Int_t from = 0;
      while ((o.Tokenize(srv, from, ","))) {
         fc = GetDataSet(uri, srv.Data());
         PrintDataSet(fc, popt);
         delete fc;
      }
   } else if (o.BeginsWith("servers")) {
      o.ReplaceAll("servers", "");
      if (o.BeginsWith(":exclude:"))
         o.ReplaceAll(":exclude:", "");
      else
         o = "";
      TMap *dsmap = GetSubDataSets(uri, o.Data());
      if (dsmap) {
         TIter nxk(dsmap);
         TObject *k = 0;
         while ((k = nxk()) && (fc = (TFileCollection *) dsmap->GetValue(k))) {
            PrintDataSet(fc, popt);
         }
         delete dsmap;
      }
   } else {
      TString u(uri);
      if (!u.IsNull() && !u.Contains("*") && (fc = GetDataSet(uri))) {
         // Single dataset
         PrintDataSet(fc, 10 + popt);
         delete fc;
      } else {
         // Support for "*" or "/*"
         if (u == "*" || u == "/*" || u == "/*/" || u == "/*/*") u = "/*/*/";
         // Scan the existing datasets and print the content
         GetDataSets(u.Data(), (UInt_t)TDataSetManager::kPrint);
      }
   }

   return;
}
 TDataSetManager.cxx:1
 TDataSetManager.cxx:2
 TDataSetManager.cxx:3
 TDataSetManager.cxx:4
 TDataSetManager.cxx:5
 TDataSetManager.cxx:6
 TDataSetManager.cxx:7
 TDataSetManager.cxx:8
 TDataSetManager.cxx:9
 TDataSetManager.cxx:10
 TDataSetManager.cxx:11
 TDataSetManager.cxx:12
 TDataSetManager.cxx:13
 TDataSetManager.cxx:14
 TDataSetManager.cxx:15
 TDataSetManager.cxx:16
 TDataSetManager.cxx:17
 TDataSetManager.cxx:18
 TDataSetManager.cxx:19
 TDataSetManager.cxx:20
 TDataSetManager.cxx:21
 TDataSetManager.cxx:22
 TDataSetManager.cxx:23
 TDataSetManager.cxx:24
 TDataSetManager.cxx:25
 TDataSetManager.cxx:26
 TDataSetManager.cxx:27
 TDataSetManager.cxx:28
 TDataSetManager.cxx:29
 TDataSetManager.cxx:30
 TDataSetManager.cxx:31
 TDataSetManager.cxx:32
 TDataSetManager.cxx:33
 TDataSetManager.cxx:34
 TDataSetManager.cxx:35
 TDataSetManager.cxx:36
 TDataSetManager.cxx:37
 TDataSetManager.cxx:38
 TDataSetManager.cxx:39
 TDataSetManager.cxx:40
 TDataSetManager.cxx:41
 TDataSetManager.cxx:42
 TDataSetManager.cxx:43
 TDataSetManager.cxx:44
 TDataSetManager.cxx:45
 TDataSetManager.cxx:46
 TDataSetManager.cxx:47
 TDataSetManager.cxx:48
 TDataSetManager.cxx:49
 TDataSetManager.cxx:50
 TDataSetManager.cxx:51
 TDataSetManager.cxx:52
 TDataSetManager.cxx:53
 TDataSetManager.cxx:54
 TDataSetManager.cxx:55
 TDataSetManager.cxx:56
 TDataSetManager.cxx:57
 TDataSetManager.cxx:58
 TDataSetManager.cxx:59
 TDataSetManager.cxx:60
 TDataSetManager.cxx:61
 TDataSetManager.cxx:62
 TDataSetManager.cxx:63
 TDataSetManager.cxx:64
 TDataSetManager.cxx:65
 TDataSetManager.cxx:66
 TDataSetManager.cxx:67
 TDataSetManager.cxx:68
 TDataSetManager.cxx:69
 TDataSetManager.cxx:70
 TDataSetManager.cxx:71
 TDataSetManager.cxx:72
 TDataSetManager.cxx:73
 TDataSetManager.cxx:74
 TDataSetManager.cxx:75
 TDataSetManager.cxx:76
 TDataSetManager.cxx:77
 TDataSetManager.cxx:78
 TDataSetManager.cxx:79
 TDataSetManager.cxx:80
 TDataSetManager.cxx:81
 TDataSetManager.cxx:82
 TDataSetManager.cxx:83
 TDataSetManager.cxx:84
 TDataSetManager.cxx:85
 TDataSetManager.cxx:86
 TDataSetManager.cxx:87
 TDataSetManager.cxx:88
 TDataSetManager.cxx:89
 TDataSetManager.cxx:90
 TDataSetManager.cxx:91
 TDataSetManager.cxx:92
 TDataSetManager.cxx:93
 TDataSetManager.cxx:94
 TDataSetManager.cxx:95
 TDataSetManager.cxx:96
 TDataSetManager.cxx:97
 TDataSetManager.cxx:98
 TDataSetManager.cxx:99
 TDataSetManager.cxx:100
 TDataSetManager.cxx:101
 TDataSetManager.cxx:102
 TDataSetManager.cxx:103
 TDataSetManager.cxx:104
 TDataSetManager.cxx:105
 TDataSetManager.cxx:106
 TDataSetManager.cxx:107
 TDataSetManager.cxx:108
 TDataSetManager.cxx:109
 TDataSetManager.cxx:110
 TDataSetManager.cxx:111
 TDataSetManager.cxx:112
 TDataSetManager.cxx:113
 TDataSetManager.cxx:114
 TDataSetManager.cxx:115
 TDataSetManager.cxx:116
 TDataSetManager.cxx:117
 TDataSetManager.cxx:118
 TDataSetManager.cxx:119
 TDataSetManager.cxx:120
 TDataSetManager.cxx:121
 TDataSetManager.cxx:122
 TDataSetManager.cxx:123
 TDataSetManager.cxx:124
 TDataSetManager.cxx:125
 TDataSetManager.cxx:126
 TDataSetManager.cxx:127
 TDataSetManager.cxx:128
 TDataSetManager.cxx:129
 TDataSetManager.cxx:130
 TDataSetManager.cxx:131
 TDataSetManager.cxx:132
 TDataSetManager.cxx:133
 TDataSetManager.cxx:134
 TDataSetManager.cxx:135
 TDataSetManager.cxx:136
 TDataSetManager.cxx:137
 TDataSetManager.cxx:138
 TDataSetManager.cxx:139
 TDataSetManager.cxx:140
 TDataSetManager.cxx:141
 TDataSetManager.cxx:142
 TDataSetManager.cxx:143
 TDataSetManager.cxx:144
 TDataSetManager.cxx:145
 TDataSetManager.cxx:146
 TDataSetManager.cxx:147
 TDataSetManager.cxx:148
 TDataSetManager.cxx:149
 TDataSetManager.cxx:150
 TDataSetManager.cxx:151
 TDataSetManager.cxx:152
 TDataSetManager.cxx:153
 TDataSetManager.cxx:154
 TDataSetManager.cxx:155
 TDataSetManager.cxx:156
 TDataSetManager.cxx:157
 TDataSetManager.cxx:158
 TDataSetManager.cxx:159
 TDataSetManager.cxx:160
 TDataSetManager.cxx:161
 TDataSetManager.cxx:162
 TDataSetManager.cxx:163
 TDataSetManager.cxx:164
 TDataSetManager.cxx:165
 TDataSetManager.cxx:166
 TDataSetManager.cxx:167
 TDataSetManager.cxx:168
 TDataSetManager.cxx:169
 TDataSetManager.cxx:170
 TDataSetManager.cxx:171
 TDataSetManager.cxx:172
 TDataSetManager.cxx:173
 TDataSetManager.cxx:174
 TDataSetManager.cxx:175
 TDataSetManager.cxx:176
 TDataSetManager.cxx:177
 TDataSetManager.cxx:178
 TDataSetManager.cxx:179
 TDataSetManager.cxx:180
 TDataSetManager.cxx:181
 TDataSetManager.cxx:182
 TDataSetManager.cxx:183
 TDataSetManager.cxx:184
 TDataSetManager.cxx:185
 TDataSetManager.cxx:186
 TDataSetManager.cxx:187
 TDataSetManager.cxx:188
 TDataSetManager.cxx:189
 TDataSetManager.cxx:190
 TDataSetManager.cxx:191
 TDataSetManager.cxx:192
 TDataSetManager.cxx:193
 TDataSetManager.cxx:194
 TDataSetManager.cxx:195
 TDataSetManager.cxx:196
 TDataSetManager.cxx:197
 TDataSetManager.cxx:198
 TDataSetManager.cxx:199
 TDataSetManager.cxx:200
 TDataSetManager.cxx:201
 TDataSetManager.cxx:202
 TDataSetManager.cxx:203
 TDataSetManager.cxx:204
 TDataSetManager.cxx:205
 TDataSetManager.cxx:206
 TDataSetManager.cxx:207
 TDataSetManager.cxx:208
 TDataSetManager.cxx:209
 TDataSetManager.cxx:210
 TDataSetManager.cxx:211
 TDataSetManager.cxx:212
 TDataSetManager.cxx:213
 TDataSetManager.cxx:214
 TDataSetManager.cxx:215
 TDataSetManager.cxx:216
 TDataSetManager.cxx:217
 TDataSetManager.cxx:218
 TDataSetManager.cxx:219
 TDataSetManager.cxx:220
 TDataSetManager.cxx:221
 TDataSetManager.cxx:222
 TDataSetManager.cxx:223
 TDataSetManager.cxx:224
 TDataSetManager.cxx:225
 TDataSetManager.cxx:226
 TDataSetManager.cxx:227
 TDataSetManager.cxx:228
 TDataSetManager.cxx:229
 TDataSetManager.cxx:230
 TDataSetManager.cxx:231
 TDataSetManager.cxx:232
 TDataSetManager.cxx:233
 TDataSetManager.cxx:234
 TDataSetManager.cxx:235
 TDataSetManager.cxx:236
 TDataSetManager.cxx:237
 TDataSetManager.cxx:238
 TDataSetManager.cxx:239
 TDataSetManager.cxx:240
 TDataSetManager.cxx:241
 TDataSetManager.cxx:242
 TDataSetManager.cxx:243
 TDataSetManager.cxx:244
 TDataSetManager.cxx:245
 TDataSetManager.cxx:246
 TDataSetManager.cxx:247
 TDataSetManager.cxx:248
 TDataSetManager.cxx:249
 TDataSetManager.cxx:250
 TDataSetManager.cxx:251
 TDataSetManager.cxx:252
 TDataSetManager.cxx:253
 TDataSetManager.cxx:254
 TDataSetManager.cxx:255
 TDataSetManager.cxx:256
 TDataSetManager.cxx:257
 TDataSetManager.cxx:258
 TDataSetManager.cxx:259
 TDataSetManager.cxx:260
 TDataSetManager.cxx:261
 TDataSetManager.cxx:262
 TDataSetManager.cxx:263
 TDataSetManager.cxx:264
 TDataSetManager.cxx:265
 TDataSetManager.cxx:266
 TDataSetManager.cxx:267
 TDataSetManager.cxx:268
 TDataSetManager.cxx:269
 TDataSetManager.cxx:270
 TDataSetManager.cxx:271
 TDataSetManager.cxx:272
 TDataSetManager.cxx:273
 TDataSetManager.cxx:274
 TDataSetManager.cxx:275
 TDataSetManager.cxx:276
 TDataSetManager.cxx:277
 TDataSetManager.cxx:278
 TDataSetManager.cxx:279
 TDataSetManager.cxx:280
 TDataSetManager.cxx:281
 TDataSetManager.cxx:282
 TDataSetManager.cxx:283
 TDataSetManager.cxx:284
 TDataSetManager.cxx:285
 TDataSetManager.cxx:286
 TDataSetManager.cxx:287
 TDataSetManager.cxx:288
 TDataSetManager.cxx:289
 TDataSetManager.cxx:290
 TDataSetManager.cxx:291
 TDataSetManager.cxx:292
 TDataSetManager.cxx:293
 TDataSetManager.cxx:294
 TDataSetManager.cxx:295
 TDataSetManager.cxx:296
 TDataSetManager.cxx:297
 TDataSetManager.cxx:298
 TDataSetManager.cxx:299
 TDataSetManager.cxx:300
 TDataSetManager.cxx:301
 TDataSetManager.cxx:302
 TDataSetManager.cxx:303
 TDataSetManager.cxx:304
 TDataSetManager.cxx:305
 TDataSetManager.cxx:306
 TDataSetManager.cxx:307
 TDataSetManager.cxx:308
 TDataSetManager.cxx:309
 TDataSetManager.cxx:310
 TDataSetManager.cxx:311
 TDataSetManager.cxx:312
 TDataSetManager.cxx:313
 TDataSetManager.cxx:314
 TDataSetManager.cxx:315
 TDataSetManager.cxx:316
 TDataSetManager.cxx:317
 TDataSetManager.cxx:318
 TDataSetManager.cxx:319
 TDataSetManager.cxx:320
 TDataSetManager.cxx:321
 TDataSetManager.cxx:322
 TDataSetManager.cxx:323
 TDataSetManager.cxx:324
 TDataSetManager.cxx:325
 TDataSetManager.cxx:326
 TDataSetManager.cxx:327
 TDataSetManager.cxx:328
 TDataSetManager.cxx:329
 TDataSetManager.cxx:330
 TDataSetManager.cxx:331
 TDataSetManager.cxx:332
 TDataSetManager.cxx:333
 TDataSetManager.cxx:334
 TDataSetManager.cxx:335
 TDataSetManager.cxx:336
 TDataSetManager.cxx:337
 TDataSetManager.cxx:338
 TDataSetManager.cxx:339
 TDataSetManager.cxx:340
 TDataSetManager.cxx:341
 TDataSetManager.cxx:342
 TDataSetManager.cxx:343
 TDataSetManager.cxx:344
 TDataSetManager.cxx:345
 TDataSetManager.cxx:346
 TDataSetManager.cxx:347
 TDataSetManager.cxx:348
 TDataSetManager.cxx:349
 TDataSetManager.cxx:350
 TDataSetManager.cxx:351
 TDataSetManager.cxx:352
 TDataSetManager.cxx:353
 TDataSetManager.cxx:354
 TDataSetManager.cxx:355
 TDataSetManager.cxx:356
 TDataSetManager.cxx:357
 TDataSetManager.cxx:358
 TDataSetManager.cxx:359
 TDataSetManager.cxx:360
 TDataSetManager.cxx:361
 TDataSetManager.cxx:362
 TDataSetManager.cxx:363
 TDataSetManager.cxx:364
 TDataSetManager.cxx:365
 TDataSetManager.cxx:366
 TDataSetManager.cxx:367
 TDataSetManager.cxx:368
 TDataSetManager.cxx:369
 TDataSetManager.cxx:370
 TDataSetManager.cxx:371
 TDataSetManager.cxx:372
 TDataSetManager.cxx:373
 TDataSetManager.cxx:374
 TDataSetManager.cxx:375
 TDataSetManager.cxx:376
 TDataSetManager.cxx:377
 TDataSetManager.cxx:378
 TDataSetManager.cxx:379
 TDataSetManager.cxx:380
 TDataSetManager.cxx:381
 TDataSetManager.cxx:382
 TDataSetManager.cxx:383
 TDataSetManager.cxx:384
 TDataSetManager.cxx:385
 TDataSetManager.cxx:386
 TDataSetManager.cxx:387
 TDataSetManager.cxx:388
 TDataSetManager.cxx:389
 TDataSetManager.cxx:390
 TDataSetManager.cxx:391
 TDataSetManager.cxx:392
 TDataSetManager.cxx:393
 TDataSetManager.cxx:394
 TDataSetManager.cxx:395
 TDataSetManager.cxx:396
 TDataSetManager.cxx:397
 TDataSetManager.cxx:398
 TDataSetManager.cxx:399
 TDataSetManager.cxx:400
 TDataSetManager.cxx:401
 TDataSetManager.cxx:402
 TDataSetManager.cxx:403
 TDataSetManager.cxx:404
 TDataSetManager.cxx:405
 TDataSetManager.cxx:406
 TDataSetManager.cxx:407
 TDataSetManager.cxx:408
 TDataSetManager.cxx:409
 TDataSetManager.cxx:410
 TDataSetManager.cxx:411
 TDataSetManager.cxx:412
 TDataSetManager.cxx:413
 TDataSetManager.cxx:414
 TDataSetManager.cxx:415
 TDataSetManager.cxx:416
 TDataSetManager.cxx:417
 TDataSetManager.cxx:418
 TDataSetManager.cxx:419
 TDataSetManager.cxx:420
 TDataSetManager.cxx:421
 TDataSetManager.cxx:422
 TDataSetManager.cxx:423
 TDataSetManager.cxx:424
 TDataSetManager.cxx:425
 TDataSetManager.cxx:426
 TDataSetManager.cxx:427
 TDataSetManager.cxx:428
 TDataSetManager.cxx:429
 TDataSetManager.cxx:430
 TDataSetManager.cxx:431
 TDataSetManager.cxx:432
 TDataSetManager.cxx:433
 TDataSetManager.cxx:434
 TDataSetManager.cxx:435
 TDataSetManager.cxx:436
 TDataSetManager.cxx:437
 TDataSetManager.cxx:438
 TDataSetManager.cxx:439
 TDataSetManager.cxx:440
 TDataSetManager.cxx:441
 TDataSetManager.cxx:442
 TDataSetManager.cxx:443
 TDataSetManager.cxx:444
 TDataSetManager.cxx:445
 TDataSetManager.cxx:446
 TDataSetManager.cxx:447
 TDataSetManager.cxx:448
 TDataSetManager.cxx:449
 TDataSetManager.cxx:450
 TDataSetManager.cxx:451
 TDataSetManager.cxx:452
 TDataSetManager.cxx:453
 TDataSetManager.cxx:454
 TDataSetManager.cxx:455
 TDataSetManager.cxx:456
 TDataSetManager.cxx:457
 TDataSetManager.cxx:458
 TDataSetManager.cxx:459
 TDataSetManager.cxx:460
 TDataSetManager.cxx:461
 TDataSetManager.cxx:462
 TDataSetManager.cxx:463
 TDataSetManager.cxx:464
 TDataSetManager.cxx:465
 TDataSetManager.cxx:466
 TDataSetManager.cxx:467
 TDataSetManager.cxx:468
 TDataSetManager.cxx:469
 TDataSetManager.cxx:470
 TDataSetManager.cxx:471
 TDataSetManager.cxx:472
 TDataSetManager.cxx:473
 TDataSetManager.cxx:474
 TDataSetManager.cxx:475
 TDataSetManager.cxx:476
 TDataSetManager.cxx:477
 TDataSetManager.cxx:478
 TDataSetManager.cxx:479
 TDataSetManager.cxx:480
 TDataSetManager.cxx:481
 TDataSetManager.cxx:482
 TDataSetManager.cxx:483
 TDataSetManager.cxx:484
 TDataSetManager.cxx:485
 TDataSetManager.cxx:486
 TDataSetManager.cxx:487
 TDataSetManager.cxx:488
 TDataSetManager.cxx:489
 TDataSetManager.cxx:490
 TDataSetManager.cxx:491
 TDataSetManager.cxx:492
 TDataSetManager.cxx:493
 TDataSetManager.cxx:494
 TDataSetManager.cxx:495
 TDataSetManager.cxx:496
 TDataSetManager.cxx:497
 TDataSetManager.cxx:498
 TDataSetManager.cxx:499
 TDataSetManager.cxx:500
 TDataSetManager.cxx:501
 TDataSetManager.cxx:502
 TDataSetManager.cxx:503
 TDataSetManager.cxx:504
 TDataSetManager.cxx:505
 TDataSetManager.cxx:506
 TDataSetManager.cxx:507
 TDataSetManager.cxx:508
 TDataSetManager.cxx:509
 TDataSetManager.cxx:510
 TDataSetManager.cxx:511
 TDataSetManager.cxx:512
 TDataSetManager.cxx:513
 TDataSetManager.cxx:514
 TDataSetManager.cxx:515
 TDataSetManager.cxx:516
 TDataSetManager.cxx:517
 TDataSetManager.cxx:518
 TDataSetManager.cxx:519
 TDataSetManager.cxx:520
 TDataSetManager.cxx:521
 TDataSetManager.cxx:522
 TDataSetManager.cxx:523
 TDataSetManager.cxx:524
 TDataSetManager.cxx:525
 TDataSetManager.cxx:526
 TDataSetManager.cxx:527
 TDataSetManager.cxx:528
 TDataSetManager.cxx:529
 TDataSetManager.cxx:530
 TDataSetManager.cxx:531
 TDataSetManager.cxx:532
 TDataSetManager.cxx:533
 TDataSetManager.cxx:534
 TDataSetManager.cxx:535
 TDataSetManager.cxx:536
 TDataSetManager.cxx:537
 TDataSetManager.cxx:538
 TDataSetManager.cxx:539
 TDataSetManager.cxx:540
 TDataSetManager.cxx:541
 TDataSetManager.cxx:542
 TDataSetManager.cxx:543
 TDataSetManager.cxx:544
 TDataSetManager.cxx:545
 TDataSetManager.cxx:546
 TDataSetManager.cxx:547
 TDataSetManager.cxx:548
 TDataSetManager.cxx:549
 TDataSetManager.cxx:550
 TDataSetManager.cxx:551
 TDataSetManager.cxx:552
 TDataSetManager.cxx:553
 TDataSetManager.cxx:554
 TDataSetManager.cxx:555
 TDataSetManager.cxx:556
 TDataSetManager.cxx:557
 TDataSetManager.cxx:558
 TDataSetManager.cxx:559
 TDataSetManager.cxx:560
 TDataSetManager.cxx:561
 TDataSetManager.cxx:562
 TDataSetManager.cxx:563
 TDataSetManager.cxx:564
 TDataSetManager.cxx:565
 TDataSetManager.cxx:566
 TDataSetManager.cxx:567
 TDataSetManager.cxx:568
 TDataSetManager.cxx:569
 TDataSetManager.cxx:570
 TDataSetManager.cxx:571
 TDataSetManager.cxx:572
 TDataSetManager.cxx:573
 TDataSetManager.cxx:574
 TDataSetManager.cxx:575
 TDataSetManager.cxx:576
 TDataSetManager.cxx:577
 TDataSetManager.cxx:578
 TDataSetManager.cxx:579
 TDataSetManager.cxx:580
 TDataSetManager.cxx:581
 TDataSetManager.cxx:582
 TDataSetManager.cxx:583
 TDataSetManager.cxx:584
 TDataSetManager.cxx:585
 TDataSetManager.cxx:586
 TDataSetManager.cxx:587
 TDataSetManager.cxx:588
 TDataSetManager.cxx:589
 TDataSetManager.cxx:590
 TDataSetManager.cxx:591
 TDataSetManager.cxx:592
 TDataSetManager.cxx:593
 TDataSetManager.cxx:594
 TDataSetManager.cxx:595
 TDataSetManager.cxx:596
 TDataSetManager.cxx:597
 TDataSetManager.cxx:598
 TDataSetManager.cxx:599
 TDataSetManager.cxx:600
 TDataSetManager.cxx:601
 TDataSetManager.cxx:602
 TDataSetManager.cxx:603
 TDataSetManager.cxx:604
 TDataSetManager.cxx:605
 TDataSetManager.cxx:606
 TDataSetManager.cxx:607
 TDataSetManager.cxx:608
 TDataSetManager.cxx:609
 TDataSetManager.cxx:610
 TDataSetManager.cxx:611
 TDataSetManager.cxx:612
 TDataSetManager.cxx:613
 TDataSetManager.cxx:614
 TDataSetManager.cxx:615
 TDataSetManager.cxx:616
 TDataSetManager.cxx:617
 TDataSetManager.cxx:618
 TDataSetManager.cxx:619
 TDataSetManager.cxx:620
 TDataSetManager.cxx:621
 TDataSetManager.cxx:622
 TDataSetManager.cxx:623
 TDataSetManager.cxx:624
 TDataSetManager.cxx:625
 TDataSetManager.cxx:626
 TDataSetManager.cxx:627
 TDataSetManager.cxx:628
 TDataSetManager.cxx:629
 TDataSetManager.cxx:630
 TDataSetManager.cxx:631
 TDataSetManager.cxx:632
 TDataSetManager.cxx:633
 TDataSetManager.cxx:634
 TDataSetManager.cxx:635
 TDataSetManager.cxx:636
 TDataSetManager.cxx:637
 TDataSetManager.cxx:638
 TDataSetManager.cxx:639
 TDataSetManager.cxx:640
 TDataSetManager.cxx:641
 TDataSetManager.cxx:642
 TDataSetManager.cxx:643
 TDataSetManager.cxx:644
 TDataSetManager.cxx:645
 TDataSetManager.cxx:646
 TDataSetManager.cxx:647
 TDataSetManager.cxx:648
 TDataSetManager.cxx:649
 TDataSetManager.cxx:650
 TDataSetManager.cxx:651
 TDataSetManager.cxx:652
 TDataSetManager.cxx:653
 TDataSetManager.cxx:654
 TDataSetManager.cxx:655
 TDataSetManager.cxx:656
 TDataSetManager.cxx:657
 TDataSetManager.cxx:658
 TDataSetManager.cxx:659
 TDataSetManager.cxx:660
 TDataSetManager.cxx:661
 TDataSetManager.cxx:662
 TDataSetManager.cxx:663
 TDataSetManager.cxx:664
 TDataSetManager.cxx:665
 TDataSetManager.cxx:666
 TDataSetManager.cxx:667
 TDataSetManager.cxx:668
 TDataSetManager.cxx:669
 TDataSetManager.cxx:670
 TDataSetManager.cxx:671
 TDataSetManager.cxx:672
 TDataSetManager.cxx:673
 TDataSetManager.cxx:674
 TDataSetManager.cxx:675
 TDataSetManager.cxx:676
 TDataSetManager.cxx:677
 TDataSetManager.cxx:678
 TDataSetManager.cxx:679
 TDataSetManager.cxx:680
 TDataSetManager.cxx:681
 TDataSetManager.cxx:682
 TDataSetManager.cxx:683
 TDataSetManager.cxx:684
 TDataSetManager.cxx:685
 TDataSetManager.cxx:686
 TDataSetManager.cxx:687
 TDataSetManager.cxx:688
 TDataSetManager.cxx:689
 TDataSetManager.cxx:690
 TDataSetManager.cxx:691
 TDataSetManager.cxx:692
 TDataSetManager.cxx:693
 TDataSetManager.cxx:694
 TDataSetManager.cxx:695
 TDataSetManager.cxx:696
 TDataSetManager.cxx:697
 TDataSetManager.cxx:698
 TDataSetManager.cxx:699
 TDataSetManager.cxx:700
 TDataSetManager.cxx:701
 TDataSetManager.cxx:702
 TDataSetManager.cxx:703
 TDataSetManager.cxx:704
 TDataSetManager.cxx:705
 TDataSetManager.cxx:706
 TDataSetManager.cxx:707
 TDataSetManager.cxx:708
 TDataSetManager.cxx:709
 TDataSetManager.cxx:710
 TDataSetManager.cxx:711
 TDataSetManager.cxx:712
 TDataSetManager.cxx:713
 TDataSetManager.cxx:714
 TDataSetManager.cxx:715
 TDataSetManager.cxx:716
 TDataSetManager.cxx:717
 TDataSetManager.cxx:718
 TDataSetManager.cxx:719
 TDataSetManager.cxx:720
 TDataSetManager.cxx:721
 TDataSetManager.cxx:722
 TDataSetManager.cxx:723
 TDataSetManager.cxx:724
 TDataSetManager.cxx:725
 TDataSetManager.cxx:726
 TDataSetManager.cxx:727
 TDataSetManager.cxx:728
 TDataSetManager.cxx:729
 TDataSetManager.cxx:730
 TDataSetManager.cxx:731
 TDataSetManager.cxx:732
 TDataSetManager.cxx:733
 TDataSetManager.cxx:734
 TDataSetManager.cxx:735
 TDataSetManager.cxx:736
 TDataSetManager.cxx:737
 TDataSetManager.cxx:738
 TDataSetManager.cxx:739
 TDataSetManager.cxx:740
 TDataSetManager.cxx:741
 TDataSetManager.cxx:742
 TDataSetManager.cxx:743
 TDataSetManager.cxx:744
 TDataSetManager.cxx:745
 TDataSetManager.cxx:746
 TDataSetManager.cxx:747
 TDataSetManager.cxx:748
 TDataSetManager.cxx:749
 TDataSetManager.cxx:750
 TDataSetManager.cxx:751
 TDataSetManager.cxx:752
 TDataSetManager.cxx:753
 TDataSetManager.cxx:754
 TDataSetManager.cxx:755
 TDataSetManager.cxx:756
 TDataSetManager.cxx:757
 TDataSetManager.cxx:758
 TDataSetManager.cxx:759
 TDataSetManager.cxx:760
 TDataSetManager.cxx:761
 TDataSetManager.cxx:762
 TDataSetManager.cxx:763
 TDataSetManager.cxx:764
 TDataSetManager.cxx:765
 TDataSetManager.cxx:766
 TDataSetManager.cxx:767
 TDataSetManager.cxx:768
 TDataSetManager.cxx:769
 TDataSetManager.cxx:770
 TDataSetManager.cxx:771
 TDataSetManager.cxx:772
 TDataSetManager.cxx:773
 TDataSetManager.cxx:774
 TDataSetManager.cxx:775
 TDataSetManager.cxx:776
 TDataSetManager.cxx:777
 TDataSetManager.cxx:778
 TDataSetManager.cxx:779
 TDataSetManager.cxx:780
 TDataSetManager.cxx:781
 TDataSetManager.cxx:782
 TDataSetManager.cxx:783
 TDataSetManager.cxx:784
 TDataSetManager.cxx:785
 TDataSetManager.cxx:786
 TDataSetManager.cxx:787
 TDataSetManager.cxx:788
 TDataSetManager.cxx:789
 TDataSetManager.cxx:790
 TDataSetManager.cxx:791
 TDataSetManager.cxx:792
 TDataSetManager.cxx:793
 TDataSetManager.cxx:794
 TDataSetManager.cxx:795
 TDataSetManager.cxx:796
 TDataSetManager.cxx:797
 TDataSetManager.cxx:798
 TDataSetManager.cxx:799
 TDataSetManager.cxx:800
 TDataSetManager.cxx:801
 TDataSetManager.cxx:802
 TDataSetManager.cxx:803
 TDataSetManager.cxx:804
 TDataSetManager.cxx:805
 TDataSetManager.cxx:806
 TDataSetManager.cxx:807
 TDataSetManager.cxx:808
 TDataSetManager.cxx:809
 TDataSetManager.cxx:810
 TDataSetManager.cxx:811
 TDataSetManager.cxx:812
 TDataSetManager.cxx:813
 TDataSetManager.cxx:814
 TDataSetManager.cxx:815
 TDataSetManager.cxx:816
 TDataSetManager.cxx:817
 TDataSetManager.cxx:818
 TDataSetManager.cxx:819
 TDataSetManager.cxx:820
 TDataSetManager.cxx:821
 TDataSetManager.cxx:822
 TDataSetManager.cxx:823
 TDataSetManager.cxx:824
 TDataSetManager.cxx:825
 TDataSetManager.cxx:826
 TDataSetManager.cxx:827
 TDataSetManager.cxx:828
 TDataSetManager.cxx:829
 TDataSetManager.cxx:830
 TDataSetManager.cxx:831
 TDataSetManager.cxx:832
 TDataSetManager.cxx:833
 TDataSetManager.cxx:834
 TDataSetManager.cxx:835
 TDataSetManager.cxx:836
 TDataSetManager.cxx:837
 TDataSetManager.cxx:838
 TDataSetManager.cxx:839
 TDataSetManager.cxx:840
 TDataSetManager.cxx:841
 TDataSetManager.cxx:842
 TDataSetManager.cxx:843
 TDataSetManager.cxx:844
 TDataSetManager.cxx:845
 TDataSetManager.cxx:846
 TDataSetManager.cxx:847
 TDataSetManager.cxx:848
 TDataSetManager.cxx:849
 TDataSetManager.cxx:850
 TDataSetManager.cxx:851
 TDataSetManager.cxx:852
 TDataSetManager.cxx:853
 TDataSetManager.cxx:854
 TDataSetManager.cxx:855
 TDataSetManager.cxx:856
 TDataSetManager.cxx:857
 TDataSetManager.cxx:858
 TDataSetManager.cxx:859
 TDataSetManager.cxx:860
 TDataSetManager.cxx:861
 TDataSetManager.cxx:862
 TDataSetManager.cxx:863
 TDataSetManager.cxx:864
 TDataSetManager.cxx:865
 TDataSetManager.cxx:866
 TDataSetManager.cxx:867
 TDataSetManager.cxx:868
 TDataSetManager.cxx:869
 TDataSetManager.cxx:870
 TDataSetManager.cxx:871
 TDataSetManager.cxx:872
 TDataSetManager.cxx:873
 TDataSetManager.cxx:874
 TDataSetManager.cxx:875
 TDataSetManager.cxx:876
 TDataSetManager.cxx:877
 TDataSetManager.cxx:878
 TDataSetManager.cxx:879
 TDataSetManager.cxx:880
 TDataSetManager.cxx:881
 TDataSetManager.cxx:882
 TDataSetManager.cxx:883
 TDataSetManager.cxx:884
 TDataSetManager.cxx:885
 TDataSetManager.cxx:886
 TDataSetManager.cxx:887
 TDataSetManager.cxx:888
 TDataSetManager.cxx:889
 TDataSetManager.cxx:890
 TDataSetManager.cxx:891
 TDataSetManager.cxx:892
 TDataSetManager.cxx:893
 TDataSetManager.cxx:894
 TDataSetManager.cxx:895
 TDataSetManager.cxx:896
 TDataSetManager.cxx:897
 TDataSetManager.cxx:898
 TDataSetManager.cxx:899
 TDataSetManager.cxx:900
 TDataSetManager.cxx:901
 TDataSetManager.cxx:902
 TDataSetManager.cxx:903
 TDataSetManager.cxx:904
 TDataSetManager.cxx:905
 TDataSetManager.cxx:906
 TDataSetManager.cxx:907
 TDataSetManager.cxx:908
 TDataSetManager.cxx:909
 TDataSetManager.cxx:910
 TDataSetManager.cxx:911
 TDataSetManager.cxx:912
 TDataSetManager.cxx:913
 TDataSetManager.cxx:914
 TDataSetManager.cxx:915
 TDataSetManager.cxx:916
 TDataSetManager.cxx:917
 TDataSetManager.cxx:918
 TDataSetManager.cxx:919
 TDataSetManager.cxx:920
 TDataSetManager.cxx:921
 TDataSetManager.cxx:922
 TDataSetManager.cxx:923
 TDataSetManager.cxx:924
 TDataSetManager.cxx:925
 TDataSetManager.cxx:926
 TDataSetManager.cxx:927
 TDataSetManager.cxx:928
 TDataSetManager.cxx:929
 TDataSetManager.cxx:930
 TDataSetManager.cxx:931
 TDataSetManager.cxx:932
 TDataSetManager.cxx:933
 TDataSetManager.cxx:934
 TDataSetManager.cxx:935
 TDataSetManager.cxx:936
 TDataSetManager.cxx:937
 TDataSetManager.cxx:938
 TDataSetManager.cxx:939
 TDataSetManager.cxx:940
 TDataSetManager.cxx:941
 TDataSetManager.cxx:942
 TDataSetManager.cxx:943
 TDataSetManager.cxx:944
 TDataSetManager.cxx:945
 TDataSetManager.cxx:946