From 49b3fdacf04c3746e56d754a2fc0178c23c2259b Mon Sep 17 00:00:00 2001
From: Iustin Pop <iustin@google.com>
Date: Thu, 18 Mar 2010 16:46:54 +0100
Subject: [PATCH] Extend ConfdFilterCallback with consistency checks

Note that users of the callback will have to manually check the
attribute.

Signed-off-by: Iustin Pop <iustin@google.com>
Reviewed-by: Guido Trotter <ultrotter@google.com>
---
 lib/confd/client.py | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/lib/confd/client.py b/lib/confd/client.py
index dfbc65063..71b510435 100644
--- a/lib/confd/client.py
+++ b/lib/confd/client.py
@@ -347,6 +347,12 @@ class ConfdClientRequest(objects.ConfdRequest):
 class ConfdFilterCallback:
   """Callback that calls another callback, but filters duplicate results.
 
+  @ivar consistent: a dictionary indexed by salt; for each salt, if
+      all responses ware identical, this will be True; this is the
+      expected state on a healthy cluster; on inconsistent or
+      partitioned clusters, this might be False, if we see answers
+      with the same serial but different contents
+
   """
   def __init__(self, callback, logger=None):
     """Constructor for ConfdFilterCallback
@@ -364,6 +370,7 @@ class ConfdFilterCallback:
     self._logger = logger
     # answers contains a dict of salt -> answer
     self._answers = {}
+    self.consistent = {}
 
   def _LogFilter(self, salt, new_reply, old_reply):
     if not self._logger:
@@ -388,6 +395,8 @@ class ConfdFilterCallback:
     # if we have no answer we have received none, before the expiration.
     if up.salt in self._answers:
       del self._answers[up.salt]
+    if up.salt in self.consistent:
+      del self.consistent[up.salt]
 
   def _HandleReply(self, up):
     """Handle a single confd reply, and decide whether to filter it.
@@ -399,6 +408,8 @@ class ConfdFilterCallback:
     """
     filter_upcall = False
     salt = up.salt
+    if salt not in self.consistent:
+      self.consistent[salt] = True
     if salt not in self._answers:
       # first answer for a query (don't filter, and record)
       self._answers[salt] = up.server_reply
@@ -413,6 +424,8 @@ class ConfdFilterCallback:
       # else: different content, pass up a second answer
     else:
       # older or same-version answer (duplicate or outdated, filter)
+      if up.server_reply.answer != self._answers[salt].answer:
+        self.consistent[salt] = False
       filter_upcall = True
       self._LogFilter(salt, up.server_reply, self._answers[salt])
 
-- 
GitLab