(self, size=None)
| 140 | self.got_eof = (chunk == b'') |
| 141 | |
| 142 | def read(self, size=None): |
| 143 | # Handle case of "read all". |
| 144 | if size is None: |
| 145 | |
| 146 | # Read everything. |
| 147 | while not self.got_eof: |
| 148 | self._read_chunk(PIPE_BUF_BYTES) |
| 149 | |
| 150 | # Defragment and return the contents. |
| 151 | return self._bd.get_all() |
| 152 | elif size > 0: |
| 153 | while True: |
| 154 | if self._bd.byteSz >= size: |
| 155 | # Enough bytes already buffered. |
| 156 | return self._bd.get(size) |
| 157 | elif self._bd.byteSz <= size and self.got_eof: |
| 158 | # Not enough bytes buffered, but the stream is |
| 159 | # over, so return what has been gotten. |
| 160 | return self._bd.get_all() |
| 161 | else: |
| 162 | # Not enough bytes buffered and stream is still |
| 163 | # open: read more bytes. |
| 164 | assert not self.got_eof |
| 165 | |
| 166 | if size == PIPE_BUF_BYTES: |
| 167 | # Many PIPE_BUF_BYTES reads are done in WAL-E |
| 168 | # to move around data in bulk. |
| 169 | # |
| 170 | # Use that as a hint that another |
| 171 | # PIPE_BUF_BYTES-sized .read() will occur |
| 172 | # soon. The goal is to trigger the |
| 173 | # less-copy-intensive fast-path in the |
| 174 | # ByteDeque frequently. |
| 175 | # |
| 176 | # To do that, attempt to align the read |
| 177 | # syscalls to the kernel with Python reads, |
| 178 | # even if that means issuing a shorter read |
| 179 | # than usual. |
| 180 | to_read = PIPE_BUF_BYTES - self._bd.byteSz |
| 181 | self._read_chunk(to_read) |
| 182 | else: |
| 183 | self._read_chunk(PIPE_BUF_BYTES) |
| 184 | else: |
| 185 | assert False |
| 186 | |
| 187 | def close(self): |
| 188 | if self.closed: |
no test coverage detected