comparison mercurial/revlogutils/nodemap.py @ 44322:72c15641c8b4

nodemap: introduce an explicit class/object for the docket We are about to add more information to this docket, having a clear location to stock them in memory will help. Differential Revision: https://phab.mercurial-scm.org/D7884
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 15 Jan 2020 15:49:35 +0100
parents f0862ee1a31e
children 76a96e3a2bbb
comparison
equal deleted inserted replaced
44321:f0862ee1a31e 44322:72c15641c8b4
34 offset = 0 34 offset = 0
35 (version,) = S_VERSION.unpack(pdata[offset : offset + S_VERSION.size]) 35 (version,) = S_VERSION.unpack(pdata[offset : offset + S_VERSION.size])
36 if version != ONDISK_VERSION: 36 if version != ONDISK_VERSION:
37 return None 37 return None
38 offset += S_VERSION.size 38 offset += S_VERSION.size
39 (uuid_size,) = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size]) 39 (uid_size,) = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size])
40 offset += S_HEADER.size 40 offset += S_HEADER.size
41 uid = pdata[offset : offset + uuid_size] 41 docket = NodeMapDocket(pdata[offset : offset + uid_size])
42 42
43 filename = _rawdata_filepath(revlog, uid) 43 filename = _rawdata_filepath(revlog, docket)
44 return revlog.opener.tryread(filename) 44 return revlog.opener.tryread(filename)
45 45
46 46
47 def setup_persistent_nodemap(tr, revlog): 47 def setup_persistent_nodemap(tr, revlog):
48 """Install whatever is needed transaction side to persist a nodemap on disk 48 """Install whatever is needed transaction side to persist a nodemap on disk
71 raise error.ProgrammingError(msg) 71 raise error.ProgrammingError(msg)
72 if util.safehasattr(revlog.index, "nodemap_data_all"): 72 if util.safehasattr(revlog.index, "nodemap_data_all"):
73 data = revlog.index.nodemap_data_all() 73 data = revlog.index.nodemap_data_all()
74 else: 74 else:
75 data = persistent_data(revlog.index) 75 data = persistent_data(revlog.index)
76 uid = _make_uid() 76 target_docket = NodeMapDocket()
77 datafile = _rawdata_filepath(revlog, uid) 77 datafile = _rawdata_filepath(revlog, target_docket)
78 olds = _other_rawdata_filepath(revlog, uid) 78 olds = _other_rawdata_filepath(revlog, target_docket)
79 if olds: 79 if olds:
80 realvfs = getattr(revlog, '_realopener', revlog.opener) 80 realvfs = getattr(revlog, '_realopener', revlog.opener)
81 81
82 def cleanup(tr): 82 def cleanup(tr):
83 for oldfile in olds: 83 for oldfile in olds:
90 with revlog.opener(datafile, b'w') as fd: 90 with revlog.opener(datafile, b'w') as fd:
91 fd.write(data) 91 fd.write(data)
92 # EXP-TODO: if this is a cache, this should use a cache vfs, not a 92 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
93 # store vfs 93 # store vfs
94 with revlog.opener(revlog.nodemap_file, b'w', atomictemp=True) as fp: 94 with revlog.opener(revlog.nodemap_file, b'w', atomictemp=True) as fp:
95 fp.write(_serialize_docket(uid)) 95 fp.write(target_docket.serialize())
96 # EXP-TODO: if the transaction abort, we should remove the new data and 96 # EXP-TODO: if the transaction abort, we should remove the new data and
97 # reinstall the old one. 97 # reinstall the old one.
98 98
99 99
100 ### Nodemap docket file 100 ### Nodemap docket file
133 133
134 The identifier is random and composed of ascii characters.""" 134 The identifier is random and composed of ascii characters."""
135 return nodemod.hex(os.urandom(ID_SIZE)) 135 return nodemod.hex(os.urandom(ID_SIZE))
136 136
137 137
138 def _serialize_docket(uid): 138 class NodeMapDocket(object):
139 """return serialized bytes for a docket using the passed uid""" 139 """metadata associated with persistent nodemap data
140 data = [] 140
141 data.append(S_VERSION.pack(ONDISK_VERSION)) 141 The persistent data may come from disk or be on their way to disk.
142 data.append(S_HEADER.pack(len(uid))) 142 """
143 data.append(uid) 143
144 return b''.join(data) 144 def __init__(self, uid=None):
145 145 if uid is None:
146 146 uid = _make_uid()
147 def _rawdata_filepath(revlog, uid): 147 self.uid = uid
148
149 def copy(self):
150 return NodeMapDocket(uid=self.uid)
151
152 def serialize(self):
153 """return serialized bytes for a docket using the passed uid"""
154 data = []
155 data.append(S_VERSION.pack(ONDISK_VERSION))
156 data.append(S_HEADER.pack(len(self.uid)))
157 data.append(self.uid)
158 return b''.join(data)
159
160
161 def _rawdata_filepath(revlog, docket):
148 """The (vfs relative) nodemap's rawdata file for a given uid""" 162 """The (vfs relative) nodemap's rawdata file for a given uid"""
149 prefix = revlog.nodemap_file[:-2] 163 prefix = revlog.nodemap_file[:-2]
150 return b"%s-%s.nd" % (prefix, uid) 164 return b"%s-%s.nd" % (prefix, docket.uid)
151 165
152 166
153 def _other_rawdata_filepath(revlog, uid): 167 def _other_rawdata_filepath(revlog, docket):
154 prefix = revlog.nodemap_file[:-2] 168 prefix = revlog.nodemap_file[:-2]
155 pattern = re.compile(b"(^|/)%s-[0-9a-f]+\.nd$" % prefix) 169 pattern = re.compile(b"(^|/)%s-[0-9a-f]+\.nd$" % prefix)
156 new_file_path = _rawdata_filepath(revlog, uid) 170 new_file_path = _rawdata_filepath(revlog, docket)
157 new_file_name = revlog.opener.basename(new_file_path) 171 new_file_name = revlog.opener.basename(new_file_path)
158 dirpath = revlog.opener.dirname(new_file_path) 172 dirpath = revlog.opener.dirname(new_file_path)
159 others = [] 173 others = []
160 for f in revlog.opener.listdir(dirpath): 174 for f in revlog.opener.listdir(dirpath):
161 if pattern.match(f) and f != new_file_name: 175 if pattern.match(f) and f != new_file_name: