From 3c0cd271437bfbca22cced2755a7fc2ccff6999f Mon Sep 17 00:00:00 2001 From: Bjoern Sikora Date: Mon, 17 Aug 2009 17:53:43 +0200 Subject: [PATCH] Introduced new Service members: UpdateInterval and MaxUpdatesWithinInterval. Implemented logic to avoid too much updates within interval. --- src/config.cpp | 47 +++++++++++++++++++++------- src/config.h | 2 +- src/dhs.cpp | 78 +++++++++++++---------------------------------- src/dhs.h | 12 +------- src/iphelper.cpp | 10 ++++-- src/logger.cpp | 69 +++++++++++++++++++++++++++++++++++++---- src/logger.h | 8 ++++- src/main.cpp | 2 - src/ods.cpp | 88 ++++++++++++++++++----------------------------------- src/ods.h | 12 +------- src/service.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++++++------- src/service.h | 21 ++++++++----- src/updater.cpp | 8 +++-- 13 files changed, 262 insertions(+), 184 deletions(-) diff --git a/src/config.cpp b/src/config.cpp index 98a4235..f6e2290 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -60,6 +60,8 @@ Config::Config(Logger::Ptr _log) ("host",po::value(),"The hostname to update.") ("login",po::value(),"Login name.") ("password",po::value(),"Corresponding password.") + ("update_interval",po::value()->default_value(-1),"Update interval in minutes.") + ("max_updates_within_interval",po::value()->default_value(-1),"How many updates can be made in one interval.") ; // Available command line only options @@ -129,7 +131,7 @@ int Config::serialize_services() BOOST_FOREACH(Service::Ptr &service, OldServices) { - if ( ( service->get_lastupdated() + service->get_timeout() ) >= current_time ) // Update Timeout of service isn't expired. + if ( ( service->get_last_updates()->front() + (service->get_update_interval()*60) ) >= current_time ) // UpdateInterval timeout of service isn't expired. service_holder->add_service(service); } @@ -207,17 +209,16 @@ int Config::deserialize_services() BOOST_FOREACH(Service::Ptr &old_service, _old_services) { OldServices.push_back(old_service); - Log->print_service_object("Deserialized following Service object:", old_service->get_protocol(), old_service->get_hostname(), old_service->get_login() ,old_service->get_password() ,old_service->get_actual_ip(), old_service->get_lastupdated()); + Log->print_service_object("Deserialized following Service object:", old_service->get_protocol(), old_service->get_hostname(), old_service->get_login() ,old_service->get_password(), old_service->get_update_interval(), old_service->get_max_updates_within_interval(), old_service->get_actual_ip(), old_service->get_last_updates()); BOOST_FOREACH(Service::Ptr &service, Services) { if ( *service == *old_service ) { - service->set_lastupdated(old_service->get_lastupdated()); + service->set_last_updates(old_service->get_last_updates()); service->set_actual_ip(old_service->get_actual_ip()); - Log->print_service_object("New Service object with adopted values:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password() ,service->get_actual_ip(), service->get_lastupdated()); + Log->print_service_object("New Service object with adopted values:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password(), service->get_update_interval(), service->get_max_updates_within_interval(), service->get_actual_ip(), service->get_last_updates()); // We have adopted the values of the old_service. Just set lastupdated and timeout to 0, so this old_service wont be serialized. - old_service->set_lastupdated(0); - old_service->set_timeout(0); + old_service->set_update_interval(0); } } } @@ -268,7 +269,15 @@ int Config::parse_cmd_line(int argc, char *argv[]) protocol = ba::to_lower_copy(protocol); - Service::Ptr service = create_service(protocol,host,login,password); + int update_interval = 0; + if ( VariablesMap.count("update_interval") ) + update_interval = VariablesMap["update_interval"].as(); + + int max_updates_within_interval = 0; + if ( VariablesMap.count("max_updates_within_interval") ) + max_updates_within_interval = VariablesMap["max_updates_within_interval"].as(); + + Service::Ptr service = create_service(protocol,host,login,password,update_interval,max_updates_within_interval); if ( service ) Services.push_back(service); else @@ -318,6 +327,12 @@ int Config::parse_cmd_line(int argc, char *argv[]) Log->print_usage(OptDescCmd); return -1; } + catch(po::multiple_occurrences e) + { + Log->print_multiple_cmd_option(e.what()); + Log->print_usage(OptDescCmd); + return -1; + } return 0; } @@ -330,16 +345,16 @@ int Config::parse_cmd_line(int argc, char *argv[]) * @param password Password. * @return A pointer to the created Service object. */ -Service::Ptr Config::create_service(const string &protocol,const string &hostname, const string &login, const string &password) +Service::Ptr Config::create_service(const string &protocol,const string &hostname, const string &login, const string &password, const int update_interval, const int max_updates_within_interval) { if(protocol == "dhs") { - Service::Ptr service_dhs(new DHS(protocol,hostname,login,password,Log,0,60,1)); + Service::Ptr service_dhs(new DHS(protocol,hostname,login,password,Log,update_interval,max_updates_within_interval)); return service_dhs; } else if(protocol == "ods") { - Service::Ptr service_ods(new ODS(protocol,hostname,login,password,Log,0,60,1)); + Service::Ptr service_ods(new ODS(protocol,hostname,login,password,Log,update_interval,max_updates_within_interval)); return service_ods; } else @@ -380,11 +395,19 @@ int Config::load_service_config_file(const string& full_filename) protocol = ba::to_lower_copy(protocol); - Service::Ptr service = create_service(protocol,host,login,password); + int update_interval = 0; + if ( VariablesMap.count("update_interval") ) + update_interval = VariablesMap["update_interval"].as(); + + int max_updates_within_interval = 0; + if ( VariablesMap.count("max_updates_within_interval") ) + max_updates_within_interval = VariablesMap["max_updates_within_interval"].as(); + + Service::Ptr service = create_service(protocol,host,login,password,update_interval,max_updates_within_interval); if ( service ) { Services.push_back(service); - Log->print_service_object("New Service object from config:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password() ,service->get_actual_ip(), service->get_lastupdated()); + Log->print_service_object("New Service object from config:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password(), service->get_update_interval(), service->get_max_updates_within_interval(), service->get_actual_ip(), service->get_last_updates()); } } } diff --git a/src/config.h b/src/config.h index ef08f53..496d6fc 100644 --- a/src/config.h +++ b/src/config.h @@ -44,7 +44,7 @@ private: std::string WebcheckIpUrl; std::string WebcheckIpUrlAlt; - Service::Ptr create_service(const std::string&,const std::string&,const std::string&,const std::string&); + Service::Ptr create_service(const std::string&,const std::string&,const std::string&,const std::string&, const int, const int); int load_main_config_file(const std::string&); int load_service_config_file(const std::string&); std::string to_lower(std::string) const; diff --git a/src/dhs.cpp b/src/dhs.cpp index 8d8139c..ae8623c 100644 --- a/src/dhs.cpp +++ b/src/dhs.cpp @@ -18,9 +18,6 @@ using namespace std; * Default Constructor, needed for object serialization. */ DHS::DHS() - : Timeout(0) - , MaxUpdatesWithinTimeout(0) - , ActualUpdatesWithinTimeout(0) { } @@ -31,17 +28,23 @@ DHS::DHS() * @param _login The login name. * @param _password The corresponding password. */ -DHS::DHS(const string& _protocol, const string& _hostname, const string& _login, const string& _password, const Logger::Ptr& _logger, const int _lastupdated, const int _timeout, const int _max_updates_per_timeout) - : Timeout(_timeout) - , MaxUpdatesWithinTimeout(_max_updates_per_timeout) - , ActualUpdatesWithinTimeout(0) +DHS::DHS(const string& _protocol, const string& _hostname, const string& _login, const string& _password, const Logger::Ptr& _logger, const int _update_interval, const int _max_updates_within_interval) { + if ( _update_interval == -1 ) // If _update_interval is default po::option_desc (not specified via config) + set_update_interval(0); // use default protocol value + else + set_update_interval(_update_interval); + + if ( _max_updates_within_interval == -1 ) + set_max_updates_within_interval(0); + else + set_max_updates_within_interval(_max_updates_within_interval); + set_protocol(_protocol); set_hostname(_hostname); set_login(_login); set_password(_password); set_logger(_logger); - set_lastupdated(_lastupdated); } @@ -59,16 +62,22 @@ DHS::~DHS() */ void DHS::update(const string& ip) { - if ( this->get_actual_ip() != ip ) + // If actual service ip (ip set in last update) differs present host ip, then update + if ( get_actual_ip() != ip ) { - this->get_logger()->print_update_service("DHS"); + get_logger()->print_update_service("DHS"); if ( perform_update(ip) == 0 ) { // if update was successful, we need to set the Lastupdated and ActualIP base member. - this->set_lastupdated(time(NULL)); - this->set_actual_ip(ip); - this->get_logger()->print_update_service_successful("DHS"); + get_last_updates()->push_front(time(NULL)); + set_actual_ip(ip); + get_logger()->print_update_service_successful("DHS"); + } + else + { + // problem while trying to update service + // TODO: error logging } } } @@ -94,47 +103,4 @@ template void DHS::serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::base_object(*this); - ar & Timeout; - ar & MaxUpdatesWithinTimeout; - ar & ActualUpdatesWithinTimeout; -} - - -/** - * Setter for member Timeout. - * @param _timeout Value to set Timeout to. - */ -void DHS::set_timeout(const int _timeout) -{ - Timeout = _timeout; -} - - -/** - * Getter for member Timeout. - * @return Value of Timeout. - */ -int DHS::get_timeout() const -{ - return Timeout; -} - - -/** - * Setter for member MaxUpdatesWithinTimeout. - * @param _max_updates_per_timeout Value to set MaxUpdatesWithinTimeout to. - */ -void DHS::set_max_updates_within_timeout(const int _max_updates_per_timeout) -{ - MaxUpdatesWithinTimeout = _max_updates_per_timeout; -} - - -/** - * Getter for member MaxUpdatesWithinTimeout. - * @return Value of MaxUpdatesWithinTimeout. - */ -int DHS::get_max_updates_within_timeout() const -{ - return MaxUpdatesWithinTimeout; } diff --git a/src/dhs.h b/src/dhs.h index feb2fd0..6250937 100644 --- a/src/dhs.h +++ b/src/dhs.h @@ -24,10 +24,6 @@ class DHS : public Service private: - int Timeout; - int MaxUpdatesWithinTimeout; - int ActualUpdatesWithinTimeout; - friend class boost::serialization::access; template void serialize(Archive &, const unsigned int); @@ -38,16 +34,10 @@ public: DHS(); - DHS(const std::string&, const std::string&, const std::string&, const std::string&, const Logger::Ptr&, const int, const int, const int); + DHS(const std::string&, const std::string&, const std::string&, const std::string&, const Logger::Ptr&, const int, const int); ~DHS(); - void set_timeout(const int); - int get_timeout() const; - - void set_max_updates_within_timeout(const int); - int get_max_updates_within_timeout() const; - void update(const std::string&); int perform_update(const std::string&); diff --git a/src/iphelper.cpp b/src/iphelper.cpp index da97293..f988621 100644 --- a/src/iphelper.cpp +++ b/src/iphelper.cpp @@ -58,15 +58,19 @@ IPHelper::~IPHelper() */ string IPHelper::get_actual_ip() const { + string ip; if ( WebcheckIpUrl.empty() ) { - return dns_query(); + ip = dns_query(); } else { - return webcheck_ip(); + ip = webcheck_ip(); } - return ""; + + // TODO IF IP is local, then return "" + + return ip; } diff --git a/src/logger.cpp b/src/logger.cpp index 93f8ed2..d49d24b 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -13,6 +13,8 @@ #include #include +#include + namespace po = boost::program_options; using namespace std; @@ -607,18 +609,23 @@ void Logger::print_deserialized_objects_success() const * @param actual_ip Service's actual_ip. * @param lastupdated Service's lastupdated. */ -void Logger::print_service_object(const string& message, const string& protocol, const string& hostname, const string& login, const string& password, const string& actual_ip, const int lastupdated) const +void Logger::print_service_object(const string& message, const string& protocol, const string& hostname, const string& login, const string& password, const int update_interval, const int max_updates_within_interval, const string& actual_ip, list* lastupdated) const { if ( 1 <= Loglevel ) { ostringstream msg; msg << message << endl; - msg << "\t" << "Protocol: " << protocol << endl; - msg << "\t" << "Hostname: " << hostname << endl; - msg << "\t" << "Login: " <*) const; void print_exception_serialize(const std::string&) const; @@ -146,6 +146,12 @@ public: void print_regex_found_ip(const std::string&) const; void print_regex_ip_not_found(const std::string&) const; + + void print_multiple_cmd_option(const std::string&) const; + + void print_update_not_allowed(const int current_time, const int old_time, const int MaxUpdatesWithinInterval, const std::string& service) const; + + void print_update_service_failure(const std::string& service) const; }; #endif diff --git a/src/main.cpp b/src/main.cpp index c421f36..cd64293 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -246,8 +246,6 @@ int main(int argc, char *argv[]) { if ( is_online == true ) { - // TODO: Get the actual IP of this host (through DNS or WEBCHECK_IP). Perhaps new Class which can handle both. - // update all configured services updater->update_services(); } diff --git a/src/ods.cpp b/src/ods.cpp index 94ce1f3..0ef8b6e 100644 --- a/src/ods.cpp +++ b/src/ods.cpp @@ -18,9 +18,6 @@ using namespace std; * Default Constructor, needed for object serialization. */ ODS::ODS() - : Timeout(0) - , MaxUpdatesWithinTimeout(0) - , ActualUpdatesWithinTimeout(0) { } @@ -31,17 +28,23 @@ ODS::ODS() * @param _login The login name. * @param _password The corresponding password. */ -ODS::ODS(const string& _protocol, const string& _hostname, const string& _login, const string& _password, const Logger::Ptr& _logger, const int _lastupdated, const int _timeout, const int _max_updates_per_timeout) - : Timeout(_timeout) - , MaxUpdatesWithinTimeout(_max_updates_per_timeout) - , ActualUpdatesWithinTimeout(0) +ODS::ODS(const string& _protocol, const string& _hostname, const string& _login, const string& _password, const Logger::Ptr& _logger, const int _update_interval, const int _max_updates_within_interval) { + if ( _update_interval == -1 ) // If _update_interval is default po::option_desc (not specified via config) + set_update_interval(15); // use default protocol value + else + set_update_interval(_update_interval); + + if ( _max_updates_within_interval == -1 ) + set_max_updates_within_interval(3); + else + set_max_updates_within_interval(_max_updates_within_interval); + set_protocol(_protocol); set_hostname(_hostname); set_login(_login); set_password(_password); set_logger(_logger); - set_lastupdated(_lastupdated); } @@ -59,16 +62,28 @@ ODS::~ODS() */ void ODS::update(const string& ip) { - if ( this->get_actual_ip() != ip ) + if ( get_actual_ip() != ip ) { - this->get_logger()->print_update_service("DHS"); + int current_time = time(NULL); + get_logger()->print_update_service("ODS"); - if ( perform_update(ip) == 0 ) + // test if update is permitted by UpdateInterval Status + if ( update_allowed(current_time) ) { - // if update was successful, we need to set the Lastupdated and ActualIP base member. - this->set_lastupdated(time(NULL)); - this->set_actual_ip(ip); - this->get_logger()->print_update_service_successful("DHS"); + + if ( perform_update(ip) == 0 ) + { + // if update was successful, we need to set the Lastupdated and ActualIP base member. + get_last_updates()->push_front(time(NULL)); + set_actual_ip(ip); + get_logger()->print_update_service_successful("ODS"); + } + else + { + // problem while trying to update service + get_logger()->print_update_service_failure("ODS"); + } + } } } @@ -94,47 +109,4 @@ template void ODS::serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::base_object(*this); - ar & Timeout; - ar & MaxUpdatesWithinTimeout; - ar & ActualUpdatesWithinTimeout; -} - - -/** - * Setter for member Timeout. - * @param _timeout Value to set Timeout to. - */ -void ODS::set_timeout(const int _timeout) -{ - Timeout = _timeout; -} - - -/** - * Getter for member Timeout. - * @return Value of Timeout. - */ -int ODS::get_timeout() const -{ - return Timeout; -} - - -/** - * Setter for member Max_updates_per_timeout. - * @param _max_updates_per_timeout Value to set Max_updates_per_timeout to. - */ -void ODS::set_max_updates_within_timeout(const int _max_updates_per_timeout) -{ - MaxUpdatesWithinTimeout = _max_updates_per_timeout; -} - - -/** - * Getter for member Max_updates_per_timeout. - * @return Value of Max_updates_per_timeout. - */ -int ODS::get_max_updates_within_timeout() const -{ - return MaxUpdatesWithinTimeout; } diff --git a/src/ods.h b/src/ods.h index 1843dd5..96f1b26 100644 --- a/src/ods.h +++ b/src/ods.h @@ -24,10 +24,6 @@ class ODS : public Service private: - int Timeout; - int MaxUpdatesWithinTimeout; - int ActualUpdatesWithinTimeout; - friend class boost::serialization::access; template void serialize(Archive &, const unsigned int); @@ -38,16 +34,10 @@ public: ODS(); - ODS(const std::string&, const std::string&, const std::string&, const std::string&, const Logger::Ptr&, const int, const int, const int); + ODS(const std::string&, const std::string&, const std::string&, const std::string&, const Logger::Ptr&, const int, const int); ~ODS(); - void set_timeout(const int); - int get_timeout() const; - - void set_max_updates_within_timeout(const int); - int get_max_updates_within_timeout() const; - void update(const std::string&); int perform_update(const std::string&); diff --git a/src/service.cpp b/src/service.cpp index bdbf8d5..bd55016 100644 --- a/src/service.cpp +++ b/src/service.cpp @@ -8,7 +8,8 @@ */ #include "service.h" - +#include +#include /** * Default Constructor @@ -19,7 +20,8 @@ Service::Service() , Login("NOT SERIALIZED") , Password("NOT SERIALIZED") , ActualIP("0.0.0.0") - , Lastupdated(0) + , UpdateInterval(0) + , MaxUpdatesWithinInterval(0) , Log(new Logger()) { } @@ -45,8 +47,10 @@ void Service::serialize(Archive & ar, const unsigned int version) ar & Protocol; ar & Hostname; // lastupdated and actual_ip must also be serialized, cause these are essential infos of each service. - ar & Lastupdated; + ar & LastUpdates; ar & ActualIP; + ar & UpdateInterval; + ar & MaxUpdatesWithinInterval; } @@ -150,13 +154,13 @@ Logger::Ptr Service::get_logger() const } -/** - * Setter for member Lastupdated. - * @param _lastupdated Value to set Lastupdated to. - */ -void Service::set_lastupdated(const int _lastupdated) +void Service::set_last_updates(std::list* _last_updates) { - Lastupdated = _lastupdated; + LastUpdates.clear(); + BOOST_FOREACH( int update_time, *_last_updates ) + { + LastUpdates.push_back(update_time); + } } @@ -164,9 +168,9 @@ void Service::set_lastupdated(const int _lastupdated) * Getter for member Lastupdated. * @return Value of member Lastupdated. */ -int Service::get_lastupdated() const +list* Service::get_last_updates() { - return Lastupdated; + return &LastUpdates; } @@ -213,3 +217,66 @@ bool Service::operator!= (const Service& other) const { return !(*this == other); } + + +/** + * Checks if update will exceed max update interval. + * @param current_time Current time. + * @return True if update is allowed, false if update would exceed max update interval. + */ +bool Service::update_allowed(const int current_time) +{ + list::iterator iter; + int i=0; + + for (iter = LastUpdates.begin(); (iter != LastUpdates.end()) && ( i < MaxUpdatesWithinInterval ); iter++) + { + if ( (i == (MaxUpdatesWithinInterval-1)) && ( (*iter + (UpdateInterval*60)) >= current_time ) ) + { + Log->print_update_not_allowed(current_time,*iter,MaxUpdatesWithinInterval,"ODS"); + return false; + } + i++; + } + return true; +} + + +/** + * Setter for member Timeout. + * @param _timeout Value to set Timeout to. + */ +void Service::set_update_interval(const int _update_interval) +{ + UpdateInterval = _update_interval; +} + + +/** + * Getter for member Timeout. + * @return Value of Timeout. + */ +int Service::get_update_interval() const +{ + return UpdateInterval; +} + + +/** + * Setter for member Max_updates_per_timeout. + * @param _max_updates_per_timeout Value to set Max_updates_per_timeout to. + */ +void Service::set_max_updates_within_interval(const int _max_updates_within_interval) +{ + MaxUpdatesWithinInterval = _max_updates_within_interval; +} + + +/** + * Getter for member Max_updates_per_timeout. + * @return Value of Max_updates_per_timeout. + */ +int Service::get_max_updates_within_interval() const +{ + return MaxUpdatesWithinInterval; +} diff --git a/src/service.h b/src/service.h index 1cde30f..effe53c 100644 --- a/src/service.h +++ b/src/service.h @@ -30,7 +30,10 @@ private: std::string ActualIP; - int Lastupdated; + int UpdateInterval; + int MaxUpdatesWithinInterval; + + std::list LastUpdates; friend class boost::serialization::access; template @@ -46,13 +49,13 @@ public: virtual ~Service(); - virtual void update(const std::string&)=0; + virtual void update(const std::string&) = 0; - virtual int get_timeout()const =0 ; - virtual void set_timeout(const int)=0; + int get_update_interval()const; + void set_update_interval(const int); - virtual int get_max_updates_within_timeout() const =0; - virtual void set_max_updates_within_timeout(const int)=0; + int get_max_updates_within_interval() const; + void set_max_updates_within_interval(const int); void set_protocol(const std::string&); std::string get_protocol() const; @@ -66,8 +69,8 @@ public: void set_password(const std::string&); std::string get_password() const; - void set_lastupdated(const int); - int get_lastupdated() const; + void set_last_updates(std::list*); + std::list* get_last_updates(); void set_actual_ip(const std::string&); std::string get_actual_ip() const; @@ -75,6 +78,8 @@ public: void set_logger(const Logger::Ptr&); Logger::Ptr get_logger() const; + bool update_allowed(const int current_time); + bool operator== (const Service&) const; bool operator!= (const Service&) const; }; diff --git a/src/updater.cpp b/src/updater.cpp index 17ed7da..a11d568 100644 --- a/src/updater.cpp +++ b/src/updater.cpp @@ -161,9 +161,11 @@ void Updater::update_services() string ip = IPHelp->get_actual_ip(); - BOOST_FOREACH(Service::Ptr &service, services ) + if ( !ip.empty() ) { - // TODO: only update if IP differs and is_valid and is_not_empty. - service->update(ip); + BOOST_FOREACH(Service::Ptr &service, services ) + { + service->update(ip); + } } } -- 1.7.1