import cPickle
import SocketServer
import sys
import os
from chestnut_dialer.dobj import *
from chestnut_dialer.dobj import _load
from chestnut_dialer.dobj import _dump
class EventHistory:
def __init__(self, max_len):
self.ev_list = []
self.max_len = max_len
def push(self, event):
self.ev_list.append(event)
if len(self.ev_list) > self.max_len: del(self.ev_list[0])
def get_after(self, after_time):
ev = []
ev_list = self.ev_list
for i in range(len(ev_list) - 1, -1, -1):
e = ev_list[i]
if e.time > after_time: ev.append(e)
else: break
return tuple(ev)
class ObjEntry:
def __init__(self, obj):
self.obj = obj
self.ref_count = 0
class DObjRequestHandler(SocketServer.StreamRequestHandler):
def prepare_value(self, value):
value_type = type(value)
if value_type in (type(None), bool, int, float, str, unicode):
return value
if value_type == tuple:
v = []
for i in value:
v.append(self.prepare_value(i))
return tuple(v)
dobj = DObject(self.server.address_family,
self.server.server_address, id(value))
self.server.ref_object(value)
return dobj
def cleanup_value(self, value):
if isinstance(value, DObject):
value._unref_on_del = 0
elif type(value) == tuple:
for i in value: self.cleanup_value(i)
def return_value(self, value):
value = self.prepare_value(value)
_dump(value, self.wfile)
self.cleanup_value(value)
def convert_input_value(self, value):
if isinstance(value, DObject):
obj = self.server.object_registry[value._id].obj
value._unref_on_del = 0
return obj
value_type = type(value)
if value_type == list:
for i in range(0, len(value)):
value[i] = self.convert_input_value(value[i])
return value
if value_type == tuple:
v = []
for i in value: v.append(self.convert_input_value(i))
return tuple(v)
if value_type == dict:
for i in value.keys():
value[i] = self.convert_input_value(value[i])
return value
return value
def return_error(self, error):
_dump(ErrorResponse(error), self.wfile)
def handle(self):
server = self.server
return_value = self.return_value
return_error = self.return_error
self.request.settimeout(3.0)
try: req = _load(self.rfile)
except:
return_error(UnknownRequestError())
return
if hasattr(req, "obj_id"):
try: obj = server.object_registry[req.obj_id].obj
except KeyError:
return_error(UnknownObjectError(req.obj_id))
return
req_class = req.__class__
if req_class == GetAttrRequest:
try: value = getattr(obj, req.name)
except AttributeError, e: return_error(e)
else: return_value(value)
return
if req_class == GetItemRequest:
try: value = obj[req.key]
except Exception, e: return_error(e)
else: return_value(value)
return
if req_class == SetAttrRequest:
value = self.convert_input_value(req.value)
try: setattr(obj, req.name, value)
except Exception, e: return_error(e)
else: return_value(None)
return
if req_class == SetItemRequest:
value = self.convert_input_value(req.value)
try: obj[req.key] = value
except Exception, e: return_error(e)
else: return_value(None)
return
if req_class == UnrefRequest:
server.unref_object(obj)
return_value(None)
return
if req_class == GetEventsRequest:
_dump(server.event_history.get_after(req.after_time), self.wfile)
return
if req_class == CallRequest:
args = self.convert_input_value(req.args)
try: value = apply(obj, args)
except Exception, e: return_error(e)
else:
try: c = obj.__self__.__class__
except AttributeError:
try: c = obj.im_class
except AttributeError: c = None
try: n = obj.__name__
except AttributeError: n = None
if ((c, n) in server.direct_result_for_call):
_dump(value, self.wfile)
return
return_value(value)
return
if req_class == ReprRequest:
return_value(repr(obj))
return
if req_class == StrRequest:
return_value(str(obj))
return
if req_class == UnicodeRequest:
return_value(unicode(obj))
return
if req_class == DelAttrRequest:
try: delattr(obj, req.name)
except Exception, e: return_error(e)
else: return_value(None)
return
if req_class == LenRequest:
try: value = len(obj)
except Exception, e: return_error(e)
else: return_value(value)
return
if req_class == DelItemRequest:
try: del obj[req.key]
except Exception, e: return_error(e)
else: return_value(None)
return
if req_class == GetRootObjectRequest:
return_value(server.root_object)
return
return_error(UnknownRequestError())
class BaseDObjServer:
def __init__(self, root_object, ev_history_max = 64):
self.root_object = root_object
self.object_registry = {}
self.event_history = EventHistory(ev_history_max)
self.push_event = self.event_history.push
self.direct_result_for_call = []
def ref_object(self, obj):
obj_id = id(obj)
if not self.object_registry.has_key(obj_id):
obj_entry = ObjEntry(obj)
self.object_registry.update({obj_id: obj_entry})
else: obj_entry = self.object_registry[obj_id]
obj_entry.ref_count += 1
def unref_object(self, obj):
obj_id = id(obj)
try: obj_entry = self.object_registry[obj_id]
except KeyError: return
obj_entry.ref_count -= 1
if obj_entry.ref_count == 0: del(self.object_registry[obj_id])
class UnixDObjServer(SocketServer.UnixStreamServer,BaseDObjServer):
def __init__(self, server_address, root_object):
SocketServer.UnixStreamServer.__init__(self,
server_address, DObjRequestHandler)
BaseDObjServer.__init__(self, root_object)
def __del__(self):
os.remove(self.server_address)
|