]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/subversion/subversion/libsvn_fs_fs/dag.h
MFC r275385 (by bapt):
[FreeBSD/stable/10.git] / contrib / subversion / subversion / libsvn_fs_fs / dag.h
1 /* dag.h : DAG-like interface 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_DAG_H
24 #define SVN_LIBSVN_FS_DAG_H
25
26 #include "svn_fs.h"
27 #include "svn_delta.h"
28 #include "private/svn_cache.h"
29
30 #include "id.h"
31
32 #ifdef __cplusplus
33 extern "C" {
34 #endif /* __cplusplus */
35
36 \f
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.
44
45    In other words:
46
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.
50
51    - The dag_node_t interface exposes the existence of copy nodes,
52      whereas the svn_fs.h handles them transparently.
53
54    - dag_node_t's must be explicitly cloned, whereas the svn_fs.h
55      operations make clones implicitly.
56
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.  */
60
61 \f
62 /* Generic DAG node stuff.  */
63
64 typedef struct dag_node_t dag_node_t;
65
66 /* Fill *NODE with a dag_node_t representing node revision ID in FS,
67    allocating in POOL.  */
68 svn_error_t *
69 svn_fs_fs__dag_get_node(dag_node_t **node,
70                         svn_fs_t *fs,
71                         const svn_fs_id_t *id,
72                         apr_pool_t *pool);
73
74
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. */
79 dag_node_t *
80 svn_fs_fs__dag_dup(const dag_node_t *node,
81                    apr_pool_t *pool);
82
83 /* Serialize a DAG node, except don't try to preserve the 'fs' member.
84    Implements svn_cache__serialize_func_t */
85 svn_error_t *
86 svn_fs_fs__dag_serialize(void **data,
87                          apr_size_t *data_len,
88                          void *in,
89                          apr_pool_t *pool);
90
91 /* Deserialize a DAG node, leaving the 'fs' member as NULL.
92    Implements svn_cache__deserialize_func_t */
93 svn_error_t *
94 svn_fs_fs__dag_deserialize(void **out,
95                            void *data,
96                            apr_size_t data_len,
97                            apr_pool_t *pool);
98
99 /* Return the filesystem containing NODE.  */
100 svn_fs_t *svn_fs_fs__dag_get_fs(dag_node_t *node);
101
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);
105
106
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,
111                                          dag_node_t *node,
112                                          apr_pool_t *pool);
113
114
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);
118
119
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);
123
124
125 /* Set *ID_P to the node revision ID of NODE's immediate predecessor,
126    or NULL if NODE has no predecessor.
127  */
128 svn_error_t *svn_fs_fs__dag_get_predecessor_id(const svn_fs_id_t **id_p,
129                                                dag_node_t *node);
130
131
132 /* Set *COUNT to the number of predecessors NODE has (recursively), or
133    -1 if not known.
134  */
135 /* ### This function is currently only used by 'verify'. */
136 svn_error_t *svn_fs_fs__dag_get_predecessor_count(int *count,
137                                                   dag_node_t *node);
138
139 /* Set *COUNT to the number of node under NODE (inclusive) with
140    svn:mergeinfo properties.
141  */
142 svn_error_t *svn_fs_fs__dag_get_mergeinfo_count(apr_int64_t *count,
143                                                 dag_node_t *node);
144
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
147    svn:mergeinfo.
148  */
149 svn_error_t *
150 svn_fs_fs__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they,
151                                               dag_node_t *node);
152
153 /* Set *HAS_MERGEINFO to a flag indicating whether or not NODE itself
154    has svn:mergeinfo set on it.
155  */
156 svn_error_t *
157 svn_fs_fs__dag_has_mergeinfo(svn_boolean_t *has_mergeinfo,
158                              dag_node_t *node);
159
160 /* Return non-zero IFF NODE is currently mutable. */
161 svn_boolean_t svn_fs_fs__dag_check_mutable(const dag_node_t *node);
162
163 /* Return the node kind of NODE. */
164 svn_node_kind_t svn_fs_fs__dag_node_kind(dag_node_t *node);
165
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
169    values).
170
171    If properties do not exist on NODE, *PROPLIST_P will be set to
172    NULL.
173
174    Use POOL for all allocations.
175  */
176 svn_error_t *svn_fs_fs__dag_get_proplist(apr_hash_t **proplist_p,
177                                          dag_node_t *node,
178                                          apr_pool_t *pool);
179
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,
183                                       dag_node_t *node,
184                                       apr_pool_t *scratch_pool);
185
186 /* Set the property list of NODE to PROPLIST, allocating from POOL.
187    The node being changed must be mutable.
188
189    Use POOL for all allocations.
190  */
191 svn_error_t *svn_fs_fs__dag_set_proplist(dag_node_t *node,
192                                          apr_hash_t *proplist,
193                                          apr_pool_t *pool);
194
195 /* Increment the mergeinfo_count field on NODE by INCREMENT.  The node
196    being changed must be mutable.
197
198    Use POOL for all allocations.
199  */
200 svn_error_t *svn_fs_fs__dag_increment_mergeinfo_count(dag_node_t *node,
201                                                       apr_int64_t increment,
202                                                       apr_pool_t *pool);
203
204 /* Set the has-mergeinfo flag on NODE to HAS_MERGEINFO.  The node
205    being changed must be mutable.
206
207    Use POOL for all allocations.
208  */
209 svn_error_t *svn_fs_fs__dag_set_has_mergeinfo(dag_node_t *node,
210                                               svn_boolean_t has_mergeinfo,
211                                               apr_pool_t *pool);
212
213
214 \f
215 /* Revision and transaction roots.  */
216
217
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,
221                                           svn_fs_t *fs,
222                                           svn_revnum_t rev,
223                                           apr_pool_t *pool);
224
225
226 /* Set *NODE_P to the root of transaction TXN_ID in FS, allocating
227    from POOL.
228
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,
234                                      svn_fs_t *fs,
235                                      const svn_fs_fs__id_part_t *txn_id,
236                                      apr_pool_t *pool);
237
238
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,
242                                           svn_fs_t *fs,
243                                           const svn_fs_fs__id_part_t *txn_id,
244                                           apr_pool_t *pool);
245
246
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,
252                                        svn_fs_t *fs,
253                                        const svn_fs_fs__id_part_t *txn_id,
254                                        apr_pool_t *pool);
255
256
257 \f
258 /* Directories.  */
259
260
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.
265  */
266 svn_error_t *
267 svn_fs_fs__dag_open(dag_node_t **child_p,
268                     dag_node_t *parent,
269                     const char *name,
270                     apr_pool_t *result_pool,
271                     apr_pool_t *scratch_pool);
272
273
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,
278                                         dag_node_t *node,
279                                         apr_pool_t *pool);
280
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.
286  */
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,
289                                        dag_node_t *node,
290                                        const char* name,
291                                        apr_pool_t *result_pool,
292                                        apr_pool_t *scratch_pool);
293
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
298    occurs.
299
300    Use POOL for all allocations, including to cache the node_revision in
301    NODE.
302  */
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,
308                                       apr_pool_t *pool);
309
310
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.
318
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.
322
323    PATH is the canonicalized absolute path at which this node is being
324    created.
325
326    TXN_ID is the Subversion transaction under which this occurs.
327
328    Use POOL for all allocations.
329  */
330 svn_error_t *svn_fs_fs__dag_clone_child(dag_node_t **child_p,
331                                         dag_node_t *parent,
332                                         const char *parent_path,
333                                         const char *name,
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,
337                                         apr_pool_t *pool);
338
339
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
345    which this occurs.
346
347    If return SVN_ERR_FS_NO_SUCH_ENTRY, then there is no entry NAME in
348    PARENT.
349
350    Use POOL for all allocations.
351  */
352 svn_error_t *svn_fs_fs__dag_delete(dag_node_t *parent,
353                                    const char *name,
354                                    const svn_fs_fs__id_part_t *txn_id,
355                                    apr_pool_t *pool);
356
357
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.
362
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,
369                                         apr_pool_t *pool);
370
371
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,
379                                               apr_pool_t *pool);
380
381
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.
390
391    Use POOL for all allocations.
392  */
393 svn_error_t *svn_fs_fs__dag_make_dir(dag_node_t **child_p,
394                                      dag_node_t *parent,
395                                      const char *parent_path,
396                                      const char *name,
397                                      const svn_fs_fs__id_part_t *txn_id,
398                                      apr_pool_t *pool);
399
400
401 \f
402 /* Files.  */
403
404
405 /* Set *CONTENTS to a readable generic stream which yields the
406    contents of FILE.  Allocate the stream in POOL.
407
408    If FILE is not a file, return SVN_ERR_FS_NOT_FILE.
409
410    Use POOL for all allocations.
411  */
412 svn_error_t *svn_fs_fs__dag_get_contents(svn_stream_t **contents,
413                                          dag_node_t *file,
414                                          apr_pool_t *pool);
415
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.
419
420    Use POOL for all allocations.
421  */
422 svn_error_t *
423 svn_fs_fs__dag_try_process_file_contents(svn_boolean_t *success,
424                                          dag_node_t *node,
425                                          svn_fs_process_contents_func_t processor,
426                                          void* baton,
427                                          apr_pool_t *pool);
428
429
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
432    string will be used.
433
434    Use POOL for all allocations.
435  */
436 svn_error_t *
437 svn_fs_fs__dag_get_file_delta_stream(svn_txdelta_stream_t **stream_p,
438                                      dag_node_t *source,
439                                      dag_node_t *target,
440                                      apr_pool_t *pool);
441
442 /* Return a generic writable stream in *CONTENTS with which to set the
443    contents of FILE.  Allocate the stream in POOL.
444
445    Any previous edits on the file will be deleted, and a new edit
446    stream will be constructed.
447
448    Use POOL for all allocations.
449  */
450 svn_error_t *svn_fs_fs__dag_get_edit_stream(svn_stream_t **contents,
451                                             dag_node_t *file,
452                                             apr_pool_t *pool);
453
454
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.
457
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.
461
462    This operation is a no-op if no edits are present.
463
464    Use POOL for all allocations, including to cache the node_revision in
465    FILE.
466  */
467 svn_error_t *svn_fs_fs__dag_finalize_edits(dag_node_t *file,
468                                            const svn_checksum_t *checksum,
469                                            apr_pool_t *pool);
470
471
472 /* Set *LENGTH to the length of the contents of FILE.
473
474    Use POOL for all allocations.
475  */
476 svn_error_t *svn_fs_fs__dag_file_length(svn_filesize_t *length,
477                                         dag_node_t *file,
478                                         apr_pool_t *pool);
479
480 /* Put the recorded checksum of type KIND for FILE into CHECKSUM, allocating
481    from POOL.
482
483    If no stored checksum is available, do not calculate the checksum,
484    just put NULL into CHECKSUM.
485
486    Use POOL for all allocations.
487  */
488 svn_error_t *
489 svn_fs_fs__dag_file_checksum(svn_checksum_t **checksum,
490                              dag_node_t *file,
491                              svn_checksum_kind_t kind,
492                              apr_pool_t *pool);
493
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.
501
502    Use POOL for all allocations.
503  */
504 svn_error_t *svn_fs_fs__dag_make_file(dag_node_t **child_p,
505                                       dag_node_t *parent,
506                                       const char *parent_path,
507                                       const char *name,
508                                       const svn_fs_fs__id_part_t *txn_id,
509                                       apr_pool_t *pool);
510
511
512 \f
513 /* Copies */
514
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.
518
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
523    here.
524
525    If PRESERVE_HISTORY is false, FROM_PATH and FROM_REV are ignored.
526
527    Use POOL for all allocations.
528  */
529 svn_error_t *svn_fs_fs__dag_copy(dag_node_t *to_node,
530                                  const char *entry,
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,
536                                  apr_pool_t *pool);
537
538 \f
539 /* Comparison */
540
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.
544
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.
547
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.
551
552    Use POOL for temporary allocations.
553  */
554 svn_error_t *svn_fs_fs__dag_things_different(svn_boolean_t *props_changed,
555                                              svn_boolean_t *contents_changed,
556                                              dag_node_t *node1,
557                                              dag_node_t *node2,
558                                              svn_boolean_t strict,
559                                              apr_pool_t *pool);
560
561
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.
564  */
565 svn_error_t *svn_fs_fs__dag_get_copyroot(svn_revnum_t *rev,
566                                          const char **path,
567                                          dag_node_t *node);
568
569 /* Set *REV to the copyfrom revision associated with NODE.
570  */
571 svn_error_t *svn_fs_fs__dag_get_copyfrom_rev(svn_revnum_t *rev,
572                                              dag_node_t *node);
573
574 /* Set *PATH to the copyfrom path associated with NODE.
575  */
576 svn_error_t *svn_fs_fs__dag_get_copyfrom_path(const char **path,
577                                               dag_node_t *node);
578
579 /* Update *TARGET so that SOURCE is it's predecessor.
580  */
581 svn_error_t *
582 svn_fs_fs__dag_update_ancestry(dag_node_t *target,
583                                dag_node_t *source,
584                                apr_pool_t *pool);
585 #ifdef __cplusplus
586 }
587 #endif /* __cplusplus */
588
589 #endif /* SVN_LIBSVN_FS_DAG_H */