##// END OF EJS Templates
documentation: add `zstd` compression to the internal `revlogs` documentation...
Antoine Cezar -
r45961:684083d1 default
parent child Browse files
Show More
@@ -1,239 +1,241 b''
1 1 Revision logs - or *revlogs* - are an append only data structure for
2 2 storing discrete entries, or *revisions*. They are the primary storage
3 3 mechanism of repository data.
4 4
5 5 Revlogs effectively model a directed acyclic graph (DAG). Each node
6 6 has edges to 1 or 2 *parent* nodes. Each node contains metadata and
7 7 the raw value for that node.
8 8
9 9 Revlogs consist of entries which have metadata and revision data.
10 10 Metadata includes the hash of the revision's content, sizes, and
11 11 links to its *parent* entries. The collective metadata is referred
12 12 to as the *index* and the revision data is the *data*.
13 13
14 14 Revision data is stored as a series of compressed deltas against
15 15 ancestor revisions.
16 16
17 17 Revlogs are written in an append-only fashion. We never need to rewrite
18 18 a file to insert nor do we need to remove data. Rolling back in-progress
19 19 writes can be performed by truncating files. Read locks can be avoided
20 20 using simple techniques. This means that references to other data in
21 21 the same revlog *always* refer to a previous entry.
22 22
23 23 Revlogs can be modeled as 0-indexed arrays. The first revision is
24 24 revision #0 and the second is revision #1. The revision -1 is typically
25 25 used to mean *does not exist* or *not defined*.
26 26
27 27 File Format
28 28 ===========
29 29
30 30 A revlog begins with a 32-bit big endian integer holding version info
31 31 and feature flags. This integer overlaps with the first four bytes of
32 32 the first revision entry.
33 33
34 34 This integer is logically divided into 2 16-bit shorts. The least
35 35 significant half of the integer is the format/version short. The other
36 36 short holds feature flags that dictate behavior of the revlog.
37 37
38 38 The following values for the format/version short are defined:
39 39
40 40 0
41 41 The original revlog version.
42 42 1
43 43 RevlogNG (*next generation*). It replaced version 0 when it was
44 44 implemented in 2006.
45 45 2
46 46 In-development version incorporating accumulated knowledge and
47 47 missing features from 10+ years of revlog version 1.
48 48 57005 (0xdead)
49 49 Reserved for internal testing of new versions. No defined format
50 50 beyond 32-bit header.
51 51
52 52 The feature flags short consists of bit flags. Where 0 is the least
53 53 significant bit. The bit flags vary by revlog version.
54 54
55 55 Version 0 revlogs have no defined flags and the presence of a flag
56 56 is considered an error.
57 57
58 58 Version 1 revlogs have the following flags at the specified bit offsets:
59 59
60 60 0
61 61 Store revision data inline.
62 62 1
63 63 Generaldelta encoding.
64 64
65 65 Version 2 revlogs have the following flags at the specified bit offsets:
66 66
67 67 0
68 68 Store revision data inline.
69 69
70 70 The following header values are common:
71 71
72 72 00 00 00 01
73 73 v1
74 74 00 01 00 01
75 75 v1 + inline
76 76 00 02 00 01
77 77 v1 + generaldelta
78 78 00 03 00 01
79 79 v1 + inline + generaldelta
80 80
81 81 Following the 32-bit header is the remaining 60 bytes of the first index
82 82 entry. Following that are additional *index* entries. Inlined revision
83 83 data is possibly located between index entries. More on this inlined
84 84 layout is described below.
85 85
86 86 Version 1 Format
87 87 ================
88 88
89 89 Version 1 (RevlogNG) begins with an index describing the revisions in
90 90 the revlog. If the ``inline`` flag is set, revision data is stored inline,
91 91 or between index entries (as opposed to in a separate container).
92 92
93 93 Each index entry is 64 bytes. The byte layout of each entry is as
94 94 follows, with byte 0 being the first byte (all data stored as big endian):
95 95
96 96 0-3 (4 bytes) (rev 0 only)
97 97 Revlog header
98 98
99 99 0-5 (6 bytes)
100 100 Absolute offset of revision data from beginning of revlog.
101 101
102 102 6-7 (2 bytes)
103 103 Bit flags impacting revision behavior. The following bit offsets define:
104 104
105 105 0: REVIDX_ISCENSORED revision has censor metadata, must be verified.
106 106
107 107 1: REVIDX_ELLIPSIS revision hash does not match its data. Used by
108 108 narrowhg
109 109
110 110 2: REVIDX_EXTSTORED revision data is stored externally.
111 111
112 112 8-11 (4 bytes)
113 113 Compressed length of revision data / chunk as stored in revlog.
114 114
115 115 12-15 (4 bytes)
116 116 Uncompressed length of revision data. This is the size of the full
117 117 revision data, not the size of the chunk post decompression.
118 118
119 119 16-19 (4 bytes)
120 120 Base or previous revision this revision's delta was produced against.
121 121 This revision holds full text (as opposed to a delta) if it points to
122 122 itself. For generaldelta repos, this is the previous revision in the
123 123 delta chain. For non-generaldelta repos, this is the base or first
124 124 revision in the delta chain.
125 125
126 126 20-23 (4 bytes)
127 127 A revision this revision is *linked* to. This allows a revision in
128 128 one revlog to be forever associated with a revision in another
129 129 revlog. For example, a file's revlog may point to the changelog
130 130 revision that introduced it.
131 131
132 132 24-27 (4 bytes)
133 133 Revision of 1st parent. -1 indicates no parent.
134 134
135 135 28-31 (4 bytes)
136 136 Revision of 2nd parent. -1 indicates no 2nd parent.
137 137
138 138 32-63 (32 bytes)
139 139 Hash of revision's full text. Currently, SHA-1 is used and only
140 140 the first 20 bytes of this field are used. The rest of the bytes
141 141 are ignored and should be stored as \0.
142 142
143 143 If inline revision data is being stored, the compressed revision data
144 144 (of length from bytes offset 8-11 from the index entry) immediately
145 145 follows the index entry. There is no header on the revision data. There
146 146 is no padding between it and the index entries before and after.
147 147
148 148 If revision data is not inline, then raw revision data is stored in a
149 149 separate byte container. The offsets from bytes 0-5 and the compressed
150 150 length from bytes 8-11 define how to access this data.
151 151
152 152 The 6 byte absolute offset field from the first revlog entry overlaps
153 153 with the revlog header. That is, the first 6 bytes of the first revlog
154 154 entry can be split into four bytes containing the header for the revlog
155 155 file and an additional two bytes containing the offset for the first
156 156 entry. Since this is the offset from the beginning of the file for the
157 157 first revision entry, the two bytes will always be set to zero.
158 158
159 159 Version 2 Format
160 160 ================
161 161
162 162 (In development. Format not finalized or stable.)
163 163
164 164 Version 2 is identical to version 1 with the following differences.
165 165
166 166 There is no dedicated *generaldelta* revlog format flag. Instead,
167 167 the feature is implied enabled by default.
168 168
169 169 Delta Chains
170 170 ============
171 171
172 172 Revision data is encoded as a chain of *chunks*. Each chain begins with
173 173 the compressed original full text for that revision. Each subsequent
174 174 *chunk* is a *delta* against the previous revision. We therefore call
175 175 these chains of chunks/deltas *delta chains*.
176 176
177 177 The full text for a revision is reconstructed by loading the original
178 178 full text for the base revision of a *delta chain* and then applying
179 179 *deltas* until the target revision is reconstructed.
180 180
181 181 *Delta chains* are limited in length so lookup time is bound. They are
182 182 limited to ~2x the length of the revision's data. The linear distance
183 183 between the base chunk and the final chunk is also limited so the
184 184 amount of read I/O to load all chunks in the delta chain is bound.
185 185
186 186 Deltas and delta chains are either computed against the previous
187 187 revision in the revlog or another revision (almost certainly one of
188 188 the parents of the revision). Historically, deltas were computed against
189 189 the previous revision. The *generaldelta* revlog feature flag (enabled
190 190 by default in Mercurial 3.7) activates the mode where deltas are
191 191 computed against an arbitrary revision (almost certainly a parent revision).
192 192
193 193 File Storage
194 194 ============
195 195
196 196 Revlogs logically consist of an index (metadata of entries) and
197 197 revision data. This data may be stored together in a single file or in
198 198 separate files. The mechanism used is indicated by the ``inline`` feature
199 199 flag on the revlog.
200 200
201 201 Mercurial's behavior is to use inline storage until a revlog reaches a
202 202 certain size, at which point it will be converted to non-inline. The
203 203 reason there is a size limit on inline storage is to establish an upper
204 204 bound on how much data must be read to load the index. It would be a waste
205 205 to read tens or hundreds of extra megabytes of data just to access the
206 206 index data.
207 207
208 208 The actual layout of revlog files on disk is governed by the repository's
209 209 *store format*. Typically, a ``.i`` file represents the index revlog
210 210 (possibly containing inline data) and a ``.d`` file holds the revision data.
211 211
212 212 Revision Entries
213 213 ================
214 214
215 215 Revision entries consist of an optional 1 byte header followed by an
216 216 encoding of the revision data. The headers are as follows:
217 217
218 218 \0 (0x00)
219 219 Revision data is the entirety of the entry, including this header.
220 ( (0x28)
221 zstd https://github.com/facebook/zstd
220 222 u (0x75)
221 223 Raw revision data follows.
222 224 x (0x78)
223 225 zlib (RFC 1950) data.
224 226
225 227 The 0x78 value is actually the first byte of the zlib header (CMF byte).
226 228
227 229 Hash Computation
228 230 ================
229 231
230 232 The hash of the revision is stored in the index and is used both as a primary
231 233 key and for data integrity verification.
232 234
233 235 Currently, SHA-1 is the only supported hashing algorithm. To obtain the SHA-1
234 236 hash of a revision:
235 237
236 238 1. Hash the parent nodes
237 239 2. Hash the fulltext of the revision
238 240
239 241 The 20 byte node ids of the parents are fed into the hasher in ascending order.
General Comments 0
You need to be logged in to leave comments. Login now