Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/transaction.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/transaction.c?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/transaction.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/transaction.c Tue Jan 27 23:27:44 2015 @@ -182,12 +182,13 @@ with_txnlist_lock(svn_fs_t *fs, } -/* Get a lock on empty file LOCK_FILENAME, creating it in POOL. */ +/* Get a lock on empty file LOCK_FILENAME, creating it in RESULT_POOL. */ static svn_error_t * get_lock_on_filesystem(const char *lock_filename, - apr_pool_t *pool) + apr_pool_t *result_pool) { - return svn_error_trace(svn_io__file_lock_autocreate(lock_filename, pool)); + return svn_error_trace(svn_io__file_lock_autocreate(lock_filename, + result_pool)); } /* Reset the HAS_WRITE_LOCK member in the FFD given as BATON_VOID. @@ -355,7 +356,8 @@ init_lock_baton(with_lock_baton_t *baton /* Return the baton for the innermost lock of a (potential) lock chain. The baton shall take out LOCK_ID from FS and execute BODY with BATON - while the lock is being held. Allocate the result in a sub-pool of POOL. + while the lock is being held. Allocate the result in a sub-pool of + RESULT_POOL. */ static with_lock_baton_t * create_lock_baton(svn_fs_t *fs, @@ -363,11 +365,11 @@ create_lock_baton(svn_fs_t *fs, svn_error_t *(*body)(void *baton, apr_pool_t *scratch_pool), void *baton, - apr_pool_t *pool) + apr_pool_t *result_pool) { /* Allocate everything along the lock chain into a single sub-pool. This minimizes memory usage and cleanup overhead. */ - apr_pool_t *lock_pool = svn_pool_create(pool); + apr_pool_t *lock_pool = svn_pool_create(result_pool); with_lock_baton_t *result = apr_pcalloc(lock_pool, sizeof(*result)); /* Store parameters. */ @@ -486,11 +488,11 @@ svn_fs_x__with_all_locks(svn_fs_t *fs, /* A structure used by unlock_proto_rev() and unlock_proto_rev_body(), which see. */ -struct unlock_proto_rev_baton +typedef struct unlock_proto_rev_baton_t { svn_fs_x__txn_id_t txn_id; void *lockcookie; -}; +} unlock_proto_rev_baton_t; /* Callback used in the implementation of unlock_proto_rev(). */ static svn_error_t * @@ -498,7 +500,7 @@ unlock_proto_rev_body(svn_fs_t *fs, const void *baton, apr_pool_t *scratch_pool) { - const struct unlock_proto_rev_baton *b = baton; + const unlock_proto_rev_baton_t *b = baton; apr_file_t *lockfile = b->lockcookie; svn_fs_x__shared_txn_data_t *txn = get_shared_txn(fs, b->txn_id, FALSE); apr_status_t apr_err; @@ -541,7 +543,7 @@ unlock_proto_rev(svn_fs_t *fs, void *lockcookie, apr_pool_t *scratch_pool) { - struct unlock_proto_rev_baton b; + unlock_proto_rev_baton_t b; b.txn_id = txn_id; b.lockcookie = lockcookie; @@ -550,11 +552,11 @@ unlock_proto_rev(svn_fs_t *fs, /* A structure used by get_writable_proto_rev() and get_writable_proto_rev_body(), which see. */ -struct get_writable_proto_rev_baton +typedef struct get_writable_proto_rev_baton_t { void **lockcookie; svn_fs_x__txn_id_t txn_id; -}; +} get_writable_proto_rev_baton_t; /* Callback used in the implementation of get_writable_proto_rev(). */ static svn_error_t * @@ -562,7 +564,7 @@ get_writable_proto_rev_body(svn_fs_t *fs const void *baton, apr_pool_t *scratch_pool) { - const struct get_writable_proto_rev_baton *b = baton; + const get_writable_proto_rev_baton_t *b = baton; void **lockcookie = b->lockcookie; svn_fs_x__shared_txn_data_t *txn = get_shared_txn(fs, b->txn_id, TRUE); @@ -688,7 +690,7 @@ get_writable_proto_rev(apr_file_t **file svn_fs_x__txn_id_t txn_id, apr_pool_t *pool) { - struct get_writable_proto_rev_baton b; + get_writable_proto_rev_baton_t b; svn_error_t *err; apr_off_t end_offset = 0; @@ -773,7 +775,8 @@ svn_fs_x__put_node_revision(svn_fs_t *fs svn_fs_x__id_unparse(id, scratch_pool)->data); SVN_ERR(svn_io_file_open(&noderev_file, - svn_fs_x__path_txn_node_rev(fs, id, scratch_pool), + svn_fs_x__path_txn_node_rev(fs, id, scratch_pool, + scratch_pool), APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BUFFERED, APR_OS_DEFAULT, scratch_pool)); @@ -1168,11 +1171,11 @@ create_new_txn_noderev_from_rev(svn_fs_t } /* A structure used by get_and_increment_txn_key_body(). */ -struct get_and_increment_txn_key_baton { +typedef struct get_and_increment_txn_key_baton_t +{ svn_fs_t *fs; apr_uint64_t txn_number; - apr_pool_t *pool; -}; +} get_and_increment_txn_key_baton_t; /* Callback used in the implementation of create_txn_dir(). This gets the current base 36 value in PATH_TXN_CURRENT and increments it. @@ -1181,14 +1184,14 @@ static svn_error_t * get_and_increment_txn_key_body(void *baton, apr_pool_t *scratch_pool) { - struct get_and_increment_txn_key_baton *cb = baton; + get_and_increment_txn_key_baton_t *cb = baton; const char *txn_current_filename = svn_fs_x__path_txn_current(cb->fs, scratch_pool); const char *tmp_filename; char new_id_str[SVN_INT64_BUFFER_SIZE]; svn_stringbuf_t *buf; - SVN_ERR(svn_fs_x__read_content(&buf, txn_current_filename, cb->pool)); + SVN_ERR(svn_fs_x__read_content(&buf, txn_current_filename, scratch_pool)); /* remove trailing newlines */ cb->txn_number = svn__base36toui64(NULL, buf->data); @@ -1214,44 +1217,52 @@ static svn_error_t * create_txn_dir(const char **id_p, svn_fs_x__txn_id_t *txn_id, svn_fs_t *fs, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - struct get_and_increment_txn_key_baton cb; + get_and_increment_txn_key_baton_t cb; const char *txn_dir; /* Get the current transaction sequence value, which is a base-36 number, from the txn-current file, and write an incremented value back out to the file. Place the revision number the transaction is based off into the transaction id. */ - cb.pool = pool; cb.fs = fs; SVN_ERR(svn_fs_x__with_txn_current_lock(fs, get_and_increment_txn_key_body, &cb, - pool)); + scratch_pool)); *txn_id = cb.txn_number; - *id_p = svn_fs_x__txn_name(*txn_id, pool); - txn_dir = svn_fs_x__path_txn_dir(fs, *txn_id, pool); + *id_p = svn_fs_x__txn_name(*txn_id, result_pool); + txn_dir = svn_fs_x__path_txn_dir(fs, *txn_id, scratch_pool); - return svn_io_dir_make(txn_dir, APR_OS_DEFAULT, pool); + return svn_io_dir_make(txn_dir, APR_OS_DEFAULT, scratch_pool); } -svn_error_t * -svn_fs_x__create_txn(svn_fs_txn_t **txn_p, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *pool) +/* Create a new transaction in filesystem FS, based on revision REV, + and store it in *TXN_P, allocated in RESULT_POOL. Allocate necessary + temporaries from SCRATCH_POOL. */ +static svn_error_t * +create_txn(svn_fs_txn_t **txn_p, + svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { svn_fs_txn_t *txn; fs_txn_data_t *ftd; svn_fs_x__id_t root_id; - txn = apr_pcalloc(pool, sizeof(*txn)); - ftd = apr_pcalloc(pool, sizeof(*ftd)); + txn = apr_pcalloc(result_pool, sizeof(*txn)); + ftd = apr_pcalloc(result_pool, sizeof(*ftd)); + + /* Valid revision number? */ + SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, scratch_pool)); /* Get the txn_id. */ - SVN_ERR(create_txn_dir(&txn->id, &ftd->txn_id, fs, pool)); + SVN_ERR(create_txn_dir(&txn->id, &ftd->txn_id, fs, result_pool, + scratch_pool)); txn->fs = fs; txn->base_rev = rev; @@ -1261,28 +1272,31 @@ svn_fs_x__create_txn(svn_fs_txn_t **txn_ *txn_p = txn; /* Create a new root node for this transaction. */ - SVN_ERR(svn_fs_x__rev_get_root(&root_id, fs, rev, pool)); - SVN_ERR(create_new_txn_noderev_from_rev(fs, ftd->txn_id, &root_id, pool)); + svn_fs_x__init_rev_root(&root_id, rev); + SVN_ERR(create_new_txn_noderev_from_rev(fs, ftd->txn_id, &root_id, + scratch_pool)); /* Create an empty rev file. */ SVN_ERR(svn_io_file_create_empty( - svn_fs_x__path_txn_proto_rev(fs, ftd->txn_id, pool), - pool)); + svn_fs_x__path_txn_proto_rev(fs, ftd->txn_id, scratch_pool), + scratch_pool)); /* Create an empty rev-lock file. */ SVN_ERR(svn_io_file_create_empty( - svn_fs_x__path_txn_proto_rev_lock(fs, ftd->txn_id, pool), - pool)); + svn_fs_x__path_txn_proto_rev_lock(fs, ftd->txn_id, scratch_pool), + scratch_pool)); /* Create an empty changes file. */ SVN_ERR(svn_io_file_create_empty( - svn_fs_x__path_txn_changes(fs, ftd->txn_id, pool), - pool)); + svn_fs_x__path_txn_changes(fs, ftd->txn_id, scratch_pool), + scratch_pool)); /* Create the next-ids file. */ - return svn_io_file_create( - svn_fs_x__path_txn_next_ids(fs, ftd->txn_id, pool), - "0 0\n", pool); + SVN_ERR(svn_io_file_create( + svn_fs_x__path_txn_next_ids(fs, ftd->txn_id, scratch_pool), + "0 0\n", scratch_pool)); + + return SVN_NO_ERROR; } /* Store the property list for transaction TXN_ID in PROPLIST. @@ -1691,12 +1705,13 @@ svn_fs_x__set_entry(svn_fs_t *fs, const char *name, const svn_fs_x__id_t *id, svn_node_kind_t kind, + apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_fs_x__representation_t *rep = parent_noderev->data_rep; const char *filename = svn_fs_x__path_txn_node_children(fs, &parent_noderev->noderev_id, - scratch_pool); + scratch_pool, scratch_pool); apr_file_t *file; svn_stream_t *out; svn_fs_x__data_t *ffd = fs->fsap_data; @@ -1718,13 +1733,21 @@ svn_fs_x__set_entry(svn_fs_t *fs, svn_pool_clear(subpool); + /* Provide the parent with a data rep if it had none before + (directories so far empty). */ + if (!rep) + { + rep = apr_pcalloc(result_pool, sizeof(*rep)); + parent_noderev->data_rep = rep; + } + /* Mark the node-rev's data rep as mutable. */ - rep = apr_pcalloc(scratch_pool, sizeof(*rep)); rep->id.change_set = svn_fs_x__change_set_by_txn(txn_id); rep->id.number = SVN_FS_X__ITEM_INDEX_UNUSED; - parent_noderev->data_rep = rep; + + /* Save noderev to disk. */ SVN_ERR(svn_fs_x__put_node_revision(fs, parent_noderev, FALSE, - scratch_pool)); + subpool)); } else { @@ -1829,7 +1852,7 @@ svn_fs_x__add_change(svn_fs_t *fs, /* This baton is used by the representation writing streams. It keeps track of the checksum information as well as the total size of the representation so far. */ -struct rep_write_baton +typedef struct rep_write_baton_t { /* The FS we are writing to. */ svn_fs_t *fs; @@ -1865,22 +1888,23 @@ struct rep_write_baton /* Receives the low-level checksum when closing REP_STREAM. */ apr_uint32_t fnv1a_checksum; - /* Local / scratch pool, available for temporary allocations. */ - apr_pool_t *scratch_pool; + /* Local pool, available for allocations that must remain valid as long + as this baton is used but may be cleaned up immediately afterwards. */ + apr_pool_t *local_pool; /* Outer / result pool. */ apr_pool_t *result_pool; -}; +} rep_write_baton_t; /* Handler for the write method of the representation writable stream. - BATON is a rep_write_baton, DATA is the data to write, and *LEN is + BATON is a rep_write_baton_t, DATA is the data to write, and *LEN is the length of this data. */ static svn_error_t * rep_write_contents(void *baton, const char *data, apr_size_t *len) { - struct rep_write_baton *b = baton; + rep_write_baton_t *b = baton; SVN_ERR(svn_checksum_update(b->md5_checksum_ctx, data, *len)); SVN_ERR(svn_checksum_update(b->sha1_checksum_ctx, data, *len)); @@ -2057,14 +2081,14 @@ static apr_status_t rep_write_cleanup(void *data) { svn_error_t *err; - struct rep_write_baton *b = data; + rep_write_baton_t *b = data; svn_fs_x__txn_id_t txn_id = svn_fs_x__get_txn_id(b->noderev->noderev_id.change_set); /* Truncate and close the protorevfile. */ - err = svn_io_file_trunc(b->file, b->rep_offset, b->scratch_pool); + err = svn_io_file_trunc(b->file, b->rep_offset, b->local_pool); err = svn_error_compose_create(err, svn_io_file_close(b->file, - b->scratch_pool)); + b->local_pool)); /* Remove our lock regardless of any preceding errors so that the being_written flag is always removed and stays consistent with the @@ -2073,7 +2097,7 @@ rep_write_cleanup(void *data) err = svn_error_compose_create(err, unlock_proto_rev(b->fs, txn_id, b->lockcookie, - b->scratch_pool)); + b->local_pool)); if (err) { apr_status_t rc = err->apr_err; @@ -2084,18 +2108,18 @@ rep_write_cleanup(void *data) return APR_SUCCESS; } -/* Get a rep_write_baton and store it in *WB_P for the representation - indicated by NODEREV in filesystem FS. Perform allocations in - POOL. Only appropriate for file contents, not for props or - directory contents. */ +/* Get a rep_write_baton_t, allocated from RESULT_POOL, and store it in + WB_P for the representation indicated by NODEREV in filesystem FS. + Only appropriate for file contents, not for props or directory contents. + */ static svn_error_t * -rep_write_get_baton(struct rep_write_baton **wb_p, +rep_write_get_baton(rep_write_baton_t **wb_p, svn_fs_t *fs, svn_fs_x__noderev_t *noderev, - apr_pool_t *pool) + apr_pool_t *result_pool) { svn_fs_x__data_t *ffd = fs->fsap_data; - struct rep_write_baton *b; + rep_write_baton_t *b; apr_file_t *file; svn_fs_x__representation_t *base_rep; svn_stream_t *source; @@ -2106,34 +2130,36 @@ rep_write_get_baton(struct rep_write_bat svn_fs_x__txn_id_t txn_id = svn_fs_x__get_txn_id(noderev->noderev_id.change_set); - b = apr_pcalloc(pool, sizeof(*b)); + b = apr_pcalloc(result_pool, sizeof(*b)); - b->sha1_checksum_ctx = svn_checksum_ctx_create(svn_checksum_sha1, pool); - b->md5_checksum_ctx = svn_checksum_ctx_create(svn_checksum_md5, pool); + b->sha1_checksum_ctx = svn_checksum_ctx_create(svn_checksum_sha1, + result_pool); + b->md5_checksum_ctx = svn_checksum_ctx_create(svn_checksum_md5, + result_pool); b->fs = fs; - b->result_pool = pool; - b->scratch_pool = svn_pool_create(pool); + b->result_pool = result_pool; + b->local_pool = svn_pool_create(result_pool); b->rep_size = 0; b->noderev = noderev; /* Open the prototype rev file and seek to its end. */ SVN_ERR(get_writable_proto_rev(&file, &b->lockcookie, fs, txn_id, - b->scratch_pool)); + b->local_pool)); b->file = file; b->rep_stream = svn_checksum__wrap_write_stream_fnv1a_32x4( &b->fnv1a_checksum, svn_stream_from_aprfile2(file, TRUE, - b->scratch_pool), - b->scratch_pool); + b->local_pool), + b->local_pool); - SVN_ERR(svn_fs_x__get_file_offset(&b->rep_offset, file, b->scratch_pool)); + SVN_ERR(svn_fs_x__get_file_offset(&b->rep_offset, file, b->local_pool)); /* Get the base for this delta. */ - SVN_ERR(choose_delta_base(&base_rep, fs, noderev, FALSE, b->scratch_pool)); + SVN_ERR(choose_delta_base(&base_rep, fs, noderev, FALSE, b->local_pool)); SVN_ERR(svn_fs_x__get_contents(&source, fs, base_rep, TRUE, - b->scratch_pool)); + b->local_pool)); /* Write out the rep header. */ if (base_rep) @@ -2148,14 +2174,14 @@ rep_write_get_baton(struct rep_write_bat header.type = svn_fs_x__rep_self_delta; } SVN_ERR(svn_fs_x__write_rep_header(&header, b->rep_stream, - b->scratch_pool)); + b->local_pool)); /* Now determine the offset of the actual svndiff data. */ SVN_ERR(svn_fs_x__get_file_offset(&b->delta_start, file, - b->scratch_pool)); + b->local_pool)); /* Cleanup in case something goes wrong. */ - apr_pool_cleanup_register(b->scratch_pool, b, rep_write_cleanup, + apr_pool_cleanup_register(b->local_pool, b, rep_write_cleanup, apr_pool_cleanup_null); /* Prepare to write the svndiff data. */ @@ -2164,7 +2190,7 @@ rep_write_get_baton(struct rep_write_bat svn_stream_disown(b->rep_stream, b->result_pool), diff_version, ffd->delta_compression_level, - pool); + result_pool); b->delta_stream = svn_txdelta_target_push(wh, whb, source, b->result_pool); @@ -2213,7 +2239,9 @@ get_shared_rep(svn_fs_x__representation_ svn_checksum_t checksum; checksum.digest = rep->sha1_digest; checksum.kind = svn_checksum_sha1; - err = svn_fs_x__get_rep_reference(old_rep, fs, &checksum, result_pool); + err = svn_fs_x__get_rep_reference(old_rep, fs, &checksum, result_pool, + scratch_pool); + /* ### Other error codes that we shouldn't mask out? */ if (err == SVN_NO_ERROR) { @@ -2301,12 +2329,12 @@ digests_final(svn_fs_x__representation_t } /* Close handler for the representation write stream. BATON is a - rep_write_baton. Writes out a new node-rev that correctly + rep_write_baton_t. Writes out a new node-rev that correctly references the representation we just finished writing. */ static svn_error_t * rep_write_contents_close(void *baton) { - struct rep_write_baton *b = baton; + rep_write_baton_t *b = baton; svn_fs_x__representation_t *rep; svn_fs_x__representation_t *old_rep; apr_off_t offset; @@ -2319,7 +2347,7 @@ rep_write_contents_close(void *baton) SVN_ERR(svn_stream_close(b->delta_stream)); /* Determine the length of the svndiff data. */ - SVN_ERR(svn_fs_x__get_file_offset(&offset, b->file, b->scratch_pool)); + SVN_ERR(svn_fs_x__get_file_offset(&offset, b->file, b->local_pool)); rep->size = offset - b->delta_start; /* Fill in the rest of the representation field. */ @@ -2334,12 +2362,12 @@ rep_write_contents_close(void *baton) /* Check and see if we already have a representation somewhere that's identical to the one we just wrote out. */ SVN_ERR(get_shared_rep(&old_rep, b->fs, rep, NULL, b->result_pool, - b->scratch_pool)); + b->local_pool)); if (old_rep) { /* We need to erase from the protorev the data we just wrote. */ - SVN_ERR(svn_io_file_trunc(b->file, b->rep_offset, b->scratch_pool)); + SVN_ERR(svn_io_file_trunc(b->file, b->rep_offset, b->local_pool)); /* Use the old rep for this content. */ b->noderev->data_rep = old_rep; @@ -2349,9 +2377,9 @@ rep_write_contents_close(void *baton) /* Write out our cosmetic end marker. */ SVN_ERR(svn_stream_puts(b->rep_stream, "ENDREP\n")); SVN_ERR(allocate_item_index(&rep->id.number, b->fs, txn_id, - b->scratch_pool)); + b->local_pool)); SVN_ERR(store_l2p_index_entry(b->fs, txn_id, b->rep_offset, - rep->id.number, b->scratch_pool)); + rep->id.number, b->local_pool)); b->noderev->data_rep = rep; } @@ -2359,11 +2387,11 @@ rep_write_contents_close(void *baton) SVN_ERR(svn_stream_close(b->rep_stream)); /* Remove cleanup callback. */ - apr_pool_cleanup_kill(b->scratch_pool, b, rep_write_cleanup); + apr_pool_cleanup_kill(b->local_pool, b, rep_write_cleanup); /* Write out the new node-rev information. */ SVN_ERR(svn_fs_x__put_node_revision(b->fs, b->noderev, FALSE, - b->scratch_pool)); + b->local_pool)); if (!old_rep) { svn_fs_x__p2l_entry_t entry; @@ -2372,46 +2400,45 @@ rep_write_contents_close(void *baton) noderev_id.number = rep->id.number; entry.offset = b->rep_offset; - SVN_ERR(svn_fs_x__get_file_offset(&offset, b->file, b->scratch_pool)); + SVN_ERR(svn_fs_x__get_file_offset(&offset, b->file, b->local_pool)); entry.size = offset - b->rep_offset; entry.type = SVN_FS_X__ITEM_TYPE_FILE_REP; entry.item_count = 1; entry.items = &noderev_id; entry.fnv1_checksum = b->fnv1a_checksum; - SVN_ERR(store_sha1_rep_mapping(b->fs, b->noderev, b->scratch_pool)); - SVN_ERR(store_p2l_index_entry(b->fs, txn_id, &entry, b->scratch_pool)); + SVN_ERR(store_sha1_rep_mapping(b->fs, b->noderev, b->local_pool)); + SVN_ERR(store_p2l_index_entry(b->fs, txn_id, &entry, b->local_pool)); } - SVN_ERR(svn_io_file_close(b->file, b->scratch_pool)); - SVN_ERR(unlock_proto_rev(b->fs, txn_id, b->lockcookie, b->scratch_pool)); - svn_pool_destroy(b->scratch_pool); + SVN_ERR(svn_io_file_close(b->file, b->local_pool)); + SVN_ERR(unlock_proto_rev(b->fs, txn_id, b->lockcookie, b->local_pool)); + svn_pool_destroy(b->local_pool); return SVN_NO_ERROR; } -/* Store a writable stream in *CONTENTS_P that will receive all data - written and store it as the file data representation referenced by - NODEREV in filesystem FS. Perform temporary allocations in - POOL. Only appropriate for file data, not props or directory - contents. */ +/* Store a writable stream in *CONTENTS_P, allocated in RESULT_POOL, that + will receive all data written and store it as the file data representation + referenced by NODEREV in filesystem FS. Only appropriate for file data, + not props or directory contents. */ static svn_error_t * set_representation(svn_stream_t **contents_p, svn_fs_t *fs, svn_fs_x__noderev_t *noderev, - apr_pool_t *pool) + apr_pool_t *result_pool) { - struct rep_write_baton *wb; + rep_write_baton_t *wb; if (! svn_fs_x__is_txn(noderev->noderev_id.change_set)) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Attempted to write to non-transaction '%s'"), svn_fs_x__id_unparse(&noderev->noderev_id, - pool)->data); + result_pool)->data); - SVN_ERR(rep_write_get_baton(&wb, fs, noderev, pool)); + SVN_ERR(rep_write_get_baton(&wb, fs, noderev, result_pool)); - *contents_p = svn_stream_create(wb, pool); + *contents_p = svn_stream_create(wb, result_pool); svn_stream_set_write(*contents_p, rep_write_contents); svn_stream_set_close(*contents_p, rep_write_contents_close); @@ -2422,13 +2449,13 @@ svn_error_t * svn_fs_x__set_contents(svn_stream_t **stream, svn_fs_t *fs, svn_fs_x__noderev_t *noderev, - apr_pool_t *pool) + apr_pool_t *result_pool) { if (noderev->kind != svn_node_file) return svn_error_create(SVN_ERR_FS_NOT_FILE, NULL, _("Can't set text contents of a directory")); - return set_representation(stream, fs, noderev, pool); + return set_representation(stream, fs, noderev, result_pool); } svn_error_t * @@ -2463,7 +2490,8 @@ svn_fs_x__set_proplist(svn_fs_t *fs, apr_pool_t *scratch_pool) { const svn_fs_x__id_t *id = &noderev->noderev_id; - const char *filename = svn_fs_x__path_txn_node_props(fs, id, scratch_pool); + const char *filename = svn_fs_x__path_txn_node_props(fs, id, scratch_pool, + scratch_pool); apr_file_t *file; svn_stream_t *out; @@ -2492,7 +2520,7 @@ svn_fs_x__set_proplist(svn_fs_t *fs, } /* This baton is used by the stream created for write_container_rep. */ -struct write_container_baton +typedef struct write_container_baton_t { svn_stream_t *stream; @@ -2500,17 +2528,17 @@ struct write_container_baton svn_checksum_ctx_t *md5_ctx; svn_checksum_ctx_t *sha1_ctx; -}; +} write_container_baton_t; /* The handler for the write_container_rep stream. BATON is a - write_container_baton, DATA has the data to write and *LEN is the number + write_container_baton_t, DATA has the data to write and *LEN is the number of bytes to write. */ static svn_error_t * write_container_handler(void *baton, const char *data, apr_size_t *len) { - struct write_container_baton *whb = baton; + write_container_baton_t *whb = baton; SVN_ERR(svn_checksum_update(whb->md5_ctx, data, *len)); SVN_ERR(svn_checksum_update(whb->sha1_ctx, data, *len)); @@ -2598,7 +2626,7 @@ write_container_delta_rep(svn_fs_x__repr apr_off_t delta_start = 0; apr_off_t offset = 0; - struct write_container_baton *whb; + write_container_baton_t *whb; int diff_version = 1; svn_boolean_t is_props = (item_type == SVN_FS_X__ITEM_TYPE_FILE_PROPS) || (item_type == SVN_FS_X__ITEM_TYPE_DIR_PROPS); @@ -2894,7 +2922,8 @@ write_final_rev(svn_fs_x__id_t *new_id_p apr_uint32_t item_type = noderev->kind == svn_node_dir ? SVN_FS_X__ITEM_TYPE_DIR_PROPS : SVN_FS_X__ITEM_TYPE_FILE_PROPS; - SVN_ERR(svn_fs_x__get_proplist(&proplist, fs, noderev, scratch_pool)); + SVN_ERR(svn_fs_x__get_proplist(&proplist, fs, noderev, scratch_pool, + scratch_pool)); noderev->prop_rep->id.change_set = change_set; @@ -3257,23 +3286,23 @@ svn_fs_x__add_index_data(svn_fs_t *fs, } /* Baton used for commit_body below. */ -struct commit_baton { +typedef struct commit_baton_t { svn_revnum_t *new_rev_p; svn_fs_t *fs; svn_fs_txn_t *txn; apr_array_header_t *reps_to_cache; apr_hash_t *reps_hash; apr_pool_t *reps_pool; -}; +} commit_baton_t; /* The work-horse for svn_fs_x__commit, called with the FS write lock. This implements the svn_fs_x__with_write_lock() 'body' callback - type. BATON is a 'struct commit_baton *'. */ + type. BATON is a 'commit_baton_t *'. */ static svn_error_t * commit_body(void *baton, apr_pool_t *scratch_pool) { - struct commit_baton *cb = baton; + commit_baton_t *cb = baton; svn_fs_x__data_t *ffd = cb->fs->fsap_data; const char *old_rev_filename, *rev_filename, *proto_filename; const char *revprop_filename, *final_revprop; @@ -3468,7 +3497,7 @@ svn_fs_x__commit(svn_revnum_t *new_rev_p svn_fs_txn_t *txn, apr_pool_t *scratch_pool) { - struct commit_baton cb; + commit_baton_t cb; svn_fs_x__data_t *ffd = fs->fsap_data; cb.new_rev_p = new_rev_p; @@ -3625,6 +3654,7 @@ svn_fs_x__delete_node_revision(svn_fs_t if (noderev->prop_rep && svn_fs_x__is_txn(noderev->prop_rep->id.change_set)) SVN_ERR(svn_io_remove_file2(svn_fs_x__path_txn_node_props(fs, id, + scratch_pool, scratch_pool), FALSE, scratch_pool)); @@ -3637,15 +3667,17 @@ svn_fs_x__delete_node_revision(svn_fs_t const svn_fs_x__id_t *key = id; SVN_ERR(svn_io_remove_file2( - svn_fs_x__path_txn_node_children(fs, id, scratch_pool), + svn_fs_x__path_txn_node_children(fs, id, scratch_pool, + scratch_pool), FALSE, scratch_pool)); /* remove the corresponding entry from the cache, if such exists */ SVN_ERR(svn_cache__set(ffd->dir_cache, key, NULL, scratch_pool)); } - return svn_io_remove_file2(svn_fs_x__path_txn_node_rev(fs, - id, scratch_pool), + return svn_io_remove_file2(svn_fs_x__path_txn_node_rev(fs, id, + scratch_pool, + scratch_pool), FALSE, scratch_pool); } @@ -3691,22 +3723,23 @@ svn_fs_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 *result_pool, + apr_pool_t *scratch_pool) { svn_string_t date; fs_txn_data_t *ftd; - apr_hash_t *props = apr_hash_make(pool); + apr_hash_t *props = apr_hash_make(scratch_pool); SVN_ERR(svn_fs__check_fs(fs, TRUE)); - SVN_ERR(svn_fs_x__create_txn(txn_p, fs, rev, pool)); + SVN_ERR(create_txn(txn_p, fs, rev, result_pool, scratch_pool)); /* Put a datestamp on the newly created txn, so we always know exactly how old it is. (This will help sysadmins identify long-abandoned txns that may need to be manually removed.) When a txn is promoted to a revision, this property will be automatically overwritten with a revision datestamp. */ - date.data = svn_time_to_cstring(apr_time_now(), pool); + date.data = svn_time_to_cstring(apr_time_now(), scratch_pool); date.len = strlen(date.data); svn_hash_sets(props, SVN_PROP_REVISION_DATE, &date); @@ -3715,17 +3748,18 @@ svn_fs_x__begin_txn(svn_fs_txn_t **txn_p behaviors. */ if (flags & SVN_FS_TXN_CHECK_OOD) svn_hash_sets(props, SVN_FS__PROP_TXN_CHECK_OOD, - svn_string_create("true", pool)); + svn_string_create("true", scratch_pool)); if (flags & SVN_FS_TXN_CHECK_LOCKS) svn_hash_sets(props, SVN_FS__PROP_TXN_CHECK_LOCKS, - svn_string_create("true", pool)); + svn_string_create("true", scratch_pool)); if (flags & SVN_FS_TXN_CLIENT_DATE) svn_hash_sets(props, SVN_FS__PROP_TXN_CLIENT_DATE, - svn_string_create("0", pool)); + svn_string_create("0", scratch_pool)); ftd = (*txn_p)->fsap_data; - return svn_error_trace(set_txn_proplist(fs, ftd->txn_id, props, FALSE, - pool)); + SVN_ERR(set_txn_proplist(fs, ftd->txn_id, props, FALSE, scratch_pool)); + + return SVN_NO_ERROR; }
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/transaction.h URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/transaction.h?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/transaction.h (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/transaction.h Tue Jan 27 23:27:44 2015 @@ -91,15 +91,6 @@ svn_fs_x__txn_changes_fetch(apr_hash_t * svn_fs_x__txn_id_t txn_id, apr_pool_t *scratch_pool); -/* Create a new transaction in filesystem FS, based on revision REV, - and store it in *TXN_P. Allocate all necessary variables from - POOL. */ -svn_error_t * -svn_fs_x__create_txn(svn_fs_txn_t **txn_p, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *pool); - /* Set the transaction property NAME to the value VALUE in transaction TXN. Perform temporary allocations from SCRATCH_POOL. */ svn_error_t * @@ -157,7 +148,11 @@ svn_fs_x__abort_txn(svn_fs_txn_t *txn, /* Add or set in filesystem FS, transaction TXN_ID, in directory PARENT_NODEREV a directory entry for NAME pointing to ID of type - KIND. Temporary allocations are done in SCRATCH_POOL. */ + KIND. The PARENT_NODEREV's DATA_REP will be redirected to the in-txn + representation, if it had not been mutable before. + + If PARENT_NODEREV does not have a DATA_REP, allocate one in RESULT_POOL. + Temporary allocations are done in SCRATCH_POOL. */ svn_error_t * svn_fs_x__set_entry(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, @@ -165,6 +160,7 @@ svn_fs_x__set_entry(svn_fs_t *fs, const char *name, const svn_fs_x__id_t *id, svn_node_kind_t kind, + apr_pool_t *result_pool, apr_pool_t *scratch_pool); /* Add a change to the changes record for filesystem FS in transaction @@ -189,14 +185,14 @@ svn_fs_x__add_change(svn_fs_t *fs, const char *copyfrom_path, apr_pool_t *scratch_pool); -/* Return a writable stream in *STREAM that allows storing the text - representation of node-revision NODEREV in filesystem FS. - Allocations are from POOL. */ +/* Return a writable stream in *STREAM, allocated in RESULT_POOL, that + allows storing the text representation of node-revision NODEREV in + filesystem FS. */ svn_error_t * svn_fs_x__set_contents(svn_stream_t **stream, svn_fs_t *fs, svn_fs_x__noderev_t *noderev, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Create a node revision in FS which is an immediate successor of NEW_NODEREV's predecessor. Use SCRATCH_POOL for any temporary allocation. @@ -304,13 +300,14 @@ svn_fs_x__txn_prop(svn_string_t **value_ apr_pool_t *pool); /* Begin a new transaction in filesystem FS, based on existing - revision REV. The new transaction is returned in *TXN_P. Allocate - the new transaction structure from POOL. */ + revision REV. The new transaction is returned in *TXN_P, allocated + in RESULT_POOL. Allocate temporaries from SCRATCH_POOL. */ svn_error_t * svn_fs_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 *result_pool, + apr_pool_t *scratch_pool); #endif Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/tree.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/tree.c?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/tree.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/tree.c Tue Jan 27 23:27:44 2015 @@ -106,8 +106,7 @@ get_dag(dag_node_t **dag_node_p, static svn_fs_root_t * make_revision_root(svn_fs_t *fs, svn_revnum_t rev, - dag_node_t *root_dir, - apr_pool_t *pool); + apr_pool_t *result_pool); static svn_error_t * make_txn_root(svn_fs_root_t **root_p, @@ -115,7 +114,7 @@ make_txn_root(svn_fs_root_t **root_p, svn_fs_x__txn_id_t txn_id, svn_revnum_t base_rev, apr_uint32_t flags, - apr_pool_t *pool); + apr_pool_t *result_pool); static svn_error_t * x_closest_copy(svn_fs_root_t **root_p, @@ -192,10 +191,10 @@ struct svn_fs_x__dag_cache_t }; svn_fs_x__dag_cache_t* -svn_fs_x__create_dag_cache(apr_pool_t *pool) +svn_fs_x__create_dag_cache(apr_pool_t *result_pool) { - svn_fs_x__dag_cache_t *result = apr_pcalloc(pool, sizeof(*result)); - result->pool = svn_pool_create(pool); + svn_fs_x__dag_cache_t *result = apr_pcalloc(result_pool, sizeof(*result)); + result->pool = svn_pool_create(result_pool); return result; } @@ -329,13 +328,13 @@ cache_lookup_last_path(svn_fs_x__dag_cac /* Find and return the DAG node cache for ROOT and the key that should be used for PATH. - Pool will only be used for allocating a new keys if necessary */ + RESULT_POOL will only be used for allocating a new keys if necessary. */ static void locate_cache(svn_cache__t **cache, const char **key, svn_fs_root_t *root, const char *path, - apr_pool_t *pool) + apr_pool_t *result_pool) { if (root->is_txn_root) { @@ -353,7 +352,8 @@ locate_cache(svn_cache__t **cache, if (cache) *cache = ffd->rev_node_cache; if (key && path) - *key = svn_fs_x__combine_number_and_string(root->rev, path, pool); + *key = svn_fs_x__combine_number_and_string(root->rev, path, + result_pool); } } @@ -444,11 +444,12 @@ dag_node_cache_set(svn_fs_root_t *root, /* Baton for find_descendants_in_cache. */ -struct fdic_baton { +typedef struct fdic_baton_t +{ const char *path; apr_array_header_t *list; apr_pool_t *pool; -}; +} fdic_baton_t; /* If the given item is a descendant of BATON->PATH, push * it onto BATON->LIST (copying into BATON->POOL). Implements @@ -460,7 +461,7 @@ find_descendants_in_cache(void *baton, void *val, apr_pool_t *pool) { - struct fdic_baton *b = baton; + fdic_baton_t *b = baton; const char *item_path = key; if (svn_fspath__skip_ancestor(b->path, item_path)) @@ -476,7 +477,7 @@ dag_node_cache_invalidate(svn_fs_root_t const char *path, apr_pool_t *scratch_pool) { - struct fdic_baton b; + fdic_baton_t b; svn_cache__t *cache; apr_pool_t *iterpool; int i; @@ -540,13 +541,10 @@ svn_fs_x__revision_root(svn_fs_root_t ** svn_revnum_t rev, apr_pool_t *pool) { - dag_node_t *root_dir; - SVN_ERR(svn_fs__check_fs(fs, TRUE)); + SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, pool)); - SVN_ERR(svn_fs_x__dag_revision_root(&root_dir, fs, rev, pool)); - - *root_p = make_revision_root(fs, rev, root_dir, pool); + *root_p = make_revision_root(fs, rev, pool); return SVN_NO_ERROR; } @@ -566,43 +564,42 @@ root_txn_id(svn_fs_root_t *root) } /* Set *NODE_P to a freshly opened dag node referring to the root - directory of ROOT, allocating from POOL. */ + directory of ROOT, allocating from RESULT_POOL. */ static svn_error_t * root_node(dag_node_t **node_p, svn_fs_root_t *root, - apr_pool_t *pool) + apr_pool_t *result_pool) { if (root->is_txn_root) { /* It's a transaction root. Open a fresh copy. */ return svn_fs_x__dag_txn_root(node_p, root->fs, root_txn_id(root), - pool); + result_pool); } else { /* It's a revision root, so we already have its root directory opened. */ - dag_node_t *root_dir = root->fsap_data; - *node_p = svn_fs_x__dag_dup(root_dir, pool); - return SVN_NO_ERROR; + return svn_fs_x__dag_revision_root(node_p, root->fs, root->rev, + result_pool); } } /* Set *NODE_P to a mutable root directory for ROOT, cloning if - necessary, allocating in POOL. ROOT must be a transaction root. + necessary, allocating in RESULT_POOL. ROOT must be a transaction root. Use ERROR_PATH in error messages. */ static svn_error_t * mutable_root_node(dag_node_t **node_p, svn_fs_root_t *root, const char *error_path, - apr_pool_t *pool) + apr_pool_t *result_pool) { if (root->is_txn_root) { /* It's a transaction root. Open a fresh copy. */ return svn_fs_x__dag_clone_root(node_p, root->fs, root_txn_id(root), - pool); + result_pool); } else /* If it's not a transaction root, we can't change its contents. */ @@ -771,17 +768,17 @@ get_copy_inheritance(copy_id_inherit_t * return SVN_NO_ERROR; } -/* Allocate a new parent_path_t node from POOL, referring to NODE, +/* Allocate a new parent_path_t node from RESULT_POOL, referring to NODE, ENTRY, PARENT, and COPY_ID. */ static parent_path_t * make_parent_path(dag_node_t *node, char *entry, parent_path_t *parent, - apr_pool_t *pool) + apr_pool_t *result_pool) { - parent_path_t *parent_path = apr_pcalloc(pool, sizeof(*parent_path)); + parent_path_t *parent_path = apr_pcalloc(result_pool, sizeof(*parent_path)); if (node) - parent_path->node = svn_fs_x__dag_copy_into_pool(node, pool); + parent_path->node = svn_fs_x__dag_copy_into_pool(node, result_pool); parent_path->entry = entry; parent_path->parent = parent; parent_path->copy_inherit = copy_id_inherit_unknown; @@ -1098,16 +1095,17 @@ open_path(parent_path_t **parent_path_p, } -/* Make the node referred to by PARENT_PATH mutable, if it isn't - already, allocating from POOL. ROOT must be the root from which +/* Make the node referred to by PARENT_PATH mutable, if it isn't already, + allocating from RESULT_POOL. ROOT must be the root from which PARENT_PATH descends. Clone any parent directories as needed. Adjust the dag nodes in PARENT_PATH to refer to the clones. Use - ERROR_PATH in error messages. */ + ERROR_PATH in error messages. Use SCRATCH_POOL for temporaries. */ static svn_error_t * make_path_mutable(svn_fs_root_t *root, parent_path_t *parent_path, const char *error_path, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { dag_node_t *clone; svn_fs_x__txn_id_t txn_id = root_txn_id(root); @@ -1132,7 +1130,7 @@ make_path_mutable(svn_fs_root_t *root, /* We're trying to clone somebody's child. Make sure our parent is mutable. */ SVN_ERR(make_path_mutable(root, parent_path->parent, - error_path, pool)); + error_path, result_pool, scratch_pool)); switch (inherit) { @@ -1143,7 +1141,7 @@ make_path_mutable(svn_fs_root_t *root, case copy_id_inherit_new: SVN_ERR(svn_fs_x__reserve_copy_id(©_id, root->fs, txn_id, - pool)); + scratch_pool)); break; case copy_id_inherit_self: @@ -1160,8 +1158,9 @@ make_path_mutable(svn_fs_root_t *root, SVN_ERR(svn_fs_x__dag_get_copyroot(©root_rev, ©root_path, parent_path->node)); SVN_ERR(svn_fs_x__revision_root(©root_root, root->fs, - copyroot_rev, pool)); - SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, pool)); + copyroot_rev, scratch_pool)); + SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, + result_pool)); SVN_ERR(svn_fs_x__dag_related_node(&related, copyroot_node, parent_path->node)); @@ -1169,23 +1168,25 @@ make_path_mutable(svn_fs_root_t *root, is_parent_copyroot = TRUE; /* Now make this node mutable. */ - clone_path = parent_path_path(parent_path->parent, pool); + clone_path = parent_path_path(parent_path->parent, scratch_pool); SVN_ERR(svn_fs_x__dag_clone_child(&clone, parent_path->parent->node, clone_path, parent_path->entry, copy_id_ptr, txn_id, is_parent_copyroot, - pool)); + result_pool, + scratch_pool)); /* Update the path cache. */ - SVN_ERR(dag_node_cache_set(root, parent_path_path(parent_path, pool), - clone, pool)); + SVN_ERR(dag_node_cache_set(root, + parent_path_path(parent_path, scratch_pool), + clone, scratch_pool)); } else { /* We're trying to clone the root directory. */ - SVN_ERR(mutable_root_node(&clone, root, error_path, pool)); + SVN_ERR(mutable_root_node(&clone, root, error_path, result_pool)); } /* Update the PARENT_PATH link to refer to the clone. */ @@ -1288,7 +1289,7 @@ x_node_id(const svn_fs_id_t **id_p, const char *path, apr_pool_t *pool) { - const svn_fs_x__id_t *noderev_id; + svn_fs_x__id_t noderev_id; if ((! root->is_txn_root) && (path[0] == '\0' || ((path[0] == '/') && (path[1] == '\0')))) @@ -1297,19 +1298,18 @@ x_node_id(const svn_fs_id_t **id_p, The root directory ("" or "/") node is stored in the svn_fs_root_t object, and never changes when it's a revision root, so we can just reach in and grab it directly. */ - dag_node_t *root_dir = root->fsap_data; - noderev_id = svn_fs_x__dag_get_id(root_dir); + svn_fs_x__init_rev_root(&noderev_id, root->rev); } else { dag_node_t *node; SVN_ERR(get_dag(&node, root, path, pool)); - noderev_id = svn_fs_x__dag_get_id(node); + noderev_id = *svn_fs_x__dag_get_id(node); } *id_p = svn_fs_x__id_create(svn_fs_x__id_create_context(root->fs, pool), - noderev_id, pool); + &noderev_id, pool); return SVN_NO_ERROR; } @@ -1462,13 +1462,15 @@ x_node_prop(svn_string_t **value_p, { dag_node_t *node; apr_hash_t *proplist; + apr_pool_t *scratch_pool = svn_pool_create(pool); SVN_ERR(get_dag(&node, root, path, pool)); - SVN_ERR(svn_fs_x__dag_get_proplist(&proplist, node, pool)); + SVN_ERR(svn_fs_x__dag_get_proplist(&proplist, node, pool, scratch_pool)); *value_p = NULL; if (proplist) *value_p = svn_hash_gets(proplist, propname); + svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; } @@ -1483,13 +1485,13 @@ x_node_proplist(apr_hash_t **table_p, const char *path, apr_pool_t *pool) { - apr_hash_t *table; dag_node_t *node; + apr_pool_t *scratch_pool = svn_pool_create(pool); SVN_ERR(get_dag(&node, root, path, pool)); - SVN_ERR(svn_fs_x__dag_get_proplist(&table, node, pool)); - *table_p = table ? table : apr_hash_make(pool); + SVN_ERR(svn_fs_x__dag_get_proplist(table_p, node, pool, scratch_pool)); + svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; } @@ -1499,11 +1501,17 @@ increment_mergeinfo_up_tree(parent_path_ apr_int64_t increment, apr_pool_t *scratch_pool) { + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + for (; pp; pp = pp->parent) - SVN_ERR(svn_fs_x__dag_increment_mergeinfo_count(pp->node, - increment, - scratch_pool)); + { + svn_pool_clear(iterpool); + SVN_ERR(svn_fs_x__dag_increment_mergeinfo_count(pp->node, + increment, + iterpool)); + } + svn_pool_destroy(iterpool); return SVN_NO_ERROR; } @@ -1538,8 +1546,9 @@ x_change_node_prop(svn_fs_root_t *root, SVN_ERR(svn_fs_x__allow_locked_operation(path, root->fs, FALSE, FALSE, subpool)); - SVN_ERR(make_path_mutable(root, parent_path, path, subpool)); - SVN_ERR(svn_fs_x__dag_get_proplist(&proplist, parent_path->node, subpool)); + SVN_ERR(make_path_mutable(root, parent_path, path, subpool, subpool)); + SVN_ERR(svn_fs_x__dag_get_proplist(&proplist, parent_path->node, subpool, + subpool)); /* If there's no proplist, but we're just deleting a property, exit now. */ if ((! proplist) && (! value)) @@ -1661,8 +1670,10 @@ compare_dir_structure(svn_boolean_t *cha int i; apr_pool_t *iterpool = svn_pool_create(scratch_pool); - SVN_ERR(svn_fs_x__dag_dir_entries(&lhs_entries, lhs, scratch_pool)); - SVN_ERR(svn_fs_x__dag_dir_entries(&rhs_entries, rhs, scratch_pool)); + SVN_ERR(svn_fs_x__dag_dir_entries(&lhs_entries, lhs, scratch_pool, + iterpool)); + SVN_ERR(svn_fs_x__dag_dir_entries(&rhs_entries, rhs, scratch_pool, + iterpool)); /* Since directories are sorted by name, we can simply compare their entries one-by-one without binary lookup etc. */ @@ -1909,12 +1920,12 @@ merge(svn_stringbuf_t *conflict_p, /* ### todo: it would be more efficient to simply check for a NULL entries hash where necessary below than to allocate an empty hash here, but another day, another day... */ - SVN_ERR(svn_fs_x__dag_dir_entries(&s_entries, source, pool)); - SVN_ERR(svn_fs_x__dag_dir_entries(&t_entries, target, pool)); - SVN_ERR(svn_fs_x__dag_dir_entries(&a_entries, ancestor, pool)); + iterpool = svn_pool_create(pool); + SVN_ERR(svn_fs_x__dag_dir_entries(&s_entries, source, pool, iterpool)); + SVN_ERR(svn_fs_x__dag_dir_entries(&t_entries, target, pool, iterpool)); + SVN_ERR(svn_fs_x__dag_dir_entries(&a_entries, ancestor, pool, iterpool)); /* for each entry E in a_entries... */ - iterpool = svn_pool_create(pool); for (i = 0; i < a_entries->nelts; ++i) { svn_fs_x__dirent_t *s_entry, *t_entry, *a_entry; @@ -2100,8 +2111,8 @@ merge_changes(dag_node_t *ancestor_node, if (ancestor_node == NULL) { - SVN_ERR(svn_fs_x__dag_txn_base_root(&ancestor_node, fs, - txn_id, scratch_pool)); + SVN_ERR(svn_fs_x__dag_txn_base_root(&ancestor_node, fs, txn_id, + scratch_pool, scratch_pool)); } SVN_ERR(svn_fs_x__dag_related_node(&related, ancestor_node, txn_root_node)); @@ -2357,10 +2368,12 @@ x_dir_entries(apr_hash_t **table_p, apr_array_header_t *table; int i; svn_fs_x__id_context_t *context = NULL; + apr_pool_t *scratch_pool = svn_pool_create(pool); /* Get the entries for this path in the caller's pool. */ - SVN_ERR(get_dag(&node, root, path, pool)); - SVN_ERR(svn_fs_x__dag_dir_entries(&table, node, pool)); + SVN_ERR(get_dag(&node, root, path, scratch_pool)); + SVN_ERR(svn_fs_x__dag_dir_entries(&table, node, scratch_pool, + scratch_pool)); if (table->nelts) context = svn_fs_x__id_create_context(root->fs, pool); @@ -2370,16 +2383,19 @@ x_dir_entries(apr_hash_t **table_p, { svn_fs_x__dirent_t *entry = APR_ARRAY_IDX(table, i, svn_fs_x__dirent_t *); + apr_size_t len = strlen(entry->name); svn_fs_dirent_t *api_dirent = apr_pcalloc(pool, sizeof(*api_dirent)); - api_dirent->name = entry->name; + api_dirent->name = apr_pstrmemdup(pool, entry->name, len); api_dirent->kind = entry->kind; api_dirent->id = svn_fs_x__id_create(context, &entry->id, pool); - svn_hash_sets(hash, api_dirent->name, api_dirent); + apr_hash_set(hash, api_dirent->name, len, api_dirent); } *table_p = hash; + svn_pool_destroy(scratch_pool); + return SVN_NO_ERROR; } @@ -2425,14 +2441,15 @@ x_make_dir(svn_fs_root_t *root, return SVN_FS__ALREADY_EXISTS(root, path); /* Create the subdirectory. */ - SVN_ERR(make_path_mutable(root, parent_path->parent, path, subpool)); + SVN_ERR(make_path_mutable(root, parent_path->parent, path, subpool, + subpool)); SVN_ERR(svn_fs_x__dag_make_dir(&sub_dir, parent_path->parent->node, parent_path_path(parent_path->parent, subpool), parent_path->entry, txn_id, - subpool)); + subpool, subpool)); /* Add this directory to the path cache. */ SVN_ERR(dag_node_cache_set(root, parent_path_path(parent_path, subpool), @@ -2481,7 +2498,8 @@ x_delete_node(svn_fs_root_t *root, subpool)); /* Make the parent directory mutable, and do the deletion. */ - SVN_ERR(make_path_mutable(root, parent_path->parent, path, subpool)); + SVN_ERR(make_path_mutable(root, parent_path->parent, path, subpool, + subpool)); SVN_ERR(svn_fs_x__dag_get_mergeinfo_count(&mergeinfo_count, parent_path->node)); SVN_ERR(svn_fs_x__dag_delete(parent_path->parent->node, @@ -2609,7 +2627,7 @@ copy_helper(svn_fs_root_t *from_root, /* Make sure the target node's parents are mutable. */ SVN_ERR(make_path_mutable(to_root, to_parent_path->parent, - to_path, scratch_pool)); + to_path, scratch_pool, scratch_pool)); /* Canonicalize the copyfrom path. */ from_canonpath = svn_fs__canonicalize_abspath(from_path, scratch_pool); @@ -2763,14 +2781,15 @@ x_make_file(svn_fs_root_t *root, subpool)); /* Create the file. */ - SVN_ERR(make_path_mutable(root, parent_path->parent, path, subpool)); + SVN_ERR(make_path_mutable(root, parent_path->parent, path, subpool, + subpool)); SVN_ERR(svn_fs_x__dag_make_file(&child, parent_path->parent->node, parent_path_path(parent_path->parent, subpool), parent_path->entry, txn_id, - subpool)); + subpool, subpool)); /* Add this file to the path cache. */ SVN_ERR(dag_node_cache_set(root, parent_path_path(parent_path, subpool), @@ -2943,7 +2962,8 @@ apply_textdelta(void *baton, FALSE, FALSE, scratch_pool)); /* Now, make sure this path is mutable. */ - SVN_ERR(make_path_mutable(tb->root, parent_path, tb->path, scratch_pool)); + SVN_ERR(make_path_mutable(tb->root, parent_path, tb->path, scratch_pool, + scratch_pool)); tb->node = svn_fs_x__dag_dup(parent_path->node, tb->pool); if (tb->base_checksum) @@ -3001,7 +3021,7 @@ x_apply_textdelta(svn_txdelta_window_han svn_checksum_t *result_checksum, apr_pool_t *pool) { - apr_pool_t *subpool = svn_pool_create(pool); + apr_pool_t *scratch_pool = svn_pool_create(pool); txdelta_baton_t *tb = apr_pcalloc(pool, sizeof(*tb)); tb->root = root; @@ -3010,12 +3030,12 @@ x_apply_textdelta(svn_txdelta_window_han tb->base_checksum = svn_checksum_dup(base_checksum, pool); tb->result_checksum = svn_checksum_dup(result_checksum, pool); - SVN_ERR(apply_textdelta(tb, subpool)); + SVN_ERR(apply_textdelta(tb, scratch_pool)); *contents_p = window_consumer; *contents_baton_p = tb; - svn_pool_destroy(subpool); + svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; } @@ -3024,7 +3044,7 @@ x_apply_textdelta(svn_txdelta_window_han /* --- Machinery for svn_fs_apply_text() --- */ /* Baton for svn_fs_apply_text(). */ -struct text_baton_t +typedef struct text_baton_t { /* The original file info */ svn_fs_root_t *root; @@ -3045,7 +3065,7 @@ struct text_baton_t /* Pool used by db txns */ apr_pool_t *pool; -}; +} text_baton_t; /* A wrapper around svn_fs_x__dag_finalize_edits, but for @@ -3064,7 +3084,7 @@ text_stream_writer(void *baton, const char *data, apr_size_t *len) { - struct text_baton_t *tb = baton; + text_baton_t *tb = baton; /* Psst, here's some data. Pass it on to the -real- file stream. */ return svn_stream_write(tb->file_stream, data, len); @@ -3074,7 +3094,7 @@ text_stream_writer(void *baton, static svn_error_t * text_stream_closer(void *baton) { - struct text_baton_t *tb = baton; + text_baton_t *tb = baton; /* Close the internal-use stream. ### This used to be inside of txn_body_fulltext_finalize_edits(), but that invoked a nested @@ -3093,7 +3113,7 @@ static svn_error_t * apply_text(void *baton, apr_pool_t *scratch_pool) { - struct text_baton_t *tb = baton; + text_baton_t *tb = baton; parent_path_t *parent_path; svn_fs_x__txn_id_t txn_id = root_txn_id(tb->root); @@ -3108,7 +3128,8 @@ apply_text(void *baton, FALSE, FALSE, scratch_pool)); /* Now, make sure this path is mutable. */ - SVN_ERR(make_path_mutable(tb->root, parent_path, tb->path, scratch_pool)); + SVN_ERR(make_path_mutable(tb->root, parent_path, tb->path, scratch_pool, + scratch_pool)); tb->node = svn_fs_x__dag_dup(parent_path->node, tb->pool); /* Make a writable stream for replacing the file's text. */ @@ -3138,19 +3159,19 @@ x_apply_text(svn_stream_t **contents_p, svn_checksum_t *result_checksum, apr_pool_t *pool) { - apr_pool_t *subpool = svn_pool_create(pool); - struct text_baton_t *tb = apr_pcalloc(pool, sizeof(*tb)); + apr_pool_t *scratch_pool = svn_pool_create(pool); + text_baton_t *tb = apr_pcalloc(pool, sizeof(*tb)); tb->root = root; tb->path = svn_fs__canonicalize_abspath(path, pool); tb->pool = pool; tb->result_checksum = svn_checksum_dup(result_checksum, pool); - SVN_ERR(apply_text(tb, subpool)); + SVN_ERR(apply_text(tb, scratch_pool)); *contents_p = tb->stream; - svn_pool_destroy(subpool); + svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; } @@ -3215,19 +3236,20 @@ x_get_file_delta_stream(svn_txdelta_stre apr_pool_t *pool) { dag_node_t *source_node, *target_node; - apr_pool_t *subpool = svn_pool_create(pool); + apr_pool_t *scratch_pool = svn_pool_create(pool); if (source_root && source_path) - SVN_ERR(get_dag(&source_node, source_root, source_path, pool)); + SVN_ERR(get_dag(&source_node, source_root, source_path, scratch_pool)); else source_node = NULL; - SVN_ERR(get_dag(&target_node, target_root, target_path, pool)); + SVN_ERR(get_dag(&target_node, target_root, target_path, scratch_pool)); /* Create a delta stream that turns the source into the target. */ SVN_ERR(svn_fs_x__dag_get_file_delta_stream(stream_p, source_node, - target_node, pool)); + target_node, pool, + scratch_pool)); - svn_pool_destroy(subpool); + svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; } @@ -3346,7 +3368,7 @@ assemble_history(svn_fs_t *fs, svn_boolean_t is_interesting, const char *path_hint, svn_revnum_t rev_hint, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Set *HISTORY_P to an opaque node history object which represents @@ -3430,14 +3452,14 @@ x_closest_copy(svn_fs_root_t **root_p, svn_fs_root_t *copy_dst_root; dag_node_t *copy_dst_node; svn_boolean_t related; - apr_pool_t *subpool = svn_pool_create(pool); + apr_pool_t *scratch_pool = svn_pool_create(pool); /* Initialize return values. */ *root_p = NULL; *path_p = NULL; - path = svn_fs__canonicalize_abspath(path, subpool); - SVN_ERR(open_path(&parent_path, root, path, 0, FALSE, subpool)); + path = svn_fs__canonicalize_abspath(path, scratch_pool); + SVN_ERR(open_path(&parent_path, root, path, 0, FALSE, scratch_pool)); /* Find the youngest copyroot in the path of this node-rev, which will indicate the target of the innermost copy affecting the @@ -3446,7 +3468,7 @@ x_closest_copy(svn_fs_root_t **root_p, fs, parent_path)); if (copy_dst_rev == 0) /* There are no copies affecting this node-rev. */ { - svn_pool_destroy(subpool); + svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; } @@ -3456,10 +3478,10 @@ x_closest_copy(svn_fs_root_t **root_p, SVN_ERR(svn_fs_x__revision_root(©_dst_root, fs, copy_dst_rev, pool)); SVN_ERR(open_path(©_dst_parent_path, copy_dst_root, path, open_path_node_only | open_path_allow_null, FALSE, - subpool)); + scratch_pool)); if (copy_dst_parent_path == NULL) { - svn_pool_destroy(subpool); + svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; } @@ -3468,7 +3490,7 @@ x_closest_copy(svn_fs_root_t **root_p, parent_path->node)); if (!related) { - svn_pool_destroy(subpool); + svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; } @@ -3493,7 +3515,7 @@ x_closest_copy(svn_fs_root_t **root_p, SVN_ERR(svn_fs_x__dag_get_predecessor_id(&pred, copy_dst_node)); if (!svn_fs_x__id_used(&pred)) { - svn_pool_destroy(subpool); + svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; } } @@ -3502,7 +3524,7 @@ x_closest_copy(svn_fs_root_t **root_p, *root_p = copy_dst_root; *path_p = apr_pstrdup(pool, copy_dst_path); - svn_pool_destroy(subpool); + svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; } @@ -3736,16 +3758,16 @@ fs_history_prev(svn_fs_history_t **prev_ /* Set *PATH and *REVISION to the path and revision for the HISTORY - object. Use POOL for all allocations. */ + object. Allocate *PATH in RESULT_POOL. */ static svn_error_t * fs_history_location(const char **path, svn_revnum_t *revision, svn_fs_history_t *history, - apr_pool_t *pool) + apr_pool_t *result_pool) { fs_history_data_t *fhd = history->fsap_data; - *path = apr_pstrdup(pool, fhd->path); + *path = apr_pstrdup(result_pool, fhd->path); *revision = fhd->revision; return SVN_NO_ERROR; } @@ -3756,9 +3778,9 @@ static history_vtable_t history_vtable = }; /* Return a new history object (marked as "interesting") for PATH and - REVISION, allocated in POOL, and with its members set to the values - of the parameters provided. Note that PATH and PATH_HINT get - normalized and duplicated in POOL. */ + REVISION, allocated in RESULT_POOL, and with its members set to the + values of the parameters provided. Note that PATH and PATH_HINT get + normalized and duplicated in RESULT_POOL. */ static svn_fs_history_t * assemble_history(svn_fs_t *fs, const char *path, @@ -3766,15 +3788,16 @@ assemble_history(svn_fs_t *fs, svn_boolean_t is_interesting, const char *path_hint, svn_revnum_t rev_hint, - apr_pool_t *pool) + apr_pool_t *result_pool) { - svn_fs_history_t *history = apr_pcalloc(pool, sizeof(*history)); - fs_history_data_t *fhd = apr_pcalloc(pool, sizeof(*fhd)); - fhd->path = svn_fs__canonicalize_abspath(path, pool); + svn_fs_history_t *history = apr_pcalloc(result_pool, sizeof(*history)); + fs_history_data_t *fhd = apr_pcalloc(result_pool, sizeof(*fhd)); + fhd->path = svn_fs__canonicalize_abspath(path, result_pool); fhd->revision = revision; fhd->is_interesting = is_interesting; - fhd->path_hint = path_hint ? svn_fs__canonicalize_abspath(path_hint, pool) - : NULL; + fhd->path_hint = path_hint + ? svn_fs__canonicalize_abspath(path_hint, result_pool) + : NULL; fhd->rev_hint = rev_hint; fhd->fs = fs; @@ -3810,7 +3833,8 @@ crawl_directory_dag_for_mergeinfo(svn_fs int i; apr_pool_t *iterpool = svn_pool_create(scratch_pool); - SVN_ERR(svn_fs_x__dag_dir_entries(&entries, dir_dag, scratch_pool)); + SVN_ERR(svn_fs_x__dag_dir_entries(&entries, dir_dag, scratch_pool, + iterpool)); for (i = 0; i < entries->nelts; ++i) { svn_fs_x__dirent_t *dirent = APR_ARRAY_IDX(entries, i, svn_fs_x__dirent_t *); @@ -3834,7 +3858,8 @@ crawl_directory_dag_for_mergeinfo(svn_fs svn_string_t *mergeinfo_string; svn_error_t *err; - SVN_ERR(svn_fs_x__dag_get_proplist(&proplist, kid_dag, iterpool)); + SVN_ERR(svn_fs_x__dag_get_proplist(&proplist, kid_dag, iterpool, + iterpool)); mergeinfo_string = svn_hash_gets(proplist, SVN_PROP_MERGEINFO); if (!mergeinfo_string) { @@ -3881,21 +3906,21 @@ crawl_directory_dag_for_mergeinfo(svn_fs /* Return the cache key as a combination of REV_ROOT->REV, the inheritance flags INHERIT and ADJUST_INHERITED_MERGEINFO, and the PATH. The result - will be allocated in POOL.. + will be allocated in RESULT_POOL. */ static const char * mergeinfo_cache_key(const char *path, svn_fs_root_t *rev_root, svn_mergeinfo_inheritance_t inherit, svn_boolean_t adjust_inherited_mergeinfo, - apr_pool_t *pool) + apr_pool_t *result_pool) { apr_int64_t number = rev_root->rev; number = number * 4 + (inherit == svn_mergeinfo_nearest_ancestor ? 2 : 0) + (adjust_inherited_mergeinfo ? 1 : 0); - return svn_fs_x__combine_number_and_string(number, path, pool); + return svn_fs_x__combine_number_and_string(number, path, result_pool); } /* Calculates the mergeinfo for PATH under REV_ROOT using inheritance @@ -3953,7 +3978,7 @@ get_mergeinfo_for_path_internal(svn_merg } SVN_ERR(svn_fs_x__dag_get_proplist(&proplist, nearest_ancestor->node, - scratch_pool)); + scratch_pool, scratch_pool)); mergeinfo_string = svn_hash_gets(proplist, SVN_PROP_MERGEINFO); if (!mergeinfo_string) return svn_error_createf @@ -4196,34 +4221,32 @@ static root_vtable_t root_vtable = { x_get_mergeinfo, }; -/* Construct a new root object in FS, allocated from POOL. */ +/* Construct a new root object in FS, allocated from RESULT_POOL. */ static svn_fs_root_t * make_root(svn_fs_t *fs, - apr_pool_t *pool) + apr_pool_t *result_pool) { - svn_fs_root_t *root = apr_pcalloc(pool, sizeof(*root)); + svn_fs_root_t *root = apr_pcalloc(result_pool, sizeof(*root)); root->fs = fs; - root->pool = pool; + root->pool = result_pool; root->vtable = &root_vtable; return root; } -/* Construct a root object referring to the root of REVISION in FS, - whose root directory is ROOT_DIR. Create the new root in POOL. */ +/* Construct a root object referring to the root of revision REV in FS. + Create the new root in RESULT_POOL. */ static svn_fs_root_t * make_revision_root(svn_fs_t *fs, svn_revnum_t rev, - dag_node_t *root_dir, - apr_pool_t *pool) + apr_pool_t *result_pool) { - svn_fs_root_t *root = make_root(fs, pool); + svn_fs_root_t *root = make_root(fs, result_pool); root->is_txn_root = FALSE; root->rev = rev; - root->fsap_data = root_dir; return root; } @@ -4231,16 +4254,16 @@ make_revision_root(svn_fs_t *fs, /* Construct a root object referring to the root of the transaction named TXN and based on revision BASE_REV in FS, with FLAGS to - describe transaction's behavior. Create the new root in POOL. */ + describe transaction's behavior. Create the new root in RESULT_POOL. */ static svn_error_t * make_txn_root(svn_fs_root_t **root_p, svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, svn_revnum_t base_rev, apr_uint32_t flags, - apr_pool_t *pool) + apr_pool_t *result_pool) { - svn_fs_root_t *root = make_root(fs, pool); + svn_fs_root_t *root = make_root(fs, result_pool); fs_txn_root_data_t *frd = apr_pcalloc(root->pool, sizeof(*frd)); frd->txn_id = txn_id; @@ -4259,8 +4282,7 @@ make_txn_root(svn_fs_root_t **root_p, svn_fs_x__dag_deserialize, APR_HASH_KEY_STRING, 32, 20, FALSE, - apr_pstrcat(pool, root->txn, ":TXN", - SVN_VA_NULL), + root->txn, root->pool)); root->fsap_data = frd; @@ -4274,10 +4296,10 @@ make_txn_root(svn_fs_root_t **root_p, /* Verify. */ static const char * stringify_node(dag_node_t *node, - apr_pool_t *pool) + apr_pool_t *result_pool) { /* ### TODO: print some PATH@REV to it, too. */ - return svn_fs_x__id_unparse(svn_fs_x__dag_get_id(node), pool)->data; + return svn_fs_x__id_unparse(svn_fs_x__dag_get_id(node), result_pool)->data; } /* Check metadata sanity on NODE, and on its children. Manually verify @@ -4363,12 +4385,14 @@ verify_node(dag_node_t *node, apr_int64_t children_mergeinfo = 0; APR_ARRAY_PUSH(parent_nodes, dag_node_t*) = node; - SVN_ERR(svn_fs_x__dag_dir_entries(&entries, node, scratch_pool)); + SVN_ERR(svn_fs_x__dag_dir_entries(&entries, node, scratch_pool, + iterpool)); /* Compute CHILDREN_MERGEINFO. */ for (i = 0; i < entries->nelts; ++i) { - svn_fs_x__dirent_t *dirent = APR_ARRAY_IDX(entries, i, svn_fs_x__dirent_t *); + svn_fs_x__dirent_t *dirent + = APR_ARRAY_IDX(entries, i, svn_fs_x__dirent_t *); dag_node_t *child; apr_int64_t child_mergeinfo; @@ -4415,7 +4439,6 @@ svn_error_t * svn_fs_x__verify_root(svn_fs_root_t *root, apr_pool_t *scratch_pool) { - svn_fs_t *fs = root->fs; dag_node_t *root_dir; apr_array_header_t *parent_nodes; @@ -4429,17 +4452,7 @@ svn_fs_x__verify_root(svn_fs_root_t *roo When this code is called in the library, we want to ensure we use the on-disk data --- rather than some data that was read in the possibly-distance past and cached since. */ - - if (root->is_txn_root) - { - fs_txn_root_data_t *frd = root->fsap_data; - SVN_ERR(svn_fs_x__dag_txn_root(&root_dir, fs, frd->txn_id, - scratch_pool)); - } - else - { - root_dir = root->fsap_data; - } + SVN_ERR(root_node(&root_dir, root, scratch_pool)); /* Recursively verify ROOT_DIR. */ parent_nodes = apr_array_make(scratch_pool, 16, sizeof(dag_node_t *)); Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/tree.h URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/tree.h?rev=1655189&r1=1655188&r2=1655189&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/tree.h (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/tree.h Tue Jan 27 23:27:44 2015 @@ -31,10 +31,9 @@ extern "C" { -/* In POOL, create an instance of a DAG node 1st level cache. - The POOL will be cleared at regular intervals. */ +/* In RESULT_POOL, create an instance of a DAG node 1st level cache. */ svn_fs_x__dag_cache_t* -svn_fs_x__create_dag_cache(apr_pool_t *pool); +svn_fs_x__create_dag_cache(apr_pool_t *result_pool); /* Set *ROOT_P to the root directory of revision REV in filesystem FS. Allocate the structure in POOL. */
