~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/__init__.py

(gz) Bug #656170, be more aggressive about closing file handles (Martin [gz])

Show diffs side-by-side

added added

removed removed

Lines of Context:
672
672
 
673
673
        This uses _coalesce_offsets to issue larger reads and fewer seeks.
674
674
 
675
 
        :param fp: A file-like object that supports seek() and read(size)
 
675
        :param fp: A file-like object that supports seek() and read(size).
 
676
            Note that implementations are allowed to call .close() on this file
 
677
            handle, so don't trust that you can use it for other work.
676
678
        :param offsets: A list of offsets to be read from the given file.
677
679
        :return: yield (pos, data) tuples for each request
678
680
        """
689
691
 
690
692
        # Cache the results, but only until they have been fulfilled
691
693
        data_map = {}
692
 
        for c_offset in coalesced:
693
 
            # TODO: jam 20060724 it might be faster to not issue seek if
694
 
            #       we are already at the right location. This should be
695
 
            #       benchmarked.
696
 
            fp.seek(c_offset.start)
697
 
            data = fp.read(c_offset.length)
698
 
            if len(data) < c_offset.length:
699
 
                raise errors.ShortReadvError(relpath, c_offset.start,
700
 
                            c_offset.length, actual=len(data))
701
 
            for suboffset, subsize in c_offset.ranges:
702
 
                key = (c_offset.start+suboffset, subsize)
703
 
                data_map[key] = data[suboffset:suboffset+subsize]
 
694
        try:
 
695
            for c_offset in coalesced:
 
696
                # TODO: jam 20060724 it might be faster to not issue seek if
 
697
                #       we are already at the right location. This should be
 
698
                #       benchmarked.
 
699
                fp.seek(c_offset.start)
 
700
                data = fp.read(c_offset.length)
 
701
                if len(data) < c_offset.length:
 
702
                    raise errors.ShortReadvError(relpath, c_offset.start,
 
703
                                c_offset.length, actual=len(data))
 
704
                for suboffset, subsize in c_offset.ranges:
 
705
                    key = (c_offset.start+suboffset, subsize)
 
706
                    data_map[key] = data[suboffset:suboffset+subsize]
704
707
 
705
 
            # Now that we've read some data, see if we can yield anything back
706
 
            while cur_offset_and_size in data_map:
707
 
                this_data = data_map.pop(cur_offset_and_size)
708
 
                this_offset = cur_offset_and_size[0]
709
 
                try:
710
 
                    cur_offset_and_size = offset_stack.next()
711
 
                except StopIteration:
712
 
                    # Close the file handle as there will be no more data
713
 
                    # The handle would normally be cleaned up as this code goes
714
 
                    # out of scope, but as we are a generator, not all code
715
 
                    # will re-enter once we have consumed all the expected
716
 
                    # data. For example:
717
 
                    #   zip(range(len(requests)), readv(foo, requests))
718
 
                    # Will stop because the range is done, and not run the
719
 
                    # cleanup code for the readv().
720
 
                    fp.close()
721
 
                    cur_offset_and_size = None
722
 
                yield this_offset, this_data
 
708
                # Now that we've read some data, see if we can yield anything back
 
709
                while cur_offset_and_size in data_map:
 
710
                    this_data = data_map.pop(cur_offset_and_size)
 
711
                    this_offset = cur_offset_and_size[0]
 
712
                    try:
 
713
                        cur_offset_and_size = offset_stack.next()
 
714
                    except StopIteration:
 
715
                        cur_offset_and_size = None
 
716
                    yield this_offset, this_data
 
717
        except:
 
718
            fp.close()
 
719
            raise
 
720
        fp.close()
723
721
 
724
722
    def _sort_expand_and_combine(self, offsets, upper_limit):
725
723
        """Helper for readv.