You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2015/01/03 15:00:44 UTC
svn commit: r1649205 [14/30] - in /subversion/branches/authzperf: ./ build/
build/ac-macros/ notes/ subversion/bindings/ctypes-python/
subversion/bindings/cxxhl/
subversion/bindings/javahl/tests/org/apache/subversion/javahl/
subversion/bindings/swig/ s...
Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/index.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/index.h?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/index.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/index.h Sat Jan 3 14:00:41 2015
@@ -24,6 +24,7 @@
#define SVN_LIBSVN_FS__INDEX_H
#include "fs.h"
+#include "rev_file.h"
/* Per-defined item index values. They are used to identify empty or
* mandatory items.
@@ -65,7 +66,7 @@ typedef struct svn_fs_x__p2l_entry_t
apr_off_t size;
/* type of the item (see SVN_FS_X__ITEM_TYPE_*) defines */
- unsigned type;
+ apr_uint32_t type;
/* modified FNV-1a checksum. 0 if unknown checksum */
apr_uint32_t fnv1_checksum;
@@ -76,7 +77,7 @@ typedef struct svn_fs_x__p2l_entry_t
apr_uint32_t item_count;
/* List of items in that block / container */
- svn_fs_x__id_part_t *items;
+ svn_fs_x__id_t *items;
} svn_fs_x__p2l_entry_t;
/* Return a (deep) copy of ENTRY, allocated in POOL.
@@ -86,20 +87,21 @@ svn_fs_x__p2l_entry_dup(const svn_fs_x__
apr_pool_t *pool);
/* Open / create a log-to-phys index file with the full file path name
- * FILE_NAME. Return the open file in *PROTO_INDEX and use POOL for
- * allocations.
+ * FILE_NAME. Return the open file in *PROTO_INDEX allocated in
+ * RESULT_POOL.
*/
svn_error_t *
svn_fs_x__l2p_proto_index_open(apr_file_t **proto_index,
const char *file_name,
- apr_pool_t *pool);
+ apr_pool_t *result_pool);
/* Call this function before adding entries for the next revision to the
- * log-to-phys index file in PROTO_INDEX. Use POOL for allocations.
+ * log-to-phys index file in PROTO_INDEX. Use SCRATCH_POOL for temporary
+ * allocations.
*/
svn_error_t *
svn_fs_x__l2p_proto_index_add_revision(apr_file_t *proto_index,
- apr_pool_t *pool);
+ apr_pool_t *scratch_pool);
/* Add a new mapping, ITEM_INDEX to the (OFFSET, SUB_ITEM) pair, to log-to-
* phys index file in PROTO_INDEX. Please note that mappings may be added
@@ -109,72 +111,84 @@ svn_fs_x__l2p_proto_index_add_revision(a
* that is already implied for all item indexes not explicitly given a
* mapping.
*
- * Use POOL for allocations.
+ * Use SCRATCH_POOL for temporary allocations.
*/
svn_error_t *
svn_fs_x__l2p_proto_index_add_entry(apr_file_t *proto_index,
apr_off_t offset,
apr_uint32_t sub_item,
apr_uint64_t item_index,
- apr_pool_t *pool);
+ apr_pool_t *scratch_pool);
-/* Use the proto index file stored at PROTO_FILE_NAME and construct the
- * final log-to-phys index file at FILE_NAME. The first revision will
+/* Use the proto index file stored at PROTO_FILE_NAME, construct the final
+ * log-to-phys index and append it to INDEX_FILE. The first revision will
* be REVISION, entries to the next revision will be assigned to REVISION+1
- * and so forth. Use POOL for allocations.
+ * and so forth.
+ *
+ * Return the MD5 checksum of the on-disk index data in *CHECKSUM, allocated
+ * in RESULT_POOL. Use SCRATCH_POOL for temporary allocations.
*/
svn_error_t *
-svn_fs_x__l2p_index_create(svn_fs_t *fs,
- const char *file_name,
+svn_fs_x__l2p_index_append(svn_checksum_t **checksum,
+ svn_fs_t *fs,
+ apr_file_t *index_file,
const char *proto_file_name,
svn_revnum_t revision,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* Open / create a phys-to-log index file with the full file path name
- * FILE_NAME. Return the open file in *PROTO_INDEX and use POOL for
- * allocations.
+ * FILE_NAME. Return the open file in *PROTO_INDEX allocated in
+ * RESULT_POOL.
*/
svn_error_t *
svn_fs_x__p2l_proto_index_open(apr_file_t **proto_index,
const char *file_name,
- apr_pool_t *pool);
+ apr_pool_t *result_pool);
/* Add a new mapping ENTRY to the phys-to-log index file in PROTO_INDEX.
* The entries must be added in ascending offset order and must not leave
* intermittent ranges uncovered. The revision value in ENTRY may be
- * SVN_INVALID_REVISION. Use POOL for allocations.
+ * SVN_INVALID_REVISION. Use SCRATCH_POOL for temporary allocations.
*/
svn_error_t *
svn_fs_x__p2l_proto_index_add_entry(apr_file_t *proto_index,
- svn_fs_x__p2l_entry_t *entry,
- apr_pool_t *pool);
+ const svn_fs_x__p2l_entry_t *entry,
+ apr_pool_t *scratch_pool);
/* Set *NEXT_OFFSET to the first offset behind the last entry in the
* phys-to-log proto index file PROTO_INDEX. This will be 0 for empty
- * index files. Use POOL for temporary allocations.
+ * index files. Use SCRATCH_POOL for temporary allocations.
*/
svn_error_t *
svn_fs_x__p2l_proto_index_next_offset(apr_off_t *next_offset,
apr_file_t *proto_index,
- apr_pool_t *pool);
+ apr_pool_t *scratch_pool);
-/* Use the proto index file stored at PROTO_FILE_NAME and construct the
- * final phys-to-log index file at FILE_NAME. Entries without a valid
+/* Use the proto index file stored at PROTO_FILE_NAME, construct the final
+ * phys-to-log index and append it to INDEX_FILE. Entries without a valid
* revision will be assigned to the REVISION given here.
- * Use POOL for allocations.
+ *
+ * Return the MD5 checksum of the on-disk index data in *CHECKSUM, allocated
+ * in RESULT_POOL. Use SCRATCH_POOL for temporary allocations.
*/
svn_error_t *
-svn_fs_x__p2l_index_create(svn_fs_t *fs,
- const char *file_name,
+svn_fs_x__p2l_index_append(svn_checksum_t **checksum,
+ svn_fs_t *fs,
+ apr_file_t *index_file,
const char *proto_file_name,
svn_revnum_t revision,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* Use the phys-to-log mapping files in FS to build a list of entries
* that (at least partly) overlap with the range given by BLOCK_START
* offset and BLOCK_SIZE in the rep / pack file containing REVISION.
- * Return the array in *ENTRIES with svn_fs_fs__p2l_entry_t as elements.
- * Use POOL for allocations.
+ * Return the array in *ENTRIES with svn_fs_fs__p2l_entry_t as elements,
+ * allocated in RESULT_POOL. REV_FILE determines whether to access single
+ * rev or pack file data. If that is not available anymore (neither in
+ * cache nor on disk), return an error. Use SCRATCH_POOL for temporary
+ * allocations.
*
* Note that (only) the first and the last mapping may cross a cluster
* boundary.
@@ -182,69 +196,122 @@ svn_fs_x__p2l_index_create(svn_fs_t *fs,
svn_error_t *
svn_fs_x__p2l_index_lookup(apr_array_header_t **entries,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
svn_revnum_t revision,
apr_off_t block_start,
apr_off_t block_size,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* Use the phys-to-log mapping files in FS to return the entry for the
* container or single item starting at global OFFSET in the rep file
- * containing REVISION in *ENTRY. Sets *ENTRY to NULL if no item starts
- * at exactly that offset. Use POOL for allocations.
+ * containing REVISION in*ENTRY, allocated in RESULT_POOL. Sets *ENTRY
+ * to NULL if no item starts at exactly that offset. REV_FILE determines
+ * whether to access single rev or pack file data. If that is not available
+ * anymore (neither in cache nor on disk), return an error.
+ * Use SCRATCH_POOL for temporary allocations.
*/
svn_error_t *
svn_fs_x__p2l_entry_lookup(svn_fs_x__p2l_entry_t **entry,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
svn_revnum_t revision,
apr_off_t offset,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
-/* Use the phys-to-log mapping files in FS to return the svn_fs_x__id_part_t
+/* Use the phys-to-log mapping files in FS to return the svn_fs_x__id_t
* for the SUB_ITEM of the container starting at global OFFSET in the rep /
- * pack file containing REVISION in *ITEM. Sets *ITEM to NULL if no element
- * starts at exactly that offset or if it contains no more than SUB_ITEM
- * sub-items. Use POOL for allocations.
+ * pack file containing REVISION in *ITEM, allocated in RESULT_POOL. Sets
+ * *ITEM to NULL if no element starts at exactly that offset or if it
+ * contains no more than SUB_ITEM sub-items.
+ *
+ * Use SCRATCH_POOL for temporary allocations.
*/
svn_error_t *
-svn_fs_x__p2l_item_lookup(svn_fs_x__id_part_t **item,
+svn_fs_x__p2l_item_lookup(svn_fs_x__id_t **item,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
svn_revnum_t revision,
apr_off_t offset,
apr_uint32_t sub_item,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
-/* Use the log-to-phys mapping files in FS to find the packed / non-packed /
- * proto-rev file offset and container sub-item of ITEM_ID. *SUB_ITEM will
- * be 0 for non-container items. Use POOL for allocations.
+/* For ITEM_ID in FS, return the position in the respective rev or pack file
+ * in *ABSOLUTE_POSITION and the *SUB_ITEM number within the object at that
+ * location. *SUB_ITEM will be 0 for non-container items.
+ *
+ * REV_FILE determines whether to access single rev or pack file data.
+ * If that is not available anymore (neither in cache nor on disk), re-open
+ * the rev / pack file and retry to open the index file. For transaction
+ * content, REV_FILE may be NULL.
+ *
+ * Use SCRATCH_POOL for temporary allocations.
*/
svn_error_t *
-svn_fs_x__item_offset(apr_off_t *offset,
+svn_fs_x__item_offset(apr_off_t *absolute_position,
apr_uint32_t *sub_item,
svn_fs_t *fs,
- const svn_fs_x__id_part_t *item_id,
- apr_pool_t *pool);
+ svn_fs_x__revision_file_t *rev_file,
+ const svn_fs_x__id_t *item_id,
+ apr_pool_t *scratch_pool);
/* Use the log-to-phys indexes in FS to determine the maximum item indexes
* assigned to revision START_REV to START_REV + COUNT - 1. That is a
* close upper limit to the actual number of items in the respective revs.
- * Return the results in *MAX_IDS, allocated in POOL.
+ * Return the results in *MAX_IDS, allocated in RESULT_POOL.
+ * Use SCRATCH_POOL for temporary allocations.
*/
svn_error_t *
svn_fs_x__l2p_get_max_ids(apr_array_header_t **max_ids,
svn_fs_t *fs,
svn_revnum_t start_rev,
apr_size_t count,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* In *OFFSET, return the first OFFSET in the pack / rev file containing
* REVISION in FS not covered by the log-to-phys index.
- * Use POOL for allocations.
+ * Use SCRATCH_POOL for temporary allocations.
*/
svn_error_t *
svn_fs_x__p2l_get_max_offset(apr_off_t *offset,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
svn_revnum_t revision,
- apr_pool_t *pool);
+ apr_pool_t *scratch_pool);
+
+/* Index (re-)creation utilities.
+ */
+
+/* For FS, create a new L2P auto-deleting proto index file in POOL and return
+ * its name in *PROTONAME. All entries to write are given in ENTRIES and
+ * entries are of type svn_fs_fs__p2l_entry_t* (sic!). The ENTRIES array
+ * will be reordered. Give the proto index file the lifetime of RESULT_POOL
+ * and use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__l2p_index_from_p2l_entries(const char **protoname,
+ svn_fs_t *fs,
+ apr_array_header_t *entries,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/* For FS, create a new P2L auto-deleting proto index file in POOL and return
+ * its name in *PROTONAME. All entries to write are given in ENTRIES and
+ * of type svn_fs_fs__p2l_entry_t*. The FVN1 checksums are not taken from
+ * ENTRIES but are begin calculated from the current contents of REV_FILE
+ * as we go. Give the proto index file the lifetime of RESULT_POOL and use
+ * SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__p2l_index_from_p2l_entries(const char **protoname,
+ svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
+ apr_array_header_t *entries,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* Serialization and caching interface
*/
Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/lock.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/lock.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/lock.c Sat Jan 3 14:00:41 2015
@@ -386,7 +386,8 @@ add_to_digest(const char *fs_path,
const char *index_digest_path;
apr_hash_t *children;
svn_lock_t *lock;
- int i, original_count;
+ int i;
+ unsigned int original_count;
SVN_ERR(digest_path_from_path(&index_digest_path, fs_path, index_path, pool));
Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.c Sat Jan 3 14:00:41 2015
@@ -27,6 +27,7 @@
#include "private/svn_sorts_private.h"
#include "private/svn_string_private.h"
#include "private/svn_subr_private.h"
+#include "private/svn_fspath.h"
#include "../libsvn_fs/fs-loader.h"
@@ -37,6 +38,8 @@
/* Headers used to describe node-revision in the revision file. */
#define HEADER_ID "id"
+#define HEADER_NODE "node"
+#define HEADER_COPY "copy"
#define HEADER_TYPE "type"
#define HEADER_COUNT "count"
#define HEADER_PROPS "props"
@@ -71,115 +74,126 @@
* various flags. */
#define MAX_CHANGE_LINE_LEN FSX_MAX_PATH_LEN + 256
-svn_error_t *
-svn_fs_x__parse_revision_trailer(apr_off_t *root_offset,
- apr_off_t *changes_offset,
- svn_stringbuf_t *trailer,
- svn_revnum_t rev)
-{
- int i, num_bytes;
- const char *str;
-
- /* This cast should be safe since the maximum amount read, 64, will
- never be bigger than the size of an int. */
- num_bytes = (int) trailer->len;
-
- /* The last byte should be a newline. */
- if (trailer->len == 0 || trailer->data[trailer->len - 1] != '\n')
+/* Convert the C string in *TEXT to a revision number and return it in *REV.
+ * Overflows, negative values other than -1 and terminating characters other
+ * than 0x20 or 0x0 will cause an error. Set *TEXT to the first char after
+ * the initial separator or to EOS.
+ */
+static svn_error_t *
+parse_revnum(svn_revnum_t *rev,
+ const char **text)
+{
+ const char *string = *text;
+ if ((string[0] == '-') && (string[1] == '1'))
{
- return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
- _("Revision file (r%ld) lacks trailing newline"),
- rev);
+ *rev = SVN_INVALID_REVNUM;
+ string += 2;
}
-
- /* Look for the next previous newline. */
- for (i = num_bytes - 2; i >= 0; i--)
+ else
{
- if (trailer->data[i] == '\n')
- break;
+ SVN_ERR(svn_revnum_parse(rev, string, &string));
}
- if (i < 0)
- {
- return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
- _("Final line in revision file (r%ld) longer "
- "than 64 characters"),
- rev);
- }
+ if (*string == ' ')
+ ++string;
+ else if (*string != '\0')
+ return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
+ _("Invalid character in revision number"));
- i++;
- str = &trailer->data[i];
+ *text = string;
+ return SVN_NO_ERROR;
+}
- /* find the next space */
- for ( ; i < (num_bytes - 2) ; i++)
- if (trailer->data[i] == ' ')
- break;
+svn_error_t *
+svn_fs_x__parse_footer(apr_off_t *l2p_offset,
+ svn_checksum_t **l2p_checksum,
+ apr_off_t *p2l_offset,
+ svn_checksum_t **p2l_checksum,
+ svn_stringbuf_t *footer,
+ svn_revnum_t rev,
+ apr_pool_t *result_pool)
+{
+ apr_int64_t val;
+ char *last_str = footer->data;
- if (i == (num_bytes - 2))
- return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
- _("Final line in revision file r%ld missing space"),
- rev);
+ /* Get the L2P offset. */
+ const char *str = svn_cstring_tokenize(" ", &last_str);
+ if (str == NULL)
+ return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
+ _("Invalid revision footer"));
- if (root_offset)
- {
- apr_int64_t val;
+ SVN_ERR(svn_cstring_atoi64(&val, str));
+ *l2p_offset = (apr_off_t)val;
- trailer->data[i] = '\0';
- SVN_ERR(svn_cstring_atoi64(&val, str));
- *root_offset = (apr_off_t)val;
- }
+ /* Get the L2P checksum. */
+ str = svn_cstring_tokenize(" ", &last_str);
+ if (str == NULL)
+ return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
+ _("Invalid revision footer"));
- i++;
- str = &trailer->data[i];
+ SVN_ERR(svn_checksum_parse_hex(l2p_checksum, svn_checksum_md5, str,
+ result_pool));
- /* find the next newline */
- for ( ; i < num_bytes; i++)
- if (trailer->data[i] == '\n')
- break;
+ /* Get the P2L offset. */
+ str = svn_cstring_tokenize(" ", &last_str);
+ if (str == NULL)
+ return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
+ _("Invalid revision footer"));
- if (changes_offset)
- {
- apr_int64_t val;
+ SVN_ERR(svn_cstring_atoi64(&val, str));
+ *p2l_offset = (apr_off_t)val;
- trailer->data[i] = '\0';
- SVN_ERR(svn_cstring_atoi64(&val, str));
- *changes_offset = (apr_off_t)val;
- }
+ /* Get the P2L checksum. */
+ str = svn_cstring_tokenize(" ", &last_str);
+ if (str == NULL)
+ return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
+ _("Invalid revision footer"));
+
+ SVN_ERR(svn_checksum_parse_hex(p2l_checksum, svn_checksum_md5, str,
+ result_pool));
return SVN_NO_ERROR;
}
svn_stringbuf_t *
-svn_fs_x__unparse_revision_trailer(apr_off_t root_offset,
- apr_off_t changes_offset,
- apr_pool_t *pool)
-{
- return svn_stringbuf_createf(pool,
- "%" APR_OFF_T_FMT " %" APR_OFF_T_FMT "\n",
- root_offset,
- changes_offset);
+svn_fs_x__unparse_footer(apr_off_t l2p_offset,
+ svn_checksum_t *l2p_checksum,
+ apr_off_t p2l_offset,
+ svn_checksum_t *p2l_checksum,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_stringbuf_createf(result_pool,
+ "%" APR_OFF_T_FMT " %s %" APR_OFF_T_FMT " %s",
+ l2p_offset,
+ svn_checksum_to_cstring(l2p_checksum,
+ scratch_pool),
+ p2l_offset,
+ svn_checksum_to_cstring(p2l_checksum,
+ scratch_pool));
}
/* Given a revision file FILE that has been pre-positioned at the
beginning of a Node-Rev header block, read in that header block and
store it in the apr_hash_t HEADERS. All allocations will be from
- POOL. */
+ RESULT_POOL. */
static svn_error_t *
read_header_block(apr_hash_t **headers,
svn_stream_t *stream,
- apr_pool_t *pool)
+ apr_pool_t *result_pool)
{
- *headers = svn_hash__make(pool);
+ *headers = svn_hash__make(result_pool);
while (1)
{
svn_stringbuf_t *header_str;
const char *name, *value;
- apr_ssize_t i = 0;
- apr_ssize_t name_len;
+ apr_size_t i = 0;
+ apr_size_t name_len;
svn_boolean_t eof;
- SVN_ERR(svn_stream_readline(stream, &header_str, "\n", &eof, pool));
+ SVN_ERR(svn_stream_readline(stream, &header_str, "\n", &eof,
+ result_pool));
if (eof || header_str->len == 0)
break; /* end of header block */
@@ -199,13 +213,10 @@ read_header_block(apr_hash_t **headers,
name = header_str->data;
name_len = i;
- /* Skip over the NULL byte and the space following it. */
- i += 2;
-
- if (i > header_str->len)
+ /* Check if we have enough data to parse. */
+ if (i + 2 > header_str->len)
{
/* Restore the original line for the error. */
- i -= 2;
header_str->data[i] = ':';
return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
_("Found malformed header '%s' in "
@@ -213,6 +224,9 @@ read_header_block(apr_hash_t **headers,
header_str->data);
}
+ /* Skip over the NULL byte and the space following it. */
+ i += 2;
+
value = header_str->data + i;
/* header_str is safely in our pool, so we can use bits of it as
@@ -224,17 +238,18 @@ read_header_block(apr_hash_t **headers,
}
svn_error_t *
-svn_fs_x__parse_representation(representation_t **rep_p,
+svn_fs_x__parse_representation(svn_fs_x__representation_t **rep_p,
svn_stringbuf_t *text,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- representation_t *rep;
+ svn_fs_x__representation_t *rep;
char *str;
apr_int64_t val;
char *string = text->data;
svn_checksum_t *checksum;
- rep = apr_pcalloc(pool, sizeof(*rep));
+ rep = apr_pcalloc(result_pool, sizeof(*rep));
*rep_p = rep;
str = svn_cstring_tokenize(" ", &string);
@@ -283,7 +298,8 @@ svn_fs_x__parse_representation(represent
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
_("Malformed text representation offset line in node-rev"));
- SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_md5, str, pool));
+ SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_md5, str,
+ scratch_pool));
if (checksum)
memcpy(rep->md5_digest, checksum->digest, sizeof(rep->md5_digest));
@@ -297,7 +313,8 @@ svn_fs_x__parse_representation(represent
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
_("Malformed text representation offset line in node-rev"));
- SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_sha1, str, pool));
+ SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_sha1, str,
+ scratch_pool));
rep->has_sha1 = checksum != NULL;
if (checksum)
memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest));
@@ -308,23 +325,28 @@ svn_fs_x__parse_representation(represent
/* Wrap read_rep_offsets_body(), extracting its TXN_ID from our NODEREV_ID,
and adding an error message. */
static svn_error_t *
-read_rep_offsets(representation_t **rep_p,
+read_rep_offsets(svn_fs_x__representation_t **rep_p,
char *string,
- const svn_fs_id_t *noderev_id,
- apr_pool_t *pool)
+ const svn_fs_x__id_t *noderev_id,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_error_t *err
= svn_fs_x__parse_representation(rep_p,
- svn_stringbuf_create_wrap(string, pool),
- pool);
+ svn_stringbuf_create_wrap(string,
+ scratch_pool),
+ result_pool,
+ scratch_pool);
if (err)
{
- const svn_string_t *id_unparsed = svn_fs_x__id_unparse(noderev_id, pool);
+ const svn_string_t *id_unparsed;
const char *where;
- where = apr_psprintf(pool,
+
+ id_unparsed = svn_fs_x__id_unparse(noderev_id, scratch_pool);
+ where = apr_psprintf(scratch_pool,
_("While reading representation offsets "
"for node-revision '%s':"),
- noderev_id ? id_unparsed->data : "(null)");
+ id_unparsed->data);
return svn_error_quick_wrap(err, where);
}
@@ -384,31 +406,45 @@ auto_unescape_path(const char *path,
return path;
}
+/* Find entry HEADER_NAME in HEADERS and parse its value into *ID. */
+static svn_error_t *
+read_id_part(svn_fs_x__id_t *id,
+ apr_hash_t *headers,
+ const char *header_name)
+{
+ const char *value = svn_hash_gets(headers, header_name);
+ if (value == NULL)
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ _("Missing %s field in node-rev"),
+ header_name);
+
+ SVN_ERR(svn_fs_x__id_parse(id, value));
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
-svn_fs_x__read_noderev(node_revision_t **noderev_p,
+svn_fs_x__read_noderev(svn_fs_x__noderev_t **noderev_p,
svn_stream_t *stream,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
apr_hash_t *headers;
- node_revision_t *noderev;
+ svn_fs_x__noderev_t *noderev;
char *value;
const char *noderev_id;
- SVN_ERR(read_header_block(&headers, stream, pool));
+ SVN_ERR(read_header_block(&headers, stream, scratch_pool));
+ SVN_ERR(svn_stream_close(stream));
- noderev = apr_pcalloc(pool, sizeof(*noderev));
+ noderev = apr_pcalloc(result_pool, sizeof(*noderev));
- /* Read the node-rev id. */
- value = svn_hash_gets(headers, HEADER_ID);
- if (value == NULL)
- /* ### More information: filename/offset coordinates */
- return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
- _("Missing id field in node-rev"));
+ /* for error messages later */
+ noderev_id = svn_hash_gets(headers, HEADER_ID);
- SVN_ERR(svn_stream_close(stream));
-
- noderev->id = svn_fs_x__id_parse(value, strlen(value), pool);
- noderev_id = value; /* for error messages later */
+ /* Read the node-rev id. */
+ SVN_ERR(read_id_part(&noderev->noderev_id, headers, HEADER_ID));
+ SVN_ERR(read_id_part(&noderev->node_id, headers, HEADER_NODE));
+ SVN_ERR(read_id_part(&noderev->copy_id, headers, HEADER_COPY));
/* Read the type. */
value = svn_hash_gets(headers, HEADER_TYPE);
@@ -437,7 +473,8 @@ svn_fs_x__read_noderev(node_revision_t *
if (value)
{
SVN_ERR(read_rep_offsets(&noderev->prop_rep, value,
- noderev->id, pool));
+ &noderev->noderev_id, result_pool,
+ scratch_pool));
}
/* Get the data location. */
@@ -445,7 +482,8 @@ svn_fs_x__read_noderev(node_revision_t *
if (value)
{
SVN_ERR(read_rep_offsets(&noderev->data_rep, value,
- noderev->id, pool));
+ &noderev->noderev_id, result_pool,
+ scratch_pool));
}
/* Get the created path. */
@@ -458,38 +496,42 @@ svn_fs_x__read_noderev(node_revision_t *
}
else
{
- noderev->created_path = auto_unescape_path(value, pool);
+ if (!svn_fspath__is_canonical(value))
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ _("Non-canonical cpath field in node-rev '%s'"),
+ noderev_id);
+
+ noderev->created_path = auto_unescape_path(apr_pstrdup(result_pool,
+ value),
+ result_pool);
}
/* Get the predecessor ID. */
value = svn_hash_gets(headers, HEADER_PRED);
if (value)
- noderev->predecessor_id = svn_fs_x__id_parse(value, strlen(value), pool);
+ SVN_ERR(svn_fs_x__id_parse(&noderev->predecessor_id, value));
+ else
+ svn_fs_x__id_reset(&noderev->predecessor_id);
/* Get the copyroot. */
value = svn_hash_gets(headers, HEADER_COPYROOT);
if (value == NULL)
{
noderev->copyroot_path = noderev->created_path;
- noderev->copyroot_rev = svn_fs_x__id_rev(noderev->id);
+ noderev->copyroot_rev
+ = svn_fs_x__get_revnum(noderev->noderev_id.change_set);
}
else
{
- char *str;
-
- str = svn_cstring_tokenize(" ", &value);
- if (str == NULL)
- return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
- _("Malformed copyroot line in node-rev '%s'"),
- noderev_id);
+ SVN_ERR(parse_revnum(&noderev->copyroot_rev, (const char **)&value));
- noderev->copyroot_rev = SVN_STR_TO_REV(str);
-
- if (*value == '\0')
+ if (!svn_fspath__is_canonical(value))
return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
_("Malformed copyroot line in node-rev '%s'"),
noderev_id);
- noderev->copyroot_path = auto_unescape_path(value, pool);
+ noderev->copyroot_path = auto_unescape_path(apr_pstrdup(result_pool,
+ value),
+ result_pool);
}
/* Get the copyfrom. */
@@ -501,19 +543,15 @@ svn_fs_x__read_noderev(node_revision_t *
}
else
{
- char *str = svn_cstring_tokenize(" ", &value);
- if (str == NULL)
- return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
- _("Malformed copyfrom line in node-rev '%s'"),
- noderev_id);
-
- noderev->copyfrom_rev = SVN_STR_TO_REV(str);
+ SVN_ERR(parse_revnum(&noderev->copyfrom_rev, (const char **)&value));
if (*value == 0)
return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
_("Malformed copyfrom line in node-rev '%s'"),
noderev_id);
- noderev->copyfrom_path = auto_unescape_path(value, pool);
+ noderev->copyfrom_path = auto_unescape_path(apr_pstrdup(result_pool,
+ value),
+ result_pool);
}
/* Get whether this is a fresh txn root. */
@@ -538,13 +576,13 @@ svn_fs_x__read_noderev(node_revision_t *
/* Return a textual representation of the DIGEST of given KIND.
* If IS_NULL is TRUE, no digest is available.
- * Use POOL for allocations.
+ * Allocate the result in RESULT_POOL.
*/
static const char *
format_digest(const unsigned char *digest,
svn_checksum_kind_t kind,
svn_boolean_t is_null,
- apr_pool_t *pool)
+ apr_pool_t *result_pool)
{
svn_checksum_t checksum;
checksum.digest = digest;
@@ -553,92 +591,105 @@ format_digest(const unsigned char *diges
if (is_null)
return "(null)";
- return svn_checksum_to_cstring_display(&checksum, pool);
+ return svn_checksum_to_cstring_display(&checksum, result_pool);
}
svn_stringbuf_t *
-svn_fs_x__unparse_representation(representation_t *rep,
- int format,
+svn_fs_x__unparse_representation(svn_fs_x__representation_t *rep,
svn_boolean_t mutable_rep_truncated,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
if (!rep->has_sha1)
return svn_stringbuf_createf
- (pool,
+ (result_pool,
"%" APR_INT64_T_FMT " %" APR_UINT64_T_FMT " %" SVN_FILESIZE_T_FMT
" %" SVN_FILESIZE_T_FMT " %s",
rep->id.change_set, rep->id.number, rep->size,
rep->expanded_size,
- format_digest(rep->md5_digest, svn_checksum_md5, FALSE, pool));
+ format_digest(rep->md5_digest, svn_checksum_md5, FALSE,
+ scratch_pool));
return svn_stringbuf_createf
- (pool,
+ (result_pool,
"%" APR_INT64_T_FMT " %" APR_UINT64_T_FMT " %" SVN_FILESIZE_T_FMT
" %" SVN_FILESIZE_T_FMT " %s %s",
rep->id.change_set, rep->id.number, rep->size,
rep->expanded_size,
- format_digest(rep->md5_digest, svn_checksum_md5, FALSE, pool),
+ format_digest(rep->md5_digest, svn_checksum_md5,
+ FALSE, scratch_pool),
format_digest(rep->sha1_digest, svn_checksum_sha1,
- !rep->has_sha1, pool));
+ !rep->has_sha1, scratch_pool));
}
svn_error_t *
svn_fs_x__write_noderev(svn_stream_t *outfile,
- node_revision_t *noderev,
- int format,
- apr_pool_t *pool)
+ svn_fs_x__noderev_t *noderev,
+ apr_pool_t *scratch_pool)
{
- SVN_ERR(svn_stream_printf(outfile, pool, HEADER_ID ": %s\n",
- svn_fs_x__id_unparse(noderev->id, pool)->data));
+ svn_string_t *str_id;
+
+ str_id = svn_fs_x__id_unparse(&noderev->noderev_id, scratch_pool);
+ SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_ID ": %s\n",
+ str_id->data));
+ str_id = svn_fs_x__id_unparse(&noderev->node_id, scratch_pool);
+ SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_NODE ": %s\n",
+ str_id->data));
+ str_id = svn_fs_x__id_unparse(&noderev->copy_id, scratch_pool);
+ SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_COPY ": %s\n",
+ str_id->data));
- SVN_ERR(svn_stream_printf(outfile, pool, HEADER_TYPE ": %s\n",
+ SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_TYPE ": %s\n",
(noderev->kind == svn_node_file) ?
SVN_FS_X__KIND_FILE : SVN_FS_X__KIND_DIR));
- if (noderev->predecessor_id)
- SVN_ERR(svn_stream_printf(outfile, pool, HEADER_PRED ": %s\n",
- svn_fs_x__id_unparse(noderev->predecessor_id,
- pool)->data));
+ if (svn_fs_x__id_used(&noderev->predecessor_id))
+ SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_PRED ": %s\n",
+ svn_fs_x__id_unparse(&noderev->predecessor_id,
+ scratch_pool)->data));
- SVN_ERR(svn_stream_printf(outfile, pool, HEADER_COUNT ": %d\n",
+ SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_COUNT ": %d\n",
noderev->predecessor_count));
if (noderev->data_rep)
- SVN_ERR(svn_stream_printf(outfile, pool, HEADER_TEXT ": %s\n",
+ SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_TEXT ": %s\n",
svn_fs_x__unparse_representation
(noderev->data_rep,
- format,
noderev->kind == svn_node_dir,
- pool)->data));
+ scratch_pool, scratch_pool)->data));
if (noderev->prop_rep)
- SVN_ERR(svn_stream_printf(outfile, pool, HEADER_PROPS ": %s\n",
+ SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_PROPS ": %s\n",
svn_fs_x__unparse_representation
- (noderev->prop_rep, format,
- TRUE, pool)->data));
+ (noderev->prop_rep,
+ TRUE, scratch_pool, scratch_pool)->data));
- SVN_ERR(svn_stream_printf(outfile, pool, HEADER_CPATH ": %s\n",
- auto_escape_path(noderev->created_path, pool)));
+ SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_CPATH ": %s\n",
+ auto_escape_path(noderev->created_path,
+ scratch_pool)));
if (noderev->copyfrom_path)
- SVN_ERR(svn_stream_printf(outfile, pool, HEADER_COPYFROM ": %ld"
+ SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_COPYFROM ": %ld"
" %s\n",
noderev->copyfrom_rev,
- auto_escape_path(noderev->copyfrom_path, pool)));
+ auto_escape_path(noderev->copyfrom_path,
+ scratch_pool)));
- if ((noderev->copyroot_rev != svn_fs_x__id_rev(noderev->id)) ||
- (strcmp(noderev->copyroot_path, noderev->created_path) != 0))
- SVN_ERR(svn_stream_printf(outfile, pool, HEADER_COPYROOT ": %ld"
+ if ( ( noderev->copyroot_rev
+ != svn_fs_x__get_revnum(noderev->noderev_id.change_set))
+ || (strcmp(noderev->copyroot_path, noderev->created_path) != 0))
+ SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_COPYROOT ": %ld"
" %s\n",
noderev->copyroot_rev,
- auto_escape_path(noderev->copyroot_path, pool)));
+ auto_escape_path(noderev->copyroot_path,
+ scratch_pool)));
if (noderev->is_fresh_txn_root)
SVN_ERR(svn_stream_puts(outfile, HEADER_FRESHTXNRT ": y\n"));
if (noderev->mergeinfo_count > 0)
- SVN_ERR(svn_stream_printf(outfile, pool, HEADER_MINFO_CNT ": %"
+ SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_MINFO_CNT ": %"
APR_INT64_T_FMT "\n",
noderev->mergeinfo_count));
@@ -651,16 +702,17 @@ svn_fs_x__write_noderev(svn_stream_t *ou
svn_error_t *
svn_fs_x__read_rep_header(svn_fs_x__rep_header_t **header,
svn_stream_t *stream,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_stringbuf_t *buffer;
char *str, *last_str;
apr_int64_t val;
svn_boolean_t eol = FALSE;
- SVN_ERR(svn_stream_readline(stream, &buffer, "\n", &eol, pool));
+ SVN_ERR(svn_stream_readline(stream, &buffer, "\n", &eol, scratch_pool));
- *header = apr_pcalloc(pool, sizeof(**header));
+ *header = apr_pcalloc(result_pool, sizeof(**header));
(*header)->header_size = buffer->len + 1;
if (strcmp(buffer->data, REP_DELTA) == 0)
{
@@ -677,10 +729,7 @@ svn_fs_x__read_rep_header(svn_fs_x__rep_
if (! str || (strcmp(str, REP_DELTA) != 0))
goto error;
- str = svn_cstring_tokenize(" ", &last_str);
- if (! str)
- goto error;
- (*header)->base_revision = SVN_STR_TO_REV(str);
+ SVN_ERR(parse_revnum(&(*header)->base_revision, (const char **)&last_str));
str = svn_cstring_tokenize(" ", &last_str);
if (! str)
@@ -704,7 +753,7 @@ svn_fs_x__read_rep_header(svn_fs_x__rep_
svn_error_t *
svn_fs_x__write_rep_header(svn_fs_x__rep_header_t *header,
svn_stream_t *stream,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
const char *text;
@@ -715,8 +764,8 @@ svn_fs_x__write_rep_header(svn_fs_x__rep
break;
default:
- text = apr_psprintf(pool, REP_DELTA " %ld %" APR_OFF_T_FMT " %"
- SVN_FILESIZE_T_FMT "\n",
+ text = apr_psprintf(scratch_pool, REP_DELTA " %ld %" APR_OFF_T_FMT
+ " %" SVN_FILESIZE_T_FMT "\n",
header->base_revision, header->base_item_index,
header->base_length);
}
@@ -728,27 +777,26 @@ svn_fs_x__write_rep_header(svn_fs_x__rep
the resulting change in *CHANGE_P. If there is no next record,
store NULL there. Perform all allocations from POOL. */
static svn_error_t *
-read_change(change_t **change_p,
+read_change(svn_fs_x__change_t **change_p,
svn_stream_t *stream,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_stringbuf_t *line;
svn_boolean_t eof = TRUE;
- change_t *change;
+ svn_fs_x__change_t *change;
char *str, *last_str, *kind_str;
- svn_fs_path_change2_t *info;
/* Default return value. */
*change_p = NULL;
- SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, pool));
+ SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, scratch_pool));
/* Check for a blank line. */
if (eof || (line->len == 0))
return SVN_NO_ERROR;
- change = apr_pcalloc(pool, sizeof(*change));
- info = &change->info;
+ change = apr_pcalloc(result_pool, sizeof(*change));
last_str = line->data;
/* Get the node-id of the change. */
@@ -757,10 +805,7 @@ read_change(change_t **change_p,
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
_("Invalid changes line in rev-file"));
- info->node_rev_id = svn_fs_x__id_parse(str, strlen(str), pool);
- if (info->node_rev_id == NULL)
- return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
- _("Invalid changes line in rev-file"));
+ SVN_ERR(svn_fs_x__id_parse(&change->noderev_id, str));
/* Get the change type. */
str = svn_cstring_tokenize(" ", &last_str);
@@ -770,7 +815,7 @@ read_change(change_t **change_p,
/* Don't bother to check the format number before looking for
* node-kinds: just read them if you find them. */
- info->node_kind = svn_node_unknown;
+ change->node_kind = svn_node_unknown;
kind_str = strchr(str, '-');
if (kind_str)
{
@@ -778,9 +823,9 @@ read_change(change_t **change_p,
*kind_str = '\0';
kind_str++;
if (strcmp(kind_str, SVN_FS_X__KIND_FILE) == 0)
- info->node_kind = svn_node_file;
+ change->node_kind = svn_node_file;
else if (strcmp(kind_str, SVN_FS_X__KIND_DIR) == 0)
- info->node_kind = svn_node_dir;
+ change->node_kind = svn_node_dir;
else
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
_("Invalid changes line in rev-file"));
@@ -788,23 +833,23 @@ read_change(change_t **change_p,
if (strcmp(str, ACTION_MODIFY) == 0)
{
- info->change_kind = svn_fs_path_change_modify;
+ change->change_kind = svn_fs_path_change_modify;
}
else if (strcmp(str, ACTION_ADD) == 0)
{
- info->change_kind = svn_fs_path_change_add;
+ change->change_kind = svn_fs_path_change_add;
}
else if (strcmp(str, ACTION_DELETE) == 0)
{
- info->change_kind = svn_fs_path_change_delete;
+ change->change_kind = svn_fs_path_change_delete;
}
else if (strcmp(str, ACTION_REPLACE) == 0)
{
- info->change_kind = svn_fs_path_change_replace;
+ change->change_kind = svn_fs_path_change_replace;
}
else if (strcmp(str, ACTION_RESET) == 0)
{
- info->change_kind = svn_fs_path_change_reset;
+ change->change_kind = svn_fs_path_change_reset;
}
else
{
@@ -820,11 +865,11 @@ read_change(change_t **change_p,
if (strcmp(str, FLAG_TRUE) == 0)
{
- info->text_mod = TRUE;
+ change->text_mod = TRUE;
}
else if (strcmp(str, FLAG_FALSE) == 0)
{
- info->text_mod = FALSE;
+ change->text_mod = FALSE;
}
else
{
@@ -840,11 +885,11 @@ read_change(change_t **change_p,
if (strcmp(str, FLAG_TRUE) == 0)
{
- info->prop_mod = TRUE;
+ change->prop_mod = TRUE;
}
else if (strcmp(str, FLAG_FALSE) == 0)
{
- info->prop_mod = FALSE;
+ change->prop_mod = FALSE;
}
else
{
@@ -860,11 +905,11 @@ read_change(change_t **change_p,
if (strcmp(str, FLAG_TRUE) == 0)
{
- info->mergeinfo_mod = svn_tristate_true;
+ change->mergeinfo_mod = svn_tristate_true;
}
else if (strcmp(str, FLAG_FALSE) == 0)
{
- info->mergeinfo_mod = svn_tristate_false;
+ change->mergeinfo_mod = svn_tristate_false;
}
else
{
@@ -873,33 +918,34 @@ read_change(change_t **change_p,
}
/* Get the changed path. */
- change->path.data = auto_unescape_path(apr_pstrmemdup(pool, last_str,
+ if (!svn_fspath__is_canonical(last_str))
+ return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
+ _("Invalid path in changes line"));
+
+ change->path.data = auto_unescape_path(apr_pstrmemdup(result_pool,
+ last_str,
strlen(last_str)),
- pool);
+ result_pool);
change->path.len = strlen(change->path.data);
/* Read the next line, the copyfrom line. */
- SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, pool));
- info->copyfrom_known = TRUE;
+ SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, result_pool));
+ change->copyfrom_known = TRUE;
if (eof || line->len == 0)
{
- info->copyfrom_rev = SVN_INVALID_REVNUM;
- info->copyfrom_path = NULL;
+ change->copyfrom_rev = SVN_INVALID_REVNUM;
+ change->copyfrom_path = NULL;
}
else
{
last_str = line->data;
- str = svn_cstring_tokenize(" ", &last_str);
- if (! str)
- return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
- _("Invalid changes line in rev-file"));
- info->copyfrom_rev = SVN_STR_TO_REV(str);
+ SVN_ERR(parse_revnum(&change->copyfrom_rev, (const char **)&last_str));
- if (! last_str)
+ if (!svn_fspath__is_canonical(last_str))
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
- _("Invalid changes line in rev-file"));
+ _("Invalid copy-from path in changes line"));
- info->copyfrom_path = auto_unescape_path(last_str, pool);
+ change->copyfrom_path = auto_unescape_path(last_str, result_pool);
}
*change_p = change;
@@ -910,33 +956,67 @@ read_change(change_t **change_p,
svn_error_t *
svn_fs_x__read_changes(apr_array_header_t **changes,
svn_stream_t *stream,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- change_t *change;
+ svn_fs_x__change_t *change;
+ apr_pool_t *iterpool;
- /* pre-allocate enough room for most change lists
- (will be auto-expanded as necessary) */
- *changes = apr_array_make(pool, 30, sizeof(change_t *));
-
- SVN_ERR(read_change(&change, stream, pool));
+ /* Pre-allocate enough room for most change lists.
+ (will be auto-expanded as necessary).
+
+ Chose the default to just below 2^N such that the doubling reallocs
+ will request roughly 2^M bytes from the OS without exceeding the
+ respective two-power by just a few bytes (leaves room array and APR
+ node overhead for large enough M).
+ */
+ *changes = apr_array_make(result_pool, 63, sizeof(svn_fs_x__change_t *));
+
+ SVN_ERR(read_change(&change, stream, result_pool, scratch_pool));
+ iterpool = svn_pool_create(scratch_pool);
while (change)
{
- APR_ARRAY_PUSH(*changes, change_t*) = change;
- SVN_ERR(read_change(&change, stream, pool));
+ APR_ARRAY_PUSH(*changes, svn_fs_x__change_t*) = change;
+ SVN_ERR(read_change(&change, stream, result_pool, iterpool));
+ svn_pool_clear(iterpool);
}
+ svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
-/* Write a single change entry, path PATH, change CHANGE, and copyfrom
- string COPYFROM, into the file specified by FILE. Only include the
- node kind field if INCLUDE_NODE_KIND is true. All temporary
- allocations are in POOL. */
+svn_error_t *
+svn_fs_x__read_changes_incrementally(svn_stream_t *stream,
+ svn_fs_x__change_receiver_t
+ change_receiver,
+ void *change_receiver_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_fs_x__change_t *change;
+ apr_pool_t *iterpool;
+
+ iterpool = svn_pool_create(scratch_pool);
+ do
+ {
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(read_change(&change, stream, iterpool, iterpool));
+ if (change)
+ SVN_ERR(change_receiver(change_receiver_baton, change, iterpool));
+ }
+ while (change);
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
+
+/* Write a single change entry, path PATH, change CHANGE, to STREAM.
+
+ All temporary allocations are in SCRATCH_POOL. */
static svn_error_t *
write_change_entry(svn_stream_t *stream,
- const char *path,
- svn_fs_path_change2_t *change,
- apr_pool_t *pool)
+ svn_fs_x__change_t *change,
+ apr_pool_t *scratch_pool)
{
const char *idstr;
const char *change_string = NULL;
@@ -967,30 +1047,29 @@ write_change_entry(svn_stream_t *stream,
change->change_kind);
}
- if (change->node_rev_id)
- idstr = svn_fs_x__id_unparse(change->node_rev_id, pool)->data;
- else
- idstr = ACTION_RESET;
+ idstr = svn_fs_x__id_unparse(&change->noderev_id, scratch_pool)->data;
SVN_ERR_ASSERT(change->node_kind == svn_node_dir
- || change->node_kind == svn_node_file);
- kind_string = apr_psprintf(pool, "-%s",
- change->node_kind == svn_node_dir
- ? SVN_FS_X__KIND_DIR
- : SVN_FS_X__KIND_FILE);
- buf = svn_stringbuf_createf(pool, "%s %s%s %s %s %s %s\n",
+ || change->node_kind == svn_node_file);
+ kind_string = apr_psprintf(scratch_pool, "-%s",
+ change->node_kind == svn_node_dir
+ ? SVN_FS_X__KIND_DIR
+ : SVN_FS_X__KIND_FILE);
+
+ buf = svn_stringbuf_createf(scratch_pool, "%s %s%s %s %s %s %s\n",
idstr, change_string, kind_string,
change->text_mod ? FLAG_TRUE : FLAG_FALSE,
change->prop_mod ? FLAG_TRUE : FLAG_FALSE,
change->mergeinfo_mod == svn_tristate_true
? FLAG_TRUE : FLAG_FALSE,
- auto_escape_path(path, pool));
+ auto_escape_path(change->path.data, scratch_pool));
if (SVN_IS_VALID_REVNUM(change->copyfrom_rev))
{
- svn_stringbuf_appendcstr(buf, apr_psprintf(pool, "%ld %s",
- change->copyfrom_rev,
- auto_escape_path(change->copyfrom_path, pool)));
+ svn_stringbuf_appendcstr(buf, apr_psprintf(scratch_pool, "%ld %s",
+ change->copyfrom_rev,
+ auto_escape_path(change->copyfrom_path,
+ scratch_pool)));
}
svn_stringbuf_appendbyte(buf, '\n');
@@ -1005,36 +1084,40 @@ svn_fs_x__write_changes(svn_stream_t *st
svn_fs_t *fs,
apr_hash_t *changes,
svn_boolean_t terminate_list,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
- apr_pool_t *iterpool = svn_pool_create(pool);
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
apr_array_header_t *sorted_changed_paths;
int i;
/* For the sake of the repository administrator sort the changes so
that the final file is deterministic and repeatable, however the
- rest of the FSX code doesn't require any particular order here. */
+ rest of the FSX code doesn't require any particular order here.
+
+ Also, this sorting is only effective in writing all entries with
+ a single call as write_final_changed_path_info() does. For the
+ list being written incrementally during transaction, we actually
+ *must not* change the order of entries from different calls.
+ */
sorted_changed_paths = svn_sort__hash(changes,
- svn_sort_compare_items_lexically, pool);
+ svn_sort_compare_items_lexically,
+ scratch_pool);
/* Write all items to disk in the new order. */
for (i = 0; i < sorted_changed_paths->nelts; ++i)
{
- svn_fs_path_change2_t *change;
- const char *path;
+ svn_fs_x__change_t *change;
svn_pool_clear(iterpool);
-
change = APR_ARRAY_IDX(sorted_changed_paths, i, svn_sort__item_t).value;
- path = APR_ARRAY_IDX(sorted_changed_paths, i, svn_sort__item_t).key;
/* Write out the new entry into the final rev-file. */
- SVN_ERR(write_change_entry(stream, path, change, iterpool));
+ SVN_ERR(write_change_entry(stream, change, iterpool));
}
if (terminate_list)
svn_stream_puts(stream, "\n");
-
+
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.h?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.h Sat Jan 3 14:00:41 2015
@@ -36,62 +36,81 @@ extern "C" {
#define SVN_FS_X__KIND_FILE "file"
#define SVN_FS_X__KIND_DIR "dir"
-/* Given the last "few" bytes (should be at least 40) of revision REV in
- * TRAILER, parse the last line and return the offset of the root noderev
- * in *ROOT_OFFSET and the offset of the changed paths list in
- * *CHANGES_OFFSET. Offsets are relative to the revision's start offset.
- * ROOT_OFFSET and / or CHANGES_OFFSET may be NULL.
+/* The functions are grouped as follows:
+ *
+ * - revision footer
+ * - representation (as in "text:" and "props:" lines)
+ * - node revision
+ * - representation header ("DELTA" lines)
+ * - changed path list
+ */
+
+/* Given the FSX revision / pack FOOTER, parse it destructively
+ * and return the start offsets of the index data in *L2P_OFFSET and
+ * *P2L_OFFSET, respectively. Also, return the expected checksums in
+ * in *L2P_CHECKSUM and *P2L_CHECKSUM.
*
- * Note that REV is only used to construct nicer error objects.
+ * Note that REV is only used to construct nicer error objects that
+ * mention this revision. Allocate the checksums in RESULT_POOL.
*/
svn_error_t *
-svn_fs_x__parse_revision_trailer(apr_off_t *root_offset,
- apr_off_t *changes_offset,
- svn_stringbuf_t *trailer,
- svn_revnum_t rev);
-
-/* Given the offset of the root noderev in ROOT_OFFSET and the offset of
- * the changed paths list in CHANGES_OFFSET, return the corresponding
- * revision's trailer. Allocate it in POOL.
+svn_fs_x__parse_footer(apr_off_t *l2p_offset,
+ svn_checksum_t **l2p_checksum,
+ apr_off_t *p2l_offset,
+ svn_checksum_t **p2l_checksum,
+ svn_stringbuf_t *footer,
+ svn_revnum_t rev,
+ apr_pool_t *result_pool);
+
+/* Given the offset of the L2P index data in L2P_OFFSET, the content
+ * checksum in L2P_CHECKSUM and the offset plus checksum of the P2L
+ * index data in P2L_OFFSET and P2L_CHECKSUM.
+ *
+ * Return the corresponding format 7+ revision / pack file footer.
+ * Allocate it in RESULT_POOL and use SCRATCH_POOL for temporary.
*/
svn_stringbuf_t *
-svn_fs_x__unparse_revision_trailer(apr_off_t root_offset,
- apr_off_t changes_offset,
- apr_pool_t *pool);
+svn_fs_x__unparse_footer(apr_off_t l2p_offset,
+ svn_checksum_t *l2p_checksum,
+ apr_off_t p2l_offset,
+ svn_checksum_t *p2l_checksum,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* Parse the description of a representation from TEXT and store it
- into *REP_P. Allocate *REP_P in POOL. */
+ into *REP_P. TEXT will be invalidated by this call. Allocate *REP_P in
+ RESULT_POOL and use SCRATCH_POOL for temporaries. */
svn_error_t *
-svn_fs_x__parse_representation(representation_t **rep_p,
+svn_fs_x__parse_representation(svn_fs_x__representation_t **rep_p,
svn_stringbuf_t *text,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
-/* Return a formatted string, compatible with filesystem format FORMAT,
- that represents the location of representation REP. If
- MUTABLE_REP_TRUNCATED is given, the rep is for props or dir contents,
- and only a "-1" revision number will be given for a mutable rep.
- If MAY_BE_CORRUPT is true, guard for NULL when constructing the string.
- Perform the allocation from POOL. */
+/* Return a formatted string that represents the location of representation
+ * REP. If MUTABLE_REP_TRUNCATED is given, the rep is for props or dir
+ * contents, and only a "-1" revision number will be given for a mutable rep.
+ * If MAY_BE_CORRUPT is true, guard for NULL when constructing the string.
+ * Allocate the result in RESULT_POOL and temporaries in SCRATCH_POOL. */
svn_stringbuf_t *
-svn_fs_x__unparse_representation(representation_t *rep,
- int format,
+svn_fs_x__unparse_representation(svn_fs_x__representation_t *rep,
svn_boolean_t mutable_rep_truncated,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* Read a node-revision from STREAM. Set *NODEREV to the new structure,
- allocated in POOL. */
+ allocated in RESULT_POOL. */
svn_error_t *
-svn_fs_x__read_noderev(node_revision_t **noderev,
+svn_fs_x__read_noderev(svn_fs_x__noderev_t **noderev,
svn_stream_t *stream,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
-/* Write the node-revision NODEREV into the stream OUTFILE, compatible with
- filesystem format FORMAT. Temporary allocations are from POOL. */
+/* Write the node-revision NODEREV into the stream OUTFILE.
+ Temporary allocations are from SCRATCH_POOL. */
svn_error_t *
svn_fs_x__write_noderev(svn_stream_t *outfile,
- node_revision_t *noderev,
- int format,
- apr_pool_t *pool);
+ svn_fs_x__noderev_t *noderev,
+ apr_pool_t *scratch_pool);
/* This type enumerates all forms of representations that we support. */
typedef enum svn_fs_x__rep_type_t
@@ -132,39 +151,61 @@ typedef struct svn_fs_x__rep_header_t
apr_size_t header_size;
} svn_fs_x__rep_header_t;
-/* Read the next line from file FILE and parse it as a text
- representation entry. Return the parsed entry in *REP_ARGS_P.
- Perform all allocations in POOL. */
+/* Read the next line from STREAM and parse it as a text
+ representation header. Return the parsed entry in *HEADER, allocated
+ in RESULT_POOL. Perform temporary allocations in SCRATCH_POOL. */
svn_error_t *
svn_fs_x__read_rep_header(svn_fs_x__rep_header_t **header,
svn_stream_t *stream,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
-/* Write the representation HEADER to STREAM. Use POOL for allocations. */
+/* Write the representation HEADER to STREAM.
+ * Use SCRATCH_POOL for allocations. */
svn_error_t *
svn_fs_x__write_rep_header(svn_fs_x__rep_header_t *header,
svn_stream_t *stream,
- apr_pool_t *pool);
+ apr_pool_t *scratch_pool);
-/* Read all the changes from STREAM and store them in *CHANGES. Do all
- allocations in POOL. */
+/* Read all the changes from STREAM and store them in *CHANGES,
+ allocated in RESULT_POOL. Do temporary allocations in SCRATCH_POOL. */
svn_error_t *
svn_fs_x__read_changes(apr_array_header_t **changes,
svn_stream_t *stream,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/* Callback function used by svn_fs_fs__read_changes_incrementally(),
+ * asking the receiver to process to process CHANGE using BATON. CHANGE
+ * and SCRATCH_POOL will not be valid beyond the current callback invocation.
+ */
+typedef svn_error_t *(*svn_fs_x__change_receiver_t)(
+ void *baton,
+ svn_fs_x__change_t *change,
+ apr_pool_t *scratch_pool);
+
+/* Read all the changes from STREAM and invoke CHANGE_RECEIVER on each change.
+ Do all allocations in SCRATCH_POOL. */
+svn_error_t *
+svn_fs_x__read_changes_incrementally(svn_stream_t *stream,
+ svn_fs_x__change_receiver_t
+ change_receiver,
+ void *change_receiver_baton,
+ apr_pool_t *scratch_pool);
/* Write the changed path info from CHANGES in filesystem FS to the
output stream STREAM. You may call this function multiple time on
- the same stream but the last call should set TERMINATE_LIST to write
- an extra empty line that marks the end of the changed paths list.
- Perform temporary allocations in POOL.
+ the same stream. If you are writing to a (proto-)revision file,
+ the last call must set TERMINATE_LIST to write an extra empty line
+ that marks the end of the changed paths list.
+ Perform temporary allocations in SCRATCH_POOL.
*/
svn_error_t *
svn_fs_x__write_changes(svn_stream_t *stream,
svn_fs_t *fs,
apr_hash_t *changes,
svn_boolean_t terminate_list,
- apr_pool_t *pool);
+ apr_pool_t *scratch_pool);
#ifdef __cplusplus
}
Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/noderevs.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/noderevs.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/noderevs.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/noderevs.c Sat Jan 3 14:00:41 2015
@@ -49,19 +49,7 @@
/* the noderev has copy-root path and revision */
#define NODEREV_HAS_CPATH 0x00040
-/* Our internal representation of an id
- * (basically, strip off the txn_id and the fs-agnostic header)
- */
-typedef struct binary_id_t
-{
- svn_fs_x__id_part_t node_id;
- svn_fs_x__id_part_t copy_id;
- svn_fs_x__id_part_t noderev_id;
-} binary_id_t;
-
/* Our internal representation of an representation.
- * We simply omit the uniquifier, which allows us to share instances of
- * binary_representation_t and uniquify them in a shared_representation_t.
*/
typedef struct binary_representation_t
{
@@ -72,7 +60,7 @@ typedef struct binary_representation_t
unsigned char md5_digest[APR_MD5_DIGESTSIZE];
/* Location of this representation. */
- svn_fs_x__id_part_t id;
+ svn_fs_x__id_t id;
/* The size of the representation in bytes as seen in the revision
file. */
@@ -83,7 +71,7 @@ typedef struct binary_representation_t
svn_filesize_t expanded_size;
} binary_representation_t;
-/* Our internal representation of a node_revision_t.
+/* Our internal representation of a svn_fs_x__noderev_t.
*
* We will store path strings in a string container and reference them
* from here. Similarly, IDs and representations are being stored in
@@ -95,9 +83,15 @@ typedef struct binary_noderev_t
/* node type and presence indicators */
apr_uint32_t flags;
- /* Index+1 of the node-id for this node-rev. */
+ /* Index+1 of the noderev-id for this node-rev. */
int id;
+ /* Index+1 of the node-id for this node-rev. */
+ int node_id;
+
+ /* Index+1 of the copy-id for this node-rev. */
+ int copy_id;
+
/* Index+1 of the predecessor node revision id, or 0 if there is no
predecessor for this node revision */
int predecessor_id;
@@ -158,19 +152,14 @@ struct svn_fs_x__noderevs_t
apr_hash_t *ids_dict;
/* During construction, maps a full binary_representation_t to an index
- * into DATA_REPS. */
- apr_hash_t *data_reps_dict;
-
- /* During construction, maps a full binary_representation_t to an index
- * into PROP_REPS. */
- apr_hash_t *prop_reps_dict;
+ * into REPS. */
+ apr_hash_t *reps_dict;
/* array of binary_id_t */
apr_array_header_t *ids;
- /* arrays of binary_representation_t */
- apr_array_header_t *data_reps;
- apr_array_header_t *prop_reps;
+ /* array of binary_representation_t */
+ apr_array_header_t *reps;
/* array of binary_noderev_t. */
apr_array_header_t *noderevs;
@@ -184,16 +173,13 @@ svn_fs_x__noderevs_create(int initial_co
noderevs->builder = svn_fs_x__string_table_builder_create(pool);
noderevs->ids_dict = svn_hash__make(pool);
- noderevs->data_reps_dict = svn_hash__make(pool);
- noderevs->prop_reps_dict = svn_hash__make(pool);
+ noderevs->reps_dict = svn_hash__make(pool);
noderevs->paths = NULL;
noderevs->ids
- = apr_array_make(pool, initial_count, sizeof(binary_id_t));
- noderevs->data_reps
- = apr_array_make(pool, initial_count, sizeof(binary_representation_t));
- noderevs->prop_reps
- = apr_array_make(pool, initial_count, sizeof(binary_representation_t));
+ = apr_array_make(pool, 2 * initial_count, sizeof(svn_fs_x__id_t));
+ noderevs->reps
+ = apr_array_make(pool, 2 * initial_count, sizeof(binary_representation_t));
noderevs->noderevs
= apr_array_make(pool, initial_count, sizeof(binary_noderev_t));
@@ -206,24 +192,19 @@ svn_fs_x__noderevs_create(int initial_co
static int
store_id(apr_array_header_t *ids,
apr_hash_t *dict,
- const svn_fs_id_t *id)
+ const svn_fs_x__id_t *id)
{
- binary_id_t bin_id = { { 0 } };
int idx;
void *idx_void;
- if (id == NULL)
+ if (!svn_fs_x__id_used(id))
return 0;
-
- bin_id.node_id = *svn_fs_x__id_node_id(id);
- bin_id.copy_id = *svn_fs_x__id_copy_id(id);
- bin_id.noderev_id = *svn_fs_x__id_noderev_id(id);
- idx_void = apr_hash_get(dict, &bin_id, sizeof(bin_id));
+ idx_void = apr_hash_get(dict, &id, sizeof(id));
idx = (int)(apr_uintptr_t)idx_void;
if (idx == 0)
{
- APR_ARRAY_PUSH(ids, binary_id_t) = bin_id;
+ APR_ARRAY_PUSH(ids, svn_fs_x__id_t) = *id;
idx = ids->nelts;
apr_hash_set(dict, ids->elts + (idx-1) * ids->elt_size,
ids->elt_size, (void*)(apr_uintptr_t)idx);
@@ -238,7 +219,7 @@ store_id(apr_array_header_t *ids,
static int
store_representation(apr_array_header_t *reps,
apr_hash_t *dict,
- const representation_t *rep)
+ const svn_fs_x__representation_t *rep)
{
binary_representation_t binary_rep = { 0 };
int idx;
@@ -269,7 +250,7 @@ store_representation(apr_array_header_t
apr_size_t
svn_fs_x__noderevs_add(svn_fs_x__noderevs_t *container,
- node_revision_t *noderev)
+ svn_fs_x__noderev_t *noderev)
{
binary_noderev_t binary_noderev = { 0 };
@@ -280,9 +261,13 @@ svn_fs_x__noderevs_add(svn_fs_x__noderev
| (int)noderev->kind;
binary_noderev.id
- = store_id(container->ids, container->ids_dict, noderev->id);
+ = store_id(container->ids, container->ids_dict, &noderev->noderev_id);
+ binary_noderev.node_id
+ = store_id(container->ids, container->ids_dict, &noderev->node_id);
+ binary_noderev.copy_id
+ = store_id(container->ids, container->ids_dict, &noderev->copy_id);
binary_noderev.predecessor_id
- = store_id(container->ids, container->ids_dict, noderev->predecessor_id);
+ = store_id(container->ids, container->ids_dict, &noderev->predecessor_id);
if (noderev->copyfrom_path)
{
@@ -303,19 +288,18 @@ svn_fs_x__noderevs_add(svn_fs_x__noderev
}
binary_noderev.predecessor_count = noderev->predecessor_count;
- binary_noderev.prop_rep = store_representation(container->prop_reps,
- container->prop_reps_dict,
+ binary_noderev.prop_rep = store_representation(container->reps,
+ container->reps_dict,
noderev->prop_rep);
- if (noderev->data_rep)
- binary_noderev.data_rep = store_representation(container->data_reps,
- container->data_reps_dict,
- noderev->data_rep);
+ binary_noderev.data_rep = store_representation(container->reps,
+ container->reps_dict,
+ noderev->data_rep);
if (noderev->created_path)
binary_noderev.created_path
= svn_fs_x__string_table_builder_add(container->builder,
- noderev->created_path,
- 0);
+ noderev->created_path,
+ 0);
binary_noderev.mergeinfo_count = noderev->mergeinfo_count;
@@ -333,58 +317,48 @@ svn_fs_x__noderevs_estimate_size(const s
/* string table code makes its own prediction,
* noderevs should be < 16 bytes each,
- * ids < 10 bytes each,
+ * id parts < 4 bytes each,
* data representations < 40 bytes each,
* property representations < 30 bytes each,
* some static overhead should be assumed */
return svn_fs_x__string_table_builder_estimate_size(container->builder)
+ container->noderevs->nelts * 16
- + container->ids->nelts * 10
- + container->data_reps->nelts * 40
- + container->prop_reps->nelts * 30
+ + container->ids->nelts * 4
+ + container->reps->nelts * 40
+ 100;
}
-/* Create an svn_fs_id_t in *ID, allocated in POOL based on the id stored
- * at index IDX in IDS.
+/* Set *ID to the ID part stored at index IDX in IDS.
*/
static svn_error_t *
-get_id(const svn_fs_id_t **id,
+get_id(svn_fs_x__id_t *id,
const apr_array_header_t *ids,
- int idx,
- apr_pool_t *pool)
+ int idx)
{
- binary_id_t *binary_id;
-
/* handle NULL IDs */
if (idx == 0)
{
- *id = NULL;
+ svn_fs_x__id_reset(id);
return SVN_NO_ERROR;
}
/* check for corrupted data */
if (idx < 0 || idx > ids->nelts)
return svn_error_createf(SVN_ERR_FS_CONTAINER_INDEX, NULL,
- _("Node revision ID index %d"
- " exceeds container size %d"),
+ _("ID part index %d exceeds container size %d"),
idx, ids->nelts);
- /* create a svn_fs_id_t from stored info */
- binary_id = &APR_ARRAY_IDX(ids, idx - 1, binary_id_t);
- *id = svn_fs_x__id_create(&binary_id->node_id,
- &binary_id->copy_id,
- &binary_id->noderev_id,
- pool);
+ /* Return the requested ID. */
+ *id = APR_ARRAY_IDX(ids, idx - 1, svn_fs_x__id_t);
return SVN_NO_ERROR;
}
-/* Create a representation_t in *REP, allocated in POOL based on the
+/* Create a svn_fs_x__representation_t in *REP, allocated in POOL based on the
* representation stored at index IDX in REPS.
*/
static svn_error_t *
-get_representation(representation_t **rep,
+get_representation(svn_fs_x__representation_t **rep,
const apr_array_header_t *reps,
int idx,
apr_pool_t *pool)
@@ -422,14 +396,14 @@ get_representation(representation_t **re
}
svn_error_t *
-svn_fs_x__noderevs_get(node_revision_t **noderev_p,
+svn_fs_x__noderevs_get(svn_fs_x__noderev_t **noderev_p,
const svn_fs_x__noderevs_t *container,
apr_size_t idx,
apr_pool_t *pool)
{
- node_revision_t *noderev;
+ svn_fs_x__noderev_t *noderev;
binary_noderev_t *binary_noderev;
-
+
/* CONTAINER must be in 'finalized' mode */
SVN_ERR_ASSERT(container->builder == NULL);
SVN_ERR_ASSERT(container->paths);
@@ -446,11 +420,15 @@ svn_fs_x__noderevs_get(node_revision_t *
/* allocate result struct and fill it field by field */
noderev = apr_pcalloc(pool, sizeof(*noderev));
binary_noderev = &APR_ARRAY_IDX(container->noderevs, idx, binary_noderev_t);
-
+
noderev->kind = (svn_node_kind_t)(binary_noderev->flags & NODEREV_KIND_MASK);
- SVN_ERR(get_id(&noderev->id, container->ids, binary_noderev->id, pool));
+ SVN_ERR(get_id(&noderev->noderev_id, container->ids, binary_noderev->id));
+ SVN_ERR(get_id(&noderev->node_id, container->ids,
+ binary_noderev->node_id));
+ SVN_ERR(get_id(&noderev->copy_id, container->ids,
+ binary_noderev->copy_id));
SVN_ERR(get_id(&noderev->predecessor_id, container->ids,
- binary_noderev->predecessor_id, pool));
+ binary_noderev->predecessor_id));
if (binary_noderev->flags & NODEREV_HAS_COPYFROM)
{
@@ -484,9 +462,9 @@ svn_fs_x__noderevs_get(node_revision_t *
noderev->predecessor_count = binary_noderev->predecessor_count;
- SVN_ERR(get_representation(&noderev->prop_rep, container->prop_reps,
+ SVN_ERR(get_representation(&noderev->prop_rep, container->reps,
binary_noderev->prop_rep, pool));
- SVN_ERR(get_representation(&noderev->data_rep, container->data_reps,
+ SVN_ERR(get_representation(&noderev->data_rep, container->reps,
binary_noderev->data_rep, pool));
if (binary_noderev->flags & NODEREV_HAS_CPATH)
@@ -576,40 +554,34 @@ svn_fs_x__write_noderevs_container(svn_s
= svn_packed__create_int_stream(root, FALSE, FALSE);
svn_packed__int_stream_t *ids_stream
= svn_packed__create_int_substream(structs_stream, FALSE, FALSE);
- svn_packed__int_stream_t *data_reps_stream
- = create_rep_stream(structs_stream);
- svn_packed__int_stream_t *prop_reps_stream
+ svn_packed__int_stream_t *reps_stream
= create_rep_stream(structs_stream);
svn_packed__int_stream_t *noderevs_stream
= svn_packed__create_int_substream(structs_stream, FALSE, FALSE);
svn_packed__byte_stream_t *digests_stream
= svn_packed__create_bytes_stream(root);
- /* structure the CHANGES_STREAM such we can extract much of the redundancy
- * from the binary_change_t structs */
- for (i = 0; i < 3 * 2; ++i)
+ /* structure the IDS_STREAM such we can extract much of the redundancy
+ * from the svn_fs_x__ip_part_t structs */
+ for (i = 0; i < 2; ++i)
svn_packed__create_int_substream(ids_stream, TRUE, FALSE);
+ /* Same storing binary_noderev_t in the NODEREVS_STREAM */
svn_packed__create_int_substream(noderevs_stream, FALSE, FALSE);
- for (i = 0; i < 11; ++i)
+ for (i = 0; i < 13; ++i)
svn_packed__create_int_substream(noderevs_stream, TRUE, FALSE);
/* serialize ids array */
for (i = 0; i < container->ids->nelts; ++i)
{
- binary_id_t *id = &APR_ARRAY_IDX(container->ids, i, binary_id_t);
+ svn_fs_x__id_t *id = &APR_ARRAY_IDX(container->ids, i, svn_fs_x__id_t);
- svn_packed__add_int(ids_stream, id->node_id.change_set);
- svn_packed__add_uint(ids_stream, id->node_id.number);
- svn_packed__add_int(ids_stream, id->copy_id.change_set);
- svn_packed__add_uint(ids_stream, id->copy_id.number);
- svn_packed__add_int(ids_stream, id->noderev_id.change_set);
- svn_packed__add_uint(ids_stream, id->noderev_id.number);
+ svn_packed__add_int(ids_stream, id->change_set);
+ svn_packed__add_uint(ids_stream, id->number);
}
/* serialize rep arrays */
- write_reps(data_reps_stream, digests_stream, container->data_reps);
- write_reps(prop_reps_stream, digests_stream, container->prop_reps);
+ write_reps(reps_stream, digests_stream, container->reps);
/* serialize noderevs array */
for (i = 0; i < container->noderevs->nelts; ++i)
@@ -620,6 +592,8 @@ svn_fs_x__write_noderevs_container(svn_s
svn_packed__add_uint(noderevs_stream, noderev->flags);
svn_packed__add_uint(noderevs_stream, noderev->id);
+ svn_packed__add_uint(noderevs_stream, noderev->node_id);
+ svn_packed__add_uint(noderevs_stream, noderev->copy_id);
svn_packed__add_uint(noderevs_stream, noderev->predecessor_id);
svn_packed__add_uint(noderevs_stream, noderev->predecessor_count);
@@ -642,9 +616,9 @@ svn_fs_x__write_noderevs_container(svn_s
return SVN_NO_ERROR;
}
-/* Allocate a representation_t array in POOL and return it in *REPS_P.
- * Deserialize the data in REP_STREAM and DIGEST_STREAM and store the
- * resulting representations into the *REPS_P.
+/* Allocate a svn_fs_x__representation_t array in POOL and return it in
+ * REPS_P. Deserialize the data in REP_STREAM and DIGEST_STREAM and store
+ * the resulting representations into the *REPS_P.
*/
static svn_error_t *
read_reps(apr_array_header_t **reps_p,
@@ -721,8 +695,7 @@ svn_fs_x__read_noderevs_container(svn_fs
svn_packed__data_root_t *root;
svn_packed__int_stream_t *structs_stream;
svn_packed__int_stream_t *ids_stream;
- svn_packed__int_stream_t *data_reps_stream;
- svn_packed__int_stream_t *prop_reps_stream;
+ svn_packed__int_stream_t *reps_stream;
svn_packed__int_stream_t *noderevs_stream;
svn_packed__byte_stream_t *digests_stream;
@@ -734,34 +707,27 @@ svn_fs_x__read_noderevs_container(svn_fs
/* get streams */
structs_stream = svn_packed__first_int_stream(root);
ids_stream = svn_packed__first_int_substream(structs_stream);
- data_reps_stream = svn_packed__next_int_stream(ids_stream);
- prop_reps_stream = svn_packed__next_int_stream(data_reps_stream);
- noderevs_stream = svn_packed__next_int_stream(prop_reps_stream);
+ reps_stream = svn_packed__next_int_stream(ids_stream);
+ noderevs_stream = svn_packed__next_int_stream(reps_stream);
digests_stream = svn_packed__first_byte_stream(root);
/* read ids array */
count
= svn_packed__int_count(svn_packed__first_int_substream(ids_stream));
noderevs->ids
- = apr_array_make(result_pool, (int)count, sizeof(binary_id_t));
+ = apr_array_make(result_pool, (int)count, sizeof(svn_fs_x__id_t));
for (i = 0; i < count; ++i)
{
- binary_id_t id;
+ svn_fs_x__id_t id;
- id.node_id.change_set = (svn_revnum_t)svn_packed__get_int(ids_stream);
- id.node_id.number = svn_packed__get_uint(ids_stream);
- id.copy_id.change_set = (svn_revnum_t)svn_packed__get_int(ids_stream);
- id.copy_id.number = svn_packed__get_uint(ids_stream);
- id.noderev_id.change_set = (svn_revnum_t)svn_packed__get_int(ids_stream);
- id.noderev_id.number = svn_packed__get_uint(ids_stream);
+ id.change_set = (svn_revnum_t)svn_packed__get_int(ids_stream);
+ id.number = svn_packed__get_uint(ids_stream);
- APR_ARRAY_PUSH(noderevs->ids, binary_id_t) = id;
+ APR_ARRAY_PUSH(noderevs->ids, svn_fs_x__id_t) = id;
}
/* read rep arrays */
- SVN_ERR(read_reps(&noderevs->data_reps, data_reps_stream, digests_stream,
- result_pool));
- SVN_ERR(read_reps(&noderevs->prop_reps, prop_reps_stream, digests_stream,
+ SVN_ERR(read_reps(&noderevs->reps, reps_stream, digests_stream,
result_pool));
/* read noderevs array */
@@ -776,6 +742,8 @@ svn_fs_x__read_noderevs_container(svn_fs
noderev.flags = (apr_uint32_t)svn_packed__get_uint(noderevs_stream);
noderev.id = (int)svn_packed__get_uint(noderevs_stream);
+ noderev.node_id = (int)svn_packed__get_uint(noderevs_stream);
+ noderev.copy_id = (int)svn_packed__get_uint(noderevs_stream);
noderev.predecessor_id = (int)svn_packed__get_uint(noderevs_stream);
noderev.predecessor_count = (int)svn_packed__get_uint(noderevs_stream);
@@ -808,8 +776,7 @@ svn_fs_x__serialize_noderevs_container(v
svn_stringbuf_t *serialized;
apr_size_t size
= noderevs->ids->elt_size * noderevs->ids->nelts
- + noderevs->data_reps->elt_size * noderevs->data_reps->nelts
- + noderevs->prop_reps->elt_size * noderevs->prop_reps->nelts
+ + noderevs->reps->elt_size * noderevs->reps->nelts
+ noderevs->noderevs->elt_size * noderevs->noderevs->nelts
+ 10 * noderevs->noderevs->elt_size
+ 100;
@@ -821,8 +788,7 @@ svn_fs_x__serialize_noderevs_container(v
/* serialize sub-structures */
svn_fs_x__serialize_string_table(context, &noderevs->paths);
svn_fs_x__serialize_apr_array(context, &noderevs->ids);
- svn_fs_x__serialize_apr_array(context, &noderevs->data_reps);
- svn_fs_x__serialize_apr_array(context, &noderevs->prop_reps);
+ svn_fs_x__serialize_apr_array(context, &noderevs->reps);
svn_fs_x__serialize_apr_array(context, &noderevs->noderevs);
/* return the serialized result */
@@ -845,8 +811,7 @@ svn_fs_x__deserialize_noderevs_container
/* de-serialize sub-structures */
svn_fs_x__deserialize_string_table(noderevs, &noderevs->paths);
svn_fs_x__deserialize_apr_array(noderevs, &noderevs->ids, pool);
- svn_fs_x__deserialize_apr_array(noderevs, &noderevs->data_reps, pool);
- svn_fs_x__deserialize_apr_array(noderevs, &noderevs->prop_reps, pool);
+ svn_fs_x__deserialize_apr_array(noderevs, &noderevs->reps, pool);
svn_fs_x__deserialize_apr_array(noderevs, &noderevs->noderevs, pool);
/* done */
@@ -880,12 +845,11 @@ svn_fs_x__noderevs_get_func(void **out,
void *baton,
apr_pool_t *pool)
{
- node_revision_t *noderev;
+ svn_fs_x__noderev_t *noderev;
binary_noderev_t *binary_noderev;
-
+
apr_array_header_t ids;
- apr_array_header_t data_reps;
- apr_array_header_t prop_reps;
+ apr_array_header_t reps;
apr_array_header_t noderevs;
apr_uint32_t idx = *(apr_uint32_t *)baton;
@@ -897,18 +861,19 @@ svn_fs_x__noderevs_get_func(void **out,
(const void *const *)&container->paths);
resolve_apr_array_header(&ids, container, &container->ids);
- resolve_apr_array_header(&data_reps, container, &container->data_reps);
- resolve_apr_array_header(&prop_reps, container, &container->prop_reps);
+ resolve_apr_array_header(&reps, container, &container->reps);
resolve_apr_array_header(&noderevs, container, &container->noderevs);
-
+
/* allocate result struct and fill it field by field */
noderev = apr_pcalloc(pool, sizeof(*noderev));
binary_noderev = &APR_ARRAY_IDX(&noderevs, idx, binary_noderev_t);
-
+
noderev->kind = (svn_node_kind_t)(binary_noderev->flags & NODEREV_KIND_MASK);
- SVN_ERR(get_id(&noderev->id, &ids, binary_noderev->id, pool));
+ SVN_ERR(get_id(&noderev->noderev_id, &ids, binary_noderev->id));
+ SVN_ERR(get_id(&noderev->node_id, &ids, binary_noderev->node_id));
+ SVN_ERR(get_id(&noderev->copy_id, &ids, binary_noderev->copy_id));
SVN_ERR(get_id(&noderev->predecessor_id, &ids,
- binary_noderev->predecessor_id, pool));
+ binary_noderev->predecessor_id));
if (binary_noderev->flags & NODEREV_HAS_COPYFROM)
{
@@ -942,9 +907,9 @@ svn_fs_x__noderevs_get_func(void **out,
noderev->predecessor_count = binary_noderev->predecessor_count;
- SVN_ERR(get_representation(&noderev->prop_rep, &prop_reps,
+ SVN_ERR(get_representation(&noderev->prop_rep, &reps,
binary_noderev->prop_rep, pool));
- SVN_ERR(get_representation(&noderev->data_rep, &data_reps,
+ SVN_ERR(get_representation(&noderev->data_rep, &reps,
binary_noderev->data_rep, pool));
if (binary_noderev->flags & NODEREV_HAS_CPATH)