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