// dataset_insert.cxx // Insert the dataset described by an XML file into the default dataset // repository. #include #include #include "dataset_util/FileStatus.h" #include "dataset_util/Environment.h" #include "dataset_util/DtdRegistry.h" #include "dataset_base/Dataset.h" #include "dataset_base/DatasetCreator.h" #include "dataset_base/DatasetRepository.h" #include "dataset_xml/XmlParser.h" #include "dataset_credential/GssCredentialManager.h" using std::string; using std::cout; using std::cerr; using std::endl; using dset::Dataset; using dset::DatasetCreator; using dset::DatasetRepository; using dset::DatasetList; using dset::GssCredentialManager; // Register TestDataset and TestCompoundDataset DTD for testing. #include "dataset_base/DatasetCreator_t.h" //********************************************************************** // Helpers. //********************************************************************** // Return XML parser. XmlParser& parser() { static XmlParser pr; return pr; } // Insert database into an new DB. // Use old DB to find children. int insert(DatasetRepository& oldrep, const Dataset* pdst, DatasetRepository& newrep, bool recursive) { // If recursive, first insert children. if ( recursive && pdst->constituents().size() ) { const DatasetIdList& childids = pdst->constituent_ids(); const DatasetList& children = pdst->constituents(); DatasetIdList::const_iterator idid = childids.begin(); for ( DatasetList::const_iterator ichi=children.begin(); ichi!=children.end(); ++ichi ) { const Dataset* pchi = *ichi; DatasetId did = *idid; ++idid; if ( pchi == 0 ) { cerr << "Dataset has null child for ID " << did.to_string() << endl; cerr << *pdst << endl; return 40; } if ( newrep.extract(pchi->id(), true) == 0 ) { int rstat = insert(oldrep, pchi, newrep, recursive); if ( rstat != 0 ) { return rstat; } } } } // Put dataset into database. DatasetId didchk = newrep.insert(pdst, true); if ( ! didchk.is_valid() ) { int ecode = newrep.error(); string msg = newrep.error_message(); cerr << "Database insertion for dataset " << pdst->id().to_string() << " failed with error " << ecode << endl; cerr << " \"" << msg << "\"" << endl; return 41; } if ( didchk != pdst->id() ) { // Should never happen. cerr << "Inserted ID differs from original!!!" << endl; cerr << "Original: " << pdst->id().to_string() << endl; cerr << "Inserted: " << didchk.to_string() << endl; return 42; } assert( newrep.extract(didchk) != 0 ); return 0; } //********************************************************************** int main(int argc, char* argv[]) { bool debug = false; bool help = false; bool error = 0; string newrep_conn = ""; string oldrep_conn = ""; string xfile = ""; string sid = ""; bool recursive = false; int iarg = 0; string exename = argv[iarg++]; while ( iarg < argc ) { // Fetch flag and its argument. string flag = argv[iarg++]; string arg = ""; if ( iarg < argc ) { bool has_arg = false; arg = argv[iarg]; if ( arg.size() && arg[0] == '-' ) { arg = ""; } else { has_arg = true; ++iarg; } } // New DB directory. if ( flag == "-o" ) { if ( arg == "" ) { error = 11; break; } newrep_conn = arg; // Old DB directory. } else if ( flag == "-c" ) { if ( arg == "" ) { error = 12; break; } oldrep_conn = arg; } else if ( flag == "-f" ) { if ( arg == "" ) { error = 14; break; } xfile = arg; sid = ""; } else if ( flag == "-i" ) { if ( arg == "" ) { error = 15; break; } xfile = ""; sid = arg; } else if ( flag == "-r" ) { recursive = true; } else if ( flag == "-h" ) { help = true; break; } else { error = 19; break; } } if ( error || help ) { cout << "Usage: " << exename << " [-d DB_DIR] [-o DB_DIR] [-f XFILE] [-i ID] [-r]" << endl; cout << " -h - help: this message" << endl; cout << " -o CONN - connection string for the install repository" << " [\"\"]" << endl; cout << " -c CONN - directory to locate existing datasets" << " [\"\"]" << endl; cout << " -f XFILE - XML file describing the dataset" << endl; cout << " -i ID - ID of the old dataset in format iii-jjj" << endl; cout << " (One of -f and -i should be present)" << endl; cout << " -r - recursive: install sub-datasets" << endl; cout << "The inserted ID is written to stdout" << endl; if ( error ) { cerr << "Error reading command line" << endl; } return error; } // Acquire credential. int cstat = GssCredentialManager::set_default(); if ( cstat != 0 ) { cerr << "Unable to acquire credential" << endl; return 21; } // Open new database. DatasetRepository newrep(newrep_conn); if ( ! newrep.is_valid() ) { cerr << "Unable to access new respository with connection " << endl; cerr << '"' << newrep_conn << '"' << endl; return 22; } // Open old database as the default. DatasetRepository::set_default_instance(oldrep_conn); DatasetRepository& oldrep = DatasetRepository::default_instance(); if ( ! oldrep.is_valid() ) { cerr << "Unable to access old respository with connection " << endl; cerr << '"' << oldrep_conn << '"' << endl; return 23; } // Display DTD registered type. if ( debug ) { cout << "Registered dataset types:" << endl; DtdRegistry::instance("dataset").display(cout) << endl; } // Open the dataset. const Dataset* pdst = 0; if ( xfile.size() ) { // Make sure DTD is present. if ( ! FileStatus("dataset.dtd").is_readable() ) { DtdRegistry::instance("dataset").write(); } const XmlElement* pele = parser().parse(xfile); if ( pele == 0 ) { cerr << "Unable to parse dataset XML file" << endl; return 31; } pdst = DatasetCreator::create(*pele, &oldrep); delete pele; if ( pdst == 0 ) { int ecode = oldrep.error(); cerr << "Error retrieving input dataset from file" << ecode << endl; } } else { DatasetId did(sid); if ( ! did.is_valid() ) { cerr << "Unable to parse id" << endl; return 34; } pdst = oldrep.extract(did); if ( pdst == 0 ) { int ecode = oldrep.error(); string msg = oldrep.error_message(); cerr << "Error retrieving input dataset with ID: " << ecode << endl; cerr << " \"" << msg << "\"" << endl; return 35; } } // Call helper. int rstat = insert(oldrep, pdst, newrep, recursive); if ( rstat != 0 ) { cerr << "Insertion failed" << endl; delete pdst; return rstat; } // Echo the ID of the inserted dataset. cout << pdst->id().to_string() << endl; delete pdst; return 0; }