Belle II Software development
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
22using namespace std;
23using namespace Belle2;
24namespace prog = boost::program_options;
25
26int 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}
static FileCatalog & Instance()
Static method to get a reference to the FileCatalog instance.
Definition: FileCatalog.cc:23
virtual bool registerFile(const std::string &fileName, FileMetaData &metaData, const std::string &oldLFN="")
Register a file in the (local) file catalog.
Definition: FileCatalog.cc:90
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.
STL namespace.