diff mercurial/revlogutils/randomaccessfile.py @ 51107:222b89224397

changelog-delay: move the appender class next to randomaccessfile We want to move the delay/divert logic at the revlog level (to have all IO related logic in the _InnerRevlog) we start with small piece that are easy to move on their own.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Thu, 26 Oct 2023 03:29:46 +0200
parents 594f912818ab
children d83d788590a8
line wrap: on
line diff
--- a/mercurial/revlogutils/randomaccessfile.py	Fri Oct 20 12:13:33 2023 +0200
+++ b/mercurial/revlogutils/randomaccessfile.py	Thu Oct 26 03:29:46 2023 +0200
@@ -23,6 +23,76 @@
     return (n & (n - 1) == 0) and n != 0
 
 
+class appender:
+    """the changelog index must be updated last on disk, so we use this class
+    to delay writes to it"""
+
+    def __init__(self, vfs, name, mode, buf):
+        self.data = buf
+        fp = vfs(name, mode)
+        self.fp = fp
+        self.offset = fp.tell()
+        self.size = vfs.fstat(fp).st_size
+        self._end = self.size
+
+    def end(self):
+        return self._end
+
+    def tell(self):
+        return self.offset
+
+    def flush(self):
+        pass
+
+    @property
+    def closed(self):
+        return self.fp.closed
+
+    def close(self):
+        self.fp.close()
+
+    def seek(self, offset, whence=0):
+        '''virtual file offset spans real file and data'''
+        if whence == 0:
+            self.offset = offset
+        elif whence == 1:
+            self.offset += offset
+        elif whence == 2:
+            self.offset = self.end() + offset
+        if self.offset < self.size:
+            self.fp.seek(self.offset)
+
+    def read(self, count=-1):
+        '''only trick here is reads that span real file and data'''
+        ret = b""
+        if self.offset < self.size:
+            s = self.fp.read(count)
+            ret = s
+            self.offset += len(s)
+            if count > 0:
+                count -= len(s)
+        if count != 0:
+            doff = self.offset - self.size
+            self.data.insert(0, b"".join(self.data))
+            del self.data[1:]
+            s = self.data[0][doff : doff + count]
+            self.offset += len(s)
+            ret += s
+        return ret
+
+    def write(self, s):
+        self.data.append(bytes(s))
+        self.offset += len(s)
+        self._end += len(s)
+
+    def __enter__(self):
+        self.fp.__enter__()
+        return self
+
+    def __exit__(self, *args):
+        return self.fp.__exit__(*args)
+
+
 class randomaccessfile:
     """Accessing arbitrary chuncks of data within a file, with some caching"""