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
=======================================
// 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();
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();
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() );
-}
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;
};
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();
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 );
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();
-}
);
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;