QwAnalysis
QwRootFile.cc
Go to the documentation of this file.
1 #include "QwRootFile.h"
2 #include "QwRunCondition.h"
3 #include "TH1.h"
4 
5 #include <unistd.h>
6 #include <cstdio>
7 
8 std::string QwRootFile::fDefaultRootFileStem = "Qweak_";
9 
10 const Long64_t QwRootFile::kMaxTreeSize = 100000000000LL;
11 //const Int_t QwRootFile::kMaxMapFileSize = 0x20000000; // 512 MiB
12 const Int_t QwRootFile::kMaxMapFileSize = 0x10000000; // 256 MiB
13 
14 /**
15  * Constructor with relative filename
16  */
17 QwRootFile::QwRootFile(const TString& run_label)
18  : fRootFile(0), fMakePermanent(0),
19  fMapFile(0), fEnableMapFile(kFALSE),
20  fUpdateInterval(400)
21 {
22  // Process the configuration options
24 
25  // Check for the memory-mapped file flag
26  if (fEnableMapFile) {
27 
28  TString mapfilename = "/dev/shm/";
29 
30  // if( host_name.Contains("cdaql4") and (not user_name.CompareTo("cdaq", TString::kExact)) ) {
31  // mapfilename = "/local/scratch/qweak/";
32  // }
33  // else {
34  // mapfilename = getenv_safe_TString("QW_ROOTFILES");
35  // }
36 
37  mapfilename += "/QwMemMapFile.map";
38 
39  fMapFile = TMapFile::Create(mapfilename,"RECREATE", kMaxMapFileSize, "RealTime Producer File");
40 
41  if (not fMapFile) {
42  QwError << "Memory-mapped file " << mapfilename
43  << " could not be opened!" << QwLog::endl;
44  return;
45  }
46 
47  QwMessage << "================== RealTime Producer Memory Map File =================" << QwLog::endl;
48  fMapFile->Print();
49  QwMessage << "======================================================================" << QwLog::endl;
50 
51  } else {
52 
53  //TString rootfilename = getenv_safe_TString("QW_ROOTFILES");
54  TString hostname = gSystem -> HostName();
55  TString rootfilename;
56  TString localRootFileName = gSystem->Getenv("QW_ROOTFILES_LOCAL");
57 
58 // std::cout << "---------------------------------------------------------------------------------" << std::endl;
59 // printf("\n\n\n\n\n\n");
60 // printf("%s %s \n", hostname.Data(), localRootFileName.Data());
61 // printf("\n\n\n\n\n\n");
62 // std::cout << "---------------------------------------------------------------------------------" << std::endl;
63 // // if( localRootFileName.CompareTo("") == 0 ) {
64  if (localRootFileName.IsNull()) {
65  rootfilename = getenv_safe_TString("QW_ROOTFILES");
66  } else {
67  rootfilename = localRootFileName;
68  }
69 // std::cout << "---------------------------------------------------------------------------------" << std::endl;
70 // printf("\n\n\n\n\n\n");
71 // printf("%s %s \n", hostname.Data(), localRootFileName.Data());
72 // printf("\n\n\n\n\n\n");
73 // std::cout << "---------------------------------------------------------------------------------" << std::endl;
74 
75 
76  // Use a probably-unique temporary file name.
77  pid_t pid = getpid();
78 
79  fPermanentName = rootfilename
80  + Form("/%s%s.root", fRootFileStem.Data(), run_label.Data());
81  rootfilename += Form("/%s%s.%s.%d.root",
82  fRootFileStem.Data(), run_label.Data(),
83  hostname.Data(), pid);
84  fRootFile = new TFile(rootfilename, "RECREATE", "QWeak ROOT file");
85  if (! fRootFile) {
86  QwError << "ROOT file " << rootfilename
87  << " could not be opened!" << QwLog::endl;
88  return;
89  }
90 
91  TString run_condition_name = Form("%s_condition", run_label.Data());
92  TList *run_cond_list = (TList*) fRootFile -> FindObjectAny(run_condition_name);
93  if (not run_cond_list) {
94  QwRunCondition run_condition(
97  run_condition_name
98  );
99 
100  fRootFile -> WriteObject(
101  run_condition.Get(),
102  run_condition.GetName()
103  );
104  }
105 
106  fRootFile->SetCompressionLevel(fCompressionLevel);
107  }
108 }
109 
110 
111 /**
112  * Destructor
113  */
115 {
116  // Keep the file on disk if any trees or histograms have been filled.
117  // Also respect any other requests to keep the file around.
119 
120  // Close the map file
121  if (fMapFile) {
122  fMapFile->Close();
123  // TMapFiles may not be deleted
124  fMapFile = 0;
125  }
126 
127  // Close the ROOT file.
128  // Rename if permanence is requested, remove otherwise
129  if (fRootFile) {
130  TString rootfilename = fRootFile->GetName();
131 
132  fRootFile->Close();
133  delete fRootFile;
134  fRootFile = 0;
135 
136  int err;
137  const char* action;
138  if (fMakePermanent) {
139  action = " rename ";
140  err = rename( rootfilename.Data(), fPermanentName.Data() );
141  } else {
142  action = " remove ";
143  err = remove( rootfilename.Data() );
144  }
145  // It'd be proper to "extern int errno" and strerror() here,
146  // but that doesn't seem very C++-ish.
147  if (err) {
148  QwWarning << "Couldn't" << action << rootfilename << QwLog::endl;
149  } else {
150  QwMessage << "Was able to" << action << rootfilename << QwLog::endl;
151  QwMessage << "Root file is " << fPermanentName << QwLog::endl;
152  }
153  }
154 
155  // Delete Qweak ROOT trees
156  std::map< const std::string, std::vector<QwRootTree*> >::iterator map_iter;
157  std::vector<QwRootTree*>::iterator vec_iter;
158  for (map_iter = fTreeByName.begin(); map_iter != fTreeByName.end(); map_iter++) {
159  for (vec_iter = map_iter->second.begin(); vec_iter != map_iter->second.end(); vec_iter++) {
160  delete *vec_iter;
161  }
162  }
163 }
164 
165 /**
166  * Defines configuration options using QwOptions functionality.
167  * @param options Options object
168  */
170 {
171  // Define the ROOT filename stem
172  options.AddOptions("Default options")
173  ("rootfile-stem", po::value<std::string>()->default_value(fDefaultRootFileStem),
174  "stem of the output ROOT filename");
175 
176  // Define the memory map option
177  options.AddOptions()
178  ("enable-mapfile", po::value<bool>()->default_bool_value(false),
179  "enable output to memory-mapped file");
180 
181  // Define the histogram and tree options
182  options.AddOptions("ROOT output options")
183  ("disable-trees", po::value<bool>()->default_bool_value(false),
184  "disable output to all trees");
185  options.AddOptions("ROOT output options")
186  ("disable-histos", po::value<bool>()->default_bool_value(false),
187  "disable output to all histograms");
188 
189  // Define the helicity window versus helicity pattern options
190  options.AddOptions("ROOT output options")
191  ("disable-mps-tree", po::value<bool>()->default_bool_value(false),
192  "disable helicity window output");
193  options.AddOptions("ROOT output options")
194  ("disable-hel-tree", po::value<bool>()->default_bool_value(false),
195  "disable helicity pattern output");
196  options.AddOptions("ROOT output options")
197  ("disable-burst-tree", po::value<bool>()->default_bool_value(false),
198  "disable burst tree");
199  options.AddOptions("ROOT output options")
200  ("disable-slow-tree", po::value<bool>()->default_bool_value(false),
201  "disable slow control tree");
202 
203  // Define the tree output prescaling options
204  options.AddOptions("ROOT output options")
205  ("num-mps-accepted-events", po::value<int>()->default_value(0),
206  "number of accepted consecutive MPS events");
207  options.AddOptions("ROOT output options")
208  ("num-mps-discarded-events", po::value<int>()->default_value(0),
209  "number of discarded consecutive MPS events");
210  options.AddOptions("ROOT output options")
211  ("num-hel-accepted-events", po::value<int>()->default_value(0),
212  "number of accepted consecutive pattern events");
213  options.AddOptions("ROOT output options")
214  ("num-hel-discarded-events", po::value<int>()->default_value(0),
215  "number of discarded consecutive pattern events");
216  options.AddOptions("ROOT output options")
217  ("mapfile-update-interval", po::value<int>()->default_value(400),
218  "Events between a map file update");
219 
220  // Define the autoflush and autosave option (default values by ROOT)
221  options.AddOptions("ROOT performance options")
222  ("autoflush", po::value<int>()->default_value(0),
223  "TTree autoflush");
224  options.AddOptions("ROOT performance options")
225  ("autosave", po::value<int>()->default_value(300000000),
226  "TTree autosave");
227  options.AddOptions("ROOT performance options")
228  ("basket-size", po::value<int>()->default_value(16000),
229  "TTree basket size");
230  options.AddOptions("ROOT performance options")
231  ("circular-buffer", po::value<int>()->default_value(0),
232  "TTree circular buffer");
233  options.AddOptions("ROOT performance options")
234  ("compression-level", po::value<int>()->default_value(1),
235  "TFile compression level");
236 }
237 
238 
239 /**
240  * Parse the configuration options and store in class fields
241  * @param options Options object
242  */
244 {
245  // Option 'root-stem' to specify ROOT file stem
246  fRootFileStem = TString(options.GetValue<std::string>("rootfile-stem"));
247 
248  // Option 'mapfile' to enable memory-mapped ROOT file
249  fEnableMapFile = options.GetValue<bool>("enable-mapfile");
250 
251  // Options 'disable-trees' and 'disable-histos' for disabling
252  // tree and histogram output
253  if (options.GetValue<bool>("disable-trees")) DisableTree(".*");
254  if (options.GetValue<bool>("disable-histos")) DisableHisto(".*");
255 
256  // Options 'disable-mps' and 'disable-hel' for disabling
257  // helicity window and helicity pattern output
258  if (options.GetValue<bool>("disable-mps-tree")) DisableTree("Mps_Tree");
259  if (options.GetValue<bool>("disable-hel-tree")) DisableTree("Hel_Tree");
260  if (options.GetValue<bool>("disable-burst-tree")) DisableTree("Burst_Tree");
261  if (options.GetValue<bool>("disable-slow-tree")) DisableTree("Slow_Tree");
262 
263  // Options 'num-accepted-events' and 'num-discarded-events' for
264  // prescaling of the tree output
265  fNumMpsEventsToSave = options.GetValue<int>("num-mps-accepted-events");
266  fNumMpsEventsToSkip = options.GetValue<int>("num-mps-discarded-events");
267  fNumHelEventsToSave = options.GetValue<int>("num-mps-accepted-events");
268  fNumHelEventsToSkip = options.GetValue<int>("num-mps-discarded-events");
269 
270  // Update interval for the map file
271  fCircularBufferSize = options.GetValue<int>("circular-buffer");
272  fUpdateInterval = options.GetValue<int>("mapfile-update-interval");
273  fCompressionLevel = options.GetValue<int>("compression-level");
274  fBasketSize = options.GetValue<int>("basket-size");
275 
276  // Autoflush and autosave
277  fAutoFlush = options.GetValue<int>("autoflush");
278  if ((ROOT_VERSION_CODE < ROOT_VERSION(5,26,00)) && fAutoFlush != -30000000){
280  QwWarning << "QwRootFile::ProcessOptions: "
281  << "The 'autoflush' flag is not supported by ROOT version "
282  << ROOT_RELEASE
283  << QwLog::endl;
284  }
285  fAutoSave = options.GetValue<int>("autosave");
286  return;
287 }
288 
289 /**
290  * Determine whether the rootfile object has any non-empty trees or
291  * histograms.
292  */
294  return this->HasAnyFilled(fRootFile);
295 }
296 Bool_t QwRootFile::HasAnyFilled(TDirectory* d) {
297  if (!d) return false;
298  TList* l = d->GetListOfKeys();
299 
300  for( int i=0; i < l->GetEntries(); ++i) {
301  const char* name = l->At(i)->GetName();
302  TObject* obj = d->FindObjectAny(name);
303 
304  // Objects which can't be found don't count.
305  if (!obj) continue;
306 
307  // Lists of parameter files, map files, and job conditions don't count.
308  if ( TString(name).Contains("parameter_file") ) continue;
309  if ( TString(name).Contains("mapfile") ) continue;
310  if ( TString(name).Contains("_condition") ) continue;
311  // The EPICS tree doesn't count
312  if ( TString(name).Contains("Slow_Tree") ) continue;
313 
314  // Recursively check subdirectories.
315  if (obj->IsA()->InheritsFrom( "TDirectory" ))
316  if (this->HasAnyFilled( (TDirectory*)obj )) return true;
317 
318  if (obj->IsA()->InheritsFrom( "TTree" ))
319  if ( ((TTree*) obj)->GetEntries() ) return true;
320 
321  if (obj->IsA()->InheritsFrom( "TH1" ))
322  if ( ((TH1*) obj)->GetEntries() ) return true;
323  }
324 
325  return false;
326 }
Int_t fBasketSize
Definition: QwRootFile.h:473
#define QwMessage
Predefined log drain for regular messages.
Definition: QwLog.h:50
UInt_t fNumMpsEventsToSave
Definition: QwRootFile.h:557
Int_t fAutoSave
Definition: QwRootFile.h:475
#define default_bool_value(b)
Definition: QwOptions.h:51
Int_t fAutoFlush
Definition: QwRootFile.h:474
Bool_t fEnableMapFile
Definition: QwRootFile.h:470
UInt_t fNumHelEventsToSkip
Definition: QwRootFile.h:558
An options class.
Definition: QwOptions.h:133
const TString getenv_safe_TString(const char *name)
Definition: QwOptions.h:40
TMapFile * fMapFile
Map file.
Definition: QwRootFile.h:469
void DisableHisto(const TString &regexp)
Add regexp to list of disabled histogram directories.
Definition: QwRootFile.h:496
UInt_t fNumMpsEventsToSkip
Prescaling of events written to tree.
Definition: QwRootFile.h:556
Int_t fUpdateInterval
Definition: QwRootFile.h:471
QwOptions gQwOptions
Definition: QwOptions.cc:27
QwRootFile()
Private default constructor.
UInt_t fNumHelEventsToSave
Definition: QwRootFile.h:559
char ** GetArgv()
Get the vector of command line arguments.
Definition: QwOptions.h:278
TString fPermanentName
Definition: QwRootFile.h:461
po::options_description_easy_init AddOptions(const std::string &blockname="Specialized options")
Add an option to a named block or create new block.
Definition: QwOptions.h:164
TString fRootFileStem
ROOT file stem.
Definition: QwRootFile.h:455
virtual ~QwRootFile()
Destructor.
Definition: QwRootFile.cc:114
T GetValue(const std::string &key)
Get a templated value.
Definition: QwOptions.h:240
UInt_t fCircularBufferSize
Definition: QwRootFile.h:560
static std::string fDefaultRootFileStem
Default ROOT file stem.
Definition: QwRootFile.h:457
Int_t WriteObject(const T *obj, const char *name, Option_t *option="", Int_t bufsize=0)
Write any object to the ROOT file (only valid for TFile)
Definition: QwRootFile.h:403
TFile * fRootFile
ROOT file.
Definition: QwRootFile.h:452
Bool_t HasAnyFilled(void)
Search for non-empty trees or histograms in the file.
Definition: QwRootFile.cc:293
std::map< const std::string, std::vector< QwRootTree * > > fTreeByName
Tree names, addresses, and types.
Definition: QwRootFile.h:510
int GetArgc()
Get the number of command line arguments.
Definition: QwOptions.h:276
Int_t fCompressionLevel
Definition: QwRootFile.h:472
static const Long64_t kMaxTreeSize
Maximum tree size.
Definition: QwRootFile.h:564
static std::ostream & endl(std::ostream &)
End of the line.
Definition: QwLog.cc:299
static const Int_t kMaxMapFileSize
Definition: QwRootFile.h:565
void ProcessOptions(QwOptions &options)
Process the configuration options.
Definition: QwRootFile.cc:243
void DisableTree(const TString &regexp)
Add regexp to list of disabled trees names.
Definition: QwRootFile.h:486
#define QwWarning
Predefined log drain for warnings.
Definition: QwLog.h:45
static void DefineOptions(QwOptions &options)
Define the configuration options.
Definition: QwRootFile.cc:169
#define QwError
Predefined log drain for errors.
Definition: QwLog.h:40
Bool_t fMakePermanent
Definition: QwRootFile.h:462