Belle II Software  release-08-01-10
b2file-metadata-add.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <framework/logging/Logger.h>
10 #include <framework/core/FileCatalog.h>
11 #include <framework/dataobjects/FileMetaData.h>
12 
13 #include <TFile.h>
14 #include <TTree.h>
15 #include <TError.h>
16 
17 #include <boost/program_options.hpp>
18 
19 #include <string>
20 #include <iostream>
21 
22 using namespace std;
23 using namespace Belle2;
24 namespace prog = boost::program_options;
25 
26 int main(int argc, char* argv[])
27 {
28  std::string fileName;
29  std::string lfn, gt;
30  std::vector<std::string> dataDescriptions;
31  // define command line options
32  prog::options_description options("Options");
33  options.add_options()
34  ("help,h", "print all available options")
35  ("file", prog::value<string>(&fileName), "file name")
36  ("lfn,l", prog::value<string>(&lfn), "logical file name")
37  ("globalTag,g", prog::value<string>(&gt), "global tag")
38  ("description,d", prog::value<std::vector<std::string>>(&dataDescriptions),
39  "data description to set of the form key=value. If the argument does not contain an equal sign it's interpeted as a key to delete from the dataDescriptions")
40  ;
41 
42  prog::positional_options_description posOptDesc;
43  posOptDesc.add("file", -1);
44 
45  prog::variables_map varMap;
46  prog::store(prog::command_line_parser(argc, argv).
47  options(options).positional(posOptDesc).run(), varMap);
48  prog::notify(varMap);
49 
50  // check for help option
51  if (varMap.count("help")) {
52  cout << "Usage: " << argv[0] << " [OPTIONS] [FILE]\n";
53  cout << "Add/edit LFN in given file or modify the data description stored in the file, also update file catalog.\n\n";
54  cout << options << endl;
55  return 0;
56  }
57 
58  // check parameters
59  if (!varMap.count("file")) {
60  B2ERROR("The filename is missing.");
61  return 1;
62  }
63  if (!varMap.count("lfn") && !varMap.count("globalTag") && !varMap.count("description")) {
64  B2ERROR("No metadata modificaton was requested, nothing to do");
65  return 1;
66  }
67 
68  // open the root file
69  gErrorIgnoreLevel = kError;
70  TFile* file = TFile::Open(fileName.c_str(), "UPDATE");
71  if (!file || !file->IsOpen()) {
72  B2ERROR("Failed to open the file " << fileName);
73  return 1;
74  }
75 
76  // read the FileMetaData object or create a new one if it doesn't exist
77  FileMetaData* fileMetaData = nullptr;
78  auto* tree = dynamic_cast<TTree*>(file->Get("persistent"));
79  TTree* newTree = nullptr;
80  if (!tree) {
81  fileMetaData = dynamic_cast<FileMetaData*>(file->Get("FileMetaData"));
82  if (!fileMetaData) {
83  B2WARNING("Failed to get persistent tree in the file " << fileName);
84  tree = new TTree("persistent", "persistent");
85  fileMetaData = new FileMetaData;
86  tree->Branch("FileMetaData", &fileMetaData);
87  newTree = tree;
88  }
89  } else {
90  tree->SetBranchAddress("FileMetaData", &fileMetaData);
91  newTree = tree->CloneTree(0);
92  tree->GetEntry(0);
93  }
94 
95  if (!fileMetaData) {
96  B2ERROR("Failed to load FileMetaData from file " << fileName);
97  return 1;
98  }
99 
100  // remember old lfn in case this file was registered in file catalog
101  const std::string oldLFN = fileMetaData->getLfn();
102 
103  // update the IDs and write the updated FileMetaData to the file
104  if (varMap.count("lfn")) fileMetaData->setLfn(lfn);
105  if (varMap.count("globalTag")) fileMetaData->setDatabaseGlobalTag(gt);
106  if (!dataDescriptions.empty()) {
107  for (const auto& keyvalue : dataDescriptions) {
108  size_t pos = keyvalue.find('=');
109  if (pos == std::string::npos) {
110  // no '=' in -d argument, assume deletion
111  fileMetaData->removeDataDescription(keyvalue);
112  } else {
113  const std::string key = keyvalue.substr(0, pos);
114  const std::string value = keyvalue.substr(pos + 1);
115  fileMetaData->setDataDescription(key, value);
116  }
117  }
118  }
119 
120 
121  if (newTree) {
122  newTree->Fill();
123  newTree->Write(newTree->GetName(), TObject::kWriteDelete);
124  } else {
125  fileMetaData->Write("FileMetaData");
126  }
127 
128  // properly close file
129  file->Close();
130 
131  // update the local file catalog but only *if* the file was already registered
132  std::string oldPFN = oldLFN;
133  FileMetaData localMetaData;
134  if (FileCatalog::Instance().getMetaData(oldPFN, localMetaData)) {
135  localMetaData = *fileMetaData;
136  FileCatalog::Instance().registerFile(fileName, localMetaData, oldLFN);
137  }
138  return 0;
139 }
Metadata information about a file.
Definition: FileMetaData.h:29
void removeDataDescription(const std::string &key)
remove an existing data description
Definition: FileMetaData.h:217
const std::string & getLfn() const
Logical file name getter.
Definition: FileMetaData.h:37
void setDatabaseGlobalTag(const std::string &globalTag)
Set the database global tag used when creating this file.
Definition: FileMetaData.h:208
void setLfn(const std::string &lfn)
Setter for LFN.
Definition: FileMetaData.h:139
void setDataDescription(const std::string &key, const std::string &value)
describe the data, if the key exists contents will be overwritten.
Definition: FileMetaData.h:214
Abstract base class for different kinds of events.
int main(int argc, char **argv)
Run all tests.
Definition: test_main.cc:91