In the command-line client, forbid
[svn.git] / subversion / libsvn_fs_fs / structure
blobe6788b803cda0574a01556f9e311664d17884d86
1 This file describes the design, layouts, and file formats of a
2 libsvn_fs_fs repository.
4 Design
5 ------
7 In FSFS, each committed revision is represented as an immutable file
8 containing the new node-revisions, contents, and changed-path
9 information for the revision, plus a second, changeable file
10 containing the revision properties.
12 In contrast to the BDB back end, the contents of recent revision of
13 files are stored as deltas against earlier revisions, instead of the
14 other way around.  This is less efficient for common-case checkouts,
15 but brings greater simplicity and robustness, as well as the
16 flexibility to make commits work without write access to existing
17 revisions.  Skip-deltas and delta combination mitigate the checkout
18 cost.
20 In-progress transactions are represented with a prototype rev file
21 containing only the new text representations of files (appended to as
22 changed file contents come in), along with a separate file for each
23 node-revision, directory representation, or property representation
24 which has been changed or added in the transaction.  During the final
25 stage of the commit, these separate files are marshalled onto the end
26 of the prototype rev file to form the immutable revision file.
28 Layout of the FS directory
29 --------------------------
31 The layout of the FS directory (the "db" subdirectory of the
32 repository) is:
34   revs/               Subdirectory containing revs
35     <shard>/          Shard directory, if sharding is in use (see below)
36       <revnum>        File containing rev <revnum>
37   revprops/           Subdirectory containing rev-props
38     <shard>/          Shard directory, if sharding is in use (see below)
39       <revnum>        File containing rev-props for <revnum>
40   indexes.sqlite      SQLite database containing index for svn:mergeinfo props
41   transactions/       Subdirectory containing transactions
42     <txnid>.txn/      Directory containing transaction <txnid>
43   transaction-current File containing the next transaction key
44   locks/              Subdirectory containing locks
45     <partial-digest>/ Subdirectory named for first 3 letters of an MD5 digest
46       <digest>        File containing locks/children for path with <digest>
47   current             File specifying current revision and next node/copy id
48   fs-type             File identifying this filesystem as an FSFS filesystem
49   write-lock          Empty file, locked to serialise writers
50   txn-current-lock    Empty file, locked to serialise 'transaction-current'
51   uuid                File containing the UUID of the repository
52   format              File containing the format number of this filesystem
54 Files in the revprops directory are in the hash dump format used by
55 svn_hash_write.
57 The format of the "current" file is a single line of the form
58 "<youngest-revision> <next-node-id> <next-copy-id>\n" giving the
59 youngest revision, the next unique node-ID, and the next unique
60 copy-ID for the repository.
62 The "write-lock" file is an empty file which is locked before the
63 final stage of a commit and unlocked after the new "current" file has
64 been moved into place to indicate that a new revision is present.  It
65 is also locked during a revprop propchange while the revprop file is
66 read in, mutated, and written out again.  Note that readers are never
67 blocked by any operation - writers must ensure that the filesystem is
68 always in a consistent state.
70 The "transaction-current" file is a file with a single line of text
71 that contains only a base-36 number.  The current value will be used
72 in the next transaction name, along with the revision number the
73 transaction is based on.  This sequence number ensures that
74 transaction names are not reused, even if the transaction is aborted
75 and a new transaction based on the same revision is begun.  The only
76 operation that FSFS performs on this file is "get and increment";
77 the "txn-current-lock" file is locked during this operation.
79 Filesystem formats
80 ------------------
82 The "format" file defines what features are permitted within the
83 filesystem, and indicates changes that are not backward-compatible.
84 It serves the same purpose as the repository file of the same name.
86 The filesystem format file was introduced in Subversion 1.2, and so
87 will not be present if the repository was created with an older
88 version of Subversion.  An absent format file should be interpreted as
89 indicating a format 1 filesystem.
91 The format file is a single line of the form "<format number>\n",
92 followed by any number of lines specifying 'format options' -
93 additional information about the filesystem's format.  Each format
94 option line is of the form "<option>\n" or "<option> <parameters>\n".
96 Clients should raise an error if they encounter an option not
97 permitted by the format number in use.
99 The format numbers have the following meanings:
101 Format 1: (understood by Subversion 1.1+)
102   Delta representations in revision files must contain only svndiff0
103   data.  No format options are permitted.  No SQLite index is
104   present.  No mechanism is provided to prevent transaction name
105   reuse.
107 Format 2: (understood by Subversion 1.4+)
108   Delta representations in revision files may contain either svndiff0
109   or svndiff1 data.  No format options are permitted.  No SQLite
110   index is present.  No mechanism is provided to prevent transaction
111   name reuse.
113 Format 3: (understood by Subversion 1.5+)
114   Delta representations in revision files may contain either svndiff0
115   or svndiff1 data.  The 'layout' format option is permitted.  The SQLite
116   index is present, and should be updated whenever the svn:mergeinfo property
117   is set on a node.  To prevent transaction name reuse, transaction names
118   should be generated using the transaction sequence number stored in the
119   transaction-current file.
121 Filesystem format options
122 -------------------------
124 Currently, the only recognised format option is "layout", which
125 specifies the paths that will be used to store the revision files and
126 revision property files.
128 The "layout" option is followed by the name of the filesystem layout
129 and any required parameters.  The default layout, if no "layout"
130 keyword is specified, is the 'linear' layout.
132 The known layouts, and the parameters they require, are as follows:
134 "linear"
135   Revision files and rev-prop files are named after the revision they
136   represent, and are placed directly in the revs/ and revprops/
137   directories.  r1234 will be represented by the revision file
138   revs/1234 and the rev-prop file revprops/1234.
140 "sharded <max-files-per-directory>"
141   Revision files and rev-prop files are named after the revision they
142   represent, and are placed in a subdirectory of the revs/ and
143   revprops/ directories named according to the 'shard' they belong to.
145   Shards are numbered from zero and contain between one and the
146   maximum number of files per directory specified in the layout's
147   parameters.
149   For the "sharded 1000" layout, r1234 will be represented by the
150   revision file revs/1/1234 and rev-prop file revprops/1/1234.  The
151   revs/0/ directory will contain revisions 0-999, revs/1/ will contain
152   1000-1999, and so on.
154 Node-revision IDs
155 -----------------
157 In order to support efficient lookup of node-revisions by their IDs
158 and to simplify the allocation of fresh node-IDs during a transaction,
159 we treat the fields of a node-ID in new and interesting ways.
161 Within a revision file, node-revs have a txn-id field of the form
162 "r<rev>/<offset>", to support easy lookup.  The node-id and copy-id
163 fields are unique base36 values as in the BDB implementation.
165 New node-revision IDs assigned within a transaction have the txn-id
166 field of "t<txnid>".  The node-id or copy-id field may be base36
167 values if the node-revision is derived from a pre-existing node and/or
168 copy; if the node-revision must have a freshly-assigned node-id or
169 copy-id, it uses "_" followed by a base36 unique to the transaction.
170 During the final phase of a commit, node-revision IDs are rewritten to
171 have unique node-ID and copy-ID fields and to have "r<rev>/<offset>"
172 txn-id fields.
174 The temporary assignment of node-ID and copy-ID fields has
175 implications for svn_fs_compare_ids and svn_fs_check_related.  The IDs
176 _1.0.t1 is not related to the ID _1.0.t2 even though they have the
177 same node-ID, because temporary node-IDs are restricted in scope to
178 the transactions they belong to.
180 Copy-IDs and copy roots
181 -----------------------
183 Copy-IDs are assigned in the same manner as they are in the BDB
184 implementation:
186   * A node-rev resulting from a creation operation (with no copy
187     history) receives the copy-ID of its parent directory.
189   * A node-rev resulting from a copy operation receives a fresh
190     copy-ID, as one would expect.
192   * A node-rev resulting from a modification operation receives a
193     copy-ID depending on whether its predecessor derives from a
194     copy operation or whether it derives from a creation operation
195     with no intervening copies:
197       - If the predecessor does not derive from a copy, the new
198         node-rev receives the copy-ID of its parent directory.  If the
199         node-rev is being modified through its created-path, this will
200         be the same copy-ID as the predecessor node-rev has; however,
201         if the node-rev is being modified through a copied ancestor
202         directory (i.e. we are performing a "lazy copy"), this will be
203         a different copy-ID.
205       - If the predecessor derives from a copy and the node-rev is
206         being modified through its created-path, the new node-rev
207         receives the copy-ID of the predecessor.
209       - If the predecessor derives from a copy and the node-rev is not
210         being modified through its created path, the new node-rev
211         receives a fresh copy-ID.  This is called a "soft copy"
212         operation, as distinct from a "true copy" operation which was
213         actually requested through the svn_fs interface.  Soft copies
214         exist to ensure that the same <node-ID,copy-ID> pair is not
215         used twice within a transaction.
217 Unlike the BDB implementation, we do not have a "copies" table.
218 Instead, each node-revision record contains a "copyroot" field
219 identifying the node-rev resulting from the true copy operation most
220 proximal to the node-rev.  If the node-rev does not itself derive from
221 a copy operation, then the copyroot field identifies the copy of an
222 ancestor directory; if no ancestor directories derive from a copy
223 operation, then the copyroot field identifies the root directory of
224 rev 0.
226 Revision file format
227 --------------------
229 A revision file contains a concatenation of various kinds of data:
231   * Text and property representations
232   * Node-revisions
233   * The changed-path data
234   * Two offsets at the very end
236 A representation begins with a line containing either "PLAIN\n" or
237 "DELTA\n" or "DELTA <rev> <offset> <length>\n", where <rev>, <offset>,
238 and <length> give the location of the delta base of the representation
239 and the amount of data it contains (not counting the header or
240 trailer).  If no base location is given for a delta, the base is the
241 empty stream.  After the initial line comes raw svndiff data, followed
242 by a cosmetic trailer "ENDREP\n".
244 If the a representation is for the text contents of a directory node,
245 the expanded contents are in hash dump format mapping entry names to
246 "<type> <id>" pairs, where <type> is "file" or "dir" and <id> gives
247 the ID of the child node-rev.
249 If a representation is for a property list, the expanded contents are
250 in the form of a dumped hash map mapping property names to property
251 values.
253 The marshalling syntax for node-revs is a series of fields terminated
254 by a blank line.  Fields have the syntax "<name>: <value>\n", where
255 <name> is a symbolic field name (each symbolic name is used only once
256 in a given node-rev) and <value> is the value data.  Unrecognized
257 fields are ignored, for extensibility.  The following fields are
258 defined:
260   id        The ID of the node-rev
261   type      "file" or "dir"
262   pred      The ID of the predecessor node-rev
263   count     Count of node-revs since the base of the node
264   text      "<rev> <offset> <length> <size> <digest>" for text rep
265   props     "<rev> <offset> <length> <size> <digest>" for props rep
266             <rev> and <offset> give location of rep
267             <length> gives length of rep, sans header and trailer
268             <size> gives size of expanded rep
269             <digest> gives hex MD5 digest of expanded rep
270   cpath     FS pathname node was created at
271   copyfrom  "<rev> <path>" of copyfrom data
272   copyroot  "<rev> <created-path>" of the root of this copy
274 The predecessor of a node-rev crosses both soft and true copies;
275 together with the count field, it allows efficient determination of
276 the base for skip-deltas.  The first node-rev of a node contains no
277 "pred" field.  A node-revision with no properties may omit the "props"
278 field.  A node-revision with no contents (a zero-length file or an
279 empty directory) may omit the "text" field.  In a node-revision
280 resulting from a true copy operation, the "copyfrom" field gives the
281 copyfrom data.  The "copyroot" field identifies the root node-revision
282 of the copy; it may be omitted if the node-rev is its own copy root
283 (as is the case for node-revs with copy history, and for the root node
284 of revision 0).  Copy roots are identified by revision and
285 created-path, not by node-rev ID, because a copy root may be a
286 node-rev which exists later on within the same revision file, meaning
287 its offset is not yet known.
289 The changed-path data is represented as a series of changed-path
290 items, each consisting of two lines.  The first line has the format
291 "<id> <action> <text-mod> <prop-mod> <path>\n", where <id> is the
292 node-rev ID of the new node-rev, <action> is "add", "delete",
293 "replace", or "modify", <text-mod> and <prop-mod> are "true" or
294 "false" indicating whether the text and/or properties changed, and
295 <path> is the changed pathname.  For deletes, <id> is the node-rev ID
296 of the deleted node-rev, and <text-mod> and <prop-mod> are always
297 "false".  The second line has the format "<rev> <path>\n" containing
298 the node-rev's copyfrom information if it has any; if it does not, the
299 second line is blank.
301 At the very end of a rev file is a pair of lines containing
302 "\n<root-offset> <cp-offset>\n", where <root-offset> is the offset of
303 the root directory node revision and <cp-offset> is the offset of the
304 changed-path data.
306 All numbers in the rev file format are unsigned and are represented as
307 ASCII decimal.
309 Transaction layout
310 ------------------
312 A transaction directory has the following layout:
314   rev                        Prototype rev file with new text reps
315   rev-lock                   Lockfile for writing to the above
316   props                      Transaction props
317   mergeinfo                  Transaction mergeinfo props, if any
318   next-ids                   Next temporary node-ID and copy-ID
319   changes                    Changed-path information so far
320   node.<nid>.<cid>           New node-rev data for node
321   node.<nid>.<cid>.props     Props for new node-rev, if changed
322   node.<nid>.<cid>.children  Directory contents for node-rev
324 The prototype rev file is used to store the text representations as
325 they are received from the client.  To ensure that only one client is
326 writing to the file at a given time, the "rev-lock" file is locked for
327 the duration of each write.
329 The three kinds of props files are all in hash dump format.  The
330 "props" file will always be present.  The "mergeinfo" file may be
331 absent if no svn:mergeinfo properties have been changed on any node in
332 the transaction.  The "node.<nid>.<cid>.props" file will only be
333 present if the node-rev properties have been changed.
335 The "next-ids" file contains a single line "<next-temp-node-id>
336 <next-temp-copy-id>\n" giving the next temporary node-ID and copy-ID
337 assignments (without the leading underscores).
339 The "children" file for a node-revision begins with a copy of the hash
340 dump representation of the directory entries from the old node-rev (or
341 a dump of the empty hash for new directories), and then an incremental
342 hash dump entry for each change made to the directory.
344 The "changes" file contains changed-path entries in the same form as
345 the changed-path entries in a rev file, except that <id> and <action>
346 may both be "reset" (in which case <text-mod> and <prop-mod> are both
347 always "false") to indicate that all changes to a path should be
348 considered undone.  Reset entries are only used during the final merge
349 phase of a transaction.
351 The node-rev files have the same format as node-revs in a revision
352 file, except that the "text" and "props" fields are augmented as
353 follows:
355   * The "props" field may have the value "-1" if properties have
356     been changed and are contained in a "props" file within the
357     node-rev subdirectory.
359   * For directory node-revs, the "text" field may have the value
360     "-1" if entries have been changed and are contained in a
361     "contents" file in the node-rev subdirectory.
363   * For the directory node-rev representing the root of the
364     transaction, the "is-fresh-txn-root" field indicates that it has
365     not been made mutable yet (see Issue #2608).
367   * For file node-revs, the "text" field may have the value "-1
368     <offset> <length> <size> <digest>" if the text representation is
369     within the prototype rev file.
371   * The "copyroot" field may have the value "-1 <created-path>" if the
372     copy root of the node-rev is part of the transaction in process.
374 Locks layout
375 ------------
377 Locks in FSFS are stored in serialized hash format in files whose
378 names are MD5 digests of the FS path which the lock is associated
379 with.  For the purposes of keeping directory inode usage down, these
380 digest files live in subdirectories of the main lock directory whose
381 names are the first 3 characters of the digest filename.
383 Also stored in the digest file for a given FS path are pointers to
384 other digest files which contain information associated with other FS
385 paths that are our path's immediate children.
387 To answer the question, "Does path FOO have a lock associated with
388 it?", one need only generate the MD5 digest of FOO's
389 absolute-in-the-FS path (say, 3b1b011fed614a263986b5c4869604e8), look
390 for a file located like so:
392    /path/to/repos/locks/3b1/3b1b011fed614a263986b5c4869604e8
394 And then see if that file contains lock information.
396 To inquire about locks on children of the path FOO, you would
397 reference the same path as above, but look for a list of children in
398 that file (instead of lock information).  Children are listed as MD5
399 digests, too, so you would simply iterate over those digests and
400 consult the files they reference, and so on, recursively.