Modified: subversion/branches/pin-externals/subversion/libsvn_fs_x/tree.h URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_fs_x/tree.h?rev=1653578&r1=1653577&r2=1653578&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_fs_x/tree.h (original) +++ subversion/branches/pin-externals/subversion/libsvn_fs_x/tree.h Wed Jan 21 16:22:19 2015 @@ -31,64 +31,65 @@ extern "C" { -/* In POOL, create an instance of a DAG node 1st level cache. - The POOL will be cleared at regular intervals. */ -fs_x_dag_cache_t* -svn_fs_x__create_dag_cache(apr_pool_t *pool); +/* In RESULT_POOL, create an instance of a DAG node 1st level cache. */ +svn_fs_x__dag_cache_t* +svn_fs_x__create_dag_cache(apr_pool_t *result_pool); /* Set *ROOT_P to the root directory of revision REV in filesystem FS. Allocate the structure in POOL. */ -svn_error_t *svn_fs_x__revision_root(svn_fs_root_t **root_p, svn_fs_t *fs, - svn_revnum_t rev, apr_pool_t *pool); +svn_error_t * +svn_fs_x__revision_root(svn_fs_root_t **root_p, + svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *pool); /* Does nothing, but included for Subversion 1.0.x compatibility. */ -svn_error_t *svn_fs_x__deltify(svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool); +svn_error_t * +svn_fs_x__deltify(svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *scratch_pool); /* Commit the transaction TXN as a new revision. Return the new revision in *NEW_REV. If the transaction conflicts with other changes return SVN_ERR_FS_CONFLICT and set *CONFLICT_P to a string that details the cause of the conflict. */ -svn_error_t *svn_fs_x__commit_txn(const char **conflict_p, - svn_revnum_t *new_rev, svn_fs_txn_t *txn, - apr_pool_t *pool); +svn_error_t * +svn_fs_x__commit_txn(const char **conflict_p, + svn_revnum_t *new_rev, + svn_fs_txn_t *txn, + apr_pool_t *pool); /* Set ROOT_P to the root directory of transaction TXN. Allocate the structure in POOL. */ -svn_error_t *svn_fs_x__txn_root(svn_fs_root_t **root_p, svn_fs_txn_t *txn, - apr_pool_t *pool); +svn_error_t * +svn_fs_x__txn_root(svn_fs_root_t **root_p, + svn_fs_txn_t *txn, + apr_pool_t *pool); /* Set KIND_P to the node kind of the node at PATH in ROOT. - Allocate the structure in POOL. */ + Use SCRATCH_POOL for temporary allocations. */ svn_error_t * svn_fs_x__check_path(svn_node_kind_t *kind_p, svn_fs_root_t *root, const char *path, - apr_pool_t *pool); - -/* Implement root_vtable_t.node_id(). */ -svn_error_t * -svn_fs_x__node_id(const svn_fs_id_t **id_p, - svn_fs_root_t *root, - const char *path, - apr_pool_t *pool); + apr_pool_t *scratch_pool); /* Set *REVISION to the revision in which PATH under ROOT was created. - Use POOL for any temporary allocations. If PATH is in an + Use SCRATCH_POOL for any temporary allocations. If PATH is in an uncommitted transaction, *REVISION will be set to SVN_INVALID_REVNUM. */ svn_error_t * svn_fs_x__node_created_rev(svn_revnum_t *revision, svn_fs_root_t *root, const char *path, - apr_pool_t *pool); + apr_pool_t *scratch_pool); /* Verify metadata for ROOT. ### Currently only implemented for revision roots. */ svn_error_t * svn_fs_x__verify_root(svn_fs_root_t *root, - apr_pool_t *pool); + apr_pool_t *scratch_pool); svn_error_t * svn_fs_x__info_format(int *fs_format,
Modified: subversion/branches/pin-externals/subversion/libsvn_fs_x/util.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_fs_x/util.c?rev=1653578&r1=1653577&r2=1653578&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_fs_x/util.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_fs_x/util.c Wed Jan 21 16:22:19 2015 @@ -55,7 +55,7 @@ are likely some errors because of that. svn_boolean_t svn_fs_x__is_packed_rev(svn_fs_t *fs, svn_revnum_t rev) { - fs_x_data_t *ffd = fs->fsap_data; + svn_fs_x__data_t *ffd = fs->fsap_data; return (rev < ffd->min_unpacked_rev); } @@ -64,7 +64,7 @@ svn_fs_x__is_packed_rev(svn_fs_t *fs, sv svn_boolean_t svn_fs_x__is_packed_revprop(svn_fs_t *fs, svn_revnum_t rev) { - fs_x_data_t *ffd = fs->fsap_data; + svn_fs_x__data_t *ffd = fs->fsap_data; /* rev 0 will not be packed */ return (rev < ffd->min_unpacked_rev) && (rev != 0); @@ -73,7 +73,7 @@ svn_fs_x__is_packed_revprop(svn_fs_t *fs svn_revnum_t svn_fs_x__packed_base_rev(svn_fs_t *fs, svn_revnum_t rev) { - fs_x_data_t *ffd = fs->fsap_data; + svn_fs_x__data_t *ffd = fs->fsap_data; return rev < ffd->min_unpacked_rev ? rev - (rev % ffd->max_files_per_dir) @@ -83,143 +83,173 @@ svn_fs_x__packed_base_rev(svn_fs_t *fs, svn_revnum_t svn_fs_x__pack_size(svn_fs_t *fs, svn_revnum_t rev) { - fs_x_data_t *ffd = fs->fsap_data; + svn_fs_x__data_t *ffd = fs->fsap_data; return rev < ffd->min_unpacked_rev ? ffd->max_files_per_dir : 1; } const char * -svn_fs_x__path_format(svn_fs_t *fs, apr_pool_t *pool) +svn_fs_x__path_format(svn_fs_t *fs, + apr_pool_t *result_pool) { - return svn_dirent_join(fs->path, PATH_FORMAT, pool); + return svn_dirent_join(fs->path, PATH_FORMAT, result_pool); } const char * -svn_fs_x__path_uuid(svn_fs_t *fs, apr_pool_t *pool) +svn_fs_x__path_uuid(svn_fs_t *fs, + apr_pool_t *result_pool) { - return svn_dirent_join(fs->path, PATH_UUID, pool); + return svn_dirent_join(fs->path, PATH_UUID, result_pool); } const char * -svn_fs_x__path_current(svn_fs_t *fs, apr_pool_t *pool) +svn_fs_x__path_current(svn_fs_t *fs, + apr_pool_t *result_pool) { - return svn_dirent_join(fs->path, PATH_CURRENT, pool); + return svn_dirent_join(fs->path, PATH_CURRENT, result_pool); } const char * -svn_fs_x__path_txn_current(svn_fs_t *fs, apr_pool_t *pool) +svn_fs_x__path_txn_current(svn_fs_t *fs, + apr_pool_t *result_pool) { - return svn_dirent_join(fs->path, PATH_TXN_CURRENT, pool); + return svn_dirent_join(fs->path, PATH_TXN_CURRENT, + result_pool); } const char * -svn_fs_x__path_txn_current_lock(svn_fs_t *fs, apr_pool_t *pool) +svn_fs_x__path_txn_current_lock(svn_fs_t *fs, + apr_pool_t *result_pool) { - return svn_dirent_join(fs->path, PATH_TXN_CURRENT_LOCK, pool); + return svn_dirent_join(fs->path, PATH_TXN_CURRENT_LOCK, result_pool); } const char * -svn_fs_x__path_lock(svn_fs_t *fs, apr_pool_t *pool) +svn_fs_x__path_lock(svn_fs_t *fs, + apr_pool_t *result_pool) { - return svn_dirent_join(fs->path, PATH_LOCK_FILE, pool); + return svn_dirent_join(fs->path, PATH_LOCK_FILE, result_pool); } const char * svn_fs_x__path_pack_lock(svn_fs_t *fs, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_dirent_join(fs->path, PATH_PACK_LOCK_FILE, pool); + return svn_dirent_join(fs->path, PATH_PACK_LOCK_FILE, result_pool); } const char * -svn_fs_x__path_revprop_generation(svn_fs_t *fs, apr_pool_t *pool) +svn_fs_x__path_revprop_generation(svn_fs_t *fs, + apr_pool_t *result_pool) { - return svn_dirent_join(fs->path, PATH_REVPROP_GENERATION, pool); + return svn_dirent_join(fs->path, PATH_REVPROP_GENERATION, result_pool); +} + +/* Return the full path of the file FILENAME within revision REV's shard in + * FS. If FILENAME is NULL, return the shard directory directory itself. + * REVPROPS indicates the parent of the shard parent folder ("revprops" or + * "revs"). PACKED says whether we want the packed shard's name. + * + * Allocate the result in RESULT_POOL. + */static const char* +construct_shard_sub_path(svn_fs_t *fs, + svn_revnum_t rev, + svn_boolean_t revprops, + svn_boolean_t packed, + const char *filename, + apr_pool_t *result_pool) +{ + svn_fs_x__data_t *ffd = fs->fsap_data; + char buffer[SVN_INT64_BUFFER_SIZE + sizeof(PATH_EXT_PACKED_SHARD)] = { 0 }; + + /* Select the appropriate parent path constant. */ + const char *parent = revprops ? PATH_REVPROPS_DIR : PATH_REVS_DIR; + + /* String containing the shard number. */ + apr_size_t len = svn__i64toa(buffer, rev / ffd->max_files_per_dir); + + /* Append the suffix. Limit it to the buffer size (should never hit it). */ + if (packed) + strncpy(buffer + len, PATH_EXT_PACKED_SHARD, sizeof(buffer) - len - 1); + + /* This will also work for NULL FILENAME as well. */ + return svn_dirent_join_many(result_pool, fs->path, parent, buffer, + filename, SVN_VA_NULL); } const char * -svn_fs_x__path_rev_packed(svn_fs_t *fs, svn_revnum_t rev, const char *kind, - apr_pool_t *pool) +svn_fs_x__path_rev_packed(svn_fs_t *fs, + svn_revnum_t rev, + const char *kind, + apr_pool_t *result_pool) { - fs_x_data_t *ffd = fs->fsap_data; assert(svn_fs_x__is_packed_rev(fs, rev)); - - return svn_dirent_join_many(pool, fs->path, PATH_REVS_DIR, - apr_psprintf(pool, - "%ld" PATH_EXT_PACKED_SHARD, - rev / ffd->max_files_per_dir), - kind, SVN_VA_NULL); + return construct_shard_sub_path(fs, rev, FALSE, TRUE, kind, result_pool); } const char * -svn_fs_x__path_rev_shard(svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *pool) +svn_fs_x__path_rev_shard(svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool) { - fs_x_data_t *ffd = fs->fsap_data; - return svn_dirent_join_many(pool, fs->path, PATH_REVS_DIR, - apr_psprintf(pool, "%ld", - rev / ffd->max_files_per_dir), - SVN_VA_NULL); + return construct_shard_sub_path(fs, rev, FALSE, FALSE, NULL, result_pool); } const char * -svn_fs_x__path_rev(svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *pool) +svn_fs_x__path_rev(svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool) { - assert(! svn_fs_x__is_packed_rev(fs, rev)); + char buffer[SVN_INT64_BUFFER_SIZE]; + svn__i64toa(buffer, rev); - return svn_dirent_join(svn_fs_x__path_rev_shard(fs, rev, pool), - apr_psprintf(pool, "%ld", rev), - pool); + assert(! svn_fs_x__is_packed_rev(fs, rev)); + return construct_shard_sub_path(fs, rev, FALSE, FALSE, buffer, result_pool); } const char * svn_fs_x__path_rev_absolute(svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return ! svn_fs_x__is_packed_rev(fs, rev) - ? svn_fs_x__path_rev(fs, rev, pool) - : svn_fs_x__path_rev_packed(fs, rev, PATH_PACKED, pool); + return svn_fs_x__is_packed_rev(fs, rev) + ? svn_fs_x__path_rev_packed(fs, rev, PATH_PACKED, result_pool) + : svn_fs_x__path_rev(fs, rev, result_pool); } const char * svn_fs_x__path_revprops_shard(svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool) + apr_pool_t *result_pool) { - fs_x_data_t *ffd = fs->fsap_data; - - return svn_dirent_join_many(pool, fs->path, PATH_REVPROPS_DIR, - apr_psprintf(pool, "%ld", - rev / ffd->max_files_per_dir), - SVN_VA_NULL); + return construct_shard_sub_path(fs, rev, TRUE, FALSE, NULL, result_pool); } const char * svn_fs_x__path_revprops_pack_shard(svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool) + apr_pool_t *result_pool) { - fs_x_data_t *ffd = fs->fsap_data; - - return svn_dirent_join_many(pool, fs->path, PATH_REVPROPS_DIR, - apr_psprintf(pool, "%ld" PATH_EXT_PACKED_SHARD, - rev / ffd->max_files_per_dir), - SVN_VA_NULL); + return construct_shard_sub_path(fs, rev, TRUE, TRUE, NULL, result_pool); } const char * -svn_fs_x__path_revprops(svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *pool) +svn_fs_x__path_revprops(svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool) { - return svn_dirent_join(svn_fs_x__path_revprops_shard(fs, rev, pool), - apr_psprintf(pool, "%ld", rev), - pool); + char buffer[SVN_INT64_BUFFER_SIZE]; + svn__i64toa(buffer, rev); + + assert(! svn_fs_x__is_packed_revprop(fs, rev)); + return construct_shard_sub_path(fs, rev, TRUE, FALSE, buffer, result_pool); } const char * svn_fs_x__txn_name(svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool) { - char *p = apr_palloc(pool, SVN_INT64_BUFFER_SIZE); + char *p = apr_palloc(result_pool, SVN_INT64_BUFFER_SIZE); svn__ui64tobase36(p, txn_id); return p; } @@ -238,35 +268,42 @@ svn_fs_x__txn_by_name(svn_fs_x__txn_id_t return SVN_NO_ERROR; } - -/* Return TO_ADD appended to the C string representation of TXN_ID. - * Allocate the result in POOL. - */ -static const char * -combine_txn_id_string(svn_fs_x__txn_id_t txn_id, - const char *to_add, - apr_pool_t *pool) -{ - return apr_pstrcat(pool, svn_fs_x__txn_name(txn_id, pool), - to_add, SVN_VA_NULL); -} - const char * svn_fs_x__path_txns_dir(svn_fs_t *fs, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_dirent_join(fs->path, PATH_TXNS_DIR, pool); + return svn_dirent_join(fs->path, PATH_TXNS_DIR, result_pool); +} + +/* Return the full path of the file FILENAME within transaction TXN_ID's + * transaction directory in FS. If FILENAME is NULL, return the transaction + * directory itself. + * + * Allocate the result in RESULT_POOL. + */ +static const char * +construct_txn_path(svn_fs_t *fs, + svn_fs_x__txn_id_t txn_id, + const char *filename, + apr_pool_t *result_pool) +{ + /* Construct the transaction directory name without temp. allocations. */ + char buffer[SVN_INT64_BUFFER_SIZE + sizeof(PATH_EXT_TXN)] = { 0 }; + apr_size_t len = svn__ui64tobase36(buffer, txn_id); + strncpy(buffer + len, PATH_EXT_TXN, sizeof(buffer) - len - 1); + + /* If FILENAME is NULL, it will terminate the list of segments + to concatenate. */ + return svn_dirent_join_many(result_pool, fs->path, PATH_TXNS_DIR, + buffer, filename, SVN_VA_NULL); } const char * svn_fs_x__path_txn_dir(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_dirent_join_many(pool, svn_fs_x__path_txns_dir(fs, pool), - combine_txn_id_string(txn_id, PATH_EXT_TXN, - pool), - SVN_VA_NULL); + return construct_txn_path(fs, txn_id, NULL, result_pool); } /* Return the name of the sha1->rep mapping file in transaction TXN_ID @@ -290,144 +327,169 @@ svn_fs_x__path_txn_sha1(svn_fs_t *fs, const char * svn_fs_x__path_txn_changes(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool), - PATH_CHANGES, pool); + return construct_txn_path(fs, txn_id, PATH_CHANGES, result_pool); } const char * svn_fs_x__path_txn_props(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool), - PATH_TXN_PROPS, pool); + return construct_txn_path(fs, txn_id, PATH_TXN_PROPS, result_pool); } const char * svn_fs_x__path_txn_props_final(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool), - PATH_TXN_PROPS_FINAL, pool); + return construct_txn_path(fs, txn_id, PATH_TXN_PROPS_FINAL, result_pool); } const char* svn_fs_x__path_l2p_proto_index(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool), - PATH_INDEX PATH_EXT_L2P_INDEX, pool); + return construct_txn_path(fs, txn_id, PATH_INDEX PATH_EXT_L2P_INDEX, + result_pool); } const char* svn_fs_x__path_p2l_proto_index(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool), - PATH_INDEX PATH_EXT_P2L_INDEX, pool); + return construct_txn_path(fs, txn_id, PATH_INDEX PATH_EXT_P2L_INDEX, + result_pool); } const char * svn_fs_x__path_txn_next_ids(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool), - PATH_NEXT_IDS, pool); + return construct_txn_path(fs, txn_id, PATH_NEXT_IDS, result_pool); } const char * -svn_fs_x__path_min_unpacked_rev(svn_fs_t *fs, apr_pool_t *pool) +svn_fs_x__path_min_unpacked_rev(svn_fs_t *fs, + apr_pool_t *result_pool) { - return svn_dirent_join(fs->path, PATH_MIN_UNPACKED_REV, pool); + return svn_dirent_join(fs->path, PATH_MIN_UNPACKED_REV, result_pool); } const char * svn_fs_x__path_txn_proto_revs(svn_fs_t *fs, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_dirent_join(fs->path, PATH_TXN_PROTOS_DIR, pool); + return svn_dirent_join(fs->path, PATH_TXN_PROTOS_DIR, result_pool); } const char * svn_fs_x__path_txn_item_index(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool), - PATH_TXN_ITEM_INDEX, pool); + return construct_txn_path(fs, txn_id, PATH_TXN_ITEM_INDEX, result_pool); +} + +/* Return the full path of the proto-rev file / lock file for transaction + * TXN_ID in FS. The SUFFIX determines what file (rev / lock) it will be. + * + * Allocate the result in RESULT_POOL. + */ +static const char * +construct_proto_rev_path(svn_fs_t *fs, + svn_fs_x__txn_id_t txn_id, + const char *suffix, + apr_pool_t *result_pool) +{ + /* Construct the file name without temp. allocations. */ + char buffer[SVN_INT64_BUFFER_SIZE + sizeof(PATH_EXT_REV_LOCK)] = { 0 }; + apr_size_t len = svn__ui64tobase36(buffer, txn_id); + strncpy(buffer + len, suffix, sizeof(buffer) - len - 1); + + /* If FILENAME is NULL, it will terminate the list of segments + to concatenate. */ + return svn_dirent_join_many(result_pool, fs->path, PATH_TXN_PROTOS_DIR, + buffer, SVN_VA_NULL); } const char * svn_fs_x__path_txn_proto_rev(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_dirent_join_many(pool, svn_fs_x__path_txn_proto_revs(fs, pool), - combine_txn_id_string(txn_id, PATH_EXT_REV, - pool), - SVN_VA_NULL); + return construct_proto_rev_path(fs, txn_id, PATH_EXT_REV, result_pool); } const char * svn_fs_x__path_txn_proto_rev_lock(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_dirent_join_many(pool, svn_fs_x__path_txn_proto_revs(fs, pool), - combine_txn_id_string(txn_id, - PATH_EXT_REV_LOCK, - pool), - SVN_VA_NULL); + return construct_proto_rev_path(fs, txn_id, PATH_EXT_REV_LOCK, result_pool); +} + +/* Return the full path of the noderev-related file with the extension SUFFIX + * for noderev *ID in transaction TXN_ID in FS. + * + * Allocate the result in RESULT_POOL and temporaries in SCRATCH_POOL. + */ +static const char * +construct_txn_node_path(svn_fs_t *fs, + const svn_fs_x__id_t *id, + const char *suffix, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *filename = svn_fs_x__id_unparse(id, result_pool)->data; + apr_int64_t txn_id = svn_fs_x__get_txn_id(id->change_set); + + return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, scratch_pool), + apr_psprintf(scratch_pool, PATH_PREFIX_NODE "%s%s", + filename, suffix), + result_pool); } const char * svn_fs_x__path_txn_node_rev(svn_fs_t *fs, - const svn_fs_id_t *id, - apr_pool_t *pool) + const svn_fs_x__id_t *id, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - char *filename = (char *)svn_fs_x__id_unparse(id, pool)->data; - *strrchr(filename, '.') = '\0'; - - return svn_dirent_join(svn_fs_x__path_txn_dir(fs, svn_fs_x__id_txn_id(id), - pool), - apr_psprintf(pool, PATH_PREFIX_NODE "%s", - filename), - pool); + return construct_txn_node_path(fs, id, "", result_pool, scratch_pool); } const char * svn_fs_x__path_txn_node_props(svn_fs_t *fs, - const svn_fs_id_t *id, - apr_pool_t *pool) + const svn_fs_x__id_t *id, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - return apr_pstrcat(pool, svn_fs_x__path_txn_node_rev(fs, id, pool), - PATH_EXT_PROPS, SVN_VA_NULL); + return construct_txn_node_path(fs, id, PATH_EXT_PROPS, result_pool, + scratch_pool); } const char * -svn_fs_x__path_txn_node_children(svn_fs_t *fs, const svn_fs_id_t *id, apr_pool_t *pool) +svn_fs_x__path_txn_node_children(svn_fs_t *fs, + const svn_fs_x__id_t *id, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - return apr_pstrcat(pool, svn_fs_x__path_txn_node_rev(fs, id, pool), - PATH_EXT_CHILDREN, SVN_VA_NULL); + return construct_txn_node_path(fs, id, PATH_EXT_CHILDREN, result_pool, + scratch_pool); } - -/* Check that BUF, a nul-terminated buffer of text from file PATH, - contains only digits at OFFSET and beyond, raising an error if not. - TITLE contains a user-visible description of the file, usually the - short file name. - - Uses POOL for temporary allocation. */ svn_error_t * -svn_fs_x__check_file_buffer_numeric(const char *buf, apr_off_t offset, - const char *path, const char *title, - apr_pool_t *pool) +svn_fs_x__check_file_buffer_numeric(const char *buf, + apr_off_t offset, + const char *path, + const char *title, + apr_pool_t *scratch_pool) { const char *p; @@ -435,7 +497,7 @@ svn_fs_x__check_file_buffer_numeric(cons if (!svn_ctype_isdigit(*p)) return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL, _("%s file '%s' contains unexpected non-digit '%c' within '%s'"), - title, svn_dirent_local_style(path, pool), *p, buf); + title, svn_dirent_local_style(path, scratch_pool), *p, buf); return SVN_NO_ERROR; } @@ -443,30 +505,32 @@ svn_fs_x__check_file_buffer_numeric(cons svn_error_t * svn_fs_x__read_min_unpacked_rev(svn_revnum_t *min_unpacked_rev, svn_fs_t *fs, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { char buf[80]; apr_file_t *file; apr_size_t len; SVN_ERR(svn_io_file_open(&file, - svn_fs_x__path_min_unpacked_rev(fs, pool), + svn_fs_x__path_min_unpacked_rev(fs, scratch_pool), APR_READ | APR_BUFFERED, APR_OS_DEFAULT, - pool)); + scratch_pool)); len = sizeof(buf); - SVN_ERR(svn_io_read_length_line(file, buf, &len, pool)); - SVN_ERR(svn_io_file_close(file, pool)); + SVN_ERR(svn_io_read_length_line(file, buf, &len, scratch_pool)); + SVN_ERR(svn_io_file_close(file, scratch_pool)); SVN_ERR(svn_revnum_parse(min_unpacked_rev, buf, NULL)); return SVN_NO_ERROR; } svn_error_t * -svn_fs_x__update_min_unpacked_rev(svn_fs_t *fs, apr_pool_t *pool) +svn_fs_x__update_min_unpacked_rev(svn_fs_t *fs, + apr_pool_t *scratch_pool) { - fs_x_data_t *ffd = fs->fsap_data; - return svn_fs_x__read_min_unpacked_rev(&ffd->min_unpacked_rev, fs, pool); + svn_fs_x__data_t *ffd = fs->fsap_data; + return svn_fs_x__read_min_unpacked_rev(&ffd->min_unpacked_rev, fs, + scratch_pool); } /* Write a file FILENAME in directory FS_PATH, containing a single line @@ -495,13 +559,13 @@ svn_fs_x__write_min_unpacked_rev(svn_fs_ svn_error_t * svn_fs_x__read_current(svn_revnum_t *rev, svn_fs_t *fs, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { const char *str; svn_stringbuf_t *content; SVN_ERR(svn_fs_x__read_content(&content, - svn_fs_x__path_current(fs, pool), - pool)); + svn_fs_x__path_current(fs, scratch_pool), + scratch_pool)); SVN_ERR(svn_revnum_parse(rev, content->data, &str)); if (*str != '\n') return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, @@ -511,44 +575,36 @@ svn_fs_x__read_current(svn_revnum_t *rev } /* Atomically update the 'current' file to hold the specifed REV. - Perform temporary allocations in POOL. */ + Perform temporary allocations in SCRATCH_POOL. */ svn_error_t * -svn_fs_x__write_current(svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *pool) +svn_fs_x__write_current(svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *scratch_pool) { char *buf; const char *tmp_name, *name; /* Now we can just write out this line. */ - buf = apr_psprintf(pool, "%ld\n", rev); + buf = apr_psprintf(scratch_pool, "%ld\n", rev); - name = svn_fs_x__path_current(fs, pool); + name = svn_fs_x__path_current(fs, scratch_pool); SVN_ERR(svn_io_write_unique(&tmp_name, - svn_dirent_dirname(name, pool), + svn_dirent_dirname(name, scratch_pool), buf, strlen(buf), - svn_io_file_del_none, pool)); + svn_io_file_del_none, scratch_pool)); - return svn_fs_x__move_into_place(tmp_name, name, name, pool); + return svn_fs_x__move_into_place(tmp_name, name, name, scratch_pool); } - -/* Read the file at PATH and return its content in *CONTENT. *CONTENT will - * not be modified unless the whole file was read successfully. - * - * ESTALE, EIO and ENOENT will not cause this function to return an error - * unless LAST_ATTEMPT has been set. If MISSING is not NULL, indicate - * missing files (ENOENT) there. - * - * Use POOL for allocations. - */ svn_error_t * svn_fs_x__try_stringbuf_from_file(svn_stringbuf_t **content, svn_boolean_t *missing, const char *path, svn_boolean_t last_attempt, - apr_pool_t *pool) + apr_pool_t *result_pool) { - svn_error_t *err = svn_stringbuf_from_file2(content, path, pool); + svn_error_t *err = svn_stringbuf_from_file2(content, path, result_pool); if (missing) *missing = FALSE; @@ -586,25 +642,23 @@ svn_fs_x__try_stringbuf_from_file(svn_st svn_error_t * svn_fs_x__get_file_offset(apr_off_t *offset_p, apr_file_t *file, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { apr_off_t offset; /* Note that, for buffered files, one (possibly surprising) side-effect of this call is to flush any unwritten data to disk. */ offset = 0; - SVN_ERR(svn_io_file_seek(file, APR_CUR, &offset, pool)); + SVN_ERR(svn_io_file_seek(file, APR_CUR, &offset, scratch_pool)); *offset_p = offset; return SVN_NO_ERROR; } -/* Read the 'current' file FNAME and store the contents in *BUF. - Allocations are performed in POOL. */ svn_error_t * svn_fs_x__read_content(svn_stringbuf_t **content, const char *fname, - apr_pool_t *pool) + apr_pool_t *result_pool) { int i; *content = NULL; @@ -612,12 +666,12 @@ svn_fs_x__read_content(svn_stringbuf_t * for (i = 0; !*content && (i < SVN_FS_X__RECOVERABLE_RETRY_COUNT); ++i) SVN_ERR(svn_fs_x__try_stringbuf_from_file(content, NULL, fname, i + 1 < SVN_FS_X__RECOVERABLE_RETRY_COUNT, - pool)); + result_pool)); if (!*content) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Can't read '%s'"), - svn_dirent_local_style(fname, pool)); + svn_dirent_local_style(fname, result_pool)); return SVN_NO_ERROR; } @@ -661,7 +715,7 @@ svn_fs_x__read_number_from_stream(apr_in /* Move a file into place from OLD_FILENAME in the transactions directory to its final location NEW_FILENAME in the repository. On Unix, match the permissions of the new file to the permissions of - PERMS_REFERENCE. Temporary allocations are from POOL. + PERMS_REFERENCE. Temporary allocations are from SCRATCH_POOL. This function almost duplicates svn_io_file_move(), but it tries to guarantee a flush. */ @@ -669,14 +723,14 @@ svn_error_t * svn_fs_x__move_into_place(const char *old_filename, const char *new_filename, const char *perms_reference, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { svn_error_t *err; - SVN_ERR(svn_io_copy_perms(perms_reference, old_filename, pool)); + SVN_ERR(svn_io_copy_perms(perms_reference, old_filename, scratch_pool)); /* Move the file into place. */ - err = svn_io_file_rename(old_filename, new_filename, pool); + err = svn_io_file_rename(old_filename, new_filename, scratch_pool); if (err && APR_STATUS_IS_EXDEV(err->apr_err)) { apr_file_t *file; @@ -684,18 +738,19 @@ svn_fs_x__move_into_place(const char *ol /* Can't rename across devices; fall back to copying. */ svn_error_clear(err); err = SVN_NO_ERROR; - SVN_ERR(svn_io_copy_file(old_filename, new_filename, TRUE, pool)); + SVN_ERR(svn_io_copy_file(old_filename, new_filename, TRUE, + scratch_pool)); /* Flush the target of the copy to disk. */ SVN_ERR(svn_io_file_open(&file, new_filename, APR_READ, - APR_OS_DEFAULT, pool)); + APR_OS_DEFAULT, scratch_pool)); /* ### BH: Does this really guarantee a flush of the data written ### via a completely different handle on all operating systems? ### ### Maybe we should perform the copy ourselves instead of making ### apr do that and flush the real handle? */ - SVN_ERR(svn_io_file_flush_to_disk(file, pool)); - SVN_ERR(svn_io_file_close(file, pool)); + SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool)); + SVN_ERR(svn_io_file_close(file, scratch_pool)); } if (err) return svn_error_trace(err); @@ -710,11 +765,11 @@ svn_fs_x__move_into_place(const char *ol const char *dirname; apr_file_t *file; - dirname = svn_dirent_dirname(new_filename, pool); + dirname = svn_dirent_dirname(new_filename, scratch_pool); SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT, - pool)); - SVN_ERR(svn_io_file_flush_to_disk(file, pool)); - SVN_ERR(svn_io_file_close(file, pool)); + scratch_pool)); + SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool)); + SVN_ERR(svn_io_file_close(file, scratch_pool)); } #endif Modified: subversion/branches/pin-externals/subversion/libsvn_fs_x/util.h URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_fs_x/util.h?rev=1653578&r1=1653577&r2=1653578&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_fs_x/util.h (original) +++ subversion/branches/pin-externals/subversion/libsvn_fs_x/util.h Wed Jan 21 16:22:19 2015 @@ -78,8 +78,8 @@ svn_boolean_t svn_fs_x__is_packed_revprop(svn_fs_t *fs, svn_revnum_t rev); -/* Return the first revision in the pack / rev file containing REVISION in - * filesystem FS. For non-packed revs, this will simply be REVISION. */ +/* Return the first revision in the pack / rev file containing REV in + * filesystem FS. For non-packed revs, this will simply be REV. */ svn_revnum_t svn_fs_x__packed_base_rev(svn_fs_t *fs, svn_revnum_t rev); @@ -89,90 +89,152 @@ svn_fs_x__packed_base_rev(svn_fs_t *fs, svn_revnum_t svn_fs_x__pack_size(svn_fs_t *fs, svn_revnum_t rev); +/* Return the full path of the "format" file in FS. + * The result will be allocated in RESULT_POOL. + */ const char * svn_fs_x__path_format(svn_fs_t *fs, - apr_pool_t *pool); + apr_pool_t *result_pool); + +/* Return the path to the 'current' file in FS. + Perform allocation in RESULT_POOL. */ +const char * +svn_fs_x__path_current(svn_fs_t *fs, + apr_pool_t *result_pool); +/* Return the full path of the "uuid" file in FS. + * The result will be allocated in RESULT_POOL. + */ const char * svn_fs_x__path_uuid(svn_fs_t *fs, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the full path of the "txn-current" file in FS. + * The result will be allocated in RESULT_POOL. + */ const char * svn_fs_x__path_txn_current(svn_fs_t *fs, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the full path of the "txn-current-lock" file in FS. + * The result will be allocated in RESULT_POOL. + */ const char * svn_fs_x__path_txn_current_lock(svn_fs_t *fs, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the full path of the global write lock file in FS. + * The result will be allocated in RESULT_POOL. + */ const char * svn_fs_x__path_lock(svn_fs_t *fs, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Return the full path of the pack operation lock file in FS. - * The result will be allocated in POOL. + * The result will be allocated in RESULT_POOL. */ const char * svn_fs_x__path_pack_lock(svn_fs_t *fs, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the full path of the revprop generation file in FS. + * Allocate the result in RESULT_POOL. + */ const char * svn_fs_x__path_revprop_generation(svn_fs_t *fs, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the path of the pack-related file that for revision REV in FS. + * KIND specifies the file name base, e.g. "pack". + * The result will be allocated in RESULT_POOL. + */ const char * svn_fs_x__path_rev_packed(svn_fs_t *fs, svn_revnum_t rev, const char *kind, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the full path of the rev shard directory that will contain + * revision REV in FS. Allocate the result in RESULT_POOL. + */ const char * svn_fs_x__path_rev_shard(svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the full path of the non-packed rev file containing revision REV + * in FS. Allocate the result in RESULT_POOL. + */ const char * svn_fs_x__path_rev(svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Set *PATH to the path of REV in FS, whether in a pack file or not. + Allocate *PATH in RESULT_POOL. + + Note: If the caller does not have the write lock on FS, then the path is + not guaranteed to be correct or to remain correct after the function + returns, because the revision might become packed before or after this + call. If a file exists at that path, then it is correct; if not, then + the caller should call update_min_unpacked_rev() and re-try once. */ +const char * +svn_fs_x__path_rev_absolute(svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool); + +/* Return the full path of the revision properties shard directory that + * will contain the properties of revision REV in FS. + * Allocate the result in RESULT_POOL. + */ const char * svn_fs_x__path_revprops_shard(svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the full path of the revision properties pack shard directory + * that will contain the packed properties of revision REV in FS. + * Allocate the result in RESULT_POOL. + */ const char * svn_fs_x__path_revprops_pack_shard(svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the full path of the non-packed revision properties file that + * contains the props for revision REV in FS. + * Allocate the result in RESULT_POOL. + */ const char * svn_fs_x__path_revprops(svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Convert the TXN_ID into a string, allocated from RESULT_POOL. + */ const char * svn_fs_x__txn_name(svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Convert TXN_NAME into an ID and return it in *TXN_ID. */ svn_error_t * svn_fs_x__txn_by_name(svn_fs_x__txn_id_t *txn_id, const char *txn_name); /* Return the path of the directory containing the transaction TXN_ID in FS. - * The result will be allocated in POOL. + * The result will be allocated in RESULT_POOL. */ const char * svn_fs_x__path_txn_dir(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Return the path of the 'transactions' directory in FS. - * The result will be allocated in POOL. + * The result will be allocated in RESULT_POOL. */ const char * svn_fs_x__path_txns_dir(svn_fs_t *fs, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Return the name of the sha1->rep mapping file in transaction TXN_ID * within FS for the given SHA1 checksum. Use POOL for allocations. @@ -184,101 +246,155 @@ svn_fs_x__path_txn_sha1(svn_fs_t *fs, apr_pool_t *pool); /* Return the path of the 'txn-protorevs' directory in FS, even if that - * folder may not exist in FS. The result will be allocated in POOL. + * folder may not exist in FS. The result will be allocated in RESULT_POOL. */ const char * svn_fs_x__path_txn_proto_revs(svn_fs_t *fs, - apr_pool_t *pool); + apr_pool_t *result_pool); -/* Return the path of the proto-revision file for transaction TXN_ID in FS. - * The result will be allocated in POOL. +/* Return the path of the changes file for transaction TXN_ID in FS. + * The result will be allocated in RESULT_POOL. */ const char * svn_fs_x__path_txn_changes(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the path of the file containing the log-to-phys index for + * the transaction identified by TXN_ID in FS. + * The result will be allocated in RESULT_POOL. + */ const char* svn_fs_x__path_l2p_proto_index(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the path of the file containing the phys-to-log index for + * the transaction identified by TXN_ID in FS. + * The result will be allocated in RESULT_POOL. + */ const char* svn_fs_x__path_p2l_proto_index(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the path of the file containing the transaction properties for + * the transaction identified by TXN_ID in FS. + * The result will be allocated in RESULT_POOL. + */ const char * svn_fs_x__path_txn_props(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the path of the file containing the "final" transaction + * properties for the transaction identified by TXN_ID in FS. + * The result will be allocated in RESULT_POOL. + */ const char * svn_fs_x__path_txn_props_final(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the path of the file containing the node and copy ID counters for + * the transaction identified by TXN_ID in FS. + * The result will be allocated in RESULT_POOL. + */ const char * svn_fs_x__path_txn_next_ids(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the path of the file storing the oldest non-packed revision in FS. + * The result will be allocated in RESULT_POOL. + */ const char * svn_fs_x__path_min_unpacked_rev(svn_fs_t *fs, - apr_pool_t *pool); - + apr_pool_t *result_pool); +/* Return the path of the file containing item_index counter for + * the transaction identified by TXN_ID in FS. + * The result will be allocated in RESULT_POOL. + */ const char * svn_fs_x__path_txn_item_index(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the path of the proto-revision file for transaction TXN_ID in FS. + * The result will be allocated in RESULT_POOL. + */ const char * svn_fs_x__path_txn_proto_rev(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the path of the proto-revision lock file for transaction TXN_ID + * in FS. The result will be allocated in RESULT_POOL. + */ const char * svn_fs_x__path_txn_proto_rev_lock(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool); +/* Return the path of the file containing the in-transaction node revision + * identified by ID in FS. + * The result will be allocated in RESULT_POOL, temporaries in SCRATCH_POOL. + */ const char * svn_fs_x__path_txn_node_rev(svn_fs_t *fs, - const svn_fs_id_t *id, - apr_pool_t *pool); - + const svn_fs_x__id_t *id, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Return the path of the file containing the in-transaction properties of + * the node identified by ID in FS. + * The result will be allocated in RESULT_POOL, temporaries in SCRATCH_POOL. + */ const char * svn_fs_x__path_txn_node_props(svn_fs_t *fs, - const svn_fs_id_t *id, - apr_pool_t *pool); - + const svn_fs_x__id_t *id, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Return the path of the file containing the directory entries of the + * in-transaction directory node identified by ID in FS. + * The result will be allocated in RESULT_POOL, temporaries in SCRATCH_POOL. + */ const char * svn_fs_x__path_txn_node_children(svn_fs_t *fs, - const svn_fs_id_t *id, - apr_pool_t *pool); + const svn_fs_x__id_t *id, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Check that BUF, a nul-terminated buffer of text from file PATH, contains only digits at OFFSET and beyond, raising an error if not. TITLE contains a user-visible description of the file, usually the short file name. - Uses POOL for temporary allocation. */ + Uses SCRATCH_POOL for temporary allocation. */ svn_error_t * svn_fs_x__check_file_buffer_numeric(const char *buf, apr_off_t offset, const char *path, const char *title, - apr_pool_t *pool); + apr_pool_t *scratch_pool); +/* Set *MIN_UNPACKED_REV to the integer value read from the file returned + * by #svn_fs_fs__path_min_unpacked_rev() for FS. + * Use SCRATCH_POOL for temporary allocations. + */ svn_error_t * svn_fs_x__read_min_unpacked_rev(svn_revnum_t *min_unpacked_rev, svn_fs_t *fs, - apr_pool_t *pool); + apr_pool_t *scratch_pool); +/* Re-read the MIN_UNPACKED_REV member of FS from disk. + * Use SCRATCH_POOL for temporary allocations. + */ svn_error_t * svn_fs_x__update_min_unpacked_rev(svn_fs_t *fs, - apr_pool_t *pool); + apr_pool_t *scratch_pool); /* Atomically update the 'min-unpacked-rev' file in FS to hold the specifed * REVNUM. Perform temporary allocations in SCRATCH_POOL. @@ -289,48 +405,48 @@ svn_fs_x__write_min_unpacked_rev(svn_fs_ apr_pool_t *scratch_pool); /* Set *REV to the value read from the 'current' file. Perform temporary - * allocations in POOL. + * allocations in SCRATCH_POOL. */ svn_error_t * svn_fs_x__read_current(svn_revnum_t *rev, svn_fs_t *fs, - apr_pool_t *pool); + apr_pool_t *scratch_pool); /* Atomically update the 'current' file to hold the specifed REV. - Perform temporary allocations in POOL. */ + Perform temporary allocations in SCRATCH_POOL. */ svn_error_t * svn_fs_x__write_current(svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool); + apr_pool_t *scratch_pool); -/* Read the file at PATH and return its content in *CONTENT. *CONTENT will - * not be modified unless the whole file was read successfully. +/* Read the file at PATH and return its content in *CONTENT, allocated in + * RESULT_POOL. *CONTENT will not be modified unless the whole file was + * read successfully. * * ESTALE, EIO and ENOENT will not cause this function to return an error * unless LAST_ATTEMPT has been set. If MISSING is not NULL, indicate * missing files (ENOENT) there. - * - * Use POOL for allocations. */ svn_error_t * svn_fs_x__try_stringbuf_from_file(svn_stringbuf_t **content, svn_boolean_t *missing, const char *path, svn_boolean_t last_attempt, - apr_pool_t *pool); + apr_pool_t *result_pool); -/* Fetch the current offset of FILE into *OFFSET_P. */ +/* Fetch the current offset of FILE into *OFFSET_P. + * Perform temporary allocations in SCRATCH_POOL. */ svn_error_t * svn_fs_x__get_file_offset(apr_off_t *offset_p, apr_file_t *file, - apr_pool_t *pool); + apr_pool_t *scratch_pool); /* Read the file FNAME and store the contents in *BUF. - Allocations are performed in POOL. */ + Allocations are performed in RESULT_POOL. */ svn_error_t * svn_fs_x__read_content(svn_stringbuf_t **content, const char *fname, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Reads a line from STREAM and converts it to a 64 bit integer to be * returned in *RESULT. If we encounter eof, set *HIT_EOF and leave @@ -347,7 +463,7 @@ svn_fs_x__read_number_from_stream(apr_in /* Move a file into place from OLD_FILENAME in the transactions directory to its final location NEW_FILENAME in the repository. On Unix, match the permissions of the new file to the permissions of - PERMS_REFERENCE. Temporary allocations are from POOL. + PERMS_REFERENCE. Temporary allocations are from SCRATCH_POOL. This function almost duplicates svn_io_file_move(), but it tries to guarantee a flush. */ @@ -355,6 +471,6 @@ svn_error_t * svn_fs_x__move_into_place(const char *old_filename, const char *new_filename, const char *perms_reference, - apr_pool_t *pool); + apr_pool_t *scratch_pool); #endif Modified: subversion/branches/pin-externals/subversion/libsvn_fs_x/verify.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_fs_x/verify.c?rev=1653578&r1=1653577&r2=1653578&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_fs_x/verify.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_fs_x/verify.c Wed Jan 21 16:22:19 2015 @@ -22,6 +22,7 @@ #include "verify.h" #include "fs_x.h" +#include "svn_time.h" #include "private/svn_subr_private.h" #include "cached_data.h" @@ -57,7 +58,7 @@ typedef struct verify_walker_baton_t /* Used by svn_fs_x__verify(). Implements svn_fs_x__walk_rep_reference().walker. */ static svn_error_t * -verify_walker(representation_t *rep, +verify_walker(svn_fs_x__representation_t *rep, void *baton, svn_fs_t *fs, apr_pool_t *scratch_pool) @@ -102,24 +103,26 @@ verify_rep_cache(svn_fs_t *fs, void *notify_baton, svn_cancel_func_t cancel_func, void *cancel_baton, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { svn_boolean_t exists; /* rep-cache verification. */ - SVN_ERR(svn_fs_x__exists_rep_cache(&exists, fs, pool)); + SVN_ERR(svn_fs_x__exists_rep_cache(&exists, fs, scratch_pool)); if (exists) { /* provide a baton to allow the reuse of open file handles between iterations (saves 2/3 of OS level file operations). */ - verify_walker_baton_t *baton = apr_pcalloc(pool, sizeof(*baton)); + verify_walker_baton_t *baton + = apr_pcalloc(scratch_pool, sizeof(*baton)); + baton->last_notified_revision = SVN_INVALID_REVNUM; baton->notify_func = notify_func; baton->notify_baton = notify_baton; /* tell the user that we are now ready to do *something* */ if (notify_func) - notify_func(SVN_INVALID_REVNUM, notify_baton, pool); + notify_func(SVN_INVALID_REVNUM, notify_baton, scratch_pool); /* Do not attempt to walk the rep-cache database if its file does not exist, since doing so would create it --- which may confuse @@ -127,7 +130,7 @@ verify_rep_cache(svn_fs_t *fs, SVN_ERR(svn_fs_x__walk_rep_reference(fs, start, end, verify_walker, baton, cancel_func, cancel_baton, - pool)); + scratch_pool)); } return SVN_NO_ERROR; @@ -223,7 +226,7 @@ verify_index_checksums(svn_fs_t *fs, /* Verify that for all log-to-phys index entries for revisions START to * START + COUNT-1 in FS there is a consistent entry in the phys-to-log * index. If given, invoke CANCEL_FUNC with CANCEL_BATON at regular - * intervals. Use POOL for allocations. + * intervals. Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * compare_l2p_to_p2l_index(svn_fs_t *fs, @@ -231,19 +234,19 @@ compare_l2p_to_p2l_index(svn_fs_t *fs, svn_revnum_t count, svn_cancel_func_t cancel_func, void *cancel_baton, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { svn_revnum_t i; - apr_pool_t *iterpool = svn_pool_create(pool); + apr_pool_t *iterpool = svn_pool_create(scratch_pool); apr_array_header_t *max_ids; /* common file access structure */ svn_fs_x__revision_file_t *rev_file; - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, start, pool, + SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, start, scratch_pool, iterpool)); /* determine the range of items to check for each revision */ - SVN_ERR(svn_fs_x__l2p_get_max_ids(&max_ids, fs, start, count, pool, + SVN_ERR(svn_fs_x__l2p_get_max_ids(&max_ids, fs, start, count, scratch_pool, iterpool)); /* check all items in all revisions if the given range */ @@ -257,8 +260,8 @@ compare_l2p_to_p2l_index(svn_fs_t *fs, { apr_off_t offset; apr_uint32_t sub_item; - svn_fs_x__id_part_t l2p_item; - svn_fs_x__id_part_t *p2l_item; + svn_fs_x__id_t l2p_item; + svn_fs_x__id_t *p2l_item; l2p_item.change_set = svn_fs_x__change_set_by_rev(revision); l2p_item.number = k; @@ -280,10 +283,10 @@ compare_l2p_to_p2l_index(svn_fs_t *fs, _("p2l index entry not found for " "PHYS o%s:s%ld returned by " "l2p index for LOG r%ld:i%ld"), - apr_off_t_toa(pool, offset), + apr_off_t_toa(scratch_pool, offset), (long)sub_item, revision, (long)k); - if (!svn_fs_x__id_part_eq(&l2p_item, p2l_item)) + if (!svn_fs_x__id_eq(&l2p_item, p2l_item)) return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT, NULL, _("p2l index info LOG r%ld:i%ld" @@ -310,7 +313,7 @@ compare_l2p_to_p2l_index(svn_fs_t *fs, /* Verify that for all phys-to-log index entries for revisions START to * START + COUNT-1 in FS there is a consistent entry in the log-to-phys * index. If given, invoke CANCEL_FUNC with CANCEL_BATON at regular - * intervals. Use POOL for allocations. + * intervals. Use SCRATCH_POOL for temporary allocations. * * Please note that we can only check on pack / rev file granularity and * must only be called for a single rev / pack file. @@ -321,21 +324,22 @@ compare_p2l_to_l2p_index(svn_fs_t *fs, svn_revnum_t count, svn_cancel_func_t cancel_func, void *cancel_baton, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { - fs_x_data_t *ffd = fs->fsap_data; - apr_pool_t *iterpool = svn_pool_create(pool); + svn_fs_x__data_t *ffd = fs->fsap_data; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + apr_pool_t *iterpool2 = svn_pool_create(scratch_pool); apr_off_t max_offset; apr_off_t offset = 0; /* common file access structure */ svn_fs_x__revision_file_t *rev_file; - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, start, pool, + SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, start, scratch_pool, iterpool)); /* get the size of the rev / pack file as covered by the P2L index */ SVN_ERR(svn_fs_x__p2l_get_max_offset(&max_offset, fs, rev_file, start, - pool)); + scratch_pool)); /* for all offsets in the file, get the P2L index entries and check them against the L2P index */ @@ -345,6 +349,8 @@ compare_p2l_to_l2p_index(svn_fs_t *fs, svn_fs_x__p2l_entry_t *last_entry; int i; + svn_pool_clear(iterpool); + /* get all entries for the current block */ SVN_ERR(svn_fs_x__p2l_index_lookup(&entries, fs, rev_file, start, offset, ffd->p2l_page_size, @@ -354,7 +360,7 @@ compare_p2l_to_l2p_index(svn_fs_t *fs, NULL, _("p2l does not cover offset %s" " for revision %ld"), - apr_off_t_toa(pool, offset), start); + apr_off_t_toa(scratch_pool, offset), start); /* process all entries (and later continue with the next block) */ last_entry @@ -372,12 +378,13 @@ compare_p2l_to_l2p_index(svn_fs_t *fs, { apr_off_t l2p_offset; apr_uint32_t sub_item; - svn_fs_x__id_part_t *p2l_item = &entry->items[k]; + svn_fs_x__id_t *p2l_item = &entry->items[k]; svn_revnum_t revision = svn_fs_x__get_revnum(p2l_item->change_set); + svn_pool_clear(iterpool2); SVN_ERR(svn_fs_x__item_offset(&l2p_offset, &sub_item, fs, - rev_file, p2l_item, iterpool)); + rev_file, p2l_item, iterpool2)); if (sub_item != k || l2p_offset != entry->offset) return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT, @@ -385,11 +392,13 @@ compare_p2l_to_l2p_index(svn_fs_t *fs, _("l2p index entry PHYS o%s:s%ld " "does not match p2l index value " "LOG r%ld:i%ld for PHYS o%s:s%ld"), - apr_off_t_toa(pool, l2p_offset), + apr_off_t_toa(scratch_pool, + l2p_offset), (long)sub_item, revision, (long)p2l_item->number, - apr_off_t_toa(pool, entry->offset), + apr_off_t_toa(scratch_pool, + entry->offset), (long)k); } } @@ -398,6 +407,7 @@ compare_p2l_to_l2p_index(svn_fs_t *fs, SVN_ERR(cancel_func(cancel_baton)); } + svn_pool_destroy(iterpool2); svn_pool_destroy(iterpool); SVN_ERR(svn_fs_x__close_revision_file(rev_file)); @@ -410,13 +420,13 @@ compare_p2l_to_l2p_index(svn_fs_t *fs, * Must be a multiple of 8. */ #define STREAM_THRESHOLD 4096 -/* Verify that the next SIZE bytes read from FILE are NUL. - * SIZE must not exceed STREAM_THRESHOLD. Use POOL for allocations. +/* Verify that the next SIZE bytes read from FILE are NUL. SIZE must not + * exceed STREAM_THRESHOLD. Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * expect_buffer_nul(apr_file_t *file, apr_off_t size, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { union { @@ -429,7 +439,8 @@ expect_buffer_nul(apr_file_t *file, /* read the whole data block; error out on failure */ data.chunks[(size - 1)/ sizeof(apr_uint64_t)] = 0; - SVN_ERR(svn_io_file_read_full2(file, data.buffer, size, NULL, NULL, pool)); + SVN_ERR(svn_io_file_read_full2(file, data.buffer, size, NULL, NULL, + scratch_pool)); /* chunky check */ for (i = 0; i < size / sizeof(apr_uint64_t); ++i) @@ -443,57 +454,59 @@ expect_buffer_nul(apr_file_t *file, const char *file_name; apr_off_t offset; - SVN_ERR(svn_io_file_name_get(&file_name, file, pool)); - SVN_ERR(svn_fs_x__get_file_offset(&offset, file, pool)); + SVN_ERR(svn_io_file_name_get(&file_name, file, scratch_pool)); + SVN_ERR(svn_fs_x__get_file_offset(&offset, file, scratch_pool)); offset -= size - i; return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Empty section in file %s contains " "non-NUL data at offset %s"), - file_name, apr_off_t_toa(pool, offset)); + file_name, + apr_off_t_toa(scratch_pool, offset)); } return SVN_NO_ERROR; } /* Verify that the next SIZE bytes read from FILE are NUL. - * Use POOL for allocations. + * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * read_all_nul(apr_file_t *file, apr_off_t size, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { for (; size >= STREAM_THRESHOLD; size -= STREAM_THRESHOLD) - SVN_ERR(expect_buffer_nul(file, STREAM_THRESHOLD, pool)); + SVN_ERR(expect_buffer_nul(file, STREAM_THRESHOLD, scratch_pool)); if (size) - SVN_ERR(expect_buffer_nul(file, size, pool)); + SVN_ERR(expect_buffer_nul(file, size, scratch_pool)); return SVN_NO_ERROR; } /* Compare the ACTUAL checksum with the one expected by ENTRY. * Return an error in case of mismatch. Use the name of FILE - * in error message. Allocate data in POOL. + * in error message. Allocate temporary data in SCRATCH_POOL. */ static svn_error_t * expected_checksum(apr_file_t *file, svn_fs_x__p2l_entry_t *entry, apr_uint32_t actual, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { if (actual != entry->fnv1_checksum) { const char *file_name; - SVN_ERR(svn_io_file_name_get(&file_name, file, pool)); - SVN_ERR(svn_io_file_name_get(&file_name, file, pool)); + SVN_ERR(svn_io_file_name_get(&file_name, file, scratch_pool)); + SVN_ERR(svn_io_file_name_get(&file_name, file, scratch_pool)); return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Checksum mismatch in item at offset %s of " "length %s bytes in file %s"), - apr_off_t_toa(pool, entry->offset), - apr_off_t_toa(pool, entry->size), file_name); + apr_off_t_toa(scratch_pool, entry->offset), + apr_off_t_toa(scratch_pool, entry->size), + file_name); } return SVN_NO_ERROR; @@ -501,37 +514,38 @@ expected_checksum(apr_file_t *file, /* Verify that the FNV checksum over the next ENTRY->SIZE bytes read * from FILE will match ENTRY's expected checksum. SIZE must not - * exceed STREAM_THRESHOLD. Use POOL for allocations. + * exceed STREAM_THRESHOLD. Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * expected_buffered_checksum(apr_file_t *file, svn_fs_x__p2l_entry_t *entry, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { unsigned char buffer[STREAM_THRESHOLD]; SVN_ERR_ASSERT(entry->size <= STREAM_THRESHOLD); SVN_ERR(svn_io_file_read_full2(file, buffer, (apr_size_t)entry->size, - NULL, NULL, pool)); + NULL, NULL, scratch_pool)); SVN_ERR(expected_checksum(file, entry, svn__fnv1a_32x4(buffer, (apr_size_t)entry->size), - pool)); + scratch_pool)); return SVN_NO_ERROR; } /* Verify that the FNV checksum over the next ENTRY->SIZE bytes read from - * FILE will match ENTRY's expected checksum. Use POOL for allocations. + * FILE will match ENTRY's expected checksum. + * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * expected_streamed_checksum(apr_file_t *file, svn_fs_x__p2l_entry_t *entry, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { unsigned char buffer[STREAM_THRESHOLD]; svn_checksum_t *checksum; svn_checksum_ctx_t *context - = svn_checksum_ctx_create(svn_checksum_fnv1a_32x4, pool); + = svn_checksum_ctx_create(svn_checksum_fnv1a_32x4, scratch_pool); apr_off_t size = entry->size; while (size > 0) @@ -540,15 +554,15 @@ expected_streamed_checksum(apr_file_t *f ? sizeof(buffer) : (apr_size_t)size; SVN_ERR(svn_io_file_read_full2(file, buffer, to_read, NULL, NULL, - pool)); + scratch_pool)); SVN_ERR(svn_checksum_update(context, buffer, to_read)); size -= to_read; } - SVN_ERR(svn_checksum_final(&checksum, context, pool)); + SVN_ERR(svn_checksum_final(&checksum, context, scratch_pool)); SVN_ERR(expected_checksum(file, entry, ntohl(*(const apr_uint32_t *)checksum->digest), - pool)); + scratch_pool)); return SVN_NO_ERROR; } @@ -556,7 +570,7 @@ expected_streamed_checksum(apr_file_t *f /* Verify that for all phys-to-log index entries for revisions START to * START + COUNT-1 in FS match the actual pack / rev file contents. * If given, invoke CANCEL_FUNC with CANCEL_BATON at regular intervals. - * Use POOL for allocations. + * Use SCRATCH_POOL for temporary allocations. * * Please note that we can only check on pack / rev file granularity and * must only be called for a single rev / pack file. @@ -567,32 +581,35 @@ compare_p2l_to_rev(svn_fs_t *fs, svn_revnum_t count, svn_cancel_func_t cancel_func, void *cancel_baton, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { - fs_x_data_t *ffd = fs->fsap_data; - apr_pool_t *iterpool = svn_pool_create(pool); + svn_fs_x__data_t *ffd = fs->fsap_data; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); apr_off_t max_offset; apr_off_t offset = 0; svn_fs_x__revision_file_t *rev_file; /* open the pack / rev file that is covered by the p2l index */ - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, start, pool, + SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, start, scratch_pool, iterpool)); /* check file size vs. range covered by index */ SVN_ERR(svn_fs_x__auto_read_footer(rev_file)); SVN_ERR(svn_fs_x__p2l_get_max_offset(&max_offset, fs, rev_file, start, - pool)); + scratch_pool)); if (rev_file->l2p_offset != max_offset) return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT, NULL, _("File size of %s for revision r%ld does " "not match p2l index size of %s"), - apr_off_t_toa(pool, rev_file->l2p_offset), start, - apr_off_t_toa(pool, max_offset)); + apr_off_t_toa(scratch_pool, + rev_file->l2p_offset), + start, + apr_off_t_toa(scratch_pool, + max_offset)); SVN_ERR(svn_io_file_aligned_seek(rev_file->file, ffd->block_size, NULL, 0, - pool)); + scratch_pool)); /* for all offsets in the file, get the P2L index entries and check them against the L2P index */ @@ -635,24 +652,25 @@ compare_p2l_to_rev(svn_fs_t *fs, " is non-contiguous between offsets " " %s and %s"), start, - apr_off_t_toa(pool, offset), - apr_off_t_toa(pool, entry->offset)); + apr_off_t_toa(scratch_pool, offset), + apr_off_t_toa(scratch_pool, + entry->offset)); /* empty sections must contain NUL bytes only */ if (entry->type == SVN_FS_X__ITEM_TYPE_UNUSED) { /* skip filler entry at the end of the p2l index */ if (entry->offset != max_offset) - SVN_ERR(read_all_nul(rev_file->file, entry->size, pool)); + SVN_ERR(read_all_nul(rev_file->file, entry->size, iterpool)); } else { if (entry->size < STREAM_THRESHOLD) SVN_ERR(expected_buffered_checksum(rev_file->file, entry, - pool)); + iterpool)); else SVN_ERR(expected_streamed_checksum(rev_file->file, entry, - pool)); + iterpool)); } /* advance offset */ @@ -668,27 +686,72 @@ compare_p2l_to_rev(svn_fs_t *fs, return SVN_NO_ERROR; } -/* Verify that the log-to-phys indexes and phys-to-log indexes are - * consistent with each other. The function signature is similar to - * svn_fs_x__verify. +/* Verify that the revprops of the revisions START to END in FS can be + * accessed. Invoke CANCEL_FUNC with CANCEL_BATON at regular intervals. * * The values of START and END have already been auto-selected and - * verified. You may call this for format7 or higher repos. + * verified. */ static svn_error_t * -verify_index_consistency(svn_fs_t *fs, - svn_revnum_t start, - svn_revnum_t end, - svn_fs_progress_notify_func_t notify_func, - void *notify_baton, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *pool) +verify_revprops(svn_fs_t *fs, + svn_revnum_t start, + svn_revnum_t end, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *scratch_pool) +{ + svn_revnum_t revision; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + + for (revision = start; revision < end; ++revision) + { + svn_string_t *date; + apr_time_t timetemp; + + svn_pool_clear(iterpool); + + /* Access the svn:date revprop. + * This implies parsing all revprops for that revision. */ + SVN_ERR(svn_fs_x__revision_prop(&date, fs, revision, + SVN_PROP_REVISION_DATE, iterpool)); + + /* The time stamp is the only revprop that, if given, needs to + * have a valid content. */ + if (date) + SVN_ERR(svn_time_from_cstring(&timetemp, date->data, iterpool)); + + if (cancel_func) + SVN_ERR(cancel_func(cancel_baton)); + } + + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + +/* Verify that on-disk representation has not been tempered with (in a way + * that leaves the repository in a corrupted state). This compares log-to- + * phys with phys-to-log indexes, verifies the low-level checksums and + * checks that all revprops are available. The function signature is + * similar to svn_fs_x__verify. + * + * The values of START and END have already been auto-selected and + * verified. + */ +static svn_error_t * +verify_metadata_consistency(svn_fs_t *fs, + svn_revnum_t start, + svn_revnum_t end, + svn_fs_progress_notify_func_t notify_func, + void *notify_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *scratch_pool) { svn_error_t *err; - fs_x_data_t *ffd = fs->fsap_data; + svn_fs_x__data_t *ffd = fs->fsap_data; svn_revnum_t revision, next_revision; - apr_pool_t *iterpool = svn_pool_create(pool); + apr_pool_t *iterpool = svn_pool_create(scratch_pool); for (revision = start; revision <= end; revision = next_revision) { @@ -718,11 +781,16 @@ verify_index_consistency(svn_fs_t *fs, err = compare_p2l_to_rev(fs, pack_start, pack_end - pack_start, cancel_func, cancel_baton, iterpool); + /* ensure that revprops are available and accessible */ + if (!err) + err = verify_revprops(fs, pack_start, pack_end, + cancel_func, cancel_baton, iterpool); + /* concurrent packing is one of the reasons why verification may fail. Make sure, we operate on up-to-date information. */ if (err) SVN_ERR(svn_fs_x__read_min_unpacked_rev(&ffd->min_unpacked_rev, - fs, pool)); + fs, scratch_pool)); /* retry the whole shard if it got packed in the meantime */ if (err && count != svn_fs_x__pack_size(fs, revision)) @@ -753,9 +821,9 @@ svn_fs_x__verify(svn_fs_t *fs, void *notify_baton, svn_cancel_func_t cancel_func, void *cancel_baton, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { - fs_x_data_t *ffd = fs->fsap_data; + svn_fs_x__data_t *ffd = fs->fsap_data; svn_revnum_t youngest = ffd->youngest_rev_cache; /* cache is current */ /* Input validation. */ @@ -763,18 +831,19 @@ svn_fs_x__verify(svn_fs_t *fs, start = 0; if (! SVN_IS_VALID_REVNUM(end)) end = youngest; - SVN_ERR(svn_fs_x__ensure_revision_exists(start, fs, pool)); - SVN_ERR(svn_fs_x__ensure_revision_exists(end, fs, pool)); + SVN_ERR(svn_fs_x__ensure_revision_exists(start, fs, scratch_pool)); + SVN_ERR(svn_fs_x__ensure_revision_exists(end, fs, scratch_pool)); /* log/phys index consistency. We need to check them first to make sure we can access the rev / pack files in format7. */ - SVN_ERR(verify_index_consistency(fs, start, end, - notify_func, notify_baton, - cancel_func, cancel_baton, pool)); + SVN_ERR(verify_metadata_consistency(fs, start, end, + notify_func, notify_baton, + cancel_func, cancel_baton, + scratch_pool)); /* rep cache consistency */ SVN_ERR(verify_rep_cache(fs, start, end, notify_func, notify_baton, - cancel_func, cancel_baton, pool)); + cancel_func, cancel_baton, scratch_pool)); return SVN_NO_ERROR; } Modified: subversion/branches/pin-externals/subversion/libsvn_fs_x/verify.h URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_fs_x/verify.h?rev=1653578&r1=1653577&r2=1653578&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_fs_x/verify.h (original) +++ subversion/branches/pin-externals/subversion/libsvn_fs_x/verify.h Wed Jan 21 16:22:19 2015 @@ -29,14 +29,15 @@ * START to END where possible. Indicate progress via the optional * NOTIFY_FUNC callback using NOTIFY_BATON. The optional CANCEL_FUNC * will periodically be called with CANCEL_BATON to allow for preemption. - * Use POOL for temporary allocations. */ -svn_error_t *svn_fs_x__verify(svn_fs_t *fs, - svn_revnum_t start, - svn_revnum_t end, - svn_fs_progress_notify_func_t notify_func, - void *notify_baton, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *pool); + * Use SCRATCH_POOL for temporary allocations. */ +svn_error_t * +svn_fs_x__verify(svn_fs_t *fs, + svn_revnum_t start, + svn_revnum_t end, + svn_fs_progress_notify_func_t notify_func, + void *notify_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *scratch_pool); #endif Modified: subversion/branches/pin-externals/subversion/libsvn_ra_serf/merge.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_ra_serf/merge.c?rev=1653578&r1=1653577&r2=1653578&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_ra_serf/merge.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_ra_serf/merge.c Wed Jan 21 16:22:19 2015 @@ -439,5 +439,13 @@ svn_ra_serf__run_merge(const svn_commit_ *commit_info = merge_ctx->commit_info; + /* Sanity check (Reported to be triggered by CodePlex's svnbridge) */ + if (! SVN_IS_VALID_REVNUM(merge_ctx->commit_info->revision)) + { + return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL, + _("The MERGE response did not include " + "a new revision")); + } + return SVN_NO_ERROR; } Modified: subversion/branches/pin-externals/subversion/libsvn_ra_serf/options.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_ra_serf/options.c?rev=1653578&r1=1653577&r2=1653578&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_ra_serf/options.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_ra_serf/options.c Wed Jan 21 16:22:19 2015 @@ -33,6 +33,7 @@ #include "svn_ra.h" #include "svn_dav.h" #include "svn_xml.h" +#include "svn_ctype.h" #include "../libsvn_ra/ra_loader.h" #include "svn_private_config.h" @@ -226,7 +227,9 @@ capabilities_headers_iterator_callback(v } /* SVN-specific headers -- if present, server supports HTTP protocol v2 */ - else if (strncmp(key, "SVN", 3) == 0) + else if (!svn_ctype_casecmp(key[0], 'S') + && !svn_ctype_casecmp(key[1], 'V') + && !svn_ctype_casecmp(key[2], 'N')) { /* If we've not yet seen any information about supported POST requests, we'll initialize the list/hash with "create-txn" Modified: subversion/branches/pin-externals/subversion/libsvn_ra_serf/replay.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_ra_serf/replay.c?rev=1653578&r1=1653577&r2=1653578&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_ra_serf/replay.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_ra_serf/replay.c Wed Jan 21 16:22:19 2015 @@ -785,6 +785,7 @@ svn_ra_serf__replay_range(svn_ra_session } /* Run the serf loop. */ + done = FALSE; SVN_ERR(svn_ra_serf__context_run_wait(&done, session, pool)); /* Substract the number of completely handled responses from our @@ -795,7 +796,6 @@ svn_ra_serf__replay_range(svn_ra_session done_list = done_reports; - done = FALSE; done_reports = NULL; while (done_list) Modified: subversion/branches/pin-externals/subversion/libsvn_ra_serf/update.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_ra_serf/update.c?rev=1653578&r1=1653577&r2=1653578&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_ra_serf/update.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_ra_serf/update.c Wed Jan 21 16:22:19 2015 @@ -771,7 +771,8 @@ get_best_connection(report_context_t *ct pending requests, thereby giving more work to lightly loaded server processes. */ - unsigned int i, min = INT_MAX, best_conn = first_conn; + int i, best_conn = first_conn; + unsigned int min = INT_MAX; for (i = first_conn; i < ctx->sess->num_conns; i++) { serf_connection_t *sc = ctx->sess->conns[i]->conn; Modified: subversion/branches/pin-externals/subversion/libsvn_repos/deprecated.c URL: http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_repos/deprecated.c?rev=1653578&r1=1653577&r2=1653578&view=diff ============================================================================== --- subversion/branches/pin-externals/subversion/libsvn_repos/deprecated.c (original) +++ subversion/branches/pin-externals/subversion/libsvn_repos/deprecated.c Wed Jan 21 16:22:19 2015 @@ -997,6 +997,35 @@ svn_repos_load_fs(svn_repos_t *repos, } svn_error_t * +svn_repos_get_fs_build_parser4(const svn_repos_parse_fns3_t **callbacks, + void **parse_baton, + svn_repos_t *repos, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + svn_boolean_t use_history, + svn_boolean_t validate_props, + enum svn_repos_load_uuid uuid_action, + const char *parent_dir, + svn_repos_notify_func_t notify_func, + void *notify_baton, + apr_pool_t *pool) +{ + SVN_ERR(svn_repos_get_fs_build_parser5(callbacks, parse_baton, + repos, + start_rev, end_rev, + use_history, + validate_props, + uuid_action, + parent_dir, + FALSE, FALSE, /*hooks */ + FALSE /*ignore_dates*/, + notify_func, + notify_baton, + pool)); + return SVN_NO_ERROR; +} + +svn_error_t * svn_repos_get_fs_build_parser3(const svn_repos_parse_fns2_t **callbacks, void **parse_baton, svn_repos_t *repos,
