diff mercurial/dirstatemap.py @ 49695:a3b1ab5f5dee stable

dirstate: deal with read-race for pure python code If we cannot read the dirstate data, this is probably because a writing process wrote it under our feet. So refresh the docket and try again a handful of time.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 28 Feb 2023 19:01:20 +0100
parents 53f196622699
children c9066fc609ef
line wrap: on
line diff
--- a/mercurial/dirstatemap.py	Wed Mar 01 16:05:28 2023 +0100
+++ b/mercurial/dirstatemap.py	Tue Feb 28 19:01:20 2023 +0100
@@ -37,6 +37,9 @@
 WRITE_MODE_FORCE_APPEND = 2
 
 
+V2_MAX_READ_ATTEMPTS = 5
+
+
 class _dirstatemapcommon:
     """
     Methods that are identical for both implementations of the dirstatemap
@@ -125,6 +128,21 @@
         return self._docket
 
     def _read_v2_data(self):
+        data = None
+        attempts = 0
+        while attempts < V2_MAX_READ_ATTEMPTS:
+            attempts += 1
+            try:
+                data = self._opener.read(self.docket.data_filename())
+            except FileNotFoundError:
+                # read race detected between docket and data file
+                # reload the docket and retry
+                self._docket = None
+        if data is None:
+            assert attempts >= V2_MAX_READ_ATTEMPTS
+            msg = b"dirstate read race happened %d times in a row"
+            msg %= attempts
+            raise error.Abort(msg)
         return self._opener.read(self.docket.data_filename())
 
     def write_v2_no_append(self, tr, st, meta, packed):