1 /* dag.h : DAG-like interface filesystem, private to libsvn_fs
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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
20 * ====================================================================
23 #ifndef SVN_LIBSVN_FS_DAG_H
24 #define SVN_LIBSVN_FS_DAG_H
27 #include "svn_delta.h"
28 #include "private/svn_cache.h"
34 #endif /* __cplusplus */
37 /* The interface in this file provides all the essential filesystem
38 operations, but exposes the filesystem's DAG structure. This makes
39 it simpler to implement than the public interface, since a client
40 of this interface has to understand and cope with shared structure
41 directly as it appears in the database. However, it's still a
42 self-consistent set of invariants to maintain, making it
43 (hopefully) a useful interface boundary.
47 - The dag_node_t interface exposes the internal DAG structure of
48 the filesystem, while the svn_fs.h interface does any cloning
49 necessary to make the filesystem look like a tree.
51 - The dag_node_t interface exposes the existence of copy nodes,
52 whereas the svn_fs.h handles them transparently.
54 - dag_node_t's must be explicitly cloned, whereas the svn_fs.h
55 operations make clones implicitly.
57 - Callers of the dag_node_t interface use Berkeley DB transactions
58 to ensure consistency between operations, while callers of the
59 svn_fs.h interface use Subversion transactions. */
62 /* Generic DAG node stuff. */
64 typedef struct dag_node_t dag_node_t;
66 /* Fill *NODE with a dag_node_t representing node revision ID in FS,
67 allocating in POOL. */
69 svn_fs_fs__dag_get_node(dag_node_t **node,
71 const svn_fs_id_t *id,
75 /* Return a new dag_node_t object referring to the same node as NODE,
76 allocated in POOL. If you're trying to build a structure in a
77 pool that wants to refer to dag nodes that may have been allocated
78 elsewhere, you can call this function and avoid inter-pool pointers. */
80 svn_fs_fs__dag_dup(const dag_node_t *node,
83 /* Serialize a DAG node, except don't try to preserve the 'fs' member.
84 Implements svn_cache__serialize_func_t */
86 svn_fs_fs__dag_serialize(void **data,
91 /* Deserialize a DAG node, leaving the 'fs' member as NULL.
92 Implements svn_cache__deserialize_func_t */
94 svn_fs_fs__dag_deserialize(void **out,
99 /* Return the filesystem containing NODE. */
100 svn_fs_t *svn_fs_fs__dag_get_fs(dag_node_t *node);
102 /* Changes the filesystem containing NODE to FS. (Used when pulling
103 nodes out of a shared cache, say.) */
104 void svn_fs_fs__dag_set_fs(dag_node_t *node, svn_fs_t *fs);
107 /* Set *REV to NODE's revision number, allocating in POOL. If NODE
108 has never been committed as part of a revision, set *REV to
109 SVN_INVALID_REVNUM. */
110 svn_error_t *svn_fs_fs__dag_get_revision(svn_revnum_t *rev,
115 /* Return the node revision ID of NODE. The value returned is shared
116 with NODE, and will be deallocated when NODE is. */
117 const svn_fs_id_t *svn_fs_fs__dag_get_id(const dag_node_t *node);
120 /* Return the created path of NODE. The value returned is shared
121 with NODE, and will be deallocated when NODE is. */
122 const char *svn_fs_fs__dag_get_created_path(dag_node_t *node);
125 /* Set *ID_P to the node revision ID of NODE's immediate predecessor,
126 or NULL if NODE has no predecessor.
128 svn_error_t *svn_fs_fs__dag_get_predecessor_id(const svn_fs_id_t **id_p,
132 /* Set *COUNT to the number of predecessors NODE has (recursively), or
135 /* ### This function is currently only used by 'verify'. */
136 svn_error_t *svn_fs_fs__dag_get_predecessor_count(int *count,
139 /* Set *COUNT to the number of node under NODE (inclusive) with
140 svn:mergeinfo properties.
142 svn_error_t *svn_fs_fs__dag_get_mergeinfo_count(apr_int64_t *count,
145 /* Set *DO_THEY to a flag indicating whether or not NODE is a
146 directory with at least one descendant (not including itself) with
150 svn_fs_fs__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they,
153 /* Set *HAS_MERGEINFO to a flag indicating whether or not NODE itself
154 has svn:mergeinfo set on it.
157 svn_fs_fs__dag_has_mergeinfo(svn_boolean_t *has_mergeinfo,
160 /* Return non-zero IFF NODE is currently mutable. */
161 svn_boolean_t svn_fs_fs__dag_check_mutable(const dag_node_t *node);
163 /* Return the node kind of NODE. */
164 svn_node_kind_t svn_fs_fs__dag_node_kind(dag_node_t *node);
166 /* Set *PROPLIST_P to a PROPLIST hash representing the entire property
167 list of NODE, allocating from POOL. The hash has const char *
168 names (the property names) and svn_string_t * values (the property
171 If properties do not exist on NODE, *PROPLIST_P will be set to
174 Use POOL for all allocations.
176 svn_error_t *svn_fs_fs__dag_get_proplist(apr_hash_t **proplist_p,
180 /* Set *HAS_PROPS to TRUE if NODE has properties. Use SCRATCH_POOL
181 for temporary allocations */
182 svn_error_t *svn_fs_fs__dag_has_props(svn_boolean_t *has_props,
184 apr_pool_t *scratch_pool);
186 /* Set the property list of NODE to PROPLIST, allocating from POOL.
187 The node being changed must be mutable.
189 Use POOL for all allocations.
191 svn_error_t *svn_fs_fs__dag_set_proplist(dag_node_t *node,
192 apr_hash_t *proplist,
195 /* Increment the mergeinfo_count field on NODE by INCREMENT. The node
196 being changed must be mutable.
198 Use POOL for all allocations.
200 svn_error_t *svn_fs_fs__dag_increment_mergeinfo_count(dag_node_t *node,
201 apr_int64_t increment,
204 /* Set the has-mergeinfo flag on NODE to HAS_MERGEINFO. The node
205 being changed must be mutable.
207 Use POOL for all allocations.
209 svn_error_t *svn_fs_fs__dag_set_has_mergeinfo(dag_node_t *node,
210 svn_boolean_t has_mergeinfo,
215 /* Revision and transaction roots. */
218 /* Open the root of revision REV of filesystem FS, allocating from
219 POOL. Set *NODE_P to the new node. */
220 svn_error_t *svn_fs_fs__dag_revision_root(dag_node_t **node_p,
226 /* Set *NODE_P to the root of transaction TXN_ID in FS, allocating
229 Note that the root node of TXN_ID is not necessarily mutable. If
230 no changes have been made in the transaction, then it may share its
231 root directory with its base revision. To get a mutable root node
232 for a transaction, call svn_fs_fs__dag_clone_root. */
233 svn_error_t *svn_fs_fs__dag_txn_root(dag_node_t **node_p,
235 const svn_fs_fs__id_part_t *txn_id,
239 /* Set *NODE_P to the base root of transaction TXN_ID in FS,
240 allocating from POOL. Allocate the node in TRAIL->pool. */
241 svn_error_t *svn_fs_fs__dag_txn_base_root(dag_node_t **node_p,
243 const svn_fs_fs__id_part_t *txn_id,
247 /* Clone the root directory of TXN_ID in FS, and update the
248 `transactions' table entry to point to it, unless this has been
249 done already. In either case, set *ROOT_P to a reference to the
250 root directory clone. Allocate *ROOT_P in POOL. */
251 svn_error_t *svn_fs_fs__dag_clone_root(dag_node_t **root_p,
253 const svn_fs_fs__id_part_t *txn_id,
261 /* Open the node named NAME in the directory PARENT. Set *CHILD_P to
262 the new node, allocated in RESULT_POOL. NAME must be a single path
263 component; it cannot be a slash-separated directory path. If NAME does
264 not exist within PARENT, set *CHILD_P to NULL.
267 svn_fs_fs__dag_open(dag_node_t **child_p,
270 apr_pool_t *result_pool,
271 apr_pool_t *scratch_pool);
274 /* Set *ENTRIES_P to an array of NODE's entries, sorted by entry names,
275 and the values are svn_fs_dirent_t's. The returned table (and elements)
276 is allocated in POOL, which is also used for temporary allocations. */
277 svn_error_t *svn_fs_fs__dag_dir_entries(apr_array_header_t **entries_p,
281 /* Fetches the NODE's entries and returns a copy of the entry selected
282 by the key value given in NAME and set *DIRENT to a copy of that
283 entry. If such entry was found, the copy will be allocated in
284 RESULT_POOL. Temporary data will be used in SCRATCH_POOL.
285 Otherwise, the *DIRENT will be set to NULL.
287 /* ### This function is currently only called from dag.c. */
288 svn_error_t * svn_fs_fs__dag_dir_entry(svn_fs_dirent_t **dirent,
291 apr_pool_t *result_pool,
292 apr_pool_t *scratch_pool);
294 /* Set ENTRY_NAME in NODE to point to ID (with kind KIND), allocating
295 from POOL. NODE must be a mutable directory. ID can refer to a
296 mutable or immutable node. If ENTRY_NAME does not exist, it will
297 be created. TXN_ID is the Subversion transaction under which this
300 Use POOL for all allocations, including to cache the node_revision in
303 svn_error_t *svn_fs_fs__dag_set_entry(dag_node_t *node,
304 const char *entry_name,
305 const svn_fs_id_t *id,
306 svn_node_kind_t kind,
307 const svn_fs_fs__id_part_t *txn_id,
311 /* Make a new mutable clone of the node named NAME in PARENT, and
312 adjust PARENT's directory entry to point to it, unless NAME in
313 PARENT already refers to a mutable node. In either case, set
314 *CHILD_P to a reference to the new node, allocated in POOL. PARENT
315 must be mutable. NAME must be a single path component; it cannot
316 be a slash-separated directory path. PARENT_PATH must be the
317 canonicalized absolute path of the parent directory.
319 COPY_ID, if non-NULL, is a key into the `copies' table, and
320 indicates that this new node is being created as the result of a
321 copy operation, and specifically which operation that was.
323 PATH is the canonicalized absolute path at which this node is being
326 TXN_ID is the Subversion transaction under which this occurs.
328 Use POOL for all allocations.
330 svn_error_t *svn_fs_fs__dag_clone_child(dag_node_t **child_p,
332 const char *parent_path,
334 const svn_fs_fs__id_part_t *copy_id,
335 const svn_fs_fs__id_part_t *txn_id,
336 svn_boolean_t is_parent_copyroot,
340 /* Delete the directory entry named NAME from PARENT, allocating from
341 POOL. PARENT must be mutable. NAME must be a single path
342 component; it cannot be a slash-separated directory path. If the
343 node being deleted is a mutable directory, remove all mutable nodes
344 reachable from it. TXN_ID is the Subversion transaction under
347 If return SVN_ERR_FS_NO_SUCH_ENTRY, then there is no entry NAME in
350 Use POOL for all allocations.
352 svn_error_t *svn_fs_fs__dag_delete(dag_node_t *parent,
354 const svn_fs_fs__id_part_t *txn_id,
358 /* Delete the node revision assigned to node ID from FS's `nodes'
359 table, allocating from POOL. Also delete any mutable
360 representations and strings associated with that node revision. ID
361 may refer to a file or directory, which must be mutable.
363 NOTE: If ID represents a directory, and that directory has mutable
364 children, you risk orphaning those children by leaving them
365 dangling, disconnected from all DAG trees. It is assumed that
366 callers of this interface know what in the world they are doing. */
367 svn_error_t *svn_fs_fs__dag_remove_node(svn_fs_t *fs,
368 const svn_fs_id_t *id,
372 /* Delete all mutable node revisions reachable from node ID, including
373 ID itself, from FS's `nodes' table, allocating from POOL. Also
374 delete any mutable representations and strings associated with that
375 node revision. ID may refer to a file or directory, which may be
376 mutable or immutable. */
377 svn_error_t *svn_fs_fs__dag_delete_if_mutable(svn_fs_t *fs,
378 const svn_fs_id_t *id,
382 /* Create a new mutable directory named NAME in PARENT. Set *CHILD_P
383 to a reference to the new node, allocated in POOL. The new
384 directory has no contents, and no properties. PARENT must be
385 mutable. NAME must be a single path component; it cannot be a
386 slash-separated directory path. PARENT_PATH must be the
387 canonicalized absolute path of the parent directory. PARENT must
388 not currently have an entry named NAME. TXN_ID is the Subversion
389 transaction under which this occurs.
391 Use POOL for all allocations.
393 svn_error_t *svn_fs_fs__dag_make_dir(dag_node_t **child_p,
395 const char *parent_path,
397 const svn_fs_fs__id_part_t *txn_id,
405 /* Set *CONTENTS to a readable generic stream which yields the
406 contents of FILE. Allocate the stream in POOL.
408 If FILE is not a file, return SVN_ERR_FS_NOT_FILE.
410 Use POOL for all allocations.
412 svn_error_t *svn_fs_fs__dag_get_contents(svn_stream_t **contents,
416 /* Attempt to fetch the contents of NODE and pass it along with the BATON
417 to the PROCESSOR. Set *SUCCESS only of the data could be provided
418 and the processor had been called.
420 Use POOL for all allocations.
423 svn_fs_fs__dag_try_process_file_contents(svn_boolean_t *success,
425 svn_fs_process_contents_func_t processor,
430 /* Set *STREAM_P to a delta stream that will turn the contents of SOURCE into
431 the contents of TARGET, allocated in POOL. If SOURCE is null, the empty
434 Use POOL for all allocations.
437 svn_fs_fs__dag_get_file_delta_stream(svn_txdelta_stream_t **stream_p,
442 /* Return a generic writable stream in *CONTENTS with which to set the
443 contents of FILE. Allocate the stream in POOL.
445 Any previous edits on the file will be deleted, and a new edit
446 stream will be constructed.
448 Use POOL for all allocations.
450 svn_error_t *svn_fs_fs__dag_get_edit_stream(svn_stream_t **contents,
455 /* Signify the completion of edits to FILE made using the stream
456 returned by svn_fs_fs__dag_get_edit_stream, allocating from POOL.
458 If CHECKSUM is non-null, it must match the checksum for FILE's
459 contents (note: this is not recalculated, the recorded checksum is
460 used), else the error SVN_ERR_CHECKSUM_MISMATCH is returned.
462 This operation is a no-op if no edits are present.
464 Use POOL for all allocations, including to cache the node_revision in
467 svn_error_t *svn_fs_fs__dag_finalize_edits(dag_node_t *file,
468 const svn_checksum_t *checksum,
472 /* Set *LENGTH to the length of the contents of FILE.
474 Use POOL for all allocations.
476 svn_error_t *svn_fs_fs__dag_file_length(svn_filesize_t *length,
480 /* Put the recorded checksum of type KIND for FILE into CHECKSUM, allocating
483 If no stored checksum is available, do not calculate the checksum,
484 just put NULL into CHECKSUM.
486 Use POOL for all allocations.
489 svn_fs_fs__dag_file_checksum(svn_checksum_t **checksum,
491 svn_checksum_kind_t kind,
494 /* Create a new mutable file named NAME in PARENT. Set *CHILD_P to a
495 reference to the new node, allocated in POOL. The new file's
496 contents are the empty string, and it has no properties. PARENT
497 must be mutable. NAME must be a single path component; it cannot
498 be a slash-separated directory path. PARENT_PATH must be the
499 canonicalized absolute path of the parent directory. TXN_ID is the
500 Subversion transaction under which this occurs.
502 Use POOL for all allocations.
504 svn_error_t *svn_fs_fs__dag_make_file(dag_node_t **child_p,
506 const char *parent_path,
508 const svn_fs_fs__id_part_t *txn_id,
515 /* Make ENTRY in TO_NODE be a copy of FROM_NODE, allocating from POOL.
516 TO_NODE must be mutable. TXN_ID is the Subversion transaction
517 under which this occurs.
519 If PRESERVE_HISTORY is true, the new node will record that it was
520 copied from FROM_PATH in FROM_REV; therefore, FROM_NODE should be
521 the node found at FROM_PATH in FROM_REV, although this is not
522 checked. FROM_PATH should be canonicalized before being passed
525 If PRESERVE_HISTORY is false, FROM_PATH and FROM_REV are ignored.
527 Use POOL for all allocations.
529 svn_error_t *svn_fs_fs__dag_copy(dag_node_t *to_node,
531 dag_node_t *from_node,
532 svn_boolean_t preserve_history,
533 svn_revnum_t from_rev,
534 const char *from_path,
535 const svn_fs_fs__id_part_t *txn_id,
541 /* Find out what is the same between two nodes. If STRICT is FALSE,
542 this function may report false positives, i.e. report changes even
543 if the resulting contents / props are equal.
545 If PROPS_CHANGED is non-null, set *PROPS_CHANGED to 1 if the two
546 nodes have different property lists, or to 0 if same.
548 If CONTENTS_CHANGED is non-null, set *CONTENTS_CHANGED to 1 if the
549 two nodes have different contents, or to 0 if same. NODE1 and NODE2
550 must refer to files from the same filesystem.
552 Use POOL for temporary allocations.
554 svn_error_t *svn_fs_fs__dag_things_different(svn_boolean_t *props_changed,
555 svn_boolean_t *contents_changed,
558 svn_boolean_t strict,
562 /* Set *REV and *PATH to the copyroot revision and path of node NODE, or
563 to SVN_INVALID_REVNUM and NULL if no copyroot exists.
565 svn_error_t *svn_fs_fs__dag_get_copyroot(svn_revnum_t *rev,
569 /* Set *REV to the copyfrom revision associated with NODE.
571 svn_error_t *svn_fs_fs__dag_get_copyfrom_rev(svn_revnum_t *rev,
574 /* Set *PATH to the copyfrom path associated with NODE.
576 svn_error_t *svn_fs_fs__dag_get_copyfrom_path(const char **path,
579 /* Update *TARGET so that SOURCE is it's predecessor.
582 svn_fs_fs__dag_update_ancestry(dag_node_t *target,
587 #endif /* __cplusplus */
589 #endif /* SVN_LIBSVN_FS_DAG_H */