LCOV - code coverage report
Current view: top level - oks/apps - oks_dump.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 177 0
Test Date: 2025-12-21 13:07:08 Functions: 0.0 % 4 0

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

Generated by: LCOV version 2.0-1