1/* util.h --- utility functions for FSFS repo access
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__UTIL_H
24#define SVN_LIBSVN_FS__UTIL_H
25
26#include "svn_fs.h"
27#include "id.h"
28
29/* Functions for dealing with recoverable errors on mutable files
30 *
31 * Revprops, current, and txn-current files are mutable; that is, they
32 * change as part of normal fsfs operation, in constrat to revs files, or
33 * the format file, which are written once at create (or upgrade) time.
34 * When more than one host writes to the same repository, we will
35 * sometimes see these recoverable errors when accesssing these files.
36 *
37 * These errors all relate to NFS, and thus we only use this retry code if
38 * ESTALE is defined.
39 *
40 ** ESTALE
41 *
42 * In NFS v3 and under, the server doesn't track opened files.  If you
43 * unlink(2) or rename(2) a file held open by another process *on the
44 * same host*, that host's kernel typically renames the file to
45 * .nfsXXXX and automatically deletes that when it's no longer open,
46 * but this behavior is not required.
47 *
48 * For obvious reasons, this does not work *across hosts*.  No one
49 * knows about the opened file; not the server, and not the deleting
50 * client.  So the file vanishes, and the reader gets stale NFS file
51 * handle.
52 *
53 ** EIO, ENOENT
54 *
55 * Some client implementations (at least the 2.6.18.5 kernel that ships
56 * with Ubuntu Dapper) sometimes give spurious ENOENT (only on open) or
57 * even EIO errors when trying to read these files that have been renamed
58 * over on some other host.
59 *
60 ** Solution
61 *
62 * Try open and read of such files in try_stringbuf_from_file().  Call
63 * this function within a loop of SVN_FS_FS__RECOVERABLE_RETRY_COUNT
64 * iterations (though, realistically, the second try will succeed).
65 */
66
67#define SVN_FS_FS__RECOVERABLE_RETRY_COUNT 10
68
69/* Return TRUE is REV is packed in FS, FALSE otherwise. */
70svn_boolean_t
71svn_fs_fs__is_packed_rev(svn_fs_t *fs,
72                         svn_revnum_t rev);
73
74/* Return TRUE is REV's props have been packed in FS, FALSE otherwise. */
75svn_boolean_t
76svn_fs_fs__is_packed_revprop(svn_fs_t *fs,
77                             svn_revnum_t rev);
78
79/* Return the first revision in the pack / rev file containing REVISION in
80 * filesystem FS.  For non-packed revs, this will simply be REVISION. */
81svn_revnum_t
82svn_fs_fs__packed_base_rev(svn_fs_t *fs,
83                           svn_revnum_t revision);
84
85/* Return the full path of the rev shard directory that will contain
86 * revision REV in FS.  Allocate the result in POOL.
87 */
88const char *
89svn_fs_fs__path_rev_shard(svn_fs_t *fs,
90                          svn_revnum_t rev,
91                          apr_pool_t *pool);
92
93/* Return the full path of the non-packed rev file containing revision REV
94 * in FS.  Allocate the result in POOL.
95 */
96const char *
97svn_fs_fs__path_rev(svn_fs_t *fs,
98                    svn_revnum_t rev,
99                    apr_pool_t *pool);
100
101/* Return the path of the pack-related file that for revision REV in FS.
102 * KIND specifies the file name base, e.g. "manifest" or "pack".
103 * The result will be allocated in POOL.
104 */
105const char *
106svn_fs_fs__path_rev_packed(svn_fs_t *fs,
107                           svn_revnum_t rev,
108                           const char *kind,
109                           apr_pool_t *pool);
110
111/* Return the full path of the "txn-current" file in FS.
112 * The result will be allocated in POOL.
113 */
114const char *
115svn_fs_fs__path_txn_current(svn_fs_t *fs,
116                            apr_pool_t *pool);
117
118/* Return the full path of the "txn-current-lock" file in FS.
119 * The result will be allocated in POOL.
120 */
121const char *
122svn_fs_fs__path_txn_current_lock(svn_fs_t *fs,
123                                 apr_pool_t *pool);
124
125/* Return the full path of the global write lock file in FS.
126 * The result will be allocated in POOL.
127 */
128const char *
129svn_fs_fs__path_lock(svn_fs_t *fs,
130                     apr_pool_t *pool);
131
132/* Return the full path of the pack operation lock file in FS.
133 * The result will be allocated in POOL.
134 */
135const char *
136svn_fs_fs__path_pack_lock(svn_fs_t *fs,
137                          apr_pool_t *pool);
138
139/* Return the full path of the revprop generation file in FS.
140 * Allocate the result in POOL.
141 */
142const char *
143svn_fs_fs__path_revprop_generation(svn_fs_t *fs,
144                                   apr_pool_t *pool);
145
146/* Return the full path of the revision properties pack shard directory
147 * that will contain the packed properties of revision REV in FS.
148 * Allocate the result in POOL.
149 */
150const char *
151svn_fs_fs__path_revprops_pack_shard(svn_fs_t *fs,
152                                    svn_revnum_t rev,
153                                    apr_pool_t *pool);
154
155/* Set *PATH to the path of REV in FS, whether in a pack file or not.
156   Allocate *PATH in POOL.
157
158   Note: If the caller does not have the write lock on FS, then the path is
159   not guaranteed to be correct or to remain correct after the function
160   returns, because the revision might become packed before or after this
161   call.  If a file exists at that path, then it is correct; if not, then
162   the caller should call update_min_unpacked_rev() and re-try once. */
163const char *
164svn_fs_fs__path_rev_absolute(svn_fs_t *fs,
165                             svn_revnum_t rev,
166                             apr_pool_t *pool);
167
168/* Return the full path of the revision properties shard directory that
169 * will contain the properties of revision REV in FS.
170 * Allocate the result in POOL.
171 */
172const char *
173svn_fs_fs__path_revprops_shard(svn_fs_t *fs,
174                               svn_revnum_t rev,
175                               apr_pool_t *pool);
176
177/* Return the full path of the non-packed revision properties file that
178 * contains the props for revision REV in FS.  Allocate the result in POOL.
179 */
180const char *
181svn_fs_fs__path_revprops(svn_fs_t *fs,
182                         svn_revnum_t rev,
183                         apr_pool_t *pool);
184
185/* Return the path of the file storing the oldest non-packed revision in FS.
186 * The result will be allocated in POOL.
187 */
188const char *
189svn_fs_fs__path_min_unpacked_rev(svn_fs_t *fs,
190                                 apr_pool_t *pool);
191
192/* Return the path of the 'transactions' directory in FS.
193 * The result will be allocated in POOL.
194 */
195const char *
196svn_fs_fs__path_txns_dir(svn_fs_t *fs,
197                         apr_pool_t *pool);
198
199/* Return the path of the directory containing the transaction TXN_ID in FS.
200 * The result will be allocated in POOL.
201 */
202const char *
203svn_fs_fs__path_txn_dir(svn_fs_t *fs,
204                        const svn_fs_fs__id_part_t *txn_id,
205                        apr_pool_t *pool);
206
207/* Return the path of the 'txn-protorevs' directory in FS, even if that
208 * folder may not exist in FS.  The result will be allocated in POOL.
209 */
210const char *
211svn_fs_fs__path_txn_proto_revs(svn_fs_t *fs,
212                               apr_pool_t *pool);
213
214/* Return the path of the proto-revision file for transaction TXN_ID in FS.
215 * The result will be allocated in POOL.
216 */
217const char *
218svn_fs_fs__path_txn_proto_rev(svn_fs_t *fs,
219                              const svn_fs_fs__id_part_t *txn_id,
220                              apr_pool_t *pool);
221
222/* Return the path of the proto-revision lock file for transaction TXN_ID
223 * in FS.  The result will be allocated in POOL.
224 */
225const char *
226svn_fs_fs__path_txn_proto_rev_lock(svn_fs_t *fs,
227                                   const svn_fs_fs__id_part_t *txn_id,
228                                   apr_pool_t *pool);
229
230/* Return the path of the file containing the in-transaction node revision
231 * identified by ID in FS.  The result will be allocated in POOL.
232 */
233const char *
234svn_fs_fs__path_txn_node_rev(svn_fs_t *fs,
235                             const svn_fs_id_t *id,
236                             apr_pool_t *pool);
237
238/* Return the path of the file containing the in-transaction properties of
239 * the node identified by ID in FS.  The result will be allocated in POOL.
240 */
241const char *
242svn_fs_fs__path_txn_node_props(svn_fs_t *fs,
243                               const svn_fs_id_t *id,
244                               apr_pool_t *pool);
245
246/* Return the path of the file containing the directory entries of the
247 * in-transaction directory node identified by ID in FS.
248 * The result will be allocated in POOL.
249 */
250const char *
251svn_fs_fs__path_txn_node_children(svn_fs_t *fs,
252                                  const svn_fs_id_t *id,
253                                  apr_pool_t *pool);
254
255/* Return the path of the file containing the log-to-phys index for
256 * the transaction identified by TXN_ID in FS.
257 * The result will be allocated in POOL.
258 */
259const char*
260svn_fs_fs__path_l2p_proto_index(svn_fs_t *fs,
261                                const svn_fs_fs__id_part_t *txn_id,
262                                apr_pool_t *pool);
263
264/* Return the path of the file containing the phys-to-log index for
265 * the transaction identified by TXN_ID in FS.
266 * The result will be allocated in POOL.
267 */
268const char*
269svn_fs_fs__path_p2l_proto_index(svn_fs_t *fs,
270                                const svn_fs_fs__id_part_t *txn_id,
271                                apr_pool_t *pool);
272
273/* Return the path of the file containing item_index counter for
274 * the transaction identified by TXN_ID in FS.
275 * The result will be allocated in POOL.
276 */
277const char *
278svn_fs_fs__path_txn_item_index(svn_fs_t *fs,
279                               const svn_fs_fs__id_part_t *txn_id,
280                               apr_pool_t *pool);
281
282/* Return the path of the file containing the node origins cachs for
283 * the given NODE_ID in FS.  The result will be allocated in POOL.
284 */
285const char *
286svn_fs_fs__path_node_origin(svn_fs_t *fs,
287                            const svn_fs_fs__id_part_t *node_id,
288                            apr_pool_t *pool);
289
290/* Set *MIN_UNPACKED_REV to the integer value read from the file returned
291 * by #svn_fs_fs__path_min_unpacked_rev() for FS.
292 * Use POOL for temporary allocations.
293 */
294svn_error_t *
295svn_fs_fs__read_min_unpacked_rev(svn_revnum_t *min_unpacked_rev,
296                                 svn_fs_t *fs,
297                                 apr_pool_t *pool);
298
299/* Check that BUF, a nul-terminated buffer of text from file PATH,
300   contains only digits at OFFSET and beyond, raising an error if not.
301   TITLE contains a user-visible description of the file, usually the
302   short file name.
303
304   Uses POOL for temporary allocation. */
305svn_error_t *
306svn_fs_fs__check_file_buffer_numeric(const char *buf,
307                                     apr_off_t offset,
308                                     const char *path,
309                                     const char *title,
310                                     apr_pool_t *pool);
311
312/* Re-read the MIN_UNPACKED_REV member of FS from disk.
313 * Use POOL for temporary allocations.
314 */
315svn_error_t *
316svn_fs_fs__update_min_unpacked_rev(svn_fs_t *fs,
317                                   apr_pool_t *pool);
318
319/* Atomically update the 'min-unpacked-rev' file in FS to hold the specifed
320 * REVNUM.  Perform temporary allocations in SCRATCH_POOL.
321 */
322svn_error_t *
323svn_fs_fs__write_min_unpacked_rev(svn_fs_t *fs,
324                                  svn_revnum_t revnum,
325                                  apr_pool_t *scratch_pool);
326
327/* Set *REV, *NEXT_NODE_ID and *NEXT_COPY_ID to the values read from the
328 * 'current' file.  For new FS formats, which only store the youngest
329 * revision, set the *NEXT_NODE_ID and *NEXT_COPY_ID to 0.  Perform
330 * temporary allocations in POOL.
331 */
332svn_error_t *
333svn_fs_fs__read_current(svn_revnum_t *rev,
334                        apr_uint64_t *next_node_id,
335                        apr_uint64_t *next_copy_id,
336                        svn_fs_t *fs,
337                        apr_pool_t *pool);
338
339/* Atomically update the 'current' file to hold the specifed REV,
340   NEXT_NODE_ID, and NEXT_COPY_ID.  (The two next-ID parameters are
341   ignored and may be 0 if the FS format does not use them.)
342   Perform temporary allocations in POOL. */
343svn_error_t *
344svn_fs_fs__write_current(svn_fs_t *fs,
345                         svn_revnum_t rev,
346                         apr_uint64_t next_node_id,
347                         apr_uint64_t next_copy_id,
348                         apr_pool_t *pool);
349
350/* Read the file at PATH and return its content in *CONTENT. *CONTENT will
351 * not be modified unless the whole file was read successfully.
352 *
353 * ESTALE, EIO and ENOENT will not cause this function to return an error
354 * unless LAST_ATTEMPT has been set.  If MISSING is not NULL, indicate
355 * missing files (ENOENT) there.
356 *
357 * Use POOL for allocations.
358 */
359svn_error_t *
360svn_fs_fs__try_stringbuf_from_file(svn_stringbuf_t **content,
361                                   svn_boolean_t *missing,
362                                   const char *path,
363                                   svn_boolean_t last_attempt,
364                                   apr_pool_t *pool);
365
366/* Read the file FNAME and store the contents in *BUF.
367   Allocations are performed in POOL. */
368svn_error_t *
369svn_fs_fs__read_content(svn_stringbuf_t **content,
370                        const char *fname,
371                        apr_pool_t *pool);
372
373/* Reads a line from STREAM and converts it to a 64 bit integer to be
374 * returned in *RESULT.  If we encounter eof, set *HIT_EOF and leave
375 * *RESULT unchanged.  If HIT_EOF is NULL, EOF causes an "corrupt FS"
376 * error return.
377 * SCRATCH_POOL is used for temporary allocations.
378 */
379svn_error_t *
380svn_fs_fs__read_number_from_stream(apr_int64_t *result,
381                                   svn_boolean_t *hit_eof,
382                                   svn_stream_t *stream,
383                                   apr_pool_t *scratch_pool);
384
385/* Move a file into place from OLD_FILENAME in the transactions
386   directory to its final location NEW_FILENAME in the repository.  On
387   Unix, match the permissions of the new file to the permissions of
388   PERMS_REFERENCE.  Temporary allocations are from POOL.
389
390   This function almost duplicates svn_io_file_move(), but it tries to
391   guarantee a flush if FLUSH_TO_DISK is non-zero. */
392svn_error_t *
393svn_fs_fs__move_into_place(const char *old_filename,
394                           const char *new_filename,
395                           const char *perms_reference,
396                           svn_boolean_t flush_to_disk,
397                           apr_pool_t *pool);
398
399/* Return TRUE, iff FS uses logical addressing. */
400svn_boolean_t
401svn_fs_fs__use_log_addressing(svn_fs_t *fs);
402
403#endif
404