REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
Loading...
Searching...
No Matches
TRestDataBase.cxx
1#include "TRestDataBase.h"
2
3#include <errno.h>
4#include <fcntl.h>
5#include <stdio.h>
6#include <sys/file.h>
7#include <sys/stat.h>
8#include <sys/types.h>
9#include <unistd.h>
10
11#include <chrono>
12#include <thread>
13
14#include "TClass.h"
15#include "TRestStringHelper.h"
16#include "TRestStringOutput.h"
17#include "TRestTools.h"
18#include "TSystem.h"
19#include "TUrl.h"
20
21using namespace std;
22
63
64DBEntry::DBEntry(vector<string> items) {
65 this->runNr = atoi(items[0].c_str());
66 this->type = items[1];
67 this->tag = items[2];
68 this->description = items[3];
69 this->version = items[4];
70}
71
73 fDataEntries.clear();
74 string metaFilename = REST_PATH + "/data/dataURL";
75 if (!TRestTools::fileExists(metaFilename)) {
76 return;
77 } else {
78 vector<int> result;
79 ifstream infile(metaFilename);
80 string s;
81 while (TRestTools::GetLine(infile, s)) {
82 DBEntry info;
83 vector<string> items = Split(s, "\t", true);
84 if (items.size() <= 2) continue;
85 for (auto item : items) {
86 vector<string> pair = Split(item, "=", true);
87 if (pair.size() == 2) {
88 if (pair[0] == "run")
89 info.runNr = atoi(pair[1].c_str());
90 else if (pair[0] == "type")
91 info.type = pair[1];
92 else if (pair[0] == "tag")
93 info.tag = pair[1];
94 else if (pair[0] == "description")
95 info.description = pair[1];
96 else if (pair[0] == "version")
97 info.version = pair[1];
98 else if (pair[0] == "value")
99 info.value = pair[1];
100 }
101 }
102
103 fDataEntries.push_back(info);
104 }
105 }
106}
107
108DBFile DBFile::ParseFile(string _filename) {
109 DBFile file;
110 file.filename = _filename;
111 auto _fullname = TRestTools::ToAbsoluteName(_filename);
112
113 struct stat buf;
114 int result = stat(_fullname.c_str(), &buf);
115
116 if (result != 0) {
117 RESTError << "DBFile::ParseFile: Failed to load file \"" << _fullname << "\"!" << RESTendl;
118 } else {
119 file.fileSize = buf.st_size;
120 file.evtRate = 0;
121 file.quality = true;
122 file.start = buf.st_ctime;
123 file.stop = buf.st_mtime;
124 string sha1result = TRestTools::Execute("sha1sum " + _fullname);
125 string sha1 = Split(sha1result, " ")[0];
126 if (sha1.size() == 40) {
127 for (int i = 0; i < 40; i++) {
128 file.sha1sum[i] = sha1[i];
129 }
130 file.sha1sum[40] = 0;
131 }
132 }
133 return file;
134}
135
136void DBFile::Print() {
137 cout << "----DBFile struct----" << endl;
138 cout << "size: " << fileSize << endl;
139 cout << "event rate: " << evtRate << endl;
140 cout << "sha1sum: " << sha1sum << endl;
141 cout << "quality: " << quality << endl;
142 cout << "start time: " << ToDateTimeString(start) << endl;
143 cout << "stop time: " << ToDateTimeString(stop) << endl;
144}
145
147 auto url = getenv("REST_DBURL");
148 if (url != nullptr) {
149 fConnectionString = url;
150 }
151 Initialize();
152}
153
161 int runNr = 1;
162 string runFilename = REST_USER_PATH + "/runNumber";
163 bool fileExist = TRestTools::fileExists(runFilename);
164 int fd = open(runFilename.c_str(), O_RDWR | O_CREAT, 0666);
165 if (fd == -1) {
166 RESTError << "Error opening file " << runFilename << strerror(errno) << RESTendl;
167 return -1;
168 }
169 flock(fd, LOCK_EX);
170 if (!fileExist) {
171 string newRun = to_string(runNr) + "\n";
172 if (write(fd, newRun.c_str(), newRun.size()) == -1)
173 RESTError << "Error writing file " << runFilename << strerror(errno) << RESTendl;
174 fsync(fd);
175 } else {
176 lseek(fd, 0, SEEK_SET);
177 char buffer[64] = {0};
178 ssize_t bytesReaded = read(fd, buffer, sizeof(buffer) - 1);
179 if (bytesReaded > 0) runNr = std::atoi(buffer);
180 }
181 flock(fd, LOCK_UN);
182 close(fd);
183 // the number recorded in "runNumber" file is for the next run, we subtract 1 to get the latest run.
184 return runNr - 1;
185}
186
199int TRestDataBase::set_run(DBEntry info, bool overwrite) {
200 int newRunNr = -1;
201 if (info.runNr == 0) {
202 newRunNr = get_lastrun() + 1;
203 } else if (info.runNr > 0) {
204 newRunNr = info.runNr;
205 } else {
206 return -1;
207 }
208
209 string runFilename = REST_USER_PATH + "/runNumber";
210 if (TRestTools::isPathWritable(REST_USER_PATH)) {
211 int fd = open(runFilename.c_str(), O_RDWR | O_CREAT, 0666);
212 if (fd == -1) {
213 RESTError << "Error opening file " << runFilename << strerror(errno) << RESTendl;
214 return -1;
215 }
216 flock(fd, LOCK_EX);
217 string newRun = to_string(newRunNr + 1) + "\n";
218 if (write(fd, newRun.c_str(), newRun.size()) == -1)
219 RESTError << "Error writing file " << runFilename << strerror(errno) << RESTendl;
220 fsync(fd);
221 flock(fd, LOCK_UN);
222 close(fd);
223
224 } else {
225 RESTWarning << "runNumber file not writable. auto run number "
226 "increment is disabled"
227 << RESTendl;
228 }
229 return newRunNr;
230}
231
236DBEntry TRestDataBase::query_data(DBEntry _info) {
237 vector<DBEntry> match;
238 if (_info.runNr <= 0 && _info.type == "" && _info.tag == "" && _info.description == "" &&
239 _info.version == "")
240 return DBEntry();
241
242 for (unsigned int i = 0; i < fDataEntries.size(); i++) {
243 DBEntry info = fDataEntries[i];
244
245 bool runmatch = (_info.runNr == 0 || info.runNr == 0 || info.runNr == _info.type);
246 bool typematch = (_info.type == "" || info.type == _info.type);
247 bool tagmatch = (_info.tag == "" || info.tag == _info.tag);
248 bool descriptionmatch = (_info.description == "" || info.description == _info.description);
249 bool versionmatch = (_info.version == "" || info.version == _info.version);
250 bool valuematch = (_info.value == "" || info.value == _info.value);
251
252 if (runmatch && typematch && tagmatch && descriptionmatch && versionmatch && valuematch) {
253 match.push_back(info);
254 }
255 }
256
257 if (match.size() == 1) {
258 return match[0];
259 } else if (match.size() > 1) {
260 RESTWarning << "multiple metadata found! returning the first!" << RESTendl;
261 return match[0];
262 } else {
263 return DBEntry();
264 }
265 return DBEntry();
266}
267
268// int TRestDataBase::add_metadata(DBEntry info, string url, bool overwrite) {
269// if (TRestTools::isPathWritable(REST_USER_PATH)) {
270// cout << "error! path not writable" << endl;
271// return -1;
272// }
273//
274// string metaFilename = REST_USER_PATH + "/dataURL";
275//
276// if (info.runNr == 0) {
277// info.runNr = get_lastmetadata();
278// }
279// fDataEntries.push_back({info, url});
280//
281// std::ofstream file(metaFilename, std::ios::app);
282// file << "\"" << info.runNr << "\" ";
283// file << "\"" << info.type << "\" ";
284// file << "\"" << info.tag << "\" ";
285// file << "\"" << info.description << "\" ";
286// file << "\"" << info.version << "\" ";
287// file << "\"" << url << "\" ";
288// file << endl;
289// file.close();
290//
291// return info.runNr;
292//}
293//
virtual void Initialize()
default: read the dataURL file
TRestDataBase()
default constructor, setting fConnectionString according to the env
virtual int get_lastrun()
get the latest run id in database
virtual DBEntry query_data(DBEntry info)
virtual int set_run(DBEntry info, bool overwrite=true)
add/update a run, with run info as struct DBEntry. returns the added run id
static std::string Execute(std::string cmd)
Executes a shell command and returns its output in a string.
static bool fileExists(const std::string &filename)
Returns true if the file (or directory) with path filename exists.
static bool isPathWritable(const std::string &path)
Returns true if the path given by argument is writable.
static std::istream & GetLine(std::istream &is, std::string &t)
It reads the next line from the incoming istream and puts it in the string argument t....
static std::string ToAbsoluteName(const std::string &filename)
It takes a path and returns its absolute path.
std::vector< std::string > Split(std::string in, std::string separator, bool allowBlankString=false, bool removeWhiteSpaces=false, int startPos=-1)
Split the input string according to the given separator. Returning a vector of fragments.
std::string ToDateTimeString(time_t time)
Format time_t into string.