Beispiel #1
0
		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;
		}
Beispiel #2
0
		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;
		}