1/* util.h --- utility functions for FSX 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_X_UTIL_H
24#define SVN_LIBSVN_FS_X_UTIL_H
25
26#include "svn_fs.h"
27#include "id.h"
28#include "batch_fsync.h"
29
30/* Functions for dealing with recoverable errors on mutable files
31 *
32 * Revprops, current, and txn-current files are mutable; that is, they
33 * change as part of normal fsx operation, in constrat to revs files, or
34 * the format file, which are written once at create (or upgrade) time.
35 * When more than one host writes to the same repository, we will
36 * sometimes see these recoverable errors when accesssing these files.
37 *
38 * These errors all relate to NFS, and thus we only use this retry code if
39 * ESTALE is defined.
40 *
41 ** ESTALE
42 *
43 * In NFS v3 and under, the server doesn't track opened files.  If you
44 * unlink(2) or rename(2) a file held open by another process *on the
45 * same host*, that host's kernel typically renames the file to
46 * .nfsXXXX and automatically deletes that when it's no longer open,
47 * but this behavior is not required.
48 *
49 * For obvious reasons, this does not work *across hosts*.  No one
50 * knows about the opened file; not the server, and not the deleting
51 * client.  So the file vanishes, and the reader gets stale NFS file
52 * handle.
53 *
54 ** EIO, ENOENT
55 *
56 * Some client implementations (at least the 2.6.18.5 kernel that ships
57 * with Ubuntu Dapper) sometimes give spurious ENOENT (only on open) or
58 * even EIO errors when trying to read these files that have been renamed
59 * over on some other host.
60 *
61 ** Solution
62 *
63 * Try open and read of such files in try_stringbuf_from_file().  Call
64 * this function within a loop of SVN_FS_X__RECOVERABLE_RETRY_COUNT
65 * iterations (though, realistically, the second try will succeed).
66 */
67
68#define SVN_FS_X__RECOVERABLE_RETRY_COUNT 10
69
70/* Pathname helper functions */
71
72/* Return TRUE is REV is packed in FS, FALSE otherwise. */
73svn_boolean_t
74svn_fs_x__is_packed_rev(svn_fs_t *fs,
75                        svn_revnum_t rev);
76
77/* Return TRUE is REV is packed in FS, FALSE otherwise. */
78svn_boolean_t
79svn_fs_x__is_packed_revprop(svn_fs_t *fs,
80                            svn_revnum_t rev);
81
82/* Return the first revision in the pack / rev file containing REV in
83 * filesystem FS.  For non-packed revs, this will simply be REV. */
84svn_revnum_t
85svn_fs_x__packed_base_rev(svn_fs_t *fs,
86                          svn_revnum_t rev);
87
88/* Return the number of revisions in the pack / rev file in FS that contains
89 * revision REV. */
90svn_revnum_t
91svn_fs_x__pack_size(svn_fs_t *fs, svn_revnum_t rev);
92
93/* Return the full path of the "format" file in FS.
94 * The result will be allocated in RESULT_POOL.
95 */
96const char *
97svn_fs_x__path_format(svn_fs_t *fs,
98                      apr_pool_t *result_pool);
99
100/* Return the path to the 'current' file in FS.
101   Perform allocation in RESULT_POOL. */
102const char *
103svn_fs_x__path_current(svn_fs_t *fs,
104                       apr_pool_t *result_pool);
105
106/* Return the path to the 'next' file in FS.
107   Perform allocation in RESULT_POOL. */
108const char *
109svn_fs_x__path_next(svn_fs_t *fs,
110                    apr_pool_t *result_pool);
111
112/* Return the full path of the "uuid" file in FS.
113 * The result will be allocated in RESULT_POOL.
114 */
115const char *
116svn_fs_x__path_uuid(svn_fs_t *fs,
117                    apr_pool_t *result_pool);
118
119/* Return the full path of the "txn-current" file in FS.
120 * The result will be allocated in RESULT_POOL.
121 */
122const char *
123svn_fs_x__path_txn_current(svn_fs_t *fs,
124                           apr_pool_t *result_pool);
125
126/* Return the full path of the "txn-current-lock" file in FS.
127 * The result will be allocated in RESULT_POOL.
128 */
129const char *
130svn_fs_x__path_txn_current_lock(svn_fs_t *fs,
131                                apr_pool_t *result_pool);
132
133/* Return the full path of the global write lock file in FS.
134 * The result will be allocated in RESULT_POOL.
135 */
136const char *
137svn_fs_x__path_lock(svn_fs_t *fs,
138                    apr_pool_t *result_pool);
139
140/* Return the full path of the pack operation lock file in FS.
141 * The result will be allocated in RESULT_POOL.
142 */
143const char *
144svn_fs_x__path_pack_lock(svn_fs_t *fs,
145                         apr_pool_t *result_pool);
146
147/* Return the full path of the revprop generation file in FS.
148 * Allocate the result in RESULT_POOL.
149 */
150const char *
151svn_fs_x__path_revprop_generation(svn_fs_t *fs,
152                                  apr_pool_t *result_pool);
153
154/* Return the path of the pack-related file that for revision REV in FS.
155 * KIND specifies the file name base, e.g. "pack".
156 * The result will be allocated in RESULT_POOL.
157 */
158const char *
159svn_fs_x__path_rev_packed(svn_fs_t *fs,
160                          svn_revnum_t rev,
161                          const char *kind,
162                          apr_pool_t *result_pool);
163
164/* Return the full path of the rev shard directory that will contain
165 * revision REV in FS.  Allocate the result in RESULT_POOL.
166 */
167const char *
168svn_fs_x__path_shard(svn_fs_t *fs,
169                     svn_revnum_t rev,
170                     apr_pool_t *result_pool);
171
172/* Return the full path of the non-packed rev file containing revision REV
173 * in FS.  Allocate the result in RESULT_POOL.
174 */
175const char *
176svn_fs_x__path_rev(svn_fs_t *fs,
177                   svn_revnum_t rev,
178                   apr_pool_t *result_pool);
179
180/* Set *PATH to the path of REV in FS, whether in a pack file or not.
181   Allocate *PATH in RESULT_POOL.
182
183   Note: If the caller does not have the write lock on FS, then the path is
184   not guaranteed to be correct or to remain correct after the function
185   returns, because the revision might become packed before or after this
186   call.  If a file exists at that path, then it is correct; if not, then
187   the caller should call update_min_unpacked_rev() and re-try once. */
188const char *
189svn_fs_x__path_rev_absolute(svn_fs_t *fs,
190                            svn_revnum_t rev,
191                            apr_pool_t *result_pool);
192
193/* Return the full path of the pack shard directory that will contain the
194 * packed revision REV in FS.  Allocate the result in RESULT_POOL.
195 */
196const char *
197svn_fs_x__path_pack_shard(svn_fs_t *fs,
198                          svn_revnum_t rev,
199                          apr_pool_t *result_pool);
200
201/* Return the full path of the non-packed revision properties file that
202 * contains the props for revision REV in FS.
203 * Allocate the result in RESULT_POOL.
204 */
205const char *
206svn_fs_x__path_revprops(svn_fs_t *fs,
207                        svn_revnum_t rev,
208                        apr_pool_t *result_pool);
209
210/* Convert the TXN_ID into a string, allocated from RESULT_POOL.
211 */
212const char *
213svn_fs_x__txn_name(svn_fs_x__txn_id_t txn_id,
214                   apr_pool_t *result_pool);
215
216/* Convert TXN_NAME into an ID and return it in *TXN_ID. */
217svn_error_t *
218svn_fs_x__txn_by_name(svn_fs_x__txn_id_t *txn_id,
219                      const char *txn_name);
220
221/* Return the path of the directory containing the transaction TXN_ID in FS.
222 * The result will be allocated in RESULT_POOL.
223 */
224const char *
225svn_fs_x__path_txn_dir(svn_fs_t *fs,
226                       svn_fs_x__txn_id_t txn_id,
227                       apr_pool_t *result_pool);
228
229/* Return the path of the 'transactions' directory in FS.
230 * The result will be allocated in RESULT_POOL.
231 */
232const char *
233svn_fs_x__path_txns_dir(svn_fs_t *fs,
234                        apr_pool_t *result_pool);
235
236/* Return the name of the sha1->rep mapping file in transaction TXN_ID
237 * within FS for the given SHA1 checksum.  Use POOL for allocations.
238 */
239const char *
240svn_fs_x__path_txn_sha1(svn_fs_t *fs,
241                        svn_fs_x__txn_id_t txn_id,
242                        const unsigned char *sha1,
243                        apr_pool_t *pool);
244
245/* Return the path of the 'txn-protorevs' directory in FS, even if that
246 * folder may not exist in FS.  The result will be allocated in RESULT_POOL.
247 */
248const char *
249svn_fs_x__path_txn_proto_revs(svn_fs_t *fs,
250                              apr_pool_t *result_pool);
251
252/* Return the path of the changes file for transaction TXN_ID in FS.
253 * The result will be allocated in RESULT_POOL.
254 */
255const char *
256svn_fs_x__path_txn_changes(svn_fs_t *fs,
257                           svn_fs_x__txn_id_t txn_id,
258                           apr_pool_t *result_pool);
259
260/* Return the path of the file containing the log-to-phys index for
261 * the transaction identified by TXN_ID in FS.
262 * The result will be allocated in RESULT_POOL.
263 */
264const char*
265svn_fs_x__path_l2p_proto_index(svn_fs_t *fs,
266                               svn_fs_x__txn_id_t txn_id,
267                               apr_pool_t *result_pool);
268
269/* Return the path of the file containing the phys-to-log index for
270 * the transaction identified by TXN_ID in FS.
271 * The result will be allocated in RESULT_POOL.
272 */
273const char*
274svn_fs_x__path_p2l_proto_index(svn_fs_t *fs,
275                               svn_fs_x__txn_id_t txn_id,
276                               apr_pool_t *result_pool);
277
278/* Return the path of the file containing the transaction properties for
279 * the transaction identified by TXN_ID in FS.
280 * The result will be allocated in RESULT_POOL.
281 */
282const char *
283svn_fs_x__path_txn_props(svn_fs_t *fs,
284                         svn_fs_x__txn_id_t txn_id,
285                         apr_pool_t *result_pool);
286
287/* Return the path of the file containing the node and copy ID counters for
288 * the transaction identified by TXN_ID in FS.
289 * The result will be allocated in RESULT_POOL.
290 */
291const char *
292svn_fs_x__path_txn_next_ids(svn_fs_t *fs,
293                            svn_fs_x__txn_id_t txn_id,
294                            apr_pool_t *result_pool);
295
296/* Return the path of the file storing the oldest non-packed revision in FS.
297 * The result will be allocated in RESULT_POOL.
298 */
299const char *
300svn_fs_x__path_min_unpacked_rev(svn_fs_t *fs,
301                                apr_pool_t *result_pool);
302
303/* Return the path of the file containing item_index counter for
304 * the transaction identified by TXN_ID in FS.
305 * The result will be allocated in RESULT_POOL.
306 */
307const char *
308svn_fs_x__path_txn_item_index(svn_fs_t *fs,
309                              svn_fs_x__txn_id_t txn_id,
310                              apr_pool_t *result_pool);
311
312/* Return the path of the proto-revision file for transaction TXN_ID in FS.
313 * The result will be allocated in RESULT_POOL.
314 */
315const char *
316svn_fs_x__path_txn_proto_rev(svn_fs_t *fs,
317                             svn_fs_x__txn_id_t txn_id,
318                             apr_pool_t *result_pool);
319
320/* Return the path of the proto-revision lock file for transaction TXN_ID
321 * in FS.  The result will be allocated in RESULT_POOL.
322 */
323const char *
324svn_fs_x__path_txn_proto_rev_lock(svn_fs_t *fs,
325                                  svn_fs_x__txn_id_t txn_id,
326                                  apr_pool_t *result_pool);
327
328/* Return the path of the file containing the in-transaction node revision
329 * identified by ID in FS.
330 * The result will be allocated in RESULT_POOL, temporaries in SCRATCH_POOL.
331 */
332const char *
333svn_fs_x__path_txn_node_rev(svn_fs_t *fs,
334                            const svn_fs_x__id_t *id,
335                            apr_pool_t *result_pool,
336                            apr_pool_t *scratch_pool);
337
338/* Return the path of the file containing the in-transaction properties of
339 * the node identified by ID in FS.
340 * The result will be allocated in RESULT_POOL, temporaries in SCRATCH_POOL.
341 */
342const char *
343svn_fs_x__path_txn_node_props(svn_fs_t *fs,
344                              const svn_fs_x__id_t *id,
345                              apr_pool_t *result_pool,
346                              apr_pool_t *scratch_pool);
347
348/* Return the path of the file containing the directory entries of the
349 * in-transaction directory node identified by ID in FS.
350 * The result will be allocated in RESULT_POOL, temporaries in SCRATCH_POOL.
351 */
352const char *
353svn_fs_x__path_txn_node_children(svn_fs_t *fs,
354                                 const svn_fs_x__id_t *id,
355                                 apr_pool_t *result_pool,
356                                 apr_pool_t *scratch_pool);
357
358/* Check that BUF, a nul-terminated buffer of text from file PATH,
359   contains only digits at OFFSET and beyond, raising an error if not.
360   TITLE contains a user-visible description of the file, usually the
361   short file name.
362
363   Uses SCRATCH_POOL for temporary allocation. */
364svn_error_t *
365svn_fs_x__check_file_buffer_numeric(const char *buf,
366                                    apr_off_t offset,
367                                    const char *path,
368                                    const char *title,
369                                    apr_pool_t *scratch_pool);
370
371/* Set *MIN_UNPACKED_REV to the integer value read from the file returned
372 * by #svn_fs_x__path_min_unpacked_rev() for FS.
373 * Use SCRATCH_POOL for temporary allocations.
374 */
375svn_error_t *
376svn_fs_x__read_min_unpacked_rev(svn_revnum_t *min_unpacked_rev,
377                                svn_fs_t *fs,
378                                apr_pool_t *scratch_pool);
379
380/* Re-read the MIN_UNPACKED_REV member of FS from disk.
381 * Use SCRATCH_POOL for temporary allocations.
382 */
383svn_error_t *
384svn_fs_x__update_min_unpacked_rev(svn_fs_t *fs,
385                                  apr_pool_t *scratch_pool);
386
387/* Atomically update the 'min-unpacked-rev' file in FS to hold the specifed
388 * REVNUM.  Perform temporary allocations in SCRATCH_POOL.
389 */
390svn_error_t *
391svn_fs_x__write_min_unpacked_rev(svn_fs_t *fs,
392                                 svn_revnum_t revnum,
393                                 apr_pool_t *scratch_pool);
394
395/* Set *REV to the value read from the 'current' file.  Perform temporary
396 * allocations in SCRATCH_POOL.
397 */
398svn_error_t *
399svn_fs_x__read_current(svn_revnum_t *rev,
400                       svn_fs_t *fs,
401                       apr_pool_t *scratch_pool);
402
403/* Atomically update the 'current' file to hold the specifed REV.
404   Perform temporary allocations in SCRATCH_POOL. */
405svn_error_t *
406svn_fs_x__write_current(svn_fs_t *fs,
407                        svn_revnum_t rev,
408                        apr_pool_t *scratch_pool);
409
410/* Read the file at PATH and return its content in *CONTENT, allocated in
411 * RESULT_POOL.  *CONTENT will not be modified unless the whole file was
412 * read successfully.
413 *
414 * ESTALE, EIO and ENOENT will not cause this function to return an error
415 * unless LAST_ATTEMPT has been set.  If MISSING is not NULL, indicate
416 * missing files (ENOENT) there.
417 */
418svn_error_t *
419svn_fs_x__try_stringbuf_from_file(svn_stringbuf_t **content,
420                                  svn_boolean_t *missing,
421                                  const char *path,
422                                  svn_boolean_t last_attempt,
423                                  apr_pool_t *result_pool);
424
425/* Read the file FNAME and store the contents in *BUF.
426   Allocations are performed in RESULT_POOL. */
427svn_error_t *
428svn_fs_x__read_content(svn_stringbuf_t **content,
429                       const char *fname,
430                       apr_pool_t *result_pool);
431
432/* Reads a line from STREAM and converts it to a 64 bit integer to be
433 * returned in *RESULT.  If we encounter eof, set *HIT_EOF and leave
434 * *RESULT unchanged.  If HIT_EOF is NULL, EOF causes an "corrupt FS"
435 * error return.
436 * SCRATCH_POOL is used for temporary allocations.
437 */
438svn_error_t *
439svn_fs_x__read_number_from_stream(apr_int64_t *result,
440                                  svn_boolean_t *hit_eof,
441                                  svn_stream_t *stream,
442                                  apr_pool_t *scratch_pool);
443
444/* Move a file into place from temporary OLD_FILENAME to its final
445   location NEW_FILENAME, which must be on to the same volume.  Schedule
446   any necessary fsync calls in BATCH.  On Unix, match the permissions
447   of the new file to the permissions of PERMS_REFERENCE.
448
449   Temporary allocations are from SCRATCH_POOL.
450
451   This function almost duplicates svn_io_file_move(), but it tries to
452   guarantee a flush if BATCH->FLUSH_TO_DISK is non-zero. */
453svn_error_t *
454svn_fs_x__move_into_place(const char *old_filename,
455                          const char *new_filename,
456                          const char *perms_reference,
457                          svn_fs_x__batch_fsync_t *batch,
458                          apr_pool_t *scratch_pool);
459
460#endif
461