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
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 void TFileAdaptor::addType(TPluginManager* mgr, char const* type, int altType ) {
0043
0044
0045
0046
0047
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
0078
0079
0080
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
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
0098
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
0124 if ((enablePrefetching_) && ((cacheHint_ == "storage-only") || (cacheHint_ == "auto-detect")))
0125 cacheHint_ = "application-only";
0126
0127
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
0156 f->enableAccounting(doStats_);
0157
0158
0159 f->setTempDir(tempDir_, minFree_);
0160
0161
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
0171 TPluginManager* mgr = gROOT->GetPluginManager();
0172
0173
0174
0175
0176 mgr->LoadHandlersFromPluginDirs("TFile");
0177 mgr->LoadHandlersFromPluginDirs("TSystem");
0178
0179
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 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);
0197 if (!native("root"))
0198 addType(mgr, "^[x]?root:", 1);
0199
0200
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
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);
0307 }
0308
0309 TFileAdaptorUI::~TFileAdaptorUI() {}
0310
0311 void TFileAdaptorUI::stats() const {
0312 me->stats(std::cout);
0313 std::cout << std::endl;
0314 }