Beispiel #1
0
void sighandler_func(int signal)
{
	IBRCOMMON_LOGGER_TAG(TAG,notice) << "got signal " << signal << IBRCOMMON_LOGGER_ENDL;
	switch (signal)
	{
	case SIGTERM:
	case SIGINT:
	{
		//stop waiting and stop running, on SIGINT or SIGTERM
		ibrcommon::MutexLock l(_wait_cond);
		_running = false;
		_wait_cond.signal(true);
		break;
	}
#ifndef __WIN32__
	case SIGUSR1:
	{
		//stop waiting on SIGUSR1 -> "quickscan"
		ibrcommon::MutexLock l(_wait_cond);
		_wait_abort = true;
		_wait_cond.signal(true);
		break;
	}
#endif
	default:
		break;
	}
}
Beispiel #2
0
// on interruption do this!
void sighandler(int signal)
{
	// do not handle further signals if the shutdown is in progress
	if (_shutdown) return;

	switch (signal)
	{
	case SIGTERM:
	case SIGINT:
	{
		ibrcommon::MutexLock l(_shutdown_cond);
		_shutdown = true;
		_shutdown_cond.signal(true);
		break;
	}

	case SIGUSR1:
		if (!_debug)
		{
			ibrcommon::Logger::addStream(std::cout, ibrcommon::Logger::LOGGER_DEBUG, logopts);
			_debug = true;
		}

		_dtnd.setDebug(99);
		break;
	case SIGUSR2:
		_dtnd.setDebug(0);
		break;
	case SIGHUP:
		_dtnd.reload();
		break;
	default:
		// dummy handler
		break;
	}
}
Beispiel #3
0
int __daemon_run()
{
	// catch process signals
	signal(SIGINT, sighandler);
	signal(SIGTERM, sighandler);
	signal(SIGHUP, sighandler);
	signal(SIGQUIT, sighandler);
	signal(SIGUSR1, sighandler);
	signal(SIGUSR2, sighandler);

	sigset_t blockset;
	sigemptyset(&blockset);
	sigaddset(&blockset, SIGPIPE);
	::sigprocmask(SIG_BLOCK, &blockset, NULL);

	dtn::daemon::Configuration &conf = dtn::daemon::Configuration::getInstance();

	// set default logging tag
	ibrcommon::Logger::setDefaultTag("DTNEngine");

	// enable ring-buffer
	ibrcommon::Logger::enableBuffer(200);

	// enable timestamps in logging if requested
	if (conf.getLogger().display_timestamps())
	{
		logopts = (~(ibrcommon::Logger::LOG_DATETIME) & logopts) | ibrcommon::Logger::LOG_TIMESTAMP;
	}

	// init syslog
	ibrcommon::Logger::enableAsync(); // enable asynchronous logging feature (thread-safe)
	ibrcommon::Logger::enableSyslog("ibrdtn-daemon", LOG_PID, LOG_DAEMON, logsys);

	if (!conf.getDebug().quiet())
	{
		if (conf.getLogger().verbose()) {
			// add logging to the cout
			ibrcommon::Logger::addStream(std::cout, logstd | ibrcommon::Logger::LOGGER_NOTICE, logopts);
		} else {
			// add logging to the cout
			ibrcommon::Logger::addStream(std::cout, logstd, logopts);
		}

		// add logging to the cerr
		ibrcommon::Logger::addStream(std::cerr, logerr, logopts);
	}

	// activate debugging
	if (conf.getDebug().enabled() && !conf.getDebug().quiet())
	{
		// init logger
		ibrcommon::Logger::setVerbosity(conf.getDebug().level());

		ibrcommon::Logger::addStream(std::cout, ibrcommon::Logger::LOGGER_DEBUG, logopts);

		_debug = true;
	}

	// load the configuration file
	conf.load();

	try {
		const ibrcommon::File &lf = conf.getLogger().getLogfile();
		ibrcommon::Logger::setLogfile(lf, ibrcommon::Logger::LOGGER_ALL ^ ibrcommon::Logger::LOGGER_DEBUG, logopts);
	} catch (const dtn::daemon::Configuration::ParameterNotSetException&) { };

	// initialize the daemon up to runlevel "Routing Extensions"
	_dtnd.init(dtn::daemon::RUNLEVEL_ROUTING_EXTENSIONS);

#ifdef HAVE_LIBDAEMON
	if (conf.getDaemon().daemonize())
	{
		/* Send OK to parent process */
		daemon_retval_send(0);
		daemon_log(LOG_INFO, "Sucessfully started");
	}
#endif

	ibrcommon::MutexLock l(_shutdown_cond);
	while (!_shutdown) _shutdown_cond.wait();

	_dtnd.init(dtn::daemon::RUNLEVEL_ZERO);

	// stop the asynchronous logger
	ibrcommon::Logger::stop();

	return 0;
}
Beispiel #4
0
/*
 * main application method
 */
int main( int argc, char** argv )
{
	// catch process signals
	ibrcommon::SignalHandler sighandler(sighandler_func);
	sighandler.handle(SIGINT);
	sighandler.handle(SIGTERM);
#ifndef __WIN32__
	sighandler.handle(SIGUSR1);
#endif

	// configration object
	config_t conf;

	// read the configuration
	read_configuration(argc, argv, conf);

	init_logger(conf);

	// initialize sighandler after possible exit call
	sighandler.initialize();

	// init working directory
	if (conf.workdir.length() > 0)
	{
		ibrcommon::File blob_path(conf.workdir);

		if (blob_path.exists())
		{
			ibrcommon::BLOB::changeProvider(new ibrcommon::FileBLOBProvider(blob_path), true);
		}
	}

	// backoff for reconnect
	unsigned int backoff = 2;

	ibrcommon::File outbox_file(conf.outbox);

	// create new file lists
	fileset new_files, prev_files, deleted_files, files_to_send;
	filelist observed_files;
	hashlist sent_hashes;

	// observed root file
	io::ObservedFile root(ibrcommon::File("/"));

#ifdef HAVE_LIBTFFS
	io::FatImageReader *imagereader = NULL;
#endif

	if (outbox_file.exists() && !outbox_file.isDirectory())
	{
#ifdef HAVE_LIBTFFS
		conf.fat = true;
		imagereader = new io::FatImageReader(conf.outbox);
		const io::FATFile fat_root(*imagereader, conf.path);
		root = io::ObservedFile(fat_root);
#else
		IBRCOMMON_LOGGER_TAG(TAG,error) << "ERROR: image-file provided, but this tool has been compiled without libtffs support!" << IBRCOMMON_LOGGER_ENDL;
		return -1;
#endif
	}
	else
	{
		if (!outbox_file.exists()) {
			ibrcommon::File::createDirectory(outbox_file);
		}
		root = io::ObservedFile(outbox_file);
	}

	IBRCOMMON_LOGGER_TAG(TAG,info) << "-- dtnoutbox --" << IBRCOMMON_LOGGER_ENDL;

	// loop, if no stop if requested
	while (_running)
	{
		try
		{
			// Create a stream to the server using TCP.
			ibrcommon::vaddress addr("localhost", 4550);
			ibrcommon::socketstream conn(new ibrcommon::tcpsocket(addr));

			// Initiate a client for synchronous receiving
			dtn::api::Client client(conf.name, conn, dtn::api::Client::MODE_SENDONLY);

			// Connect to the server. Actually, this function initiate the
			// stream protocol by starting the thread and sending the contact header.
			client.connect();

			// reset backoff if connected
			backoff = 2;

			// check the connection
			while (_running)
			{
				// get all files
				fileset current_files;
				root.findFiles(current_files);

				// determine deleted files
				fileset deleted_files;
				std::set_difference(prev_files.begin(), prev_files.end(), current_files.begin(), current_files.end(), std::inserter(deleted_files, deleted_files.begin()));

				// remove deleted files from observation
				for (fileset::const_iterator iter = deleted_files.begin(); iter != deleted_files.end(); ++iter)
				{
					const io::ObservedFile &deletedFile = (*iter);

					// remove references in the sent_hashes
					for (hashlist::iterator hash_it = sent_hashes.begin(); hash_it != sent_hashes.end(); /* blank */) {
						if ((*hash_it).getPath() == deletedFile.getFile().getPath()) {
							sent_hashes.erase(hash_it++);
						} else {
							++hash_it;
						}
					}

					// remove from observed files
					observed_files.remove(deletedFile);

					// output
					IBRCOMMON_LOGGER_TAG(TAG,info) << "file removed: " << deletedFile.getFile().getBasename() << IBRCOMMON_LOGGER_ENDL;
				}

				// determine new files
				fileset new_files;
				std::set_difference(current_files.begin(), current_files.end(), prev_files.begin(), prev_files.end(), std::inserter(new_files, new_files.begin()));

				// add new files to observation
				for (fileset::const_iterator iter = new_files.begin(); iter != new_files.end(); ++iter)
				{
					const io::ObservedFile &of = (*iter);

					int reg_ret = regexec(&conf.regex, of.getFile().getBasename().c_str(), 0, NULL, 0);
					if (!reg_ret && !conf.invert)
						continue;
					if (reg_ret && conf.invert)
						continue;

					// print error message, if regex error occurs
					if (reg_ret && reg_ret != REG_NOMATCH)
					{
							char msgbuf[100];
							regerror(reg_ret,&conf.regex,msgbuf,sizeof(msgbuf));
							IBRCOMMON_LOGGER_TAG(TAG,info) << "ERROR: regex match failed : " << std::string(msgbuf) << IBRCOMMON_LOGGER_ENDL;
					}

					// add new file to the observed set
					observed_files.push_back(of);

					// log output
					IBRCOMMON_LOGGER_TAG(TAG, info) << "file found: " << of.getFile().getBasename() << IBRCOMMON_LOGGER_ENDL;
				}

				// store current files for the next round
				prev_files.clear();
				prev_files.insert(current_files.begin(), current_files.end());

				IBRCOMMON_LOGGER_TAG(TAG, notice)
						<< "file statistics: "
						<< observed_files.size() << " observed, "
						<< deleted_files.size() << " deleted, "
						<< new_files.size() << " new"
						<< IBRCOMMON_LOGGER_ENDL;

				// find files to send, create std::list
				files_to_send.clear();


				IBRCOMMON_LOGGER_TAG(TAG, notice) << "updating observed files:" << IBRCOMMON_LOGGER_ENDL;
				for (filelist::iterator iter = observed_files.begin(); iter != observed_files.end(); ++iter)
				{
					io::ObservedFile &of = (*iter);

					// tick and update all files
					of.update();

					if (of.getStableCounter() > conf.rounds)
					{
						if (sent_hashes.find(of.getHash()) == sent_hashes.end())
						{
							sent_hashes.insert(of.getHash());
							files_to_send.insert(*iter);
						}
					}

					IBRCOMMON_LOGGER_TAG(TAG, notice)
						<< "\t"
						<< of.getFile().getBasename() << ": "
						<< of.getStableCounter()
						<< IBRCOMMON_LOGGER_ENDL;
				}

				if (!files_to_send.empty())
				{
					std::stringstream ss;
					for (fileset::const_iterator it = files_to_send.begin(); it != files_to_send.end(); ++it) {
						ss << (*it).getFile().getBasename() << " ";
					}
					IBRCOMMON_LOGGER_TAG("dtnoutbox",info) << "files sent: " << ss.str() << IBRCOMMON_LOGGER_ENDL;

					try {
						// create a blob
						ibrcommon::BLOB::Reference blob = ibrcommon::BLOB::create();

						// write files into BLOB while it is locked
						{
							ibrcommon::BLOB::iostream stream = blob.iostream();
							io::TarUtils::write(*stream, root, files_to_send);
						}

						// create a new bundle
						dtn::data::EID destination = EID(conf.destination);

						// create a new bundle
						dtn::data::Bundle b;

						// set destination
						b.destination = destination;

						// add payload block using the blob
						b.push_back(blob);

						// set destination address to non-singleton, if configured
						if (conf.bundle_group)
							b.set(dtn::data::PrimaryBlock::DESTINATION_IS_SINGLETON, false);

						// send the bundle
						client << b;
						client.flush();
					} catch (const ibrcommon::IOException &e) {
						IBRCOMMON_LOGGER_TAG(TAG,error) << "send failed: " << e.what() << IBRCOMMON_LOGGER_ENDL;
					}
				}

				// wait defined seconds
				ibrcommon::MutexLock l(_wait_cond);
				IBRCOMMON_LOGGER_TAG(TAG, notice) << conf.interval <<" ms wait" << IBRCOMMON_LOGGER_ENDL;
				while (!_wait_abort && _running) {
					_wait_cond.wait(conf.interval);
				}
				_wait_abort = false;
			}

			// clean up regex
			regfree(&conf.regex);

			// close the client connection
			client.close();

			// close the connection
			conn.close();

		}
		catch (const ibrcommon::socket_exception&)
		{
			if (_running)
			{
				IBRCOMMON_LOGGER_TAG(TAG,error) << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << IBRCOMMON_LOGGER_ENDL;
				ibrcommon::Thread::sleep(backoff * 1000);

				// if backoff < 10 minutes
				if (backoff < 600)
				{
					// set a new backoff
					backoff = backoff * 2;
				}
			}
		}
		catch (const ibrcommon::IOException&)
		{
			if (_running)
			{
				IBRCOMMON_LOGGER_TAG(TAG,error) << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << IBRCOMMON_LOGGER_ENDL;
				ibrcommon::Thread::sleep(backoff * 1000);

				// if backoff < 10 minutes
				if (backoff < 600)
				{
					// set a new backoff
					backoff = backoff * 2;
				}
			}
		}
		catch (const std::exception&) { };
	}

	// clear observed files
	observed_files.clear();

#ifdef HAVE_LIBTFFS
	// clean-up
	if (imagereader != NULL) delete imagereader;
#endif

	return (EXIT_SUCCESS);
}