From 291f8e196ccb4343e2539a55d480b0b5a76d1e87 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Fri, 5 Apr 2019 13:19:13 -0500 Subject: simplify rotation --- waitress/channel.py | 17 ++++++----------- waitress/tests/test_channel.py | 23 ++++++++++++++--------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/waitress/channel.py b/waitress/channel.py index 27eb532..6f20742 100644 --- a/waitress/channel.py +++ b/waitress/channel.py @@ -222,7 +222,7 @@ class HTTPChannel(wasyncore.dispatcher, object): while True: outbuf = self.outbufs[0] # use outbuf.__len__ rather than len(outbuf) FBO of not getting - # OverflowError on 32-bit Python + # OverflowError on 32-bit Python outbuflen = outbuf.__len__() while outbuflen > 0: chunk = outbuf.get(self.sendbuf_len) @@ -303,7 +303,7 @@ class HTTPChannel(wasyncore.dispatcher, object): # the async mainloop might be popping data off outbuf; we can # block here waiting for it because we're in a task thread with self.outbuf_lock: - overflowed = self._flush_outbufs_below_high_watermark() + self._flush_outbufs_below_high_watermark() if not self.connected: raise ClientDisconnected if data.__class__ is ReadOnlyFileBasedBuffer: @@ -313,12 +313,9 @@ class HTTPChannel(wasyncore.dispatcher, object): self.outbufs.append(nextbuf) self.current_outbuf_count = 0 else: - # if we overflowed then start a new buffer to ensure - # the original eventually gets pruned otherwise it may - # grow unbounded - if overflowed or ( - self.current_outbuf_count > self.adj.outbuf_high_watermark - ): + # if we overflowed then start a new buffer to ensure avoid + # this buffer growing unbounded + if self.current_outbuf_count > self.adj.outbuf_high_watermark: nextbuf = OverflowableBuffer(self.adj.outbuf_overflow) self.outbufs.append(nextbuf) self.current_outbuf_count = 0 @@ -334,16 +331,14 @@ class HTTPChannel(wasyncore.dispatcher, object): return 0 def _flush_outbufs_below_high_watermark(self): - overflowed = self.total_outbufs_len > self.adj.outbuf_high_watermark # check first to avoid locking if possible - if overflowed: + if self.total_outbufs_len > self.adj.outbuf_high_watermark: with self.outbuf_lock: while ( self.connected and self.total_outbufs_len > self.adj.outbuf_high_watermark ): self.outbuf_lock.wait() - return overflowed def service(self): """Execute all pending requests """ diff --git a/waitress/tests/test_channel.py b/waitress/tests/test_channel.py index ff3bba6..35fccf6 100644 --- a/waitress/tests/test_channel.py +++ b/waitress/tests/test_channel.py @@ -239,18 +239,27 @@ class TestHTTPChannel(unittest.TestCase): def test_write_soon_rotates_outbuf_on_overflow(self): inst, sock, map = self._makeOneWithMap() inst.adj.outbuf_high_watermark = 3 - inst.outbufs = [DummyBuffer(b'abcd')] - inst.total_outbufs_len = sum(len(x) for x in inst.outbufs) + inst.current_outbuf_count = 4 + wrote = inst.write_soon(b'xyz') + self.assertEqual(wrote, 3) + self.assertEqual(len(inst.outbufs), 2) + self.assertEqual(inst.outbufs[0].get(), b'') + self.assertEqual(inst.outbufs[1].get(), b'xyz') + + def test_write_soon_waits_on_backpressure(self): + inst, sock, map = self._makeOneWithMap() + inst.adj.outbuf_high_watermark = 3 + inst.total_outbufs_len = 4 + inst.current_outbuf_count = 4 class Lock(DummyLock): def wait(self): - inst.outbufs[0].prune() - inst.total_outbufs_len = sum(len(x) for x in inst.outbufs) + inst.total_outbufs_len = 0 super(Lock, self).wait() inst.outbuf_lock = Lock() wrote = inst.write_soon(b'xyz') self.assertEqual(wrote, 3) self.assertEqual(len(inst.outbufs), 2) - self.assertTrue(inst.outbufs[0].pruned) + self.assertEqual(inst.outbufs[0].get(), b'') self.assertEqual(inst.outbufs[1].get(), b'xyz') self.assertTrue(inst.outbuf_lock.waited) @@ -753,10 +762,6 @@ class DummyBuffer(object): def skip(self, num, x): self.skipped = num - def prune(self): - self.pruned = True - self.data = b'' - def __len__(self): return len(self.data) -- cgit v1.2.1