Go to the documentation of this file.00001 #include "Utilities/StorageFactory/interface/StorageFactory.h"
00002 #include "Utilities/StorageFactory/interface/StorageMakerFactory.h"
00003 #include "Utilities/StorageFactory/interface/StorageAccount.h"
00004 #include "Utilities/StorageFactory/interface/StorageAccountProxy.h"
00005 #include "Utilities/StorageFactory/interface/LocalCacheFile.h"
00006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00007 #include "FWCore/PluginManager/interface/PluginManager.h"
00008 #include "FWCore/PluginManager/interface/standard.h"
00009 #include "FWCore/Utilities/interface/Exception.h"
00010 #include <boost/shared_ptr.hpp>
00011
00012 StorageFactory StorageFactory::s_instance;
00013
00014 StorageFactory::StorageFactory (void)
00015 : m_cacheHint(CACHE_HINT_AUTO_DETECT),
00016 m_readHint(READ_HINT_AUTO),
00017 m_accounting (false),
00018 m_tempfree (4.),
00019 m_temppath (".:$TMPDIR"),
00020 m_timeout(0U),
00021 m_debugLevel(0U)
00022 {
00023 setTempDir(m_temppath, m_tempfree);
00024 }
00025
00026 StorageFactory::~StorageFactory (void)
00027 {
00028 for (MakerTable::iterator i = m_makers.begin (); i != m_makers.end (); ++i)
00029 delete i->second;
00030 }
00031
00032 StorageFactory *
00033 StorageFactory::get (void)
00034 { return &s_instance; }
00035
00036 bool
00037 StorageFactory::enableAccounting (bool enabled)
00038 {
00039 bool old = m_accounting;
00040 m_accounting = enabled;
00041 return old;
00042 }
00043
00044 bool
00045 StorageFactory::accounting(void) const
00046 { return m_accounting; }
00047
00048 void
00049 StorageFactory::setCacheHint(CacheHint value)
00050 { m_cacheHint = value; }
00051
00052 StorageFactory::CacheHint
00053 StorageFactory::cacheHint(void) const
00054 { return m_cacheHint; }
00055
00056 void
00057 StorageFactory::setReadHint(ReadHint value)
00058 { m_readHint = value; }
00059
00060 StorageFactory::ReadHint
00061 StorageFactory::readHint(void) const
00062 { return m_readHint; }
00063
00064 void
00065 StorageFactory::setTimeout(unsigned int timeout)
00066 { m_timeout = timeout; }
00067
00068 unsigned int
00069 StorageFactory::timeout(void) const
00070 { return m_timeout; }
00071
00072 void
00073 StorageFactory::setDebugLevel(unsigned int level)
00074 { m_debugLevel = level; }
00075
00076 unsigned int
00077 StorageFactory::debugLevel(void) const
00078 { return m_debugLevel; }
00079
00080 void
00081 StorageFactory::setTempDir(const std::string &s, double minFreeSpace)
00082 {
00083 #if 0
00084 std::cerr
00085 << "Considering path '" << s
00086 << "', min free space " << minFreeSpace
00087 << "GB for temp dir" << std::endl;
00088 #endif
00089
00090 size_t begin = 0;
00091 std::vector<std::string> dirs;
00092 dirs.reserve(std::count(s.begin(), s.end(), ':') + 1);
00093
00094 while (true)
00095 {
00096 size_t end = s.find(':', begin);
00097 if (end == std::string::npos)
00098 {
00099 dirs.push_back(s.substr(begin, end));
00100 break;
00101 }
00102 else
00103 {
00104 dirs.push_back(s.substr(begin, end - begin));
00105 begin = end+1;
00106 }
00107 }
00108
00109 m_temppath = s;
00110 m_tempfree = minFreeSpace;
00111 m_tempdir = m_lfs.findCachePath(dirs, minFreeSpace);
00112
00113 #if 0
00114 std::cerr
00115 << "Using '" << m_tempdir << "' for temp dir"
00116 << std::endl;
00117 #endif
00118 }
00119
00120 std::string
00121 StorageFactory::tempDir(void) const
00122 { return m_tempdir; }
00123
00124 std::string
00125 StorageFactory::tempPath(void) const
00126 { return m_temppath; }
00127
00128 double
00129 StorageFactory::tempMinFree(void) const
00130 { return m_tempfree; }
00131
00132 StorageMaker *
00133 StorageFactory::getMaker (const std::string &proto)
00134 {
00135 StorageMaker *&instance = m_makers [proto];
00136 if (! edmplugin::PluginManager::isAvailable())
00137 edmplugin::PluginManager::configure(edmplugin::standard::config());
00138 if (! instance)
00139 instance = StorageMakerFactory::get()->tryToCreate(proto);
00140 return instance;
00141 }
00142
00143 StorageMaker *
00144 StorageFactory::getMaker (const std::string &url,
00145 std::string &protocol,
00146 std::string &rest)
00147 {
00148 size_t p = url.find(':');
00149 if (p != std::string::npos)
00150 {
00151 protocol = url.substr(0,p);
00152 rest = url.substr(p+1);
00153 }
00154 else
00155 {
00156 protocol = "file";
00157 rest = url;
00158 }
00159
00160 return getMaker (protocol);
00161 }
00162
00163 Storage *
00164 StorageFactory::open (const std::string &url, int mode )
00165 {
00166 std::string protocol;
00167 std::string rest;
00168 Storage *ret = 0;
00169 boost::shared_ptr<StorageAccount::Stamp> stats;
00170 if (StorageMaker *maker = getMaker (url, protocol, rest))
00171 {
00172 maker->setDebugLevel(m_debugLevel);
00173 if (m_accounting)
00174 stats.reset(new StorageAccount::Stamp(StorageAccount::counter (protocol, "open")));
00175 try
00176 {
00177 if (Storage *storage = maker->open (protocol, rest, mode))
00178 {
00179 if (dynamic_cast<LocalCacheFile *>(storage))
00180 protocol = "local-cache";
00181
00182 if (m_accounting)
00183 ret = new StorageAccountProxy(protocol, storage);
00184 else
00185 ret = storage;
00186
00187 if (stats)
00188 stats->tick();
00189 }
00190 }
00191 catch (cms::Exception &err)
00192 {
00193 err.addContext("Calling StorageFactory::open()");
00194 err.addAdditionalInfo(err.message());
00195 err.clearMessage();
00196 err << "Failed to open the file '" << url << "'";
00197 throw;
00198 }
00199 }
00200 return ret;
00201 }
00202
00203 void
00204 StorageFactory::stagein (const std::string &url)
00205 {
00206 std::string protocol;
00207 std::string rest;
00208
00209 boost::shared_ptr<StorageAccount::Stamp> stats;
00210 if (StorageMaker *maker = getMaker (url, protocol, rest))
00211 {
00212 if (m_accounting)
00213 stats.reset(new StorageAccount::Stamp(StorageAccount::counter (protocol, "stagein")));
00214 try
00215 {
00216 maker->stagein (protocol, rest);
00217 if (stats) stats->tick();
00218 }
00219 catch (cms::Exception &err)
00220 {
00221 edm::LogWarning("StorageFactory::stagein()")
00222 << "Failed to stage in file '" << url << "' because:\n"
00223 << err.explainSelf();
00224 }
00225 }
00226 }
00227
00228 bool
00229 StorageFactory::check (const std::string &url, IOOffset *size )
00230 {
00231 std::string protocol;
00232 std::string rest;
00233
00234 bool ret = false;
00235 boost::shared_ptr<StorageAccount::Stamp> stats;
00236 if (StorageMaker *maker = getMaker (url, protocol, rest))
00237 {
00238 if (m_accounting)
00239 stats.reset(new StorageAccount::Stamp(StorageAccount::counter (protocol, "check")));
00240 try
00241 {
00242 ret = maker->check (protocol, rest, size);
00243 if (stats) stats->tick();
00244 }
00245 catch (cms::Exception &err)
00246 {
00247 edm::LogWarning("StorageFactory::check()")
00248 << "Existence or size check for the file '" << url << "' failed because:\n"
00249 << err.explainSelf();
00250 }
00251 }
00252
00253 return ret;
00254 }
00255
00256 Storage *
00257 StorageFactory::wrapNonLocalFile (Storage *s,
00258 const std::string &proto,
00259 const std::string &path,
00260 int mode)
00261 {
00262 StorageFactory::CacheHint hint = cacheHint();
00263 if ((hint == StorageFactory::CACHE_HINT_LAZY_DOWNLOAD)
00264 && ! (mode & IOFlags::OpenWrite)
00265 && ! m_tempdir.empty()
00266 && (path.empty() || ! m_lfs.isLocalPath(path)))
00267 {
00268 if (accounting())
00269 s = new StorageAccountProxy(proto, s);
00270 s = new LocalCacheFile(s, m_tempdir);
00271 }
00272
00273 return s;
00274 }
00275
00276 void
00277 StorageFactory::activateTimeout (const std::string &url)
00278 {
00279 std::string protocol;
00280 std::string rest;
00281
00282 if (StorageMaker *maker = getMaker (url, protocol, rest))
00283 {
00284 maker->setTimeout (m_timeout);
00285 }
00286 }
00287
00288