Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-05-19 07:20:09

0001 #include "TFileAdaptor.h"
0002 
0003 #include "FWCore/Catalog/interface/SiteLocalConfig.h"
0004 #include "FWCore/MessageLogger/interface/JobReport.h"
0005 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0006 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0007 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0008 #include "FWCore/ParameterSet/interface/PluginDescription.h"
0009 #include "FWCore/Reflection/interface/SetClassParsing.h"
0010 #include "FWCore/ServiceRegistry/interface/Service.h"
0011 #include "FWCore/Utilities/interface/EDMException.h"
0012 #include "Utilities/StorageFactory/interface/StorageAccount.h"
0013 #include "Utilities/StorageFactory/interface/StorageFactory.h"
0014 #include "Utilities/StorageFactory/interface/StorageProxyMaker.h"
0015 #include "Utilities/StorageFactory/interface/StorageProxyMakerFactory.h"
0016 
0017 #include <TROOT.h>
0018 #include <TFile.h>
0019 #include <TPluginManager.h>
0020 
0021 #include <memory>
0022 
0023 #include <algorithm>
0024 #include <sstream>
0025 
0026 // Driver for configuring ROOT plug-in manager to use TStorageFactoryFile.
0027 
0028 /**
0029    Register TFileAdaptor to be the handler for a given type.
0030 
0031    Once registered, URLs matching a specified regexp (for example, ^root: to
0032    manage files starting with root://) will be managed by a TFileAdaptor instance,
0033    possibly overriding any built-in ROOT adaptors.
0034 
0035    @param[in] mgr      The ROOT plugin manager object.
0036    @param[in] type     A regexp-string; URLs matching this string will use TFileAdaptor.
0037    @param[in] altType  Due to a limitation in the TPluginManager, if the type was 
0038                        previously managed by TXNetFile, we must invoke AddHandler with
0039                        a slightly different syntax.  Set this parameter to 1 if this
0040                        applies to you.  Otherwise, leave it at the default (0)
0041  */
0042 void TFileAdaptor::addType(TPluginManager* mgr, char const* type, int altType /*=0*/) {
0043   // HACK:
0044   // The ROOT plug-in manager does not understand loading plugins with different
0045   // signatures.  So, because TXNetSystem is registered with a different constructor
0046   // than all the other plugins, we must match its interface in order to override
0047   // it.
0048   if (altType == 0) {
0049     mgr->AddHandler("TFile",
0050                     type,
0051                     "TStorageFactoryFile",
0052                     "IOPoolTFileAdaptor",
0053                     "TStorageFactoryFile(char const*,Option_t*,char const*,Int_t)");
0054 
0055     mgr->AddHandler("TSystem", type, "TStorageFactorySystem", "IOPoolTFileAdaptor", "TStorageFactorySystem()");
0056   } else if (altType == 1) {
0057     mgr->AddHandler("TFile",
0058                     type,
0059                     "TStorageFactoryFile",
0060                     "IOPoolTFileAdaptor",
0061                     "TStorageFactoryFile(char const*,Option_t*,char const*,Int_t, Int_t, Bool_t)");
0062 
0063     mgr->AddHandler(
0064         "TSystem", type, "TStorageFactorySystem", "IOPoolTFileAdaptor", "TStorageFactorySystem(const char *,Bool_t)");
0065   }
0066 }
0067 
0068 bool TFileAdaptor::native(char const* proto) const {
0069   return std::find(native_.begin(), native_.end(), "all") != native_.end() ||
0070          std::find(native_.begin(), native_.end(), proto) != native_.end();
0071 }
0072 
0073 TFileAdaptor::TFileAdaptor(edm::ParameterSet const& pset, edm::ActivityRegistry& ar)
0074     : enabled_(pset.getUntrackedParameter<bool>("enable")),
0075       doStats_(pset.getUntrackedParameter<bool>("stats")),
0076       enablePrefetching_(false),
0077       // values set in the site local config or in SiteLocalConfigService override
0078       // any values set here for this service.
0079       // These parameters here are needed only for backward compatibility
0080       // for WMDM tools until we switch to only using the site local config for this info.
0081       cacheHint_(pset.getUntrackedParameter<std::string>("cacheHint")),
0082       readHint_(pset.getUntrackedParameter<std::string>("readHint")),
0083       tempDir_(pset.getUntrackedParameter<std::string>("tempDir")),
0084       minFree_(pset.getUntrackedParameter<double>("tempMinFree")),
0085       native_(pset.getUntrackedParameter<std::vector<std::string>>("native")),
0086       // end of section of values overridden by SiteLocalConfigService
0087       timeout_(0U),
0088       debugLevel_(0U) {
0089   if (not enabled_)
0090     return;
0091 
0092   using namespace edm::storage;
0093   StorageFactory* f = StorageFactory::getToModify();
0094 
0095   ar.watchPostEndJob(this, &TFileAdaptor::termination);
0096 
0097   // Retrieve values from SiteLocalConfigService.
0098   // Any such values will override values set above.
0099   edm::Service<edm::SiteLocalConfig> pSLC;
0100   if (pSLC.isAvailable()) {
0101     if (std::string const* p = pSLC->sourceCacheTempDir()) {
0102       tempDir_ = *p;
0103     }
0104     if (double const* p = pSLC->sourceCacheMinFree()) {
0105       minFree_ = *p;
0106     }
0107     if (std::string const* p = pSLC->sourceCacheHint()) {
0108       cacheHint_ = *p;
0109     }
0110     if (std::string const* p = pSLC->sourceReadHint()) {
0111       readHint_ = *p;
0112     }
0113     if (unsigned int const* p = pSLC->sourceTimeout()) {
0114       timeout_ = *p;
0115     }
0116     if (std::vector<std::string> const* p = pSLC->sourceNativeProtocols()) {
0117       native_ = *p;
0118     }
0119     debugLevel_ = pSLC->debugLevel();
0120     enablePrefetching_ = pSLC->enablePrefetching();
0121   }
0122 
0123   // Prefetching does not work with storage-only; forcibly disable it.
0124   if ((enablePrefetching_) && ((cacheHint_ == "storage-only") || (cacheHint_ == "auto-detect")))
0125     cacheHint_ = "application-only";
0126 
0127   // tell factory how clients should access files
0128   if (cacheHint_ == "application-only")
0129     f->setCacheHint(StorageFactory::CACHE_HINT_APPLICATION);
0130   else if (cacheHint_ == "storage-only")
0131     f->setCacheHint(StorageFactory::CACHE_HINT_STORAGE);
0132   else if (cacheHint_ == "lazy-download")
0133     f->setCacheHint(StorageFactory::CACHE_HINT_LAZY_DOWNLOAD);
0134   else if (cacheHint_ == "auto-detect")
0135     f->setCacheHint(StorageFactory::CACHE_HINT_AUTO_DETECT);
0136   else
0137     throw cms::Exception("TFileAdaptor") << "Unrecognised 'cacheHint' value '" << cacheHint_
0138                                          << "', recognised values are 'application-only',"
0139                                          << " 'storage-only', 'lazy-download', 'auto-detect'";
0140 
0141   if (readHint_ == "direct-unbuffered")
0142     f->setReadHint(StorageFactory::READ_HINT_UNBUFFERED);
0143   else if (readHint_ == "read-ahead-buffered")
0144     f->setReadHint(StorageFactory::READ_HINT_READAHEAD);
0145   else if (readHint_ == "auto-detect")
0146     f->setReadHint(StorageFactory::READ_HINT_AUTO);
0147   else
0148     throw cms::Exception("TFileAdaptor") << "Unrecognised 'readHint' value '" << readHint_
0149                                          << "', recognised values are 'direct-unbuffered',"
0150                                          << " 'read-ahead-buffered', 'auto-detect'";
0151 
0152   f->setTimeout(timeout_);
0153   f->setDebugLevel(debugLevel_);
0154 
0155   // enable file access stats accounting if requested
0156   f->enableAccounting(doStats_);
0157 
0158   // tell where to save files.
0159   f->setTempDir(tempDir_, minFree_);
0160 
0161   // forward generic storage proxy makers
0162   {
0163     std::vector<std::unique_ptr<StorageProxyMaker>> makers;
0164     for (auto const& pset : pset.getUntrackedParameter<std::vector<edm::ParameterSet>>("storageProxies")) {
0165       makers.push_back(StorageProxyMakerFactory::get()->create(pset.getUntrackedParameter<std::string>("type"), pset));
0166     }
0167     f->setStorageProxyMakers(std::move(makers));
0168   }
0169 
0170   // set our own root plugins
0171   TPluginManager* mgr = gROOT->GetPluginManager();
0172 
0173   // Make sure ROOT parses system directories first.
0174   // Then our AddHandler() calls will also remove an existing handler
0175   // that was registered with the same regex
0176   mgr->LoadHandlersFromPluginDirs("TFile");
0177   mgr->LoadHandlersFromPluginDirs("TSystem");
0178 
0179   // Note: if you add a new handler, please update the test/tfileTest.cpp as well
0180   if (!native("file"))
0181     addType(mgr, "^file:");
0182   if (!native("http"))
0183     addType(mgr, "^http:");
0184   if (!native("http"))
0185     addType(mgr, "^http[s]?:");
0186   if (!native("ftp"))
0187     addType(mgr, "^ftp:");
0188   /* always */ addType(mgr, "^web:");
0189   if (!native("dcache"))
0190     addType(mgr, "^dcache:");
0191   if (!native("dcap"))
0192     addType(mgr, "^dcap:");
0193   if (!native("gsidcap"))
0194     addType(mgr, "^gsidcap:");
0195   if (!native("root"))
0196     addType(mgr, "^root:", 1);  // See comments in addType
0197   if (!native("root"))
0198     addType(mgr, "^[x]?root:", 1);  // See comments in addType
0199 
0200   // Make sure the TStorageFactoryFile can be loaded regardless of the header auto-parsing setting
0201   {
0202     edm::SetClassParsing guard(true);
0203     if (auto cl = TClass::GetClass("TStorageFactoryFile")) {
0204       cl->GetClassInfo();
0205     } else {
0206       throw cms::Exception("TFileAdaptor") << "Unable to obtain TClass for TStorageFactoryFile";
0207     }
0208   }
0209 }
0210 
0211 void TFileAdaptor::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0212   using namespace edm::storage;
0213   edm::ParameterSetDescription desc;
0214   desc.addUntracked<bool>("enable", true)->setComment("Enable or disable TFileAdaptor behavior");
0215   desc.addUntracked<bool>("stats", true);
0216   desc.addUntracked<std::string>("cacheHint", "auto-detect")
0217       ->setComment(
0218           "Hint for read caching. Possible values: 'application-only', 'storage-only', 'lazy-download', 'auto-detect'. "
0219           "The value from the SiteLocalConfigService overrides the value set here. In addition, if the "
0220           "SiteLocalConfigService has prefetching enabled, the default hint is 'application-only'.");
0221   desc.addUntracked<std::string>("readHint", "auto-detect")
0222       ->setComment(
0223           "Hint for reading itself. Possible values: 'direct-unbuffered', 'read-ahead-buffered', 'auto-detect'. The "
0224           "value from SiteLocalConfigService overrides the value set here.");
0225   desc.addUntracked<std::string>("tempDir", StorageFactory::defaultTempDir())
0226       ->setComment(
0227           "Colon-separated list of directories that storage implementations downloading the full file could place the "
0228           "file. The value from SiteLocalConfigService overrides the value set here.");
0229   desc.addUntracked<double>("tempMinFree", StorageFactory::defaultMinTempFree())
0230       ->setComment(
0231           "Minimum amount of space in GB required for a temporary data directory specified in tempDir. The value from "
0232           "SiteLocalConfigService overrides the value set here.");
0233   desc.addUntracked<std::vector<std::string>>("native", {})
0234       ->setComment(
0235           "Set of protocols for which to use a native ROOT storage implementation instead of CMSSW's StorageFactory. "
0236           "Valid "
0237           "values are 'file', 'http', 'ftp', 'dcache', 'dcap', 'gsidcap', 'root', or 'all' to prefer ROOT for all "
0238           "protocols. The value from SiteLocalConfigService overrides the value set here.");
0239 
0240   edm::ParameterSetDescription proxyMakerDesc;
0241   proxyMakerDesc.addNode(edm::PluginDescription<edm::storage::StorageProxyMakerFactory>("type", false));
0242   std::vector<edm::ParameterSet> proxyMakerDefaults;
0243   desc.addVPSetUntracked("storageProxies", proxyMakerDesc, proxyMakerDefaults)
0244       ->setComment(
0245           "Ordered list of Storage proxies the real Storage object is wrapped into. The real Storage is wrapped into "
0246           "the first element of the list, then that proxy is wrapped into the second element of the list and so on. "
0247           "Only after this wrapping are the LocalCacheFile (lazy-download) and statistics accounting ('stats' "
0248           "parameter) proxies applied.");
0249 
0250   descriptions.add("AdaptorConfig", desc);
0251   descriptions.setComment(
0252       "AdaptorConfig Service is used to configure the TFileAdaptor. If enabled, the TFileAdaptor registers "
0253       "TStorageFactoryFile as a handler for various protocols. The StorageFactory facility provides custom storage "
0254       "access implementations for these protocols, as well as statistics accounting.");
0255 }
0256 
0257 // Write current Storage statistics on a ostream
0258 void TFileAdaptor::termination(void) const {
0259   std::map<std::string, std::string> data;
0260   statsXML(data);
0261   if (!data.empty()) {
0262     edm::Service<edm::JobReport> reportSvc;
0263     reportSvc->reportPerformanceSummary("StorageStatistics", data);
0264   }
0265 }
0266 
0267 void TFileAdaptor::stats(std::ostream& o) const {
0268   if (!doStats_) {
0269     return;
0270   }
0271   float const oneMeg = 1048576.0;
0272   o << "Storage parameters: adaptor: true"
0273     << " Stats:" << (doStats_ ? "true" : "false") << '\n'
0274     << " Prefetching:" << (enablePrefetching_ ? "true" : "false") << '\n'
0275     << " Cache hint:" << cacheHint_ << '\n'
0276     << " Read hint:" << readHint_ << '\n'
0277     << "Storage statistics: " << edm::storage::StorageAccount::summaryText() << "; tfile/read=?/?/"
0278     << (TFile::GetFileBytesRead() / oneMeg) << "MB/?ms/?ms/?ms"
0279     << "; tfile/write=?/?/" << (TFile::GetFileBytesWritten() / oneMeg) << "MB/?ms/?ms/?ms";
0280 }
0281 
0282 void TFileAdaptor::statsXML(std::map<std::string, std::string>& data) const {
0283   if (!doStats_) {
0284     return;
0285   }
0286   float const oneMeg = 1048576.0;
0287   data.insert(std::make_pair("Parameter-untracked-bool-enabled", "true"));
0288   data.insert(std::make_pair("Parameter-untracked-bool-stats", (doStats_ ? "true" : "false")));
0289   data.insert(std::make_pair("Parameter-untracked-bool-prefetching", (enablePrefetching_ ? "true" : "false")));
0290   data.insert(std::make_pair("Parameter-untracked-string-cacheHint", cacheHint_));
0291   data.insert(std::make_pair("Parameter-untracked-string-readHint", readHint_));
0292   edm::storage::StorageAccount::fillSummary(data);
0293   std::ostringstream r;
0294   std::ostringstream w;
0295   r << (TFile::GetFileBytesRead() / oneMeg);
0296   w << (TFile::GetFileBytesWritten() / oneMeg);
0297   data.insert(std::make_pair("ROOT-tfile-read-totalMegabytes", r.str()));
0298   data.insert(std::make_pair("ROOT-tfile-write-totalMegabytes", w.str()));
0299 }
0300 
0301 #include <iostream>
0302 
0303 TFileAdaptorUI::TFileAdaptorUI() {
0304   edm::ActivityRegistry ar;
0305   const edm::ParameterSet param;
0306   me = std::make_shared<TFileAdaptor>(param, ar);  // propagate_const<T> has no reset() function
0307 }
0308 
0309 TFileAdaptorUI::~TFileAdaptorUI() {}
0310 
0311 void TFileAdaptorUI::stats() const {
0312   me->stats(std::cout);
0313   std::cout << std::endl;
0314 }