Protocols( ping_protocol_list ),
ProtocolIter(),
PingIntervalInSec( ping_interval_in_sec ),
+ NPingers( n_parallel_pings ),
FirstDelay( first_delay ),
NextPingTimer( *io_serv ),
TimeSentLastPing( microsec_clock::universal_time() ),
link_analyzer ),
Resolver(),
Pingers(),
- NPingers( n_parallel_pings ),
NPingersDone( 0 ),
ParallelPingDelay( parallel_ping_delay ),
DelayedPingTimer( *io_serv ),
update_log_prefix();
init_ping_protocol();
+
+ // start resolving already so we are prepared to ping
+ update_dns_resolver();
+
}
/**
return;
}
else if ( !Resolver )
+ {
// should not happen, but check anyway
GlobalLogger.warning() << LogPrefix << "Have no resolver!";
+ return;
+ }
GlobalLogger.info() << LogPrefix << "start ping";
WantToPing = false;
}
else
{
+ // create new pingers
+ for (int count=0; count<NPingers; ++count)
+ Pingers.push_back(
+ PingerFactory::createPinger(*ProtocolIter, IoService,
+ NetworkInterfaceName,
+ PingReplyTimeout) );
+
+ // remember when pinging started
+ TimeSentLastPing = microsec_clock::universal_time();
+
+ // get actual IP
boost::asio::ip::address actual_ip = ip.get_ip();
GlobalLogger.info() << LogPrefix << "pinging IP " << actual_ip
<< " with TTL " << ip.get_ttl().get_updated_value() << "s";
- delayed_ping(boost::system::error_code(), actual_ip, 0);
NPingersDone = 0;
- TimeSentLastPing = microsec_clock::universal_time();
+ delayed_ping(boost::system::error_code(), actual_ip, 0);
}
}
void PingScheduler::delayed_ping( const boost::system::error_code &error,
- const boost::asio::ip::address &ip,
+ const boost::asio::ip::address ip,
const int pinger_index )
{
if (error)
<< error;
return;
}
- if (pinger_index == NPingers)
- {
- GlobalLogger.debug() << LogPrefix << "started all delayed pings";
- return;
- }
GlobalLogger.debug() << LogPrefix << "starting delayed ping index "
<< pinger_index;
DestinationPort,
boost::bind(&PingScheduler::ping_done_handler,
this, _1, _2) );
- DelayedPingTimer.expires_from_now( milliseconds(ParallelPingDelay) );
- DelayedPingTimer.async_wait( bind( &PingScheduler::delayed_ping,
+ if (pinger_index >= NPingers-1)
+ GlobalLogger.debug() << LogPrefix << "started all delayed pings";
+ else
+ {
+ DelayedPingTimer.expires_from_now( milliseconds(ParallelPingDelay) );
+ DelayedPingTimer.async_wait( bind( &PingScheduler::delayed_ping,
this, boost::asio::placeholders::error, ip, pinger_index+1) );
+ }
}
// prepare next ping only after all pingers are done
if (NPingersDone == NPingers)
+ {
+ // stop and destruct all pingers
+ clear_pingers();
+
+ GlobalLogger.debug() << LogPrefix
+ << "--------------------------------------------------------------";
+
+ // update variables for next ping: number of pings, delay, protocol
+ update_ping_protocol();
+ update_ping_interval();
+ update_ping_number();
+
prepare_next_ping();
+ }
}
void PingScheduler::prepare_next_ping()
{
- update_ping_interval();
-
- // get next protocol, possibly start resolving IPs
- update_ping_protocol();
+ // start DNS resolve if necessary
+ update_dns_resolver();
// schedule next ping
int seconds_since_last_ping = (microsec_clock::universal_time()
}
}
+/** in case of congested line, increase number of pings
+ *
+ * CAUTION! Only call this after clear_pingers !!!
+ * */
+void PingScheduler::update_ping_number()
+{
+ // make sure we do not loose track of pingers here
+ if ( NPingersDone != NPingers || !Pingers.empty() )
+ {
+ GlobalLogger.warning() << LogPrefix << "Should only change number of "
+ << "pingers when all are finished and deleted! Have " << NPingers
+ << " pingers, " << NPingersDone << " of which are done and "
+ << Pingers.size() << " in listDone! Will not change NPingers.";
+ return;
+ }
+
+ if ( HostAnalyzer.exceeded_ping_congestion_limit() )
+ {
+ NPingers.increase();
+
+ GlobalLogger.debug() << LogPrefix << "- Increasing ping number to: "
+ << NPingers;
+ }
+ else
+ {
+ NPingers.back_to_original();
+
+ GlobalLogger.debug() << LogPrefix << "- Stick to the original ping "
+ << "number: " << NPingers;
+ }
+
+ HostAnalyzer.set_n_parallel_pings(NPingers);
+}
+
//------------------------------------------------------------------------------
// Ping Protocol Rotation
//------------------------------------------------------------------------------
void PingScheduler::get_next_ping_protocol()
{
- // stop and destruct all pingers
- clear_pingers();
- GlobalLogger.debug() << LogPrefix
- << "------------------------------------------------------------------";
-
- // get next protocol
++ProtocolIter;
if (ProtocolIter == Protocols.end())
ProtocolIter = Protocols.begin();
- PingProtocol ping_protocol = *ProtocolIter;
- // --> ProtocolIter still points to currently used protocol which is
- // required in dns_resolve_callback
-
- // create new pingers
- for (int count=0; count<NPingers; ++count)
- Pingers.push_back( PingerFactory::createPinger(ping_protocol, IoService,
- NetworkInterfaceName, PingReplyTimeout) );
-
- update_dns_resolver( ping_protocol );
}
bool PingScheduler::can_change_ping_protocol() const
LogPrefix = temp.str();
}
-void PingScheduler::update_dns_resolver( PingProtocol current_protocol )
+void PingScheduler::update_dns_resolver()
{
if (Resolver && Resolver->is_resolving())
cancel_resolve(false);
// probably just return an existing resolver with already resolved IPs for
// requested protocol ( ICMP/TCP is ignored, only IPv4/v6 is important)
Resolver = DnsMaster::get_instance()->get_resolver_for(DestinationAddress,
- current_protocol);
+ *ProtocolIter);
// get number of up-to-date IPs
// TODO should check here, if they will be up to date in PingIntervalInSec