class StageSocket(threading.Thread): def __init__(self, sock, socket_id, store, manager_loc): threading.Thread.__init__(self) log.debug(self, "New socket at %s" % socket_id) self.sock = sock self.wfile = sock.makefile('w') self.rfile = sock.makefile('r') self.id = socket_id self.store = store self.store.add_socket(socket_id, self) self.exit = False self.manager_loc = manager_loc self.messages = MessageQueue() self.results = ResultMap() self.m_id = 0 def run(self): while not self.exit: try: request = self.messages.get_next() if self.exit: break mid, target, method, args, kwds = request log.debug(self,"Call %s on %s with %s and %s" % (method, target, args, kwds)) meth = getattr(target, method) result = meth(*args, **kwds) # print "Got result %s" % result #special cases if method == 'makefile': log.debug(self, "Called makefile %s, %s, %s" % (self.manager_loc, self.id, args[0][0])) result = socketutil.SocketFileReference(self.manager_loc, self.id, args[0][0]) elif method == 'accept': socket_id = "%s:%d" % result[1] StageSocket(result[0], socket_id, self.store, self.manager_loc).start() result = socketutil.SocketReference(self.manager_loc, socket_id) elif method == 'close': self.exit = True self.store.remove_socket(self.id) log.debug(self, "Socket %s closing" % self.id) self.results.add(SocketResult(mid,result)) except Exception as e: log.debug(self, "Socket exception: %s" % e) # t, v, tr = sys.exc_info() log.debug(self, "%s" % traceback.format_exc()) if self.exit: break else: self.results.add(SocketResult(mid,None)) log.debug(self,"Socket %s run out" % self.id) def __getattr__(self, name): if self.__dict__.has_key(name): return self.__dict__[name] elif name.find(':') > 0: #print "No attr %s for listening socket" % name targetname, method = name.split(':') target = getattr(self, targetname) if hasattr(target, method): #print "But it's socket has %s" % name self.m_id = self.m_id + 1 return SocketRequest(self, self.m_id, target, method) def close(self): print "Closing socket %s" % self.id self.exit = True self.messages.add(None) self.sock.close() self.store.remove_socket(self.id) log.debug(self, "Closed socket %s" % self.id)
class MessageStore(object): def __init__(self): self.__requests = MessageQueue() self.__responses = ResultMap() self.__last_req_id = 0 self.__callbacks = dict() self.offers = 0 self.split = 0 def __len__(self): return len(self.__requests) def add_front(self, name, args, kwds): self.__requests.add_front(SpecialMessage(name, args, kwds)) def get_next_request(self): return self.__requests.get_next() def __add_callback_result(self, method, result, *args, **kwds): message = CallbackMessage(method, result, *args, **kwds) self.__requests.add(message) def __request_callback(self, request_id, method, *args, **kwds): self.__callbacks[request_id] = (method, args, kwds) def add_callback(self, method, request_id, *args, **kwds): message = self.__responses.get_async(request_id) if message: # We already have the result, add the result into the incoming # queue. self.__add_callback_result(method, message.response, *args, **kwds) else: self.__request_callback(request_id, method, *args, **kwds) def wait_for_result(self, request_id): return self.__responses.wait_for(request_id).response def add(self, message): if type(message) == RequestMessage: # TODO: reverse dependancy? would be nicer if actor # called add_front, but at the moment add_front only # deals with special messages- change help_offer to # be special, or change others so they aren't if message.name == 'help_offer': self.__requests.add_front(message) self.offers += 1 elif message.name == 'add_all': for msg in message.args: self.__requests.extend(msg) else: self.__requests.add(message) elif type(message) == ResponseMessage: if (self.__callbacks.has_key(message.id)): meth, args, kwds = self.__callbacks[message.id] #meth = self.__callbacks[message.id] del self.__callbacks[message.id] self.__add_callback_result(meth, message.response, *args, **kwds) else: self.__responses.add(message) elif type(message) == ActorJoinMessage: self.__requests.add(message) else: raise MessageRejectedException(self, message) def get_messages(self, start, finish): return self.__requests.get_messages(start, finish) def has_result(self, request_id): return self.__responses.has_result(request_id) def new_request(self): self.__last_req_id += 1 return self.__last_req_id def new_request(self): self.__last_req_id += 1 return self.__last_req_id