comparison mercurial/revlogutils/nodemap.py @ 44312:563dfdfd01a4

nodemap: delete older raw data file when creating a new ones When we write new full files, it replace an older one with a different name. We add the associated cleanup for the older file to be removed after the transaction. We delete all file matching the expected pattern to give use extra chance to delete orphan files we might have failed to delete earlier. Note: eventually we won't rewrite all data for each transaction. This is coming in later changesets. Differential Revision: https://phab.mercurial-scm.org/D7839
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 15 Jan 2020 15:47:59 +0100
parents 2b72c4ff8ed1
children 7f4f7ef3133e
comparison
equal deleted inserted replaced
44311:2b72c4ff8ed1 44312:563dfdfd01a4
7 # GNU General Public License version 2 or any later version. 7 # GNU General Public License version 2 or any later version.
8 8
9 from __future__ import absolute_import 9 from __future__ import absolute_import
10 10
11 import os 11 import os
12 import re
12 import struct 13 import struct
13 14
14 from .. import ( 15 from .. import (
15 error, 16 error,
16 node as nodemod, 17 node as nodemod,
69 msg = "calling persist nodemap on a revlog without the feature enableb" 70 msg = "calling persist nodemap on a revlog without the feature enableb"
70 raise error.ProgrammingError(msg) 71 raise error.ProgrammingError(msg)
71 data = persistent_data(revlog.index) 72 data = persistent_data(revlog.index)
72 uid = _make_uid() 73 uid = _make_uid()
73 datafile = _rawdata_filepath(revlog, uid) 74 datafile = _rawdata_filepath(revlog, uid)
75 olds = _other_rawdata_filepath(revlog, uid)
76 if olds:
77 realvfs = getattr(revlog, '_realopener', revlog.opener)
78
79 def cleanup(tr):
80 for oldfile in olds:
81 realvfs.tryunlink(oldfile)
82
83 callback_id = b"revlog-cleanup-nodemap-%s" % revlog.nodemap_file
84 tr.addpostclose(callback_id, cleanup)
74 # EXP-TODO: if this is a cache, this should use a cache vfs, not a 85 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
75 # store vfs 86 # store vfs
76 with revlog.opener(datafile, b'w') as fd: 87 with revlog.opener(datafile, b'w') as fd:
77 fd.write(data) 88 fd.write(data)
78 # EXP-TODO: if this is a cache, this should use a cache vfs, not a 89 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
132 143
133 def _rawdata_filepath(revlog, uid): 144 def _rawdata_filepath(revlog, uid):
134 """The (vfs relative) nodemap's rawdata file for a given uid""" 145 """The (vfs relative) nodemap's rawdata file for a given uid"""
135 prefix = revlog.nodemap_file[:-2] 146 prefix = revlog.nodemap_file[:-2]
136 return b"%s-%s.nd" % (prefix, uid) 147 return b"%s-%s.nd" % (prefix, uid)
148
149
150 def _other_rawdata_filepath(revlog, uid):
151 prefix = revlog.nodemap_file[:-2]
152 pattern = re.compile(b"(^|/)%s-[0-9a-f]+\.nd$" % prefix)
153 new_file_path = _rawdata_filepath(revlog, uid)
154 new_file_name = revlog.opener.basename(new_file_path)
155 dirpath = revlog.opener.dirname(new_file_path)
156 others = []
157 for f in revlog.opener.listdir(dirpath):
158 if pattern.match(f) and f != new_file_name:
159 others.append(f)
160 return others
137 161
138 162
139 ### Nodemap Trie 163 ### Nodemap Trie
140 # 164 #
141 # This is a simple reference implementation to compute and persist a nodemap 165 # This is a simple reference implementation to compute and persist a nodemap