def read(self, offset, length, fh):
current = (offset, offset + length)<EOL>safe = [ current[<NUM_LIT:0>] - ( <NUM_LIT:8> * length ), current[<NUM_LIT:1>] + ( <NUM_LIT:16> * length ) ]<EOL>if safe[<NUM_LIT:0>] < <NUM_LIT:0>: safe[<NUM_LIT:0>] = <NUM_LIT:0><EOL>if safe[<NUM_LIT:1>] > self.filesize: safe[<NUM_LIT:1>] = self.filesize<EOL>safe = tuple(safe)<EOL>self.lock.acquire()<EOL>try:<EOL><INDENT>dl = range_t({safe}) - self.avail<EOL>for r in dl.toset():<EOL><INDENT>try:<EOL><INDENT>Downloader.fetch(self, r, fh) <EOL><DEDENT>except requests.exceptions.ConnectionError:<EOL><INDENT>raise ConnectionError<EOL><DEDENT><DEDENT>if self.disk + <NUM_LIT:1> < len(self.avail):<EOL><INDENT>self.data.rollover()<EOL>self.disk += <NUM_LIT:1><EOL><DEDENT><DEDENT>finally:<EOL><INDENT>self.lock.release()<EOL><DEDENT>self.data.seek(offset)<EOL>return self.data.read(length)<EOL>
Read data. Method returns data instantly, if they're avaialable and in ``self.safe_range``. Otherwise data is
downloaded and then returned.

Parameters
----------
offset : int
    Read offset
length : int
    Length of data to read.
fh : int
    File descriptor.