Commit 44291d90 authored by Timothy Stack's avatar Timothy Stack
Browse files

Cleanup the EventClient interface a bit and add a hack to keep the

event system from crashing when multiple EventClients are created.
parent d8a212f7
......@@ -303,6 +303,7 @@ cvar = _tbevent.cvar
# output file
#
import sys
import time
class NotificationWrapper:
......@@ -418,11 +419,37 @@ class CallbackIterator:
pass
class EventError:
"""
Base class for event related exceptions.
"""
def __init__(self, code):
self.args = code,
return
pass
class EventTimedOutError(EventError):
"""
Exception raised when the run() method of EventClient timed out.
"""
def __init__(self, timeout):
self.args = timeout,
return
pass
# Ugh, elvin likes to crash if we unregister all of the handles, so we keep
# a dummy one around just to keep things happy.
_hack_handle = None
class EventClient:
"""
Event client class, mostly just wraps the SWIG'd versions of the functions.
"""
def __init__(self, server=None, port=None, url=None):
"""
Construct an EventClient object.
......@@ -431,7 +458,8 @@ class EventClient:
@param server The name of the server.
@param port The server port number.
"""
global _hack_handle
if url:
if not url.startswith("elvin:"):
raise ValueError, "malformed url: " + url
......@@ -442,8 +470,18 @@ class EventClient:
url = "elvin://" + server
if port and len(port) > 0:
url = url + ":" + port
pass
pass
self.handle = event_register(url, 0)
self.timeout = 0
if not _hack_handle:
# Open a handle for the sole purpose of keeping the event library
# from calling the elvin cleanup function, because elvin likes to
# segfault when it has been init'd/clean'd multiple times.
_hack_handle = event_register(url, 0)
pass
return
def __del__(self):
......@@ -465,8 +503,10 @@ class EventClient:
"""
Default implementation of the event handling method. Should be
overridden by subclasses.
@return None to continue processing events, any other value to stop.
"""
return
return None
def subscribe(self, tuple):
"""
......@@ -490,23 +530,45 @@ class EventClient:
"""
return event_notify(self.handle, en.notification)
def set_timeout(self, timeout):
"""
@param timeout The timeout, in seconds, for the run() loop.
"""
self.timeout = timeout * 1000
return
def run(self):
"""
Main loop used to wait for and process events.
@return The not None value returned by handle_event.
"""
while True:
rc = c_event_poll_blocking(self.handle, 0)
retval = None
while not retval:
rc = c_event_poll_blocking(self.handle, self.timeout)
if rc != 0:
sys.stderr.write("c_event_poll_blocking: " + str(rc) + "\n")
pass
raise EventError, rc
else:
for ev in self._callbacks():
self.handle_event(ev)
retval = self.handle_event(ev)
if retval:
# Not None return value, stop the bus.
break
pass
else:
if self.timeout != 0:
# We're making a bit of an assumption here that no
# callbacks means a timeout occurred, oh well.
raise EventTimedOutError, self.timeout
pass
if not retval:
time.sleep(0.1) # Forcefully slow down the poll.
pass
time.sleep(0.1)
pass
pass
return
return retval
def poll(self):
"""
......
......@@ -7,6 +7,7 @@
# output file
#
import sys
import time
class NotificationWrapper:
......@@ -122,11 +123,37 @@ class CallbackIterator:
pass
class EventError:
"""
Base class for event related exceptions.
"""
def __init__(self, code):
self.args = code,
return
pass
class EventTimedOutError(EventError):
"""
Exception raised when the run() method of EventClient timed out.
"""
def __init__(self, timeout):
self.args = timeout,
return
pass
# Ugh, elvin likes to crash if we unregister all of the handles, so we keep
# a dummy one around just to keep things happy.
_hack_handle = None
class EventClient:
"""
Event client class, mostly just wraps the SWIG'd versions of the functions.
"""
def __init__(self, server=None, port=None, url=None):
"""
Construct an EventClient object.
......@@ -135,7 +162,8 @@ class EventClient:
@param server The name of the server.
@param port The server port number.
"""
global _hack_handle
if url:
if not url.startswith("elvin:"):
raise ValueError, "malformed url: " + url
......@@ -146,8 +174,18 @@ class EventClient:
url = "elvin://" + server
if port and len(port) > 0:
url = url + ":" + port
pass
pass
self.handle = event_register(url, 0)
self.timeout = 0
if not _hack_handle:
# Open a handle for the sole purpose of keeping the event library
# from calling the elvin cleanup function, because elvin likes to
# segfault when it has been init'd/clean'd multiple times.
_hack_handle = event_register(url, 0)
pass
return
def __del__(self):
......@@ -169,8 +207,10 @@ class EventClient:
"""
Default implementation of the event handling method. Should be
overridden by subclasses.
@return None to continue processing events, any other value to stop.
"""
return
return None
def subscribe(self, tuple):
"""
......@@ -194,23 +234,45 @@ class EventClient:
"""
return event_notify(self.handle, en.notification)
def set_timeout(self, timeout):
"""
@param timeout The timeout, in seconds, for the run() loop.
"""
self.timeout = timeout * 1000
return
def run(self):
"""
Main loop used to wait for and process events.
@return The not None value returned by handle_event.
"""
while True:
rc = c_event_poll_blocking(self.handle, 0)
retval = None
while not retval:
rc = c_event_poll_blocking(self.handle, self.timeout)
if rc != 0:
sys.stderr.write("c_event_poll_blocking: " + str(rc) + "\n")
pass
raise EventError, rc
else:
for ev in self._callbacks():
self.handle_event(ev)
retval = self.handle_event(ev)
if retval:
# Not None return value, stop the bus.
break
pass
else:
if self.timeout != 0:
# We're making a bit of an assumption here that no
# callbacks means a timeout occurred, oh well.
raise EventTimedOutError, self.timeout
pass
if not retval:
time.sleep(0.1) # Forcefully slow down the poll.
pass
time.sleep(0.1)
pass
pass
return
return retval
def poll(self):
"""
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment