CMS 3D CMS Logo

Namespaces | Macros | Functions
refresh.cc File Reference
#include "FWCore/PluginManager/interface/CacheParser.h"
#include "FWCore/PluginManager/interface/PluginCapabilities.h"
#include "FWCore/PluginManager/interface/PluginFactoryBase.h"
#include "FWCore/PluginManager/interface/PluginFactoryManager.h"
#include "FWCore/PluginManager/interface/SharedLibrary.h"
#include "FWCore/PluginManager/interface/standard.h"
#include "FWCore/Utilities/interface/Exception.h"
#include "FWCore/Utilities/interface/Algorithms.h"
#include <boost/filesystem/operations.hpp>
#include <boost/program_options.hpp>
#include <algorithm>
#include <cstdlib>
#include <fstream>
#include <functional>
#include <iostream>
#include <set>
#include <string>
#include <utility>
#include <sys/wait.h>

Go to the source code of this file.

Namespaces

 std
 

Macros

#define PER_PROCESS_DSO   2000
 

Functions

int main (int argc, char **argv)
 
ostream & std::operator<< (std::ostream &o, vector< std::string > const &iValue)
 

Macro Definition Documentation

#define PER_PROCESS_DSO   2000

Definition at line 43 of file refresh.cc.

Referenced by main().

Function Documentation

int main ( int  argc,
char **  argv 
)

Definition at line 76 of file refresh.cc.

References edmplugin::standard::cachefileName(), cms::Exception::category(), MessageLogger_cfi::cerr, edmplugin::standard::config(), gather_cfg::cout, createBeamHaloJobs::directory, end, relativeConstraints::error, cppFunctionSkipper::exception, Exception, cmsRelvalreport::exit, f, FrontierConditions_GlobalTag_cff::file, corrVsCorr::filename, PatBasicFWLiteAnalyzer::files, edm::for_all(), edmplugin::PluginCapabilities::get(), edmplugin::PluginFactoryManager::get(), kHelpCommandOpt, kHelpOpt, mps_check::lib, edmplugin::PluginFactoryManager::newFactory_, AlcaSiPixelAliHarvester0T_cff::options, AlCaHLTBitMon_ParallelJobs::p, callgraph::path, PER_PROCESS_DSO, edmplugin::standard::pluginPrefix(), edmplugin::CacheParser::read(), findQualityFiles::run, edmplugin::PluginManager::Config::searchPath(), mps_update::status, AlCaHLTBitMon_QueryRunRegistry::string, edmplugin::PluginCapabilities::tryToFind(), cms::Exception::what(), and edmplugin::CacheParser::write().

76  {
77  using namespace boost::program_options;
78  using std::placeholders::_1;
79 
80  static char const* const kPathsOpt = "paths";
81  static char const* const kPathsCommandOpt = "paths,p";
82  //static char const* const kAllOpt = "all";
83  //static char const* const kAllCommandOpt = "all,a";
84  static char const* const kHelpOpt = "help";
85  static char const* const kHelpCommandOpt = "help,h";
86 
87  std::string descString(argv[0]);
88  descString += " [options] [[--";
89  descString += kPathsOpt;
90  descString += "] path [path]] \nAllowed options";
91  options_description desc(descString);
92  std::string defaultDir(".");
93  std::vector<std::string> defaultDirList = edmplugin::standard::config().searchPath();
94  if(!defaultDirList.empty()) {
95  defaultDir = defaultDirList[0];
96  }
97  desc.add_options()
98  (kHelpCommandOpt, "produce help message")
99  (kPathsCommandOpt, value<std::vector<std::string> >()->default_value(
100  std::vector<std::string>(1, defaultDir))
101  , "a directory or a list of files to scan")
102  //(kAllCommandOpt, "when no paths given, try to update caches for all known directories [default is to only scan the first directory]")
103  ;
104 
105  positional_options_description p;
106  p.add(kPathsOpt, -1);
107 
108  variables_map vm;
109  try {
110  store(command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
111  notify(vm);
112  } catch(error const& iException) {
113  std::cerr << iException.what();
114  return 1;
115  }
116 
117  if(vm.count(kHelpOpt)) {
118  std::cout << desc << std::endl;
119  return 0;
120  }
121 
123 
124  /*if(argc == 1) {
125  std::cerr << "Requires at least one argument. Please pass either one directory or a list of files (all in the same directory)." << std::endl;
126  return 1;
127  } */
128 
129  int returnValue = EXIT_SUCCESS;
130 
131  try {
132  std::vector<std::string> requestedPaths(vm[kPathsOpt].as<std::vector<std::string> >());
133 
134  //first find the directory and create a list of files to look at in that directory
135  path directory(requestedPaths[0]);
136  std::vector<std::string> files;
137  bool removeMissingFiles = false;
138  if(boost::filesystem::is_directory(directory)) {
139  if (requestedPaths.size() > 1) {
140  std::cerr << "if a directory is given then only one argument is allowed" << std::endl;
141  return 1;
142  }
143 
144  //if asked to look at whole directory, then we can also remove missing files
145  removeMissingFiles = true;
146 
147  boost::filesystem::directory_iterator file (directory);
148  boost::filesystem::directory_iterator end;
149 
150  path cacheFile(directory);
151  cacheFile /= standard::cachefileName();
152 
153  std::time_t cacheLastChange(0);
154  if(exists(cacheFile)) {
155  cacheLastChange = last_write_time(cacheFile);
156  }
157  for (; file != end; ++file)
158  {
159 
160  path filename (*file);
161  path shortName(file->path().filename());
162  const std::string& stringName = shortName.string();
163 
164  static std::string const kPluginPrefix(standard::pluginPrefix());
165  if (stringName.size() < kPluginPrefix.size()) {
166  continue;
167  }
168  if(stringName.substr(0, kPluginPrefix.size()) != kPluginPrefix) {
169  continue;
170  }
171 
172  if(last_write_time(filename) > cacheLastChange) {
173  files.push_back(stringName);
174  }
175  }
176  } else {
177  //we have files
178  directory = directory.branch_path();
179  for(std::vector<std::string>::iterator it = requestedPaths.begin(), itEnd = requestedPaths.end();
180  it != itEnd; ++it) {
182  if (!exists(f)) {
183  std::cerr << "the file '" << f.string() << "' does not exist" << std::endl;
184  return 1;
185  }
186  if (is_directory(f)) {
187  std::cerr << "either one directory or a list of files are allowed as arguments" << std::endl;
188  return 1;
189  }
190  if(directory != f.branch_path()) {
191  std::cerr << "all files must have be in the same directory (" << directory.string() << ")\n"
192  " the file " << f.string() << " does not." << std::endl;
193  }
194 #if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 47
195  files.push_back(f.filename().string());
196 #else
197  files.push_back(f.leaf());
198 #endif
199  }
200  }
201 
202  path cacheFile(directory);
203  cacheFile /= edmplugin::standard::cachefileName();//path(s_cacheFile);
204 
205  CacheParser::LoadableToPlugins old;
206  if(exists(cacheFile)) {
207  std::ifstream cf(cacheFile.string().c_str());
208  if(!cf) {
209  cms::Exception("FailedToOpen") << "unable to open file '" << cacheFile.string() << "' for reading even though it is present.\n"
210  "Please check permissions on the file.";
211  }
212  CacheParser::read(cf, old);
213  }
214 
215 
216  //load each file and 'listen' to which plugins are loaded
217  Listener listener;
219  pfm->newFactory_.connect(std::bind(std::mem_fn(&Listener::newFactory), &listener, _1));
220  edm::for_all(*pfm, std::bind(std::mem_fn(&Listener::newFactory), &listener, _1));
221 
222  // We open the cache file before forking so that all the children will
223  // use it.
224  std::string temporaryFilename = (cacheFile.string() + ".tmp");
225  std::ofstream cf(temporaryFilename.c_str());
226  if(!cf) {
227  cms::Exception("FailedToOpen") << "unable to open file '"
228  << temporaryFilename << "' for writing.\n"
229  "Please check permissions on the file.";
230  }
231  // Sort the files so that they are loaded "by subsystem", hopefully meaning
232  // they share more dependencies.
233  std::sort(files.begin(), files.end());
234 
235  for(size_t fi = 0, fe = files.size(); fi < fe; fi += PER_PROCESS_DSO)
236  {
237  CacheParser::LoadableToPlugins ltp;
238  pid_t worker = fork();
239  if (worker == 0)
240  {
241  // This the child process.
242  // We load the DSO and find out its plugins, write to the cache
243  // stream and exit, leaving the parent to spawn a new proces.
244  size_t ci = PER_PROCESS_DSO;
245  while (ci && fi != fe)
246  {
247  path loadableFile(directory);
248  loadableFile /= (files[fi]);
249  listener.nameAndTypes_.clear();
250 
251  try {
252  try {
253  edmplugin::SharedLibrary lib(loadableFile);
254  //PluginCapabilities is special, the plugins do not call it. Instead, for each shared library load
255  // we need to ask it to try to find plugins
256  PluginCapabilities::get()->tryToFind(lib);
257  ltp[files[fi]] = listener.nameAndTypes_;
258 
259  } catch(cms::Exception const& iException) {
260  if(iException.category() == "PluginLibraryLoadError") {
261  std::cerr << "Caught exception " << iException.what() << " will ignore " << files[fi] << " and continue." << std::endl;
262  } else {
263  throw;
264  }
265  }
266  }catch(std::exception& iException) {
267  std::cerr << "Caught exception " << iException.what() << std::endl;
268  exit(1);
269  }
270  ++fi;
271  --ci;
272  }
273  CacheParser::write(ltp, cf);
274  cf << std::flush;
275  _exit(0);
276  }
277  else
278  {
279  // Throw if any of the child died with non 0 status.
280  int status = 0;
281  waitpid(worker, &status, 0);
282  if (WIFEXITED(status) == true && status != 0)
283  {
284  std::cerr << "Error while processing." << std::endl;
285  exit(status);
286  }
287  }
288  }
289 
290  cf << std::flush;
291 
292  // We read the new cache and we merge it with the old one.
293  CacheParser::LoadableToPlugins ltp;
294  std::ifstream icf(temporaryFilename.c_str());
295  if(!icf) {
296  cms::Exception("FailedToOpen") << "unable to open file '" << temporaryFilename.c_str() << "' for reading even though it is present.\n"
297  "Please check permissions on the file.";
298  }
299  CacheParser::read(icf, ltp);
300 
301  for (CacheParser::LoadableToPlugins::iterator itFile = ltp.begin() ;
302  itFile != ltp.end() ;
303  ++itFile)
304  {
305  old[itFile->first] = itFile->second;
306  }
307 
308  // If required, we remove the plugins which are missing. Notice that old is
309  // now the most updated copy of the cache.
310  if(removeMissingFiles) {
311  for(CacheParser::LoadableToPlugins::iterator itFile = old.begin();
312  itFile != old.end();
313  /*don't advance the iterator here because it may have become invalid */) {
314  path loadableFile(directory);
315  loadableFile /= (itFile->first);
316  if(not exists(loadableFile)) {
317  std::cout << "removing file '" << temporaryFilename.c_str() << "'" << std::endl;
318  CacheParser::LoadableToPlugins::iterator itToItemBeingRemoved = itFile;
319  //advance the iterator while it is still valid
320  ++itFile;
321  old.erase(itToItemBeingRemoved);
322  } else {
323  //since we are not advancing the iterator in the for loop, do it here
324  ++itFile;
325  }
326  }
327  }
328 
329  // We finally write the final cache.
330  std::ofstream fcf(temporaryFilename.c_str());
331  if(!fcf) {
332  cms::Exception("FailedToOpen") << "unable to open file '" << temporaryFilename.c_str() << "' for writing.\n"
333  "Please check permissions on the file.";
334  }
335  CacheParser::write(old, fcf);
336  rename(temporaryFilename.c_str(), cacheFile.string().c_str());
337  } catch(std::exception& iException) {
338  std::cerr << "Caught exception " << iException.what() << std::endl;
339  returnValue = EXIT_FAILURE;
340  }
341 
342  return returnValue;
343 } catch(std::exception const& iException) {
344  std::cerr << iException.what() << std::endl;
345  return 1;
346 }
#define PER_PROCESS_DSO
Definition: refresh.cc:43
const boost::filesystem::path & cachefileName()
Definition: standard.cc:47
Definition: rename.py:1
std::string const & category() const
Definition: Exception.cc:183
char const * what() const override
Definition: Exception.cc:141
const std::string & pluginPrefix()
Definition: standard.cc:58
Func for_all(ForwardSequence &s, Func f)
wrapper for std::for_each
Definition: Algorithms.h:16
PluginManager::Config config()
Definition: standard.cc:21
edm::signalslot::Signal< void(const PluginFactoryBase *)> newFactory_
double f[11][100]
#define end
Definition: vmac.h:39
Definition: value.py:1
static const char *const kHelpCommandOpt
Definition: CmsShowMain.cc:103
Config & searchPath(const SearchPath &iPath)
Definition: PluginManager.h:59
def write(self, setup)
static const char *const kHelpOpt
Definition: CmsShowMain.cc:102
T get(const Candidate &c)
Definition: component.h:55
static PluginFactoryManager * get()