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. */ 70 svn_boolean_t 71 svn_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. */ 75 svn_boolean_t 76 svn_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. */ 81 svn_revnum_t 82 svn_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 */ 88 const char * 89 svn_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 */ 96 const char * 97 svn_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 */ 105 const char * 106 svn_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 */ 114 const char * 115 svn_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 */ 121 const char * 122 svn_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 */ 128 const char * 129 svn_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 */ 135 const char * 136 svn_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 */ 142 const char * 143 svn_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 */ 150 const char * 151 svn_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. */ 163 const char * 164 svn_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 */ 172 const char * 173 svn_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 */ 180 const char * 181 svn_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 */ 188 const char * 189 svn_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 */ 195 const char * 196 svn_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 */ 202 const char * 203 svn_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 */ 210 const char * 211 svn_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 */ 217 const char * 218 svn_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 */ 225 const char * 226 svn_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 */ 233 const char * 234 svn_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 */ 241 const char * 242 svn_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 */ 250 const char * 251 svn_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 */ 259 const char* 260 svn_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 */ 268 const char* 269 svn_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 */ 277 const char * 278 svn_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 */ 285 const char * 286 svn_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 */ 294 svn_error_t * 295 svn_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. */ 305 svn_error_t * 306 svn_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 */ 315 svn_error_t * 316 svn_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 */ 322 svn_error_t * 323 svn_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 */ 332 svn_error_t * 333 svn_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. */ 343 svn_error_t * 344 svn_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 */ 359 svn_error_t * 360 svn_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. */ 368 svn_error_t * 369 svn_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 */ 379 svn_error_t * 380 svn_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. */ 392 svn_error_t * 393 svn_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. */ 400 svn_boolean_t 401 svn_fs_fs__use_log_addressing(svn_fs_t *fs); 402 403 #endif 404