From e39cc3daca80b30f7085950ab1c3dbb18521c6b9 Mon Sep 17 00:00:00 2001 From: Guilherme Maciel Ferreira Date: Tue, 8 Mar 2011 18:56:29 +0100 Subject: [PATCH] The application now pings many hosts in parallel - uses an asynchronous approach, based on boost::asio::io_service::run() loop and asynchronous timers --- conf/pingcheck.conf | 8 +++--- src/main.cpp | 19 ++++++++++++-- src/ping/pingcheck.cpp | 65 +++++++++++++++++++++++++++-------------------- src/ping/pingcheck.h | 25 ++++++++++++++--- 4 files changed, 77 insertions(+), 40 deletions(-) diff --git a/conf/pingcheck.conf b/conf/pingcheck.conf index d9ed170..642876d 100644 --- a/conf/pingcheck.conf +++ b/conf/pingcheck.conf @@ -2,12 +2,12 @@ limit-to-notify=5 [host] name=www.intra2net.com -interval=4 +interval=30 [host] -name=209.85.148.105 -interval=2 +name=www.google.com +interval=5 [host] name=www.ufsc.br -interval=3 +interval=60 diff --git a/src/main.cpp b/src/main.cpp index 8e4bdde..43db4c7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -6,6 +7,7 @@ #include "pingcheck.h" using namespace std; +using namespace boost::asio; int main( int argc, char* argv[] ) { @@ -13,13 +15,24 @@ int main( int argc, char* argv[] ) bool read_success = config_reader.parse( argc, argv ); if ( read_success ) { + io_service io_service; + Configuration config = config_reader.get_configuration(); - vector hosts = config.get_hosts(); + vector< HostItem > hosts = config.get_hosts(); + vector< PingCheckItem > check_list; BOOST_FOREACH( HostItem host, hosts ) { - PingCheck check( *host ); - check.start_pinging(); + PingCheckItem check( new PingCheck( io_service, *host ) ); + check_list.push_back( check ); } + + BOOST_FOREACH( PingCheckItem check, check_list ) + { + check->start_pinging(); + } + + // Main loop to handle ping requests when they were scheduled + io_service.run(); } return 0; diff --git a/src/ping/pingcheck.cpp b/src/ping/pingcheck.cpp index d7b1bd5..9551d16 100644 --- a/src/ping/pingcheck.cpp +++ b/src/ping/pingcheck.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include "boostpinger.h" @@ -7,13 +7,20 @@ using namespace std; using namespace boost::asio; +using namespace boost::posix_time; //----------------------------------------------------------------------------- // PingCheck //----------------------------------------------------------------------------- -PingCheck::PingCheck( const Host &host ) : - Host_( host ) +PingCheck::PingCheck( + boost::asio::io_service &io_service, + const Host &host +) : + IoService( io_service ), + Timer( io_service ), + TimeSentLastPing( microsec_clock::universal_time() ), + DestinationHost( host ) { } @@ -23,45 +30,47 @@ PingCheck::~PingCheck() void PingCheck::start_pinging() { - string destination = Host_.get_address(); - uint ping_set_total = 3; // TODO configurable: + string destination = DestinationHost.get_address(); + uint ping_set_total = 1; // TODO configurable: uint ping_set_count = 0; while ( ping_set_count < ping_set_total ) { - ping_and_wait( destination ); + ping( destination ); ping_set_count++; } } -void PingCheck::ping_and_wait( const string &destination ) +void PingCheck::ping( const string &destination ) { - try - { - ping( destination ); + BOOST_ASSERT( !destination.empty() ); - wait(); - } - catch ( exception& e ) - { - cerr << "Exception: " << e.what() << endl; - return; - } -} - -void PingCheck::ping( const string &destination ) throw ( exception& ) -{ - uint times_to_ping = 3; // TODO configurable: this must be automatically selected + uint times_to_ping = 1; // TODO configurable: this must be automatically selected boost::asio::io_service io_service; BoostPinger pinger( io_service ); pinger.ping( destination, times_to_ping ); + + update_ping_statistics(); + + schedule_next_ping(); } -void PingCheck::wait() +void PingCheck::update_ping_statistics() { - boost::asio::io_service io_service; - deadline_timer timer( io_service ); - uint interval = Host_.get_interval(); // TODO configurable: - timer.expires_from_now( boost::posix_time::seconds( interval ) ); - timer.wait(); + ptime now = microsec_clock::universal_time(); // TODO + cerr << "- Time elapsed since last ping = " + << (now - TimeSentLastPing).total_seconds() << "s" << endl; // TODO + TimeSentLastPing = microsec_clock::universal_time(); // TODO +} + +void PingCheck::schedule_next_ping() +{ + uint interval = DestinationHost.get_interval(); // TODO configurable: + Timer.expires_from_now( seconds( interval ) ); + Timer.async_wait( boost::bind( &PingCheck::handle_next_ping, this ) ); +} + +void PingCheck::handle_next_ping() +{ + start_pinging(); } diff --git a/src/ping/pingcheck.h b/src/ping/pingcheck.h index 6c940e2..e733385 100644 --- a/src/ping/pingcheck.h +++ b/src/ping/pingcheck.h @@ -1,6 +1,8 @@ #ifndef PINGCHECK_H #define PINGCHECK_H +#include +#include #include #include "host.h" @@ -12,19 +14,32 @@ class PingCheck { public: - PingCheck( const Host &host ); + PingCheck( + boost::asio::io_service &io_service, + const Host &host + ); virtual ~PingCheck(); void start_pinging(); private: - void ping_and_wait( const std::string &destination ); - void ping( const std::string &destination ) throw ( std::exception& ); - void wait(); + void ping( const std::string &destination ); + void update_ping_statistics(); + void schedule_next_ping(); + void handle_next_ping(); private: - Host Host_; + boost::asio::io_service &IoService; + boost::asio::deadline_timer Timer; + boost::posix_time::ptime TimeSentLastPing; + Host DestinationHost; }; +//----------------------------------------------------------------------------- +// PingCheckItem +//----------------------------------------------------------------------------- + +typedef boost::shared_ptr PingCheckItem; + #endif /* PINGCHECK_H */ -- 1.7.1