Block service for a short period of time on too many update errors
authorThomas Jarosch <thomas.jarosch@intra2net.com>
Thu, 14 Oct 2010 09:56:54 +0000 (11:56 +0200)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Thu, 14 Oct 2010 09:56:54 +0000 (11:56 +0200)
docs/TODO
src/logger.cpp
src/logger.hpp
src/service.cpp
src/service.hpp

index 6fd020f..bd9e72d 100644 (file)
--- 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
index 3b00e56..f26fb91 100644 (file)
@@ -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.
index 8a27831..26140fb 100644 (file)
@@ -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;
index 0294615..dcc7fa1 100644 (file)
 
 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;
+            }
         }
     }
 }
index 3b460e2..1573bd7 100644 (file)
@@ -39,6 +39,9 @@ private:
 
     std::list<time_t> LastUpdates;
 
+    int ErrorCount;
+    time_t ErrorServiceBlockedUntil;
+
     friend class boost::serialization::access;
     template<class Archive>
     void serialize(Archive & ar, const unsigned int version)