CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 41 of file refresh.cc.

Referenced by main().

Function Documentation

int main ( int  argc,
char **  argv 
)

Definition at line 74 of file refresh.cc.

References edmplugin::standard::cachefileName(), cms::Exception::category(), ecal_dqm_sourceclient-live_cfg::cerr, edmplugin::standard::config(), gather_cfg::cout, createBeamHaloJobs::directory, end, relativeConstraints::error, cppFunctionSkipper::exception, Exception, cmsRelvalreport::exit, f, mergeVDriftHistosByStation::file, lut2db_cfg::filename, MainPageGenerator::files, edm::for_all(), edmplugin::PluginCapabilities::get(), edmplugin::PluginFactoryManager::get(), kHelpCommandOpt, kHelpOpt, edmplugin::PluginFactoryManager::newFactory_, AlCaHLTBitMon_ParallelJobs::options, AlCaHLTBitMon_ParallelJobs::p, fed_dqm_sourceclient-live_cfg::path, PER_PROCESS_DSO, edmplugin::standard::pluginPrefix(), edmplugin::CacheParser::read(), DTTTrigCorrFirst::run, edmplugin::PluginManager::Config::searchPath(), ntuplemaker::status, AlCaHLTBitMon_QueryRunRegistry::string, edmplugin::PluginCapabilities::tryToFind(), relativeConstraints::value, cms::Exception::what(), and edmplugin::CacheParser::write().

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