// dataset_merge_events.cxx // // David Adams // June 2003 // // Create an event merge dataset from a collection of datasets. // The latter are specified by ID. // // The new dataset is inserted in the same database where the input // datasets are found. #include #include #include #include "dataset_util/FileStatus.h" #include "dataset_util/Environment.h" #include "dataset_util/XmlElement.h" #include "dataset_xml/XmlParser.h" #include "dataset_file/FileCatalog.h" #include "dataset_id/UniqueIdGenerator.h" #include "dataset_credential/GssCredentialManager.h" #include "dataset_base/EventMergeDataset.h" #include "dataset_base/DatasetRepository.h" #include "dataset_base/DatasetCreator_t.h" using std::string; using std::cout; using std::cerr; using std::endl; using std::vector; using dset::FileCatalog; using dset::GssCredentialManager; using dset::ContentBlock; using dset::Content; using dset::Dataset; using dset::DatasetRepository; using dset::EventMergeDataset; //********************************************************************** // Helpers. //********************************************************************** // Return XML parser. XmlParser& parser() { static XmlParser pr; return pr; } // Return default location for Unique ID's. string defuid_name() { string name = ""; if ( name == "" ) { name = Environment::initial().value("DIAL_UIDS"); } return name; } //********************************************************************** int main(int argc, char* argv[]) { // Fetch arguments. string arg0 = argv[0]; // List if ID's. vector ids; // Print help and exit. bool help = false; int error = 0; string id_name = ""; bool use_uid = true; string uid_name = ""; string conn = ""; string xfile = "dataset.xml"; bool db_insert = false; int iarg = 0; string exename = argv[iarg++]; while ( iarg < argc ) { // Fetch flag and its argument. string flag = argv[iarg++]; string arg = ""; bool has_arg = false; if ( iarg < argc && flag.size() && flag[0]=='-' ) { arg = argv[iarg]; if ( arg.size() && arg[0] == '-' ) { arg = ""; } else { has_arg = true; ++iarg; } } // help if ( flag == "-h" ) { help = true; break; // ID for new dataset } else if ( flag == "-i" ) { if ( arg == "" ) { error = 1; break; } id_name = arg; use_uid = false; // specify unique ID generator } else if ( flag == "-u" ) { use_uid = true; id_name = ""; if ( arg != "" ) { uid_name = arg; } // Dataset database } else if ( flag == "-c" ) { conn = arg; // Output file name. } else if ( flag == "-f" ) { if ( arg == "" ) { xfile = "dataset.xml"; } xfile = arg; // List of ID's. } else if ( flag == "-l" ) { if ( arg == "" ) { error = 3; break; } Text idlist(arg); for ( unsigned int iline=0; iline end of flags. } else { --iarg; while ( iarg < argc ) { // Fetch flag and its argument. string sid = argv[iarg++]; DatasetId id(sid); if ( ! id.is_valid() ) { cerr << "Invalid ID " << arg << endl; return 4; } ids.push_back(id); } } } int stat = 0; if ( help ) { } else if ( ids.size() == 0 ) { stat = 21; cerr << "At least one ID must be provided" << endl; } if ( help || stat!=0 ) { cout << "Usage: " << arg0 << " [-i iii.jjj] [-f fcname] [-c CONN] id1 [id2 ...]" << endl; cout << " " << arg0 << " [-i iii.jjj] [-f fcname] [-c CONN] -l IDLIST" << endl; cout << " -i iii-jjj resets output dataset ID to iii-jjj" << endl; cout << " (normally option -u is preferable)" << endl; cout << " -u UID_DIR - location of Dataset unique ID's [$DIAL_UIDS]" << endl; cout << " -c CONN - Dataset repository connection [\"\"]" << endl; cout << " -f FILE - name of the output XML file [dataset.xml]" << endl; cout << " -w - insert output dataset in (input) dataset DB" << endl; cout << " -l IDLIST - file containing the list of ID's" << endl; return stat; } // Check that unique ID generator and explicit ID are not both // specified. bool use_id = id_name.size(); if ( use_id && use_uid ) { cerr << "Use only one of -i and -u" << endl; return 5; } // Initialize the unique ID generator. if ( use_uid ) { if ( ! uid_name.size() ) { uid_name = Environment::initial().value("DIAL_UIDS"); if ( uid_name == "" ) { cerr << "Unable to locate $DIAL_UIDS" << endl; stat = 4; } } int gstat = UniqueIdGenerator::set_generator(uid_name); if ( gstat != 0 ) { cerr << "Unable to set unique ID generator" << endl; cerr << " " << uid_name << endl; cerr << " Error code is " << gstat << endl; return 17; } Dataset::reset_id_generator(); if ( ! Dataset::id_generator().is_global() ) { cerr << "Unable to find unique ID generator at " << endl; cerr << " " << uid_name << endl; return 15; } } else { assert( use_id ); Dataset::set_local_id_generator(); assert( ! Dataset::id_generator().is_global() ); } // Set the credential for this thread. // This is needed to find owner for task. int cstat = GssCredentialManager::set_default(); if ( cstat != 0 ) { cerr << "Unable to find credential" << endl; return 18; } // Open the dataset repository. DatasetRepository rep(conn); if ( ! rep.is_valid() ) { cerr << "Unable to access dataset repository at connection" << endl; cerr << " " << '"' << conn << '"' << endl; } // Turn list of ID's into a list of datasets. vector dsts; string dataset_type; string content_label; ContentIdList cids; for ( vector::const_iterator idid=ids.begin(); idid!=ids.end(); ++idid ) { DatasetId did = *idid; // Retrieve dataset and check retrieval. const Dataset* pdst = rep.extract(did); if ( pdst == 0 ) { cerr << "Unable to retrieve dataset with ID " << did.to_string() << endl; int ecode = rep.error(); string emsg = rep.error_message(); cerr << "DB returned error " << ecode << ": " << emsg << endl; return 3; } // Check validity. if ( ! pdst->is_valid() ) { cerr << "Invalid dataset with ID " << did.to_string() << endl; return 4; } // Check this is an event dataset. if ( ! pdst->content().has_event_content() ) { cerr << "Non-event dataset with ID " << did.to_string() << endl; return 5; } if ( pdst->content().size() != 1 ) { cerr << "Dataset does not have exactly one content block" << did.to_string() << endl; return 5; } const ContentBlock& blk = pdst->content().front(); const ContentIdList& newcids = blk.content_ids(); // First entry, record the content. if ( idid == ids.begin() ) { dataset_type = blk.dataset_type(); content_label = blk.name(); cids = newcids; cerr << cids << endl; // All others, verify the content. } else { if ( newcids != cids || blk.dataset_type() != dataset_type || blk.name() != content_label ) { cerr << "Inconsistent content in dataset with ID " << did.to_string() << endl; return 6; } } // Add dataset to list. dsts.push_back(pdst); } assert( dsts.size() == ids.size() ); // Create dataset. assert( dsts.size() ); const Dataset& dst1 = *dsts.front(); bool virt = dst1.is_virtual(); EventIdList eids; Content con(dataset_type, content_label, cids, eids); EventMergeDataset mdst(virt, con); assert( mdst.is_valid() ); for ( vector::const_iterator idst=dsts.begin(); idst!=dsts.end(); ++idst ) { const Dataset& dst = **idst; if ( virt && !dst.is_virtual() ) { cerr << "Inconsistent datasets: "<< endl; cerr << " Dataset " << dst1.id().to_string() << " is virtual" << endl; cerr << " Dataset " << dst.id().to_string() << " is non-virtual" << endl; return 7; } if ( !virt && dst.is_virtual() ) { cerr << "Inconsistent datasets: "<< endl; cerr << " Dataset " << dst1.id().to_string() << " is non-virtual" << endl; cerr << " Dataset " << dst.id().to_string() << " is virtual" << endl; return 8; } const ContentBlock& blk = dst.content().front(); cerr << "...Adding dataset " << dst.id().to_string() << " with " << blk.event_count() << " event"; if ( blk.event_count() != 1 ) cerr << "s"; cerr << endl; int mstat = mdst.merge(**idst); if ( mstat != 0 ) { cerr << "Event merge failed with error " << mstat << endl; return 9; } } if ( ! mdst.is_valid() ) { cerr << "Unable to create dataset" << endl; return 10; } // Set ID. if ( use_id ) { DatasetId newid(id_name); if ( mdst.set_id(newid) != 0 ) { cerr << "Error setting dataset ID " << id_name << endl; return 11; } } mdst.lock(); EventIdList::size_type count = mdst.content().front().event_count(); cerr << "Merged dataset has " << count << " event"; if ( count != 1 ) cerr << "s"; cerr << endl; // Create XML. if ( ! mdst.id().is_global() ) { cerr << "Dataset has local ID." << endl; cerr << "Define Dataset ID generator or use option -i" << endl; return 12; } const XmlElement* pele = mdst.xml(); if ( pele == 0 ) { cerr << "Unable to create XML" << endl; return 13; } // Write to database. if ( db_insert ) { if ( rep.insert(&mdst, false).is_valid() ) { cerr << "Dataset inserted in database\n " << rep << endl; cout << mdst.id().to_string() << endl; } else { cerr << "Dataset insertion failed for\n " << rep << endl; return 14; } } // Write to a file. if ( xfile.size() ) { int wstat = parser().write(xfile, *pele); if ( wstat != 0 ) { cerr << "Error writing XML file" << endl; } } }