Handle the error when a host cannot be resolved
authorGuilherme Maciel Ferreira <guilherme.maciel.ferreira@intra2net.com>
Fri, 18 Mar 2011 11:39:53 +0000 (12:39 +0100)
committerGuilherme Maciel Ferreira <guilherme.maciel.ferreira@intra2net.com>
Fri, 18 Mar 2011 11:39:53 +0000 (12:39 +0100)
- reorganization of PingScheduler to do not ping a host that was not resolved
- from now, the DnsResolver::resolve() method must be explicitly called by the client of the class

Readme
src/dns/dnsresolver.cpp
src/dns/dnsresolver.h
src/ping/pingscheduler.cpp
src/ping/pingscheduler.h

diff --git a/Readme b/Readme
index 0733905..e4cfe76 100644 (file)
--- a/Readme
+++ b/Readme
@@ -88,6 +88,23 @@ where:
   they are optional and not required in public release.
 
 
+2.4. Error Handling
+---------------------------------------
+There are two basic kinds of errors that shall happen in the program, errors
+that the program can recover (expected) and errors that the progam can not or
+should not recover from (exceptional errors). Bellow the description and the
+method adopted to deal with each one:
+- Expected: these errors can occur and must be handled by boolean return values.
+  (i.e. if a host is down, if the address was not resolved). This errors can
+  happen, but THE PROGRAM MUST CONTINUE TO OPERATE EVEN IF THEY HAPPEN.
+- Exceptional: these are the kinds of errors that should not occur. They must be
+  handled by exceptions and THE PROGRAM MUST HALT IF THEY HAPPEN.
+Thus, to keep things as simple as possible, this program adopts just two kinds
+of error detection and handling:
+- Return Boolean Value for expected errors and
+- Handle Exceptions for exceptional errors.
+
+
 
 3.   Source Code
 =======================================
index 54cb70a..eaf8370 100644 (file)
@@ -14,16 +14,62 @@ using namespace boost::asio::ip;
 // DnsResolver
 //-----------------------------------------------------------------------------
 
-DnsResolver::DnsResolver( string dns_address ) :
-        ResolvedHostAddressList()
+DnsResolver::DnsResolver( const string &dns_address ) :
+    ResolvedHostAddressList(),
+    HostDnsAddress( dns_address )
 {
-    resolve( dns_address );
 }
 
 DnsResolver::~DnsResolver()
 {
 }
 
+/**
+ * Resolve the IPs from this DNS and build a list of these IPs.
+ *
+ * @return true if the host address could be resolved, or false otherwise.
+ */
+bool DnsResolver::resolve()
+{
+    BOOST_ASSERT( !HostDnsAddress.empty() );
+
+    cerr << "* Host : " << HostDnsAddress << endl;
+
+    try
+    {
+        io_service io_service;
+        tcp::resolver resolver( io_service );
+        tcp::resolver::query query( tcp::v4(), HostDnsAddress, "" );
+        tcp::resolver::iterator it_first = resolver.resolve( query );
+        tcp::resolver::iterator it_last = tcp::resolver::iterator();
+        while ( it_first != it_last )
+        {
+            string ip = (*it_first).endpoint().address().to_string();
+
+            HostAddress resolved_host;
+            resolved_host.set_ip( ip );
+            ResolvedHostAddressList.push_back( resolved_host );
+
+            cerr << ip << endl;
+
+            ++it_first;
+        }
+    }
+    catch ( boost::system::system_error& ex )
+    {
+        cerr << "Error: host " << HostDnsAddress << " could not be resolved."
+             << endl;
+        return false;
+    }
+
+    BOOST_ASSERT( 1 <= ResolvedHostAddressList.size() );
+
+    return true;
+}
+
+/**
+ * @return the amount of IPs resolved for the DNS.
+ */
 int DnsResolver::get_resolved_ip_count()
 {
     int resolved_ip_count = ResolvedHostAddressList.size();
@@ -33,6 +79,10 @@ int DnsResolver::get_resolved_ip_count()
     return resolved_ip_count;
 }
 
+/**
+ * @return the next IP string in the list of resolved IPs. When reach the last
+ * IP, it goes back to first, like a circular buffer.
+ */
 string DnsResolver::get_next_ip()
 {
     uint list_size_before = ResolvedHostAddressList.size();
@@ -43,40 +93,8 @@ string DnsResolver::get_next_ip()
     ResolvedHostAddressList.push_back( host_address );
 
     uint list_size_after = ResolvedHostAddressList.size();
+
     BOOST_ASSERT( list_size_before == list_size_after );
 
     return destination_ip;
 }
-
-/**
- * Resolve which IPs belong to the given DNS and build a list of these IPs.
- *
- * @param dns_address The DNS address to be query for IPs.
- */
-void DnsResolver::resolve( string dns_address )
-{
-    BOOST_ASSERT( !dns_address.empty() );
-
-    cerr << " - Host : " << dns_address << endl;
-
-    io_service io_service;
-    tcp::resolver resolver( io_service );
-    tcp::resolver::query query( tcp::v4(), dns_address, "" );
-    // TODO can throw exceptions if a host is not found
-    tcp::resolver::iterator it_first = resolver.resolve( query );
-    tcp::resolver::iterator it_last = tcp::resolver::iterator();
-    while ( it_first != it_last )
-    {
-        string ip = (*it_first).endpoint().address().to_string();
-
-        HostAddress resolved_host;
-        resolved_host.set_ip( ip );
-        ResolvedHostAddressList.push_back( resolved_host );
-
-        cerr << "   |_ " << ip << endl;
-
-        ++it_first;
-    }
-
-    BOOST_ASSERT( 0 < ResolvedHostAddressList.size() );
-}
index 635b5ab..990cf31 100644 (file)
@@ -13,17 +13,16 @@ class HostAddress;
 class DnsResolver
 {
 public:
-    explicit DnsResolver( std::string dns_address );
+    explicit DnsResolver( const std::string &dns_address );
     virtual ~DnsResolver();
 
+    bool resolve();
     int get_resolved_ip_count();
     std::string get_next_ip();
 
 private:
-    void resolve( std::string dns_address );
-
-private:
     std::list<HostAddress> ResolvedHostAddressList;
+    const std::string HostDnsAddress;
 
 };
 
index d0956d8..ee320e7 100644 (file)
@@ -28,22 +28,47 @@ PingScheduler::PingScheduler(
     PingIntervalInSec( ping_interval_in_sec ),
     Analyzer( ping_address, 50 ) // 50% max acceptable failure
 {
-    uint resolved_ip_count = IpList.get_resolved_ip_count();
-    Analyzer.set_resolved_ip_count( resolved_ip_count );
 }
 
 PingScheduler::~PingScheduler()
 {
 }
 
-void PingScheduler::start_pinging()
+bool PingScheduler::start_pinging()
 {
-    string destination_ip = IpList.get_next_ip();
+    bool address_resolved = resolve_ping_address();
+    if ( !address_resolved )
+    {
+        return false;
+    }
+
+    schedule_next_ping();
+
+    return true;
+}
+
+bool PingScheduler::resolve_ping_address()
+{
+    bool address_resolved = IpList.resolve();
+    if ( !address_resolved )
+    {
+        return false;
+    }
+
+    int resolved_ip_count = IpList.get_resolved_ip_count();
+    Analyzer.set_resolved_ip_count( resolved_ip_count );
 
+    return true;
+}
+
+void PingScheduler::setup_ping()
+{
+    BOOST_ASSERT( 1 <= IpList.get_resolved_ip_count() );
+
+    string destination_ip = IpList.get_next_ip();
     bool ping_success = ping( destination_ip );
 
     update_ping_statistics( ping_success );
-
     update_ping_elapsed_time();
 
     schedule_next_ping();
@@ -60,6 +85,19 @@ bool PingScheduler::ping( const string &destination )
     return pinger.ping( destination );
 }
 
+void PingScheduler::schedule_next_ping()
+{
+    BOOST_ASSERT( 0 < PingIntervalInSec );
+
+    Timer.expires_from_now( seconds( PingIntervalInSec ) );
+    Timer.async_wait( bind( &PingScheduler::handle_next_ping, this ) );
+}
+
+void PingScheduler::handle_next_ping()
+{
+    setup_ping();
+}
+
 void PingScheduler::update_ping_statistics( const bool ping_success )
 {
     Analyzer.update_ping_statistics( ping_success );
@@ -73,14 +111,3 @@ void PingScheduler::update_ping_elapsed_time()
 
     TimeSentLastPing = microsec_clock::universal_time();
 }
-
-void PingScheduler::schedule_next_ping()
-{
-    Timer.expires_from_now( seconds( PingIntervalInSec ) );
-    Timer.async_wait( bind( &PingScheduler::handle_next_ping, this ) );
-}
-
-void PingScheduler::handle_next_ping()
-{
-    start_pinging();
-}
index e33b977..f4bc992 100644 (file)
@@ -23,14 +23,16 @@ public:
     );
     virtual ~PingScheduler();
 
-    void start_pinging();
+    bool start_pinging();
 
 private:
+    bool resolve_ping_address();
+    void setup_ping();
     bool ping( const std::string &destination );
-    void update_ping_statistics( const bool ping_success );
-    void update_ping_elapsed_time();
     void schedule_next_ping();
     void handle_next_ping();
+    void update_ping_statistics( const bool ping_success );
+    void update_ping_elapsed_time();
 
 private:
     boost::asio::io_service &IoService;