fs.h revision 269847
1/* fs.h : interface to Subversion filesystem, private to libsvn_fs
2 *
3 * ====================================================================
4 *    Licensed to the Apache Software Foundation (ASF) under one
5 *    or more contributor license agreements.  See the NOTICE file
6 *    distributed with this work for additional information
7 *    regarding copyright ownership.  The ASF licenses this file
8 *    to you under the Apache License, Version 2.0 (the
9 *    "License"); you may not use this file except in compliance
10 *    with the License.  You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 *    Unless required by applicable law or agreed to in writing,
15 *    software distributed under the License is distributed on an
16 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 *    KIND, either express or implied.  See the License for the
18 *    specific language governing permissions and limitations
19 *    under the License.
20 * ====================================================================
21 */
22
23#ifndef SVN_LIBSVN_FS_FS_H
24#define SVN_LIBSVN_FS_FS_H
25
26#include <apr_pools.h>
27#include <apr_hash.h>
28#include <apr_network_io.h>
29
30#include "svn_fs.h"
31#include "svn_config.h"
32#include "private/svn_atomic.h"
33#include "private/svn_cache.h"
34#include "private/svn_fs_private.h"
35#include "private/svn_sqlite.h"
36#include "private/svn_mutex.h"
37#include "private/svn_named_atomic.h"
38
39#ifdef __cplusplus
40extern "C" {
41#endif /* __cplusplus */
42
43
44/*** The filesystem structure.  ***/
45
46/* Following are defines that specify the textual elements of the
47   native filesystem directories and revision files. */
48
49/* Names of special files in the fs_fs filesystem. */
50#define PATH_FORMAT           "format"           /* Contains format number */
51#define PATH_UUID             "uuid"             /* Contains UUID */
52#define PATH_CURRENT          "current"          /* Youngest revision */
53#define PATH_LOCK_FILE        "write-lock"       /* Revision lock file */
54#define PATH_REVS_DIR         "revs"             /* Directory of revisions */
55#define PATH_REVPROPS_DIR     "revprops"         /* Directory of revprops */
56#define PATH_TXNS_DIR         "transactions"     /* Directory of transactions */
57#define PATH_NODE_ORIGINS_DIR "node-origins"     /* Lazy node-origin cache */
58#define PATH_TXN_PROTOS_DIR   "txn-protorevs"    /* Directory of proto-revs */
59#define PATH_TXN_CURRENT      "txn-current"      /* File with next txn key */
60#define PATH_TXN_CURRENT_LOCK "txn-current-lock" /* Lock for txn-current */
61#define PATH_LOCKS_DIR        "locks"            /* Directory of locks */
62#define PATH_MIN_UNPACKED_REV "min-unpacked-rev" /* Oldest revision which
63                                                    has not been packed. */
64#define PATH_REVPROP_GENERATION "revprop-generation"
65                                                 /* Current revprop generation*/
66#define PATH_MANIFEST         "manifest"         /* Manifest file name */
67#define PATH_PACKED           "pack"             /* Packed revision data file */
68#define PATH_EXT_PACKED_SHARD ".pack"            /* Extension for packed
69                                                    shards */
70/* If you change this, look at tests/svn_test_fs.c(maybe_install_fsfs_conf) */
71#define PATH_CONFIG           "fsfs.conf"        /* Configuration */
72
73/* Names of special files and file extensions for transactions */
74#define PATH_CHANGES       "changes"       /* Records changes made so far */
75#define PATH_TXN_PROPS     "props"         /* Transaction properties */
76#define PATH_NEXT_IDS      "next-ids"      /* Next temporary ID assignments */
77#define PATH_PREFIX_NODE   "node."         /* Prefix for node filename */
78#define PATH_EXT_TXN       ".txn"          /* Extension of txn dir */
79#define PATH_EXT_CHILDREN  ".children"     /* Extension for dir contents */
80#define PATH_EXT_PROPS     ".props"        /* Extension for node props */
81#define PATH_EXT_REV       ".rev"          /* Extension of protorev file */
82#define PATH_EXT_REV_LOCK  ".rev-lock"     /* Extension of protorev lock file */
83/* Names of files in legacy FS formats */
84#define PATH_REV           "rev"           /* Proto rev file */
85#define PATH_REV_LOCK      "rev-lock"      /* Proto rev (write) lock file */
86
87/* Names of sections and options in fsfs.conf. */
88#define CONFIG_SECTION_CACHES            "caches"
89#define CONFIG_OPTION_FAIL_STOP          "fail-stop"
90#define CONFIG_SECTION_REP_SHARING       "rep-sharing"
91#define CONFIG_OPTION_ENABLE_REP_SHARING "enable-rep-sharing"
92#define CONFIG_SECTION_DELTIFICATION     "deltification"
93#define CONFIG_OPTION_ENABLE_DIR_DELTIFICATION   "enable-dir-deltification"
94#define CONFIG_OPTION_ENABLE_PROPS_DELTIFICATION "enable-props-deltification"
95#define CONFIG_OPTION_MAX_DELTIFICATION_WALK     "max-deltification-walk"
96#define CONFIG_OPTION_MAX_LINEAR_DELTIFICATION   "max-linear-deltification"
97#define CONFIG_SECTION_PACKED_REVPROPS   "packed-revprops"
98#define CONFIG_OPTION_REVPROP_PACK_SIZE  "revprop-pack-size"
99#define CONFIG_OPTION_COMPRESS_PACKED_REVPROPS  "compress-packed-revprops"
100
101/* The format number of this filesystem.
102   This is independent of the repository format number, and
103   independent of any other FS back ends. */
104#define SVN_FS_FS__FORMAT_NUMBER   6
105
106/* The minimum format number that supports svndiff version 1.  */
107#define SVN_FS_FS__MIN_SVNDIFF1_FORMAT 2
108
109/* The minimum format number that supports transaction ID generation
110   using a transaction sequence in the txn-current file. */
111#define SVN_FS_FS__MIN_TXN_CURRENT_FORMAT 3
112
113/* The minimum format number that supports the "layout" filesystem
114   format option. */
115#define SVN_FS_FS__MIN_LAYOUT_FORMAT_OPTION_FORMAT 3
116
117/* The minimum format number that stores protorevs in a separate directory. */
118#define SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT 3
119
120/* The minimum format number that doesn't keep node and copy ID counters. */
121#define SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT 3
122
123/* The minimum format number that maintains minfo-here and minfo-count
124   noderev fields. */
125#define SVN_FS_FS__MIN_MERGEINFO_FORMAT 3
126
127/* The minimum format number that allows rep sharing. */
128#define SVN_FS_FS__MIN_REP_SHARING_FORMAT 4
129
130/* The minimum format number that supports packed shards. */
131#define SVN_FS_FS__MIN_PACKED_FORMAT 4
132
133/* The minimum format number that stores node kinds in changed-paths lists. */
134#define SVN_FS_FS__MIN_KIND_IN_CHANGED_FORMAT 4
135
136/* 1.8 deltification options should work with any FSFS repo but to avoid
137 * issues with very old servers, restrict those options to the 1.6+ format*/
138#define SVN_FS_FS__MIN_DELTIFICATION_FORMAT 4
139
140/* The 1.7-dev format, never released, that packed revprops into SQLite
141   revprops.db . */
142#define SVN_FS_FS__PACKED_REVPROP_SQLITE_DEV_FORMAT 5
143
144/* The minimum format number that supports packed revprops. */
145#define SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT 6
146
147/* The minimum format number that supports a configuration file (fsfs.conf) */
148#define SVN_FS_FS__MIN_CONFIG_FILE 4
149
150/* Private FSFS-specific data shared between all svn_txn_t objects that
151   relate to a particular transaction in a filesystem (as identified
152   by transaction id and filesystem UUID).  Objects of this type are
153   allocated in their own subpool of the common pool. */
154typedef struct fs_fs_shared_txn_data_t
155{
156  /* The next transaction in the list, or NULL if there is no following
157     transaction. */
158  struct fs_fs_shared_txn_data_t *next;
159
160  /* This transaction's ID.  For repositories whose format is less
161     than SVN_FS_FS__MIN_TXN_CURRENT_FORMAT, the ID is in the form
162     <rev>-<uniqueifier>, where <uniqueifier> runs from 0-99999 (see
163     create_txn_dir_pre_1_5() in fs_fs.c).  For newer repositories,
164     the form is <rev>-<200 digit base 36 number> (see
165     create_txn_dir() in fs_fs.c). */
166  char txn_id[SVN_FS__TXN_MAX_LEN+1];
167
168  /* Whether the transaction's prototype revision file is locked for
169     writing by any thread in this process (including the current
170     thread; recursive locks are not permitted).  This is effectively
171     a non-recursive mutex. */
172  svn_boolean_t being_written;
173
174  /* The pool in which this object has been allocated; a subpool of the
175     common pool. */
176  apr_pool_t *pool;
177} fs_fs_shared_txn_data_t;
178
179/* On most operating systems apr implements file locks per process, not
180   per file.  On Windows apr implements the locking as per file handle
181   locks, so we don't have to add our own mutex for just in-process
182   synchronization. */
183/* Compare ../libsvn_subr/named_atomic.c:USE_THREAD_MUTEX */
184#if APR_HAS_THREADS && !defined(WIN32)
185#define SVN_FS_FS__USE_LOCK_MUTEX 1
186#else
187#define SVN_FS_FS__USE_LOCK_MUTEX 0
188#endif
189
190/* Private FSFS-specific data shared between all svn_fs_t objects that
191   relate to a particular filesystem, as identified by filesystem UUID.
192   Objects of this type are allocated in the common pool. */
193typedef struct fs_fs_shared_data_t
194{
195  /* A list of shared transaction objects for each transaction that is
196     currently active, or NULL if none are.  All access to this list,
197     including the contents of the objects stored in it, is synchronised
198     under TXN_LIST_LOCK. */
199  fs_fs_shared_txn_data_t *txns;
200
201  /* A free transaction object, or NULL if there is no free object.
202     Access to this object is synchronised under TXN_LIST_LOCK. */
203  fs_fs_shared_txn_data_t *free_txn;
204
205  /* A lock for intra-process synchronization when accessing the TXNS list. */
206  svn_mutex__t *txn_list_lock;
207
208  /* A lock for intra-process synchronization when grabbing the
209     repository write lock. */
210  svn_mutex__t *fs_write_lock;
211
212  /* A lock for intra-process synchronization when locking the
213     txn-current file. */
214  svn_mutex__t *txn_current_lock;
215
216  /* The common pool, under which this object is allocated, subpools
217     of which are used to allocate the transaction objects. */
218  apr_pool_t *common_pool;
219} fs_fs_shared_data_t;
220
221/* Data structure for the 1st level DAG node cache. */
222typedef struct fs_fs_dag_cache_t fs_fs_dag_cache_t;
223
224/* Key type for all caches that use revision + offset / counter as key. */
225typedef struct pair_cache_key_t
226{
227  svn_revnum_t revision;
228
229  apr_int64_t second;
230} pair_cache_key_t;
231
232/* Private (non-shared) FSFS-specific data for each svn_fs_t object.
233   Any caches in here may be NULL. */
234typedef struct fs_fs_data_t
235{
236  /* The format number of this FS. */
237  int format;
238  /* The maximum number of files to store per directory (for sharded
239     layouts) or zero (for linear layouts). */
240  int max_files_per_dir;
241
242  /* The revision that was youngest, last time we checked. */
243  svn_revnum_t youngest_rev_cache;
244
245  /* The fsfs.conf file, parsed.  Allocated in FS->pool. */
246  svn_config_t *config;
247
248  /* Caches of immutable data.  (Note that if these are created with
249     svn_cache__create_memcache, the data can be shared between
250     multiple svn_fs_t's for the same filesystem.) */
251
252  /* A cache of revision root IDs, mapping from (svn_revnum_t *) to
253     (svn_fs_id_t *).  (Not threadsafe.) */
254  svn_cache__t *rev_root_id_cache;
255
256  /* Caches native dag_node_t* instances and acts as a 1st level cache */
257  fs_fs_dag_cache_t *dag_node_cache;
258
259  /* DAG node cache for immutable nodes.  Maps (revision, fspath)
260     to (dag_node_t *). This is the 2nd level cache for DAG nodes. */
261  svn_cache__t *rev_node_cache;
262
263  /* A cache of the contents of immutable directories; maps from
264     unparsed FS ID to a apr_hash_t * mapping (const char *) dirent
265     names to (svn_fs_dirent_t *). */
266  svn_cache__t *dir_cache;
267
268  /* Fulltext cache; currently only used with memcached.  Maps from
269     rep key (revision/offset) to svn_stringbuf_t. */
270  svn_cache__t *fulltext_cache;
271
272  /* Access object to the atomics namespace used by revprop caching.
273     Will be NULL until the first access. */
274  svn_atomic_namespace__t *revprop_namespace;
275
276  /* Access object to the revprop "generation". Will be NULL until
277     the first access. */
278  svn_named_atomic__t *revprop_generation;
279
280  /* Access object to the revprop update timeout. Will be NULL until
281     the first access. */
282  svn_named_atomic__t *revprop_timeout;
283
284  /* Revision property cache.  Maps from (rev,generation) to apr_hash_t. */
285  svn_cache__t *revprop_cache;
286
287  /* Node properties cache.  Maps from rep key to apr_hash_t. */
288  svn_cache__t *properties_cache;
289
290  /* Pack manifest cache; a cache mapping (svn_revnum_t) shard number to
291     a manifest; and a manifest is a mapping from (svn_revnum_t) revision
292     number offset within a shard to (apr_off_t) byte-offset in the
293     respective pack file. */
294  svn_cache__t *packed_offset_cache;
295
296  /* Cache for txdelta_window_t objects; the key is (revFilePath, offset) */
297  svn_cache__t *txdelta_window_cache;
298
299  /* Cache for combined windows as svn_stringbuf_t objects;
300     the key is (revFilePath, offset) */
301  svn_cache__t *combined_window_cache;
302
303  /* Cache for node_revision_t objects; the key is (revision, id offset) */
304  svn_cache__t *node_revision_cache;
305
306  /* Cache for change lists as APR arrays of change_t * objects; the key
307     is the revision */
308  svn_cache__t *changes_cache;
309
310  /* Cache for svn_mergeinfo_t objects; the key is a combination of
311     revision, inheritance flags and path. */
312  svn_cache__t *mergeinfo_cache;
313
314  /* Cache for presence of svn_mergeinfo_t on a noderev; the key is a
315     combination of revision, inheritance flags and path; value is "1"
316     if the node has mergeinfo, "0" if it doesn't. */
317  svn_cache__t *mergeinfo_existence_cache;
318
319  /* TRUE while the we hold a lock on the write lock file. */
320  svn_boolean_t has_write_lock;
321
322  /* If set, there are or have been more than one concurrent transaction */
323  svn_boolean_t concurrent_transactions;
324
325  /* Temporary cache for changed directories yet to be committed; maps from
326     unparsed FS ID to ###x.  NULL outside transactions. */
327  svn_cache__t *txn_dir_cache;
328
329  /* Data shared between all svn_fs_t objects for a given filesystem. */
330  fs_fs_shared_data_t *shared;
331
332  /* The sqlite database used for rep caching. */
333  svn_sqlite__db_t *rep_cache_db;
334
335  /* Thread-safe boolean */
336  svn_atomic_t rep_cache_db_opened;
337
338  /* The oldest revision not in a pack file.  It also applies to revprops
339   * if revprop packing has been enabled by the FSFS format version. */
340  svn_revnum_t min_unpacked_rev;
341
342  /* Whether rep-sharing is supported by the filesystem
343   * and allowed by the configuration. */
344  svn_boolean_t rep_sharing_allowed;
345
346  /* File size limit in bytes up to which multiple revprops shall be packed
347   * into a single file. */
348  apr_int64_t revprop_pack_size;
349
350  /* Whether packed revprop files shall be compressed. */
351  svn_boolean_t compress_packed_revprops;
352
353  /* Whether directory nodes shall be deltified just like file nodes. */
354  svn_boolean_t deltify_directories;
355
356  /* Whether nodes properties shall be deltified. */
357  svn_boolean_t deltify_properties;
358
359  /* Restart deltification histories after each multiple of this value */
360  apr_int64_t max_deltification_walk;
361
362  /* Maximum number of length of the linear part at the top of the
363   * deltification history after which skip deltas will be used. */
364  apr_int64_t max_linear_deltification;
365
366  /* Pointer to svn_fs_open. */
367  svn_error_t *(*svn_fs_open_)(svn_fs_t **, const char *, apr_hash_t *,
368                               apr_pool_t *);
369} fs_fs_data_t;
370
371
372/*** Filesystem Transaction ***/
373typedef struct transaction_t
374{
375  /* property list (const char * name, svn_string_t * value).
376     may be NULL if there are no properties.  */
377  apr_hash_t *proplist;
378
379  /* node revision id of the root node.  */
380  const svn_fs_id_t *root_id;
381
382  /* node revision id of the node which is the root of the revision
383     upon which this txn is base.  (unfinished only) */
384  const svn_fs_id_t *base_id;
385
386  /* copies list (const char * copy_ids), or NULL if there have been
387     no copies in this transaction.  */
388  apr_array_header_t *copies;
389
390} transaction_t;
391
392
393/*** Representation ***/
394/* If you add fields to this, check to see if you need to change
395 * svn_fs_fs__rep_copy. */
396typedef struct representation_t
397{
398  /* Checksums for the contents produced by this representation.
399     This checksum is for the contents the rep shows to consumers,
400     regardless of how the rep stores the data under the hood.  It is
401     independent of the storage (fulltext, delta, whatever).
402
403     If checksum is NULL, then for compatibility behave as though this
404     checksum matches the expected checksum.
405
406     The md5 checksum is always filled, unless this is rep which was
407     retrieved from the rep-cache.  The sha1 checksum is only computed on
408     a write, for use with rep-sharing; it may be read from an existing
409     representation, but otherwise it is NULL. */
410  svn_checksum_t *md5_checksum;
411  svn_checksum_t *sha1_checksum;
412
413  /* Revision where this representation is located. */
414  svn_revnum_t revision;
415
416  /* Offset into the revision file where it is located. */
417  apr_off_t offset;
418
419  /* The size of the representation in bytes as seen in the revision
420     file. */
421  svn_filesize_t size;
422
423  /* The size of the fulltext of the representation. If this is 0,
424   * the fulltext size is equal to representation size in the rev file, */
425  svn_filesize_t expanded_size;
426
427  /* Is this representation a transaction? */
428  const char *txn_id;
429
430  /* For rep-sharing, we need a way of uniquifying node-revs which share the
431     same representation (see svn_fs_fs__noderev_same_rep_key() ).  So, we
432     store the original txn of the node rev (not the rep!), along with some
433     intra-node uniqification content.
434
435     May be NULL, in which case, it is considered to match other NULL
436     values.*/
437  const char *uniquifier;
438} representation_t;
439
440
441/*** Node-Revision ***/
442/* If you add fields to this, check to see if you need to change
443 * copy_node_revision in dag.c. */
444typedef struct node_revision_t
445{
446  /* node kind */
447  svn_node_kind_t kind;
448
449  /* The node-id for this node-rev. */
450  const svn_fs_id_t *id;
451
452  /* predecessor node revision id, or NULL if there is no predecessor
453     for this node revision */
454  const svn_fs_id_t *predecessor_id;
455
456  /* If this node-rev is a copy, where was it copied from? */
457  const char *copyfrom_path;
458  svn_revnum_t copyfrom_rev;
459
460  /* Helper for history tracing, root of the parent tree from whence
461     this node-rev was copied. */
462  svn_revnum_t copyroot_rev;
463  const char *copyroot_path;
464
465  /* number of predecessors this node revision has (recursively), or
466     -1 if not known (for backward compatibility). */
467  int predecessor_count;
468
469  /* representation key for this node's properties.  may be NULL if
470     there are no properties.  */
471  representation_t *prop_rep;
472
473  /* representation for this node's data.  may be NULL if there is
474     no data. */
475  representation_t *data_rep;
476
477  /* path at which this node first came into existence.  */
478  const char *created_path;
479
480  /* is this the unmodified root of a transaction? */
481  svn_boolean_t is_fresh_txn_root;
482
483  /* Number of nodes with svn:mergeinfo properties that are
484     descendants of this node (including it itself) */
485  apr_int64_t mergeinfo_count;
486
487  /* Does this node itself have svn:mergeinfo? */
488  svn_boolean_t has_mergeinfo;
489
490} node_revision_t;
491
492
493/*** Change ***/
494typedef struct change_t
495{
496  /* Path of the change. */
497  const char *path;
498
499  /* Node revision ID of the change. */
500  const svn_fs_id_t *noderev_id;
501
502  /* The kind of change. */
503  svn_fs_path_change_kind_t kind;
504
505  /* Text or property mods? */
506  svn_boolean_t text_mod;
507  svn_boolean_t prop_mod;
508
509  /* Node kind (possibly svn_node_unknown). */
510  svn_node_kind_t node_kind;
511
512  /* Copyfrom revision and path. */
513  svn_revnum_t copyfrom_rev;
514  const char * copyfrom_path;
515
516} change_t;
517
518
519#ifdef __cplusplus
520}
521#endif /* __cplusplus */
522
523#endif /* SVN_LIBSVN_FS_FS_H */
524