##// END OF EJS Templates
nodemap: use an intermediate "docket" file to carry small metadata...
marmoute -
r44792:2b72c4ff default
parent child Browse files
Show More
@@ -8,6 +8,7 b''
8
8
9 from __future__ import absolute_import
9 from __future__ import absolute_import
10
10
11 import os
11 import struct
12 import struct
12
13
13 from .. import (
14 from .. import (
@@ -26,7 +27,20 b' def persisted_data(revlog):'
26 """read the nodemap for a revlog from disk"""
27 """read the nodemap for a revlog from disk"""
27 if revlog.nodemap_file is None:
28 if revlog.nodemap_file is None:
28 return None
29 return None
29 return revlog.opener.tryread(revlog.nodemap_file)
30 pdata = revlog.opener.tryread(revlog.nodemap_file)
31 if not pdata:
32 return None
33 offset = 0
34 (version,) = S_VERSION.unpack(pdata[offset : offset + S_VERSION.size])
35 if version != ONDISK_VERSION:
36 return None
37 offset += S_VERSION.size
38 (uuid_size,) = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size])
39 offset += S_HEADER.size
40 uid = pdata[offset : offset + uuid_size]
41
42 filename = _rawdata_filepath(revlog, uid)
43 return revlog.opener.tryread(filename)
30
44
31
45
32 def setup_persistent_nodemap(tr, revlog):
46 def setup_persistent_nodemap(tr, revlog):
@@ -55,13 +69,71 b' def _persist_nodemap(tr, revlog):'
55 msg = "calling persist nodemap on a revlog without the feature enableb"
69 msg = "calling persist nodemap on a revlog without the feature enableb"
56 raise error.ProgrammingError(msg)
70 raise error.ProgrammingError(msg)
57 data = persistent_data(revlog.index)
71 data = persistent_data(revlog.index)
72 uid = _make_uid()
73 datafile = _rawdata_filepath(revlog, uid)
74 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
75 # store vfs
76 with revlog.opener(datafile, b'w') as fd:
77 fd.write(data)
58 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
78 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
59 # store vfs
79 # store vfs
60 with revlog.opener(revlog.nodemap_file, b'w') as f:
80 with revlog.opener(revlog.nodemap_file, b'w', atomictemp=True) as fp:
61 f.write(data)
81 fp.write(_serialize_docket(uid))
62 # EXP-TODO: if the transaction abort, we should remove the new data and
82 # EXP-TODO: if the transaction abort, we should remove the new data and
63 # reinstall the old one. (This will be simpler when the file format get a
83 # reinstall the old one.
64 # bit more advanced)
84
85
86 ### Nodemap docket file
87 #
88 # The nodemap data are stored on disk using 2 files:
89 #
90 # * a raw data files containing a persistent nodemap
91 # (see `Nodemap Trie` section)
92 #
93 # * a small "docket" file containing medatadata
94 #
95 # While the nodemap data can be multiple tens of megabytes, the "docket" is
96 # small, it is easy to update it automatically or to duplicated its content
97 # during a transaction.
98 #
99 # Multiple raw data can exist at the same time (The currently valid one and a
100 # new one beind used by an in progress transaction). To accomodate this, the
101 # filename hosting the raw data has a variable parts. The exact filename is
102 # specified inside the "docket" file.
103 #
104 # The docket file contains information to find, qualify and validate the raw
105 # data. Its content is currently very light, but it will expand as the on disk
106 # nodemap gains the necessary features to be used in production.
107
108 # version 0 is experimental, no BC garantee, do no use outside of tests.
109 ONDISK_VERSION = 0
110
111 S_VERSION = struct.Struct(">B")
112 S_HEADER = struct.Struct(">B")
113
114 ID_SIZE = 8
115
116
117 def _make_uid():
118 """return a new unique identifier.
119
120 The identifier is random and composed of ascii characters."""
121 return nodemod.hex(os.urandom(ID_SIZE))
122
123
124 def _serialize_docket(uid):
125 """return serialized bytes for a docket using the passed uid"""
126 data = []
127 data.append(S_VERSION.pack(ONDISK_VERSION))
128 data.append(S_HEADER.pack(len(uid)))
129 data.append(uid)
130 return b''.join(data)
131
132
133 def _rawdata_filepath(revlog, uid):
134 """The (vfs relative) nodemap's rawdata file for a given uid"""
135 prefix = revlog.nodemap_file[:-2]
136 return b"%s-%s.nd" % (prefix, uid)
65
137
66
138
67 ### Nodemap Trie
139 ### Nodemap Trie
@@ -10,6 +10,8 b' Test the persistent on-disk nodemap'
10 > exp-persistent-nodemap=yes
10 > exp-persistent-nodemap=yes
11 > EOF
11 > EOF
12 $ hg debugbuilddag .+5000
12 $ hg debugbuilddag .+5000
13 $ f --size .hg/store/00changelog.n
14 .hg/store/00changelog.n: size=18
13 $ hg debugnodemap --dump-new | f --sha256 --size
15 $ hg debugnodemap --dump-new | f --sha256 --size
14 size=122880, sha256=b961925120e1c9bc345c199b2cc442abc477029fdece37ef9d99cbe59c0558b7
16 size=122880, sha256=b961925120e1c9bc345c199b2cc442abc477029fdece37ef9d99cbe59c0558b7
15 $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
17 $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
General Comments 0
You need to be logged in to leave comments. Login now