LCOV - code coverage report
Current view: top level - oks/apps - oks_dump.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 190 0
Test Date: 2026-10-11 15:05:20 Functions: 0.0 % 4 0

            Line data    Source code
       1              : // DUNE DAQ modification notice:
       2              : // This file has been modified from the original ATLAS oks source for the DUNE DAQ project.
       3              : // Fork baseline commit: oks-08-03-04 (2022-04-14).
       4              : // Renamed since fork: yes (from bin/oks_dump.cpp to apps/oks_dump.cxx).
       5              : 
       6              : /**
       7              :  *  \file oks_dump.cpp
       8              :  *
       9              :  *  This file is part of the OKS package.
      10              :  *  Author: <Igor.Soloviev@cern.ch>
      11              :  *
      12              :  *  This file contains the implementation of the OKS application to dump
      13              :  *  contents of the OKS database files.
      14              :  *
      15              :  */
      16              : 
      17              : #include "oks/exceptions.hpp"
      18              : #include "oks/kernel.hpp"
      19              : #include "oks/query.hpp"
      20              : 
      21              : #include <iostream>
      22              : #include <vector>
      23              : 
      24              : #include <stdlib.h>
      25              : #include <string.h>
      26              : 
      27              : using namespace dunedaq::oks;
      28              : 
      29              : enum __OksDumpExitStatus__
      30              : {
      31              :   __Success__ = 0,
      32              :   __BadCommandLine__,
      33              :   __BadOksFile__,
      34              :   __BadQuery__,
      35              :   __NoSuchClass__,
      36              :   __FoundDanglingReferences__,
      37              :   __ExceptionCaught__
      38              : };
      39              : 
      40              : static void
      41            0 : printUsage(std::ostream& s)
      42              : {
      43            0 :   s << "Usage: oks_dump\n"
      44              :        "    [--files-only | --files-stat-only | --schema-files-only | --schema-files-stat-only | --data-files-only | "
      45              :        "--data-files-stat-only]\n"
      46              :        "    [--class name-of-class [--query query [--print-references recursion-depth [class-name*] [--]] "
      47              :        "[--print-referenced_by [name] [--]]]]\n"
      48              :        "    [--path object-from object-to query]\n"
      49              :        "    [--allow-duplicated-objects-via-inheritance]\n"
      50              :        "    [--version]\n"
      51              :        "    [--help]\n"
      52              :        "    [--input-from-files] database-file [database-file(s)]\n"
      53              :        "\n"
      54              :        "Options:\n"
      55              :        "    -f | --files-only                                 print list of oks files names\n"
      56              :        "    -F | --files-stat-only                            print list of oks files with statistic details (size, "
      57              :        "number of items\n"
      58              :        "    -s | --schema-files-only                          print list of schema oks files names\n"
      59              :        "    -S | --schema-files-stat-only                     print list of oks schema files with statistic details\n"
      60              :        "    -d | --data-files-only                            print list of data oks files names\n"
      61              :        "    -D | --data-files-stat-only                       print list of oks data files with statistic details\n"
      62              :        "    -c | --class class_name                           dump given class (all objects or matching some query)\n"
      63              :        "    -q | --query query                                print objects matching query (can only be used with "
      64              :        "class)\n"
      65              :        "    -r | --print-references N C1 C2 ... CX            print objects referenced by found objects (can only be "
      66              :        "used with query), where:\n"
      67              :        "                                                       * the parameter N defines recursion depth for "
      68              :        "referenced objects (> 0)\n"
      69              :        "                                                       * the optional set of names {C1 .. CX} defines "
      70              :        "[sub-]classes for above objects\n"
      71              :        "    -b | --print-referenced_by [name]                 print objects referencing found objects (can only be "
      72              :        "used with query), where:\n"
      73              :        "                                                       * the optional parameter name defines name of "
      74              :        "relationship\n"
      75              :        "    -p | --path obj query                             print path from object \'obj\' to object of query "
      76              :        "expression\n"
      77              :        "    -i | --input-from-files                           read oks files to be loaded from file(s) instead of "
      78              :        "command line\n"
      79              :        "                                                      (to avoid problems with long command line, when there is "
      80              :        "huge number of files)\n"
      81              :        "    -a | --allow-duplicated-objects-via-inheritance   do not stop if there are duplicated object via "
      82              :        "inheritance hierarchy\n"
      83              :        "    -v | --version                                    print version\n"
      84              :        "    -h | --help                                       print this text\n"
      85              :        "\n"
      86              :        "Description:\n"
      87              :        "    Dumps contents of the OKS database.\n"
      88              :        "\n"
      89              :        "Return Status:\n"
      90              :        "    0 - no problems found\n"
      91              :        "    1 - bad command line parameter\n"
      92              :        "    2 - bad oks file(s)\n"
      93              :        "    3 - bad query passed via -q or -p options\n"
      94              :        "    4 - cannot find class passed via -c option\n"
      95              :        "    5 - loaded objects have dangling references\n"
      96              :        "    6 - caught an exception\n"
      97            0 :        "\n";
      98            0 : }
      99              : 
     100              : static void
     101            0 : no_param(const char* s)
     102              : {
     103            0 :   Oks::error_msg("oks_dump") << "no parameter(s) for command line argument \'" << s << "\' provided\n\n";
     104            0 :   exit(EXIT_FAILURE);
     105              : }
     106              : 
     107              : OksObject*
     108            0 : find_object(char* s, OksKernel& k)
     109              : {
     110            0 :   char* id = s;
     111              : 
     112            0 :   if ((s = strchr(id, '@')) == 0)
     113              :     return 0;
     114              : 
     115            0 :   *s = '\0';
     116            0 :   s++;
     117              : 
     118            0 :   if (OksClass* c = k.find_class(s)) {
     119            0 :     if (OksObject* o = c->get_object(id)) {
     120              :       return o;
     121              :     } else {
     122            0 :       Oks::error_msg("oks_dump::find_object()") << "cannot find object \"" << id << '@' << s << "\"\n";
     123              :     }
     124              :   } else {
     125            0 :     Oks::error_msg("oks_dump::find_object()") << "cannot find class \"" << s << "\"\n";
     126              :   }
     127              : 
     128              :   return 0;
     129              : }
     130              : 
     131              : int
     132            0 : main(int argc, char** argv)
     133              : {
     134            0 :   if (argc == 1) {
     135            0 :     printUsage(std::cerr);
     136            0 :     return __BadCommandLine__;
     137              :   }
     138              : 
     139            0 :   OksKernel kernel;
     140            0 :   kernel.set_test_duplicated_objects_via_inheritance_mode(true);
     141              : 
     142            0 :   try {
     143              : 
     144            0 :     int dump_files_only = 0; // 0 - none, 12 - data, 1 - schema, 2 - schema & data
     145            0 :     const char* class_name = 0;
     146            0 :     const char* query = 0;
     147            0 :     const char* object_from = 0;
     148            0 :     const char* path_query = 0;
     149            0 :     long recursion_depth = 0;
     150            0 :     bool print_referenced_by = false;
     151            0 :     const char* ref_by_rel_name = "*";
     152            0 :     std::vector<std::string> ref_classes;
     153            0 :     bool input_from_files = false;
     154            0 :     bool print_files_stat = false;
     155              : 
     156            0 :     for (int i = 1; i < argc; i++) {
     157            0 :       const char* cp = argv[i];
     158              : 
     159            0 :       if (!strcmp(cp, "-h") || !strcmp(cp, "--help")) {
     160            0 :         printUsage(std::cout);
     161              :         return __Success__;
     162            0 :       } else if (!strcmp(cp, "-v") || !strcmp(cp, "--version")) {
     163            0 :         std::cout << "OKS kernel version " << OksKernel::GetVersion() << std::endl;
     164              :         return __Success__;
     165            0 :       } else if (!strcmp(cp, "-a") || !strcmp(cp, "--allow-duplicated-objects-via-inheritance")) {
     166            0 :         kernel.set_test_duplicated_objects_via_inheritance_mode(false);
     167            0 :       } else if (!strcmp(cp, "-f") || !strcmp(cp, "--files-only")) {
     168              :         dump_files_only = 2;
     169            0 :       } else if (!strcmp(cp, "-F") || !strcmp(cp, "--files-stat-only")) {
     170              :         dump_files_only = 2;
     171              :         print_files_stat = true;
     172            0 :       } else if (!strcmp(cp, "-s") || !strcmp(cp, "--schema-files-only")) {
     173              :         dump_files_only = 1;
     174            0 :       } else if (!strcmp(cp, "-S") || !strcmp(cp, "--schema-files-stat-only")) {
     175              :         dump_files_only = 1;
     176              :         print_files_stat = true;
     177            0 :       } else if (!strcmp(cp, "-d") || !strcmp(cp, "--data-files-only")) {
     178              :         dump_files_only = 12;
     179            0 :       } else if (!strcmp(cp, "-D") || !strcmp(cp, "--data-files-stat-only")) {
     180              :         dump_files_only = 12;
     181              :         print_files_stat = true;
     182            0 :       } else if (!strcmp(cp, "-c") || !strcmp(cp, "--class")) {
     183            0 :         if (++i == argc) {
     184            0 :           no_param(cp);
     185              :         } else {
     186            0 :           class_name = argv[i];
     187              :         }
     188            0 :       } else if (!strcmp(cp, "-q") || !strcmp(cp, "--query")) {
     189            0 :         if (++i == argc) {
     190            0 :           no_param(cp);
     191              :         } else {
     192            0 :           query = argv[i];
     193              :         }
     194            0 :       } else if (!strcmp(cp, "-i") || !strcmp(cp, "--input-from-files")) {
     195              :         input_from_files = true;
     196            0 :       } else if (!strcmp(cp, "-r") || !strcmp(cp, "--print-references")) {
     197            0 :         if (++i == argc) {
     198            0 :           no_param(cp);
     199              :         } else {
     200            0 :           recursion_depth = atol(argv[i]);
     201              :         }
     202            0 :         int j = 0;
     203            0 :         for (; j < argc - i - 1; ++j) {
     204            0 :           if (argv[i + 1 + j][0] != '-') {
     205            0 :             ref_classes.push_back(argv[i + 1 + j]);
     206              :           } else {
     207              :             break;
     208              :           }
     209              :         }
     210            0 :         i += j;
     211            0 :       } else if (!strcmp(cp, "-b") || !strcmp(cp, "--print-referenced_by")) {
     212            0 :         print_referenced_by = true;
     213            0 :         if ((i + 1) < argc && argv[i + 1][0] != '-') {
     214            0 :           ref_by_rel_name = argv[++i];
     215              :         }
     216            0 :       } else if (!strcmp(cp, "-p") || !strcmp(cp, "--path")) {
     217            0 :         if (++i > argc - 1) {
     218            0 :           no_param(cp);
     219              :         } else {
     220            0 :           object_from = argv[i];
     221            0 :           path_query = argv[++i];
     222              :         }
     223            0 :       } else if (strcmp(cp, "--")) {
     224            0 :         if (input_from_files) {
     225            0 :           std::ifstream f(cp);
     226            0 :           if (f.good()) {
     227            0 :             while (f.good() && !f.eof()) {
     228            0 :               std::string file_name;
     229            0 :               std::getline(f, file_name);
     230            0 :               if (!file_name.empty() && kernel.load_file(file_name) == 0) {
     231            0 :                 Oks::error_msg("oks_dump") << "\tCan not load file \"" << file_name << "\", exiting...\n";
     232            0 :                 return __BadOksFile__;
     233              :               }
     234            0 :             }
     235              :           } else {
     236            0 :             Oks::error_msg("oks_dump") << "\tCan not open file \"" << cp << "\" for reading, exiting...\n";
     237              :             return __BadCommandLine__;
     238              :           }
     239            0 :         } else {
     240            0 :           if (kernel.load_file(cp) == 0) {
     241            0 :             Oks::error_msg("oks_dump") << "\tCan not load file \"" << cp << "\", exiting...\n";
     242              :             return __BadOksFile__;
     243              :           }
     244              :         }
     245              :       }
     246              :     }
     247              : 
     248            0 :     if (kernel.schema_files().empty()) {
     249            0 :       Oks::error_msg("oks_dump") << "\tAt least one oks file have to be provided, exiting...\n";
     250              :       return __BadCommandLine__;
     251              :     }
     252              : 
     253            0 :     if (query && !class_name) {
     254            0 :       Oks::error_msg("oks_dump")
     255            0 :         << "\tQuery can only be executed when class name is provided (use -c option), exiting...\n";
     256              :       return __BadCommandLine__;
     257              :     }
     258              : 
     259            0 :     if (dump_files_only) {
     260            0 :       long total_size = 0;
     261            0 :       long total_items = 0;
     262            0 :       const OksFile::Map* files[2] = { &kernel.schema_files(), &kernel.data_files() };
     263            0 :       for (int j = (dump_files_only / 10); j < (dump_files_only % 10); ++j) {
     264            0 :         if (!files[j]->empty()) {
     265            0 :           for (OksFile::Map::const_iterator i = files[j]->begin(); i != files[j]->end(); ++i) {
     266            0 :             if (print_files_stat) {
     267            0 :               total_size += i->second->get_size();
     268            0 :               total_items += i->second->get_number_of_items();
     269            0 :               std::cout << *(i->first) << " (" << i->second->get_number_of_items() << " items, "
     270            0 :                         << i->second->get_size() << " bytes)" << std::endl;
     271              :             } else {
     272            0 :               std::cout << *(i->first) << std::endl;
     273              :             }
     274              :           }
     275              :         }
     276              :       }
     277              : 
     278            0 :       if (print_files_stat) {
     279            0 :         std::cout << "Total number of items: " << total_items
     280              :                   << "\n"
     281            0 :                      "Total size of files: "
     282            0 :                   << total_size << " bytes" << std::endl;
     283              :       }
     284            0 :     } else if (class_name && *class_name) {
     285            0 :       if (OksClass* c = kernel.find_class(class_name)) {
     286            0 :         if (query && *query) {
     287            0 :           OksQuery* q = new OksQuery(c, query);
     288            0 :           if (q->good()) {
     289            0 :             OksObject::List* objs = c->execute_query(q);
     290            0 :             size_t num = (objs ? objs->size() : 0);
     291            0 :             std::cout << "Found " << num << " matching query \"" << query << "\" in class \"" << class_name << "\"";
     292            0 :             if (num) {
     293            0 :               std::cout << ':' << std::endl;
     294            0 :               while (!objs->empty()) {
     295            0 :                 OksObject* o = objs->front();
     296            0 :                 objs->pop_front();
     297              : 
     298            0 :                 if (recursion_depth > 0 || print_referenced_by) {
     299            0 :                   if (recursion_depth) {
     300            0 :                     ClassSet all_ref_classes;
     301            0 :                     kernel.get_all_classes(ref_classes, all_ref_classes);
     302            0 :                     OksObject::FSet refs;
     303            0 :                     o->references(refs, recursion_depth, false, &all_ref_classes);
     304            0 :                     std::cout << o << " references " << refs.size() << " object(s)" << std::endl;
     305            0 :                     for (OksObject::FSet::const_iterator i = refs.begin(); i != refs.end(); ++i) {
     306            0 :                       std::cout << " - " << *i << std::endl;
     307              :                     }
     308            0 :                   }
     309            0 :                   if (print_referenced_by) {
     310            0 :                     if (OksObject::FList* ref_by_objs = o->get_all_rels(ref_by_rel_name)) {
     311            0 :                       std::cout << o << " is referenced by " << ref_by_objs->size() << " object(s) via relationship \""
     312            0 :                                 << ref_by_rel_name << "\":" << std::endl;
     313              : 
     314            0 :                       for (OksObject::FList::const_iterator i = ref_by_objs->begin(); i != ref_by_objs->end(); ++i) {
     315            0 :                         std::cout << " - " << *i << std::endl;
     316              :                       }
     317              : 
     318            0 :                       delete ref_by_objs;
     319              :                     } else {
     320            0 :                       std::cout << o << " is not referenced by any object via relationship \"" << ref_by_rel_name
     321            0 :                                 << '\"' << std::endl;
     322              :                     }
     323              :                   }
     324              :                 } else {
     325            0 :                   std::cout << *o << std::endl;
     326              :                 }
     327              :               }
     328            0 :               delete objs;
     329              :             } else {
     330            0 :               std::cout << std::endl;
     331              :             }
     332              :           } else {
     333            0 :             Oks::error_msg("oks_dump") << "\tFailed to parse query \"" << query << "\" in class \"" << class_name
     334            0 :                                        << "\"\n";
     335              :             return __BadQuery__;
     336              :           }
     337            0 :           delete q;
     338              :         } else {
     339            0 :           std::cout << *c << std::endl;
     340              :         }
     341              :       } else {
     342            0 :         Oks::error_msg("oks_dump") << "\tCan not find class \"" << class_name << "\"\n";
     343              :         return __NoSuchClass__;
     344              :       }
     345            0 :     } else if (object_from && *object_from && path_query && *path_query) {
     346            0 :       OksObject* obj_from = find_object((char*)object_from, kernel);
     347            0 :       try {
     348            0 :         QueryPath q(path_query, kernel);
     349            0 :         OksObject::List* objs = obj_from->find_path(q);
     350              : 
     351            0 :         size_t num = (objs ? objs->size() : 0);
     352            0 :         std::cout << "Found " << num << " objects in the path \"" << q << "\" from object " << obj_from << ":"
     353            0 :                   << std::endl;
     354              : 
     355            0 :         if (num) {
     356            0 :           while (!objs->empty()) {
     357            0 :             OksObject* o = objs->front();
     358            0 :             objs->pop_front();
     359            0 :             std::cout << *o << std::endl;
     360              :           }
     361            0 :           delete objs;
     362              :         }
     363            0 :       } catch (bad_query_syntax& e) {
     364            0 :         Oks::error_msg("oks_dump") << "\tFailed to parse query: " << e.what() << std::endl;
     365            0 :         return __BadQuery__;
     366            0 :       }
     367            0 :     } else {
     368            0 :       std::cout << kernel;
     369              :     }
     370              : 
     371            0 :     if (!kernel.get_bind_classes_status().empty()) {
     372            0 :       Oks::error_msg("oks_dump") << "The schema contains dangling references to non-loaded classes:\n"
     373            0 :                                  << kernel.get_bind_classes_status();
     374              :     }
     375              : 
     376            0 :     if (!kernel.get_bind_objects_status().empty()) {
     377            0 :       Oks::error_msg("oks_dump") << "\tThe data contain dangling references to non-loaded objects\n";
     378              :     }
     379              : 
     380            0 :     if (!kernel.get_bind_classes_status().empty() || !kernel.get_bind_objects_status().empty()) {
     381              :       return __FoundDanglingReferences__;
     382              :     }
     383            0 :   } catch (exception& ex) {
     384            0 :     std::cerr << "Caught oks exception:\n" << ex << std::endl;
     385            0 :     return __ExceptionCaught__;
     386            0 :   } catch (std::exception& e) {
     387            0 :     std::cerr << "Caught standard C++ exception: " << e.what() << std::endl;
     388            0 :     return __ExceptionCaught__;
     389            0 :   } catch (...) {
     390            0 :     std::cerr << "Caught unknown exception" << std::endl;
     391            0 :     return __ExceptionCaught__;
     392            0 :   }
     393              : 
     394            0 :   return __Success__;
     395            0 : }
        

Generated by: LCOV version 2.0-1