13map<int, string>
const Errors{{401,
"Unauthorized Access (check user login and password)"},
14 {403,
"Token invalid or expired"},
15 {404,
"Requested Data not found"},
16 {409,
"Incorrect Database Request (e.g. violating constraints)"},
17 {422,
"Incorrect Input Request"},
18 {500,
"Internal Server Error"},
19 {503,
"Service Unavaialble"},
20 {504,
"Server Timeout"}};
24 auto it =
Errors.find(error_id);
25 return it !=
Errors.end() ? it->second :
"";
30 unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
31 std::mt19937 engine(seed);
32 std::uniform_int_distribution<int>
dist(1, 1000000000);
33 int randomNum =
dist(engine);
92 return std::to_string(
iValue);
96 return std::to_string(
fValue);
106 curl_global_init(CURL_GLOBAL_DEFAULT);
109 throw runtime_error(
"CURL initialisation failed");
122 curl_global_cleanup();
125std::string
ReplaceAll(std::string str,
const std::string& from,
const std::string& to)
127 size_t start_pos = 0;
128 while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
129 str.replace(start_pos, from.length(), to);
130 start_pos += to.length();
137 string conditions =
"filepath?";
138 for (
const auto& cond : file_conditions) {
139 switch (cond->getFileAttribute()) {
141 conditions +=
"period_number";
144 conditions +=
"run_number";
147 conditions +=
"run_type";
150 conditions +=
"start_datetime";
153 conditions +=
"end_datetime";
156 conditions +=
"beam_particle";
159 conditions +=
"target_particle";
162 conditions +=
"energy";
165 conditions +=
"field_voltage";
168 conditions +=
"start_event";
171 conditions +=
"end_event";
174 conditions +=
"event_count";
177 conditions +=
"file_size";
182 switch (cond->getMatchCriteria()) {
184 conditions = conditions +
"=|" + cond->getValueAsString();
187 conditions = conditions +
"=" + cond->getValueAsString();
190 conditions = conditions +
"!=" + cond->getValueAsString();
193 conditions = conditions +
"=" + cond->getValueAsString() +
"|";
196 conditions = conditions +
"=*" + cond->getValueAsString() +
"*";
200 conditions.erase(conditions.size() - 1, 1);
201 conditions =
ReplaceAll(conditions,
string(
" "),
string(
"%20"));
204 if (result ==
"ERROR: Failed to authenticate\n") {
207 if (result ==
"ERROR: Can't get files list (DIRAC API ERROR)\n") {
210 if (result ==
"ERROR: Can't get files list\n") {
213 if (result.find(
"ERROR") != std::string::npos)
215 result = result.erase(0, 2);
216 size_t delim = result.find(
"\",\"");
217 while (delim != string::npos) {
218 filepaths.push_back(result.substr(0, delim));
219 result.erase(0, delim + 3);
220 delim = result.find(
"\",\"");
222 delim = result.find(
"\"]");
223 filepaths.push_back(result.substr(0, delim));
229 string conditions =
"meta?filepath=" + LFN;
231 if (res ==
"ERROR: Failed to authenticate\n") {
234 if (res ==
"ERROR: File not found\n") {
237 if (res ==
"ERROR: Can't get meta (DIRAC API ERROR)\n") {
240 if (res ==
"ERROR: Can't get meta\n") {
243 if (res.find(
"ERROR") != std::string::npos)
245 json result = json::parse(res);
248 for (
auto& [key, value] : result.items()) {
249 if (key ==
"period_number")
251 if (key ==
"run_number")
253 if (key ==
"run_type")
254 file_info.
RunType = value.get<
int>();
255 if (key ==
"start_datetime") {
256 strptime(value.get<
string>().c_str(),
"%a, %d %b %Y %H:%M:%S GMT", &DTtm);
257 strftime(DTbuf,
sizeof DTbuf,
"%Y-%m-%d %H:%M:%S", &DTtm);
260 if (key ==
"end_datetime") {
261 strptime(value.get<
string>().c_str(),
"%a, %d %b %Y %H:%M:%S GMT", &DTtm);
262 strftime(DTbuf,
sizeof DTbuf,
"%Y-%m-%d %H:%M:%S", &DTtm);
265 if (key ==
"beam_particle")
267 if (key ==
"target_particle")
270 file_info.
Energy = value.get<
float>();
271 if (key ==
"field_voltage")
273 if (key ==
"start_event")
275 if (key ==
"end_event")
276 file_info.
EndEvent = value.get<
int>();
277 if (key ==
"event_count")
279 if (key ==
"file_size")
280 file_info.
FileSize = value.get<
float>();
287 string conditions =
"directorymeta?dirpath=" + path;
289 if (res ==
"ERROR: Failed to authenticate\n") {
292 if (res ==
"ERROR: File not found\n") {
295 if (res ==
"ERROR: Can't get meta (DIRAC API ERROR)\n") {
298 if (res ==
"ERROR: Can't get meta\n") {
301 if (res.find(
"ERROR") != std::string::npos)
303 directory_info = res;
309 string conditions =
"checkstatus?";
311 if (result ==
"ERROR: Can't read check status file\n")
313 if (result ==
"ERROR: Failed to authenticate\n")
315 result = result.erase(0, result.find(
"ID=") + 3);
320 int& fc_missing_count,
321 vector<string>& eos_missing,
322 vector<string>& fc_missing)
324 string conditions =
"checkresults?";
326 if (result ==
"ERROR: Can't read check results file\n")
328 if (result ==
"ERROR: Failed to authenticate\n")
330 if (result.find(
"ERROR") != std::string::npos)
333 stringstream stream(result);
334 getline(stream, line);
335 while (getline(stream, line)) {
336 if (line.find(
"Addto count:") != string::npos) {
337 fc_missing_count = stoi(line.erase(0, 12));
340 fc_missing.push_back(line);
342 getline(stream, line);
343 while (getline(stream, line)) {
344 if (line.find(
"Missing count:") != string::npos) {
345 eos_missing_count = stoi(line.erase(0, 14));
348 eos_missing.push_back(line);
355 if (save_path.find(
"root") == 0) {
357 string conditions =
"file_to_xrd?LFN=" + LFN +
"&XRDURL=" + save_path;
359 if (res ==
"ERROR: Failed to authenticate\n")
361 if (res ==
"ERROR: Can't download file from CICC(DIRAC)\n")
363 if (res ==
"ERROR: Can't upload to xrootd path\n")
367 string conditions =
"file?LFN=" + LFN;
374 string conditions =
"pfn?LFN=" + LFN;
376 if (res ==
"ERROR: Failed to authenticate\n") {
379 if (res ==
"ERROR: None found\n") {
382 if (res ==
"ERROR: Can't get PFN\n") {
385 if (res.find(
"ERROR") != std::string::npos)
388 json j = json::parse(res);
392 PFNs = j.get<std::vector<std::string>>();
394 }
catch (
const json::parse_error& e) {
404 fi[
"run_number"] = file_metadata.
RunNumber;
405 fi[
"run_type"] = file_metadata.
RunType;
410 fi[
"energy"] = file_metadata.
Energy;
413 fi[
"end_event"] = file_metadata.
EndEvent;
415 fi[
"file_size"] = file_metadata.
FileSize;
416 string conditions =
"meta?filepath=" + LFN;
418 if (result ==
"ERROR: Can't set meta (DIRAC API ERROR)\n" || result ==
"ERROR: Can't set meta\n")
420 if (result ==
"ERROR: File not found\n")
422 if (result ==
"ERROR: Failed to authenticate\n")
429 set<string> valid_meta_types = {
"INT",
"DATETIME",
"FLOAT",
"VARCHAR(128)"};
430 if (valid_meta_types.find(field_type) == valid_meta_types.end()) {
431 cout <<
" Please, use the valid metadata field type. Like one of this: (INT, DATETIME, FLOAT, VARCHAR(128). "
436 string conditions =
"";
438 conditions =
"metadatafield_directory?fieldname=" + field_name +
"&fieldtype=" + field_type;
440 conditions =
"metadatafield?fieldname=" + field_name +
"&fieldtype=" + field_type;
442 if (result ==
"ERROR: Failed to authenticate\n")
444 if (result ==
"ERROR: Can't set metadata field (DIRAC API ERROR)\n"
445 || result ==
"ERROR: Can't set metadata field\n")
450size_t appendData(
void* contents,
size_t size,
size_t nmemb,
string* data)
452 size_t realsize = size * nmemb;
454 data->append((
char*)contents, realsize);
455 }
catch (std::bad_alloc& e) {
465 ifstream json_file(json_file_path);
466 json full_json = json::parse(json_file);
467 auto it = full_json.find(
"file_path");
468 if (it == full_json.end()) {
469 cout <<
" Please include \"file_path\" field with correct filepath to file in your json, thanks " << endl;
472 string filepath = it.value();
473 full_json.erase(
"file_path");
474 string conditions =
"meta?filepath=" + filepath;
475 string result =
performRequest(conditions, full_json.dump(),
"PUT");
477 if (result ==
"ERROR: Failed to authenticate\n")
479 if (result ==
"ERROR: Can't set meta (DIRAC API ERROR)\n" || result ==
"ERROR: Can't set meta\n")
481 if (result ==
"ERROR: File not found\n")
488 ifstream json_file(json_file_path);
489 json full_json = json::parse(json_file);
490 auto it = full_json.find(
"dir_path");
491 if (it == full_json.end()) {
492 cout <<
" Please include \"dir_path\" field with correct filepath to file in your json, thanks " << endl;
495 string dirpath = it.value();
496 full_json.erase(
"dir_path");
497 string conditions =
"meta?filepath=" + dirpath;
498 string result =
performRequest(conditions, full_json.dump(),
"PUT");
499 if (result ==
"ERROR: Failed to authenticate\n")
501 if (result ==
"ERROR: Can't set meta (DIRAC API ERROR)\n" || result ==
"ERROR: Can't set meta\n")
503 if (result ==
"ERROR: File not found\n")
511 string conditions =
"file?LFN=" + LFN;
522 string conditions =
"meta?filepath=" + LFN;
524 if (result ==
"ERROR: Can't delete metadata (DIRAC API ERROR)\n" || result ==
"ERROR: Can't delete metadata\n")
526 if (result ==
"ERROR: File not found\n")
528 if (result ==
"ERROR: Failed to authenticate\n")
535 string conditions =
"directorymeta?dirpath=" + path;
537 if (result ==
"ERROR: Can't delete metadata (DIRAC API ERROR)\n" || result ==
"ERROR: Can't delete metadata\n")
539 if (result ==
"ERROR: Directory not found\n")
541 if (result ==
"ERROR: Failed to authenticate\n")
548 string conditions =
"metadatafield?fieldname=" + metadatafield_name;
550 if (result ==
"ERROR: Can't delete metadata field (DIRAC API ERROR)\n"
551 || result ==
"ERROR: Can't delete metadata field\n")
553 if (result ==
"ERROR: Failed to authenticate\n")
560 string conditions =
"file?LFN=" + LFN;
562 if (result ==
"ERROR: Can't delete file from CICC (DIRAC API ERROR)\n"
563 || result ==
"ERROR: Can't delete file from CICC\n")
565 if (result ==
"ERROR: Failed to authenticate\n")
572 string conditions =
"meta?filepath=" + LFN;
574 if (res ==
"ERROR: Failed to authenticate\n")
576 if (res ==
"ERROR: File not found\n")
578 if (res ==
"ERROR: Can't get meta (DIRAC API ERROR)\n" || res ==
"ERROR: Can't get meta\n")
587 string conditions =
"isfileexist?filepath=" + LFN;
589 if (res ==
"ERROR: Failed to authenticate\n")
591 if (res ==
"ERROR: Can't check file exist (DIRAC API ERROR)\n" || res ==
"ERROR: Can't check file exist\n")
593 if (res ==
"FALSE\n")
602 string conditions =
"meta?filepath=" + LFN;
604 if (res ==
"ERROR: Failed to authenticate\n") {
605 cout <<
" Sorry, failed to authenticate" << endl;
608 if (res ==
"ERROR: File not found\n") {
609 cout <<
" The file " << LFN <<
" was not found! " << endl;
612 if (res ==
"ERROR: Can't get meta (DIRAC API ERROR)\n" || res ==
"ERROR: Can't get meta\n") {
613 cout <<
" Sorry, we got some errors while getting metadata of your file " << endl;
617 cout <<
" There is no metadata for your file - " << LFN << endl;
620 cout <<
" Here is metadata for your file - " << LFN <<
": " << endl << res << endl;
627 if (res ==
"ERROR: Can't get metadata fields (DIRAC API ERROR)\n" || res ==
"ERROR: Can't get metadata fields\n")
629 if (res ==
"ERROR: Failed to authenticate\n")
631 cout <<
" Metadatafields list: " << endl << res << endl;
635std::string
exec(
const char* cmd)
638 std::string result =
"";
639 FILE* pipe = popen(cmd,
"r");
644 while (fgets(buffer,
sizeof buffer, pipe) != NULL) {
657 vector<string> file_array;
658 if (rest_api_request.find(
"GET") == string::npos) {
663 result =
exec(rest_api_request.c_str());
667 if (result ==
"ERROR: Failed to authenticate\n")
671 result = result.erase(0, 2);
672 size_t delim = result.find(
"\",\"");
673 while (delim != string::npos) {
674 filepaths.push_back(result.substr(0, delim));
675 result.erase(0, delim + 3);
676 delim = result.find(
"\",\"");
678 delim = result.find(
"\"]");
679 filepaths.push_back(result.substr(0, delim));
687 if (res ==
"ERROR: Can't run consistency check (error from running shell script)\n")
689 if (res ==
"ERROR: Failed to authenticate\n")
692 check_id = stoi(res.erase(0, 21));
693 }
catch (
const std::invalid_argument& e) {
700 int& files_without_replicas,
702 int& replicas_without_files)
705 if (res ==
"ERROR: Can't get catalog counters (DIRAC API ERROR)\n" || res ==
"ERROR: Can't get catalog counters\n")
707 if (res ==
"ERROR: Failed to authenticate\n")
709 json metrics = json::parse(res);
710 for (
auto& [key, value] : metrics.items()) {
712 files_count = value.get<
int>();
713 if (key ==
"Files w/o Replicas")
714 files_without_replicas = value.get<
int>();
715 if (key ==
"Replicas")
716 replicas_count = value.get<
int>();
717 if (key ==
"Replicas w/o Files")
718 replicas_without_files = value.get<
int>();
726 string response_string;
729 const char* curl_url = conditions.c_str();
733#ifdef CURLOPT_CA_CACHE_TIMEOUT
734 curl_easy_setopt(
curlInstance, CURLOPT_CA_CACHE_TIMEOUT, 604800L);
737 curl_easy_setopt(
curlInstance, CURLOPT_WRITEDATA, &response_string);
741 struct curl_slist* headers = NULL;
743 headers = curl_slist_append(headers,
"Content-Type: application/json");
746 const char* c_json = json_content.c_str();
747 const char* curl_customRequest = qType.c_str();
748 curl_easy_setopt(
curlInstance, CURLOPT_CUSTOMREQUEST, curl_customRequest);
749 curl_easy_setopt(
curlInstance, CURLOPT_HTTPHEADER, headers);
750 curl_easy_setopt(
curlInstance, CURLOPT_POSTFIELDS, c_json);
754 if (res != CURLE_OK) {
755 fprintf(stderr,
"curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
759 curl_easy_getinfo(
curlInstance, CURLINFO_RESPONSE_CODE, &response_code);
762 curl_easy_getinfo(
curlInstance, CURLINFO_TOTAL_TIME, &elapsed);
764 curl_easy_getinfo(
curlInstance, CURLINFO_EFFECTIVE_URL, &url);
765 cout <<
"DEBUG: CURLINFO_TOTAL_TIME = " << elapsed <<
", CURLINFO_EFFECTIVE_URL = " << string(url) << endl;
770 curl_easy_getinfo(
curlInstance, CURLINFO_TOTAL_TIME, &elapsed);
772 curl_easy_getinfo(
curlInstance, CURLINFO_EFFECTIVE_URL, &url);
773 cout <<
"CURLINFO_TOTAL_TIME = " << elapsed << endl;
776 if ((response_code >= 200) && (response_code < 205)) {
778 cout << qType <<
" request has been succesfully processed " << endl;
780 cout <<
"Request was finished with the following response: " << response_string << endl;
782 cout <<
"ERROR: Sending request to '" <<
ServiceUrl <<
"' has been failed with code = " << response_code
783 <<
" and message: " << endl
784 << response_string << endl;
785 curl_slist_free_all(headers);
786 return "ERROR: error code: " + to_string(response_code);
788 curl_slist_free_all(headers);
789 return response_string;
810 size_t total = size * nmemb;
811 char* chunk =
static_cast<char*
>(contents);
819 data->
buffer.append(chunk, total);
821 if (data->
buffer.size() >= 5) {
822 if (data->
buffer.compare(0, 5,
"ERROR") == 0) {
829 if (data->
file && data->
file->is_open()) {
839 if (data->
file && data->
file->is_open()) {
840 data->
file->write(chunk, total);
848 std::ofstream file(savePath, std::ios::binary);
849 if (!file.is_open()) {
857 const char* curl_url = conditions.c_str();
860 curl_easy_setopt(
curlInstance, CURLOPT_WRITEDATA, &data);
861 curl_easy_setopt(
curlInstance, CURLOPT_FAILONERROR, 1L);
867 curl_easy_getinfo(
curlInstance, CURLINFO_RESPONSE_CODE, &http_code);
873 std::remove(savePath.c_str());
874 if (data.
error_msg ==
"ERROR: Failed to authenticate\n")
880 if (res != CURLE_OK) {
881 cout <<
"CURL error: " << curl_easy_strerror(res) << endl;
882 std::remove(savePath.c_str());
891#define FC_HAS_CURL_MIME (LIBCURL_VERSION_NUM >= 0x073800)
892#define FC_HAS_CURL_XFERINFO (LIBCURL_VERSION_NUM >= 0x072000)
894#if FC_HAS_CURL_XFERINFO
895int progressCallback(
void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
898int progressCallback(
void* clientp,
double dltotal,
double dlnow,
double ultotal,
double ulnow)
902 double percent = (double)ulnow / ultotal * 100;
903 std::cout <<
"\rUploading: " << int(percent) <<
"%" << std::flush;
912 struct curl_mimepart* part = curl_mime_addpart(mime);
913 curl_mime_name(part,
"file");
914 curl_mime_filedata(part, filepath.c_str());
916 struct curl_httppost* formpost =
nullptr;
917 struct curl_httppost* lastptr =
nullptr;
918 curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME,
"file",
919 CURLFORM_FILE, filepath.c_str(),
923 std::string response;
925 const char* curl_url = conditions.c_str();
932 curl_easy_setopt(
curlInstance, CURLOPT_HTTPPOST, formpost);
935 curl_easy_setopt(
curlInstance, CURLOPT_WRITEDATA, &response);
936 curl_easy_setopt(
curlInstance, CURLOPT_FAILONERROR, 1L);
939 curl_easy_setopt(
curlInstance, CURLOPT_LOW_SPEED_LIMIT, 1024L);
940 curl_easy_setopt(
curlInstance, CURLOPT_LOW_SPEED_TIME, 60L);
942#if FC_HAS_CURL_XFERINFO
952 curl_easy_getinfo(
curlInstance, CURLINFO_RESPONSE_CODE, &http_code);
955 curl_mime_free(mime);
957 curl_formfree(formpost);
961 if (res != CURLE_OK) {
962 return http_code ? -http_code : -500;
966 if (response.compare(0, 5,
"ERROR") == 0) {
967 if (response ==
"ERROR: Failed to authenticate\n")
969 if (response ==
"ERROR: No file uploaded\n" or response ==
"ERROR: Empty filename\n")
vector< Double_t > dist(vector< Double_t > qp, Double_t mu)
map< int, string > const Errors
std::string exec(const char *cmd)
size_t appendData(void *contents, size_t size, size_t nmemb, string *data)
int progressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
string const GetErrorString(int error_id)
std::string ReplaceAll(std::string str, const std::string &from, const std::string &to)
int CheckFileExist(string LFN)
Function to check whether file exist or not.
int DeleteDirectoryInfo(string path)
Function to delete metadata for the directory at specific path.
int AddDirectoryInfo(string json_file_path)
Function to add directory metadata to the File Catalog using input JSON directory path.
int DeleteFile(string LFN)
Function to delete file from the File Catalog and CICC.
int AddMetadataField(string field_name, string field_type, bool isDirectoryType=true)
Function to add new metadata field to the File Catalog.
int FileCatalogRequest(string rest_api_request, vector< string > &filepaths)
Function for searching for files matching specific metadata in the File Catalog using REST API reques...
int FileCatalogStats(int &files_count, int &files_without_replicas, int &replicas_count, int &replicas_without_files)
Function to collect summary statistics on the File Catalog.
int UploadFile(string conditions, string filepath)
int PrintFileInfo(string LFN)
Function to print metadata for the file stored at the given location.
int GetDirectoryInfo(string path, string &directory_info)
Function to get metadata of the directory at the given path.
int DeleteMetadataField(string metadatafield_name)
Function to delete metadata field from the File Catalog.
int FileCatalogConsistencyCheck()
Function to perform a consistency check in the File Catalog.
int CheckFileInfo(string LFN)
Function to check metadata for the file with specific LFN.
int GetFile(string LFN, string save_path)
Function to download file from the CICC (Dirac FC).
int GetFileList(vector< unique_ptr< FileCondition > > file_conditions, vector< string > &filepaths)
Function for searching for file metadata in the File Catalog using specified conditions.
int UpdateFileInfo(string LFN, FileInfo file_metadata)
Function to update metadata for the file with specific LFN.
int DeleteFileInfo(string LFN)
Function to delete metadata for the file with specific LFN.
int GetConsistencyCheckResults(int &eos_missing_count, int &fc_missing_count, vector< string > &eos_missing, vector< string > &fc_missing)
Function to get result of the last successful consistency check.
int DownloadFile(string conditions, string savePath)
int AddFileInfo(string LFN, FileInfo file_metadata)
Function to add metadata for the file with specific LFN.
string performRequest(string conditions, string json_content, string qType)
Perfrom common curl read/write shenanigans.
int AddFile(string input_path, string LFN)
Function to add file to the File Catalog and upload to CICC.
int GetFileInfo(string LFN, FileInfo &file_info)
Function to get metadata of the file stored at the given location.
int GetPFNs(string LFN, vector< string > &PFNs)
Function to get file PFN (Physical File Name).
int PrintMetadataFields()
Function to print current metadata fields.
int GetConsistencyCheckStatus()
Function to get status of the last successful consistency check.
searchAttributes
enumeration for attributes, which can be used in searching file metadata
string getValueAsString()
matchCriteria
enumeration for conditions, which can be used for matching with a specified value
matchCriteria getMatchCriteria()
matchCriteria FileMatchCriteria
searchAttributes getFileAttribute()
searchAttributes FileAttribute
Class presenting File Info (Metadata) Structure.
int StartEvent
event number from which stored event set begins
float FileSize
file size in bytes
int RunType
run type (1 - physics run, 2 - calibration run, 3 - test run)
static const int Version
structure (API) version
string BeamParticle
beam particle name
int EndEvent
event number with which event set ends
int EventCount
event count stored in the file
string EndDateTime
end datetime of the stored event set (YYYY-MM-DD HH-MM-SS format)
int PeriodNumber
number of experiment session, when the events was collected
string StartDateTime
start datetime of the stored event set (YYYY-MM-DD HH-MM-SS format)
int RunNumber
number of experiment run, when the events was collected
string TargetParticle
target particle name
float FieldVoltage
field voltage
const char *const FILE_API_USERNAME
const char *const FILE_API_HOST
const char *const FILE_API_NAME
const char *const FILE_API_PASSWORD
basic_json< nlohmann::ordered_map > ordered_json
specialization that maintains the insertion order of object keys