From 0f0908e16b130d4d778e82c0879cc078a25cca43 Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Thu, 14 Oct 2010 11:56:54 +0200 Subject: [PATCH] Block service for a short period of time on too many update errors --- docs/TODO | 2 ++ src/logger.cpp | 35 ++++++++++++++++++++++++++++++++++- src/logger.hpp | 4 ++++ src/service.cpp | 33 ++++++++++++++++++++++++++++++--- src/service.hpp | 3 +++ 5 files changed, 73 insertions(+), 4 deletions(-) diff --git a/docs/TODO b/docs/TODO index 6fd020f..bd9e72d 100644 --- a/docs/TODO +++ b/docs/TODO @@ -9,3 +9,5 @@ -> temporary failure: e.g. increase idle period for that service. - Add curl HTTP headers to disable proxy caching + +- On too many update errors: Configurable block period and error threshold counter diff --git a/src/logger.cpp b/src/logger.cpp index 3b00e56..f26fb91 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -374,7 +374,7 @@ void Logger::print_constructor_call(const string& _class) const /** * Update method for specified service was called. - * @param service The service for which is the update running. + * @param service The service for which the update is running. */ void Logger::print_update_service(const string& service) const { @@ -387,6 +387,39 @@ void Logger::print_update_service(const string& service) const } } +/** + * Service is blocked for update because of too many errors + * @param service The service for which the update is running. + * @param remaining_seconds Remaining seconds this service is blocked + */ +void Logger::print_update_service_is_blocked(const std::string& service, int remaining_seconds) const +{ + int level = 1; + if ( level <= Loglevel ) + { + ostringstream msg; + msg << "Service " << service << " is blocked for " << remaining_seconds << " seconds because of too many errors" << endl; + log_notice(msg.str()); + } +} + + +/** + * Service will be blocked because of update errors + * @param service The service for which the update is running. + * @param block_seconds Number of seconds this service is blocked + */ +void Logger::print_block_service(const std::string& service, int block_seconds) const +{ + int level = 0; + if ( level <= Loglevel ) + { + ostringstream msg; + msg << "Service " << service << " will be blocked for " << block_seconds << " seconds because of too many errors" << endl; + log_notice(msg.str()); + } +} + /** * An unknown option on the command line was detected. diff --git a/src/logger.hpp b/src/logger.hpp index 8a27831..26140fb 100644 --- a/src/logger.hpp +++ b/src/logger.hpp @@ -80,6 +80,10 @@ public: void print_update_service(const std::string& service) const; + void print_update_service_is_blocked(const std::string& service, int remaining_seconds) const; + + void print_block_service(const std::string& service, int block_seconds) const; + void print_unknown_cmd_option(const std::string& unknown_option) const; void print_unknown_protocol(const std::string& protocol) const; diff --git a/src/service.cpp b/src/service.cpp index 0294615..dcc7fa1 100644 --- a/src/service.cpp +++ b/src/service.cpp @@ -12,6 +12,10 @@ using namespace std; +/// Number of update errors until a service will be blocked +const int MaxErrorCount = 3; +/// Number of seconds a service will be blocked if MaxErrorCount is reached +const int ErrorBlockServiceSeconds = 15 * 60; /** * Default Constructor @@ -23,6 +27,8 @@ Service::Service() , UpdateInterval(0) , MaxUpdatesWithinInterval(0) , DNSCacheTTL(0) + , ErrorCount(0) + , ErrorServiceBlockedUntil(0) , Log(new Logger()) { } @@ -227,7 +233,16 @@ bool Service::update_allowed(const time_t current_time) */ void Service::update(const string& ip, const time_t current_time) { - Log->print_update_service(get_service_name()); + const std::string service_name = get_service_name(); + + // Check if service is blocked for a short period of time (because of update errors) + if (ErrorServiceBlockedUntil && current_time < ErrorServiceBlockedUntil) + { + Log->print_update_service_is_blocked(service_name, ErrorServiceBlockedUntil - current_time); + return; + } + + Log->print_update_service(service_name); // test if update is permitted by UpdateInterval Status if ( update_allowed(current_time) ) @@ -237,12 +252,24 @@ void Service::update(const string& ip, const time_t current_time) // if update was successful, we need to set the Lastupdated and ActualIP base member. set_last_update(current_time); ActualIP = ip; - Log->print_update_service_successful(get_service_name()); + Log->print_update_service_successful(service_name); + + ErrorCount = 0; + ErrorServiceBlockedUntil = 0; } else { // problem while trying to update service - Log->print_update_service_failure(get_service_name()); + Log->print_update_service_failure(service_name); + + ++ErrorCount; + if (ErrorCount >= MaxErrorCount) + { + Log->print_block_service(service_name, ErrorBlockServiceSeconds); + + ErrorServiceBlockedUntil = time(NULL) + ErrorBlockServiceSeconds; + ErrorCount = 0; + } } } } diff --git a/src/service.hpp b/src/service.hpp index 3b460e2..1573bd7 100644 --- a/src/service.hpp +++ b/src/service.hpp @@ -39,6 +39,9 @@ private: std::list LastUpdates; + int ErrorCount; + time_t ErrorServiceBlockedUntil; + friend class boost::serialization::access; template void serialize(Archive & ar, const unsigned int version) -- 1.7.1