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 2015/12/01 19:15:51 UTC
svn commit: r1717485 - /subversion/trunk/subversion/libsvn_fs_x/revprops.c
Author: stefan2
Date: Tue Dec 1 18:15:51 2015
New Revision: 1717485
URL: http://svn.apache.org/viewvc?rev=1717485&view=rev
Log:
Switch the header of packed FSX revprops from decimal numbers to the 7/8b
integer encoding.
* subversion/libsvn_fs_x/revprops.c
(parse_packed_revprops): We can parse directly from the uncompressed
buffer but we must always parse the whole header
now because there is no way to skip to its end.
(write_encoded_uint): New utility.
(serialize_revprops_header): Write the simpler header format now.
Modified:
subversion/trunk/subversion/libsvn_fs_x/revprops.c
Modified: subversion/trunk/subversion/libsvn_fs_x/revprops.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/revprops.c?rev=1717485&r1=1717484&r2=1717485&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/revprops.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/revprops.c Tue Dec 1 18:15:51 2015
@@ -731,12 +731,11 @@ parse_packed_revprops(svn_fs_t *fs,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- svn_stream_t *stream;
- apr_int64_t first_rev, count, i;
+ apr_uint64_t first_rev, count, i;
apr_size_t offset;
- const char *header_end;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
svn_boolean_t cache_all = has_revprop_cache(fs, scratch_pool);
+ const apr_byte_t *p, *end;
/* decompress (even if the data is only "stored", there is still a
* length header to remove) */
@@ -746,10 +745,10 @@ parse_packed_revprops(svn_fs_t *fs,
uncompressed, APR_SIZE_MAX));
/* read first revision number and number of revisions in the pack */
- stream = svn_stream_from_stringbuf(uncompressed, scratch_pool);
- SVN_ERR(svn_fs_x__read_number_from_stream(&first_rev, NULL, stream,
- iterpool));
- SVN_ERR(svn_fs_x__read_number_from_stream(&count, NULL, stream, iterpool));
+ p = (apr_byte_t *)uncompressed->data;
+ end = p + uncompressed->len;
+ p = svn__decode_uint(&first_rev, p, end);
+ p = svn__decode_uint(&count, p, end);
/* Check revision range for validity. */
if ( !same_shard(fs, revprops->revision, first_rev)
@@ -771,51 +770,65 @@ parse_packed_revprops(svn_fs_t *fs,
" starts at non-packed revisions r%ld"),
revprops->revision, (svn_revnum_t)first_rev);
+ /* Read the item sizes from the header. */
+ revprops->sizes = apr_array_make(result_pool, (int)count, sizeof(offset));
+ revprops->offsets = apr_array_make(result_pool, (int)count, sizeof(offset));
+
+ for (i = 0, offset = 0, revprops->total_size = 0; i < count; ++i)
+ {
+ apr_uint64_t size64;
+ apr_size_t size;
+
+ /* read & check the serialized size */
+ p = svn__decode_uint(&size64, p, end);
+ if (size64 > uncompressed->len - offset)
+ return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
+ "Packed revprop size exceeds pack file size");
+
+ size = (apr_size_t)size64;
+
+ /* fill REVPROPS data structures */
+ APR_ARRAY_PUSH(revprops->sizes, apr_size_t) = size;
+ APR_ARRAY_PUSH(revprops->offsets, apr_size_t) = offset;
+ revprops->total_size += size;
+
+ offset += size;
+ }
+
/* make PACKED_REVPROPS point to the first char after the header.
* This is where the serialized revprops are. */
- header_end = strstr(uncompressed->data, "\n\n");
- if (header_end == NULL)
- return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
- _("Header end not found"));
-
- offset = header_end - uncompressed->data + 2;
+ offset = p - (apr_byte_t *)uncompressed->data;
revprops->packed_revprops = svn_stringbuf_create_empty(result_pool);
revprops->packed_revprops->data = uncompressed->data + offset;
- revprops->packed_revprops->len = (apr_size_t)(uncompressed->len - offset);
- revprops->packed_revprops->blocksize = (apr_size_t)(uncompressed->blocksize - offset);
+ revprops->packed_revprops->len = uncompressed->len - offset;
+ revprops->packed_revprops->blocksize = uncompressed->blocksize - offset;
+
+ /* Verify that the last offset size does not extend beyond file sans
+ * header (we only checked against the full file contents). */
+ if (revprops->total_size > revprops->packed_revprops->len)
+ return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
+ "Packed revprop size exceeds pack file size");
/* STREAM still points to the first entry in the sizes list. */
SVN_ERR_ASSERT(revprops->entry.start_rev = (svn_revnum_t)first_rev);
- if (read_all)
- {
- /* Init / construct REVPROPS members. */
- revprops->sizes = apr_array_make(result_pool, (int)count,
- sizeof(offset));
- revprops->offsets = apr_array_make(result_pool, (int)count,
- sizeof(offset));
- }
/* Now parse, revision by revision, the size and content of each
* revisions' revprops. */
- for (i = 0, offset = 0, revprops->total_size = 0; i < count; ++i)
+ for (i = 0, offset = 0; i < count; ++i)
{
- apr_int64_t size;
svn_string_t serialized;
+
svn_revnum_t revision = (svn_revnum_t)(first_rev + i);
- svn_pool_clear(iterpool);
+ apr_size_t size = APR_ARRAY_IDX(revprops->sizes, (int)i, apr_size_t);
+ offset = APR_ARRAY_IDX(revprops->offsets, (int)i, apr_size_t);
- /* read & check the serialized size */
- SVN_ERR(svn_fs_x__read_number_from_stream(&size, NULL, stream,
- iterpool));
- if (size > (apr_int64_t)revprops->packed_revprops->len - offset)
- return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
- _("Packed revprop size exceeds pack file size"));
+ svn_pool_clear(iterpool);
- /* Parse this revprops list, if necessary */
serialized.data = revprops->packed_revprops->data + offset;
- serialized.len = (apr_size_t)size;
+ serialized.len = size;
+ /* Parse this revprops list, if necessary */
if (revision == revprops->revision)
{
/* Parse (and possibly cache) the one revprop list we care about. */
@@ -834,18 +847,10 @@ parse_packed_revprops(svn_fs_t *fs,
SVN_ERR(parse_revprop(&properties, fs, revision, &serialized,
iterpool, iterpool));
}
-
- if (read_all)
- {
- /* fill REVPROPS data structures */
- APR_ARRAY_PUSH(revprops->sizes, apr_size_t) = serialized.len;
- APR_ARRAY_PUSH(revprops->offsets, apr_size_t) = offset;
- }
- revprops->total_size += serialized.len;
-
- offset += serialized.len;
}
+ svn_pool_destroy(iterpool);
+
return SVN_NO_ERROR;
}
@@ -1091,6 +1096,20 @@ switch_to_new_revprop(svn_fs_t *fs,
return SVN_NO_ERROR;
}
+/* Write VALUE to STREAM using 7/8b encoding. */
+static svn_error_t *
+write_encoded_uint(svn_stream_t *stream,
+ apr_uint64_t value)
+{
+ apr_byte_t buffer[SVN__MAX_ENCODED_UINT_LEN];
+ apr_size_t len;
+
+ len = svn__encode_uint(buffer, value) - buffer;
+ SVN_ERR(svn_stream_write(stream, (const char *)buffer, &len));
+
+ return SVN_NO_ERROR;
+}
+
/* Write a pack file header to STREAM that starts at revision START_REVISION
* and contains the indexes [START,END) of SIZES.
*/
@@ -1102,32 +1121,17 @@ serialize_revprops_header(svn_stream_t *
int end,
apr_pool_t *scratch_pool)
{
- apr_pool_t *iterpool = svn_pool_create(scratch_pool);
int i;
-
SVN_ERR_ASSERT(start < end);
/* start revision and entry count */
- SVN_ERR(svn_stream_printf(stream, scratch_pool, "%ld\n", start_revision));
- SVN_ERR(svn_stream_printf(stream, scratch_pool, "%d\n", end - start));
+ SVN_ERR(write_encoded_uint(stream, start_revision));
+ SVN_ERR(write_encoded_uint(stream, end - start));
/* the sizes array */
for (i = start; i < end; ++i)
- {
- /* Non-standard pool usage.
- *
- * We only allocate a few bytes each iteration -- even with a
- * million iterations we would still be in good shape memory-wise.
- */
- apr_size_t size = APR_ARRAY_IDX(sizes, i, apr_size_t);
- SVN_ERR(svn_stream_printf(stream, iterpool, "%" APR_SIZE_T_FMT "\n",
- size));
- }
+ SVN_ERR(write_encoded_uint(stream, APR_ARRAY_IDX(sizes, i, apr_size_t)));
- /* the double newline char indicates the end of the header */
- SVN_ERR(svn_stream_printf(stream, iterpool, "\n"));
-
- svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}