예제 #1
0
class FrameHandler(object):

    def __init__(self, connection):
        self.conn = connection
        self.status = status.CLOSED
        self._method_queue = []
        self._pending_meth = None
        self._pending_cb = None
        self._msg_builder = None

    @property
    def message(self):
        return self._msg_builder.get_msg()

    @property
    def callback(self):
        return self._pending_cb

    def invoke_callback(self, *args, **kargs):
        if self._pending_cb:
            try:
                self._pending_cb(*args, **kargs)
            except Exception:
                logger.error('Error in callback for %s', self._pending_meth,
                                                         exc_info=True)
            self._pending_cb = None

    def process_frame(self, frame):
        processor = getattr(self, 'process_'+frame.frame_type)
        processor(frame.payload)

    def process_method(self, method):
        if method._content:
            self._msg_builder = MessageBuilder(content_method=method)
        else:
            self._msg_builder = None
            self.handle_method(method)

    def process_content_header(self, ch):
        self._msg_builder.add_content_header(ch)

    def process_content_body(self, cb):
        # FIXME better error checking
        self._msg_builder.add_content_body(cb)
        if self._msg_builder.msg_complete:
            self.handle_method(self._msg_builder.content_method)

    def process_heartbeat(self, hb):
        self.conn.stream.write(HEARTBEAT)

    def handle_method(self, method):
        pending_meth = self._pending_meth
        if hasattr(method, 'handle'):
            try:
                method.handle(self)
            except AmqpError:
                logger.error('Error while handling %s', method, exc_info=True)
                self.reset()
                return
        if pending_meth and method._name.startswith(pending_meth._name):
            self.invoke_callback()
            self._flush()

    def send_method(self, method, callback=None, message=None):
        if self.status == status.CLOSED:
            raise AmqpStatusError('cannot send on a closed %s' %
                                  type(self).__name__)
        self._method_queue.append( (method, callback, message) )
        if not self._pending_meth:
            self._flush()

    def _flush(self):
        self._pending_cb = None
        self._pending_meth = None
        while self._pending_meth is None and self._method_queue:
            method, callback, msg = self._method_queue.pop(0)
            self.write_method(method)
            if msg:
                self.write_msg(msg)
            if method._sync:
                self._pending_meth = method
                self._pending_cb = callback
            else:
                if callback is not None:
                    callback()

    def write_method(self, method):
        f = from_method(method, self)
        self.conn.stream.write(f)

    def write_msg(self, msg):
        frames = []
        frames.append(content_header_from_msg(msg, self))
        frames.extend(body_frames_from_msg(msg, self))
        self.conn.stream.write(''.join(frames))

    def reset(self):
        self.status = status.CLOSED
        self._method_queue = []
        self._pending_meth = None
        self._pending_cb = None
        self._msg_builder = None
예제 #2
0
 def process_method(self, method):
     if method._content:
         self._msg_builder = MessageBuilder(content_method=method)
     else:
         self._msg_builder = None
         self.handle_method(method)