[Zodb-checkins] SVN: ZODB/branches/jim-async-client/src/ZEO/zrpc/connection.py Added heartbeat code to the client loop to, hopefully, detect server

Jim Fulton jim at zope.com
Tue Jul 18 07:30:38 EDT 2006


Log message for revision 69169:
  Added heartbeat code to the client loop to, hopefully, detect server
  disconnections in situations in which the disconnect might not
  otherwise be detected.  This is imperfect because we only check
  dureing periods of inactivity.  A busy server with multiple
  connections might never execute the heartbeat code, but this code
  should at least help in other cases.
  
  Also, simplified the client loop polling logic to take advantahe of
  the fact that we know that all map entries are readable (unless they
  are closed, but we already have to handle that case and it is
  infrequent).
  

Changed:
  U   ZODB/branches/jim-async-client/src/ZEO/zrpc/connection.py

-=-
Modified: ZODB/branches/jim-async-client/src/ZEO/zrpc/connection.py
===================================================================
--- ZODB/branches/jim-async-client/src/ZEO/zrpc/connection.py	2006-07-18 03:09:46 UTC (rev 69168)
+++ ZODB/branches/jim-async-client/src/ZEO/zrpc/connection.py	2006-07-18 11:30:37 UTC (rev 69169)
@@ -37,6 +37,7 @@
 client_map = {}
 client_trigger = trigger(client_map)
 client_timeout = 30.0
+client_timeout_count = 0 # for testing
 
 def client_loop():
     map = client_map
@@ -49,16 +50,8 @@
     
     while map:
         try:
-            r = []; w = []; e = []
-            for fd, obj in map.items():
-                is_r = obj.readable()
-                is_w = obj.writable()
-                if is_r:
-                    r.append(fd)
-                if is_w:
-                    w.append(fd)
-                if is_r or is_w:
-                    e.append(fd)
+            r = e = list(client_map)
+            w = [fd for (fd, obj) in map.iteritems() if obj.writable()]
 
             try:
                 r, w, e = select.select(r, w, e, client_timeout)
@@ -77,11 +70,23 @@
                         if [fd for fd in w if fd not in client_map]:
                             continue
                         
-#                        print 'BADF', list(client_map), r, w, e
                     raise
                 else:
                     continue
 
+            if not (r or w or e):
+                for obj in client_map.itervalues():
+                    if isinstance(obj, Connection):
+                        # Send a heartbeat message as a reply to a
+                        # non-existent message id.
+                        try:
+                            obj.send_reply(-1, None)
+                        except DisconnectedError:
+                            pass
+                global client_timeout_count
+                client_timeout_count += 1
+                continue
+
             for fd in r:
                 obj = map.get(fd)
                 if obj is None:
@@ -101,51 +106,9 @@
                 _exception(obj)
 
         except:
-#            print 'poll failure', sys.exc_info()[1], time.time()
             logger.exception('poll failure')
             raise
 
-#import time
-def poll(timeout, map):
-    if map:
-        r = []; w = []; e = []
-        for fd, obj in map.items():
-            is_r = obj.readable()
-            is_w = obj.writable()
-            if is_r:
-                r.append(fd)
-            if is_w:
-                w.append(fd)
-            if is_r or is_w:
-                e.append(fd)
-
-        try:
-            r, w, e = select.select(r, w, e, timeout)
-        except select.error, err:
-            if err[0] != errno.EINTR:
-                raise
-            else:
-                return
-
-        for fd in r:
-            obj = map.get(fd)
-            if obj is None:
-                continue
-            asyncore.read(obj)
-
-        for fd in w:
-            obj = map.get(fd)
-            if obj is None:
-                continue
-            asyncore.write(obj)
-
-        for fd in e:
-            obj = map.get(fd)
-            if obj is None:
-                continue
-            asyncore._exception(obj)
-
-
 client_thread = threading.Thread(target=client_loop)
 client_thread.setDaemon(True)
 client_thread.start()



More information about the Zodb-checkins mailing list