diff bitten/util/beep.py @ 18:591a5a836ecc

* {{{beep.Listener}}} now has an event loop (based on code mostly from medusa) * The Bitten master now opens a Trac environment and checks for changes to the repository every 15 seconds. * {{{beep.Profile}}} renamed to {{{beep.ProfileHandler}}}
author cmlenz
date Fri, 17 Jun 2005 09:09:07 +0000
parents 06207499c58c
children 1a7b9044b0a5
line wrap: on
line diff
--- a/bitten/util/beep.py
+++ b/bitten/util/beep.py
@@ -28,6 +28,7 @@
 
 import asynchat
 import asyncore
+import bisect
 from email.Message import Message
 from email.Parser import Parser
 import logging
@@ -63,6 +64,7 @@
         self.set_reuse_addr()
         self.bind((ip, port))
         self.profiles = {}
+        self.eventqueue = []
         logging.debug('Listening to connections on %s:%d', ip, port)
         self.listen(5)
 
@@ -82,14 +84,44 @@
         """Start a new BEEP session."""
         conn, (ip, port) = self.accept()
         logging.debug('Connected to %s:%d', ip, port)
-        Session(conn, (ip, port), self.profiles, first_channelno=2)
+        Session(self, conn, (ip, port), self.profiles, first_channelno=2)
+
+    def run(self, timeout=15.0, granularity=5):
+        socket_map = asyncore.socket_map
+        last_event_check = 0
+        while socket_map:
+            now = int(time.time())
+            if (now - last_event_check) >= granularity:
+                last_event_check = now
+                fired = []
+                # yuck. i want my lisp.
+                i = j = 0
+                while i < len(self.eventqueue):
+                    when, what = self.eventqueue[i]
+                    if now >= when:
+                        fired.append(what)
+                        j = i + 1
+                    else:
+                        break
+                    i = i + 1
+                if fired:
+                    self.eventqueue = self.eventqueue[j:]
+                    for what in fired:
+                        what (self, now)
+            asyncore.poll(timeout)
+
+    def schedule (self, delta, callback):
+        now = int(time.time())
+        bisect.insort(self.eventqueue, (now + delta, callback))
 
 
 class Session(asynchat.async_chat):
     """A BEEP session between two peers."""
 
-    def __init__(self, conn, addr, profiles, first_channelno=1):
+    def __init__(self, listener=None, conn=None, addr=None, profiles=None,
+                 first_channelno=1):
         asynchat.async_chat.__init__(self, conn)
+        self.listener = listener
         self.addr = addr
         self.set_terminator('\r\n')
 
@@ -98,7 +130,7 @@
         self.header = self.payload = None
         
         self.channelno = cycle_through(first_channelno, 2147483647, step=2)
-        self.channels = {0: Channel(self, 0, ManagementProfile())}
+        self.channels = {0: Channel(self, 0, ManagementProfileHandler())}
 
     def handle_connect(self):
         pass
@@ -214,7 +246,7 @@
                          `Profile` instance that will handle the communication
                          for that profile
         """
-        Session.__init__(self, None, None, profiles or {})
+        Session.__init__(self, profiles=profiles or {})
         self.terminated = False
         self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
         logging.debug('Connecting to %s:%s', ip, port)
@@ -378,7 +410,7 @@
         del self.ansnos[msgno] # dealloc answer numbers for the message
 
 
-class Profile(object):
+class ProfileHandler(object):
     """Abstract base class for handlers of specific BEEP profiles.
     
     Concrete subclasses need to at least implement the `handle_msg()` method,
@@ -411,7 +443,7 @@
         pass
 
 
-class ManagementProfile(Profile):
+class ManagementProfileHandler(ProfileHandler):
     """Implementation of the BEEP management profile."""
 
     def handle_connect(self):
Copyright (C) 2012-2017 Edgewall Software