D9277: transaction: change list of journal entries into a dictionary
joerg.sonnenberger (Joerg Sonnenberger)
phabricator at mercurial-scm.org
Sat Nov 7 21:32:17 UTC 2020
joerg.sonnenberger created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.
REVISION SUMMARY
The transaction object used to keep a mapping table of path names to
journal entries and a list of journal entries consisting of path and
file offset to truncate on rollback. Code normally doesn't care about
the order at all with the exception of repair.strip, which cares only
about finding new entries. For the special case of repair.strip,
remember the keys before the strip operation and compute the difference
with the keys afterwards. Some extra care is necessary as the test case
wants deterministic operation, but this is outside the hot path so just
sort everything.
REPOSITORY
rHG Mercurial
BRANCH
default
REVISION DETAIL
https://phab.mercurial-scm.org/D9277
AFFECTED FILES
mercurial/repair.py
mercurial/transaction.py
CHANGE DETAILS
diff --git a/mercurial/transaction.py b/mercurial/transaction.py
--- a/mercurial/transaction.py
+++ b/mercurial/transaction.py
@@ -158,8 +158,7 @@
vfsmap[b''] = opener # set default value
self._vfsmap = vfsmap
self._after = after
- self._entries = []
- self._map = {}
+ self._offsetmap = {}
self._journal = journalname
self._undoname = undoname
self._queue = []
@@ -249,7 +248,7 @@
@active
def add(self, file, offset):
"""record the state of an append-only file before update"""
- if file in self._map or file in self._backupmap:
+ if file in self._offsetmap or file in self._backupmap:
return
if self._queue:
self._queue[-1].append((file, offset))
@@ -259,10 +258,9 @@
def _addentry(self, file, offset):
"""add a append-only entry to memory and on-disk state"""
- if file in self._map or file in self._backupmap:
+ if file in self._offsetmap or file in self._backupmap:
return
- self._entries.append((file, offset))
- self._map[file] = len(self._entries) - 1
+ self._offsetmap[file] = offset
# add enough data to the journal to do the truncate
self._file.write(b"%s\0%d\n" % (file, offset))
self._file.flush()
@@ -282,7 +280,7 @@
msg = b'cannot use transaction.addbackup inside "group"'
raise error.ProgrammingError(msg)
- if file in self._map or file in self._backupmap:
+ if file in self._offsetmap or file in self._backupmap:
return
vfs = self._vfsmap[location]
dirname, filename = vfs.split(file)
@@ -396,9 +394,7 @@
@active
def findoffset(self, file):
- if file in self._map:
- return self._entries[self._map[file]][1]
- return None
+ return self._offsetmap.get(file)
@active
def replace(self, file, offset):
@@ -407,10 +403,9 @@
that are not pending in the queue
'''
- if file not in self._map:
+ if file not in self._offsetmap:
raise KeyError(file)
- index = self._map[file]
- self._entries[index] = (file, offset)
+ self._offsetmap[file] = offset
self._file.write(b"%s\0%d\n" % (file, offset))
self._file.flush()
@@ -550,7 +545,7 @@
self._report(
b"couldn't remove %s: %s\n" % (vfs.join(b), inst)
)
- self._entries = []
+ self._offsetmap = {}
self._writeundo()
if self._after:
self._after()
@@ -631,9 +626,11 @@
self._usages = 0
self._file.close()
self._backupsfile.close()
+ entries = list(pycompat.iteritems(self._offsetmap))
+ entries.sort()
try:
- if not self._entries and not self._backupentries:
+ if not self._offsetmap and not self._backupentries:
if self._backupjournal:
self._opener.unlink(self._backupjournal)
if self._journal:
@@ -652,7 +649,7 @@
self._report,
self._opener,
self._vfsmap,
- self._entries,
+ entries,
self._backupentries,
False,
checkambigfiles=self._checkambigfiles,
diff --git a/mercurial/repair.py b/mercurial/repair.py
--- a/mercurial/repair.py
+++ b/mercurial/repair.py
@@ -209,7 +209,7 @@
# transaction and makes assumptions that file storage is
# using append-only files. We'll need some kind of storage
# API to handle stripping for us.
- offset = len(tr._entries)
+ oldfiles = set(tr._offsetmap.keys())
tr.startgroup()
cl.strip(striprev, tr)
@@ -219,8 +219,14 @@
repo.file(fn).strip(striprev, tr)
tr.endgroup()
- for i in pycompat.xrange(offset, len(tr._entries)):
- file, troffset = tr._entries[i]
+ newfiles = set(tr._offsetmap.keys())
+ newfiles.difference_update(oldfiles)
+
+ # The processing order doesn't matter during normal
+ # operation, but the test-repair-strip.t test case
+ # inserts faults and it benefits from the sorting.
+ for file in sorted(newfiles):
+ troffset = tr.findoffset(file)
with repo.svfs(file, b'a', checkambig=True) as fp:
fp.truncate(troffset)
if troffset == 0:
To: joerg.sonnenberger, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
More information about the Mercurial-devel
mailing list