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("minimal");
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("minimal");
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  // we don't need a full database, just the systems & runs will do
633  KVExpDB* db = fDataSet->GetDataBase("minimal");
634  std::unique_ptr<KVExpDB> garbage_db;
635  if (!db) {
636  db = new KVExpDB;
637  garbage_db.reset(db);//clean up
638  }
639 #ifdef WITH_RSQLITE
640  auto runDB = OpenAvailableRunsFile();
641 
642  // list of systems for available runs
643  runDB->select_data("Systems", "system", "id > 1");
644  while (runDB->get_next_result()) {
645  auto sys = db->GetSystem((*runDB)["Systems"]["system"].get_data<TString>());
646  if (sys && sys->GetNGoodRunFiles()) sys_list.Add(sys);
647  }
648  // set number of runs & events associated with each system
649  TIter it_sys(&sys_list);
650  while (auto sys = (KVDBSystem*)it_sys()) {
651  runDB->select_data("Available_Runs,Systems", "run,index", Form("system = '%s'", sys->GetName()), true);
652  std::map<int, int> nruns;
653  ULong64_t events = 0;
654  while (runDB->get_next_result()) {
655  auto run = (*runDB)["Available_Runs"]["run"].get_data<int>();
656  auto index = (*runDB)["Available_Runs"]["index"].is_null() ? -1 : (*runDB)["Available_Runs"]["index"].get_data<int>();
657  if (!db->GetDBRunFile({run, index}).IsBad()) {
658  ++nruns[run];
659  events += db->GetDBRunFile({run, index}).GetEvents();
660  }
661  }
662  sys->SetNumberRuns(nruns.size());
663  sys->SetEvents(events);
664  }
665 
666  //sort list of systems in order of increasing run number
667  if (sys_list.GetSize() > 1)
668  sys_list.Sort();
669 #endif
670  return sys_list;
671 }
672 
673 
674 
677 
679 {
680  // \return list of systems corresponding to given runfiles
681  KVExpDB* db = fDataSet->GetDataBase("minimal");
682  if (!db)
683  return {};
684  KVUniqueNameList syslist;
685  for (auto& ri : rl) {
686  KVDBRun* r{nullptr};
687  KVDBSystem* s{nullptr};
688  if ((r = db->GetDBRun(ri.run())) && (s = r->GetSystem()))
689  syslist.Add(s);
690  }
691  return syslist;
692 }
693 
694 
695 
702 
704 {
705  //\param[in] systol pointer to system description in experimental database
706  //
707  //\return sorted list of available run files (KVRunFile objects) for the given system.
708  //
709  // \note 'bad' runfiles are excluded
710 
711  KVList sys_list;
712 
713  KVExpDB* db = fDataSet->GetDataBase("minimal");
714  std::unique_ptr<KVExpDB> garbage_db;
715  if (!db) {
716  db = new KVExpDB;
717  garbage_db.reset(db);//clean up
718  }
719 #ifdef WITH_RSQLITE
720  auto runDB = OpenAvailableRunsFile();
721 
722  // list of runfiles for given system
723  runDB->select_data("Available_Runs,Systems", "run,index,filename,date,version,username", Form("system = '%s'", systol->GetName()), true);
724  while (runDB->get_next_result()) {
725  auto a_run = db->GetDBRun((*runDB)["Available_Runs"]["run"].get_data<int>());
726  auto run = a_run->GetNumber();
727  std::optional<int> index = ((*runDB)["Available_Runs"]["index"].is_null() ?
728  std::nullopt : std::optional<int>((*runDB)["Available_Runs"]["index"].get_data<int>()));
729  KVDatime fDatime((*runDB)["Available_Runs"]["date"].get_data<TString>(), KVDatime::kSQL);
730  KVString kvversion = (*runDB)["Available_Runs"]["version"].get_data<KVString>();
731  KVString username = (*runDB)["Available_Runs"]["username"].get_data<KVString>();
732  KVString filename = (*runDB)["Available_Runs"]["filename"].get_data<KVString>();
733  if (IsCalled("raw")) {
734  // for raw data files, use the actual date/time of the start of data taking in the database
735  TString start_date = a_run->GetRunFile({run, index}).GetStartDate();
736  if (start_date != "") fDatime.Set(start_date);
737  }
738  if (!db->GetDBRunFile({run, index}).IsBad())
739  sys_list.Add(new KVRunFile(a_run, {run, index}, filename, fDatime, kvversion, username));
740  }
741 
742  //sort list of runs in order of increasing run number
743  if (sys_list.GetSize() > 1)
744  sys_list.Sort();
745 #endif
746  return sys_list;
747 }
748 
749 
750 
755 
756 void KVAvailableRunsFile::UpdateInfos(const run_index_t& run, const KVString& filename, const KVString& kvversion, const KVString& username)
757 {
758  // Call this method to update informations on the file "filename" corresponding to run,
759  // by adding/replacing the KV version and username read from the file itself (not necessarily
760  // corresponding to current KV version and username)
761 #ifdef WITH_RSQLITE
762  auto runDB = OpenAvailableRunsFile();
763 
764  auto selection = SelectRunAndOrIndex(run) + " AND " + SelectFileName(filename);
765 
766  (*runDB)["Available_Runs"]["version"] = kvversion;
767  (*runDB)["Available_Runs"]["username"] = username;
768  runDB->update("Available_Runs", "version,username", selection);
769 #endif
770 }
771 
772 
773 
776 
777 void KVAvailableRunsFile::Remove(const run_index_t& run, const KVString& filename)
778 {
779  //Remove from the db ALL entries corresponding to the given run/index (and filename if given)
780 
781 #ifdef WITH_RSQLITE
782  auto runDB = OpenAvailableRunsFile();
783 
784  auto selection = SelectRunAndOrIndex(run);
785  if (!filename.IsNull()) selection += " AND " + SelectFileName(filename);
786 
787  runDB->delete_rows_in_table("Available_Runs", selection);
788 #endif
789 }
790 
791 
792 
793 
797 
798 void KVAvailableRunsFile::Add(const run_index_t& run, const KVString& filename)
799 {
800  //Add to the file an entry corresponding to this run, assumed to be present in the repository
801  //with the given filename.
802 
803 #ifdef WITH_RSQLITE
804  auto runDB = OpenAvailableRunsFile();
805 
806  insert_runfile_into_database(fDataSet->GetRepository(), filename, KVDatime(), runDB.get(), run, fDataSet->GetDataBase("minimal")->GetDBRun(run.run()), true);
807 #endif
808 }
809 
810 
811 
814 
815 std::forward_list<run_index_t> KVAvailableRunsFile::CheckMultiRunfiles()
816 {
817  //Returns a list with all run/indexes for which more than one file is in the available runs db
818 
819  std::forward_list<run_index_t> multiruns;
820 #ifdef WITH_RSQLITE
821  auto runDB = OpenAvailableRunsFile();
822 
823  runDB->select_data("Available_Runs", "run,index,COUNT(*)", "", false, "GROUP BY run, index HAVING COUNT(*)>1");
824 
825  while (runDB->get_next_result()) {
826  multiruns.push_front({(*runDB)["Available_Runs"]["run"].get_data<int>(),
827  ((*runDB)["Available_Runs"]["index"].is_null() ?
828  std::nullopt : std::optional<int>((*runDB)["Available_Runs"]["index"].get_data<int>()))});
829  }
830 #endif
831  return multiruns;
832 }
833 
834 
835 
836 
844 
846 {
847  //Returns list of available run/indexes for this data type.
848  //
849  //If 'sys' gives the address of a valid database reaction system, only files
850  //corresponding to the system will be included.
851  //
852  //Note that runfiles which are considered to be 'bad' are excluded
853 
854  TString selection, tables("Available_Runs");
855  if (sys) {
856  selection = Form("system = '%s'", sys->GetName());
857  tables += ",Systems";
858  }
859 
860  KVExpDB* db = fDataSet->GetDataBase("minimal");
861  std::unique_ptr<KVExpDB> garbage_db;
862  if (!db) {
863  db = new KVExpDB;
864  garbage_db.reset(db);//clean up
865  }
867 #ifdef WITH_RSQLITE
868  auto runDB = OpenAvailableRunsFile();
869 
870  runDB->select_data(tables, "run,index", selection);
871  while (runDB->get_next_result()) {
872  auto run = (*runDB)["Available_Runs"]["run"].get_data<int>();
873  auto index = (*runDB)["Available_Runs"]["index"].is_null() ? -1 : (*runDB)["Available_Runs"]["index"].get_data<int>();
874  if (!db->GetDBRunFile({run, index}).IsBad())
875  l.Add({run, index});
876  }
877 #endif
878  return l;
879 }
880 
881 
882 
889 
891 {
892  // Filename of file containing information on available runs
893  // i.e. [repository].available_runs.[dataset subdir].[dattype subdir].sqlite
894  //
895  // If [dataset subdir] contains "/" (i.e. if data is grouped into subdirectories)
896  // we replace them by "_"
897 
899  if (!fDataSet) {
900  Error("GetFileName", "Dataset has not been set for this file.");
901  filename = "";
902  }
903  else {
904  KVString datapath = fDataSet->GetDataPathSubdir();
905  datapath.ReplaceAll("/", "_");
906  filename.Form("%s.available_runs.%s.%s.sqlite", fDataSet->GetRepository()->GetName(), datapath.Data(),
908  }
909  return filename;
910 }
911 
912 
913 
928 
930 {
931  // Returns the full path to the directory where the available runs file is stored.
932  // This is by default the same directory where the dataset files are stored.
933  // However, if KaliVeda was installed using a GNU-style directory layout
934  // (possibly in the system directories, e.g. Ubuntu packages)
935  // then the path will be the user's working directory + dataset name
936  //
937  // Alternatively, by setting the config variable
938  // KVAvailableRunsFile.RunFileDirectory: /some/path
939  //
940  // files will be stored/looked for in
941  // /some/path/[dataset]
942  //
943  // You can use environment variables - $(VAR) - in the path
944 
945  KVString filepath;
946  if (!fDataSet) {
947  Error("GetFilePath", "Dataset has not been set for this file.");
948  filepath = "";
949  }
950  else {
951  TString p = gEnv->GetValue("KVAvailableRunsFile.RunFileDirectory", "");
952  if (p == "") {
953  // no user-defined run file directory
954  if (is_gnuinstall()) {
955  // GNU-style install: use working directory
956  filepath = GetWORKDIRFilePath(fDataSet->GetName());
957  }
958  else
959  filepath = fDataSet->GetDataSetDir();
960  }
961  else {
963  AssignAndDelete(filepath, gSystem->ConcatFileName(p.Data(), fDataSet->GetName()));
964  }
965  }
966  return filepath;
967 }
968 
969 
970 
974 
976 {
977  // Return the full path on the local machine to the file
978  // used to store information on available runs
979 
980  KVString path;
982  return path;
983 }
984 
985 
986 
991 
993 {
994  // Check that the directory given by GetFilePath() exists and is writable
995  // If it does not exist, it will be created if possible
996  // If it exists but is not writable, or cannot be created, returns kFALSE.
997 
998  if (gSystem->AccessPathName(GetFilePath(), kFileExists)) { // directory does not exist
999  if (gSystem->mkdir(GetFilePath(), kTRUE) == -1) {
1000  Error("CheckDirectoryForAvailableRunsFile", "cannot create directory %s - check access permissions", GetFilePath().Data());
1001  return kFALSE;
1002  }
1003  // set access permissions on created directory
1004  gSystem->Chmod(GetFilePath(), 0775);
1005  }
1006  if (gSystem->AccessPathName(GetFilePath(), kWritePermission)) { // directory is not writable
1007  Error("CheckDirectoryForAvailableRunsFile", "directory %s is not writable - check access permissions", GetFilePath().Data());
1008  return kFALSE;
1009  }
1010  return kTRUE;
1011 }
1012 
1013 
1014 
1016 
1017 std::unique_ptr<DataBase> KVAvailableRunsFile::OpenAvailableRunsFile(bool called_by_update)
1018 {
1019 #ifdef WITH_RSQLITE
1022  auto db = std::make_unique<KVSQLite::database>(GetFullPathToAvailableRunsFile());
1023  if (!db->good()) {
1024  Error("OpenAvailableRunsFile", "Failed to open/create sqlite database file %s", GetFullPathToAvailableRunsFile().Data());
1025  db.reset(nullptr);
1026  return db;
1027  }
1028  if (making_new_db) {
1029  // set access permissions on database file
1031 
1032  // create systems table
1033  KVSQLite::table sys_tab("Systems");
1035  sys_tab.primary_key("id");
1036  sys_tab.add_column("system", KVSQLite::column_type::TEXT).NOT_NULL().UNIQUE();
1037  auto& t = db->add_table(sys_tab);
1038  // add default 'unknown' system (which will have id=1)
1039  t.prepare_insert_single_row();
1040  t["system"] = "unknown";
1041  t.insert_single_row();
1042 
1043  // create runs table
1044  KVSQLite::table run_tab("Available_Runs");
1046  run_tab.primary_key("id");
1048  run_tab.add_column("index", KVSQLite::column_type::INTEGER);
1049  run_tab.add_column("filename", KVSQLite::column_type::TEXT).NOT_NULL();
1050  run_tab.add_column("date", KVSQLite::column_type::TEXT).NOT_NULL();
1051  run_tab.add_column("version", KVSQLite::column_type::TEXT);
1052  run_tab.add_column("username", KVSQLite::column_type::TEXT);
1053  run_tab.add_column("sys_id", KVSQLite::column_type::INTEGER).NOT_NULL();
1054  run_tab.foreign_key("sys_id", "Systems", "id");
1055 
1056  db->add_table(run_tab);
1057 
1058  if (!called_by_update) Update(db);
1059  }
1060  return db;
1061 #else
1062  return {};
1063 #endif
1064 }
1065 
1066 
1067 
1073 
1075 {
1076  // return kTRUE if the given file for this runfile is lacking some information
1077  // e.g. the KV version and username
1078  //
1079  // N.B.: if no file is known for this run, we return kFALSE
1080 #ifdef WITH_RSQLITE
1081  auto runDB = OpenAvailableRunsFile();
1082  auto selection = SelectRunAndOrIndex(run) + " AND " + SelectFileName(filename);
1083  runDB->select_data("Available_Runs", "run,version", selection);
1084  while (runDB->get_next_result()) {
1085  if ((*runDB)["Available_Runs"]["version"].is_null()) return true;
1086  }
1087 #endif
1088  return false;
1089 }
1090 
1091 
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:1674
static const Char_t * GetWORKDIRFilePath(const Char_t *namefile="")
Definition: KVBase.cpp:121
static bool is_gnuinstall()
Definition: KVBase.h:275
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:877
void Warning(const char *method, const char *msgfmt,...) const override
Definition: KVBase.cpp:1661
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:1507
const Char_t * GetDataSetDir() const
Definition: KVDataSet.cpp:748
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:290
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:155
KVDBRun * GetDBRun(Int_t number) const
Definition: KVExpDB.h:135
const KVDBRunFile & GetDBRunFile(const run_index_t &r) const
Definition: KVExpDB.h:139
Int_t GetIndexMultiplier() const
Definition: KVExpDB.h:232
Bool_t HasIndexMultiplier() const
Definition: KVExpDB.h:228
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)