Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.c Sun Jun 14 20:58:10 2015 @@ -371,7 +371,7 @@ set_lock(const char *fs_path, SVN_ERR(read_digest_file(&children, NULL, fs_path, digest_path, scratch_pool)); - SVN_ERR(write_digest_file(children, lock, fs_path, digest_path, + SVN_ERR(write_digest_file(children, lock, fs_path, digest_path, perms_reference, scratch_pool)); return SVN_NO_ERROR; @@ -423,7 +423,7 @@ add_to_digest(const char *fs_path, } if (apr_hash_count(children) != original_count) - SVN_ERR(write_digest_file(children, lock, fs_path, index_digest_path, + SVN_ERR(write_digest_file(children, lock, fs_path, index_digest_path, perms_reference, scratch_pool)); return SVN_NO_ERROR; @@ -458,7 +458,7 @@ delete_from_digest(const char *fs_path, } if (apr_hash_count(children) || lock) - SVN_ERR(write_digest_file(children, lock, fs_path, index_digest_path, + SVN_ERR(write_digest_file(children, lock, fs_path, index_digest_path, perms_reference, scratch_pool)); else SVN_ERR(svn_io_remove_file2(index_digest_path, TRUE, scratch_pool)); @@ -471,6 +471,12 @@ unlock_single(svn_fs_t *fs, svn_lock_t *lock, apr_pool_t *pool); +/* Check if LOCK has been already expired. */ +static svn_boolean_t lock_expired(const svn_lock_t *lock) +{ + return lock->expiration_date && (apr_time_now() > lock->expiration_date); +} + /* Set *LOCK_P to the lock for PATH in FS. HAVE_WRITE_LOCK should be TRUE if the caller (or one of its callers) has taken out the repository-wide write lock, FALSE otherwise. If MUST_EXIST is @@ -500,7 +506,7 @@ get_lock(svn_lock_t **lock_p, return must_exist ? SVN_FS__ERR_NO_SUCH_LOCK(fs, path) : SVN_NO_ERROR; /* Don't return an expired lock. */ - if (lock->expiration_date && (apr_time_now() > lock->expiration_date)) + if (lock_expired(lock)) { /* Only remove the lock if we have the write lock. Read operations shouldn't change the filesystem. */ @@ -547,68 +553,17 @@ get_lock_helper(svn_fs_t *fs, } -/* Baton for locks_walker(). */ -typedef struct walk_locks_baton_t -{ - svn_fs_get_locks_callback_t get_locks_func; - void *get_locks_baton; - svn_fs_t *fs; -} walk_locks_baton_t; - -/* Implements walk_digests_callback_t. */ -static svn_error_t * -locks_walker(void *baton, - const char *fs_path, - const char *digest_path, - svn_lock_t *lock, - svn_boolean_t have_write_lock, - apr_pool_t *pool) -{ - walk_locks_baton_t *wlb = baton; - - if (lock) - { - /* Don't report an expired lock. */ - if (lock->expiration_date == 0 - || (apr_time_now() <= lock->expiration_date)) - { - if (wlb->get_locks_func) - SVN_ERR(wlb->get_locks_func(wlb->get_locks_baton, lock, pool)); - } - else - { - /* Only remove the lock if we have the write lock. - Read operations shouldn't change the filesystem. */ - if (have_write_lock) - SVN_ERR(unlock_single(wlb->fs, lock, pool)); - } - } - - return SVN_NO_ERROR; -} - -/* Callback type for walk_digest_files(). - * - * LOCK come from a read_digest_file(digest_path) call. - */ -typedef svn_error_t *(*walk_digests_callback_t)(void *baton, - const char *fs_path, - const char *digest_path, - svn_lock_t *lock, - svn_boolean_t have_write_lock, - apr_pool_t *pool); - -/* A function that calls WALK_DIGESTS_FUNC/WALK_DIGESTS_BATON for - all lock digest files in and under PATH in FS. +/* A function that calls GET_LOCKS_FUNC/GET_LOCKS_BATON for + all locks in and under PATH in FS. HAVE_WRITE_LOCK should be true if the caller (directly or indirectly) has the FS write lock. */ static svn_error_t * -walk_digest_files(const char *fs_path, - const char *digest_path, - walk_digests_callback_t walk_digests_func, - void *walk_digests_baton, - svn_boolean_t have_write_lock, - apr_pool_t *pool) +walk_locks(svn_fs_t *fs, + const char *digest_path, + svn_fs_get_locks_callback_t get_locks_func, + void *get_locks_baton, + svn_boolean_t have_write_lock, + apr_pool_t *pool) { apr_hash_index_t *hi; apr_hash_t *children; @@ -616,10 +571,19 @@ walk_digest_files(const char *fs_path, svn_lock_t *lock; /* First, send up any locks in the current digest file. */ - SVN_ERR(read_digest_file(&children, &lock, fs_path, digest_path, pool)); + SVN_ERR(read_digest_file(&children, &lock, fs->path, digest_path, pool)); - SVN_ERR(walk_digests_func(walk_digests_baton, fs_path, digest_path, lock, - have_write_lock, pool)); + if (lock && lock_expired(lock)) + { + /* Only remove the lock if we have the write lock. + Read operations shouldn't change the filesystem. */ + if (have_write_lock) + SVN_ERR(unlock_single(fs, lock, pool)); + } + else if (lock) + { + SVN_ERR(get_locks_func(get_locks_baton, lock, pool)); + } /* Now, report all the child entries (if any; bail otherwise). */ if (! apr_hash_count(children)) @@ -631,39 +595,25 @@ walk_digest_files(const char *fs_path, svn_pool_clear(subpool); SVN_ERR(read_digest_file - (NULL, &lock, fs_path, - digest_path_from_digest(fs_path, digest, subpool), subpool)); + (NULL, &lock, fs->path, + digest_path_from_digest(fs->path, digest, subpool), subpool)); - SVN_ERR(walk_digests_func(walk_digests_baton, fs_path, digest_path, lock, - have_write_lock, subpool)); + if (lock && lock_expired(lock)) + { + /* Only remove the lock if we have the write lock. + Read operations shouldn't change the filesystem. */ + if (have_write_lock) + SVN_ERR(unlock_single(fs, lock, pool)); + } + else if (lock) + { + SVN_ERR(get_locks_func(get_locks_baton, lock, pool)); + } } svn_pool_destroy(subpool); return SVN_NO_ERROR; } -/* A function that calls GET_LOCKS_FUNC/GET_LOCKS_BATON for - all locks in and under PATH in FS. - HAVE_WRITE_LOCK should be true if the caller (directly or indirectly) - has the FS write lock. */ -static svn_error_t * -walk_locks(svn_fs_t *fs, - const char *digest_path, - svn_fs_get_locks_callback_t get_locks_func, - void *get_locks_baton, - svn_boolean_t have_write_lock, - apr_pool_t *pool) -{ - walk_locks_baton_t wlb; - - wlb.get_locks_func = get_locks_func; - wlb.get_locks_baton = get_locks_baton; - wlb.fs = fs; - SVN_ERR(walk_digest_files(fs->path, digest_path, locks_walker, &wlb, - have_write_lock, pool)); - return SVN_NO_ERROR; -} - - /* Utility function: verify that a lock can be used. Interesting errors returned from this function: @@ -738,6 +688,35 @@ svn_fs_x__allow_locked_operation(const c return SVN_NO_ERROR; } +/* Helper function called from the lock and unlock code. + UPDATES is a map from "const char *" parent paths to "apr_array_header_t *" + arrays of child paths. For all of the parent paths of PATH this function + adds PATH to the corresponding array of child paths. */ +static void +schedule_index_update(apr_hash_t *updates, + const char *path, + apr_pool_t *scratch_pool) +{ + apr_pool_t *hashpool = apr_hash_pool_get(updates); + const char *parent_path = path; + + while (! svn_fspath__is_root(parent_path, strlen(parent_path))) + { + apr_array_header_t *children; + + parent_path = svn_fspath__dirname(parent_path, scratch_pool); + children = svn_hash_gets(updates, parent_path); + + if (! children) + { + children = apr_array_make(hashpool, 8, sizeof(const char *)); + svn_hash_sets(updates, apr_pstrdup(hashpool, parent_path), children); + } + + APR_ARRAY_PUSH(children, const char *) = path; + } +} + /* The effective arguments for lock_body() below. */ typedef struct lock_baton_t { svn_fs_t *fs; @@ -756,6 +735,7 @@ check_lock(svn_error_t **fs_err, const svn_fs_lock_target_t *target, lock_baton_t *lb, svn_fs_root_t *root, + svn_revnum_t youngest_rev, apr_pool_t *pool) { svn_node_kind_t kind; @@ -792,6 +772,15 @@ check_lock(svn_error_t **fs_err, if (SVN_IS_VALID_REVNUM(target->current_rev)) { svn_revnum_t created_rev; + + if (target->current_rev > youngest_rev) + { + *fs_err = svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL, + _("No such revision %ld"), + target->current_rev); + return SVN_NO_ERROR; + } + SVN_ERR(svn_fs_x__node_created_rev(&created_rev, root, path, pool)); @@ -850,7 +839,6 @@ check_lock(svn_error_t **fs_err, typedef struct lock_info_t { const char *path; - const char *component; svn_lock_t *lock; svn_error_t *fs_err; } lock_info_t; @@ -874,12 +862,11 @@ lock_body(void *baton, svn_fs_root_t *root; svn_revnum_t youngest; const char *rev_0_path; - int i, outstanding = 0; + int i; + apr_hash_t *index_updates = apr_hash_make(pool); + apr_hash_index_t *hi; apr_pool_t *iterpool = svn_pool_create(pool); - lb->infos = apr_array_make(lb->result_pool, lb->targets->nelts, - sizeof(lock_info_t)); - /* Until we implement directory locks someday, we only allow locks on files or non-existent paths. */ /* Use fs->vtable->foo instead of svn_fs_foo to avoid circular @@ -891,34 +878,28 @@ lock_body(void *baton, { const svn_sort__item_t *item = &APR_ARRAY_IDX(lb->targets, i, svn_sort__item_t); - const svn_fs_lock_target_t *target = item->value; lock_info_t info; svn_pool_clear(iterpool); info.path = item->key; - SVN_ERR(check_lock(&info.fs_err, info.path, target, lb, root, iterpool)); info.lock = NULL; - info.component = NULL; - APR_ARRAY_PUSH(lb->infos, lock_info_t) = info; + info.fs_err = SVN_NO_ERROR; + + SVN_ERR(check_lock(&info.fs_err, info.path, item->value, lb, root, + youngest, iterpool)); + + /* If no error occurred while pre-checking, schedule the index updates for + this path. */ if (!info.fs_err) - ++outstanding; + schedule_index_update(index_updates, info.path, iterpool); + + APR_ARRAY_PUSH(lb->infos, lock_info_t) = info; } rev_0_path = svn_fs_x__path_rev_absolute(lb->fs, 0, pool); - /* Given the paths: - - /foo/bar/f - /foo/bar/g - /zig/x - - we loop through repeatedly. The first pass sees '/' on all paths - and writes the '/' index. The second pass sees '/foo' twice and - writes that index followed by '/zig' and that index. The third - pass sees '/foo/bar' twice and writes that index, and then writes - the lock for '/zig/x'. The fourth pass writes the locks for - '/foo/bar/f' and '/foo/bar/g'. + /* We apply the scheduled index updates before writing the actual locks. Writing indices before locks is correct: if interrupted it leaves indices without locks rather than locks without indices. An @@ -927,91 +908,49 @@ lock_body(void *baton, index is inconsistent, svn_fs_x__allow_locked_operation will show locked on the file but unlocked on the parent. */ - - while (outstanding) + for (hi = apr_hash_first(pool, index_updates); hi; hi = apr_hash_next(hi)) + { + const char *path = apr_hash_this_key(hi); + apr_array_header_t *children = apr_hash_this_val(hi); + + svn_pool_clear(iterpool); + SVN_ERR(add_to_digest(lb->fs->path, children, path, rev_0_path, + iterpool)); + } + + for (i = 0; i < lb->infos->nelts; ++i) { - const char *last_path = NULL; - apr_array_header_t *paths; + struct lock_info_t *info = &APR_ARRAY_IDX(lb->infos, i, + struct lock_info_t); + svn_sort__item_t *item = &APR_ARRAY_IDX(lb->targets, i, svn_sort__item_t); + svn_fs_lock_target_t *target = item->value; svn_pool_clear(iterpool); - paths = apr_array_make(iterpool, 1, sizeof(const char *)); - for (i = 0; i < lb->infos->nelts; ++i) + if (! info->fs_err) { - lock_info_t *info = &APR_ARRAY_IDX(lb->infos, i, lock_info_t); - const svn_sort__item_t *item = &APR_ARRAY_IDX(lb->targets, i, - svn_sort__item_t); - const svn_fs_lock_target_t *target = item->value; - - if (!info->fs_err && !info->lock) - { - if (!info->component) - { - info->component = info->path; - APR_ARRAY_PUSH(paths, const char *) = info->path; - last_path = "/"; - } - else - { - info->component = strchr(info->component + 1, '/'); - if (!info->component) - { - /* The component is a path to lock, this cannot - match a previous path that need to be indexed. */ - if (paths->nelts) - { - SVN_ERR(add_to_digest(lb->fs->path, paths, last_path, - rev_0_path, iterpool)); - apr_array_clear(paths); - last_path = NULL; - } - - info->lock = svn_lock_create(lb->result_pool); - if (target->token) - info->lock->token = target->token; - else - SVN_ERR(svn_fs_x__generate_lock_token( - &(info->lock->token), lb->fs, - lb->result_pool)); - info->lock->path = info->path; - info->lock->owner = lb->fs->access_ctx->username; - info->lock->comment = lb->comment; - info->lock->is_dav_comment = lb->is_dav_comment; - info->lock->creation_date = apr_time_now(); - info->lock->expiration_date = lb->expiration_date; - - info->fs_err = set_lock(lb->fs->path, info->lock, - rev_0_path, iterpool); - --outstanding; - } - else - { - /* The component is a path to an index. */ - apr_size_t len = info->component - info->path; - - if (last_path - && (strncmp(last_path, info->path, len) - || strlen(last_path) != len)) - { - /* No match to the previous paths to index. */ - SVN_ERR(add_to_digest(lb->fs->path, paths, last_path, - rev_0_path, iterpool)); - apr_array_clear(paths); - last_path = NULL; - } - APR_ARRAY_PUSH(paths, const char *) = info->path; - if (!last_path) - last_path = apr_pstrndup(iterpool, info->path, len); - } - } - } - - if (last_path && i == lb->infos->nelts - 1) - SVN_ERR(add_to_digest(lb->fs->path, paths, last_path, - rev_0_path, iterpool)); + info->lock = svn_lock_create(lb->result_pool); + if (target->token) + info->lock->token = apr_pstrdup(lb->result_pool, target->token); + else + SVN_ERR(svn_fs_x__generate_lock_token(&(info->lock->token), lb->fs, + lb->result_pool)); + + /* The INFO->PATH is already allocated in LB->RESULT_POOL as a result + of svn_fspath__canonicalize() (see svn_fs_fs__lock()). */ + info->lock->path = info->path; + info->lock->owner = apr_pstrdup(lb->result_pool, + lb->fs->access_ctx->username); + info->lock->comment = apr_pstrdup(lb->result_pool, lb->comment); + info->lock->is_dav_comment = lb->is_dav_comment; + info->lock->creation_date = apr_time_now(); + info->lock->expiration_date = lb->expiration_date; + + info->fs_err = set_lock(lb->fs->path, info->lock, rev_0_path, + iterpool); } } - + return SVN_NO_ERROR; } @@ -1052,10 +991,8 @@ check_unlock(svn_error_t **fs_err, typedef struct unlock_info_t { const char *path; - const char *component; svn_error_t *fs_err; svn_boolean_t done; - int components; } unlock_info_t; /* The body of svn_fs_x__unlock(), which see. @@ -1077,12 +1014,11 @@ unlock_body(void *baton, svn_fs_root_t *root; svn_revnum_t youngest; const char *rev_0_path; - int i, max_components = 0, outstanding = 0; + int i; + apr_hash_t *indices_updates = apr_hash_make(pool); + apr_hash_index_t *hi; apr_pool_t *iterpool = svn_pool_create(pool); - ub->infos = apr_array_make(ub->result_pool, ub->targets->nelts, - sizeof( unlock_info_t)); - SVN_ERR(ub->fs->vtable->youngest_rev(&youngest, ub->fs, pool)); SVN_ERR(ub->fs->vtable->revision_root(&root, ub->fs, youngest, pool)); @@ -1091,95 +1027,56 @@ unlock_body(void *baton, const svn_sort__item_t *item = &APR_ARRAY_IDX(ub->targets, i, svn_sort__item_t); const char *token = item->value; - unlock_info_t info = { 0 }; + unlock_info_t info; svn_pool_clear(iterpool); info.path = item->key; + info.fs_err = SVN_NO_ERROR; + info.done = FALSE; + if (!ub->skip_check) SVN_ERR(check_unlock(&info.fs_err, info.path, token, ub, root, iterpool)); - if (!info.fs_err) - { - const char *s; - - info.components = 1; - info.component = info.path; - while((s = strchr(info.component + 1, '/'))) - { - info.component = s; - ++info.components; - } - if (info.components > max_components) - max_components = info.components; + /* If no error occurred while pre-checking, schedule the index updates for + this path. */ + if (!info.fs_err) + schedule_index_update(indices_updates, info.path, iterpool); - ++outstanding; - } APR_ARRAY_PUSH(ub->infos, unlock_info_t) = info; } rev_0_path = svn_fs_x__path_rev_absolute(ub->fs, 0, pool); - for (i = max_components; i >= 0; --i) + /* Unlike the lock_body(), we need to delete locks *before* we start to + update indices. */ + + for (i = 0; i < ub->infos->nelts; ++i) { - const char *last_path = NULL; - apr_array_header_t *paths; - int j; + struct unlock_info_t *info = &APR_ARRAY_IDX(ub->infos, i, + struct unlock_info_t); svn_pool_clear(iterpool); - paths = apr_array_make(pool, 1, sizeof(const char *)); - for (j = 0; j < ub->infos->nelts; ++j) + if (! info->fs_err) { - unlock_info_t *info = &APR_ARRAY_IDX(ub->infos, j, unlock_info_t); + SVN_ERR(delete_lock(ub->fs->path, info->path, iterpool)); + info->done = TRUE; + } + } - if (!info->fs_err && info->path) - { + for (hi = apr_hash_first(pool, indices_updates); hi; hi = apr_hash_next(hi)) + { + const char *path = apr_hash_this_key(hi); + apr_array_header_t *children = apr_hash_this_val(hi); - if (info->components == i) - { - SVN_ERR(delete_lock(ub->fs->path, info->path, iterpool)); - info->done = TRUE; - } - else if (info->components > i) - { - apr_size_t len = info->component - info->path; - - if (last_path - && strcmp(last_path, "/") - && (strncmp(last_path, info->path, len) - || strlen(last_path) != len)) - { - SVN_ERR(delete_from_digest(ub->fs->path, paths, last_path, - rev_0_path, iterpool)); - apr_array_clear(paths); - last_path = NULL; - } - APR_ARRAY_PUSH(paths, const char *) = info->path; - if (!last_path) - { - if (info->component > info->path) - last_path = apr_pstrndup(pool, info->path, len); - else - last_path = "/"; - } - - if (info->component > info->path) - { - --info->component; - while(info->component[0] != '/') - --info->component; - } - } - } - - if (last_path && j == ub->infos->nelts - 1) - SVN_ERR(delete_from_digest(ub->fs->path, paths, last_path, - rev_0_path, iterpool)); - } + svn_pool_clear(iterpool); + SVN_ERR(delete_from_digest(ub->fs->path, children, path, rev_0_path, + iterpool)); } + svn_pool_destroy(iterpool); return SVN_NO_ERROR; } @@ -1203,6 +1100,8 @@ unlock_single(svn_fs_t *fs, ub.fs = fs; ub.targets = targets; + ub.infos = apr_array_make(scratch_pool, targets->nelts, + sizeof(struct unlock_info_t)); ub.skip_check = TRUE; ub.result_pool = scratch_pool; @@ -1231,6 +1130,7 @@ svn_fs_x__lock(svn_fs_t *fs, apr_array_header_t *sorted_targets; apr_hash_t *canonical_targets = apr_hash_make(scratch_pool); apr_hash_index_t *hi; + apr_pool_t *iterpool; svn_error_t *err, *cb_err = SVN_NO_ERROR; int i; @@ -1263,29 +1163,34 @@ svn_fs_x__lock(svn_fs_t *fs, lb.fs = fs; lb.targets = sorted_targets; + lb.infos = apr_array_make(scratch_pool, sorted_targets->nelts, + sizeof(struct lock_info_t)); lb.comment = comment; lb.is_dav_comment = is_dav_comment; lb.expiration_date = expiration_date; lb.steal_lock = steal_lock; lb.result_pool = result_pool; - err = svn_fs_x__with_write_lock(fs, lock_body, &lb, scratch_pool); + iterpool = svn_pool_create(scratch_pool); + err = svn_fs_x__with_write_lock(fs, lock_body, &lb, iterpool); for (i = 0; i < lb.infos->nelts; ++i) { struct lock_info_t *info = &APR_ARRAY_IDX(lb.infos, i, struct lock_info_t); + svn_pool_clear(iterpool); if (!cb_err && lock_callback) { if (!info->lock && !info->fs_err) info->fs_err = svn_error_createf(SVN_ERR_FS_LOCK_OPERATION_FAILED, 0, _("Failed to lock '%s'"), info->path); - + cb_err = lock_callback(lock_baton, info->path, info->lock, - info->fs_err, scratch_pool); + info->fs_err, iterpool); } svn_error_clear(info->fs_err); } + svn_pool_destroy(iterpool); if (err && cb_err) svn_error_compose(err, cb_err); @@ -1325,6 +1230,7 @@ svn_fs_x__unlock(svn_fs_t *fs, apr_array_header_t *sorted_targets; apr_hash_t *canonical_targets = apr_hash_make(scratch_pool); apr_hash_index_t *hi; + apr_pool_t *iterpool; svn_error_t *err, *cb_err = SVN_NO_ERROR; int i; @@ -1353,14 +1259,18 @@ svn_fs_x__unlock(svn_fs_t *fs, ub.fs = fs; ub.targets = sorted_targets; + ub.infos = apr_array_make(scratch_pool, sorted_targets->nelts, + sizeof(struct unlock_info_t)); ub.skip_check = FALSE; ub.break_lock = break_lock; ub.result_pool = result_pool; - err = svn_fs_x__with_write_lock(fs, unlock_body, &ub, scratch_pool); + iterpool = svn_pool_create(scratch_pool); + err = svn_fs_x__with_write_lock(fs, unlock_body, &ub, iterpool); for (i = 0; i < ub.infos->nelts; ++i) { unlock_info_t *info = &APR_ARRAY_IDX(ub.infos, i, unlock_info_t); + svn_pool_clear(iterpool); if (!cb_err && lock_callback) { if (!info->done && !info->fs_err) @@ -1368,10 +1278,11 @@ svn_fs_x__unlock(svn_fs_t *fs, 0, _("Failed to unlock '%s'"), info->path); cb_err = lock_callback(lock_baton, info->path, NULL, info->fs_err, - scratch_pool); + iterpool); } svn_error_clear(info->fs_err); } + svn_pool_destroy(iterpool); if (err && cb_err) svn_error_compose(err, cb_err);
Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.h Sun Jun 14 20:58:10 2015 @@ -60,7 +60,7 @@ svn_fs_x__unlock(svn_fs_t *fs, void *lock_baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool); - + /* See svn_fs_get_lock(). */ svn_error_t * svn_fs_x__get_lock(svn_lock_t **lock, Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.c Sun Jun 14 20:58:10 2015 @@ -587,7 +587,7 @@ format_digest(const unsigned char *diges svn_checksum_t checksum; checksum.digest = digest; checksum.kind = kind; - + if (is_null) return "(null)"; @@ -753,7 +753,7 @@ svn_fs_x__write_rep_header(svn_fs_x__rep apr_pool_t *scratch_pool) { const char *text; - + switch (header->type) { case svn_fs_x__rep_self_delta: @@ -999,7 +999,7 @@ svn_fs_x__read_changes_incrementally(svn } while (change); svn_pool_destroy(iterpool); - + return SVN_NO_ERROR; } Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.h Sun Jun 14 20:58:10 2015 @@ -49,7 +49,7 @@ extern "C" { * and return the start offsets of the index data in *L2P_OFFSET and * *P2L_OFFSET, respectively. Also, return the expected checksums in * in *L2P_CHECKSUM and *P2L_CHECKSUM. - * + * * Note that REV is only used to construct nicer error objects that * mention this revision. Allocate the checksums in RESULT_POOL. */ @@ -160,7 +160,7 @@ svn_fs_x__read_rep_header(svn_fs_x__rep_ apr_pool_t *result_pool, apr_pool_t *scratch_pool); -/* Write the representation HEADER to STREAM. +/* Write the representation HEADER to STREAM. * Use SCRATCH_POOL for allocations. */ svn_error_t * svn_fs_x__write_rep_header(svn_fs_x__rep_header_t *header, Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/noderevs.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/noderevs.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/noderevs.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/noderevs.c Sun Jun 14 20:58:10 2015 @@ -50,7 +50,7 @@ #define NODEREV_HAS_CPATH 0x00040 /* Our internal representation of a svn_fs_x__noderev_t. - * + * * We will store path strings in a string container and reference them * from here. Similarly, IDs and representations are being stored in * separate containers and then also referenced here. This eliminates @@ -274,7 +274,7 @@ svn_fs_x__noderevs_add(svn_fs_x__noderev 0); binary_noderev.mergeinfo_count = noderev->mergeinfo_count; - + APR_ARRAY_PUSH(container->noderevs, binary_noderev_t) = binary_noderev; return container->noderevs->nelts - 1; @@ -574,7 +574,7 @@ svn_fs_x__write_noderevs_container(svn_s /* write to disk */ SVN_ERR(svn_fs_x__write_string_table(stream, paths, scratch_pool)); SVN_ERR(svn_packed__data_write(stream, root, scratch_pool)); - + return SVN_NO_ERROR; } @@ -725,7 +725,7 @@ svn_fs_x__read_noderevs_container(svn_fs } *container = noderevs; - + return SVN_NO_ERROR; } @@ -906,7 +906,7 @@ svn_fs_x__mergeinfo_count_get_func(void /* Resolve all container pointers */ resolve_apr_array_header(&noderevs, container, &container->noderevs); binary_noderev = &APR_ARRAY_IDX(&noderevs, idx, binary_noderev_t); - + *(apr_int64_t *)out = binary_noderev->mergeinfo_count; return SVN_NO_ERROR; Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.c Sun Jun 14 20:58:10 2015 @@ -70,7 +70,7 @@ * each of the 4 buckets separately. The first three will simply order * their items by revision, starting with the newest once. Placing rep * and noderev items is a more elaborate process documented in the code. - * + * * In short, we store items in the following order: * - changed paths lists * - node property @@ -269,7 +269,7 @@ initialize_pack_context(pack_context_t * context->start_rev = shard_rev; context->end_rev = shard_rev; context->shard_end_rev = shard_rev + ffd->max_files_per_dir; - + /* Create the new directory and pack file. */ context->shard_dir = shard_dir; context->pack_file_dir = pack_file_dir; @@ -346,7 +346,7 @@ reset_pack_context(pack_context_t *conte SVN_ERR(svn_io_file_trunc(context->reps_file, 0, scratch_pool)); svn_pool_clear(context->info_pool); - + return SVN_NO_ERROR; } @@ -375,7 +375,7 @@ close_pack_context(pack_context_t *conte SVN_ERR(svn_fs_x__add_index_data(context->fs, context->pack_file, proto_l2p_index_path, proto_p2l_index_path, - context->shard_rev, + context->shard_rev, scratch_pool)); /* remove proto index files */ @@ -401,7 +401,7 @@ copy_file_data(pack_context_t *context, /* most non-representation items will be small. Minimize the buffer * and infrastructure overhead in that case. */ enum { STACK_BUFFER_SIZE = 1024 }; - + if (size < STACK_BUFFER_SIZE) { /* copy small data using a fixed-size buffer on stack */ @@ -630,13 +630,14 @@ compare_dir_entries(const svn_sort__item apr_array_header_t * svn_fs_x__order_dir_entries(svn_fs_t *fs, apr_hash_t *directory, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { apr_array_header_t *ordered - = svn_sort__hash(directory, compare_dir_entries, pool); + = svn_sort__hash(directory, compare_dir_entries, scratch_pool); apr_array_header_t *result - = apr_array_make(pool, ordered->nelts, sizeof(svn_fs_dirent_t *)); + = apr_array_make(result_pool, ordered->nelts, sizeof(svn_fs_dirent_t *)); int i; for (i = 0; i < ordered->nelts; ++i) @@ -757,7 +758,7 @@ compare_p2l_info(const svn_fs_x__p2l_ent return (*lhs)->item_count == 0 ? 0 : -1; if ((*lhs)->item_count == 0) return 1; - + if ((*lhs)->items[0].change_set == (*rhs)->items[0].change_set) return (*lhs)->items[0].number > (*rhs)->items[0].number ? -1 : 1; @@ -850,7 +851,7 @@ auto_pad_block(pack_context_t *context, apr_pool_t *scratch_pool) { svn_fs_x__data_t *ffd = context->fs->fsap_data; - + /* This is the maximum number of bytes "wasted" that way per block. * Larger items will cross the block boundaries. */ const apr_off_t max_padding = MAX(ffd->block_size / 50, 512); @@ -881,7 +882,7 @@ auto_pad_block(pack_context_t *context, return SVN_NO_ERROR; } -/* Return the index of the first entry in CONTEXT->REFERENCES that +/* Return the index of the first entry in CONTEXT->REFERENCES that * references ITEM->ITEMS[0] if such entries exist. All matching items * will be consecutive. */ @@ -894,7 +895,7 @@ find_first_reference(pack_context_t *con while (lower <= upper) { - int current = lower + (upper - lower) / 2; + int current = lower + (upper - lower) / 2; reference_t *reference = APR_ARRAY_IDX(context->references, current, reference_t *); @@ -1013,7 +1014,7 @@ reps_fit_into_containers(apr_array_heade return TRUE; } -/* Write the *CONTAINER containing the noderevs described by the +/* Write the *CONTAINER containing the noderevs described by the * svn_fs_x__p2l_entry_t * in ITEMS to the pack file on CONTEXT. * Append a P2L entry for the container to CONTAINER->REPS. * Afterwards, clear ITEMS and re-allocate *CONTAINER in CONTAINER_POOL @@ -1080,8 +1081,8 @@ write_nodes_container(pack_context_t *co * from TEMP_FILE and add them to *CONTAINER and NODES_IN_CONTAINER. * Whenever the container grows bigger than the current block in CONTEXT, * write the data to disk and continue in the next block. - * - * Use CONTAINER_POOL to re-allocate the *CONTAINER as necessary and + * + * Use CONTAINER_POOL to re-allocate the *CONTAINER as necessary and * SCRATCH_POOL to temporary allocations. */ static svn_error_t * @@ -1438,7 +1439,7 @@ copy_reps_from_temp(pack_context_t *cont nodes_in_container, container_pool, iterpool)); /* actually flush the noderevs to disk if the reps container is likely - * to fill the block, i.e. no further noderevs will be added to the + * to fill the block, i.e. no further noderevs will be added to the * nodes container. */ if (should_flush_nodes_container(context, nodes_container, node_parts)) SVN_ERR(write_nodes_container(context, &nodes_container, @@ -1739,7 +1740,7 @@ pack_range(pack_context_t *context, /* store the indirect array index */ APR_ARRAY_PUSH(context->rev_offsets, int) = context->reps->nelts; - + /* read the phys-to-log index file until we covered the whole rev file. * That index contains enough info to build both target indexes from it. */ while (offset < l2p_index_info.start) @@ -1834,7 +1835,7 @@ pack_range(pack_context_t *context, SVN_ERR(write_l2p_index(context, revpool)); svn_pool_destroy(revpool); - + return SVN_NO_ERROR; } Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.h Sun Jun 14 20:58:10 2015 @@ -51,13 +51,15 @@ svn_fs_x__get_packed_offset(apr_off_t *r apr_pool_t *scratch_pool); /* Return the svn_dir_entry_t* objects of DIRECTORY in an APR array - * allocated in POOL with entries added in storage (on-disk) order. - * FS format will be used to pick the optimal ordering strategy. + * allocated in RESULT_POOL with entries added in storage (on-disk) order. + * FS' format will be used to pick the optimal ordering strategy. Use + * SCRATCH_POOL for temporary allocations. */ apr_array_header_t * svn_fs_x__order_dir_entries(svn_fs_t *fs, apr_hash_t *directory, - apr_pool_t *pool); + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); #endif Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache-db.sql URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache-db.sql?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache-db.sql (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache-db.sql Sun Jun 14 20:58:10 2015 @@ -65,3 +65,6 @@ WHERE revision > ?1 -- STMT_LOCK_REP BEGIN TRANSACTION; INSERT INTO rep_cache VALUES ('dummy', 0, 0, 0, 0) + +-- STMT_UNLOCK_REP +ROLLBACK TRANSACTION; Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.c Sun Jun 14 20:58:10 2015 @@ -369,16 +369,48 @@ svn_fs_x__del_rep_reference(svn_fs_t *fs return SVN_NO_ERROR; } -svn_error_t * -svn_fs_x__lock_rep_cache(svn_fs_t *fs, - apr_pool_t *scratch_pool) +/* Start a transaction to take an SQLite reserved lock that prevents + other writes. + + See unlock_rep_cache(). */ +static svn_error_t * +lock_rep_cache(svn_fs_t *fs, + apr_pool_t *pool) { svn_fs_x__data_t *ffd = fs->fsap_data; if (! ffd->rep_cache_db) - SVN_ERR(svn_fs_x__open_rep_cache(fs, scratch_pool)); + SVN_ERR(svn_fs_x__open_rep_cache(fs, pool)); SVN_ERR(svn_sqlite__exec_statements(ffd->rep_cache_db, STMT_LOCK_REP)); return SVN_NO_ERROR; } + +/* End the transaction started by lock_rep_cache(). */ +static svn_error_t * +unlock_rep_cache(svn_fs_t *fs, + apr_pool_t *pool) +{ + svn_fs_x__data_t *ffd = fs->fsap_data; + + SVN_ERR_ASSERT(ffd->rep_cache_db); /* was opened by lock_rep_cache() */ + + SVN_ERR(svn_sqlite__exec_statements(ffd->rep_cache_db, STMT_UNLOCK_REP)); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__with_rep_cache_lock(svn_fs_t *fs, + svn_error_t *(*body)(void *, + apr_pool_t *), + void *baton, + apr_pool_t *pool) +{ + svn_error_t *err; + + SVN_ERR(lock_rep_cache(fs, pool)); + err = body(baton, pool); + return svn_error_compose_create(err, unlock_rep_cache(fs, pool)); +} Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.h Sun Jun 14 20:58:10 2015 @@ -88,12 +88,16 @@ svn_fs_x__del_rep_reference(svn_fs_t *fs svn_revnum_t youngest, apr_pool_t *scratch_pool); + /* Start a transaction to take an SQLite reserved lock that prevents - other writes. */ + other writes, call BODY, end the transaction, and return what BODY returned. + */ svn_error_t * -svn_fs_x__lock_rep_cache(svn_fs_t *fs, - apr_pool_t *scratch_pool); - +svn_fs_x__with_rep_cache_lock(svn_fs_t *fs, + svn_error_t *(*body)(void *baton, + apr_pool_t *pool), + void *baton, + apr_pool_t *pool); #ifdef __cplusplus } #endif /* __cplusplus */ Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/reps.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/reps.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/reps.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/reps.c Sun Jun 14 20:58:10 2015 @@ -34,7 +34,7 @@ /* Length of the text chunks we hash and match. The algorithm will find * most matches with a length of 2 * MATCH_BLOCKSIZE and only specific * ones that are shorter than MATCH_BLOCKSIZE. - * + * * This should be a power of two and must be a multiple of 8. * Good choices are 32, 64 and 128. */ @@ -55,7 +55,7 @@ /* Byte strings are described by a series of copy instructions that each * do one of the following - * + * * - copy a given number of bytes from the text corpus starting at a * given offset * - reference other instruction and specify how many of instructions of @@ -244,7 +244,7 @@ struct svn_fs_x__rep_extractor_t /* bases (base_t) yet to process (not used ATM) */ apr_array_header_t *bases; - + /* missing sections (missing_t) in result->data that need to be filled, * yet */ apr_array_header_t *missing; @@ -627,7 +627,7 @@ get_text(svn_fs_x__rep_extractor_t *extr missing.count = instruction->count; missing.offset = instruction->offset; svn_stringbuf_appendfill(extractor->result, 0, instruction->count); - + if (extractor->missing == NULL) extractor->missing = apr_array_make(extractor->pool, 1, sizeof(missing)); @@ -724,7 +724,7 @@ svn_fs_x__write_reps_container(svn_strea svn_packed__create_int_substream(instructions_stream, TRUE, TRUE); svn_packed__create_int_substream(instructions_stream, FALSE, FALSE); - + /* text */ svn_packed__add_bytes(text_stream, builder->text->data, builder->text->len); @@ -761,7 +761,7 @@ svn_fs_x__write_reps_container(svn_strea /* write to stream */ SVN_ERR(svn_packed__data_write(stream, root, scratch_pool)); - + return SVN_NO_ERROR; } @@ -788,7 +788,7 @@ svn_fs_x__read_reps_container(svn_fs_x__ /* read from disk */ SVN_ERR(svn_packed__data_read(&root, stream, result_pool, scratch_pool)); - + bases_stream = svn_packed__first_int_stream(root); reps_stream = svn_packed__next_int_stream(bases_stream); instructions_stream = svn_packed__next_int_stream(reps_stream); @@ -849,7 +849,7 @@ svn_fs_x__read_reps_container(svn_fs_x__ /* return result */ *container = reps; - + return SVN_NO_ERROR; } @@ -925,7 +925,7 @@ svn_fs_x__reps_get_func(void **out, apr_pool_t *pool) { svn_fs_x__reps_baton_t *reps_baton = baton; - + /* get a usable reps structure */ const svn_fs_x__reps_t *cached = data; svn_fs_x__reps_t *reps = apr_pmemdup(pool, cached, sizeof(*reps)); Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rev_file.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rev_file.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rev_file.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rev_file.c Sun Jun 14 20:58:10 2015 @@ -217,7 +217,7 @@ open_pack_or_rev_file(svn_fs_x__revision /* We may have to *temporarily* enable write access. */ err = writable ? auto_make_writable(path, file_pool, scratch_pool) - : SVN_NO_ERROR; + : SVN_NO_ERROR; /* open the revision file in buffered r/o or r/w mode */ if (!err) Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.c Sun Jun 14 20:58:10 2015 @@ -574,7 +574,7 @@ typedef struct packed_revprops_t * our file system, the revprops belong to REVISION and the global revprop * GENERATION is used as well. * - * The returned hash will be allocated in RESULT_POOL, SCRATCH_POOL is + * The returned hash will be allocated in RESULT_POOL, SCRATCH_POOL is * being used for temporary allocations. */ static svn_error_t * @@ -809,7 +809,8 @@ parse_packed_revprops(svn_fs_t *fs, * length header to remove) */ svn_stringbuf_t *compressed = revprops->packed_revprops; svn_stringbuf_t *uncompressed = svn_stringbuf_create_empty(result_pool); - SVN_ERR(svn__decompress(compressed, uncompressed, APR_SIZE_MAX)); + SVN_ERR(svn__decompress(compressed->data, compressed->len, + uncompressed, APR_SIZE_MAX)); /* read first revision number and number of revisions in the pack */ stream = svn_stream_from_stringbuf(uncompressed, scratch_pool); @@ -856,7 +857,7 @@ parse_packed_revprops(svn_fs_t *fs, if (read_all) { /* Init / construct REVPROPS members. */ - revprops->sizes = apr_array_make(result_pool, (int)count, + revprops->sizes = apr_array_make(result_pool, (int)count, sizeof(offset)); revprops->offsets = apr_array_make(result_pool, (int)count, sizeof(offset)); @@ -1092,20 +1093,26 @@ write_non_packed_revprop(const char **fi apr_pool_t *result_pool, apr_pool_t *scratch_pool) { + apr_file_t *file; svn_stream_t *stream; *final_path = svn_fs_x__path_revprops(fs, rev, result_pool); /* ### do we have a directory sitting around already? we really shouldn't ### have to get the dirname here. */ - SVN_ERR(svn_stream_open_unique(&stream, tmp_path, - svn_dirent_dirname(*final_path, - scratch_pool), - svn_io_file_del_none, - result_pool, scratch_pool)); + SVN_ERR(svn_io_open_unique_file3(&file, tmp_path, + svn_dirent_dirname(*final_path, + scratch_pool), + svn_io_file_del_none, + scratch_pool, scratch_pool)); + stream = svn_stream_from_aprfile2(file, TRUE, scratch_pool); SVN_ERR(svn_hash_write2(proplist, stream, SVN_HASH_TERMINATOR, scratch_pool)); SVN_ERR(svn_stream_close(stream)); + /* Flush temporary file to disk and close it. */ + SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool)); + SVN_ERR(svn_io_file_close(file, scratch_pool)); + return SVN_NO_ERROR; } @@ -1201,7 +1208,7 @@ serialize_revprops_header(svn_stream_t * return SVN_NO_ERROR; } -/* Writes the a pack file to FILE_STREAM. It copies the serialized data +/* Writes the a pack file to FILE. It copies the serialized data * from REVPROPS for the indexes [START,END) except for index CHANGED_INDEX. * * The data for the latter is taken from NEW_SERIALIZED. Note, that @@ -1219,7 +1226,7 @@ repack_revprops(svn_fs_t *fs, int changed_index, svn_stringbuf_t *new_serialized, apr_off_t new_total_size, - svn_stream_t *file_stream, + apr_file_t *file, apr_pool_t *scratch_pool) { svn_fs_x__data_t *ffd = fs->fsap_data; @@ -1262,15 +1269,17 @@ repack_revprops(svn_fs_t *fs, SVN_ERR(svn_stream_close(stream)); /* compress / store the data */ - SVN_ERR(svn__compress(uncompressed, + SVN_ERR(svn__compress(uncompressed->data, uncompressed->len, compressed, ffd->compress_packed_revprops ? SVN_DELTA_COMPRESSION_LEVEL_DEFAULT : SVN_DELTA_COMPRESSION_LEVEL_NONE)); - /* finally, write the content to the target stream and close it */ - SVN_ERR(svn_stream_write(file_stream, compressed->data, &compressed->len)); - SVN_ERR(svn_stream_close(file_stream)); + /* finally, write the content to the target file, flush and close it */ + SVN_ERR(svn_io_file_write_full(file, compressed->data, compressed->len, + NULL, scratch_pool)); + SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool)); + SVN_ERR(svn_io_file_close(file, scratch_pool)); return SVN_NO_ERROR; } @@ -1278,27 +1287,26 @@ repack_revprops(svn_fs_t *fs, /* Allocate a new pack file name for revisions * [REVPROPS->START_REVISION + START, REVPROPS->START_REVISION + END - 1] * of REVPROPS->MANIFEST. Add the name of old file to FILES_TO_DELETE, - * auto-create that array if necessary. Return an open file stream to - * the new file in *STREAM allocated in RESULT_POOL. Allocate the paths - * in *FILES_TO_DELETE from the same pool that contains the array itself. + * auto-create that array if necessary. Return an open file *FILE that is + * allocated in RESULT_POOL. Allocate the paths in *FILES_TO_DELETE from + * the same pool that contains the array itself. * * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * -repack_stream_open(svn_stream_t **stream, - svn_fs_t *fs, - packed_revprops_t *revprops, - int start, - int end, - apr_array_header_t **files_to_delete, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +repack_file_open(apr_file_t **file, + svn_fs_t *fs, + packed_revprops_t *revprops, + int start, + int end, + apr_array_header_t **files_to_delete, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { apr_int64_t tag; const char *tag_string; svn_string_t *new_filename; int i; - apr_file_t *file; int manifest_offset = (int)(revprops->start_revision - revprops->manifest_start); @@ -1332,13 +1340,12 @@ repack_stream_open(svn_stream_t **stream APR_ARRAY_IDX(revprops->manifest, i + manifest_offset, const char*) = new_filename->data; - /* create a file stream for the new file */ - SVN_ERR(svn_io_file_open(&file, svn_dirent_join(revprops->folder, - new_filename->data, - scratch_pool), + /* open the file */ + SVN_ERR(svn_io_file_open(file, svn_dirent_join(revprops->folder, + new_filename->data, + scratch_pool), APR_WRITE | APR_CREATE, APR_OS_DEFAULT, result_pool)); - *stream = svn_stream_from_aprfile2(file, FALSE, result_pool); return SVN_NO_ERROR; } @@ -1364,6 +1371,7 @@ write_packed_revprop(const char **final_ packed_revprops_t *revprops; apr_int64_t generation = 0; svn_stream_t *stream; + apr_file_t *file; svn_stringbuf_t *serialized; apr_off_t new_total_size; int changed_index; @@ -1401,12 +1409,12 @@ write_packed_revprop(const char **final_ *final_path = svn_dirent_join(revprops->folder, revprops->filename, result_pool); - SVN_ERR(svn_stream_open_unique(&stream, tmp_path, revprops->folder, - svn_io_file_del_none, result_pool, - scratch_pool)); + SVN_ERR(svn_io_open_unique_file3(&file, tmp_path, revprops->folder, + svn_io_file_del_none, result_pool, + scratch_pool)); SVN_ERR(repack_revprops(fs, revprops, 0, revprops->sizes->nelts, changed_index, serialized, new_total_size, - stream, scratch_pool)); + file, scratch_pool)); } else { @@ -1458,54 +1466,57 @@ write_packed_revprop(const char **final_ /* write the new, split files */ if (left_count) { - SVN_ERR(repack_stream_open(&stream, fs, revprops, 0, - left_count, files_to_delete, - scratch_pool, scratch_pool)); + SVN_ERR(repack_file_open(&file, fs, revprops, 0, + left_count, files_to_delete, + scratch_pool, scratch_pool)); SVN_ERR(repack_revprops(fs, revprops, 0, left_count, changed_index, serialized, new_total_size, - stream, scratch_pool)); + file, scratch_pool)); } if (left_count + right_count < revprops->sizes->nelts) { - SVN_ERR(repack_stream_open(&stream, fs, revprops, changed_index, - changed_index + 1, files_to_delete, - scratch_pool, scratch_pool)); + SVN_ERR(repack_file_open(&file, fs, revprops, changed_index, + changed_index + 1, files_to_delete, + scratch_pool, scratch_pool)); SVN_ERR(repack_revprops(fs, revprops, changed_index, changed_index + 1, changed_index, serialized, new_total_size, - stream, scratch_pool)); + file, scratch_pool)); } if (right_count) { - SVN_ERR(repack_stream_open(&stream, fs, revprops, - revprops->sizes->nelts - right_count, - revprops->sizes->nelts, - files_to_delete, scratch_pool, - scratch_pool)); + SVN_ERR(repack_file_open(&file, fs, revprops, + revprops->sizes->nelts - right_count, + revprops->sizes->nelts, + files_to_delete, scratch_pool, + scratch_pool)); SVN_ERR(repack_revprops(fs, revprops, revprops->sizes->nelts - right_count, revprops->sizes->nelts, changed_index, - serialized, new_total_size, stream, + serialized, new_total_size, file, scratch_pool)); } /* write the new manifest */ *final_path = svn_dirent_join(revprops->folder, PATH_MANIFEST, result_pool); - SVN_ERR(svn_stream_open_unique(&stream, tmp_path, revprops->folder, - svn_io_file_del_none, result_pool, - scratch_pool)); + SVN_ERR(svn_io_open_unique_file3(&file, tmp_path, revprops->folder, + svn_io_file_del_none, result_pool, + scratch_pool)); for (i = 0; i < revprops->manifest->nelts; ++i) { const char *filename = APR_ARRAY_IDX(revprops->manifest, i, const char*); - SVN_ERR(svn_stream_printf(stream, scratch_pool, "%s\n", filename)); + SVN_ERR(svn_io_file_write_full(file, filename, strlen(filename), + NULL, scratch_pool)); + SVN_ERR(svn_io_file_putc('\n', file, scratch_pool)); } - SVN_ERR(svn_stream_close(stream)); + SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool)); + SVN_ERR(svn_io_file_close(file, scratch_pool)); } return SVN_NO_ERROR; @@ -1722,7 +1733,8 @@ copy_revprops(svn_fs_t *fs, SVN_ERR(svn_stream_close(pack_stream)); /* compress the content (or just store it for COMPRESSION_LEVEL 0) */ - SVN_ERR(svn__compress(uncompressed, compressed, compression_level)); + SVN_ERR(svn__compress(uncompressed->data, uncompressed->len, + compressed, compression_level)); /* write the pack file content to disk */ stream = svn_stream_from_aprfile2(pack_file, FALSE, scratch_pool); @@ -1841,4 +1853,3 @@ svn_fs_x__pack_revprops_shard(svn_fs_t * return SVN_NO_ERROR; } - Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.h Sun Jun 14 20:58:10 2015 @@ -64,7 +64,7 @@ svn_fs_x__set_revision_proplist(svn_fs_t /* Return TRUE, if for REVISION in FS, we can find the revprop pack file. * Use SCRATCH_POOL for temporary allocations. - * Set *MISSING, if the reason is a missing manifest or pack file. + * Set *MISSING, if the reason is a missing manifest or pack file. */ svn_boolean_t svn_fs_x__packed_revprop_available(svn_boolean_t *missing, Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.c Sun Jun 14 20:58:10 2015 @@ -128,7 +128,7 @@ svn_fs_x__string_table_builder_create(ap result->tables = apr_array_make(result_pool, 1, sizeof(builder_table_t *)); add_table(result); - + return result; } @@ -146,7 +146,7 @@ balance(builder_table_t *table, node->left->right = node; *parent = node->left; node->left = temp; - + --left_height; } else if (left_height + 1 < right_height) @@ -370,7 +370,7 @@ svn_fs_x__string_table_builder_estimate_ /* ZIP compression should give us a 50% reduction. * add some static overhead */ return 200 + total / 2; - + } static void @@ -458,7 +458,7 @@ svn_fs_x__string_table_create(const stri apr_pool_t *result_pool) { apr_size_t i; - + string_table_t *result = apr_pcalloc(result_pool, sizeof(*result)); result->size = (apr_size_t)builder->tables->nelts; result->sub_tables @@ -612,7 +612,7 @@ svn_fs_x__write_string_table(svn_stream_ svn_packed__add_uint(table_sizes, table->size); /* all short-string char data sizes */ - + for (i = 0; i < table->size; ++i) svn_packed__add_uint(table_sizes, table->sub_tables[i].short_string_count); @@ -662,7 +662,7 @@ svn_fs_x__read_string_table(string_table apr_size_t i, k; string_table_t *table = apr_palloc(result_pool, sizeof(*table)); - + svn_packed__data_root_t *root; svn_packed__int_stream_t *table_sizes; svn_packed__byte_stream_t *large_strings; @@ -789,7 +789,7 @@ svn_fs_x__serialize_string_table(svn_tem (const void * const *)&string->data, string->len + 1); } - + svn_temp_serializer__pop(context); } @@ -804,7 +804,7 @@ svn_fs_x__deserialize_string_table(void { apr_size_t i, k; string_sub_table_t *sub_tables; - + svn_temp_deserializer__resolve(buffer, (void **)table); if (*table == NULL) return; Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.h Sun Jun 14 20:58:10 2015 @@ -32,7 +32,7 @@ extern "C" { /* A string table is a very space efficient, read-only representation for * a set of strings with high degreed of prefix and postfix overhead. - * + * * Creating a string table is a two-stage process: Use a builder class, * stuff all the strings in there and let it then do the heavy lifting of * classification and compression to create the actual string table object. @@ -101,7 +101,7 @@ svn_error_t * svn_fs_x__read_string_table(string_table_t **table_p, svn_stream_t *stream, apr_pool_t *result_pool, - apr_pool_t *scratch_pool); + apr_pool_t *scratch_pool); /* Serialize string table *ST within the serialization CONTEXT. */ Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/transaction.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/transaction.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/transaction.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/transaction.c Sun Jun 14 20:58:10 2015 @@ -474,7 +474,7 @@ svn_fs_x__with_all_locks(svn_fs_t *fs, apr_pool_t *scratch_pool) { /* Be sure to use the correct lock ordering as documented in - fs_fs_shared_data_t. The lock chain is being created in + fs_fs_shared_data_t. The lock chain is being created in innermost (last to acquire) -> outermost (first to acquire) order. */ with_lock_baton_t *lock_baton = create_lock_baton(fs, write_lock, body, baton, scratch_pool); @@ -716,7 +716,7 @@ get_writable_proto_rev(apr_file_t **file /* We don't want unused sections (such as leftovers from failed delta stream) in our file. If we use log addressing, we would need an - index entry for the unused section and that section would need to + index entry for the unused section and that section would need to be all NUL by convention. So, detect and fix those cases by truncating the protorev file. */ if (!err) @@ -1547,7 +1547,7 @@ write_next_ids(svn_fs_t *fs, apr_file_t *file; char buffer[2 * SVN_INT64_BUFFER_SIZE + 2]; char *p = buffer; - + p += svn__ui64tobase36(p, node_id); *(p++) = ' '; p += svn__ui64tobase36(p, copy_id); @@ -3283,7 +3283,7 @@ svn_fs_x__add_index_data(svn_fs_t *fs, scratch_pool, scratch_pool)); /* Append footer. */ - footer = svn_fs_x__unparse_footer(l2p_offset, l2p_checksum, + footer = svn_fs_x__unparse_footer(l2p_offset, l2p_checksum, p2l_offset, p2l_checksum, scratch_pool, scratch_pool); SVN_ERR(svn_io_file_write_full(file, footer->data, footer->len, NULL, Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/tree.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/tree.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/tree.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/tree.c Sun Jun 14 20:58:10 2015 @@ -317,20 +317,19 @@ x_node_relation(svn_fs_node_relation_t * return SVN_NO_ERROR; } - /* Nodes from different transactions are never related. */ - if (root_a->is_txn_root && root_b->is_txn_root - && strcmp(root_a->txn, root_b->txn)) - { - *relation = svn_fs_node_unrelated; - return SVN_NO_ERROR; - } - /* Are both (!) root paths? Then, they are related and we only test how * direct the relation is. */ if (a_is_root_dir && b_is_root_dir) { - *relation = root_a->rev == root_b->rev - ? svn_fs_node_same + svn_boolean_t different_txn + = root_a->is_txn_root && root_b->is_txn_root + && strcmp(root_a->txn, root_b->txn); + + /* For txn roots, root->REV is the base revision of that TXN. */ + *relation = ( (root_a->rev == root_b->rev) + && (root_a->is_txn_root == root_b->is_txn_root) + && !different_txn) + ? svn_fs_node_unchanged : svn_fs_node_common_ancestor; return SVN_NO_ERROR; } @@ -345,8 +344,10 @@ x_node_relation(svn_fs_node_relation_t * noderev_id_b = *svn_fs_x__dag_get_id(node); node_id_b = *svn_fs_x__dag_get_node_id(node); + /* In FSX, even in-txn IDs are globally unique. + * So, we can simply compare them. */ if (svn_fs_x__id_eq(&noderev_id_a, &noderev_id_b)) - *relation = svn_fs_node_same; + *relation = svn_fs_node_unchanged; else if (svn_fs_x__id_eq(&node_id_a, &node_id_b)) *relation = svn_fs_node_common_ancestor; else @@ -475,6 +476,20 @@ x_node_proplist(apr_hash_t **table_p, return SVN_NO_ERROR; } +static svn_error_t * +x_node_has_props(svn_boolean_t *has_props, + svn_fs_root_t *root, + const char *path, + apr_pool_t *scratch_pool) +{ + apr_hash_t *props; + + SVN_ERR(x_node_proplist(&props, root, path, scratch_pool)); + + *has_props = (0 < apr_hash_count(props)); + + return SVN_NO_ERROR; +} static svn_error_t * increment_mergeinfo_up_tree(svn_fs_x__dag_path_t *pp, @@ -659,6 +674,15 @@ compare_dir_structure(svn_boolean_t *cha SVN_ERR(svn_fs_x__dag_dir_entries(&rhs_entries, rhs, scratch_pool, iterpool)); + /* different number of entries -> some addition / removal */ + if (lhs_entries->nelts != rhs_entries->nelts) + { + svn_pool_destroy(iterpool); + *changed = TRUE; + + return SVN_NO_ERROR; + } + /* Since directories are sorted by name, we can simply compare their entries one-by-one without binary lookup etc. */ for (i = 0; i < lhs_entries->nelts; ++i) @@ -680,9 +704,9 @@ compare_dir_structure(svn_boolean_t *cha svn_pool_clear(iterpool); /* Modified but not copied / replaced or anything? */ - SVN_ERR(svn_fs_x__dag_get_node(&lhs_node, fs, &lhs_entry->id, + SVN_ERR(svn_fs_x__dag_get_node(&lhs_node, fs, &lhs_entry->id, iterpool, iterpool)); - SVN_ERR(svn_fs_x__dag_get_node(&rhs_node, fs, &rhs_entry->id, + SVN_ERR(svn_fs_x__dag_get_node(&rhs_node, fs, &rhs_entry->id, iterpool, iterpool)); if (svn_fs_x__dag_same_line_of_history(lhs_node, rhs_node)) continue; @@ -690,7 +714,9 @@ compare_dir_structure(svn_boolean_t *cha /* This is a different entry. */ *changed = TRUE; - break; + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; } svn_pool_destroy(iterpool); @@ -1377,9 +1403,11 @@ static svn_error_t * x_dir_optimal_order(apr_array_header_t **ordered_p, svn_fs_root_t *root, apr_hash_t *entries, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - *ordered_p = svn_fs_x__order_dir_entries(root->fs, entries, pool); + *ordered_p = svn_fs_x__order_dir_entries(root->fs, entries, result_pool, + scratch_pool); return SVN_NO_ERROR; } @@ -1666,7 +1694,7 @@ x_copy(svn_fs_root_t *from_root, SVN_ERR(copy_helper(from_root, svn_fs__canonicalize_abspath(from_path, subpool), - to_root, + to_root, svn_fs__canonicalize_abspath(to_path, subpool), TRUE, subpool)); @@ -1903,7 +1931,7 @@ window_consumer(svn_txdelta_window_t *wi cb->target_string. */ SVN_ERR(tb->interpreter(window, tb->interpreter_baton)); - /* Is the window NULL? If so, we're done. The stream has already been + /* Is the window NULL? If so, we're done. The stream has already been closed by the interpreter. */ if (! window) SVN_ERR(svn_fs_x__dag_finalize_edits(tb->node, tb->result_checksum, @@ -3161,6 +3189,7 @@ static root_vtable_t root_vtable = { x_closest_copy, x_node_prop, x_node_proplist, + x_node_has_props, x_change_node_prop, x_props_changed, x_dir_entries, Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/util.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/util.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/util.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/util.c Sun Jun 14 20:58:10 2015 @@ -312,7 +312,7 @@ svn_fs_x__path_txn_sha1(svn_fs_t *fs, svn_checksum_t checksum; checksum.digest = sha1; checksum.kind = svn_checksum_sha1; - + return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool), svn_checksum_to_cstring(&checksum, pool), pool); Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/verify.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/verify.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/verify.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/verify.c Sun Jun 14 20:58:10 2015 @@ -756,7 +756,7 @@ verify_metadata_consistency(svn_fs_t *fs /* Check for external corruption to the indexes. */ err = verify_index_checksums(fs, pack_start, cancel_func, cancel_baton, iterpool); - + /* two-way index check */ if (!err) err = compare_l2p_to_p2l_index(fs, pack_start, pack_end - pack_start, Modified: subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.c Sun Jun 14 20:58:10 2015 @@ -143,7 +143,7 @@ load_ra_module(svn_ra__init_func_t *func const char *compat_funcname; apr_status_t status; - libname = apr_psprintf(pool, "libsvn_ra_%s-%d.so.%d", + libname = apr_psprintf(pool, "libsvn_ra_%s-" SVN_DSO_SUFFIX_FMT, ra_name, SVN_VER_MAJOR, SVN_SOVERSION); funcname = apr_psprintf(pool, "svn_ra_%s__init", ra_name); compat_funcname = apr_psprintf(pool, "svn_ra_%s_init", ra_name); @@ -232,6 +232,11 @@ check_ra_version(const svn_version_t *ra svn_error_t *svn_ra_initialize(apr_pool_t *pool) { +#if defined(SVN_USE_DSO) && APR_HAS_DSO + /* Ensure that DSO subsystem is initialized early as possible if + we're going to use it. */ + SVN_ERR(svn_dso_initialize2()); +#endif return SVN_NO_ERROR; } @@ -261,6 +266,7 @@ svn_error_t *svn_ra_open4(svn_ra_session apr_pool_t *pool) { apr_pool_t *sesspool = svn_pool_create(pool); + apr_pool_t *scratch_pool = svn_pool_create(sesspool); svn_ra_session_t *session; const struct ra_lib_defn *defn; const svn_ra__vtable_t *vtable = NULL; @@ -270,6 +276,7 @@ svn_error_t *svn_ra_open4(svn_ra_session #ifdef CHOOSABLE_DAV_MODULE const char *http_library = DEFAULT_HTTP_LIBRARY; #endif + svn_auth_baton_t *auth_baton; /* Initialize the return variable. */ *session_p = NULL; @@ -285,8 +292,12 @@ svn_error_t *svn_ra_open4(svn_ra_session repos_URL); if (callbacks->auth_baton) - SVN_ERR(svn_auth__apply_config_for_server(callbacks->auth_baton, config, - repos_URI.hostname, sesspool)); + SVN_ERR(svn_auth__make_session_auth(&auth_baton, + callbacks->auth_baton, config, + repos_URI.hostname, + sesspool, scratch_pool)); + else + auth_baton = NULL; #ifdef CHOOSABLE_DAV_MODULE if (config) @@ -339,16 +350,16 @@ svn_error_t *svn_ra_open4(svn_ra_session if (! initfunc) SVN_ERR(load_ra_module(&initfunc, NULL, defn->ra_name, - sesspool)); + scratch_pool)); if (! initfunc) /* Library not found. */ continue; - SVN_ERR(initfunc(svn_ra_version(), &vtable, sesspool)); + SVN_ERR(initfunc(svn_ra_version(), &vtable, scratch_pool)); SVN_ERR(check_ra_version(vtable->get_version(), scheme)); - if (! has_scheme_of(vtable->get_schemes(sesspool), repos_URL)) + if (! has_scheme_of(vtable->get_schemes(scratch_pool), repos_URL)) /* Library doesn't support the scheme at runtime. */ continue; @@ -372,10 +383,12 @@ svn_error_t *svn_ra_open4(svn_ra_session /* Ask the library to open the session. */ err = vtable->open_session(session, corrected_url_p, repos_URL, - callbacks, callback_baton, config, sesspool); + callbacks, callback_baton, auth_baton, + config, sesspool, scratch_pool); if (err) { + svn_pool_destroy(sesspool); /* Includes scratch_pool */ if (err->apr_err == SVN_ERR_RA_SESSION_URL_MISMATCH) return svn_error_trace(err); @@ -393,7 +406,7 @@ svn_error_t *svn_ra_open4(svn_ra_session { /* *session_p = NULL; */ *corrected_url_p = apr_pstrdup(pool, *corrected_url_p); - svn_pool_destroy(sesspool); + svn_pool_destroy(sesspool); /* Includes scratch_pool */ return SVN_NO_ERROR; } @@ -407,7 +420,7 @@ svn_error_t *svn_ra_open4(svn_ra_session { /* Duplicate the uuid as it is allocated in sesspool */ repository_uuid = apr_pstrdup(pool, repository_uuid); - svn_pool_destroy(sesspool); + svn_pool_destroy(sesspool); /* includes scratch_pool */ return svn_error_createf(SVN_ERR_RA_UUID_MISMATCH, NULL, _("Repository UUID '%s' doesn't match " "expected UUID '%s'"), @@ -415,6 +428,7 @@ svn_error_t *svn_ra_open4(svn_ra_session } } + svn_pool_destroy(scratch_pool); *session_p = session; return SVN_NO_ERROR; } @@ -582,61 +596,6 @@ svn_error_t *svn_ra_rev_prop(svn_ra_sess return session->vtable->rev_prop(session, rev, name, value, pool); } -struct ccw_baton -{ - svn_commit_callback2_t original_callback; - void *original_baton; - - svn_ra_session_t *session; -}; - -/* Wrapper which populates the repos_root field of the commit_info struct */ -static svn_error_t * -commit_callback_wrapper(const svn_commit_info_t *commit_info, - void *baton, - apr_pool_t *pool) -{ - struct ccw_baton *ccwb = baton; - svn_commit_info_t *ci = svn_commit_info_dup(commit_info, pool); - - SVN_ERR(svn_ra_get_repos_root2(ccwb->session, &ci->repos_root, pool)); - - return ccwb->original_callback(ci, ccwb->original_baton, pool); -} - - -/* Some RA layers do not correctly fill in REPOS_ROOT in commit_info, or - they are third-party layers conforming to an older commit_info structure. - Interpose a utility function to ensure the field is valid. */ -static void -remap_commit_callback(svn_commit_callback2_t *callback, - void **callback_baton, - svn_ra_session_t *session, - svn_commit_callback2_t original_callback, - void *original_baton, - apr_pool_t *result_pool) -{ - if (original_callback == NULL) - { - *callback = NULL; - *callback_baton = NULL; - } - else - { - /* Allocate this in RESULT_POOL, since the callback will be called - long after this function has returned. */ - struct ccw_baton *ccwb = apr_palloc(result_pool, sizeof(*ccwb)); - - ccwb->session = session; - ccwb->original_callback = original_callback; - ccwb->original_baton = original_baton; - - *callback = commit_callback_wrapper; - *callback_baton = ccwb; - } -} - - svn_error_t *svn_ra_get_commit_editor3(svn_ra_session_t *session, const svn_delta_editor_t **editor, void **edit_baton, @@ -647,10 +606,6 @@ svn_error_t *svn_ra_get_commit_editor3(s svn_boolean_t keep_locks, apr_pool_t *pool) { - remap_commit_callback(&commit_callback, &commit_baton, - session, commit_callback, commit_baton, - pool); - return session->vtable->get_commit_editor(session, editor, edit_baton, revprop_table, commit_callback, commit_baton, @@ -998,6 +953,7 @@ svn_error_t *svn_ra_get_locations(svn_ra { svn_error_t *err; + SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(peg_revision)); SVN_ERR_ASSERT(svn_relpath_is_canonical(path)); err = session->vtable->get_locations(session, locations, path, peg_revision, location_revisions, pool); @@ -1058,7 +1014,7 @@ svn_error_t *svn_ra_get_file_revs2(svn_r if (include_merged_revisions) SVN_ERR(svn_ra__assert_mergeinfo_capable_server(session, NULL, pool)); - if (start > end) + if (start > end || !SVN_IS_VALID_REVNUM(start)) SVN_ERR( svn_ra__assert_capable_server(session, SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE, @@ -1068,7 +1024,8 @@ svn_error_t *svn_ra_get_file_revs2(svn_r err = session->vtable->get_file_revs(session, path, start, end, include_merged_revisions, handler, handler_baton, pool); - if (err && (err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)) + if (err && (err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED) + && !include_merged_revisions) { svn_error_clear(err); @@ -1076,7 +1033,7 @@ svn_error_t *svn_ra_get_file_revs2(svn_r err = svn_ra__file_revs_from_log(session, path, start, end, handler, handler_baton, pool); } - return err; + return svn_error_trace(err); } svn_error_t *svn_ra_lock(svn_ra_session_t *session, @@ -1164,6 +1121,8 @@ svn_error_t *svn_ra_replay(svn_ra_sessio void *edit_baton, apr_pool_t *pool) { + SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision) + && SVN_IS_VALID_REVNUM(low_water_mark)); return session->vtable->replay(session, revision, low_water_mark, text_deltas, editor, edit_baton, pool); } @@ -1231,7 +1190,14 @@ svn_ra_replay_range(svn_ra_session_t *se void *replay_baton, apr_pool_t *pool) { - svn_error_t *err = + svn_error_t *err; + + SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(start_revision) + && SVN_IS_VALID_REVNUM(end_revision) + && start_revision <= end_revision + && SVN_IS_VALID_REVNUM(low_water_mark)); + + err = session->vtable->replay_range(session, start_revision, end_revision, low_water_mark, text_deltas, revstart_func, revfinish_func, @@ -1390,11 +1356,6 @@ svn_ra__get_commit_ev2(svn_editor_t **ed /* The specific RA layer does not have an implementation. Use our default shim over the normal commit editor. */ - /* Remap for RA layers exposing Ev1. */ - remap_commit_callback(&commit_callback, &commit_baton, - session, commit_callback, commit_baton, - result_pool); - return svn_error_trace(svn_ra__use_commit_shim( editor, session, Modified: subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.h Sun Jun 14 20:58:10 2015 @@ -61,8 +61,10 @@ typedef struct svn_ra__vtable_t { const char *session_URL, const svn_ra_callbacks2_t *callbacks, void *callback_baton, + svn_auth_baton_t *auth_baton, apr_hash_t *config, - apr_pool_t *pool); + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Backs svn_ra_dup_session */ svn_error_t * (*dup_session)(svn_ra_session_t *new_session, svn_ra_session_t *old_session, Modified: subversion/branches/fsx-1.10/subversion/libsvn_ra/wrapper_template.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_ra/wrapper_template.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_ra/wrapper_template.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_ra/wrapper_template.h Sun Jun 14 20:58:10 2015 @@ -91,7 +91,9 @@ static svn_error_t *compat_open(void **s callbacks2->progress_baton = NULL; SVN_ERR(VTBL.open_session(sess, &session_url, repos_URL, - callbacks2, callback_baton, config, sesspool)); + callbacks2, callback_baton, + callbacks ? callbacks->auth_baton : NULL, + config, sesspool, sesspool)); if (strcmp(repos_URL, session_url) != 0) { Modified: subversion/branches/fsx-1.10/subversion/libsvn_ra_local/ra_local.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_ra_local/ra_local.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_ra_local/ra_local.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_ra_local/ra_local.h Sun Jun 14 20:58:10 2015 @@ -63,6 +63,9 @@ typedef struct svn_ra_local__session_bat const svn_ra_callbacks2_t *callbacks; void *callback_baton; + /* Slave auth baton */ + svn_auth_baton_t *auth_baton; + const char *useragent; } svn_ra_local__session_baton_t;
