'Return the requested amount of bytes, fetching the next chunk of
the underlying iterator when needed.
This is replaced with cooperative_read in __init__ if the underlying
fd already supports read().'

def read(self, length=None):

    if (length is None):
        if ((len(self.buffer) - self.position) > 0):
            result = self.buffer[self.position:]
            self.buffer = ''
            self.position = 0
            return str(result)
        else:
            try:
                if (self.iterator is None):
                    self.iterator = self.__iter__()
                return next(self.iterator)
            except StopIteration:
                return ''
            finally:
                self.buffer = ''
                self.position = 0
    else:
        result = bytearray()
        while (len(result) < length):
            if (self.position < len(self.buffer)):
                to_read = (length - len(result))
                chunk = self.buffer[self.position:(self.position + to_read)]
                result.extend(chunk)
                if (len(result) >= MAX_COOP_READER_BUFFER_SIZE):
                    raise exception.LimitExceeded()
                self.position += len(chunk)
            else:
                try:
                    if (self.iterator is None):
                        self.iterator = self.__iter__()
                    self.buffer = next(self.iterator)
                    self.position = 0
                except StopIteration:
                    self.buffer = ''
                    self.position = 0
                    return bytes(result)
        return bytes(result)
