]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/subversion/subversion/libsvn_fs_fs/dag.h
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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 #ifdef __cplusplus
31 extern "C" {
32 #endif /* __cplusplus */
33
34 \f
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.
42
43    In other words:
44
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.
48
49    - The dag_node_t interface exposes the existence of copy nodes,
50      whereas the svn_fs.h handles them transparently.
51
52    - dag_node_t's must be explicitly cloned, whereas the svn_fs.h
53      operations make clones implicitly.
54
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.  */
58
59 \f
60 /* Generic DAG node stuff.  */
61
62 typedef struct dag_node_t dag_node_t;
63
64 /* Fill *NODE with a dag_node_t representing node revision ID in FS,
65    allocating in POOL.  */
66 svn_error_t *
67 svn_fs_fs__dag_get_node(dag_node_t **node,
68                         svn_fs_t *fs,
69                         const svn_fs_id_t *id,
70                         apr_pool_t *pool);
71
72
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. */
77 dag_node_t *
78 svn_fs_fs__dag_dup(const dag_node_t *node,
79                    apr_pool_t *pool);
80
81 /* Serialize a DAG node, except don't try to preserve the 'fs' member.
82    Implements svn_cache__serialize_func_t */
83 svn_error_t *
84 svn_fs_fs__dag_serialize(void **data,
85                          apr_size_t *data_len,
86                          void *in,
87                          apr_pool_t *pool);
88
89 /* Deserialize a DAG node, leaving the 'fs' member as NULL.
90    Implements svn_cache__deserialize_func_t */
91 svn_error_t *
92 svn_fs_fs__dag_deserialize(void **out,
93                            void *data,
94                            apr_size_t data_len,
95                            apr_pool_t *pool);
96
97 /* Return the filesystem containing NODE.  */
98 svn_fs_t *svn_fs_fs__dag_get_fs(dag_node_t *node);
99
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);
103
104
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,
109                                          dag_node_t *node,
110                                          apr_pool_t *pool);
111
112
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);
116
117
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);
121
122
123 /* Set *ID_P to the node revision ID of NODE's immediate predecessor,
124    or NULL if NODE has no predecessor.
125  */
126 svn_error_t *svn_fs_fs__dag_get_predecessor_id(const svn_fs_id_t **id_p,
127                                                dag_node_t *node);
128
129
130 /* Set *COUNT to the number of predecessors NODE has (recursively), or
131    -1 if not known.
132  */
133 /* ### This function is currently only used by 'verify'. */
134 svn_error_t *svn_fs_fs__dag_get_predecessor_count(int *count,
135                                                   dag_node_t *node);
136
137 /* Set *COUNT to the number of node under NODE (inclusive) with
138    svn:mergeinfo properties.
139  */
140 svn_error_t *svn_fs_fs__dag_get_mergeinfo_count(apr_int64_t *count,
141                                                 dag_node_t *node);
142
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
145    svn:mergeinfo.
146  */
147 svn_error_t *
148 svn_fs_fs__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they,
149                                               dag_node_t *node);
150
151 /* Set *HAS_MERGEINFO to a flag indicating whether or not NODE itself
152    has svn:mergeinfo set on it.
153  */
154 svn_error_t *
155 svn_fs_fs__dag_has_mergeinfo(svn_boolean_t *has_mergeinfo,
156                              dag_node_t *node);
157
158 /* Return non-zero IFF NODE is currently mutable. */
159 svn_boolean_t svn_fs_fs__dag_check_mutable(const dag_node_t *node);
160
161 /* Return the node kind of NODE. */
162 svn_node_kind_t svn_fs_fs__dag_node_kind(dag_node_t *node);
163
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
167    values).
168
169    If properties do not exist on NODE, *PROPLIST_P will be set to
170    NULL.
171
172    Use POOL for all allocations.
173  */
174 svn_error_t *svn_fs_fs__dag_get_proplist(apr_hash_t **proplist_p,
175                                          dag_node_t *node,
176                                          apr_pool_t *pool);
177
178 /* Set the property list of NODE to PROPLIST, allocating from POOL.
179    The node being changed must be mutable.
180
181    Use POOL for all allocations.
182  */
183 svn_error_t *svn_fs_fs__dag_set_proplist(dag_node_t *node,
184                                          apr_hash_t *proplist,
185                                          apr_pool_t *pool);
186
187 /* Increment the mergeinfo_count field on NODE by INCREMENT.  The node
188    being changed must be mutable.
189
190    Use POOL for all allocations.
191  */
192 svn_error_t *svn_fs_fs__dag_increment_mergeinfo_count(dag_node_t *node,
193                                                       apr_int64_t increment,
194                                                       apr_pool_t *pool);
195
196 /* Set the has-mergeinfo flag on NODE to HAS_MERGEINFO.  The node
197    being changed must be mutable.
198
199    Use POOL for all allocations.
200  */
201 svn_error_t *svn_fs_fs__dag_set_has_mergeinfo(dag_node_t *node,
202                                               svn_boolean_t has_mergeinfo,
203                                               apr_pool_t *pool);
204
205
206 \f
207 /* Revision and transaction roots.  */
208
209
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,
213                                           svn_fs_t *fs,
214                                           svn_revnum_t rev,
215                                           apr_pool_t *pool);
216
217
218 /* Set *NODE_P to the root of transaction TXN_ID in FS, allocating
219    from POOL.
220
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,
226                                      svn_fs_t *fs,
227                                      const char *txn_id,
228                                      apr_pool_t *pool);
229
230
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,
234                                           svn_fs_t *fs,
235                                           const char *txn_id,
236                                           apr_pool_t *pool);
237
238
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,
244                                        svn_fs_t *fs,
245                                        const char *txn_id,
246                                        apr_pool_t *pool);
247
248
249 \f
250 /* Directories.  */
251
252
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.
256  */
257 svn_error_t *
258 svn_fs_fs__dag_open(dag_node_t **child_p,
259                     dag_node_t *parent,
260                     const char *name,
261                     apr_pool_t *result_pool,
262                     apr_pool_t *scratch_pool);
263
264
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,
270                                         dag_node_t *node,
271                                         apr_pool_t *pool);
272
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.
277  */
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,
280                                        dag_node_t *node,
281                                        const char* name,
282                                        apr_pool_t *pool);
283
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
288    occurs.
289
290    Use POOL for all allocations, including to cache the node_revision in
291    NODE.
292  */
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,
297                                       const char *txn_id,
298                                       apr_pool_t *pool);
299
300
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.
308
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.
312
313    PATH is the canonicalized absolute path at which this node is being
314    created.
315
316    TXN_ID is the Subversion transaction under which this occurs.
317
318    Use POOL for all allocations.
319  */
320 svn_error_t *svn_fs_fs__dag_clone_child(dag_node_t **child_p,
321                                         dag_node_t *parent,
322                                         const char *parent_path,
323                                         const char *name,
324                                         const char *copy_id,
325                                         const char *txn_id,
326                                         svn_boolean_t is_parent_copyroot,
327                                         apr_pool_t *pool);
328
329
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
335    which this occurs.
336
337    If return SVN_ERR_FS_NO_SUCH_ENTRY, then there is no entry NAME in
338    PARENT.
339
340    Use POOL for all allocations.
341  */
342 svn_error_t *svn_fs_fs__dag_delete(dag_node_t *parent,
343                                    const char *name,
344                                    const char *txn_id,
345                                    apr_pool_t *pool);
346
347
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.
352
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,
359                                         apr_pool_t *pool);
360
361
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,
369                                               apr_pool_t *pool);
370
371
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.
380
381    Use POOL for all allocations.
382  */
383 svn_error_t *svn_fs_fs__dag_make_dir(dag_node_t **child_p,
384                                      dag_node_t *parent,
385                                      const char *parent_path,
386                                      const char *name,
387                                      const char *txn_id,
388                                      apr_pool_t *pool);
389
390
391 \f
392 /* Files.  */
393
394
395 /* Set *CONTENTS to a readable generic stream which yields the
396    contents of FILE.  Allocate the stream in POOL.
397
398    If FILE is not a file, return SVN_ERR_FS_NOT_FILE.
399
400    Use POOL for all allocations.
401  */
402 svn_error_t *svn_fs_fs__dag_get_contents(svn_stream_t **contents,
403                                          dag_node_t *file,
404                                          apr_pool_t *pool);
405
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.
409
410    Use POOL for all allocations.
411  */
412 svn_error_t *
413 svn_fs_fs__dag_try_process_file_contents(svn_boolean_t *success,
414                                          dag_node_t *node,
415                                          svn_fs_process_contents_func_t processor,
416                                          void* baton,
417                                          apr_pool_t *pool);
418
419
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
422    string will be used.
423
424    Use POOL for all allocations.
425  */
426 svn_error_t *
427 svn_fs_fs__dag_get_file_delta_stream(svn_txdelta_stream_t **stream_p,
428                                      dag_node_t *source,
429                                      dag_node_t *target,
430                                      apr_pool_t *pool);
431
432 /* Return a generic writable stream in *CONTENTS with which to set the
433    contents of FILE.  Allocate the stream in POOL.
434
435    Any previous edits on the file will be deleted, and a new edit
436    stream will be constructed.
437
438    Use POOL for all allocations.
439  */
440 svn_error_t *svn_fs_fs__dag_get_edit_stream(svn_stream_t **contents,
441                                             dag_node_t *file,
442                                             apr_pool_t *pool);
443
444
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.
447
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.
451
452    This operation is a no-op if no edits are present.
453
454    Use POOL for all allocations, including to cache the node_revision in
455    FILE.
456  */
457 svn_error_t *svn_fs_fs__dag_finalize_edits(dag_node_t *file,
458                                            const svn_checksum_t *checksum,
459                                            apr_pool_t *pool);
460
461
462 /* Set *LENGTH to the length of the contents of FILE.
463
464    Use POOL for all allocations.
465  */
466 svn_error_t *svn_fs_fs__dag_file_length(svn_filesize_t *length,
467                                         dag_node_t *file,
468                                         apr_pool_t *pool);
469
470 /* Put the recorded checksum of type KIND for FILE into CHECKSUM, allocating
471    from POOL.
472
473    If no stored checksum is available, do not calculate the checksum,
474    just put NULL into CHECKSUM.
475
476    Use POOL for all allocations.
477  */
478 svn_error_t *
479 svn_fs_fs__dag_file_checksum(svn_checksum_t **checksum,
480                              dag_node_t *file,
481                              svn_checksum_kind_t kind,
482                              apr_pool_t *pool);
483
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.
491
492    Use POOL for all allocations.
493  */
494 svn_error_t *svn_fs_fs__dag_make_file(dag_node_t **child_p,
495                                       dag_node_t *parent,
496                                       const char *parent_path,
497                                       const char *name,
498                                       const char *txn_id,
499                                       apr_pool_t *pool);
500
501
502 \f
503 /* Copies */
504
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.
508
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
513    here.
514
515    If PRESERVE_HISTORY is false, FROM_PATH and FROM_REV are ignored.
516
517    Use POOL for all allocations.
518  */
519 svn_error_t *svn_fs_fs__dag_copy(dag_node_t *to_node,
520                                  const char *entry,
521                                  dag_node_t *from_node,
522                                  svn_boolean_t preserve_history,
523                                  svn_revnum_t from_rev,
524                                  const char *from_path,
525                                  const char *txn_id,
526                                  apr_pool_t *pool);
527
528 \f
529 /* Comparison */
530
531 /* Find out what is the same between two nodes.
532
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.
535
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.)
542
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.
547  */
548 svn_error_t *svn_fs_fs__dag_things_different(svn_boolean_t *props_changed,
549                                              svn_boolean_t *contents_changed,
550                                              dag_node_t *node1,
551                                              dag_node_t *node2);
552
553
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.
556  */
557 svn_error_t *svn_fs_fs__dag_get_copyroot(svn_revnum_t *rev,
558                                          const char **path,
559                                          dag_node_t *node);
560
561 /* Set *REV to the copyfrom revision associated with NODE.
562  */
563 svn_error_t *svn_fs_fs__dag_get_copyfrom_rev(svn_revnum_t *rev,
564                                              dag_node_t *node);
565
566 /* Set *PATH to the copyfrom path associated with NODE.
567  */
568 svn_error_t *svn_fs_fs__dag_get_copyfrom_path(const char **path,
569                                               dag_node_t *node);
570
571 /* Update *TARGET so that SOURCE is it's predecessor.
572  */
573 svn_error_t *
574 svn_fs_fs__dag_update_ancestry(dag_node_t *target,
575                                dag_node_t *source,
576                                apr_pool_t *pool);
577 #ifdef __cplusplus
578 }
579 #endif /* __cplusplus */
580
581 #endif /* SVN_LIBSVN_FS_DAG_H */