You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/10/15 10:52:18 UTC
svn commit: r1532250 [15/37] - in /subversion/branches/cache-server: ./
build/ build/ac-macros/ build/generator/ build/generator/swig/
build/generator/templates/ contrib/client-side/emacs/ contrib/hook-scripts/
contrib/server-side/fsfsfixer/ contrib/se...
Modified: subversion/branches/cache-server/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_fs_fs/fs_fs.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/cache-server/subversion/libsvn_fs_fs/fs_fs.h Tue Oct 15 08:52:06 2013
@@ -34,166 +34,30 @@ svn_error_t *svn_fs_fs__open(svn_fs_t *f
const char *path,
apr_pool_t *pool);
-/* Upgrade the fsfs filesystem FS. Use POOL for temporary allocations. */
-svn_error_t *svn_fs_fs__upgrade(svn_fs_t *fs,
- 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
+/* Upgrade the fsfs filesystem FS. 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_error_t *svn_fs_fs__upgrade(svn_fs_t *fs,
+ svn_fs_upgrade_notify_t notify_func,
+ void *notify_baton,
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. */
@@ -220,153 +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. 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,
- 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.
@@ -383,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. */
@@ -450,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. */
@@ -469,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,
@@ -516,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);
@@ -530,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);
@@ -558,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/cache-server/subversion/libsvn_fs_fs/id.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_fs_fs/id.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/libsvn_fs_fs/id.c (original)
+++ subversion/branches/cache-server/subversion/libsvn_fs_fs/id.c Tue Oct 15 08:52:06 2013
@@ -24,90 +24,253 @@
#include <stdlib.h>
#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/cache-server/subversion/libsvn_fs_fs/id.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_fs_fs/id.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/libsvn_fs_fs/id.h (original)
+++ subversion/branches/cache-server/subversion/libsvn_fs_fs/id.h Tue Oct 15 08:52:06 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/cache-server/subversion/libsvn_fs_fs/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_fs_fs/lock.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/branches/cache-server/subversion/libsvn_fs_fs/lock.c Tue Oct 15 08:52:06 2013
@@ -20,7 +20,7 @@
* ====================================================================
*/
-
+#include "svn_private_config.h"
#include "svn_pools.h"
#include "svn_error.h"
#include "svn_dirent_uri.h"
@@ -37,11 +37,11 @@
#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"
#include "private/svn_fspath.h"
-#include "svn_private_config.h"
/* Names of hash keys used to store a lock for writing to disk. */
#define PATH_KEY "path"
@@ -456,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));
}
@@ -864,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/cache-server/subversion/libsvn_fs_fs/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_fs_fs/rep-cache.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/libsvn_fs_fs/rep-cache.c (original)
+++ subversion/branches/cache-server/subversion/libsvn_fs_fs/rep-cache.c Tue Oct 15 08:52:06 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/cache-server/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_fs_fs/temp_serializer.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/cache-server/subversion/libsvn_fs_fs/temp_serializer.c Tue Oct 15 08:52:06 2013
@@ -22,6 +22,7 @@
#include <apr_pools.h>
+#include "svn_private_config.h"
#include "svn_pools.h"
#include "svn_hash.h"
@@ -33,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.
@@ -106,13 +108,12 @@ serialize_svn_string(svn_temp_serializer
/* the "string" content may actually be arbitrary binary data.
* Thus, we cannot use svn_temp_serializer__add_string. */
- svn_temp_serializer__push(context,
- (const void * const *)&string->data,
- string->len + 1);
+ svn_temp_serializer__add_leaf(context,
+ (const void * const *)&string->data,
+ string->len + 1);
/* back to the caller's nesting level */
svn_temp_serializer__pop(context);
- svn_temp_serializer__pop(context);
}
/* Utility function to deserialize the STRING inside the BUFFER.
@@ -127,44 +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__push(context,
- (const void * const *)&checksum->digest,
- svn_checksum_size(checksum));
-
- /* return to the caller's nesting level */
- svn_temp_serializer__pop(context);
- 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.
*/
@@ -177,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 */
@@ -413,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);
@@ -434,10 +365,9 @@ serialize_txdelta_ops(svn_temp_serialize
return;
/* the ops form a contiguous chunk of memory with no further references */
- svn_temp_serializer__push(context,
- (const void * const *)ops,
- count * sizeof(svn_txdelta_op_t));
- svn_temp_serializer__pop(context);
+ svn_temp_serializer__add_leaf(context,
+ (const void * const *)ops,
+ count * sizeof(svn_txdelta_op_t));
}
/* Utility function to serialize W in the given serialization CONTEXT.
@@ -1059,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.
*/
@@ -1076,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);
@@ -1101,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.
@@ -1274,22 +1234,19 @@ svn_fs_fs__serialize_mergeinfo(void **da
svn_temp_serializer__pop(context);
/* key lengths array */
- svn_temp_serializer__push(context,
- (const void * const *)&merges.key_lengths,
- merges.count * sizeof(*merges.key_lengths));
- svn_temp_serializer__pop(context);
+ svn_temp_serializer__add_leaf(context,
+ (const void * const *)&merges.key_lengths,
+ merges.count * sizeof(*merges.key_lengths));
/* range counts array */
- svn_temp_serializer__push(context,
- (const void * const *)&merges.range_counts,
- merges.count * sizeof(*merges.range_counts));
- svn_temp_serializer__pop(context);
+ svn_temp_serializer__add_leaf(context,
+ (const void * const *)&merges.range_counts,
+ merges.count * sizeof(*merges.range_counts));
/* ranges */
- svn_temp_serializer__push(context,
- (const void * const *)&merges.ranges,
- range_count * sizeof(*merges.ranges));
- svn_temp_serializer__pop(context);
+ svn_temp_serializer__add_leaf(context,
+ (const void * const *)&merges.ranges,
+ range_count * sizeof(*merges.ranges));
/* return the serialized result */
serialized = svn_temp_serializer__get(context);
Modified: subversion/branches/cache-server/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/libsvn_fs_fs/temp_serializer.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/libsvn_fs_fs/temp_serializer.h (original)
+++ subversion/branches/cache-server/subversion/libsvn_fs_fs/temp_serializer.h Tue Oct 15 08:52:06 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 *.
*/