Return-Path: X-Original-To: apmail-subversion-commits-archive@minotaur.apache.org Delivered-To: apmail-subversion-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 57E2D10193 for ; Thu, 26 Sep 2013 13:48:29 +0000 (UTC) Received: (qmail 86733 invoked by uid 500); 26 Sep 2013 13:48:23 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 86615 invoked by uid 500); 26 Sep 2013 13:48:22 -0000 Mailing-List: contact commits-help@subversion.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@subversion.apache.org Delivered-To: mailing list commits@subversion.apache.org Received: (qmail 86535 invoked by uid 99); 26 Sep 2013 13:48:20 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 26 Sep 2013 13:48:20 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 26 Sep 2013 13:48:16 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 5B3EB2388B75; Thu, 26 Sep 2013 13:47:34 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1526487 [6/10] - in /subversion/branches/invoke-diff-cmd-feature: ./ build/ac-macros/ build/generator/ build/generator/templates/ contrib/client-side/emacs/ notes/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apach... Date: Thu, 26 Sep 2013 13:47:26 -0000 To: commits@subversion.apache.org From: gbg@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20130926134734.5B3EB2388B75@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs_fs.h URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs_fs.h?rev=1526487&r1=1526486&r2=1526487&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs_fs.h (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs_fs.h Thu Sep 26 13:47:21 2013 @@ -45,162 +45,19 @@ svn_error_t *svn_fs_fs__upgrade(svn_fs_t void *cancel_baton, apr_pool_t *pool); -/* Verify metadata in fsfs filesystem FS. Limit the checks to revisions - * START to END where possible. Indicate progress via the optional - * NOTIFY_FUNC callback using NOTIFY_BATON. The optional CANCEL_FUNC - * will periodically be called with CANCEL_BATON to allow for preemption. - * Use POOL for temporary allocations. */ -svn_error_t *svn_fs_fs__verify(svn_fs_t *fs, - svn_revnum_t start, - svn_revnum_t end, - svn_fs_progress_notify_func_t notify_func, - void *notify_baton, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *pool); - -/* Copy the fsfs filesystem SRC_FS at SRC_PATH into a new copy DST_FS at - * DST_PATH. If INCREMENTAL is TRUE, do not re-copy data which already - * exists in DST_FS. Use POOL for temporary allocations. */ -svn_error_t * svn_fs_fs__hotcopy(svn_fs_t *src_fs, - svn_fs_t *dst_fs, - const char *src_path, - const char *dst_path, - svn_boolean_t incremental, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *pool); - -/* Recover the fsfs associated with filesystem FS. - Use optional CANCEL_FUNC/CANCEL_BATON for cancellation support. - Use POOL for temporary allocations. */ -svn_error_t *svn_fs_fs__recover(svn_fs_t *fs, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *pool); - -/* Set *NODEREV_P to the node-revision for the node ID in FS. Do any - allocations in POOL. */ -svn_error_t *svn_fs_fs__get_node_revision(node_revision_t **noderev_p, - svn_fs_t *fs, - const svn_fs_id_t *id, - apr_pool_t *pool); - -/* Store NODEREV as the node-revision for the node whose id is ID in - FS, after setting its is_fresh_txn_root to FRESH_TXN_ROOT. Do any - necessary temporary allocation in POOL. */ -svn_error_t *svn_fs_fs__put_node_revision(svn_fs_t *fs, - const svn_fs_id_t *id, - node_revision_t *noderev, - svn_boolean_t fresh_txn_root, - apr_pool_t *pool); - -/* Write the node-revision NODEREV into the stream OUTFILE, compatible with - filesystem format FORMAT. Only write mergeinfo-related metadata if - INCLUDE_MERGEINFO is true. Temporary allocations are from POOL. */ -/* ### Currently used only by fs_fs.c */ -svn_error_t * -svn_fs_fs__write_noderev(svn_stream_t *outfile, - node_revision_t *noderev, - int format, - svn_boolean_t include_mergeinfo, - apr_pool_t *pool); - -/* Read a node-revision from STREAM. Set *NODEREV to the new structure, - allocated in POOL. */ -/* ### Currently used only by fs_fs.c */ -svn_error_t * -svn_fs_fs__read_noderev(node_revision_t **noderev, - svn_stream_t *stream, - apr_pool_t *pool); - - /* Set *YOUNGEST to the youngest revision in filesystem FS. Do any temporary allocation in POOL. */ svn_error_t *svn_fs_fs__youngest_rev(svn_revnum_t *youngest, svn_fs_t *fs, apr_pool_t *pool); -/* Return an error iff REV does not exist in FS. */ -svn_error_t * -svn_fs_fs__revision_exists(svn_revnum_t rev, - svn_fs_t *fs, - apr_pool_t *pool); - -/* Set *ROOT_ID to the node-id for the root of revision REV in - filesystem FS. Do any allocations in POOL. */ -svn_error_t *svn_fs_fs__rev_get_root(svn_fs_id_t **root_id, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *pool); - -/* Set *ENTRIES to an apr_hash_t of dirent structs that contain the - directory entries of node-revision NODEREV in filesystem FS. The - returned table (and its keys and values) is allocated in POOL, - which is also used for temporary allocations. */ -svn_error_t *svn_fs_fs__rep_contents_dir(apr_hash_t **entries, - svn_fs_t *fs, - node_revision_t *noderev, - apr_pool_t *pool); - -/* Set *DIRENT to the entry identified by NAME in the directory given - by NODEREV in filesystem FS. If no such entry exits, *DIRENT will - be NULL. The returned object is allocated in RESULT_POOL; SCRATCH_POOL - used for temporary allocations. */ +/* Return SVN_ERR_FS_NO_SUCH_REVISION if the given revision REV is newer + than the current youngest revision in FS or is simply not a valid + revision number, else return success. */ svn_error_t * -svn_fs_fs__rep_contents_dir_entry(svn_fs_dirent_t **dirent, +svn_fs_fs__ensure_revision_exists(svn_revnum_t rev, svn_fs_t *fs, - node_revision_t *noderev, - const char *name, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool); - -/* Set *CONTENTS to be a readable svn_stream_t that receives the text - representation of node-revision NODEREV as seen in filesystem FS. - Use POOL for temporary allocations. */ -svn_error_t *svn_fs_fs__get_contents(svn_stream_t **contents, - svn_fs_t *fs, - node_revision_t *noderev, - apr_pool_t *pool); - -/* Attempt to fetch the text representation of node-revision NODEREV as - seen in filesystem FS and pass it along with the BATON to the PROCESSOR. - Set *SUCCESS only of the data could be provided and the processing - had been called. - Use POOL for all allocations. - */ -svn_error_t * -svn_fs_fs__try_process_file_contents(svn_boolean_t *success, - svn_fs_t *fs, - node_revision_t *noderev, - svn_fs_process_contents_func_t processor, - void* baton, - apr_pool_t *pool); - -/* Set *STREAM_P to a delta stream turning the contents of the file SOURCE into - the contents of the file TARGET, allocated in POOL. - If SOURCE is null, the empty string will be used. */ -svn_error_t *svn_fs_fs__get_file_delta_stream(svn_txdelta_stream_t **stream_p, - svn_fs_t *fs, - node_revision_t *source, - node_revision_t *target, - apr_pool_t *pool); - -/* Set *PROPLIST to be an apr_hash_t containing the property list of - node-revision NODEREV as seen in filesystem FS. Use POOL for - temporary allocations. */ -svn_error_t *svn_fs_fs__get_proplist(apr_hash_t **proplist, - svn_fs_t *fs, - node_revision_t *noderev, - apr_pool_t *pool); - -/* Set *PROPLIST to be an apr_hash_t containing the property list of - revision REV as seen in filesystem FS. Use POOL for temporary - allocations. */ -svn_error_t *svn_fs_fs__revision_proplist(apr_hash_t **proplist, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *pool); + apr_pool_t *pool); /* Set *LENGTH to the be fulltext length of the node revision specified by NODEREV. Use POOL for temporary allocations. */ @@ -227,155 +84,9 @@ svn_error_t *svn_fs_fs__file_checksum(sv svn_checksum_kind_t kind, apr_pool_t *pool); -/* Find the paths which were changed in revision REV of filesystem FS - and store them in *CHANGED_PATHS_P. Cached copyfrom information - will be stored in *COPYFROM_CACHE. Get any temporary allocations - from POOL. */ -svn_error_t *svn_fs_fs__paths_changed(apr_hash_t **changed_paths_p, - svn_fs_t *fs, - svn_revnum_t rev, - apr_hash_t *copyfrom_cache, - apr_pool_t *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_fs__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 POOL. */ -svn_error_t *svn_fs_fs__change_txn_prop(svn_fs_txn_t *txn, - const char *name, - const svn_string_t *value, - apr_pool_t *pool); - -/* Change transaction properties in transaction TXN based on PROPS. - Perform temporary allocations from POOL. */ -svn_error_t *svn_fs_fs__change_txn_props(svn_fs_txn_t *txn, - const apr_array_header_t *props, - apr_pool_t *pool); - /* Return whether or not the given FS supports mergeinfo metadata. */ svn_boolean_t svn_fs_fs__fs_supports_mergeinfo(svn_fs_t *fs); -/* Store a transaction record in *TXN_P for the transaction identified - by TXN_ID in filesystem FS. Allocate everything from POOL. */ -svn_error_t *svn_fs_fs__get_txn(transaction_t **txn_p, - svn_fs_t *fs, - const char *txn_id, - apr_pool_t *pool); - -/* Abort the existing transaction TXN, performing any temporary - allocations in POOL. */ -svn_error_t *svn_fs_fs__abort_txn(svn_fs_txn_t *txn, apr_pool_t *pool); - -/* Create an entirely new mutable node in the filesystem FS, whose - node-revision is NODEREV. Set *ID_P to the new node revision's ID. - Use POOL for any temporary allocation. COPY_ID is the copy_id to - use in the node revision ID. TXN_ID is the Subversion transaction - under which this occurs. */ -svn_error_t *svn_fs_fs__create_node(const svn_fs_id_t **id_p, - svn_fs_t *fs, - node_revision_t *noderev, - const char *copy_id, - const char *txn_id, - apr_pool_t *pool); - -/* Remove all references to the transaction TXN_ID from filesystem FS. - Temporary allocations are from POOL. */ -svn_error_t *svn_fs_fs__purge_txn(svn_fs_t *fs, - const char *txn_id, - apr_pool_t *pool); - -/* Add or set in filesystem FS, transaction TXN_ID, in directory - PARENT_NODEREV a directory entry for NAME pointing to ID of type - KIND. Allocations are done in POOL. */ -svn_error_t *svn_fs_fs__set_entry(svn_fs_t *fs, - const char *txn_id, - node_revision_t *parent_noderev, - const char *name, - const svn_fs_id_t *id, - svn_node_kind_t kind, - apr_pool_t *pool); - -/* Add a change to the changes record for filesystem FS in transaction - TXN_ID. Mark path PATH, having node-id ID, as changed according to - the type in CHANGE_KIND. If the text representation was changed - set TEXT_MOD to TRUE, and likewise for PROP_MOD. If this change - was the result of a copy, set COPYFROM_REV and COPYFROM_PATH to the - revision and path of the copy source, otherwise they should be set - to SVN_INVALID_REVNUM and NULL. Perform any temporary allocations - from POOL. */ -svn_error_t *svn_fs_fs__add_change(svn_fs_t *fs, - const char *txn_id, - const char *path, - const svn_fs_id_t *id, - svn_fs_path_change_kind_t change_kind, - svn_boolean_t text_mod, - svn_boolean_t prop_mod, - svn_node_kind_t node_kind, - svn_revnum_t copyfrom_rev, - const char *copyfrom_path, - apr_pool_t *pool); - -/* Return a writable stream in *STREAM that allows storing the text - representation of node-revision NODEREV in filesystem FS. - Allocations are from POOL. */ -svn_error_t *svn_fs_fs__set_contents(svn_stream_t **stream, - svn_fs_t *fs, - node_revision_t *noderev, - apr_pool_t *pool); - -/* Create a node revision in FS which is an immediate successor of - OLD_ID, whose contents are NEW_NR. Set *NEW_ID_P to the new node - revision's ID. Use POOL for any temporary allocation. - - COPY_ID, if non-NULL, is a key into the `copies' table, and - indicates that this new node is being created as the result of a - copy operation, and specifically which operation that was. If - COPY_ID is NULL, then re-use the copy ID from the predecessor node. - - TXN_ID is the Subversion transaction under which this occurs. - - After this call, the deltification code assumes that the new node's - contents will change frequently, and will avoid representing other - nodes as deltas against this node's contents. */ -svn_error_t *svn_fs_fs__create_successor(const svn_fs_id_t **new_id_p, - svn_fs_t *fs, - const svn_fs_id_t *old_idp, - node_revision_t *new_noderev, - const char *copy_id, - const char *txn_id, - apr_pool_t *pool); - -/* Write a new property list PROPLIST for node-revision NODEREV in - filesystem FS. Perform any temporary allocations in POOL. */ -svn_error_t *svn_fs_fs__set_proplist(svn_fs_t *fs, - node_revision_t *noderev, - apr_hash_t *proplist, - apr_pool_t *pool); - -/* Commit the transaction TXN in filesystem FS and return its new - revision number in *REV. If the transaction is out of date, return - the error SVN_ERR_FS_TXN_OUT_OF_DATE. Update commit time to ensure that - svn:date revprops remain ordered if SET_TIMESTAMP is non-zero. Use POOL for - temporary allocations. */ -svn_error_t *svn_fs_fs__commit(svn_revnum_t *new_rev_p, - svn_fs_t *fs, - svn_fs_txn_t *txn, - svn_boolean_t set_timestamp, - apr_pool_t *pool); - -/* Return the next available copy_id in *COPY_ID for the transaction - TXN_ID in filesystem FS. Allocate space in POOL. */ -svn_error_t *svn_fs_fs__reserve_copy_id(const char **copy_id, - svn_fs_t *fs, - const char *txn_id, - apr_pool_t *pool); - /* Create a fs_fs fileysystem referenced by FS at path PATH. Get any temporary allocations from POOL. @@ -392,63 +103,20 @@ svn_error_t *svn_fs_fs__set_uuid(svn_fs_ const char *uuid, apr_pool_t *pool); -/* Set *NAMES_P to an array of names which are all the active - transactions in filesystem FS. Allocate the array from POOL. */ -svn_error_t *svn_fs_fs__list_transactions(apr_array_header_t **names_p, - svn_fs_t *fs, - apr_pool_t *pool); - -/* Open the transaction named NAME in filesystem FS. Set *TXN_P to - * the transaction. If there is no such transaction, return -` * SVN_ERR_FS_NO_SUCH_TRANSACTION. Allocate the new transaction in - * POOL. */ -svn_error_t *svn_fs_fs__open_txn(svn_fs_txn_t **txn_p, - svn_fs_t *fs, - const char *name, - apr_pool_t *pool); - -/* Return the property list from transaction TXN and store it in - *PROPLIST. Allocate the property list from POOL. */ -svn_error_t *svn_fs_fs__txn_proplist(apr_hash_t **proplist, - svn_fs_txn_t *txn, - apr_pool_t *pool); - -/* Delete the mutable node-revision referenced by ID, along with any - mutable props or directory contents associated with it. Perform - temporary allocations in POOL. */ -svn_error_t *svn_fs_fs__delete_node_revision(svn_fs_t *fs, - const svn_fs_id_t *id, - apr_pool_t *pool); - - -/* Find the paths which were changed in transaction TXN_ID of - filesystem FS and store them in *CHANGED_PATHS_P. - Get any temporary allocations from POOL. */ -svn_error_t *svn_fs_fs__txn_changes_fetch(apr_hash_t **changes, - svn_fs_t *fs, - const char *txn_id, - apr_pool_t *pool); - - -/* Set *PATH to the path of REV in FS, whether in a pack file or not. - Allocate *PATH in POOL. - - Note: If the caller does not have the write lock on FS, then the path is - not guaranteed to be correct or to remain correct after the function - returns, because the revision might become packed before or after this - call. If a file exists at that path, then it is correct; if not, then - the caller should call update_min_unpacked_rev() and re-try once. */ -svn_error_t * -svn_fs_fs__path_rev_absolute(const char **path, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *pool); - /* Return the path to the 'current' file in FS. Perform allocation in POOL. */ const char * svn_fs_fs__path_current(svn_fs_t *fs, apr_pool_t *pool); +/* Write the format number and maximum number of files per directory + for FS, possibly expecting to overwrite a previously existing file. + + Use POOL for temporary allocation. */ +svn_error_t * +svn_fs_fs__write_format(svn_fs_t *fs, + svn_boolean_t overwrite, + apr_pool_t *pool); + /* Obtain a write lock on the filesystem FS in a subpool of POOL, call BODY with BATON and that subpool, destroy the subpool (releasing the write lock) and return what BODY returned. */ @@ -459,6 +127,15 @@ svn_fs_fs__with_write_lock(svn_fs_t *fs, void *baton, apr_pool_t *pool); +/* Run BODY (with BATON and POOL) while the txn-current file + of FS is locked. */ +svn_error_t * +svn_fs_fs__with_txn_current_lock(svn_fs_t *fs, + svn_error_t *(*body)(void *baton, + apr_pool_t *pool), + void *baton, + apr_pool_t *pool); + /* Find the value of the property named PROPNAME in transaction TXN. Return the contents in *VALUE_P. The contents will be allocated from POOL. */ @@ -478,38 +155,6 @@ svn_error_t *svn_fs_fs__change_rev_prop( const svn_string_t *value, apr_pool_t *pool); -/* Retrieve information about the Subversion transaction SVN_TXN from - the `transactions' table of FS, allocating from POOL. Set - *ROOT_ID_P to the ID of the transaction's root directory. Set - *BASE_ROOT_ID_P to the ID of the root directory of the - transaction's base revision. - - If there is no such transaction, SVN_ERR_FS_NO_SUCH_TRANSACTION is - the error returned. - - Returns SVN_ERR_FS_TRANSACTION_NOT_MUTABLE if TXN_NAME refers to a - transaction that has already been committed. - - Allocate *ROOT_ID_P and *BASE_ROOT_ID_P in POOL. */ -svn_error_t *svn_fs_fs__get_txn_ids(const svn_fs_id_t **root_id_p, - const svn_fs_id_t **base_root_id_p, - svn_fs_t *fs, - const char *txn_name, - 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. */ -svn_error_t *svn_fs_fs__begin_txn(svn_fs_txn_t **txn_p, svn_fs_t *fs, - svn_revnum_t rev, apr_uint32_t flags, - apr_pool_t *pool); - -/* Find the value of the property named PROPNAME in transaction TXN. - Return the contents in *VALUE_P. The contents will be allocated - from POOL. */ -svn_error_t *svn_fs_fs__txn_prop(svn_string_t **value_p, svn_fs_txn_t *txn, - const char *propname, apr_pool_t *pool); - /* If directory PATH does not exist, create it and give it the same permissions as FS_PATH.*/ svn_error_t *svn_fs_fs__ensure_dir_exists(const char *path, @@ -525,7 +170,7 @@ svn_error_t *svn_fs_fs__ensure_dir_exist */ svn_error_t * svn_fs_fs__set_node_origin(svn_fs_t *fs, - const char *node_id, + const svn_fs_fs__id_part_t *node_id, const svn_fs_id_t *node_rev_id, apr_pool_t *pool); @@ -539,7 +184,7 @@ svn_fs_fs__set_node_origin(svn_fs_t *fs, svn_error_t * svn_fs_fs__get_node_origin(const svn_fs_id_t **origin_id, svn_fs_t *fs, - const char *node_id, + const svn_fs_fs__id_part_t *node_id, apr_pool_t *pool); @@ -567,18 +212,4 @@ svn_fs_fs__initialize_txn_caches(svn_fs_ void svn_fs_fs__reset_txn_caches(svn_fs_t *fs); -/* Possibly pack the repository at PATH. This just take full shards, and - combines all the revision files into a single one, with a manifest header. - Use optional CANCEL_FUNC/CANCEL_BATON for cancellation support. - - Existing filesystem references need not change. */ -svn_error_t * -svn_fs_fs__pack(svn_fs_t *fs, - svn_fs_pack_notify_t notify_func, - void *notify_baton, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *pool); - - #endif Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.c URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.c?rev=1526487&r1=1526486&r2=1526487&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.c (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.c Thu Sep 26 13:47:21 2013 @@ -24,90 +24,253 @@ #include #include "id.h" + #include "../libsvn_fs/fs-loader.h" #include "private/svn_temp_serializer.h" #include "private/svn_string_private.h" -typedef struct id_private_t { - const char *node_id; - const char *copy_id; - const char *txn_id; - svn_revnum_t rev; - apr_off_t offset; -} id_private_t; +typedef struct fs_fs__id_t +{ + /* API visible part */ + svn_fs_id_t generic_id; + + /* private members */ + struct + { + svn_fs_fs__id_part_t node_id; + svn_fs_fs__id_part_t copy_id; + svn_fs_fs__id_part_t txn_id; + svn_fs_fs__id_part_t rev_offset; + } private_id; +} fs_fs__id_t; -/* Accessing ID Pieces. */ -const char * -svn_fs_fs__id_node_id(const svn_fs_id_t *id) +/* Parse the NUL-terminated ID part at DATA and write the result into *PART. + * Return TRUE if no errors were detected. */ +static svn_boolean_t +part_parse(svn_fs_fs__id_part_t *part, + const char *data) { - id_private_t *pvt = id->fsap_data; + /* special case: ID inside some transaction */ + if (data[0] == '_') + { + part->revision = SVN_INVALID_REVNUM; + part->number = svn__base36toui64(&data, data + 1); + return *data == '\0'; + } - return pvt->node_id; + /* special case: 0 / default ID */ + if (data[0] == '0' && data[1] == '\0') + { + part->revision = 0; + part->number = 0; + return TRUE; + } + + /* read old style / new style ID */ + part->number = svn__base36toui64(&data, data); + if (data[0] != '-') + { + part->revision = 0; + return *data == '\0'; + } + + part->revision = SVN_STR_TO_REV(++data); + + return TRUE; } +/* Parse the transaction id in DATA and store the result in *TXN_ID. + * Return FALSE if there was some problem. + */ +static svn_boolean_t +txn_id_parse(svn_fs_fs__id_part_t *txn_id, + const char *data) +{ + txn_id->revision = SVN_STR_TO_REV(data); + data = strchr(data, '-'); + if (data == NULL) + return FALSE; + + txn_id->number = svn__base36toui64(&data, ++data); + return *data == '\0'; +} -const char * -svn_fs_fs__id_copy_id(const svn_fs_id_t *id) +/* Write the textual representation of *PART into P and return a pointer + * to the first position behind that string. + */ +static char * +unparse_id_part(char *p, + const svn_fs_fs__id_part_t *part) { - id_private_t *pvt = id->fsap_data; + if (SVN_IS_VALID_REVNUM(part->revision)) + { + /* ordinary old style / new style ID */ + p += svn__ui64tobase36(p, part->number); + if (part->revision > 0) + { + *(p++) = '-'; + p += svn__i64toa(p, part->revision); + } + } + else + { + /* in txn: mark with "_" prefix */ + *(p++) = '_'; + p += svn__ui64tobase36(p, part->number); + } - return pvt->copy_id; + *(p++) = '.'; + + return p; } + + +/* Operations on ID parts */ + +svn_boolean_t +svn_fs_fs__id_part_is_root(const svn_fs_fs__id_part_t* part) +{ + return part->revision == 0 && part->number == 0; +} + +svn_boolean_t +svn_fs_fs__id_part_eq(const svn_fs_fs__id_part_t *lhs, + const svn_fs_fs__id_part_t *rhs) +{ + return lhs->revision == rhs->revision && lhs->number == rhs->number; +} + +svn_boolean_t +svn_fs_fs__id_txn_used(const svn_fs_fs__id_part_t *txn_id) +{ + return SVN_IS_VALID_REVNUM(txn_id->revision) || (txn_id->number != 0); +} + +void +svn_fs_fs__id_txn_reset(svn_fs_fs__id_part_t *txn_id) +{ + txn_id->revision = SVN_INVALID_REVNUM; + txn_id->number = 0; +} + +svn_error_t * +svn_fs_fs__id_txn_parse(svn_fs_fs__id_part_t *txn_id, + const char *data) +{ + if (! txn_id_parse(txn_id, data)) + return svn_error_createf(SVN_ERR_FS_MALFORMED_TXN_ID, NULL, + "malformed txn id '%s'", data); + + return SVN_NO_ERROR; +} const char * -svn_fs_fs__id_txn_id(const svn_fs_id_t *id) +svn_fs_fs__id_txn_unparse(const svn_fs_fs__id_part_t *txn_id, + apr_pool_t *pool) { - id_private_t *pvt = id->fsap_data; + char string[2 * SVN_INT64_BUFFER_SIZE + 1]; + char *p = string; + + p += svn__i64toa(p, txn_id->revision); + *(p++) = '-'; + p += svn__ui64tobase36(p, txn_id->number); - return pvt->txn_id; + return apr_pstrmemdup(pool, string, p - string); } + + +/* Accessing ID Pieces. */ -svn_revnum_t -svn_fs_fs__id_rev(const svn_fs_id_t *id) +const svn_fs_fs__id_part_t * +svn_fs_fs__id_node_id(const svn_fs_id_t *fs_id) +{ + fs_fs__id_t *id = (fs_fs__id_t *)fs_id; + + return &id->private_id.node_id; +} + + +const svn_fs_fs__id_part_t * +svn_fs_fs__id_copy_id(const svn_fs_id_t *fs_id) +{ + fs_fs__id_t *id = (fs_fs__id_t *)fs_id; + + return &id->private_id.copy_id; +} + + +const svn_fs_fs__id_part_t * +svn_fs_fs__id_txn_id(const svn_fs_id_t *fs_id) +{ + fs_fs__id_t *id = (fs_fs__id_t *)fs_id; + + return &id->private_id.txn_id; +} + + +const svn_fs_fs__id_part_t * +svn_fs_fs__id_rev_offset(const svn_fs_id_t *fs_id) { - id_private_t *pvt = id->fsap_data; + fs_fs__id_t *id = (fs_fs__id_t *)fs_id; - return pvt->rev; + return &id->private_id.rev_offset; } +svn_revnum_t +svn_fs_fs__id_rev(const svn_fs_id_t *fs_id) +{ + fs_fs__id_t *id = (fs_fs__id_t *)fs_id; + + return id->private_id.rev_offset.revision; +} -apr_off_t -svn_fs_fs__id_offset(const svn_fs_id_t *id) +apr_uint64_t +svn_fs_fs__id_offset(const svn_fs_id_t *fs_id) { - id_private_t *pvt = id->fsap_data; + fs_fs__id_t *id = (fs_fs__id_t *)fs_id; - return pvt->offset; + return id->private_id.rev_offset.number; } +svn_boolean_t +svn_fs_fs__id_is_txn(const svn_fs_id_t *fs_id) +{ + fs_fs__id_t *id = (fs_fs__id_t *)fs_id; + + return svn_fs_fs__id_txn_used(&id->private_id.txn_id); +} svn_string_t * -svn_fs_fs__id_unparse(const svn_fs_id_t *id, +svn_fs_fs__id_unparse(const svn_fs_id_t *fs_id, apr_pool_t *pool) { - id_private_t *pvt = id->fsap_data; + char string[6 * SVN_INT64_BUFFER_SIZE + 10]; + fs_fs__id_t *id = (fs_fs__id_t *)fs_id; - if ((! pvt->txn_id)) - { - char rev_string[SVN_INT64_BUFFER_SIZE]; - char offset_string[SVN_INT64_BUFFER_SIZE]; + char *p = unparse_id_part(string, &id->private_id.node_id); + p = unparse_id_part(p, &id->private_id.copy_id); - svn__i64toa(rev_string, pvt->rev); - svn__i64toa(offset_string, pvt->offset); - return svn_string_createf(pool, "%s.%s.r%s/%s", - pvt->node_id, pvt->copy_id, - rev_string, offset_string); + if (svn_fs_fs__id_txn_used(&id->private_id.txn_id)) + { + *(p++) = 't'; + p += svn__i64toa(p, id->private_id.txn_id.revision); + *(p++) = '-'; + p += svn__ui64tobase36(p, id->private_id.txn_id.number); } else { - return svn_string_createf(pool, "%s.%s.t%s", - pvt->node_id, pvt->copy_id, - pvt->txn_id); + *(p++) = 'r'; + p += svn__i64toa(p, id->private_id.rev_offset.revision); + *(p++) = '/'; + p += svn__i64toa(p, id->private_id.rev_offset.number); } + + return svn_string_ncreate(string, p - string, pool); } @@ -117,23 +280,14 @@ svn_boolean_t svn_fs_fs__id_eq(const svn_fs_id_t *a, const svn_fs_id_t *b) { - id_private_t *pvta = a->fsap_data, *pvtb = b->fsap_data; + fs_fs__id_t *id_a = (fs_fs__id_t *)a; + fs_fs__id_t *id_b = (fs_fs__id_t *)b; if (a == b) return TRUE; - if (strcmp(pvta->node_id, pvtb->node_id) != 0) - return FALSE; - if (strcmp(pvta->copy_id, pvtb->copy_id) != 0) - return FALSE; - if ((pvta->txn_id == NULL) != (pvtb->txn_id == NULL)) - return FALSE; - if (pvta->txn_id && pvtb->txn_id && strcmp(pvta->txn_id, pvtb->txn_id) != 0) - return FALSE; - if (pvta->rev != pvtb->rev) - return FALSE; - if (pvta->offset != pvtb->offset) - return FALSE; - return TRUE; + + return memcmp(&id_a->private_id, &id_b->private_id, + sizeof(id_a->private_id)) == 0; } @@ -141,20 +295,24 @@ svn_boolean_t svn_fs_fs__id_check_related(const svn_fs_id_t *a, const svn_fs_id_t *b) { - id_private_t *pvta = a->fsap_data, *pvtb = b->fsap_data; + fs_fs__id_t *id_a = (fs_fs__id_t *)a; + fs_fs__id_t *id_b = (fs_fs__id_t *)b; if (a == b) return TRUE; + /* If both node_ids start with _ and they have differing transaction IDs, then it is impossible for them to be related. */ - if (pvta->node_id[0] == '_') + if (id_a->private_id.node_id.revision == SVN_INVALID_REVNUM) { - if (pvta->txn_id && pvtb->txn_id && - (strcmp(pvta->txn_id, pvtb->txn_id) != 0)) + if ( !svn_fs_fs__id_part_eq(&id_a->private_id.txn_id, + &id_b->private_id.txn_id) + || !svn_fs_fs__id_txn_used(&id_a->private_id.txn_id)) return FALSE; } - return (strcmp(pvta->node_id, pvtb->node_id) == 0); + return svn_fs_fs__id_part_eq(&id_a->private_id.node_id, + &id_b->private_id.node_id); } @@ -167,6 +325,18 @@ svn_fs_fs__id_compare(const svn_fs_id_t return (svn_fs_fs__id_check_related(a, b) ? 1 : -1); } +int +svn_fs_fs__id_part_compare(const svn_fs_fs__id_part_t *a, + const svn_fs_fs__id_part_t *b) +{ + if (a->revision < b->revision) + return -1; + if (a->revision > b->revision) + return 1; + + return a->number < b->number ? -1 : a->number == b->number ? 0 : 1; +} + /* Creating ID's. */ @@ -176,66 +346,73 @@ static id_vtable_t id_vtable = { svn_fs_fs__id_compare }; +svn_fs_id_t * +svn_fs_fs__id_txn_create_root(const svn_fs_fs__id_part_t *txn_id, + apr_pool_t *pool) +{ + fs_fs__id_t *id = apr_pcalloc(pool, sizeof(*id)); + + /* node ID and copy ID are "0" */ + + id->private_id.txn_id = *txn_id; + id->private_id.rev_offset.revision = SVN_INVALID_REVNUM; + + id->generic_id.vtable = &id_vtable; + id->generic_id.fsap_data = &id; + + return (svn_fs_id_t *)id; +} svn_fs_id_t * -svn_fs_fs__id_txn_create(const char *node_id, - const char *copy_id, - const char *txn_id, +svn_fs_fs__id_txn_create(const svn_fs_fs__id_part_t *node_id, + const svn_fs_fs__id_part_t *copy_id, + const svn_fs_fs__id_part_t *txn_id, apr_pool_t *pool) { - svn_fs_id_t *id = apr_palloc(pool, sizeof(*id)); - id_private_t *pvt = apr_palloc(pool, sizeof(*pvt)); + fs_fs__id_t *id = apr_pcalloc(pool, sizeof(*id)); + + id->private_id.node_id = *node_id; + id->private_id.copy_id = *copy_id; + id->private_id.txn_id = *txn_id; + id->private_id.rev_offset.revision = SVN_INVALID_REVNUM; - pvt->node_id = apr_pstrdup(pool, node_id); - pvt->copy_id = apr_pstrdup(pool, copy_id); - pvt->txn_id = apr_pstrdup(pool, txn_id); - pvt->rev = SVN_INVALID_REVNUM; - pvt->offset = -1; - - id->vtable = &id_vtable; - id->fsap_data = pvt; - return id; + id->generic_id.vtable = &id_vtable; + id->generic_id.fsap_data = &id; + + return (svn_fs_id_t *)id; } svn_fs_id_t * -svn_fs_fs__id_rev_create(const char *node_id, - const char *copy_id, - svn_revnum_t rev, - apr_off_t offset, +svn_fs_fs__id_rev_create(const svn_fs_fs__id_part_t *node_id, + const svn_fs_fs__id_part_t *copy_id, + const svn_fs_fs__id_part_t *rev_offset, apr_pool_t *pool) { - svn_fs_id_t *id = apr_palloc(pool, sizeof(*id)); - id_private_t *pvt = apr_palloc(pool, sizeof(*pvt)); + fs_fs__id_t *id = apr_pcalloc(pool, sizeof(*id)); + + id->private_id.node_id = *node_id; + id->private_id.copy_id = *copy_id; + id->private_id.txn_id.revision = SVN_INVALID_REVNUM; + id->private_id.rev_offset = *rev_offset; - pvt->node_id = apr_pstrdup(pool, node_id); - pvt->copy_id = apr_pstrdup(pool, copy_id); - pvt->txn_id = NULL; - pvt->rev = rev; - pvt->offset = offset; - - id->vtable = &id_vtable; - id->fsap_data = pvt; - return id; + id->generic_id.vtable = &id_vtable; + id->generic_id.fsap_data = &id; + + return (svn_fs_id_t *)id; } svn_fs_id_t * -svn_fs_fs__id_copy(const svn_fs_id_t *id, apr_pool_t *pool) +svn_fs_fs__id_copy(const svn_fs_id_t *source, apr_pool_t *pool) { - svn_fs_id_t *new_id = apr_palloc(pool, sizeof(*new_id)); - id_private_t *new_pvt = apr_palloc(pool, sizeof(*new_pvt)); - id_private_t *pvt = id->fsap_data; - - new_pvt->node_id = apr_pstrdup(pool, pvt->node_id); - new_pvt->copy_id = apr_pstrdup(pool, pvt->copy_id); - new_pvt->txn_id = pvt->txn_id ? apr_pstrdup(pool, pvt->txn_id) : NULL; - new_pvt->rev = pvt->rev; - new_pvt->offset = pvt->offset; - - new_id->vtable = &id_vtable; - new_id->fsap_data = new_pvt; - return new_id; + fs_fs__id_t *id = (fs_fs__id_t *)source; + fs_fs__id_t *new_id = apr_palloc(pool, sizeof(*new_id)); + + *new_id = *id; + new_id->generic_id.fsap_data = new_id; + + return (svn_fs_id_t *)new_id; } @@ -244,8 +421,7 @@ svn_fs_fs__id_parse(const char *data, apr_size_t len, apr_pool_t *pool) { - svn_fs_id_t *id; - id_private_t *pvt; + fs_fs__id_t *id; char *data_copy, *str; /* Dup the ID data into POOL. Our returned ID will have references @@ -253,10 +429,9 @@ svn_fs_fs__id_parse(const char *data, data_copy = apr_pstrmemdup(pool, data, len); /* Alloc a new svn_fs_id_t structure. */ - id = apr_palloc(pool, sizeof(*id)); - pvt = apr_palloc(pool, sizeof(*pvt)); - id->vtable = &id_vtable; - id->fsap_data = pvt; + id = apr_pcalloc(pool, sizeof(*id)); + id->generic_id.vtable = &id_vtable; + id->generic_id.fsap_data = &id; /* Now, we basically just need to "split" this data on `.' characters. We will use svn_cstring_tokenize, which will put @@ -268,13 +443,15 @@ svn_fs_fs__id_parse(const char *data, str = svn_cstring_tokenize(".", &data_copy); if (str == NULL) return NULL; - pvt->node_id = str; + if (! part_parse(&id->private_id.node_id, str)) + return NULL; /* Copy Id */ str = svn_cstring_tokenize(".", &data_copy); if (str == NULL) return NULL; - pvt->copy_id = str; + if (! part_parse(&id->private_id.copy_id, str)) + return NULL; /* Txn/Rev Id */ str = svn_cstring_tokenize(".", &data_copy); @@ -287,119 +464,78 @@ svn_fs_fs__id_parse(const char *data, svn_error_t *err; /* This is a revision type ID */ - pvt->txn_id = NULL; + id->private_id.txn_id.revision = SVN_INVALID_REVNUM; + id->private_id.txn_id.number = 0; data_copy = str + 1; str = svn_cstring_tokenize("/", &data_copy); if (str == NULL) return NULL; - pvt->rev = SVN_STR_TO_REV(str); + id->private_id.rev_offset.revision = SVN_STR_TO_REV(str); - str = svn_cstring_tokenize("/", &data_copy); - if (str == NULL) - return NULL; - err = svn_cstring_atoi64(&val, str); + err = svn_cstring_atoi64(&val, data_copy); if (err) { svn_error_clear(err); return NULL; } - pvt->offset = (apr_off_t)val; + id->private_id.rev_offset.number = (apr_uint64_t)val; } else if (str[0] == 't') { /* This is a transaction type ID */ - pvt->txn_id = str + 1; - pvt->rev = SVN_INVALID_REVNUM; - pvt->offset = -1; + id->private_id.rev_offset.revision = SVN_INVALID_REVNUM; + id->private_id.rev_offset.number = 0; + + if (! txn_id_parse(&id->private_id.txn_id, str + 1)) + return NULL; } else return NULL; - return id; + return (svn_fs_id_t *)id; } /* (de-)serialization support */ -/* Serialization of the PVT sub-structure within the CONTEXT. - */ -static void -serialize_id_private(svn_temp_serializer__context_t *context, - const id_private_t * const *pvt) -{ - const id_private_t *private = *pvt; - - /* serialize the pvt data struct itself */ - svn_temp_serializer__push(context, - (const void * const *)pvt, - sizeof(*private)); - - /* append the referenced strings */ - svn_temp_serializer__add_string(context, &private->node_id); - svn_temp_serializer__add_string(context, &private->copy_id); - svn_temp_serializer__add_string(context, &private->txn_id); - - /* return to caller's nesting level */ - svn_temp_serializer__pop(context); -} - /* Serialize an ID within the serialization CONTEXT. */ void svn_fs_fs__id_serialize(svn_temp_serializer__context_t *context, - const struct svn_fs_id_t * const *id) + const svn_fs_id_t * const *in) { + const fs_fs__id_t *id = (const fs_fs__id_t *)*in; + /* nothing to do for NULL ids */ - if (*id == NULL) + if (id == NULL) return; /* serialize the id data struct itself */ - svn_temp_serializer__push(context, - (const void * const *)id, - sizeof(**id)); - - /* serialize the id_private_t data sub-struct */ - serialize_id_private(context, - (const id_private_t * const *)&(*id)->fsap_data); - - /* return to caller's nesting level */ - svn_temp_serializer__pop(context); -} - -/* Deserialization of the PVT sub-structure in BUFFER. - */ -static void -deserialize_id_private(void *buffer, id_private_t **pvt) -{ - /* fixup the reference to the only sub-structure */ - id_private_t *private; - svn_temp_deserializer__resolve(buffer, (void**)pvt); - - /* fixup the sub-structure itself */ - private = *pvt; - svn_temp_deserializer__resolve(private, (void**)&private->node_id); - svn_temp_deserializer__resolve(private, (void**)&private->copy_id); - svn_temp_deserializer__resolve(private, (void**)&private->txn_id); + svn_temp_serializer__add_leaf(context, + (const void * const *)in, + sizeof(fs_fs__id_t)); } /* Deserialize an ID inside the BUFFER. */ void -svn_fs_fs__id_deserialize(void *buffer, svn_fs_id_t **id) +svn_fs_fs__id_deserialize(void *buffer, svn_fs_id_t **in_out) { + fs_fs__id_t *id; + /* The id maybe all what is in the whole buffer. * Don't try to fixup the pointer in that case*/ - if (*id != buffer) - svn_temp_deserializer__resolve(buffer, (void**)id); + if (*in_out != buffer) + svn_temp_deserializer__resolve(buffer, (void**)in_out); + + id = (fs_fs__id_t *)*in_out; /* no id, no sub-structure fixup necessary */ - if (*id == NULL) + if (id == NULL) return; /* the stored vtable is bogus at best -> set the right one */ - (*id)->vtable = &id_vtable; - - /* handle sub-structures */ - deserialize_id_private(*id, (id_private_t **)&(*id)->fsap_data); + id->generic_id.vtable = &id_vtable; + id->generic_id.fsap_data = id; } Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.h URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.h?rev=1526487&r1=1526486&r2=1526487&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.h (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.h Thu Sep 26 13:47:21 2013 @@ -29,25 +29,78 @@ extern "C" { #endif /* __cplusplus */ +/* Node-revision IDs in FSFS consist of 3 of sub-IDs ("parts") that consist + * of a creation REVISION number and some revision- / transaction-local + * counter value (NUMBER). Old-style ID parts use global counter values. + * + * The parts are: node_id, copy_id and txn_id for in-txn IDs as well as + * node_id, copy_id and rev_offset for in-revision IDs. This struct the + * data structure used for each of those parts. + */ +typedef struct svn_fs_fs__id_part_t +{ + /* SVN_INVALID_REVNUM for txns -> not a txn, COUNTER must be 0. + SVN_INVALID_REVNUM for others -> not assigned to a revision, yet. + 0 for others -> old-style ID or the root in rev 0. */ + svn_revnum_t revision; + + /* sub-id value relative to REVISION. Its interpretation depends on + the part itself. In rev_offset, it is the offset value, in others + it represents a unique counter value. */ + apr_uint64_t number; +} svn_fs_fs__id_part_t; + + +/*** Operations on ID parts. ***/ + +/* Return TRUE, if both elements of the PART is 0, i.e. this is the default + * value if e.g. no copies were made of this node. */ +svn_boolean_t svn_fs_fs__id_part_is_root(const svn_fs_fs__id_part_t *part); + +/* Return TRUE, if all element values of *LHS and *RHS match. */ +svn_boolean_t svn_fs_fs__id_part_eq(const svn_fs_fs__id_part_t *lhs, + const svn_fs_fs__id_part_t *rhs); + +/* Return TRUE, if TXN_ID is used, i.e. doesn't contain just the defaults. */ +svn_boolean_t svn_fs_fs__id_txn_used(const svn_fs_fs__id_part_t *txn_id); + +/* Reset TXN_ID to the defaults. */ +void svn_fs_fs__id_txn_reset(svn_fs_fs__id_part_t *txn_id); + +/* Parse the transaction id in DATA and store the result in *TXN_ID */ +svn_error_t *svn_fs_fs__id_txn_parse(svn_fs_fs__id_part_t *txn_id, + const char *data); + +/* Convert the transaction id in *TXN_ID into a textual representation + * allocated in POOL. */ +const char *svn_fs_fs__id_txn_unparse(const svn_fs_fs__id_part_t *txn_id, + apr_pool_t *pool); + /*** ID accessor functions. ***/ /* Get the "node id" portion of ID. */ -const char *svn_fs_fs__id_node_id(const svn_fs_id_t *id); +const svn_fs_fs__id_part_t *svn_fs_fs__id_node_id(const svn_fs_id_t *id); /* Get the "copy id" portion of ID. */ -const char *svn_fs_fs__id_copy_id(const svn_fs_id_t *id); +const svn_fs_fs__id_part_t *svn_fs_fs__id_copy_id(const svn_fs_id_t *id); /* Get the "txn id" portion of ID, or NULL if it is a permanent ID. */ -const char *svn_fs_fs__id_txn_id(const svn_fs_id_t *id); +const svn_fs_fs__id_part_t *svn_fs_fs__id_txn_id(const svn_fs_id_t *id); + +/* Get the "rev,offset" portion of ID. */ +const svn_fs_fs__id_part_t *svn_fs_fs__id_rev_offset(const svn_fs_id_t *id); /* Get the "rev" portion of ID, or SVN_INVALID_REVNUM if it is a transaction ID. */ svn_revnum_t svn_fs_fs__id_rev(const svn_fs_id_t *id); -/* Access the "offset" portion of the ID, or -1 if it is a transaction +/* Access the "offset" portion of the ID, or 0 if it is a transaction ID. */ -apr_off_t svn_fs_fs__id_offset(const svn_fs_id_t *id); +apr_uint64_t svn_fs_fs__id_offset(const svn_fs_id_t *id); + +/* Return TRUE, if this is a transaction ID. */ +svn_boolean_t svn_fs_fs__id_is_txn(const svn_fs_id_t *id); /* Convert ID into string form, allocated in POOL. */ svn_string_t *svn_fs_fs__id_unparse(const svn_fs_id_t *id, @@ -65,19 +118,26 @@ svn_boolean_t svn_fs_fs__id_check_relate int svn_fs_fs__id_compare(const svn_fs_id_t *a, const svn_fs_id_t *b); +/* Return 0 if A and B are equal, 1 if A is "greater than" B, -1 otherwise. */ +int svn_fs_fs__id_part_compare(const svn_fs_fs__id_part_t *a, + const svn_fs_fs__id_part_t *b); + +/* Create the txn root ID for transaction TXN_ID. Allocate it in POOL. */ +svn_fs_id_t *svn_fs_fs__id_txn_create_root(const svn_fs_fs__id_part_t *txn_id, + apr_pool_t *pool); + /* Create an ID within a transaction based on NODE_ID, COPY_ID, and TXN_ID, allocated in POOL. */ -svn_fs_id_t *svn_fs_fs__id_txn_create(const char *node_id, - const char *copy_id, - const char *txn_id, +svn_fs_id_t *svn_fs_fs__id_txn_create(const svn_fs_fs__id_part_t *node_id, + const svn_fs_fs__id_part_t *copy_id, + const svn_fs_fs__id_part_t *txn_id, apr_pool_t *pool); -/* Create a permanent ID based on NODE_ID, COPY_ID, REV, and OFFSET, +/* Create a permanent ID based on NODE_ID, COPY_ID and REV_OFFSET, allocated in POOL. */ -svn_fs_id_t *svn_fs_fs__id_rev_create(const char *node_id, - const char *copy_id, - svn_revnum_t rev, - apr_off_t offset, +svn_fs_id_t *svn_fs_fs__id_rev_create(const svn_fs_fs__id_part_t *node_id, + const svn_fs_fs__id_part_t *copy_id, + const svn_fs_fs__id_part_t *rev_offset, apr_pool_t *pool); /* Return a copy of ID, allocated from POOL. */ Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/lock.c URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/lock.c?rev=1526487&r1=1526486&r2=1526487&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/lock.c (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/lock.c Thu Sep 26 13:47:21 2013 @@ -37,6 +37,7 @@ #include "lock.h" #include "tree.h" #include "fs_fs.h" +#include "util.h" #include "../libsvn_fs/fs-loader.h" #include "private/svn_fs_util.h" @@ -455,8 +456,7 @@ delete_lock(svn_fs_t *fs, } else { - const char *rev_0_path; - SVN_ERR(svn_fs_fs__path_rev_absolute(&rev_0_path, fs, 0, pool)); + const char *rev_0_path = svn_fs_fs__path_rev_absolute(fs, 0, pool); SVN_ERR(write_digest_file(this_children, this_lock, fs->path, digest_path, rev_0_path, subpool)); } @@ -863,7 +863,8 @@ lock_body(void *baton, apr_pool_t *pool) lock->is_dav_comment = lb->is_dav_comment; lock->creation_date = apr_time_now(); lock->expiration_date = lb->expiration_date; - SVN_ERR(svn_fs_fs__path_rev_absolute(&rev_0_path, lb->fs, 0, pool)); + + rev_0_path = svn_fs_fs__path_rev_absolute(lb->fs, 0, pool); SVN_ERR(set_lock(lb->fs->path, lock, rev_0_path, pool)); *lb->lock_p = lock; Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/rep-cache.c URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/rep-cache.c?rev=1526487&r1=1526486&r2=1526487&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/rep-cache.c (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/rep-cache.c Thu Sep 26 13:47:21 2013 @@ -58,7 +58,7 @@ rep_has_been_born(representation_t *rep, { SVN_ERR_ASSERT(rep); - SVN_ERR(svn_fs_fs__revision_exists(rep->revision, fs, pool)); + SVN_ERR(svn_fs_fs__ensure_revision_exists(rep->revision, fs, pool)); return SVN_NO_ERROR; } @@ -163,7 +163,7 @@ svn_fs_fs__walk_rep_reference(svn_fs_t * max = svn_sqlite__column_revnum(stmt, 0); SVN_ERR(svn_sqlite__reset(stmt)); if (SVN_IS_VALID_REVNUM(max)) /* The rep-cache could be empty. */ - SVN_ERR(svn_fs_fs__revision_exists(max, fs, iterpool)); + SVN_ERR(svn_fs_fs__ensure_revision_exists(max, fs, iterpool)); } SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db, @@ -178,6 +178,7 @@ svn_fs_fs__walk_rep_reference(svn_fs_t * representation_t *rep; const char *sha1_digest; svn_error_t *err; + svn_checksum_t *checksum; /* Clear ITERPOOL occasionally. */ if (iterations++ % 16 == 0) @@ -193,12 +194,15 @@ svn_fs_fs__walk_rep_reference(svn_fs_t * /* Construct a representation_t. */ rep = apr_pcalloc(iterpool, sizeof(*rep)); + svn_fs_fs__id_txn_reset(&rep->txn_id); sha1_digest = svn_sqlite__column_text(stmt, 0, iterpool); - err = svn_checksum_parse_hex(&rep->sha1_checksum, - svn_checksum_sha1, sha1_digest, - iterpool); + err = svn_checksum_parse_hex(&checksum, svn_checksum_sha1, + sha1_digest, iterpool); if (err) return svn_error_compose_create(err, svn_sqlite__reset(stmt)); + + rep->has_sha1 = TRUE; + memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest)); rep->revision = svn_sqlite__column_revnum(stmt, 1); rep->offset = svn_sqlite__column_int64(stmt, 2); rep->size = svn_sqlite__column_int64(stmt, 3); @@ -250,7 +254,10 @@ svn_fs_fs__get_rep_reference(representat if (have_row) { *rep = apr_pcalloc(pool, sizeof(**rep)); - (*rep)->sha1_checksum = svn_checksum_dup(checksum, pool); + svn_fs_fs__id_txn_reset(&(*rep)->txn_id); + memcpy((*rep)->sha1_digest, checksum->digest, + sizeof((*rep)->sha1_digest)); + (*rep)->has_sha1 = TRUE; (*rep)->revision = svn_sqlite__column_revnum(stmt, 0); (*rep)->offset = svn_sqlite__column_int64(stmt, 1); (*rep)->size = svn_sqlite__column_int64(stmt, 2); @@ -276,20 +283,23 @@ svn_fs_fs__set_rep_reference(svn_fs_t *f fs_fs_data_t *ffd = fs->fsap_data; svn_sqlite__stmt_t *stmt; svn_error_t *err; + svn_checksum_t checksum; + checksum.kind = svn_checksum_sha1; + checksum.digest = rep->sha1_digest; SVN_ERR_ASSERT(ffd->rep_sharing_allowed); if (! ffd->rep_cache_db) SVN_ERR(svn_fs_fs__open_rep_cache(fs, pool)); /* We only allow SHA1 checksums in this table. */ - if (rep->sha1_checksum == NULL) + if (! rep->has_sha1) return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, _("Only SHA1 checksums can be used as keys in the " "rep_cache table.\n")); SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db, STMT_SET_REP)); SVN_ERR(svn_sqlite__bindf(stmt, "siiii", - svn_checksum_to_cstring(rep->sha1_checksum, pool), + svn_checksum_to_cstring(&checksum, pool), (apr_int64_t) rep->revision, (apr_int64_t) rep->offset, (apr_int64_t) rep->size, @@ -309,8 +319,7 @@ svn_fs_fs__set_rep_reference(svn_fs_t *f should exist. If so, and the value is the same one we were about to write, that's cool -- just do nothing. If, however, the value is *different*, that's a red flag! */ - SVN_ERR(svn_fs_fs__get_rep_reference(&old_rep, fs, rep->sha1_checksum, - pool)); + SVN_ERR(svn_fs_fs__get_rep_reference(&old_rep, fs, &checksum, pool)); if (old_rep) { @@ -327,10 +336,10 @@ svn_fs_fs__set_rep_reference(svn_fs_t *f APR_OFF_T_FMT, SVN_FILESIZE_T_FMT, SVN_FILESIZE_T_FMT, APR_OFF_T_FMT, SVN_FILESIZE_T_FMT, SVN_FILESIZE_T_FMT), - svn_checksum_to_cstring_display(rep->sha1_checksum, pool), - fs->path, old_rep->revision, old_rep->offset, old_rep->size, - old_rep->expanded_size, rep->revision, rep->offset, rep->size, - rep->expanded_size); + svn_checksum_to_cstring_display(&checksum, pool), + fs->path, old_rep->revision, old_rep->offset, + old_rep->size, old_rep->expanded_size, rep->revision, + rep->offset, rep->size, rep->expanded_size); else return SVN_NO_ERROR; } Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/temp_serializer.c URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/temp_serializer.c?rev=1526487&r1=1526486&r2=1526487&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/temp_serializer.c (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/temp_serializer.c Thu Sep 26 13:47:21 2013 @@ -34,6 +34,7 @@ #include "private/svn_subr_private.h" #include "temp_serializer.h" +#include "low_level.h" /* Utility to encode a signed NUMBER into a variable-length sequence of * 8-bit chars in KEY_BUFFER and return the last writen position. @@ -127,43 +128,6 @@ deserialize_svn_string(void *buffer, svn svn_temp_deserializer__resolve(*string, (void **)&(*string)->data); } -/* Utility function to serialize checkum CS within the given serialization - * CONTEXT. - */ -static void -serialize_checksum(svn_temp_serializer__context_t *context, - svn_checksum_t * const *cs) -{ - const svn_checksum_t *checksum = *cs; - if (checksum == NULL) - return; - - svn_temp_serializer__push(context, - (const void * const *)cs, - sizeof(*checksum)); - - /* The digest is arbitrary binary data. - * Thus, we cannot use svn_temp_serializer__add_string. */ - svn_temp_serializer__add_leaf(context, - (const void * const *)&checksum->digest, - svn_checksum_size(checksum)); - - /* return to the caller's nesting level */ - svn_temp_serializer__pop(context); -} - -/* Utility function to deserialize the checksum CS inside the BUFFER. - */ -static void -deserialize_checksum(void *buffer, svn_checksum_t **cs) -{ - svn_temp_deserializer__resolve(buffer, (void **)cs); - if (*cs == NULL) - return; - - svn_temp_deserializer__resolve(*cs, (void **)&(*cs)->digest); -} - /* Utility function to serialize the REPRESENTATION within the given * serialization CONTEXT. */ @@ -176,41 +140,9 @@ serialize_representation(svn_temp_serial return; /* serialize the representation struct itself */ - svn_temp_serializer__push(context, - (const void * const *)representation, - sizeof(*rep)); - - /* serialize sub-structures */ - serialize_checksum(context, &rep->md5_checksum); - serialize_checksum(context, &rep->sha1_checksum); - - svn_temp_serializer__add_string(context, &rep->txn_id); - svn_temp_serializer__add_string(context, &rep->uniquifier); - - /* return to the caller's nesting level */ - svn_temp_serializer__pop(context); -} - -/* Utility function to deserialize the REPRESENTATIONS inside the BUFFER. - */ -static void -deserialize_representation(void *buffer, - representation_t **representation) -{ - representation_t *rep; - - /* fixup the reference to the representation itself */ - svn_temp_deserializer__resolve(buffer, (void **)representation); - rep = *representation; - if (rep == NULL) - return; - - /* fixup of sub-structures */ - deserialize_checksum(rep, &rep->md5_checksum); - deserialize_checksum(rep, &rep->sha1_checksum); - - svn_temp_deserializer__resolve(rep, (void **)&rep->txn_id); - svn_temp_deserializer__resolve(rep, (void **)&rep->uniquifier); + svn_temp_serializer__add_leaf(context, + (const void * const *)representation, + sizeof(*rep)); } /* auxilliary structure representing the content of a directory hash */ @@ -412,8 +344,8 @@ svn_fs_fs__noderev_deserialize(void *buf /* fixup of sub-structures */ svn_fs_fs__id_deserialize(noderev, (svn_fs_id_t **)&noderev->id); svn_fs_fs__id_deserialize(noderev, (svn_fs_id_t **)&noderev->predecessor_id); - deserialize_representation(noderev, &noderev->prop_rep); - deserialize_representation(noderev, &noderev->data_rep); + svn_temp_deserializer__resolve(noderev, (void **)&noderev->prop_rep); + svn_temp_deserializer__resolve(noderev, (void **)&noderev->data_rep); svn_temp_deserializer__resolve(noderev, (void **)&noderev->copyfrom_path); svn_temp_deserializer__resolve(noderev, (void **)&noderev->copyroot_path); @@ -1057,6 +989,36 @@ svn_fs_fs__replace_dir_entry(void **data return SVN_NO_ERROR; } +svn_error_t * +svn_fs_fs__serialize_rep_header(void **data, + apr_size_t *data_len, + void *in, + apr_pool_t *pool) +{ + svn_fs_fs__rep_header_t *copy = apr_palloc(pool, sizeof(*copy)); + *copy = *(svn_fs_fs__rep_header_t *)in; + + *data_len = sizeof(svn_fs_fs__rep_header_t); + *data = copy; + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_fs__deserialize_rep_header(void **out, + void *data, + apr_size_t data_len, + apr_pool_t *pool) +{ + svn_fs_fs__rep_header_t *copy = apr_palloc(pool, sizeof(*copy)); + SVN_ERR_ASSERT(data_len == sizeof(*copy)); + + *copy = *(svn_fs_fs__rep_header_t *)data; + *out = data; + + return SVN_NO_ERROR; +} + /* Utility function to serialize change CHANGE_P in the given serialization * CONTEXT. */ @@ -1074,10 +1036,10 @@ serialize_change(svn_temp_serializer__co sizeof(*change)); /* serialize sub-structures */ - svn_fs_fs__id_serialize(context, &change->noderev_id); + svn_fs_fs__id_serialize(context, &change->info.node_rev_id); - svn_temp_serializer__add_string(context, &change->path); - svn_temp_serializer__add_string(context, &change->copyfrom_path); + svn_temp_serializer__add_string(context, &change->path.data); + svn_temp_serializer__add_string(context, &change->info.copyfrom_path); /* return to the caller's nesting level */ svn_temp_serializer__pop(context); @@ -1099,10 +1061,10 @@ deserialize_change(void *buffer, change_ return; /* fix-up of sub-structures */ - svn_fs_fs__id_deserialize(change, (svn_fs_id_t **)&change->noderev_id); + svn_fs_fs__id_deserialize(change, (svn_fs_id_t **)&change->info.node_rev_id); - svn_temp_deserializer__resolve(change, (void **)&change->path); - svn_temp_deserializer__resolve(change, (void **)&change->copyfrom_path); + svn_temp_deserializer__resolve(change, (void **)&change->path.data); + svn_temp_deserializer__resolve(change, (void **)&change->info.copyfrom_path); } /* Auxiliary structure representing the content of a change_t array. Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/temp_serializer.h URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/temp_serializer.h?rev=1526487&r1=1526486&r2=1526487&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/temp_serializer.h (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/temp_serializer.h Thu Sep 26 13:47:21 2013 @@ -226,6 +226,24 @@ svn_fs_fs__replace_dir_entry(void **data apr_pool_t *pool); /** + * Implements #svn_cache__serialize_func_t for a #svn_fs_fs__rep_header_t. + */ +svn_error_t * +svn_fs_fs__serialize_rep_header(void **data, + apr_size_t *data_len, + void *in, + apr_pool_t *pool); + +/** + * Implements #svn_cache__deserialize_func_t for a #svn_fs_fs__rep_header_t. + */ +svn_error_t * +svn_fs_fs__deserialize_rep_header(void **out, + void *data, + apr_size_t data_len, + apr_pool_t *pool); + +/** * Implements #svn_cache__serialize_func_t for an #apr_array_header_t of * #change_t *. */