Implemented feature: cache DNS requests info only until DNS reply is valid (TTL).
authorGuilherme Maciel Ferreira <guilherme.maciel.ferreira@intra2net.com>
Mon, 18 Apr 2011 10:46:45 +0000 (12:46 +0200)
committerGuilherme Maciel Ferreira <guilherme.maciel.ferreira@intra2net.com>
Mon, 18 Apr 2011 10:46:45 +0000 (12:46 +0200)
- created a class TimeToLive which is self updatable, and can get the ttl updated
- before each ping checks if the address is valid, if not, builds another IP list (which renews the ttl)

src/CMakeLists.txt
src/dns/dnsresolver.cpp
src/dns/dnsresolver.h
src/dns/hostaddress.cpp
src/dns/hostaddress.h
src/dns/timetolive.cpp [new file with mode: 0644]
src/dns/timetolive.h [new file with mode: 0644]
src/host/pingscheduler.cpp

index be4b8e9..82dbcbe 100644 (file)
@@ -27,6 +27,7 @@ set(SOURCES
     config/host.cpp
     dns/dnsresolver.cpp
     dns/hostaddress.cpp
+    dns/timetolive.cpp
     host/boostpinger.cpp
     host/hoststatusanalyzer.cpp
     host/pingscheduler.cpp
index bd33585..dea6720 100644 (file)
@@ -3,6 +3,7 @@
 #include <iostream>
 
 #include <boost/asio.hpp>
+#include <boost/foreach.hpp>
 #include <boost/net/dns.hpp>
 #include <boost/net/resolve.hpp>
 
@@ -60,6 +61,8 @@ bool DnsResolver::resolve()
             return false;
         }
 
+        ResolvedHostAddressList.clear();
+
         for ( rr_list_t::iterator riter = answers->begin();
               riter != answers->end();
               ++riter )
@@ -77,7 +80,7 @@ bool DnsResolver::resolve()
                 HostAddress resolved_host( ip, ttl );
                 ResolvedHostAddressList.push_back( resolved_host );
 
-                cout << "- " << ip << endl;
+                cout << "- " << ip << " [" << ttl << "s]" << endl;
             }
         }
     }
@@ -116,13 +119,29 @@ string DnsResolver::get_next_ip()
     HostAddress host_address = ResolvedHostAddressList.front();
     ResolvedHostAddressList.pop_front();
     string destination_ip = host_address.get_ip();
+    int ttl = host_address.get_ttl().get_updated_value();
     ResolvedHostAddressList.push_back( host_address );
 
     size_t list_size_after = ResolvedHostAddressList.size();
 
+    BOOST_ASSERT( 0 < ttl );
     BOOST_ASSERT( list_size_before == list_size_after );
 
-    // TODO check the ttl of the resolved IP, if it is next to zero, call the resolve again
-
     return destination_ip;
 }
+
+bool DnsResolver::expired_resolved_ip()
+{
+    const int threshold = 10; // TODO configurable
+
+    BOOST_FOREACH( HostAddress host_address, ResolvedHostAddressList )
+    {
+        int ttl = host_address.get_ttl().get_updated_value();
+        if ( ttl <= threshold )
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
index 0ef5e7c..1d3b024 100644 (file)
@@ -21,8 +21,11 @@ public:
 
     bool resolve();
     int get_resolved_ip_count() const;
+
     std::string get_next_ip();
 
+    bool expired_resolved_ip();
+
 private:
     std::list<HostAddress> ResolvedHostAddressList;
     const std::string HostDnsAddress;
index a7cc69c..9aa92d4 100644 (file)
@@ -1,5 +1,7 @@
 #include "dns/hostaddress.h"
 
+#include <boost/assert.hpp>
+
 using namespace std;
 
 //-----------------------------------------------------------------------------
@@ -13,7 +15,7 @@ HostAddress::HostAddress() :
 }
 
 HostAddress::HostAddress(
-        string ip,
+        const string &ip,
         int ttl
 ) :
     Ip( ip ),
@@ -25,23 +27,24 @@ HostAddress::~HostAddress()
 {
 }
 
-void HostAddress::set_ip( string ip )
+string HostAddress::get_ip() const
 {
-    this->Ip = ip;
+    return Ip;
 }
 
-string HostAddress::get_ip() const
+void HostAddress::set_ip( const string &ip )
 {
-    return Ip;
+    BOOST_ASSERT( !ip.empty() );
+
+    Ip = ip;
 }
 
-int HostAddress::get_ttl() const
+TimeToLive HostAddress::get_ttl() const
 {
     return Ttl;
 }
 
-void HostAddress::set_ttl( int ttl )
+void HostAddress::set_ttl( const TimeToLive &ttl )
 {
-    this->Ttl = ttl;
+    Ttl = ttl;
 }
-
index 061b798..7ffd031 100644 (file)
@@ -1,10 +1,10 @@
 #ifndef HOSTADDRESS_H_
 #define HOSTADDRESS_H_
 
-#include <sys/types.h>
-
 #include <string>
 
+#include "dns/timetolive.h"
+
 //-----------------------------------------------------------------------------
 // HostAddress
 //-----------------------------------------------------------------------------
@@ -13,18 +13,21 @@ class HostAddress
 {
 public:
     HostAddress();
-    HostAddress( std::string ip, int ttl );
+    HostAddress(
+            const std::string &ip,
+            int ttl
+    );
     ~HostAddress();
 
     std::string get_ip() const;
-    void set_ip( std::string ip );
+    void set_ip( const std::string &ip );
 
-    int get_ttl() const;
-    void set_ttl( int ttl );
+    TimeToLive get_ttl() const;
+    void set_ttl( const TimeToLive &ttl );
 
 private:
     std::string Ip;
-    int Ttl;
+    TimeToLive Ttl;
 
 };
 
diff --git a/src/dns/timetolive.cpp b/src/dns/timetolive.cpp
new file mode 100644 (file)
index 0000000..21e02c1
--- /dev/null
@@ -0,0 +1,46 @@
+#include "dns/timetolive.h"
+
+#include <boost/assert.hpp>
+
+using boost::date_time::time_resolution_traits_adapted64_impl;
+using boost::posix_time::microsec_clock;
+using boost::posix_time::ptime;
+
+//-----------------------------------------------------------------------------
+// TimeToLive
+//-----------------------------------------------------------------------------
+
+TimeToLive::TimeToLive( int ttl ) :
+    Ttl( ttl ),
+    TtlSetTime( microsec_clock::universal_time() )
+{
+}
+
+TimeToLive::~TimeToLive()
+{
+}
+
+int TimeToLive::get_value() const
+{
+    return Ttl;
+}
+
+void TimeToLive::set_value( const int ttl )
+{
+    BOOST_ASSERT( 0 < ttl );
+
+    Ttl = ttl;
+    TtlSetTime = microsec_clock::universal_time();
+}
+
+int TimeToLive::get_updated_value() const
+{
+    ptime now = microsec_clock::universal_time();
+    int elapsed_seconds = static_cast<int> (
+            (now - TtlSetTime).total_seconds()
+    );
+    int original_ttl = get_value();
+    int remaining_seconds = original_ttl - elapsed_seconds;
+
+    return remaining_seconds;
+}
diff --git a/src/dns/timetolive.h b/src/dns/timetolive.h
new file mode 100644 (file)
index 0000000..4f17302
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef TIMETOLIVE_H
+#define TIMETOLIVE_H
+
+#include <boost/asio.hpp>
+
+//-----------------------------------------------------------------------------
+// TimeToLive
+//-----------------------------------------------------------------------------
+
+class TimeToLive
+{
+public:
+    TimeToLive( int ttl = 0 );
+    ~TimeToLive();
+
+    int get_value() const;
+    void set_value( const int ttl );
+
+    int get_updated_value() const;
+
+private:
+    int Ttl;
+    boost::posix_time::ptime TtlSetTime;
+};
+
+#endif /* TIMETOLIVE_H */
index 5a05c34..7620b33 100644 (file)
@@ -5,12 +5,13 @@
 #include <boost/bind.hpp>
 
 #include "dns/dnsresolver.h"
-#include "link/linkstatusanalyzer.h"
 #include "host/boostpinger.h"
+#include "link/linkstatusanalyzer.h"
 
 using namespace std;
 using boost::asio::io_service;
 using boost::bind;
+using boost::date_time::time_resolution_traits_adapted64_impl;
 using boost::posix_time::microsec_clock;
 using boost::posix_time::ptime;
 using boost::posix_time::seconds;
@@ -46,9 +47,6 @@ PingScheduler::~PingScheduler()
 
 bool PingScheduler::start_pinging()
 {
-    // TODO the DNS resolution is called only once. Find a way to resolve when
-    // the TTL ends
-    // TODO does the DNS keeps the same number of IPs?
     bool address_resolved = resolve_ping_address();
     if ( !address_resolved )
     {
@@ -93,6 +91,18 @@ void PingScheduler::setup_next_ping()
 {
     BOOST_ASSERT( 1 <= IpList.get_resolved_ip_count() );
 
+    // TODO this code is similar to the one at start_pinging(), make it simple!
+    if ( IpList.expired_resolved_ip() )
+    {
+        cout << "Updating DNS ... "; // TODO
+        bool address_resolved = resolve_ping_address();
+        if ( !address_resolved )
+        {
+            cerr << "Error: could not update host IP, may use outdated address"
+                 << endl;
+        }
+    }
+
     string destination_ip = IpList.get_next_ip();
     bool ping_success = ping( destination_ip );
 
@@ -143,8 +153,9 @@ void PingScheduler::update_ping_interval()
 void PingScheduler::update_ping_elapsed_time()
 {
     ptime now = microsec_clock::universal_time();
-    cout << "- Time elapsed since last ping: "
-         << (now - TimeSentLastPing).total_seconds() << "s"
+    time_resolution_traits_adapted64_impl::int_type elapsed_time_in_sec =
+            (now - TimeSentLastPing).total_seconds();
+    cout << "- Time elapsed since last ping: " << elapsed_time_in_sec << "s"
          << endl; // TODO output log
 
     TimeSentLastPing = microsec_clock::universal_time();