Mercurial > hg
changeset 47463:5fa083a5ff04
copies: Keep changelog sidedata file open during copy tracing
Instead of having a callback that opens and closes that file many times,
a add and use a context manager method on the `revlog` class that keeps
files open for its duration.
Differential Revision: https://phab.mercurial-scm.org/D10888
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Thu, 17 Jun 2021 19:48:25 +0200 |
parents | 75d4e60c7c81 |
children | bc8536e09a20 |
files | mercurial/copies.py mercurial/revlog.py mercurial/revlogutils/randomaccessfile.py |
diffstat | 3 files changed, 38 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/copies.py Tue Jun 22 13:18:29 2021 -0400 +++ b/mercurial/copies.py Thu Jun 17 19:48:25 2021 +0200 @@ -318,15 +318,16 @@ if p in children_count: children_count[p] += 1 revinfo = _revinfo_getter(repo, match) - return _combine_changeset_copies( - revs, - children_count, - b.rev(), - revinfo, - match, - isancestor, - multi_thread, - ) + with repo.changelog.reading(): + return _combine_changeset_copies( + revs, + children_count, + b.rev(), + revinfo, + match, + isancestor, + multi_thread, + ) else: # When not using side-data, we will process the edges "from" the parent. # so we need a full mapping of the parent -> children relation.
--- a/mercurial/revlog.py Tue Jun 22 13:18:29 2021 -0400 +++ b/mercurial/revlog.py Thu Jun 17 19:48:25 2021 +0200 @@ -2086,6 +2086,13 @@ """called when trying to add a node already stored.""" @contextlib.contextmanager + def reading(self): + """Context manager that keeps data and sidedata files open for reading""" + with self._segmentfile.reading(): + with self._segmentfile_sidedata.reading(): + yield + + @contextlib.contextmanager def _writing(self, transaction): if self._trypending: msg = b'try to write in a `trypending` revlog: %s'
--- a/mercurial/revlogutils/randomaccessfile.py Tue Jun 22 13:18:29 2021 -0400 +++ b/mercurial/revlogutils/randomaccessfile.py Thu Jun 17 19:48:25 2021 +0200 @@ -40,6 +40,7 @@ self.filename = filename self.default_cached_chunk_size = default_cached_chunk_size self.writing_handle = None # This is set from revlog.py + self.reading_handle = None self._cached_chunk = b'' self._cached_chunk_position = 0 # Offset from the start of the file if initial_cache: @@ -67,11 +68,31 @@ elif self.writing_handle: yield self.writing_handle + elif self.reading_handle: + yield self.reading_handle + # Otherwise open a new file handle. else: with self._open() as fp: yield fp + @contextlib.contextmanager + def reading(self): + """Context manager that keeps the file open for reading""" + if ( + self.reading_handle is None + and self.writing_handle is None + and self.filename is not None + ): + with self._open() as fp: + self.reading_handle = fp + try: + yield + finally: + self.reading_handle = None + else: + yield + def read_chunk(self, offset, length, existing_file_obj=None): """Read a chunk of bytes from the file.