KaliVeda
Toolkit for HIC analysis
KVAvailableRunsFile.cpp
1 /*
2 $Id: KVAvailableRunsFile.cpp,v 1.18 2009/03/12 14:01:02 franklan Exp $
3 $Revision: 1.18 $
4 $Date: 2009/03/12 14:01:02 $
5 */
6 
7 //Created by KVClassFactory on Fri May 5 10:46:40 2006
8 //Author: franklan
9 
10 #include "KVAvailableRunsFile.h"
11 #include "KVDBRun.h"
12 #include "TObjArray.h"
13 #include "TObjString.h"
14 #include "KVString.h"
15 #include "KVList.h"
16 #include "KVDataRepository.h"
17 #include "KVRunFile.h"
18 
20 
22 
23 
24 
33 std::optional<run_index_t> KVAvailableRunsFile::IsRunFileName(const Char_t* filename)
34 {
35  // This method tests the string given as 'filename' to see if it could be the name of a runfile
36  // of the datatype of this available runs file (GetDataType()), for its parent dataset, fDataSet.
37  // Any protocol and/or path information in the filename is first removed.
38  //
39  // The format for a given dataset is defined by variable
40  //
41  // [dataset].DataSet.RunFileName.[datatype]: [format]
42 
43  TString fmt = fDataSet->GetDataSetEnv(Form("DataSet.RunFileName.%s", GetDataType()), ""); //get format string for current dataset
44  if (fmt == "") {
45  Error("IsRunFileName", "No default format set for datatype: %s",
46  GetDataType());
47  return {};
48  }
49  return IsRunFileName(fmt, filename);
50 }
51 
52 
53 
99 
100 std::optional<run_index_t> KVAvailableRunsFile::IsRunFileName(const KVString& fmt, const KVString& filename, const KVString& separators)
101 {
102  // This method tests the string given as 'filename' to see if it could be the name of a runfile.
103  // Any protocol and/or path information in the filename is first removed.
104  // The decision as to whether the filename is valid or not is based on whether it corresponds
105  // to the given format string, e.g. run_%04d.dat
106  //
107  // If good, we return the run number & eventual index as a std::optional<run_index_t>
108  // (if no index is defined for the file i.e. if %I does not appear in the format,
109  // this part of the run_index_t has no value).
110  //
111  // If not, the std::optional has no value. This can be tested as:
112  //
113  //~~~{.cpp}
114  // if(toto.IsRunFileName(...))
115  // {
116  // ...ok, filename is good & run number was retrieved
117  // }
118  //~~~
119  //
120  // KNOWN CASES:
121  //~~~
122  // dataset example filename format
123  // ======= ================ =====================
124  // INDRA_camp1 run127.raw run%R.raw
125  // INDRA_camp2 run127.raw run%R.raw
126  // INDRA_camp4 run127.raw run%R.raw
127  // INDRA_camp5 run127.raw run%R.raw
128  // INDRA_e416a Run356_06-Oct-05_12_44_12.dat Run%R_%D.dat
129  // INDRA_e475s run_0085.dat.13-Mar-06.12:46:24 run_%R.dat.%D1.%D2
130  // INDRA_e494s run_0026.dat.04-May-07.20:33:00 run_%R.dat.%D1.%D2
131  // INDRA_e503 run_0026.dat.04-May-07.20:33:00 run_%R.dat.%D1.%D2
132  // INDRA_e613 run_0022.dat.08Sep11_00h54m47s run_%R.dat.%D
133  // INDRAFAZIA.E789 run_0017.dat.04-04-19_08h25m57s.1 run_%R.dat.%D.%I
134  // FAZIA* run000345 run%R
135  //
136  // %R : run number
137  // %D : date and time
138  // %D1.%D2 : date and time separated by '.'
139  // %I : file index number. WARNING: the first file has NO index, the
140  // second file has index '1', etc. The index returned for the first
141  // file is zero.
142  //~~~
143  //
144  // The filename will be broken up according to the separators (default: ".")
145  // Then the different parts will be analysed according to the given format string
146  KVString _file(gSystem->BaseName(filename)); //Remove protocol and/or path
147 
148  // the filename should contain the same number of "."-separated parts as the format
149  // string, unless the format contains "%I", in which case it can have one less part
150  // (case of first file for run with no index)
151  int np_fmt = fmt.GetNValues(separators);
152  bool with_index = fmt.Contains("%I");
153  bool two_part_date = false;
154  bool got_date = false;
155  int np_fn = _file.GetNValues(separators);
157  KVString _fmt = fmt;
158  if (np_fn == np_fmt + 1) {
159  // if there is 1 more segment after splitting of the filename than in the format string,
160  // try adding an index at the end
161  _fmt.Append(".%I");
162  with_index = true;
163  ++np_fmt;
164  }
165  if (np_fmt == np_fn || (with_index && np_fn == np_fmt - 1)) {
166  _file.Begin(separators);
167  _fmt.Begin(separators);
168  int index(-1), run(0);
169  char date1[100], date2[100];
170  if (fmt.Contains("%D1") && fmt.Contains("%D2")) two_part_date = true;
171 
172  while (!_file.End()) {
173  KVString run_part = _file.Next();
174  KVString fmt_part = _fmt.Next();
175 
176  if (fmt_part.Contains("%R")) {
177  fmt_part.ReplaceAll("%R", "%d");
178  if (fmt_part.Contains("%D")) {
179  fmt_part.ReplaceAll("%D", "%s");
180  sscanf(run_part.Data(), fmt_part.Data(), &run, date1);
181  got_date = true;
182  }
183  else
184  sscanf(run_part.Data(), fmt_part.Data(), &run);
185  }
186  else if (fmt_part.Contains("%I")) {
187  fmt_part.ReplaceAll("%I", "%d");
188  sscanf(run_part.Data(), fmt_part.Data(), &index);
189  }
190  else if (fmt_part.Contains("%D1")) {
191  fmt_part.ReplaceAll("%D1", "%s");
192  sscanf(run_part.Data(), fmt_part.Data(), date1);
193  got_date = true;
194  }
195  else if (fmt_part.Contains("%D2")) {
196  fmt_part.ReplaceAll("%D2", "%s");
197  sscanf(run_part.Data(), fmt_part.Data(), date2);
198  got_date = true;
199  }
200  else if (fmt_part.Contains("%D")) {
201  fmt_part.ReplaceAll("%D", "%s");
202  sscanf(run_part.Data(), fmt_part.Data(), date1);
203  got_date = true;
204  }
205  }
206  if (got_date) {
207  if (two_part_date) date_read_from_filename.Form("%s.%s", date1, date2);
208  else date_read_from_filename = date1;
209  }
210  if (with_index) return run_index_t{run, index};
211  else return run_index_t{run, std::nullopt};
212  }
213  return {};
214 }
215 
216 
217 
223 
225 {
226  // We assume that 'name' is the name of a runfile according to given format 'fmt'.
227  // (see KVAvailableRunsFile::IsRunFileName for accepted formats for runfile names with dates).
228  // We attempt several methods to try to extract a date from 'name'.
229  // If successful, we return kTRUE and 'date' contains the result.
230 
231  auto run = IsRunFileName(fmt, name);
232  if (!run) return kFALSE;
233  // if runfile name contains a date, it is now in variable date_read_from_filename
234  if (date_read_from_filename == "") return kFALSE;
239  return kTRUE;
240  }
241  else {
245  return kTRUE;
246  }
249  return kTRUE;
250  }
253  return kTRUE;
254  }
255  }
256  return kFALSE;
257 }
258 
259 
260 
262 
264 {
265  FileStat_t fs;
266  if (repository->GetFileInfo(fDataSet, GetDataType(), objs->GetName(), fs)) {
267  //runfile exists in repository
268  modt = KVDatime(fs.fMtime);
269  return kTRUE;
270  }
271  return kFALSE;
272 }
273 
274 
275 
277 
279  const KVBase* objs,
280  DataBase* RunListTable,
281  const run_index_t& run_num,
282  KVDBRun* run
283  , bool with_version_and_username)
284 {
285  KVString filename = objs->GetName();
286  KVDatime modt;
287  if (get_file_modification_date(repository, objs, modt)) {
288  insert_runfile_into_database(repository, filename, modt, RunListTable, run_num, run, with_version_and_username);
289  return true;
290  }
291  return false;
292 }
293 
294 
295 
297 
298 void KVAvailableRunsFile::insert_runfile_into_database(KVDataRepository* repository, const KVString& filename, const KVDatime& modt, DataBase* RunListTable,
299  const run_index_t& run_num, KVDBRun* run, bool with_version_and_username)
300 {
301 #ifdef WITH_RSQLITE
302  auto& runs_table = RunListTable->get_table("Available_Runs");
303  runs_table.prepare_insert_single_row();
304  runs_table["run"] = run_num.run();
305  if (run_num.has_index())
306  runs_table["index"] = run_num.index();
307  else
308  runs_table["index"].set_null();
309  runs_table["filename"] = filename;
310  runs_table["date"] = modt.AsSQLString();
311  int sys_id = 1;
312  // is the run associated with a system which is already in the db?
313  if (run && run->GetSystem()) {
314  auto& sys_table = RunListTable->get_table("Systems");
315  if (!RunListTable->count("Systems", "*", Form("system = '%s'", run->GetSystemName()))) {
316  // system not in table; need to add it
317  sys_table.prepare_insert_single_row();
318  sys_table["system"] = run->GetSystemName();
319  sys_table.insert_single_row();
320  }
321  // now retrieve system id for foreign key cross-reference
322  RunListTable->select_data("Systems", "id", Form("system = '%s'", run->GetSystemName()));
323  while (RunListTable->get_next_result())
324  sys_id = sys_table["id"].get_data<int>();
325  }
326  runs_table["sys_id"] = sys_id;
327  if (with_version_and_username) {
328  std::unique_ptr<UserGroup_t> userinfo(gSystem->GetUserInfo());
329  runs_table["username"] = userinfo->fUser;
330  runs_table["version"] = GetKVVersion();
331  }
332  runs_table.insert_single_row();
333 #endif
334 }
335 
336 
337 
347 
348 void KVAvailableRunsFile::Update(const std::unique_ptr<DataBase>& db_handle)
349 {
350  // Examine the contents of the repository directory corresponding to this datatype
351  // for parent dataset fDataSet.
352  //
353  // For each file found which was not already in the list of available runs and
354  // we add an entry to the available runlist database file.
355  //
356  // This may be called by OpenAvailableRunsFile() in order to initially create
357  // the new db file: in this case db_handle contains the pointer to the (already open) db.
358 
359 #ifdef WITH_RSQLITE
360  KVSQLite::database* RunListTable;
361  std::unique_ptr<KVSQLite::database> _db;
362  if (db_handle) {
363  // we have been called by OpenAvailableRunsFile() to create a new db file
364  RunListTable = db_handle.get();
365  }
366  else {
367  // we have been called to either create or update an existing db file
368  _db = OpenAvailableRunsFile(true);
369  RunListTable = _db.get();
370  }
371 
372  auto& runs_table = RunListTable->get_table("Available_Runs");
373  auto& sys_table = RunListTable->get_table("Systems");
374 
375  KVDataRepository* repository = fDataSet->GetRepository();
376 
377  std::cout << std::endl << "Updating runlist : " << std::flush;
378  //get directory listing from repository
379  auto dir_list = repository->GetDirectoryListing(fDataSet, GetDataType());
380  if (!dir_list)
381  return;
382 
383  TIter next(&dir_list);
384  KVBase* objs;
385  //progress bar
386  Int_t ntot = dir_list.GetSize();
387  Int_t n5pc = TMath::Max(ntot / 20, 1);
388  Int_t ndone = 0;
389  std::unique_ptr<KVExpDB> db_garbage;
390  KVExpDB* db = fDataSet->GetDataBase();
391  if (!db) {
392  db = new KVExpDB();
393  db_garbage.reset(db);//clean up
394  }
395  while ((objs = (KVBase*) next())) { // loop over all files in directory
396 
397  auto run_num = IsRunFileName(objs->GetName());
398 
399  if (run_num) { // file has correct name format for runfile
400 
401  KVDBRun* run = db->GetDBRun(run_num.value().run());
402 
403  if (!run) {
404  // if dataset has an index multiplier, this may be a recon file with an artificial run number
405  if (db->HasIndexMultiplier()) {
406  // try to decompose run number into run + index
407  auto r = run_num.value().run() / db->GetIndexMultiplier();
408  auto i = run_num.value().run() % db->GetIndexMultiplier();
409  run_num->clear();
410  run_num->set_run(r);
411  if (i) run_num->set_index(i);
412  run = db->GetDBRun(r);
413  }
414  }
415 
416  if (run && run->HasRunFile(run_num.value())) { // the run number & index is included in the database of runs
417 
418  bool add_to_db = true;
419  if (!making_new_db) {
420  // is there an entry for the same run/index & filename in the database?
421  int occurences = 0;
422  auto selection = SelectFileName(objs->GetName()) + " AND " + SelectRunAndOrIndex(run_num.value());
423  occurences = RunListTable->count("Available_Runs", "*", selection);
424  add_to_db = (occurences == 0);
425  }
426 
427  if (add_to_db) {
428  insert_runfile_into_database(repository, objs, RunListTable, run_num.value(), run);
429  }
430  }
431  else { // run not included in database of runs
432  Info("Update", "the current run [%s] is not in database", objs->GetName());
433  if (!insert_runfile_into_database(repository, objs, RunListTable, run_num.value(), nullptr))
434  Warning("Update", "%s GetFileInfo return kFALSE", objs->GetName());
435  }
436  }
437 
438  ndone++;
439  if (!(ndone % n5pc))
440  std::cout << '>' << std::flush;
441  }
442 
443  std::cout << " DONE" << std::endl;
444  making_new_db = false;
445 #endif
446 }
447 
448 
449 
450 
459 
460 Bool_t KVAvailableRunsFile::GetRunInfo(const run_index_t& run, TDatime& modtime, TString& filename)
461 {
462  // Look for a given run/index number in the DB, and read the file's modification date/time and filename
463  //
464  // \returns kTRUE if runfile found in DB, otherwise kFALSE
465  //
466  // If available runs file does not exist, Update() is called to create it.
467  //
468  // If there are multiple versions of the same run (abnormal situation), we print a warning and give info on the most recent file.
469 
470  KVList filenames, dates;
471  //get infos for all versions of run
472  GetRunInfos(run, dates, filenames);
473  if (filenames.GetEntries() == 1) { //only one version
474  filename = ((TObjString*) filenames.First())->String();
475  modtime = ((TObjString*) dates.First())->String().Data();
476  return kTRUE;
477  }
478  else if (filenames.GetEntries() > 1) { //several versions
479  Warning("GetRunInfo",
480  "Multiple versions of this runfile exist in the repository. Infos for most recent file will be returned.");
481  Warning("GetRunInfo",
482  "You should clean the repository using KVDataSet::CleanMultiRunfiles.");
483  //find most recent version
484  TDatime most_recent("1998-12-25 00:00:00");
485  Int_t i_most_recent = 0;
486  for (int i = 0; i < dates.GetEntries(); i++) {
487  //check if run is most recent
488  TDatime rundate(((TObjString*) dates.At(i))->String().Data());
489  if (rundate > most_recent) {
490  most_recent = rundate;
491  i_most_recent = i;
492  }
493  }
494  filename = ((TObjString*) filenames.At(i_most_recent))->String();
495  modtime = ((TObjString*) dates.At(i_most_recent))->String().Data();
496  return kTRUE;
497  }
498  return kFALSE;
499 }
500 
501 
502 
512 
514 {
515  //Look for a given run/index in the database, and store the file's modification date/time and filename
516  //in the two KVList as TObjString objects (these objects belong to the
517  //lists and will be deleted by them).
518  //
519  //We do not stop at the first run found, but add informations for every occurence of the run in the database
520  //(however, we do ignore any spurious duplicate entries if they exist)
521  //
522  //If available runs db does not exist, it will be created
523 
524 #ifdef WITH_RSQLITE
525  auto RunDB = OpenAvailableRunsFile();
526 
527  //clear lists - delete objects
528  dates.Clear();
529  files.Clear();
530 
531  auto& runtable = RunDB->get_table("Available_Runs");
532  if (RunDB->select_data("Available_Runs", "filename,date", SelectRunAndOrIndex(run), kTRUE)) {
533  while (RunDB->get_next_result()) {
534  dates.Add(new TObjString(runtable["date"].data().GetString()));
535  files.Add(new TObjString(runtable["filename"].data().GetString()));
536  }
537  }
538  else {
539  Error("GetRunInfos", "DB query failure? selection=%s", SelectRunAndOrIndex(run).Data());
540  }
541 #endif
542 }
543 
544 
545 #ifdef WITH_RSQLITE
546 
549 
550 std::vector<KVAvailableRunsFile::runfile_info_t> KVAvailableRunsFile::GetRunInfos(const run_index_t& run)
551 {
552  // \return vector of runfile_info_t = std::pair<TDatime,TString> for each runfile in DB for given run_index_t
553  auto RunDB = OpenAvailableRunsFile();
554 
555  std::vector<runfile_info_t> infos;
556 
557  auto& runtable = RunDB->get_table("Available_Runs");
558  if (RunDB->select_data("Available_Runs", "filename,date", SelectRunAndOrIndex(run), kTRUE)) {
559  while (RunDB->get_next_result()) {
560  infos.push_back(std::make_pair(KVDatime(runtable["date"].data().GetString(), KVDatime::kSQL), TString(runtable["filename"].data().GetString())));
561  }
562  }
563  else {
564  Error("GetRunInfos", "DB query failure? selection=%s", SelectRunAndOrIndex(run).Data());
565  }
566  return infos;
567 }
568 
569 
570 
573 
574 std::map<run_index_t, std::vector<KVAvailableRunsFile::runfile_info_t>> KVAvailableRunsFile::GetRunFileInfos(const run_index_list& runlist)
575 {
576  // For all runfiles in the run_index_list, fill the map with the dates & filenames from the DB
577  std::map<run_index_t, std::vector<KVAvailableRunsFile::runfile_info_t>> infos;
578  for (auto& ri : runlist) {
579  infos[ri] = GetRunInfos(ri);
580  }
581  return infos;
582 }
583 
584 
585 
588 
590 {
591  // For all runfiles in the run_index_list, print list of all filenames & dates from the DB.
592 
593  auto info_map = GetRunFileInfos(runlist);
594  auto db = fDataSet->GetDataBase();
595  KVDBSystem* sys = nullptr;
596  for (auto& p : info_map) {
597  auto S = db->GetDBRun(p.first.run())->GetSystem();
598  if (S != sys) {
599  std::cout << "\t" << S->GetName() << std::endl;
600  sys = S;
601  }
602  std::cout << p.first << ":";
603  for (auto& rf : p.second) {
604  std::cout << "\t" << rf.first.AsSQLString() << "\t" << rf.second << std::endl;
605  }
606  }
607 }
608 
609 #endif
610 
611 
612 
620 
622 {
623  //\return a sorted list of available systems based on the runs in the available runs database.
624  //
625  //For each system in the list we set the number of available runs : this number
626  //can be retrieved with KVDBSystem::GetNumberRuns()
627  //
628  // \note 'bad' runfiles are excluded
629 
630  KVUnownedList sys_list;
631 
632  KVExpDB* db = fDataSet->GetDataBase();
633  std::unique_ptr<KVExpDB> garbage_db;
634  if (!db) {
635  db = new KVExpDB;
636  garbage_db.reset(db);//clean up
637  }
638 #ifdef WITH_RSQLITE
639  auto runDB = OpenAvailableRunsFile();
640 
641  // list of systems for available runs
642  runDB->select_data("Systems", "system", "id > 1");
643  while (runDB->get_next_result()) {
644  auto sys = db->GetSystem((*runDB)["Systems"]["system"].get_data<TString>());
645  if (sys && sys->GetNGoodRunFiles()) sys_list.Add(sys);
646  }
647  // set number of runs & events associated with each system
648  TIter it_sys(&sys_list);
649  while (auto sys = (KVDBSystem*)it_sys()) {
650  runDB->select_data("Available_Runs,Systems", "run,index", Form("system = '%s'", sys->GetName()), true);
651  std::map<int, int> nruns;
652  ULong64_t events = 0;
653  while (runDB->get_next_result()) {
654  auto run = (*runDB)["Available_Runs"]["run"].get_data<int>();
655  auto index = (*runDB)["Available_Runs"]["index"].is_null() ? -1 : (*runDB)["Available_Runs"]["index"].get_data<int>();
656  if (!db->GetDBRunFile({run, index}).IsBad()) {
657  ++nruns[run];
658  events += db->GetDBRunFile({run, index}).GetEvents();
659  }
660  }
661  sys->SetNumberRuns(nruns.size());
662  sys->SetEvents(events);
663  }
664 
665  //sort list of systems in order of increasing run number
666  if (sys_list.GetSize() > 1)
667  sys_list.Sort();
668 #endif
669  return sys_list;
670 }
671 
672 
673 
676 
678 {
679  // \return list of systems corresponding to given runfiles
680  KVExpDB* db = fDataSet->GetDataBase();
681  if (!db)
682  return {};
683  KVUniqueNameList syslist;
684  for (auto& ri : rl) {
685  KVDBRun* r{nullptr};
686  KVDBSystem* s{nullptr};
687  if ((r = db->GetDBRun(ri.run())) && (s = r->GetSystem()))
688  syslist.Add(s);
689  }
690  return syslist;
691 }
692 
693 
694 
701 
703 {
704  //\param[in] systol pointer to system description in experimental database
705  //
706  //\return sorted list of available run files (KVRunFile objects) for the given system.
707  //
708  // \note 'bad' runfiles are excluded
709 
710  KVList sys_list;
711 
712  KVExpDB* db = fDataSet->GetDataBase();
713  std::unique_ptr<KVExpDB> garbage_db;
714  if (!db) {
715  db = new KVExpDB;
716  garbage_db.reset(db);//clean up
717  }
718 #ifdef WITH_RSQLITE
719  auto runDB = OpenAvailableRunsFile();
720 
721  // list of runfiles for given system
722  runDB->select_data("Available_Runs,Systems", "run,index,filename,date,version,username", Form("system = '%s'", systol->GetName()), true);
723  while (runDB->get_next_result()) {
724  auto a_run = db->GetDBRun((*runDB)["Available_Runs"]["run"].get_data<int>());
725  auto run = a_run->GetNumber();
726  std::optional<int> index = ((*runDB)["Available_Runs"]["index"].is_null() ?
727  std::nullopt : std::optional<int>((*runDB)["Available_Runs"]["index"].get_data<int>()));
728  KVDatime fDatime((*runDB)["Available_Runs"]["date"].get_data<TString>(), KVDatime::kSQL);
729  KVString kvversion = (*runDB)["Available_Runs"]["version"].get_data<KVString>();
730  KVString username = (*runDB)["Available_Runs"]["username"].get_data<KVString>();
731  KVString filename = (*runDB)["Available_Runs"]["filename"].get_data<KVString>();
732  if (IsCalled("raw")) {
733  // for raw data files, use the actual date/time of the start of data taking in the database
734  TString start_date = a_run->GetRunFile({run, index}).GetStartDate();
735  if (start_date != "") fDatime.Set(start_date);
736  }
737  if (!db->GetDBRunFile({run, index}).IsBad())
738  sys_list.Add(new KVRunFile(a_run, {run, index}, filename, fDatime, kvversion, username));
739  }
740 
741  //sort list of runs in order of increasing run number
742  if (sys_list.GetSize() > 1)
743  sys_list.Sort();
744 #endif
745  return sys_list;
746 }
747 
748 
749 
754 
755 void KVAvailableRunsFile::UpdateInfos(const run_index_t& run, const KVString& filename, const KVString& kvversion, const KVString& username)
756 {
757  // Call this method to update informations on the file "filename" corresponding to run,
758  // by adding/replacing the KV version and username read from the file itself (not necessarily
759  // corresponding to current KV version and username)
760 #ifdef WITH_RSQLITE
761  auto runDB = OpenAvailableRunsFile();
762 
763  auto selection = SelectRunAndOrIndex(run) + " AND " + SelectFileName(filename);
764 
765  (*runDB)["Available_Runs"]["version"] = kvversion;
766  (*runDB)["Available_Runs"]["username"] = username;
767  runDB->update("Available_Runs", "version,username", selection);
768 #endif
769 }
770 
771 
772 
775 
776 void KVAvailableRunsFile::Remove(const run_index_t& run, const KVString& filename)
777 {
778  //Remove from the db ALL entries corresponding to the given run/index (and filename if given)
779 
780 #ifdef WITH_RSQLITE
781  auto runDB = OpenAvailableRunsFile();
782 
783  auto selection = SelectRunAndOrIndex(run);
784  if (!filename.IsNull()) selection += " AND " + SelectFileName(filename);
785 
786  runDB->delete_rows_in_table("Available_Runs", selection);
787 #endif
788 }
789 
790 
791 
792 
796 
797 void KVAvailableRunsFile::Add(const run_index_t& run, const KVString& filename)
798 {
799  //Add to the file an entry corresponding to this run, assumed to be present in the repository
800  //with the given filename.
801 
802 #ifdef WITH_RSQLITE
803  auto runDB = OpenAvailableRunsFile();
804 
806 #endif
807 }
808 
809 
810 
813 
814 std::forward_list<run_index_t> KVAvailableRunsFile::CheckMultiRunfiles()
815 {
816  //Returns a list with all run/indexes for which more than one file is in the available runs db
817 
818  std::forward_list<run_index_t> multiruns;
819 #ifdef WITH_RSQLITE
820  auto runDB = OpenAvailableRunsFile();
821 
822  runDB->select_data("Available_Runs", "run,index,COUNT(*)", "", false, "GROUP BY run, index HAVING COUNT(*)>1");
823 
824  while (runDB->get_next_result()) {
825  multiruns.push_front({(*runDB)["Available_Runs"]["run"].get_data<int>(),
826  ((*runDB)["Available_Runs"]["index"].is_null() ?
827  std::nullopt : std::optional<int>((*runDB)["Available_Runs"]["index"].get_data<int>()))});
828  }
829 #endif
830  return multiruns;
831 }
832 
833 
834 
835 
843 
845 {
846  //Returns list of available run/indexes for this data type.
847  //
848  //If 'sys' gives the address of a valid database reaction system, only files
849  //corresponding to the system will be included.
850  //
851  //Note that runfiles which are considered to be 'bad' are excluded
852 
853  TString selection, tables("Available_Runs");
854  if (sys) {
855  selection = Form("system = '%s'", sys->GetName());
856  tables += ",Systems";
857  }
858 
859  KVExpDB* db = fDataSet->GetDataBase();
860  std::unique_ptr<KVExpDB> garbage_db;
861  if (!db) {
862  db = new KVExpDB;
863  garbage_db.reset(db);//clean up
864  }
866 #ifdef WITH_RSQLITE
867  auto runDB = OpenAvailableRunsFile();
868 
869  runDB->select_data(tables, "run,index", selection);
870  while (runDB->get_next_result()) {
871  auto run = (*runDB)["Available_Runs"]["run"].get_data<int>();
872  auto index = (*runDB)["Available_Runs"]["index"].is_null() ? -1 : (*runDB)["Available_Runs"]["index"].get_data<int>();
873  if (!db->GetDBRunFile({run, index}).IsBad())
874  l.Add({run, index});
875  }
876 #endif
877  return l;
878 }
879 
880 
881 
888 
890 {
891  // Filename of file containing information on available runs
892  // i.e. [repository].available_runs.[dataset subdir].[dattype subdir].sqlite
893  //
894  // If [dataset subdir] contains "/" (i.e. if data is grouped into subdirectories)
895  // we replace them by "_"
896 
898  if (!fDataSet) {
899  Error("GetFileName", "Dataset has not been set for this file.");
900  filename = "";
901  }
902  else {
903  KVString datapath = fDataSet->GetDataPathSubdir();
904  datapath.ReplaceAll("/", "_");
905  filename.Form("%s.available_runs.%s.%s.sqlite", fDataSet->GetRepository()->GetName(), datapath.Data(),
907  }
908  return filename;
909 }
910 
911 
912 
927 
929 {
930  // Returns the full path to the directory where the available runs file is stored.
931  // This is by default the same directory where the dataset files are stored.
932  // However, if KaliVeda was installed using a GNU-style directory layout
933  // (possibly in the system directories, e.g. Ubuntu packages)
934  // then the path will be the user's working directory + dataset name
935  //
936  // Alternatively, by setting the config variable
937  // KVAvailableRunsFile.RunFileDirectory: /some/path
938  //
939  // files will be stored/looked for in
940  // /some/path/[dataset]
941  //
942  // You can use environment variables - $(VAR) - in the path
943 
944  KVString filepath;
945  if (!fDataSet) {
946  Error("GetFilePath", "Dataset has not been set for this file.");
947  filepath = "";
948  }
949  else {
950  TString p = gEnv->GetValue("KVAvailableRunsFile.RunFileDirectory", "");
951  if (p == "") {
952  // no user-defined run file directory
953  if (is_gnuinstall()) {
954  // GNU-style install: use working directory
955  filepath = GetWORKDIRFilePath(fDataSet->GetName());
956  }
957  else
958  filepath = fDataSet->GetDataSetDir();
959  }
960  else {
962  AssignAndDelete(filepath, gSystem->ConcatFileName(p.Data(), fDataSet->GetName()));
963  }
964  }
965  return filepath;
966 }
967 
968 
969 
973 
975 {
976  // Return the full path on the local machine to the file
977  // used to store information on available runs
978 
979  KVString path;
981  return path;
982 }
983 
984 
985 
990 
992 {
993  // Check that the directory given by GetFilePath() exists and is writable
994  // If it does not exist, it will be created if possible
995  // If it exists but is not writable, or cannot be created, returns kFALSE.
996 
997  if (gSystem->AccessPathName(GetFilePath(), kFileExists)) { // directory does not exist
998  if (gSystem->mkdir(GetFilePath(), kTRUE) == -1) {
999  Error("CheckDirectoryForAvailableRunsFile", "cannot create directory %s - check access permissions", GetFilePath().Data());
1000  return kFALSE;
1001  }
1002  // set access permissions on created directory
1003  gSystem->Chmod(GetFilePath(), 0775);
1004  }
1005  if (gSystem->AccessPathName(GetFilePath(), kWritePermission)) { // directory is not writable
1006  Error("CheckDirectoryForAvailableRunsFile", "directory %s is not writable - check access permissions", GetFilePath().Data());
1007  return kFALSE;
1008  }
1009  return kTRUE;
1010 }
1011 
1012 
1013 
1015 
1016 std::unique_ptr<DataBase> KVAvailableRunsFile::OpenAvailableRunsFile(bool called_by_update)
1017 {
1018 #ifdef WITH_RSQLITE
1021  auto db = std::make_unique<KVSQLite::database>(GetFullPathToAvailableRunsFile());
1022  if (!db->good()) {
1023  Error("OpenAvailableRunsFile", "Failed to open/create sqlite database file %s", GetFullPathToAvailableRunsFile().Data());
1024  db.reset(nullptr);
1025  return db;
1026  }
1027  if (making_new_db) {
1028  // set access permissions on database file
1030 
1031  // create systems table
1032  KVSQLite::table sys_tab("Systems");
1034  sys_tab.primary_key("id");
1035  sys_tab.add_column("system", KVSQLite::column_type::TEXT).NOT_NULL().UNIQUE();
1036  auto& t = db->add_table(sys_tab);
1037  // add default 'unknown' system (which will have id=1)
1038  t.prepare_insert_single_row();
1039  t["system"] = "unknown";
1040  t.insert_single_row();
1041 
1042  // create runs table
1043  KVSQLite::table run_tab("Available_Runs");
1045  run_tab.primary_key("id");
1047  run_tab.add_column("index", KVSQLite::column_type::INTEGER);
1048  run_tab.add_column("filename", KVSQLite::column_type::TEXT).NOT_NULL();
1049  run_tab.add_column("date", KVSQLite::column_type::TEXT).NOT_NULL();
1050  run_tab.add_column("version", KVSQLite::column_type::TEXT);
1051  run_tab.add_column("username", KVSQLite::column_type::TEXT);
1052  run_tab.add_column("sys_id", KVSQLite::column_type::INTEGER).NOT_NULL();
1053  run_tab.foreign_key("sys_id", "Systems", "id");
1054 
1055  db->add_table(run_tab);
1056 
1057  if (!called_by_update) Update(db);
1058  }
1059  return db;
1060 #else
1061  return {};
1062 #endif
1063 }
1064 
1065 
1066 
1072 
1074 {
1075  // return kTRUE if the given file for this runfile is lacking some information
1076  // e.g. the KV version and username
1077  //
1078  // N.B.: if no file is known for this run, we return kFALSE
1079 #ifdef WITH_RSQLITE
1080  auto runDB = OpenAvailableRunsFile();
1081  auto selection = SelectRunAndOrIndex(run) + " AND " + SelectFileName(filename);
1082  runDB->select_data("Available_Runs", "run,version", selection);
1083  while (runDB->get_next_result()) {
1084  if ((*runDB)["Available_Runs"]["version"].is_null()) return true;
1085  }
1086 #endif
1087  return false;
1088 }
1089 
1090 
int Int_t
ROOT::R::TRInterface & r
bool Bool_t
char Char_t
constexpr Bool_t kFALSE
constexpr Bool_t kTRUE
R__EXTERN TEnv * gEnv
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize fs
char name[80]
char * Form(const char *fmt,...)
void AssignAndDelete(TString &target, char *tobedeleted)
kFileExists
kWritePermission
R__EXTERN TSystem * gSystem
Handles lists of available runs for different datasets and types of data.
KVList GetListOfAvailableRunFilesForSystem(const KVDBSystem *systol)
Bool_t CheckDirectoryForAvailableRunsFile()
virtual std::unique_ptr< DataBase > OpenAvailableRunsFile(bool called_by_update=false)
Bool_t InfosNeedUpdate(const run_index_t &run, const KVString &filename)
void GetRunInfos(const run_index_t &run, KVList &dates, KVList &names)
bool insert_runfile_into_database(KVDataRepository *repository, const KVBase *objs, DataBase *RunListTable, const run_index_t &run_num, KVDBRun *run, bool with_version_and_username=false)
void PrintRunFileInfos(const run_index_list &runlist)
For all runfiles in the run_index_list, print list of all filenames & dates from the DB.
virtual void Remove(const run_index_t &run, const KVString &filename="")
Remove from the db ALL entries corresponding to the given run/index (and filename if given)
void UpdateInfos(const run_index_t &run, const KVString &filename, const KVString &kvversion, const KVString &username)
Bool_t ExtractDateFromFileName(const Char_t *name, KVDatime &date)
const Char_t * GetDataType() const
TString SelectRunAndOrIndex(const run_index_t &run)
dataset to which this file belongs
std::forward_list< run_index_t > CheckMultiRunfiles()
Returns a list with all run/indexes for which more than one file is in the available runs db.
virtual void Update(const std::unique_ptr< DataBase > &db_handle={})
KVUniqueNameList GetSystemsForRunFiles(const run_index_list &rl) const
const KVDataSet * fDataSet
std::map< run_index_t, std::vector< runfile_info_t > > GetRunFileInfos(const run_index_list &runlist)
For all runfiles in the run_index_list, fill the map with the dates & filenames from the DB.
KVString GetFileName() const
KVString GetFullPathToAvailableRunsFile() const
run_index_list GetRunList(const KVDBSystem *system=0)
std::optional< run_index_t > IsRunFileName(const Char_t *filename)
KVUnownedList GetListOfAvailableSystems()
TString SelectFileName(const KVString &filename)
KVString GetFilePath() const
static KVString date_read_from_filename
virtual bool get_file_modification_date(KVDataRepository *repository, const KVBase *objs, KVDatime &modt)
virtual void Add(const run_index_t &run, const KVString &filename)
Base class for KaliVeda framework.
Definition: KVBase.h:139
void Error(const char *method, const char *msgfmt,...) const override
Definition: KVBase.cpp:1666
static const Char_t * GetWORKDIRFilePath(const Char_t *namefile="")
Definition: KVBase.cpp:121
static bool is_gnuinstall()
Definition: KVBase.h:274
virtual Bool_t IsCalled(const Char_t *name) const
Definition: KVBase.h:189
static const Char_t * GetKVVersion()
Returns KaliVeda version string.
Definition: KVBase.cpp:869
void Warning(const char *method, const char *msgfmt,...) const override
Definition: KVBase.cpp:1653
virtual Int_t GetNumber() const
Definition: KVDBRecord.h:73
void SetEvents(ULong64_t evt_number)
Definition: KVDBRunFile.h:183
Description of an experimental run in database ,,.
Definition: KVDBRun.h:41
const Char_t * GetSystemName() const
Definition: KVDBRun.h:259
KVDBSystem * GetSystem() const
Definition: KVDBRun.cpp:239
Bool_t HasRunFile(const run_index_t &run_index) const
Definition: KVDBRun.h:69
Database class used to store information on different colliding systems studied during an experiment....
Definition: KVDBSystem.h:51
Base class for managing repositories of experimental data.
virtual KVUniqueNameList GetDirectoryListing(const KVDataSet *dataset, const Char_t *datatype="", const Char_t *subdir="")
virtual Bool_t GetFileInfo(const KVDataSet *dataset, const Char_t *datatype, const Char_t *runfile, FileStat_t &fs) const
KVDataRepository * GetRepository() const
Get pointer to data repository in which dataset is stored.
Definition: KVDataSet.cpp:1503
const Char_t * GetDataSetDir() const
Definition: KVDataSet.cpp:745
KVString GetDataTypeSubdir(const Char_t *type) const
Definition: KVDataSet.h:206
virtual const Char_t * GetDataPathSubdir() const
Definition: KVDataSet.h:201
KVExpDB * GetDataBase(const TString &opt="") const
Definition: KVDataSet.cpp:287
Extension of TDatime to handle various useful date formats.
Definition: KVDatime.h:33
@ kSQL
Definition: KVDatime.h:44
static Bool_t IsGANACQFormat(const Char_t *date)
Definition: KVDatime.cpp:433
static Bool_t IsSQLFormat(const Char_t *date)
Definition: KVDatime.cpp:496
static Bool_t IsGANACQ2010Format(const Char_t *date)
Definition: KVDatime.cpp:455
void SetSQLDate(const Char_t *SQLDateString)
Definition: KVDatime.cpp:204
void SetGanacqNarvalDate(const Char_t *GanacqDateString)
Definition: KVDatime.cpp:297
static Bool_t IsGANACQNarvalFormat(const Char_t *date)
Definition: KVDatime.cpp:476
void SetGanacq2010Date(const Char_t *GanacqDateString)
Definition: KVDatime.cpp:273
void SetGanacqDate(const Char_t *GanacqDateString)
Definition: KVDatime.cpp:323
Base class to describe database of an experiment ,,.
Definition: KVExpDB.h:61
virtual KVDBSystem * GetSystem(const Char_t *system) const
Definition: KVExpDB.h:152
KVDBRun * GetDBRun(Int_t number) const
Definition: KVExpDB.h:132
const KVDBRunFile & GetDBRunFile(const run_index_t &r) const
Definition: KVExpDB.h:136
Int_t GetIndexMultiplier() const
Definition: KVExpDB.h:229
Bool_t HasIndexMultiplier() const
Definition: KVExpDB.h:225
Extended TList class which owns its objects by default.
Definition: KVList.h:22
Description of an individual data file in an experimental dataset.
Definition: KVRunFile.h:19
column & UNIQUE()
Definition: SQLiteDB.h:186
column & NOT_NULL()
Definition: SQLiteDB.h:193
Interface to ROOT SQLite database backend.
Definition: SQLiteDB.h:473
bool select_data(const TString &tables, const TString &columns="*", const TString &selection="", bool distinct=false, const TString &anything_else="") const
Definition: SQLiteDB.cpp:822
bool get_next_result() const
Definition: SQLiteDB.cpp:941
KVSQLite::table & get_table(const TString &name)
Definition: SQLiteDB.h:567
int count(const TString &tables, const TString &column="*", const TString &selection="", bool distinct=false, const TString &anything_else="") const
Definition: SQLiteDB.cpp:1111
void primary_key(const TString &cols)
Definition: SQLiteDB.h:428
void foreign_key(const TString &child_key, const TString &parent_table, const TString &parent_key)
Definition: SQLiteDB.cpp:1661
column & add_column(const KVSQLite::column &c)
Definition: SQLiteDB.cpp:1610
void prepare_insert_single_row()
Definition: SQLiteDB.cpp:1797
void Add(TObject *obj) override
void Clear(Option_t *option="") override
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition: KVString.h:73
void Begin(TString delim) const
Definition: KVString.cpp:565
Bool_t End() const
Definition: KVString.cpp:634
KVString Next(Bool_t strip_whitespace=kFALSE) const
Definition: KVString.cpp:695
Int_t GetNValues(TString delim) const
Definition: KVString.cpp:886
Optimised list in which named objects can only be placed once.
void Add(TObject *obj) override
Extended TList class which does not own its objects by default.
Definition: KVUnownedList.h:20
const char * GetName() const override
const char * AsSQLString() const
void Set()
virtual const char * GetValue(const char *name, const char *dflt) const
const char * GetName() const override
virtual void Info(const char *method, const char *msgfmt,...) const
const char * Data() const
void ToUpper()
TString & Append(char c, Ssiz_t rep=1)
void Form(const char *fmt,...)
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
TString & ReplaceAll(const char *s1, const char *s2)
virtual int Chmod(const char *file, UInt_t mode)
virtual char * ConcatFileName(const char *dir, const char *name)
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
virtual UserGroup_t * GetUserInfo(const char *user=nullptr)
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
virtual const char * BaseName(const char *pathname)
virtual char * ExpandPathName(const char *path)
List of runfiles specified by run number and file index ,.
Specifies a runfile according to run number and file index ,.
Definition: run_index.h:31
int run() const
Definition: run_index.h:50
int index(int no_index=-1) const
Definition: run_index.h:55
bool has_index() const
Definition: run_index.h:59
unsigned long long ULong64_t
BinData::ErrorType GetDataType(const TGraph *gr, DataOptions &fitOpt)
void Error(const char *location, const char *fmt,...)
RooArgSet S(Args_t &&... args)
Double_t Max(Double_t a, Double_t b)
const char * String
TLine l
ClassImp(TPyArg)