def test_size_zero_buffer(self): b = RingBuffer(0) self.assertEqual(b.bytes_total(), 0) self.assertEqual(b.bytes_free(), 0) self.assertEqual(b.bytes_used(), 0) with self.assertRaises(ValueError): b.write(b"a")
def test_basic_wrap(self): b = RingBuffer(4) b.write(b"ab") self.assertEqual(b.read(), b"ab") self.assertEqual(b.bytes_used(), 0) b.write(b"cde") self.assertEqual(b.read(), b"cd") self.assertEqual(b.read(), b"e") self.assertEqual(b.read(), None)
def test_size_one_buffer(self): b = RingBuffer(1) self.assertEqual(b.bytes_total(), 1) self.assertEqual(b.bytes_free(), 1) self.assertEqual(b.bytes_used(), 0) b.write(b"a") self.assertEqual(b.bytes_total(), 1) self.assertEqual(b.bytes_free(), 0) self.assertEqual(b.bytes_used(), 1) self.assertEqual(b.read(), b"a") self.assertEqual(b.bytes_total(), 1) self.assertEqual(b.bytes_free(), 1) self.assertEqual(b.bytes_used(), 0) self.assertEqual(b.read(), None) b.write(b"b") self.assertEqual(b.read(), b"b") self.assertEqual(b.read(), None)
def test_write_empty(self): b = RingBuffer(6) b.write(b"") self.assertEqual(b.bytes_used(), 0) self.assertEqual(b.read(), None)
class Messenger(object): def __init__(self, socket): self.socket = socket self._read_buffer = RingBuffer(2**20) self._send_buffer = RingBuffer(2**20) self._parser = MessageReader() def debug(self, s): print("Messenger{}: {}".format(self.socket.getpeername(), s)) def read_messages(self): """Call this you when know there is readable data for this socket; it will yield a tuple in the format of (transaction_id, message object) for each message that has been received.""" bytes_read = self.socket.recv(2048) if len(bytes_read) == 0: raise MessengerConnectionBroken("Socket connection broken", self.socket) self.debug("read {} bytes".format(len(bytes_read))) try: self._read_buffer.write(bytes_read) except ValueError: raise MessengerBufferFullError( "Failed to read message because read buffer is full", self.socket) while True: parsed = self._parser.try_parse(self._read_buffer) if parsed is None: return else: (tid, message) = parsed self.debug("received message; tid: {} message: {}".format( tid, message)) yield tid, message def queue_message(self, tid, message): """An API for queuing messages for sending later""" self.debug("queuing message; tid: {} message: {}".format( tid, message)) data = bson.dumps(message) header = struct.pack(MSG_HEADER_FMT, tid, len(data)) try: self._send_buffer.write(header) self._send_buffer.write(data) except ValueError: MessengerBufferFullError( "Failed to enqueue message because send buffer is full", self.socket) def has_messages_to_send(self): """Returns true if a message was previously queued but has not yet been sent""" return self._send_buffer.bytes_used() > 0 def send_messages(self): """Call this to actually send messages previous queued""" while True: to_send = self._send_buffer.read() if to_send is None: break self.debug("sending {} bytes".format(len(to_send))) message_length = len(to_send) bytes_sent_total = 0 while bytes_sent_total < message_length: sent = self.socket.send(to_send[bytes_sent_total:]) if sent == 0: raise MessengerConnectionBroken( "error sending, probably socket connection broke", self.socket) bytes_sent_total += sent