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