Mercurial > public > mercurial-scm > hg
diff mercurial/revlog.py @ 50638:5460424092e2
stream-clone: smoothly detect and handle a case were a revlog is split
This detect and handle the most common case for a race condition around stream
and revlog splitting. The one were the revlog is split between the initial
collection of data and the time were we start considering stream that data.
In such case, we repatch an inlined version of that revlog together when this
happens. This is necessary as stream-v2 promised a specific number of bytes and
a specific number of files to the client. In stream-v3, we will have the
opportunity to just send a split revlog instead.
Getting a better version of the protocol for stream-v3 is still useful, but it
is no longer a blocket to fix that race condition.
Note that another, rarer race condition exist, were the revlog is split while
we creating the revlog and extracing content from it. This can be dealt with
later.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Mon, 29 May 2023 18:41:58 +0200 |
parents | 9caa860dcbec |
children | 3b56395404a1 |
line wrap: on
line diff
--- a/mercurial/revlog.py Mon May 29 14:07:58 2023 +0200 +++ b/mercurial/revlog.py Mon May 29 18:41:58 2023 +0200 @@ -506,7 +506,7 @@ except FileNotFoundError: return b'' - def get_streams(self, max_linkrev): + def get_streams(self, max_linkrev, force_inline=False): n = len(self) index = self.index while n > 0: @@ -547,6 +547,29 @@ return [ (self._indexfile, inline_stream, index_size + data_size), ] + elif force_inline: + + def get_stream(): + with self._datafp() as fp_d: + yield None + + for rev in range(n): + idx = self.index.entry_binary(rev) + if rev == 0 and self._docket is None: + # re-inject the inline flag + header = self._format_flags + header |= self._format_version + header |= FLAG_INLINE_DATA + header = self.index.pack_header(header) + idx = header + idx + yield idx + yield self._getsegmentforrevs(rev, rev, df=fp_d)[1] + + inline_stream = get_stream() + next(inline_stream) + return [ + (self._indexfile, inline_stream, index_size + data_size), + ] else: def get_index_stream():