Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/dag.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/dag.c?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/dag.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/dag.c Tue Jan 27 23:27:44 2015 @@ -54,10 +54,11 @@ struct dag_node_t svn_fs_x__id_t id; /* In the special case that this node is the root of a transaction - that has not yet been modified, the node revision ID for this dag - node's predecessor; otherwise NULL. (Used in - svn_fs_node_created_rev.) */ - svn_fs_x__id_t fresh_root_predecessor_id; + that has not yet been modified, the revision of this node is the + respective txn's base rev. Otherwise, this is SVN_INVALID_REVNUM + for txn nodes and the respective crev for committed nodes. + (Used in svn_fs_node_created_rev.) */ + svn_revnum_t revision; /* The node's type (file, dir, etc.) */ svn_node_kind_t kind; @@ -76,6 +77,11 @@ struct dag_node_t /* the path at which this node was created. */ const char *created_path; + + /* Directory entry lookup hint to speed up consecutive calls to + svn_fs_x__rep_contents_dir_entry(). Only used for directory nodes. + Any value is legal but should default to APR_SIZE_MAX. */ + apr_size_t hint; }; @@ -248,6 +254,7 @@ svn_fs_x__dag_get_node(dag_node_t **node new_node = apr_pcalloc(result_pool, sizeof(*new_node)); new_node->fs = fs; new_node->id = *id; + new_node->hint = APR_SIZE_MAX; /* Grab the contents so we can inspect the node's kind and created path. */ new_node->node_pool = result_pool; @@ -257,10 +264,12 @@ svn_fs_x__dag_get_node(dag_node_t **node new_node->kind = noderev->kind; new_node->created_path = apr_pstrdup(result_pool, noderev->created_path); - if (noderev->is_fresh_txn_root) - new_node->fresh_root_predecessor_id = noderev->predecessor_id; - else - svn_fs_x__id_reset(&new_node->fresh_root_predecessor_id); + /* Support our quirky svn_fs_node_created_rev API. + Untouched txn roots report the base rev as theirs. */ + new_node->revision + = ( noderev->is_fresh_txn_root + ? svn_fs_x__get_revnum(noderev->predecessor_id.change_set) + : svn_fs_x__get_revnum(id->change_set)); /* Return a fresh new node */ *node = new_node; @@ -271,16 +280,7 @@ svn_fs_x__dag_get_node(dag_node_t **node svn_revnum_t svn_fs_x__dag_get_revision(const dag_node_t *node) { - /* In the special case that this is an unmodified transaction root, - we need to actually get the revision of the noderev's predecessor - (the revision root); see Issue #2608. */ - const svn_fs_x__id_t *correct_id - = svn_fs_x__id_used(&node->fresh_root_predecessor_id) - ? &node->fresh_root_predecessor_id - : &node->id; - - /* Look up the committed revision from the Node-ID. */ - return svn_fs_x__get_revnum(correct_id->change_set); + return node->revision; } @@ -375,7 +375,8 @@ dir_entry_id_from_node(svn_fs_x__id_t *i /* Get a dirent hash for this directory. */ SVN_ERR(svn_fs_x__rep_contents_dir_entry(&dirent, parent->fs, noderev, - name, scratch_pool, scratch_pool)); + name, &parent->hint, + scratch_pool, scratch_pool)); if (dirent) *id_p = dirent->id; else @@ -408,16 +409,16 @@ set_entry(dag_node_t *parent, /* Set the new entry. */ return svn_fs_x__set_entry(parent->fs, txn_id, parent_noderev, name, id, - kind, scratch_pool); + kind, parent->node_pool, scratch_pool); } /* Make a new entry named NAME in PARENT. If IS_DIR is true, then the node revision the new entry points to will be a directory, else it - will be a file. The new node will be allocated in POOL. PARENT + will be a file. The new node will be allocated in RESULT_POOL. PARENT must be mutable, and must not have an entry named NAME. - Use POOL for all allocations, except caching the node_revision in PARENT. + Use SCRATCH_POOL for all temporary allocations. */ static svn_error_t * make_entry(dag_node_t **child_p, @@ -426,7 +427,8 @@ make_entry(dag_node_t **child_p, const char *name, svn_boolean_t is_dir, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { svn_fs_x__noderev_t new_noderev, *parent_noderev; @@ -451,10 +453,10 @@ make_entry(dag_node_t **child_p, /* Create the new node's NODE-REVISION */ memset(&new_noderev, 0, sizeof(new_noderev)); new_noderev.kind = is_dir ? svn_node_dir : svn_node_file; - new_noderev.created_path = svn_fspath__join(parent_path, name, pool); + new_noderev.created_path = svn_fspath__join(parent_path, name, result_pool); SVN_ERR(get_node_revision(&parent_noderev, parent)); - new_noderev.copyroot_path = apr_pstrdup(pool, + new_noderev.copyroot_path = apr_pstrdup(result_pool, parent_noderev->copyroot_path); new_noderev.copyroot_rev = parent_noderev->copyroot_rev; new_noderev.copyfrom_rev = SVN_INVALID_REVNUM; @@ -463,24 +465,25 @@ make_entry(dag_node_t **child_p, SVN_ERR(svn_fs_x__create_node (svn_fs_x__dag_get_fs(parent), &new_noderev, - &parent_noderev->copy_id, txn_id, pool)); + &parent_noderev->copy_id, txn_id, scratch_pool)); /* Create a new dag_node_t for our new node */ SVN_ERR(svn_fs_x__dag_get_node(child_p, svn_fs_x__dag_get_fs(parent), - &new_noderev.noderev_id, pool)); + &new_noderev.noderev_id, result_pool)); /* We can safely call set_entry because we already know that PARENT is mutable, and we just created CHILD, so we know it has no ancestors (therefore, PARENT cannot be an ancestor of CHILD) */ return set_entry(parent, name, &new_noderev.noderev_id, - new_noderev.kind, txn_id, pool); + new_noderev.kind, txn_id, scratch_pool); } svn_error_t * svn_fs_x__dag_dir_entries(apr_array_header_t **entries, dag_node_t *node, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { svn_fs_x__noderev_t *noderev; @@ -490,7 +493,8 @@ svn_fs_x__dag_dir_entries(apr_array_head return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL, _("Can't get entries of non-directory")); - return svn_fs_x__rep_contents_dir(entries, node->fs, noderev, pool, pool); + return svn_fs_x__rep_contents_dir(entries, node->fs, noderev, result_pool, + scratch_pool); } @@ -524,14 +528,16 @@ svn_fs_x__dag_set_entry(dag_node_t *node svn_error_t * svn_fs_x__dag_get_proplist(apr_hash_t **proplist_p, dag_node_t *node, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { svn_fs_x__noderev_t *noderev; apr_hash_t *proplist = NULL; SVN_ERR(get_node_revision(&noderev, node)); - SVN_ERR(svn_fs_x__get_proplist(&proplist, node->fs, noderev, pool)); + SVN_ERR(svn_fs_x__get_proplist(&proplist, node->fs, noderev, result_pool, + scratch_pool)); *proplist_p = proplist; @@ -648,22 +654,23 @@ svn_error_t * svn_fs_x__dag_revision_root(dag_node_t **node_p, svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool) + apr_pool_t *result_pool) { dag_node_t *new_node; /* Construct the node. */ - new_node = apr_pcalloc(pool, sizeof(*new_node)); + new_node = apr_pcalloc(result_pool, sizeof(*new_node)); new_node->fs = fs; - SVN_ERR(svn_fs_x__rev_get_root(&new_node->id, fs, rev, pool)); - svn_fs_x__id_reset(&new_node->fresh_root_predecessor_id); + new_node->revision = rev; + svn_fs_x__init_rev_root(&new_node->id, rev); /* Grab the contents so we can inspect the node's kind and created path. */ - new_node->node_pool = pool; + new_node->node_pool = result_pool; /* Initialize the KIND and CREATED_PATH attributes */ new_node->kind = svn_node_dir; new_node->created_path = "/"; + new_node->hint = APR_SIZE_MAX; /* Return a fresh new node */ *node_p = new_node; @@ -688,15 +695,16 @@ svn_error_t * svn_fs_x__dag_txn_base_root(dag_node_t **node_p, svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { svn_fs_x__id_t base_root_id; svn_revnum_t base_rev; - SVN_ERR(svn_fs_x__get_base_rev(&base_rev, fs, txn_id, pool)); + SVN_ERR(svn_fs_x__get_base_rev(&base_rev, fs, txn_id, scratch_pool)); svn_fs_x__init_rev_root(&base_root_id, base_rev); - return svn_fs_x__dag_get_node(node_p, fs, &base_root_id, pool); + return svn_fs_x__dag_get_node(node_p, fs, &base_root_id, result_pool); } @@ -708,12 +716,12 @@ svn_fs_x__dag_clone_child(dag_node_t **c const svn_fs_x__id_t *copy_id, svn_fs_x__txn_id_t txn_id, svn_boolean_t is_parent_copyroot, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { dag_node_t *cur_entry; /* parent's current entry named NAME */ const svn_fs_x__id_t *new_node_id; /* node id we'll put into NEW_NODE */ svn_fs_t *fs = svn_fs_x__dag_get_fs(parent); - apr_pool_t *subpool = svn_pool_create(pool); /* First check that the parent is mutable. */ if (! svn_fs_x__dag_check_mutable(parent)) @@ -728,7 +736,8 @@ svn_fs_x__dag_clone_child(dag_node_t **c "Attempted to make a child clone with an illegal name '%s'", name); /* Find the node named NAME in PARENT's entries list if it exists. */ - SVN_ERR(svn_fs_x__dag_open(&cur_entry, parent, name, pool, subpool)); + SVN_ERR(svn_fs_x__dag_open(&cur_entry, parent, name, scratch_pool, + scratch_pool)); if (! cur_entry) return svn_error_createf (SVN_ERR_FS_NOT_FOUND, NULL, @@ -752,7 +761,7 @@ svn_fs_x__dag_clone_child(dag_node_t **c { SVN_ERR(get_node_revision(&parent_noderev, parent)); noderev->copyroot_rev = parent_noderev->copyroot_rev; - noderev->copyroot_path = apr_pstrdup(pool, + noderev->copyroot_path = apr_pstrdup(scratch_pool, parent_noderev->copyroot_path); } @@ -761,23 +770,24 @@ svn_fs_x__dag_clone_child(dag_node_t **c noderev->predecessor_id = noderev->noderev_id; noderev->predecessor_count++; - noderev->created_path = svn_fspath__join(parent_path, name, pool); + noderev->created_path = svn_fspath__join(parent_path, name, + scratch_pool); if (copy_id == NULL) copy_id = &noderev->copy_id; - SVN_ERR(svn_fs_x__create_successor(fs, noderev, copy_id, txn_id, pool)); + SVN_ERR(svn_fs_x__create_successor(fs, noderev, copy_id, txn_id, + scratch_pool)); new_node_id = &noderev->noderev_id; /* Replace the ID in the parent's ENTRY list with the ID which refers to the mutable clone of this child. */ SVN_ERR(set_entry(parent, name, new_node_id, noderev->kind, txn_id, - pool)); + scratch_pool)); } /* Initialize the youngster. */ - svn_pool_destroy(subpool); - return svn_fs_x__dag_get_node(child_p, fs, new_node_id, pool); + return svn_fs_x__dag_get_node(child_p, fs, new_node_id, result_pool); } @@ -796,6 +806,55 @@ svn_fs_x__dag_clone_root(dag_node_t **ro } +/* Delete all mutable node revisions reachable from node ID, including + ID itself, from FS's `nodes' table. Also delete any mutable + representations and strings associated with that node revision. + ID may refer to a file or directory, which may be mutable or immutable. + + Use SCRATCH_POOL for temporary allocations. + */ +static svn_error_t * +delete_if_mutable(svn_fs_t *fs, + const svn_fs_x__id_t *id, + apr_pool_t *scratch_pool) +{ + dag_node_t *node; + + /* Get the node. */ + SVN_ERR(svn_fs_x__dag_get_node(&node, fs, id, scratch_pool)); + + /* If immutable, do nothing and return immediately. */ + if (! svn_fs_x__dag_check_mutable(node)) + return SVN_NO_ERROR; + + /* Else it's mutable. Recurse on directories... */ + if (node->kind == svn_node_dir) + { + apr_array_header_t *entries; + int i; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + + /* Loop over directory entries */ + SVN_ERR(svn_fs_x__dag_dir_entries(&entries, node, scratch_pool, + iterpool)); + for (i = 0; i < entries->nelts; ++i) + { + const svn_fs_x__id_t *noderev_id + = &APR_ARRAY_IDX(entries, i, svn_fs_x__dirent_t *)->id; + + svn_pool_clear(iterpool); + SVN_ERR(delete_if_mutable(fs, noderev_id, iterpool)); + } + + svn_pool_destroy(iterpool); + } + + /* ... then delete the node itself, after deleting any mutable + representations and strings it points to. */ + return svn_fs_x__delete_node_revision(fs, id, scratch_pool); +} + + svn_error_t * svn_fs_x__dag_delete(dag_node_t *parent, const char *name, @@ -832,7 +891,8 @@ svn_fs_x__dag_delete(dag_node_t *parent, /* Search this directory for a dirent with that NAME. */ SVN_ERR(svn_fs_x__rep_contents_dir_entry(&dirent, fs, parent_noderev, - name, subpool, subpool)); + name, &parent->hint, + subpool, subpool)); /* If we never found ID in ENTRIES (perhaps because there are no ENTRIES, perhaps because ID just isn't in the existing ENTRIES @@ -843,68 +903,28 @@ svn_fs_x__dag_delete(dag_node_t *parent, "Delete failed--directory has no entry '%s'", name); /* If mutable, remove it and any mutable children from db. */ - SVN_ERR(svn_fs_x__dag_delete_if_mutable(parent->fs, &dirent->id, - scratch_pool)); + SVN_ERR(delete_if_mutable(parent->fs, &dirent->id, scratch_pool)); svn_pool_destroy(subpool); /* Remove this entry from its parent's entries list. */ return svn_fs_x__set_entry(parent->fs, txn_id, parent_noderev, name, - NULL, svn_node_unknown, scratch_pool); + NULL, svn_node_unknown, parent->node_pool, + scratch_pool); } svn_error_t * -svn_fs_x__dag_delete_if_mutable(svn_fs_t *fs, - const svn_fs_x__id_t *id, - apr_pool_t *scratch_pool) -{ - dag_node_t *node; - - /* Get the node. */ - SVN_ERR(svn_fs_x__dag_get_node(&node, fs, id, scratch_pool)); - - /* If immutable, do nothing and return immediately. */ - if (! svn_fs_x__dag_check_mutable(node)) - return SVN_NO_ERROR; - - /* Else it's mutable. Recurse on directories... */ - if (node->kind == svn_node_dir) - { - apr_array_header_t *entries; - int i; - apr_pool_t *iterpool = svn_pool_create(scratch_pool); - - /* Loop over directory entries */ - SVN_ERR(svn_fs_x__dag_dir_entries(&entries, node, scratch_pool)); - if (entries) - for (i = 0; i < entries->nelts; ++i) - { - const svn_fs_x__id_t *noderev_id - = &APR_ARRAY_IDX(entries, i, svn_fs_x__dirent_t *)->id; - - svn_pool_clear(iterpool); - SVN_ERR(svn_fs_x__dag_delete_if_mutable(fs, noderev_id, - scratch_pool)); - } - - svn_pool_destroy(iterpool); - } - - /* ... then delete the node itself, after deleting any mutable - representations and strings it points to. */ - return svn_fs_x__delete_node_revision(fs, id, scratch_pool); -} - -svn_error_t * svn_fs_x__dag_make_file(dag_node_t **child_p, dag_node_t *parent, const char *parent_path, const char *name, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { /* Call our little helper function */ - return make_entry(child_p, parent, parent_path, name, FALSE, txn_id, pool); + return make_entry(child_p, parent, parent_path, name, FALSE, txn_id, + result_pool, scratch_pool); } @@ -914,17 +934,19 @@ svn_fs_x__dag_make_dir(dag_node_t **chil const char *parent_path, const char *name, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { /* Call our little helper function */ - return make_entry(child_p, parent, parent_path, name, TRUE, txn_id, pool); + return make_entry(child_p, parent, parent_path, name, TRUE, txn_id, + result_pool, scratch_pool); } svn_error_t * svn_fs_x__dag_get_contents(svn_stream_t **contents_p, dag_node_t *file, - apr_pool_t *pool) + apr_pool_t *result_pool) { svn_fs_x__noderev_t *noderev; svn_stream_t *contents; @@ -940,7 +962,7 @@ svn_fs_x__dag_get_contents(svn_stream_t /* Get a stream to the contents. */ SVN_ERR(svn_fs_x__get_contents(&contents, file->fs, - noderev->data_rep, TRUE, pool)); + noderev->data_rep, TRUE, result_pool)); *contents_p = contents; @@ -952,7 +974,8 @@ svn_error_t * svn_fs_x__dag_get_file_delta_stream(svn_txdelta_stream_t **stream_p, dag_node_t *source, dag_node_t *target, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { svn_fs_x__noderev_t *src_noderev; svn_fs_x__noderev_t *tgt_noderev; @@ -973,7 +996,8 @@ svn_fs_x__dag_get_file_delta_stream(svn_ /* Get the delta stream. */ return svn_fs_x__get_file_delta_stream(stream_p, target->fs, - src_noderev, tgt_noderev, pool); + src_noderev, tgt_noderev, + result_pool, scratch_pool); } @@ -982,7 +1006,7 @@ svn_fs_x__dag_try_process_file_contents( dag_node_t *node, svn_fs_process_contents_func_t processor, void* baton, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { svn_fs_x__noderev_t *noderev; @@ -991,7 +1015,7 @@ svn_fs_x__dag_try_process_file_contents( return svn_fs_x__try_process_file_contents(success, node->fs, noderev, - processor, baton, pool); + processor, baton, scratch_pool); } @@ -1036,7 +1060,7 @@ svn_fs_x__dag_file_checksum(svn_checksum svn_error_t * svn_fs_x__dag_get_edit_stream(svn_stream_t **contents, dag_node_t *file, - apr_pool_t *pool) + apr_pool_t *result_pool) { svn_fs_x__noderev_t *noderev; svn_stream_t *ws; @@ -1056,7 +1080,7 @@ svn_fs_x__dag_get_edit_stream(svn_stream /* Get the node revision. */ SVN_ERR(get_node_revision(&noderev, file)); - SVN_ERR(svn_fs_x__set_contents(&ws, file->fs, noderev, pool)); + SVN_ERR(svn_fs_x__set_contents(&ws, file->fs, noderev, result_pool)); *contents = ws; @@ -1227,7 +1251,7 @@ svn_fs_x__dag_copy(dag_node_t *to_node, svn_revnum_t from_rev, const char *from_path, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { const svn_fs_x__id_t *id; @@ -1239,10 +1263,10 @@ svn_fs_x__dag_copy(dag_node_t *to_node, /* Make a copy of the original node revision. */ SVN_ERR(get_node_revision(&from_noderev, from_node)); - to_noderev = copy_node_revision(from_noderev, pool); + to_noderev = copy_node_revision(from_noderev, scratch_pool); /* Reserve a copy ID for this new copy. */ - SVN_ERR(svn_fs_x__reserve_copy_id(©_id, fs, txn_id, pool)); + SVN_ERR(svn_fs_x__reserve_copy_id(©_id, fs, txn_id, scratch_pool)); /* Create a successor with its predecessor pointing at the copy source. */ @@ -1250,15 +1274,15 @@ svn_fs_x__dag_copy(dag_node_t *to_node, to_noderev->predecessor_count++; to_noderev->created_path = svn_fspath__join(svn_fs_x__dag_get_created_path(to_node), entry, - pool); - to_noderev->copyfrom_path = apr_pstrdup(pool, from_path); + scratch_pool); + to_noderev->copyfrom_path = apr_pstrdup(scratch_pool, from_path); to_noderev->copyfrom_rev = from_rev; /* Set the copyroot equal to our own id. */ to_noderev->copyroot_path = NULL; SVN_ERR(svn_fs_x__create_successor(fs, to_noderev, - ©_id, txn_id, pool)); + ©_id, txn_id, scratch_pool)); id = &to_noderev->noderev_id; } else /* don't preserve history */ @@ -1268,7 +1292,7 @@ svn_fs_x__dag_copy(dag_node_t *to_node, /* Set the entry in to_node to the new id. */ return svn_fs_x__dag_set_entry(to_node, entry, id, from_node->kind, - txn_id, pool); + txn_id, scratch_pool); }
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/dag.h URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/dag.h?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/dag.h (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/dag.h Tue Jan 27 23:27:44 2015 @@ -208,12 +208,13 @@ svn_fs_x__dag_node_kind(dag_node_t *node If properties do not exist on NODE, *PROPLIST_P will be set to NULL. - Use POOL for all allocations. + Allocate the result in RESULT_POOL and use SCRATCH_POOL for temporaries. */ svn_error_t * svn_fs_x__dag_get_proplist(apr_hash_t **proplist_p, dag_node_t *node, - apr_pool_t *pool); + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Set the property list of NODE to PROPLIST, allocating from POOL. The node being changed must be mutable. @@ -251,16 +252,16 @@ svn_fs_x__dag_set_has_mergeinfo(dag_node /* Open the root of revision REV of filesystem FS, allocating from - POOL. Set *NODE_P to the new node. */ + RESULT_POOL. Set *NODE_P to the new node. */ svn_error_t * svn_fs_x__dag_revision_root(dag_node_t **node_p, svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Set *NODE_P to the root of transaction TXN_ID in FS, allocating - from POOL. + from RESULT_POOL. Note that the root node of TXN_ID is not necessarily mutable. If no changes have been made in the transaction, then it may share its @@ -270,16 +271,18 @@ svn_error_t * svn_fs_x__dag_txn_root(dag_node_t **node_p, svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Set *NODE_P to the base root of transaction TXN_ID in FS, - allocating from POOL. Allocate the node in TRAIL->pool. */ + allocating from RESULT_POOL. Allocate the node in TRAIL->pool. + Use SCRATCH_POOL for temporaries. */ svn_error_t * svn_fs_x__dag_txn_base_root(dag_node_t **node_p, svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Clone the root directory of TXN_ID in FS, and update the @@ -312,11 +315,12 @@ svn_fs_x__dag_open(dag_node_t **child_p, /* Set *ENTRIES_P to an array of NODE's entries, sorted by entry names, and the values are svn_fs_x__dirent_t. The returned table (and elements) - is allocated in POOL, which is also used for temporary allocations. */ + is allocated in RESULT_POOL, temporaries in SCRATCH_POOL. */ svn_error_t * svn_fs_x__dag_dir_entries(apr_array_header_t **entries_p, dag_node_t *node, - apr_pool_t *pool); + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Set ENTRY_NAME in NODE to point to ID (with kind KIND), allocating from POOL. NODE must be a mutable directory. ID can refer to a @@ -352,7 +356,7 @@ svn_fs_x__dag_set_entry(dag_node_t *node TXN_ID is the Subversion transaction under which this occurs. - Use POOL for all allocations. + Allocate *CHILD_P in RESULT_POOL and use SCRATCH_POOL for temporaries. */ svn_error_t * svn_fs_x__dag_clone_child(dag_node_t **child_p, @@ -362,7 +366,8 @@ svn_fs_x__dag_clone_child(dag_node_t **c const svn_fs_x__id_t *copy_id, svn_fs_x__txn_id_t txn_id, svn_boolean_t is_parent_copyroot, - apr_pool_t *pool); + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Delete the directory entry named NAME from PARENT, allocating from @@ -384,21 +389,8 @@ svn_fs_x__dag_delete(dag_node_t *parent, apr_pool_t *scratch_pool); -/* Delete all mutable node revisions reachable from node ID, including - ID itself, from FS's `nodes' table. Also delete any mutable - representations and strings associated with that node revision. - ID may refer to a file or directory, which may be mutable or immutable. - - Use SCRATCH_POOL for temporary allocations. - */ -svn_error_t * -svn_fs_x__dag_delete_if_mutable(svn_fs_t *fs, - const svn_fs_x__id_t *id, - apr_pool_t *scratch_pool); - - /* Create a new mutable directory named NAME in PARENT. Set *CHILD_P - to a reference to the new node, allocated in POOL. The new + to a reference to the new node, allocated in RESULT_POOL. The new directory has no contents, and no properties. PARENT must be mutable. NAME must be a single path component; it cannot be a slash-separated directory path. PARENT_PATH must be the @@ -406,7 +398,7 @@ svn_fs_x__dag_delete_if_mutable(svn_fs_t not currently have an entry named NAME. TXN_ID is the Subversion transaction under which this occurs. - Use POOL for all allocations. + Use SCRATCH_POOL for temporary allocations. */ svn_error_t * svn_fs_x__dag_make_dir(dag_node_t **child_p, @@ -414,7 +406,8 @@ svn_fs_x__dag_make_dir(dag_node_t **chil const char *parent_path, const char *name, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); @@ -422,59 +415,56 @@ svn_fs_x__dag_make_dir(dag_node_t **chil /* Set *CONTENTS to a readable generic stream which yields the - contents of FILE. Allocate the stream in POOL. + contents of FILE. Allocate the stream in RESULT_POOL. If FILE is not a file, return SVN_ERR_FS_NOT_FILE. - - Use POOL for all allocations. */ svn_error_t * svn_fs_x__dag_get_contents(svn_stream_t **contents, dag_node_t *file, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Attempt to fetch the contents of NODE and pass it along with the BATON to the PROCESSOR. Set *SUCCESS only of the data could be provided and the processor had been called. - Use POOL for all allocations. + Use SCRATCH_POOL for temporary allocations. */ svn_error_t * svn_fs_x__dag_try_process_file_contents(svn_boolean_t *success, dag_node_t *node, svn_fs_process_contents_func_t processor, void* baton, - apr_pool_t *pool); + apr_pool_t *scratch_pool); /* Set *STREAM_P to a delta stream that will turn the contents of SOURCE into - the contents of TARGET, allocated in POOL. If SOURCE is null, the empty - string will be used. + the contents of TARGET, allocated in RESULT_POOL. If SOURCE is null, the + empty string will be used is its stead. - Use POOL for all allocations. + Use SCRATCH_POOL for temporary allocations. */ svn_error_t * svn_fs_x__dag_get_file_delta_stream(svn_txdelta_stream_t **stream_p, dag_node_t *source, dag_node_t *target, - apr_pool_t *pool); + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Return a generic writable stream in *CONTENTS with which to set the - contents of FILE. Allocate the stream in POOL. + contents of FILE. Allocate the stream in RESULT_POOL. Any previous edits on the file will be deleted, and a new edit stream will be constructed. - - Use POOL for all allocations. */ svn_error_t * svn_fs_x__dag_get_edit_stream(svn_stream_t **contents, dag_node_t *file, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Signify the completion of edits to FILE made using the stream - returned by svn_fs_x__dag_get_edit_stream, allocating from POOL. + returned by svn_fs_x__dag_get_edit_stream. If CHECKSUM is non-null, it must match the checksum for FILE's contents (note: this is not recalculated, the recorded checksum is @@ -509,14 +499,14 @@ svn_fs_x__dag_file_checksum(svn_checksum apr_pool_t *result_pool); /* Create a new mutable file named NAME in PARENT. Set *CHILD_P to a - reference to the new node, allocated in POOL. The new file's + reference to the new node, allocated in RESULT_POOL. The new file's contents are the empty string, and it has no properties. PARENT must be mutable. NAME must be a single path component; it cannot be a slash-separated directory path. PARENT_PATH must be the canonicalized absolute path of the parent directory. TXN_ID is the Subversion transaction under which this occurs. - Use POOL for all allocations. + Use SCRATCH_POOL for temporary allocations. */ svn_error_t * svn_fs_x__dag_make_file(dag_node_t **child_p, @@ -524,15 +514,15 @@ svn_fs_x__dag_make_file(dag_node_t **chi const char *parent_path, const char *name, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Copies */ -/* Make ENTRY in TO_NODE be a copy of FROM_NODE, allocating from POOL. - TO_NODE must be mutable. TXN_ID is the Subversion transaction - under which this occurs. +/* Make ENTRY in TO_NODE be a copy of FROM_NODE. TO_NODE must be mutable. + TXN_ID is the Subversion transaction under which this occurs. If PRESERVE_HISTORY is true, the new node will record that it was copied from FROM_PATH in FROM_REV; therefore, FROM_NODE should be @@ -542,7 +532,7 @@ svn_fs_x__dag_make_file(dag_node_t **chi If PRESERVE_HISTORY is false, FROM_PATH and FROM_REV are ignored. - Use POOL for all allocations. + Use SCRATCH_POOL for temporary allocations. */ svn_error_t * svn_fs_x__dag_copy(dag_node_t *to_node, @@ -552,7 +542,7 @@ svn_fs_x__dag_copy(dag_node_t *to_node, svn_revnum_t from_rev, const char *from_path, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool); + apr_pool_t *scratch_pool); /* Comparison */ Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs.c?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs.c Tue Jan 27 23:27:44 2015 @@ -150,17 +150,17 @@ x_set_errcall(svn_fs_t *fs, return SVN_NO_ERROR; } -struct x_freeze_baton_t { +typedef struct x_freeze_baton_t { svn_fs_t *fs; svn_fs_freeze_func_t freeze_func; void *freeze_baton; -}; +} x_freeze_baton_t; static svn_error_t * x_freeze_body(void *baton, apr_pool_t *scratch_pool) { - struct x_freeze_baton_t *b = baton; + x_freeze_baton_t *b = baton; svn_boolean_t exists; SVN_ERR(svn_fs_x__exists_rep_cache(&exists, b->fs, scratch_pool)); @@ -176,7 +176,7 @@ static svn_error_t * x_freeze_body2(void *baton, apr_pool_t *scratch_pool) { - struct x_freeze_baton_t *b = baton; + x_freeze_baton_t *b = baton; SVN_ERR(svn_fs_x__with_write_lock(b->fs, x_freeze_body, baton, scratch_pool)); @@ -189,7 +189,7 @@ x_freeze(svn_fs_t *fs, void *freeze_baton, apr_pool_t *scratch_pool) { - struct x_freeze_baton_t b; + x_freeze_baton_t b; b.fs = fs; b.freeze_func = freeze_func; @@ -241,6 +241,21 @@ x_set_uuid(svn_fs_t *fs, return svn_error_trace(svn_fs_x__set_uuid(fs, uuid, NULL, scratch_pool)); } +/* Wrapper around svn_fs_x__begin_txn() providing the scratch pool. */ +static svn_error_t * +x_begin_txn(svn_fs_txn_t **txn_p, + svn_fs_t *fs, + svn_revnum_t rev, + apr_uint32_t flags, + apr_pool_t *pool) +{ + apr_pool_t *scratch_pool = svn_pool_create(pool); + SVN_ERR(svn_fs_x__begin_txn(txn_p, fs, rev, flags, pool, scratch_pool)); + svn_pool_destroy(scratch_pool); + + return SVN_NO_ERROR; +} + /* The vtable associated with a specific open filesystem. */ @@ -251,7 +266,7 @@ static fs_vtable_t fs_vtable = { svn_fs_x__change_rev_prop, x_set_uuid, svn_fs_x__revision_root, - svn_fs_x__begin_txn, + x_begin_txn, svn_fs_x__open_txn, svn_fs_x__purge_txn, svn_fs_x__list_transactions, Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs.h URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs.h?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs.h (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs.h Tue Jan 27 23:27:44 2015 @@ -217,14 +217,16 @@ typedef struct svn_fs_x__pair_cache_key_ apr_int64_t second; } svn_fs_x__pair_cache_key_t; -/* Key type that identifies a representation / rep header. */ +/* Key type that identifies a representation / rep header. + + Note: Cache keys should require no padding. */ typedef struct svn_fs_x__representation_cache_key_t { /* Revision that contains the representation */ - svn_revnum_t revision; + apr_int64_t revision; - /* Packed or non-packed representation? */ - svn_boolean_t is_packed; + /* Packed or non-packed representation (boolean)? */ + apr_int64_t is_packed; /* Item index of the representation */ apr_uint64_t item_index; Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs_x.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs_x.c?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs_x.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/fs_x.c Tue Jan 27 23:27:44 2015 @@ -201,8 +201,7 @@ static svn_error_t * verify_block_size(apr_int64_t block_size, apr_size_t item_size, const char *name, - apr_pool_t *scratch_pool - ) + apr_pool_t *scratch_pool) { /* Limit range. */ if (block_size <= 0) @@ -594,14 +593,14 @@ svn_fs_x__open(svn_fs_t *fs, /* Baton type bridging svn_fs_x__upgrade and upgrade_body carrying * parameters over between them. */ -struct upgrade_baton_t +typedef struct upgrade_baton_t { svn_fs_t *fs; svn_fs_upgrade_notify_t notify_func; void *notify_baton; svn_cancel_func_t cancel_func; void *cancel_baton; -}; +} upgrade_baton_t; /* Upgrade the FS given in upgrade_baton_t *)BATON to the latest format * version. Apply options an invoke callback from that BATON. @@ -614,7 +613,7 @@ static svn_error_t * upgrade_body(void *baton, apr_pool_t *scratch_pool) { - struct upgrade_baton_t *upgrade_baton = baton; + upgrade_baton_t *upgrade_baton = baton; svn_fs_t *fs = upgrade_baton->fs; int format, max_files_per_dir; const char *format_path = svn_fs_x__path_format(fs, scratch_pool); @@ -640,7 +639,7 @@ svn_fs_x__upgrade(svn_fs_t *fs, void *cancel_baton, apr_pool_t *scratch_pool) { - struct upgrade_baton_t baton; + upgrade_baton_t baton; baton.fs = fs; baton.notify_func = notify_func; baton.notify_baton = notify_baton; @@ -789,8 +788,10 @@ svn_fs_x__prop_rep_equal(svn_boolean_t * /* At least one of the reps has been modified in a txn. Fetch and compare them. */ - SVN_ERR(svn_fs_x__get_proplist(&proplist_a, fs, a, scratch_pool)); - SVN_ERR(svn_fs_x__get_proplist(&proplist_b, fs, b, scratch_pool)); + SVN_ERR(svn_fs_x__get_proplist(&proplist_a, fs, a, scratch_pool, + scratch_pool)); + SVN_ERR(svn_fs_x__get_proplist(&proplist_b, fs, b, scratch_pool, + scratch_pool)); *equal = svn_fs__prop_lists_equal(proplist_a, proplist_b, scratch_pool); return SVN_NO_ERROR; @@ -1124,22 +1125,22 @@ svn_fs_x__revision_prop(svn_string_t **v /* Baton used for change_rev_prop_body below. */ -struct change_rev_prop_baton { +typedef struct change_rev_prop_baton_t { svn_fs_t *fs; svn_revnum_t rev; const char *name; const svn_string_t *const *old_value_p; const svn_string_t *value; -}; +} change_rev_prop_baton_t; /* The work-horse for svn_fs_x__change_rev_prop, called with the FS write lock. This implements the svn_fs_x__with_write_lock() - 'body' callback type. BATON is a 'struct change_rev_prop_baton *'. */ + 'body' callback type. BATON is a 'change_rev_prop_baton_t *'. */ static svn_error_t * change_rev_prop_body(void *baton, apr_pool_t *scratch_pool) { - struct change_rev_prop_baton *cb = baton; + change_rev_prop_baton_t *cb = baton; apr_hash_t *table; SVN_ERR(svn_fs_x__revision_proplist(&table, cb->fs, cb->rev, scratch_pool)); @@ -1174,7 +1175,7 @@ svn_fs_x__change_rev_prop(svn_fs_t *fs, const svn_string_t *value, apr_pool_t *scratch_pool) { - struct change_rev_prop_baton cb; + change_rev_prop_baton_t cb; SVN_ERR(svn_fs__check_fs(fs, TRUE)); Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/hotcopy.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/hotcopy.c?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/hotcopy.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/hotcopy.c Tue Jan 27 23:27:44 2015 @@ -710,7 +710,7 @@ hotcopy_revisions(svn_fs_t *src_fs, } /* Baton for hotcopy_body(). */ -struct hotcopy_body_baton { +typedef struct hotcopy_body_baton_t { svn_fs_t *src_fs; svn_fs_t *dst_fs; svn_boolean_t incremental; @@ -718,7 +718,7 @@ struct hotcopy_body_baton { void *notify_baton; svn_cancel_func_t cancel_func; void *cancel_baton; -}; +} hotcopy_body_baton_t; /* Perform a hotcopy, either normal or incremental. * @@ -742,7 +742,7 @@ static svn_error_t * hotcopy_body(void *baton, apr_pool_t *scratch_pool) { - struct hotcopy_body_baton *hbb = baton; + hotcopy_body_baton_t *hbb = baton; svn_fs_t *src_fs = hbb->src_fs; svn_fs_t *dst_fs = hbb->dst_fs; svn_boolean_t incremental = hbb->incremental; @@ -881,7 +881,7 @@ static svn_error_t * hotcopy_locking_src_body(void *baton, apr_pool_t *scratch_pool) { - struct hotcopy_body_baton *hbb = baton; + hotcopy_body_baton_t *hbb = baton; return svn_error_trace(svn_fs_x__with_pack_lock(hbb->src_fs, hotcopy_body, baton, scratch_pool)); @@ -975,7 +975,7 @@ svn_fs_x__hotcopy(svn_fs_t *src_fs, void *cancel_baton, apr_pool_t *scratch_pool) { - struct hotcopy_body_baton hbb; + hotcopy_body_baton_t hbb; hbb.src_fs = src_fs; hbb.dst_fs = dst_fs; Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/lock.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/lock.c?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/lock.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/lock.c Tue Jan 27 23:27:44 2015 @@ -104,8 +104,7 @@ hash_store(apr_hash_t *hash, of that value (if it exists). */ static const char * hash_fetch(apr_hash_t *hash, - const char *key, - apr_pool_t *pool) + const char *key) { svn_string_t *str = svn_hash_gets(hash, key); return str ? str->data : NULL; @@ -297,7 +296,7 @@ read_digest_file(apr_hash_t **children_p /* If our caller cares, see if we have a lock path in our hash. If so, we'll assume we have a lock here. */ - val = hash_fetch(hash, PATH_KEY, pool); + val = hash_fetch(hash, PATH_KEY); if (val && lock_p) { const char *path = val; @@ -306,30 +305,30 @@ read_digest_file(apr_hash_t **children_p lock = svn_lock_create(pool); lock->path = path; - if (! ((lock->token = hash_fetch(hash, TOKEN_KEY, pool)))) + if (! ((lock->token = hash_fetch(hash, TOKEN_KEY)))) return svn_error_trace(err_corrupt_lockfile(fs_path, path)); - if (! ((lock->owner = hash_fetch(hash, OWNER_KEY, pool)))) + if (! ((lock->owner = hash_fetch(hash, OWNER_KEY)))) return svn_error_trace(err_corrupt_lockfile(fs_path, path)); - if (! ((val = hash_fetch(hash, IS_DAV_COMMENT_KEY, pool)))) + if (! ((val = hash_fetch(hash, IS_DAV_COMMENT_KEY)))) return svn_error_trace(err_corrupt_lockfile(fs_path, path)); lock->is_dav_comment = (val[0] == '1'); - if (! ((val = hash_fetch(hash, CREATION_DATE_KEY, pool)))) + if (! ((val = hash_fetch(hash, CREATION_DATE_KEY)))) return svn_error_trace(err_corrupt_lockfile(fs_path, path)); SVN_ERR(svn_time_from_cstring(&(lock->creation_date), val, pool)); - if ((val = hash_fetch(hash, EXPIRATION_DATE_KEY, pool))) + if ((val = hash_fetch(hash, EXPIRATION_DATE_KEY))) SVN_ERR(svn_time_from_cstring(&(lock->expiration_date), val, pool)); - lock->comment = hash_fetch(hash, COMMENT_KEY, pool); + lock->comment = hash_fetch(hash, COMMENT_KEY); *lock_p = lock; } /* If our caller cares, see if we have any children for this path. */ - val = hash_fetch(hash, CHILDREN_KEY, pool); + val = hash_fetch(hash, CHILDREN_KEY); if (val && children_p) { apr_array_header_t *kiddos = svn_cstring_split(val, "\n", FALSE, pool); @@ -548,11 +547,12 @@ get_lock_helper(svn_fs_t *fs, /* Baton for locks_walker(). */ -struct walk_locks_baton { +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 * @@ -564,7 +564,7 @@ locks_walker(void *baton, svn_boolean_t have_write_lock, apr_pool_t *pool) { - struct walk_locks_baton *wlb = baton; + walk_locks_baton_t *wlb = baton; if (lock) { @@ -651,7 +651,7 @@ walk_locks(svn_fs_t *fs, svn_boolean_t have_write_lock, apr_pool_t *pool) { - struct walk_locks_baton wlb; + walk_locks_baton_t wlb; wlb.get_locks_func = get_locks_func; wlb.get_locks_baton = get_locks_baton; @@ -671,8 +671,7 @@ walk_locks(svn_fs_t *fs, */ static svn_error_t * verify_lock(svn_fs_t *fs, - svn_lock_t *lock, - apr_pool_t *pool) + svn_lock_t *lock) { if ((! fs->access_ctx) || (! fs->access_ctx->username)) return svn_error_createf @@ -703,7 +702,7 @@ get_locks_callback(void *baton, svn_lock_t *lock, apr_pool_t *pool) { - return verify_lock(baton, lock, pool); + return verify_lock(baton, lock); } @@ -732,13 +731,13 @@ svn_fs_x__allow_locked_operation(const c SVN_ERR(get_lock_helper(fs, &lock, path, have_write_lock, scratch_pool)); if (lock) - SVN_ERR(verify_lock(fs, lock, scratch_pool)); + SVN_ERR(verify_lock(fs, lock)); } return SVN_NO_ERROR; } /* The effective arguments for lock_body() below. */ -struct lock_baton { +typedef struct lock_baton_t { svn_fs_t *fs; apr_array_header_t *targets; apr_array_header_t *infos; @@ -747,13 +746,13 @@ struct lock_baton { apr_time_t expiration_date; svn_boolean_t steal_lock; apr_pool_t *result_pool; -}; +} lock_baton_t; static svn_error_t * check_lock(svn_error_t **fs_err, const char *path, const svn_fs_lock_target_t *target, - struct lock_baton *lb, + lock_baton_t *lb, svn_fs_root_t *root, apr_pool_t *pool) { @@ -847,16 +846,16 @@ check_lock(svn_error_t **fs_err, return SVN_NO_ERROR; } -struct lock_info_t { +typedef struct lock_info_t { const char *path; const char *component; svn_lock_t *lock; svn_error_t *fs_err; -}; +} lock_info_t; /* The body of svn_fs_x__lock(), which see. - BATON is a 'struct lock_baton *' holding the effective arguments. + BATON is a 'lock_baton_t *' holding the effective arguments. BATON->targets is an array of 'svn_sort__item_t' targets, sorted by path, mapping canonical path to 'svn_fs_lock_target_t'. Set BATON->infos to an array of 'lock_info_t' holding the results. For @@ -868,7 +867,7 @@ struct lock_info_t { static svn_error_t * lock_body(void *baton, apr_pool_t *pool) { - struct lock_baton *lb = baton; + lock_baton_t *lb = baton; svn_fs_root_t *root; svn_revnum_t youngest; const char *rev_0_path; @@ -876,7 +875,7 @@ lock_body(void *baton, apr_pool_t *pool) apr_pool_t *iterpool = svn_pool_create(pool); lb->infos = apr_array_make(lb->result_pool, lb->targets->nelts, - sizeof(struct lock_info_t)); + sizeof(lock_info_t)); /* Until we implement directory locks someday, we only allow locks on files or non-existent paths. */ @@ -890,7 +889,7 @@ lock_body(void *baton, apr_pool_t *pool) 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; - struct lock_info_t info; + lock_info_t info; svn_pool_clear(iterpool); @@ -898,7 +897,7 @@ lock_body(void *baton, apr_pool_t *pool) SVN_ERR(check_lock(&info.fs_err, info.path, target, lb, root, iterpool)); info.lock = NULL; info.component = NULL; - APR_ARRAY_PUSH(lb->infos, struct lock_info_t) = info; + APR_ARRAY_PUSH(lb->infos, lock_info_t) = info; if (!info.fs_err) ++outstanding; } @@ -936,8 +935,7 @@ lock_body(void *baton, apr_pool_t *pool) for (i = 0; i < lb->infos->nelts; ++i) { - struct lock_info_t *info = &APR_ARRAY_IDX(lb->infos, i, - struct lock_info_t); + 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; @@ -1015,7 +1013,7 @@ lock_body(void *baton, apr_pool_t *pool) } /* The effective arguments for unlock_body() below. */ -struct unlock_baton { +typedef struct unlock_baton_t { svn_fs_t *fs; apr_array_header_t *targets; apr_array_header_t *infos; @@ -1023,13 +1021,13 @@ struct unlock_baton { svn_boolean_t skip_check; svn_boolean_t break_lock; apr_pool_t *result_pool; -}; +} unlock_baton_t; static svn_error_t * check_unlock(svn_error_t **fs_err, const char *path, const char *token, - struct unlock_baton *ub, + unlock_baton_t *ub, svn_fs_root_t *root, apr_pool_t *pool) { @@ -1049,17 +1047,17 @@ check_unlock(svn_error_t **fs_err, return SVN_NO_ERROR; } -struct unlock_info_t { +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. - BATON is a 'struct unlock_baton *' holding the effective arguments. + BATON is a 'unlock_baton_t *' holding the effective arguments. BATON->targets is an array of 'svn_sort__item_t' targets, sorted by path, mapping canonical path to (const char *) token. Set BATON->infos to an array of 'unlock_info_t' results. For the other @@ -1071,7 +1069,7 @@ struct unlock_info_t { static svn_error_t * unlock_body(void *baton, apr_pool_t *pool) { - struct unlock_baton *ub = baton; + unlock_baton_t *ub = baton; svn_fs_root_t *root; svn_revnum_t youngest; const char *rev_0_path; @@ -1079,7 +1077,7 @@ unlock_body(void *baton, apr_pool_t *poo apr_pool_t *iterpool = svn_pool_create(pool); ub->infos = apr_array_make(ub->result_pool, ub->targets->nelts, - sizeof(struct unlock_info_t)); + 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)); @@ -1089,7 +1087,7 @@ unlock_body(void *baton, apr_pool_t *poo const svn_sort__item_t *item = &APR_ARRAY_IDX(ub->targets, i, svn_sort__item_t); const char *token = item->value; - struct unlock_info_t info = { 0 }; + unlock_info_t info = { 0 }; svn_pool_clear(iterpool); @@ -1114,7 +1112,7 @@ unlock_body(void *baton, apr_pool_t *poo ++outstanding; } - APR_ARRAY_PUSH(ub->infos, struct unlock_info_t) = info; + APR_ARRAY_PUSH(ub->infos, unlock_info_t) = info; } rev_0_path = svn_fs_x__path_rev_absolute(ub->fs, 0, pool); @@ -1130,8 +1128,7 @@ unlock_body(void *baton, apr_pool_t *poo for (j = 0; j < ub->infos->nelts; ++j) { - struct unlock_info_t *info = &APR_ARRAY_IDX(ub->infos, j, - struct unlock_info_t); + unlock_info_t *info = &APR_ARRAY_IDX(ub->infos, j, unlock_info_t); if (!info->fs_err && info->path) { @@ -1191,7 +1188,7 @@ unlock_single(svn_fs_t *fs, svn_lock_t *lock, apr_pool_t *scratch_pool) { - struct unlock_baton ub; + unlock_baton_t ub; svn_sort__item_t item; apr_array_header_t *targets = apr_array_make(scratch_pool, 1, sizeof(svn_sort__item_t)); @@ -1226,7 +1223,7 @@ svn_fs_x__lock(svn_fs_t *fs, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - struct lock_baton lb; + lock_baton_t lb; apr_array_header_t *sorted_targets; apr_hash_t *canonical_targets = apr_hash_make(scratch_pool); apr_hash_index_t *hi; @@ -1320,7 +1317,7 @@ svn_fs_x__unlock(svn_fs_t *fs, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - struct unlock_baton ub; + unlock_baton_t ub; apr_array_header_t *sorted_targets; apr_hash_t *canonical_targets = apr_hash_make(scratch_pool); apr_hash_index_t *hi; @@ -1359,8 +1356,7 @@ svn_fs_x__unlock(svn_fs_t *fs, err = svn_fs_x__with_write_lock(fs, unlock_body, &ub, scratch_pool); for (i = 0; i < ub.infos->nelts; ++i) { - struct unlock_info_t *info = &APR_ARRAY_IDX(ub.infos, i, - struct unlock_info_t); + unlock_info_t *info = &APR_ARRAY_IDX(ub.infos, i, unlock_info_t); if (!cb_err && lock_callback) { if (!info->done && !info->fs_err) Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/pack.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/pack.c?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/pack.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/pack.c Tue Jan 27 23:27:44 2015 @@ -2229,19 +2229,19 @@ pack_shard(const char *revs_dir, return SVN_NO_ERROR; } -struct pack_baton +typedef struct pack_baton_t { svn_fs_t *fs; svn_fs_pack_notify_t notify_func; void *notify_baton; svn_cancel_func_t cancel_func; void *cancel_baton; -}; +} pack_baton_t; /* The work-horse for svn_fs_x__pack, called with the FS write lock. This implements the svn_fs_x__with_write_lock() 'body' callback - type. BATON is a 'struct pack_baton *'. + type. BATON is a 'pack_baton_t *'. WARNING: if you add a call to this function, please note: The code currently assumes that any piece of code running with @@ -2257,7 +2257,7 @@ static svn_error_t * pack_body(void *baton, apr_pool_t *scratch_pool) { - struct pack_baton *pb = baton; + pack_baton_t *pb = baton; svn_fs_x__data_t *ffd = pb->fs->fsap_data; apr_int64_t completed_shards; apr_int64_t i; @@ -2313,7 +2313,7 @@ svn_fs_x__pack(svn_fs_t *fs, void *cancel_baton, apr_pool_t *scratch_pool) { - struct pack_baton pb = { 0 }; + pack_baton_t pb = { 0 }; pb.fs = fs; pb.notify_func = notify_func; pb.notify_baton = notify_baton; Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/recovery.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/recovery.c?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/recovery.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/recovery.c Tue Jan 27 23:27:44 2015 @@ -106,25 +106,26 @@ recover_get_largest_revision(svn_fs_t *f } /* Baton used for recover_body below. */ -struct recover_baton { +typedef struct recover_baton_t { svn_fs_t *fs; svn_cancel_func_t cancel_func; void *cancel_baton; -}; +} recover_baton_t; /* The work-horse for svn_fs_x__recover, called with the FS write lock. This implements the svn_fs_x__with_write_lock() - 'body' callback type. BATON is a 'struct recover_baton *'. */ + 'body' callback type. BATON is a 'recover_baton_t *'. */ static svn_error_t * recover_body(void *baton, apr_pool_t *scratch_pool) { - struct recover_baton *b = baton; + recover_baton_t *b = baton; svn_fs_t *fs = b->fs; svn_fs_x__data_t *ffd = fs->fsap_data; svn_revnum_t max_rev; svn_revnum_t youngest_rev; - svn_node_kind_t youngest_revprops_kind; + svn_boolean_t revprop_missing = TRUE; + svn_boolean_t revprop_accessible = FALSE; /* Lose potentially corrupted data in temp files */ SVN_ERR(svn_fs_x__reset_revprop_generation_file(fs, scratch_pool)); @@ -179,35 +180,49 @@ recover_body(void *baton, /* Before setting current, verify that there is a revprops file for the youngest revision. (Issue #2992) */ - SVN_ERR(svn_io_check_path(svn_fs_x__path_revprops(fs, max_rev, scratch_pool), - &youngest_revprops_kind, scratch_pool)); - if (youngest_revprops_kind == svn_node_none) + if (svn_fs_x__is_packed_revprop(fs, max_rev)) { - svn_boolean_t missing = TRUE; - if (!svn_fs_x__packed_revprop_available(&missing, fs, max_rev, scratch_pool)) + revprop_accessible + = svn_fs_x__packed_revprop_available(&revprop_missing, fs, max_rev, + scratch_pool); + } + else + { + svn_node_kind_t youngest_revprops_kind; + SVN_ERR(svn_io_check_path(svn_fs_x__path_revprops(fs, max_rev, + scratch_pool), + &youngest_revprops_kind, scratch_pool)); + + if (youngest_revprops_kind == svn_node_file) + { + revprop_missing = FALSE; + revprop_accessible = TRUE; + } + else if (youngest_revprops_kind != svn_node_none) { - if (missing) - { - return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, - _("Revision %ld has a revs file but no " - "revprops file"), - max_rev); - } - else - { - return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, - _("Revision %ld has a revs file but the " - "revprops file is inaccessible"), - max_rev); - } - } + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + _("Revision %ld has a non-file where its " + "revprops file should be"), + max_rev); + } } - else if (youngest_revprops_kind != svn_node_file) + + if (!revprop_accessible) { - return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, - _("Revision %ld has a non-file where its " - "revprops file should be"), - max_rev); + if (revprop_missing) + { + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + _("Revision %ld has a revs file but no " + "revprops file"), + max_rev); + } + else + { + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + _("Revision %ld has a revs file but the " + "revprops file is inaccessible"), + max_rev); + } } /* Prune younger-than-(newfound-youngest) revisions from the rep @@ -217,7 +232,8 @@ recover_body(void *baton, { svn_boolean_t rep_cache_exists; - SVN_ERR(svn_fs_x__exists_rep_cache(&rep_cache_exists, fs, scratch_pool)); + SVN_ERR(svn_fs_x__exists_rep_cache(&rep_cache_exists, fs, + scratch_pool)); if (rep_cache_exists) SVN_ERR(svn_fs_x__del_rep_reference(fs, max_rev, scratch_pool)); } @@ -230,10 +246,11 @@ recover_body(void *baton, /* This implements the fs_library_vtable_t.recover() API. */ svn_error_t * svn_fs_x__recover(svn_fs_t *fs, - svn_cancel_func_t cancel_func, void *cancel_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, apr_pool_t *scratch_pool) { - struct recover_baton b; + recover_baton_t b; /* We have no way to take out an exclusive lock in FSX, so we're restricted as to the types of recovery we can do. Luckily, Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/rep-cache.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/rep-cache.c?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/rep-cache.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/rep-cache.c Tue Jan 27 23:27:44 2015 @@ -239,7 +239,8 @@ svn_error_t * svn_fs_x__get_rep_reference(svn_fs_x__representation_t **rep, svn_fs_t *fs, svn_checksum_t *checksum, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { svn_fs_x__data_t *ffd = fs->fsap_data; svn_sqlite__stmt_t *stmt; @@ -247,7 +248,7 @@ svn_fs_x__get_rep_reference(svn_fs_x__re SVN_ERR_ASSERT(ffd->rep_sharing_allowed); if (! ffd->rep_cache_db) - SVN_ERR(svn_fs_x__open_rep_cache(fs, pool)); + SVN_ERR(svn_fs_x__open_rep_cache(fs, scratch_pool)); /* We only allow SHA1 checksums in this table. */ if (checksum->kind != svn_checksum_sha1) @@ -257,12 +258,12 @@ svn_fs_x__get_rep_reference(svn_fs_x__re SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db, STMT_GET_REP)); SVN_ERR(svn_sqlite__bindf(stmt, "s", - svn_checksum_to_cstring(checksum, pool))); + svn_checksum_to_cstring(checksum, scratch_pool))); SVN_ERR(svn_sqlite__step(&have_row, stmt)); if (have_row) { - *rep = apr_pcalloc(pool, sizeof(**rep)); + *rep = apr_pcalloc(result_pool, sizeof(**rep)); memcpy((*rep)->sha1_digest, checksum->digest, sizeof((*rep)->sha1_digest)); (*rep)->has_sha1 = TRUE; @@ -280,12 +281,12 @@ svn_fs_x__get_rep_reference(svn_fs_x__re { /* Check that REP refers to a revision that exists in FS. */ svn_revnum_t revision = svn_fs_x__get_revnum((*rep)->id.change_set); - svn_error_t *err = svn_fs_x__ensure_revision_exists(revision, fs, pool); + svn_error_t *err = svn_fs_x__ensure_revision_exists(revision, fs, + scratch_pool); if (err) return svn_error_createf(SVN_ERR_FS_CORRUPT, err, - "Checksum '%s' in rep-cache is beyond HEAD", - svn_checksum_to_cstring_display(checksum, - pool)); + "Checksum '%s' in rep-cache is beyond HEAD", + svn_checksum_to_cstring_display(checksum, scratch_pool)); } return SVN_NO_ERROR; @@ -335,7 +336,7 @@ svn_fs_x__set_rep_reference(svn_fs_t *fs should exist. If so that's cool -- just do nothing. If not, that's a red flag! */ SVN_ERR(svn_fs_x__get_rep_reference(&old_rep, fs, &checksum, - scratch_pool)); + scratch_pool, scratch_pool)); if (!old_rep) { Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/rep-cache.h URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/rep-cache.h?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/rep-cache.h (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/rep-cache.h Tue Jan 27 23:27:44 2015 @@ -61,14 +61,15 @@ svn_fs_x__walk_rep_reference(svn_fs_t *f apr_pool_t *scratch_pool); /* Return the representation REP in FS which has fulltext CHECKSUM. - REP is allocated in POOL. If the rep cache database has not been - opened, just set *REP to NULL. Returns SVN_ERR_FS_CORRUPT if - a reference beyond HEAD is detected. */ + REP is allocated in RESULT_POOL. If the rep cache database has not been + opened, just set *REP to NULL. Returns SVN_ERR_FS_CORRUPT if a reference + beyond HEAD is detected. Uses SCRATCH_POOL for temporary allocations. */ svn_error_t * svn_fs_x__get_rep_reference(svn_fs_x__representation_t **rep, svn_fs_t *fs, svn_checksum_t *checksum, - apr_pool_t *pool); + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Set the representation REP in FS, using REP->CHECKSUM. Use SCRATCH_POOL for temporary allocations. Returns SVN_ERR_FS_CORRUPT Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/revprops.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/revprops.c?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/revprops.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/revprops.c Tue Jan 27 23:27:44 2015 @@ -677,7 +677,7 @@ parse_revprop(apr_hash_t **properties, SVN_ERR(svn_hash_read2(*properties, stream, SVN_HASH_TERMINATOR, result_pool)); - if (has_revprop_cache(fs, result_pool)) + if (has_revprop_cache(fs, scratch_pool)) { svn_fs_x__data_t *ffd = fs->fsap_data; svn_fs_x__pair_cache_key_t key = { 0 }; Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/temp_serializer.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/temp_serializer.c?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/temp_serializer.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/temp_serializer.c Tue Jan 27 23:27:44 2015 @@ -795,6 +795,23 @@ find_entry(svn_fs_x__dirent_t **entries, return lower; } +/* Utility function that returns TRUE if entry number IDX in ENTRIES has the + * name NAME. + */ +static svn_boolean_t +found_entry(const svn_fs_x__dirent_t * const *entries, + const char *name, + apr_size_t idx) +{ + /* check whether we actually found a match */ + const svn_fs_x__dirent_t *entry = + svn_temp_deserializer__ptr(entries, (const void *const *)&entries[idx]); + const char* entry_name = + svn_temp_deserializer__ptr(entry, (const void *const *)&entry->name); + + return strcmp(entry_name, name) == 0; +} + svn_error_t * svn_fs_x__extract_dir_entry(void **out, const void *data, @@ -803,8 +820,9 @@ svn_fs_x__extract_dir_entry(void **out, apr_pool_t *pool) { const dir_data_t *dir_data = data; - const char* name = baton; + svn_fs_x__ede_baton_t *b = baton; svn_boolean_t found; + apr_size_t pos; /* resolve the reference to the entries array */ const svn_fs_x__dirent_t * const *entries = @@ -814,14 +832,33 @@ svn_fs_x__extract_dir_entry(void **out, const apr_uint32_t *lengths = svn_temp_deserializer__ptr(data, (const void *const *)&dir_data->lengths); - /* binary search for the desired entry by name */ - apr_size_t pos = find_entry((svn_fs_x__dirent_t **)entries, - name, - dir_data->count, - &found); + /* Special case: Early out for empty directories. + That simplifies tests further down the road. */ + *out = NULL; + if (dir_data->count == 0) + return SVN_NO_ERROR; + + /* HINT _might_ be the position we hit last time. + If within valid range, check whether HINT+1 is a hit. */ + if ( b->hint < dir_data->count - 1 + && found_entry(entries, b->name, b->hint + 1)) + { + /* Got lucky. */ + pos = b->hint + 1; + found = TRUE; + } + else + { + /* Binary search for the desired entry by name. */ + pos = find_entry((svn_fs_x__dirent_t **)entries, b->name, + dir_data->count, &found); + } + + /* Remember the hit index - if we FOUND the entry. */ + if (found) + b->hint = pos; /* de-serialize that entry or return NULL, if no match has been found */ - *out = NULL; if (found) { const svn_fs_x__dirent_t *source = Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/temp_serializer.h URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/temp_serializer.h?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/temp_serializer.h (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/temp_serializer.h Tue Jan 27 23:27:44 2015 @@ -194,9 +194,20 @@ svn_fs_x__get_sharded_offset(void **out, apr_pool_t *pool); /** + * Baton type to be used with svn_fs_x__extract_dir_entry. */ +typedef struct svn_fs_x__ede_baton_t +{ + /* Name of the directory entry to find. */ + const char *name; + + /* Lookup hint [in / out] */ + apr_size_t hint; +} svn_fs_x__ede_baton_t; + +/** * Implements #svn_cache__partial_getter_func_t for a single * #svn_fs_x__dirent_t within a serialized directory contents hash, - * identified by its name (const char @a *baton). + * identified by its name (given in @a svn_fs_x__ede_baton_t @a *baton). */ svn_error_t * svn_fs_x__extract_dir_entry(void **out,
