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"
32 #endif /* __cplusplus */
35 /* The interface in this file provides all the essential filesystem
36 operations, but exposes the filesystem's DAG structure. This makes
37 it simpler to implement than the public interface, since a client
38 of this interface has to understand and cope with shared structure
39 directly as it appears in the database. However, it's still a
40 self-consistent set of invariants to maintain, making it
41 (hopefully) a useful interface boundary.
45 - The dag_node_t interface exposes the internal DAG structure of
46 the filesystem, while the svn_fs.h interface does any cloning
47 necessary to make the filesystem look like a tree.
49 - The dag_node_t interface exposes the existence of copy nodes,
50 whereas the svn_fs.h handles them transparently.
52 - dag_node_t's must be explicitly cloned, whereas the svn_fs.h
53 operations make clones implicitly.
55 - Callers of the dag_node_t interface use Berkeley DB transactions
56 to ensure consistency between operations, while callers of the
57 svn_fs.h interface use Subversion transactions. */
60 /* Generic DAG node stuff. */
62 typedef struct dag_node_t dag_node_t;
64 /* Fill *NODE with a dag_node_t representing node revision ID in FS,
65 allocating in POOL. */
67 svn_fs_fs__dag_get_node(dag_node_t **node,
69 const svn_fs_id_t *id,
73 /* Return a new dag_node_t object referring to the same node as NODE,
74 allocated in POOL. If you're trying to build a structure in a
75 pool that wants to refer to dag nodes that may have been allocated
76 elsewhere, you can call this function and avoid inter-pool pointers. */
78 svn_fs_fs__dag_dup(const dag_node_t *node,
81 /* Serialize a DAG node, except don't try to preserve the 'fs' member.
82 Implements svn_cache__serialize_func_t */
84 svn_fs_fs__dag_serialize(void **data,
89 /* Deserialize a DAG node, leaving the 'fs' member as NULL.
90 Implements svn_cache__deserialize_func_t */
92 svn_fs_fs__dag_deserialize(void **out,
97 /* Return the filesystem containing NODE. */
98 svn_fs_t *svn_fs_fs__dag_get_fs(dag_node_t *node);
100 /* Changes the filesystem containing NODE to FS. (Used when pulling
101 nodes out of a shared cache, say.) */
102 void svn_fs_fs__dag_set_fs(dag_node_t *node, svn_fs_t *fs);
105 /* Set *REV to NODE's revision number, allocating in POOL. If NODE
106 has never been committed as part of a revision, set *REV to
107 SVN_INVALID_REVNUM. */
108 svn_error_t *svn_fs_fs__dag_get_revision(svn_revnum_t *rev,
113 /* Return the node revision ID of NODE. The value returned is shared
114 with NODE, and will be deallocated when NODE is. */
115 const svn_fs_id_t *svn_fs_fs__dag_get_id(const dag_node_t *node);
118 /* Return the created path of NODE. The value returned is shared
119 with NODE, and will be deallocated when NODE is. */
120 const char *svn_fs_fs__dag_get_created_path(dag_node_t *node);
123 /* Set *ID_P to the node revision ID of NODE's immediate predecessor,
124 or NULL if NODE has no predecessor.
126 svn_error_t *svn_fs_fs__dag_get_predecessor_id(const svn_fs_id_t **id_p,
130 /* Set *COUNT to the number of predecessors NODE has (recursively), or
133 /* ### This function is currently only used by 'verify'. */
134 svn_error_t *svn_fs_fs__dag_get_predecessor_count(int *count,
137 /* Set *COUNT to the number of node under NODE (inclusive) with
138 svn:mergeinfo properties.
140 svn_error_t *svn_fs_fs__dag_get_mergeinfo_count(apr_int64_t *count,
143 /* Set *DO_THEY to a flag indicating whether or not NODE is a
144 directory with at least one descendant (not including itself) with
148 svn_fs_fs__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they,
151 /* Set *HAS_MERGEINFO to a flag indicating whether or not NODE itself
152 has svn:mergeinfo set on it.
155 svn_fs_fs__dag_has_mergeinfo(svn_boolean_t *has_mergeinfo,
158 /* Return non-zero IFF NODE is currently mutable. */
159 svn_boolean_t svn_fs_fs__dag_check_mutable(const dag_node_t *node);
161 /* Return the node kind of NODE. */
162 svn_node_kind_t svn_fs_fs__dag_node_kind(dag_node_t *node);
164 /* Set *PROPLIST_P to a PROPLIST hash representing the entire property
165 list of NODE, allocating from POOL. The hash has const char *
166 names (the property names) and svn_string_t * values (the property
169 If properties do not exist on NODE, *PROPLIST_P will be set to
172 Use POOL for all allocations.
174 svn_error_t *svn_fs_fs__dag_get_proplist(apr_hash_t **proplist_p,
178 /* Set the property list of NODE to PROPLIST, allocating from POOL.
179 The node being changed must be mutable.
181 Use POOL for all allocations.
183 svn_error_t *svn_fs_fs__dag_set_proplist(dag_node_t *node,
184 apr_hash_t *proplist,
187 /* Increment the mergeinfo_count field on NODE by INCREMENT. The node
188 being changed must be mutable.
190 Use POOL for all allocations.
192 svn_error_t *svn_fs_fs__dag_increment_mergeinfo_count(dag_node_t *node,
193 apr_int64_t increment,
196 /* Set the has-mergeinfo flag on NODE to HAS_MERGEINFO. The node
197 being changed must be mutable.
199 Use POOL for all allocations.
201 svn_error_t *svn_fs_fs__dag_set_has_mergeinfo(dag_node_t *node,
202 svn_boolean_t has_mergeinfo,
207 /* Revision and transaction roots. */
210 /* Open the root of revision REV of filesystem FS, allocating from
211 POOL. Set *NODE_P to the new node. */
212 svn_error_t *svn_fs_fs__dag_revision_root(dag_node_t **node_p,
218 /* Set *NODE_P to the root of transaction TXN_ID in FS, allocating
221 Note that the root node of TXN_ID is not necessarily mutable. If
222 no changes have been made in the transaction, then it may share its
223 root directory with its base revision. To get a mutable root node
224 for a transaction, call svn_fs_fs__dag_clone_root. */
225 svn_error_t *svn_fs_fs__dag_txn_root(dag_node_t **node_p,
231 /* Set *NODE_P to the base root of transaction TXN_ID in FS,
232 allocating from POOL. Allocate the node in TRAIL->pool. */
233 svn_error_t *svn_fs_fs__dag_txn_base_root(dag_node_t **node_p,
239 /* Clone the root directory of TXN_ID in FS, and update the
240 `transactions' table entry to point to it, unless this has been
241 done already. In either case, set *ROOT_P to a reference to the
242 root directory clone. Allocate *ROOT_P in POOL. */
243 svn_error_t *svn_fs_fs__dag_clone_root(dag_node_t **root_p,
253 /* Open the node named NAME in the directory PARENT. Set *CHILD_P to
254 the new node, allocated in RESULT_POOL. NAME must be a single path
255 component; it cannot be a slash-separated directory path.
258 svn_fs_fs__dag_open(dag_node_t **child_p,
261 apr_pool_t *result_pool,
262 apr_pool_t *scratch_pool);
265 /* Set *ENTRIES_P to a hash table of NODE's entries. The keys of the
266 table are entry names, and the values are svn_fs_dirent_t's. The
267 returned table (and its keys and values) is allocated in POOL,
268 which is also used for temporary allocations. */
269 svn_error_t *svn_fs_fs__dag_dir_entries(apr_hash_t **entries_p,
273 /* Fetches the NODE's entries and returns a copy of the entry selected
274 by the key value given in NAME and set *DIRENT to a copy of that
275 entry. If such entry was found, the copy will be allocated in POOL.
276 Otherwise, the *DIRENT will be set to NULL.
278 /* ### This function is currently only called from dag.c. */
279 svn_error_t * svn_fs_fs__dag_dir_entry(svn_fs_dirent_t **dirent,
284 /* Set ENTRY_NAME in NODE to point to ID (with kind KIND), allocating
285 from POOL. NODE must be a mutable directory. ID can refer to a
286 mutable or immutable node. If ENTRY_NAME does not exist, it will
287 be created. TXN_ID is the Subversion transaction under which this
290 Use POOL for all allocations, including to cache the node_revision in
293 svn_error_t *svn_fs_fs__dag_set_entry(dag_node_t *node,
294 const char *entry_name,
295 const svn_fs_id_t *id,
296 svn_node_kind_t kind,
301 /* Make a new mutable clone of the node named NAME in PARENT, and
302 adjust PARENT's directory entry to point to it, unless NAME in
303 PARENT already refers to a mutable node. In either case, set
304 *CHILD_P to a reference to the new node, allocated in POOL. PARENT
305 must be mutable. NAME must be a single path component; it cannot
306 be a slash-separated directory path. PARENT_PATH must be the
307 canonicalized absolute path of the parent directory.
309 COPY_ID, if non-NULL, is a key into the `copies' table, and
310 indicates that this new node is being created as the result of a
311 copy operation, and specifically which operation that was.
313 PATH is the canonicalized absolute path at which this node is being
316 TXN_ID is the Subversion transaction under which this occurs.
318 Use POOL for all allocations.
320 svn_error_t *svn_fs_fs__dag_clone_child(dag_node_t **child_p,
322 const char *parent_path,
326 svn_boolean_t is_parent_copyroot,
330 /* Delete the directory entry named NAME from PARENT, allocating from
331 POOL. PARENT must be mutable. NAME must be a single path
332 component; it cannot be a slash-separated directory path. If the
333 node being deleted is a mutable directory, remove all mutable nodes
334 reachable from it. TXN_ID is the Subversion transaction under
337 If return SVN_ERR_FS_NO_SUCH_ENTRY, then there is no entry NAME in
340 Use POOL for all allocations.
342 svn_error_t *svn_fs_fs__dag_delete(dag_node_t *parent,
348 /* Delete the node revision assigned to node ID from FS's `nodes'
349 table, allocating from POOL. Also delete any mutable
350 representations and strings associated with that node revision. ID
351 may refer to a file or directory, which must be mutable.
353 NOTE: If ID represents a directory, and that directory has mutable
354 children, you risk orphaning those children by leaving them
355 dangling, disconnected from all DAG trees. It is assumed that
356 callers of this interface know what in the world they are doing. */
357 svn_error_t *svn_fs_fs__dag_remove_node(svn_fs_t *fs,
358 const svn_fs_id_t *id,
362 /* Delete all mutable node revisions reachable from node ID, including
363 ID itself, from FS's `nodes' table, allocating from POOL. Also
364 delete any mutable representations and strings associated with that
365 node revision. ID may refer to a file or directory, which may be
366 mutable or immutable. */
367 svn_error_t *svn_fs_fs__dag_delete_if_mutable(svn_fs_t *fs,
368 const svn_fs_id_t *id,
372 /* Create a new mutable directory named NAME in PARENT. Set *CHILD_P
373 to a reference to the new node, allocated in POOL. The new
374 directory has no contents, and no properties. PARENT must be
375 mutable. NAME must be a single path component; it cannot be a
376 slash-separated directory path. PARENT_PATH must be the
377 canonicalized absolute path of the parent directory. PARENT must
378 not currently have an entry named NAME. TXN_ID is the Subversion
379 transaction under which this occurs.
381 Use POOL for all allocations.
383 svn_error_t *svn_fs_fs__dag_make_dir(dag_node_t **child_p,
385 const char *parent_path,
395 /* Set *CONTENTS to a readable generic stream which yields the
396 contents of FILE. Allocate the stream in POOL.
398 If FILE is not a file, return SVN_ERR_FS_NOT_FILE.
400 Use POOL for all allocations.
402 svn_error_t *svn_fs_fs__dag_get_contents(svn_stream_t **contents,
406 /* Attempt to fetch the contents of NODE and pass it along with the BATON
407 to the PROCESSOR. Set *SUCCESS only of the data could be provided
408 and the processor had been called.
410 Use POOL for all allocations.
413 svn_fs_fs__dag_try_process_file_contents(svn_boolean_t *success,
415 svn_fs_process_contents_func_t processor,
420 /* Set *STREAM_P to a delta stream that will turn the contents of SOURCE into
421 the contents of TARGET, allocated in POOL. If SOURCE is null, the empty
424 Use POOL for all allocations.
427 svn_fs_fs__dag_get_file_delta_stream(svn_txdelta_stream_t **stream_p,
432 /* Return a generic writable stream in *CONTENTS with which to set the
433 contents of FILE. Allocate the stream in POOL.
435 Any previous edits on the file will be deleted, and a new edit
436 stream will be constructed.
438 Use POOL for all allocations.
440 svn_error_t *svn_fs_fs__dag_get_edit_stream(svn_stream_t **contents,
445 /* Signify the completion of edits to FILE made using the stream
446 returned by svn_fs_fs__dag_get_edit_stream, allocating from POOL.
448 If CHECKSUM is non-null, it must match the checksum for FILE's
449 contents (note: this is not recalculated, the recorded checksum is
450 used), else the error SVN_ERR_CHECKSUM_MISMATCH is returned.
452 This operation is a no-op if no edits are present.
454 Use POOL for all allocations, including to cache the node_revision in
457 svn_error_t *svn_fs_fs__dag_finalize_edits(dag_node_t *file,
458 const svn_checksum_t *checksum,
462 /* Set *LENGTH to the length of the contents of FILE.
464 Use POOL for all allocations.
466 svn_error_t *svn_fs_fs__dag_file_length(svn_filesize_t *length,
470 /* Put the recorded checksum of type KIND for FILE into CHECKSUM, allocating
473 If no stored checksum is available, do not calculate the checksum,
474 just put NULL into CHECKSUM.
476 Use POOL for all allocations.
479 svn_fs_fs__dag_file_checksum(svn_checksum_t **checksum,
481 svn_checksum_kind_t kind,
484 /* Create a new mutable file named NAME in PARENT. Set *CHILD_P to a
485 reference to the new node, allocated in POOL. The new file's
486 contents are the empty string, and it has no properties. PARENT
487 must be mutable. NAME must be a single path component; it cannot
488 be a slash-separated directory path. PARENT_PATH must be the
489 canonicalized absolute path of the parent directory. TXN_ID is the
490 Subversion transaction under which this occurs.
492 Use POOL for all allocations.
494 svn_error_t *svn_fs_fs__dag_make_file(dag_node_t **child_p,
496 const char *parent_path,
505 /* Make ENTRY in TO_NODE be a copy of FROM_NODE, allocating from POOL.
506 TO_NODE must be mutable. TXN_ID is the Subversion transaction
507 under which this occurs.
509 If PRESERVE_HISTORY is true, the new node will record that it was
510 copied from FROM_PATH in FROM_REV; therefore, FROM_NODE should be
511 the node found at FROM_PATH in FROM_REV, although this is not
512 checked. FROM_PATH should be canonicalized before being passed
515 If PRESERVE_HISTORY is false, FROM_PATH and FROM_REV are ignored.
517 Use POOL for all allocations.
519 svn_error_t *svn_fs_fs__dag_copy(dag_node_t *to_node,
521 dag_node_t *from_node,
522 svn_boolean_t preserve_history,
523 svn_revnum_t from_rev,
524 const char *from_path,
531 /* Find out what is the same between two nodes.
533 If PROPS_CHANGED is non-null, set *PROPS_CHANGED to 1 if the two
534 nodes have different property lists, or to 0 if same.
536 If CONTENTS_CHANGED is non-null, set *CONTENTS_CHANGED to 1 if the
537 two nodes have different contents, or to 0 if same. For files,
538 file contents are compared; for directories, the entries lists are
539 compared. If one is a file and the other is a directory, the one's
540 contents will be compared to the other's entries list. (Not
541 terribly useful, I suppose, but that's the caller's business.)
543 ### todo: This function only compares rep keys at the moment. This
544 may leave us with a slight chance of a false positive, though I
545 don't really see how that would happen in practice. Nevertheless,
546 it should probably be fixed.
548 svn_error_t *svn_fs_fs__dag_things_different(svn_boolean_t *props_changed,
549 svn_boolean_t *contents_changed,
554 /* Set *REV and *PATH to the copyroot revision and path of node NODE, or
555 to SVN_INVALID_REVNUM and NULL if no copyroot exists.
557 svn_error_t *svn_fs_fs__dag_get_copyroot(svn_revnum_t *rev,
561 /* Set *REV to the copyfrom revision associated with NODE.
563 svn_error_t *svn_fs_fs__dag_get_copyfrom_rev(svn_revnum_t *rev,
566 /* Set *PATH to the copyfrom path associated with NODE.
568 svn_error_t *svn_fs_fs__dag_get_copyfrom_path(const char **path,
571 /* Update *TARGET so that SOURCE is it's predecessor.
574 svn_fs_fs__dag_update_ancestry(dag_node_t *target,
579 #endif /* __cplusplus */
581 #endif /* SVN_LIBSVN_FS_DAG_H */