bool send(DataModel::NotifierMessage *nmsg) { int error; if ( !connection()->send(nmsg, &error) ) { if ( error == Core::Status::SEISCOMP_MESSAGE_SIZE_ERROR ) { SEISCOMP_WARNING("Message with %d notifiers is too big, will split it", nmsg->size()); DataModel::NotifierMessagePtr tmp = new DataModel::NotifierMessage; int halfSize = nmsg->size() / 2; if ( halfSize <= 0 ) { SEISCOMP_ERROR("Not enough notifiers to split message, need at least 2"); return false; } while ( halfSize-- ) { tmp->attach(*nmsg->begin()); nmsg->detach(nmsg->begin()); } return send(tmp.get()) && send(nmsg); } } return true; }
bool syncInventory() { DataModel::Inventory *targetInv = Client::Inventory::Instance()->inventory(); bool createNotifier = commandline().hasOption("create-notifier"); bool testMode = commandline().hasOption("test"); if ( testMode || _output.empty() ) createNotifier = true; if ( targetInv == NULL ) { cerr << "No inventory to sync" << endl; return false; } // Disable object registration DataModel::PublicObject::SetRegistrationEnabled(false); // Disable notifier check DataModel::Notifier::SetCheckEnabled(false); vector<string> files; collectFiles(files); if ( _filebase.empty() && files.empty() ) { cerr << "Nothing to merge, no files given" << endl; return false; } DataModel::InventoryPtr mergedInventory = new DataModel::Inventory(); Merge merger(mergedInventory.get()); merger.setLogHandler(this); _continueOperation = true; _currentTask = &merger; DataModel::Notifier::SetEnabled(false); for ( size_t i = 0; i < files.size(); ++i ) { if ( _exitRequested ) break; IO::XMLArchive ar; if ( !ar.open(files[i].c_str()) ) { cerr << "Could not open file (ignored): " << files[i] << endl; continue; } DataModel::InventoryPtr inv; cerr << "Parsing " << files[i] << " ... " << flush; ar >> inv; cerr << "done" << endl; if ( !inv ) { cerr << "No inventory found (ignored): " << files[i] << endl; continue; } _inventorySources[inv.get()] = files[i]; // Pushing the inventory into the merger cleans it // completely. The ownership of all childs goes to // the merger merger.push(inv.get()); } if ( _exitRequested ) { cerr << "Exit requested: abort" << endl; return false; } cerr << "Merging inventory ... " << flush; if ( merger.merge(false) ) cerr << "done" << endl; else cerr << "failed" << endl; printLogs(); if ( !_continueOperation ) { cerr << "Unresolvable errors ... aborting" << endl; return false; } if ( _exitRequested ) { cerr << "Exit requested: abort" << endl; return false; } // Activate registration again DataModel::PublicObject::SetRegistrationEnabled(true); Sync syncTask(targetInv); _currentTask = &syncTask; if ( createNotifier ) DataModel::Notifier::SetEnabled(true); cerr << "Synchronising inventory ... " << flush; if ( syncTask.push(mergedInventory.get()) ) cerr << "done"; else cerr << "failed"; cerr << endl; if ( _exitRequested ) { cerr << "Exit requested: abort" << endl; return false; } if ( createNotifier ) DataModel::Notifier::SetEnabled(true); cerr << "Removing remaining objects ... " << flush; syncTask.cleanUp(); cerr << "done" << endl; // --- Check key files // Collect all station key files map<string,string> keyFiles; try { fs::path directory = SC_FS_PATH(_keydir); fs::directory_iterator it(directory); fs::directory_iterator dirEnd; for ( ; it != dirEnd; ++it ) { if ( fs::is_directory(SC_FS_IT_PATH(it)) ) continue; string name = SC_FS_IT_LEAF(it); if ( name.compare(0, 8, "station_") == 0 ) keyFiles[SC_FS_IT_LEAF(it)] = SC_FS_IT_STR(it); } } catch ( ... ) {} for ( size_t n = 0; n < mergedInventory->networkCount(); ++n ) { DataModel::Network *net = mergedInventory->network(n); for ( size_t s = 0; s < net->stationCount(); ++s ) { DataModel::Station *sta = net->station(s); string id = net->code() + "_" + sta->code(); string filename = "station_" + id; // Remove filename from keyFiles map<string,string>::iterator it = keyFiles.find(filename); if ( it != keyFiles.end() ) keyFiles.erase(it); } } // Warn about existing key files without a corresponding station // in inventory if ( !keyFiles.empty() ) { SEISCOMP_WARNING("Found %d key file%s without a corresponding " "station in inventory:", (int)keyFiles.size(), keyFiles.size() > 1?"s":""); for ( map<string,string>::iterator it = keyFiles.begin(); it != keyFiles.end(); ++it ) SEISCOMP_WARNING(" %s", it->second.c_str()); } DataModel::Notifier::SetEnabled(false); _currentTask = NULL; if ( _exitRequested ) { cerr << "Exit requested: abort" << endl; return false; } bool doSyncKeys = false; if ( createNotifier ) { DataModel::NotifierMessagePtr nmsg; size_t notifierCount = DataModel::Notifier::Size(); if ( notifierCount > 0 ) { cerr << notifierCount << " notifiers available" << endl; if ( !_output.empty() ) { IO::XMLArchive ar; if ( !ar.create(_output.c_str()) ) { cerr << "Failed to create output file: " << _output << endl; DataModel::Notifier::Clear(); return false; } cerr << "Generating output ... " << flush; ar.setFormattedOutput(true); nmsg = DataModel::Notifier::GetMessage(true); ar << nmsg; ar.close(); cerr << "done" << endl; } else if ( !testMode ) { // Notify about start of synchronization DataModel::InventorySyncMessagePtr ismsg = new DataModel::InventorySyncMessage(false); ismsg->setCreationInfo(DataModel::CreationInfo()); ismsg->creationInfo().setCreationTime(Core::Time::GMT()); ismsg->creationInfo().setAuthor(author()); ismsg->creationInfo().setAgencyID(agencyID()); connection()->send(Communication::Protocol::STATUS_GROUP, ismsg.get()); // Send an inital sync command to also wake-up the messaging sync(); // Send notifier DataModel::NotifierMessagePtr tmp = new DataModel::NotifierMessage(); DataModel::NotifierMessage::iterator it; int count = 0; // Fetch each single notifier message. Fetching all notifiers // in one message can take a long time if a huge amount of // notifiers is in the queue. Due to memory fragmentation // most of the time spent is in malloc. while ( (nmsg = DataModel::Notifier::GetMessage(false)) != NULL ) { if ( _exitRequested ) break; for ( it = nmsg->begin(); it != nmsg->end(); ++it ) { DataModel::Notifier* n = DataModel::Notifier::Cast(*it); if ( !n ) continue; tmp->attach(n); ++count; if ( count % 100 == 0 ) { cerr << "\rSending notifiers: " << (int)(count*100/notifierCount) << "%" << flush; if ( !send(tmp.get()) ) { SEISCOMP_ERROR("Failed to send message, abort"); return false; } tmp->clear(); sync(); } } } if ( !_exitRequested && !tmp->empty() ) { if ( !send(tmp.get()) ) { SEISCOMP_ERROR("Failed to send message, abort"); return false; } cerr << "\rSending notifiers: " << (int)(count*100/notifierCount) << "%" << flush; } cerr << endl; sync(); // Notify about end of synchronization ismsg->creationInfo().setCreationTime(Core::Time::GMT()); ismsg->isFinished = true; connection()->send(Communication::Protocol::STATUS_GROUP, ismsg.get()); doSyncKeys = true; } else { /* DataModel::NotifierMessage::iterator it; while ( (nmsg = DataModel::Notifier::GetMessage(false)) != NULL ) { for ( it = nmsg->begin(); it != nmsg->end(); ++it ) { DataModel::Notifier* n = DataModel::Notifier::Cast(*it); if ( !n ) continue; switch ( n->operation() ) { case DataModel::OP_ADD: cout << "+"; break; case DataModel::OP_REMOVE: cout << "-"; break; case DataModel::OP_UPDATE: cout << "M"; break; default: cout << "?"; break; } cout << " " << n->object()->className() << endl; } } */ DataModel::Notifier::Clear(); cout << "OK - synchronization test passed" << endl; } } else cerr << "Inventory is synchronised already, nothing to do" << endl; DataModel::Notifier::Clear(); } else { if ( _output.empty() ) _output = "-"; IO::XMLArchive ar; if ( !ar.create(_output.c_str()) ) { cerr << "Failed to create output file: " << _output << endl; return false; } cerr << "Generating output ... " << flush; ar.setFormattedOutput(true); ar << targetInv; ar.close(); cerr << "done" << endl; } if ( doSyncKeys ) { if ( !commandline().hasOption("no-rc") ) { if ( !syncRCFiles(targetInv) ) return false; } if ( !commandline().hasOption("no-keys") ) { bool syncKeys = true; try { syncKeys = configGetBool("syncKeys"); } catch (...) {} if ( syncKeys && !syncKeyFiles(targetInv) ) return false; } } return true; }
bool applyNotifier() { DataModel::Inventory *targetInv = Client::Inventory::Instance()->inventory(); if ( targetInv == NULL ) { cerr << "No inventory to apply" << endl; return false; } // Disable object registration DataModel::PublicObject::SetRegistrationEnabled(false); vector<string> files; collectFiles(files); if ( files.empty() ) { cerr << "Nothing to apply, no files given" << endl; return false; } Sync syncTask(targetInv); _currentTask = &syncTask; for ( size_t i = 0; i < files.size(); ++i ) { if ( _exitRequested ) break; IO::XMLArchive ar; if ( !ar.open(files[i].c_str()) ) { cerr << "Could not open file (ignored): " << files[i] << endl; continue; } cerr << "Parsing " << files[i] << " ... " << flush; DataModel::NotifierMessagePtr msg; ar >> msg; cerr << "done" << endl; if ( !msg ) { cerr << "No notifier message found (ignored): " << files[i] << endl; continue; } size_t notifierCount = msg->size(); cerr << notifierCount << " notifiers available" << endl; if ( !_output.empty() ) { cerr << "Applying notifier ... " << flush; // Apply all notifier DataModel::NotifierMessage::iterator it; for ( it = msg->begin(); it != msg->end(); ++it ) { DataModel::Notifier* n = DataModel::Notifier::Cast(*it); if ( !n ) continue; n->apply(); } cerr << "done" << endl; } else { // Send all notifier // Send an inital sync command to also wake-up the messaging sync(); // Send notifier DataModel::NotifierMessagePtr tmp = new DataModel::NotifierMessage(); DataModel::NotifierMessage::iterator it; int count = 0; for ( it = msg->begin(); it != msg->end(); ++it ) { DataModel::Notifier* n = DataModel::Notifier::Cast(*it); if ( !n ) continue; tmp->attach(n); ++count; if ( count % 100 == 0 ) { cerr << "\rSending notifiers: " << (int)(count*100/notifierCount) << "%" << flush; if ( !send(tmp.get()) ) { SEISCOMP_ERROR("Failed to send message, abort"); return false; } tmp->clear(); sync(); } } sync(); if ( !tmp->empty() ) { if ( !send(tmp.get()) ) { SEISCOMP_ERROR("Failed to send message, abort"); return false; } cerr << "\rSending notifiers: " << (int)(count*100/notifierCount) << "%" << flush; } } } if ( _exitRequested ) { cerr << "Exit requested: abort" << endl; return false; } if ( !_output.empty() ) { IO::XMLArchive ar; if ( !ar.create(_output.c_str()) ) { cerr << "Failed to create output file: " << _output << endl; return false; } cerr << "Generating output ... " << flush; ar.setFormattedOutput(true); ar << targetInv; ar.close(); cerr << "done" << endl; } return true; }