summaryrefslogtreecommitdiff
path: root/subversion/libsvn_fs_fs/temp_serializer.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_fs_fs/temp_serializer.c')
-rw-r--r--subversion/libsvn_fs_fs/temp_serializer.c431
1 files changed, 222 insertions, 209 deletions
diff --git a/subversion/libsvn_fs_fs/temp_serializer.c b/subversion/libsvn_fs_fs/temp_serializer.c
index 0178143..4e7ae2d 100644
--- a/subversion/libsvn_fs_fs/temp_serializer.c
+++ b/subversion/libsvn_fs_fs/temp_serializer.c
@@ -24,15 +24,18 @@
#include "svn_pools.h"
#include "svn_hash.h"
-
-#include "id.h"
+#include "svn_sorts.h"
#include "svn_fs.h"
#include "private/svn_fs_util.h"
+#include "private/svn_sorts_private.h"
#include "private/svn_temp_serializer.h"
#include "private/svn_subr_private.h"
+#include "id.h"
#include "temp_serializer.h"
+#include "low_level.h"
+#include "cached_data.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 +109,12 @@ serialize_svn_string(svn_temp_serializer__context_t *context,
/* 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 +129,6 @@ deserialize_svn_string(void *buffer, svn_string_t **string)
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,48 +141,17 @@ serialize_representation(svn_temp_serializer__context_t *context,
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 */
-typedef struct hash_data_t
+/* auxiliary structure representing the content of a directory array */
+typedef struct dir_data_t
{
- /* number of entries in the directory */
- apr_size_t count;
+ /* number of entries in the directory
+ * (it's int because the directory is an APR array) */
+ int count;
/* number of unused dir entry buckets in the index */
apr_size_t over_provision;
@@ -238,14 +171,7 @@ typedef struct hash_data_t
/* size of the serialized entries and don't be too wasteful
* (needed since the entries are no longer in sequence) */
apr_uint32_t *lengths;
-} hash_data_t;
-
-static int
-compare_dirent_id_names(const void *lhs, const void *rhs)
-{
- return strcmp((*(const svn_fs_dirent_t *const *)lhs)->name,
- (*(const svn_fs_dirent_t *const *)rhs)->name);
-}
+} dir_data_t;
/* Utility function to serialize the *ENTRY_P into a the given
* serialization CONTEXT. Return the serialized size of the
@@ -276,91 +202,85 @@ serialize_dir_entry(svn_temp_serializer__context_t *context,
* context to be returned. Allocation will be made form POOL.
*/
static svn_temp_serializer__context_t *
-serialize_dir(apr_hash_t *entries, apr_pool_t *pool)
+serialize_dir(apr_array_header_t *entries, apr_pool_t *pool)
{
- hash_data_t hash_data;
- apr_hash_index_t *hi;
- apr_size_t i = 0;
+ dir_data_t dir_data;
+ int i = 0;
svn_temp_serializer__context_t *context;
/* calculate sizes */
- apr_size_t count = apr_hash_count(entries);
+ int count = entries->nelts;
apr_size_t over_provision = 2 + count / 4;
apr_size_t entries_len = (count + over_provision) * sizeof(svn_fs_dirent_t*);
apr_size_t lengths_len = (count + over_provision) * sizeof(apr_uint32_t);
- /* copy the hash entries to an auxilliary struct of known layout */
- hash_data.count = count;
- hash_data.over_provision = over_provision;
- hash_data.operations = 0;
- hash_data.entries = apr_palloc(pool, entries_len);
- hash_data.lengths = apr_palloc(pool, lengths_len);
+ /* copy the hash entries to an auxiliary struct of known layout */
+ dir_data.count = count;
+ dir_data.over_provision = over_provision;
+ dir_data.operations = 0;
+ dir_data.entries = apr_palloc(pool, entries_len);
+ dir_data.lengths = apr_palloc(pool, lengths_len);
- for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi), ++i)
- hash_data.entries[i] = svn__apr_hash_index_val(hi);
-
- /* sort entry index by ID name */
- qsort(hash_data.entries,
- count,
- sizeof(*hash_data.entries),
- compare_dirent_id_names);
+ for (i = 0; i < count; ++i)
+ dir_data.entries[i] = APR_ARRAY_IDX(entries, i, svn_fs_dirent_t *);
/* Serialize that aux. structure into a new one. Also, provide a good
* estimate for the size of the buffer that we will need. */
- context = svn_temp_serializer__init(&hash_data,
- sizeof(hash_data),
+ context = svn_temp_serializer__init(&dir_data,
+ sizeof(dir_data),
50 + count * 200 + entries_len,
pool);
/* serialize entries references */
svn_temp_serializer__push(context,
- (const void * const *)&hash_data.entries,
+ (const void * const *)&dir_data.entries,
entries_len);
/* serialize the individual entries and their sub-structures */
for (i = 0; i < count; ++i)
serialize_dir_entry(context,
- &hash_data.entries[i],
- &hash_data.lengths[i]);
+ &dir_data.entries[i],
+ &dir_data.lengths[i]);
svn_temp_serializer__pop(context);
/* serialize entries references */
svn_temp_serializer__push(context,
- (const void * const *)&hash_data.lengths,
+ (const void * const *)&dir_data.lengths,
lengths_len);
return context;
}
-/* Utility function to reconstruct a dir entries hash from serialized data
- * in BUFFER and HASH_DATA. Allocation will be made form POOL.
+/* Utility function to reconstruct a dir entries array from serialized data
+ * in BUFFER and DIR_DATA. Allocation will be made form POOL.
*/
-static apr_hash_t *
-deserialize_dir(void *buffer, hash_data_t *hash_data, apr_pool_t *pool)
+static apr_array_header_t *
+deserialize_dir(void *buffer, dir_data_t *dir_data, apr_pool_t *pool)
{
- apr_hash_t *result = svn_hash__make(pool);
+ apr_array_header_t *result
+ = apr_array_make(pool, dir_data->count, sizeof(svn_fs_dirent_t *));
apr_size_t i;
apr_size_t count;
svn_fs_dirent_t *entry;
svn_fs_dirent_t **entries;
/* resolve the reference to the entries array */
- svn_temp_deserializer__resolve(buffer, (void **)&hash_data->entries);
- entries = hash_data->entries;
+ svn_temp_deserializer__resolve(buffer, (void **)&dir_data->entries);
+ entries = dir_data->entries;
/* fixup the references within each entry and add it to the hash */
- for (i = 0, count = hash_data->count; i < count; ++i)
+ for (i = 0, count = dir_data->count; i < count; ++i)
{
svn_temp_deserializer__resolve(entries, (void **)&entries[i]);
- entry = hash_data->entries[i];
+ entry = dir_data->entries[i];
/* pointer fixup */
svn_temp_deserializer__resolve(entry, (void **)&entry->name);
svn_fs_fs__id_deserialize(entry, (svn_fs_id_t **)&entry->id);
/* add the entry to the hash */
- svn_hash_sets(result, entry->name, entry);
+ APR_ARRAY_PUSH(result, svn_fs_dirent_t *) = entry;
}
/* return the now complete hash */
@@ -413,14 +333,63 @@ svn_fs_fs__noderev_deserialize(void *buffer,
/* 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);
svn_temp_deserializer__resolve(noderev, (void **)&noderev->created_path);
}
+svn_error_t *
+svn_fs_fs__serialize_raw_window(void **buffer,
+ apr_size_t *buffer_size,
+ void *item,
+ apr_pool_t *pool)
+{
+ svn_fs_fs__raw_cached_window_t *window = item;
+ svn_stringbuf_t *serialized;
+
+ /* initialize the serialization process and allocate a buffer large
+ * enough to do prevent re-allocations. */
+ svn_temp_serializer__context_t *context =
+ svn_temp_serializer__init(window,
+ sizeof(*window),
+ sizeof(*window) + window->window.len + 16,
+ pool);
+
+ /* serialize the sub-structure(s) */
+ svn_temp_serializer__add_leaf(context,
+ (const void * const *)&window->window.data,
+ window->window.len + 1);
+
+ /* return the serialized result */
+ serialized = svn_temp_serializer__get(context);
+
+ *buffer = serialized->data;
+ *buffer_size = serialized->len;
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__deserialize_raw_window(void **item,
+ void *buffer,
+ apr_size_t buffer_size,
+ apr_pool_t *pool)
+{
+ svn_fs_fs__raw_cached_window_t *window =
+ (svn_fs_fs__raw_cached_window_t *)buffer;
+
+ /* pointer reference fixup */
+ svn_temp_deserializer__resolve(window, (void **)&window->window.data);
+
+ /* done */
+ *item = buffer;
+
+ return SVN_NO_ERROR;
+}
+
/* Utility function to serialize COUNT svn_txdelta_op_t objects
* at OPS in the given serialization CONTEXT.
@@ -434,10 +403,9 @@ serialize_txdelta_ops(svn_temp_serializer__context_t *context,
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.
@@ -551,7 +519,7 @@ svn_fs_fs__deserialize_manifest(void **out,
return SVN_NO_ERROR;
}
-/* Auxilliary structure representing the content of a properties hash.
+/* Auxiliary structure representing the content of a properties hash.
This structure is much easier to (de-)serialize than an apr_hash.
*/
typedef struct properties_data_t
@@ -621,7 +589,7 @@ svn_fs_fs__serialize_properties(void **data,
svn_stringbuf_t *serialized;
apr_size_t i;
- /* create our auxilliary data structure */
+ /* create our auxiliary data structure */
properties.count = apr_hash_count(hash);
properties.keys = apr_palloc(pool, sizeof(const char*) * (properties.count + 1));
properties.values = apr_palloc(pool, sizeof(const char*) * properties.count);
@@ -629,8 +597,8 @@ svn_fs_fs__serialize_properties(void **data,
/* populate it with the hash entries */
for (hi = apr_hash_first(pool, hash), i=0; hi; hi = apr_hash_next(hi), ++i)
{
- properties.keys[i] = svn__apr_hash_index_key(hi);
- properties.values[i] = svn__apr_hash_index_val(hi);
+ properties.keys[i] = apr_hash_this_key(hi);
+ properties.values[i] = apr_hash_this_val(hi);
}
/* serialize it */
@@ -662,7 +630,7 @@ svn_fs_fs__deserialize_properties(void **out,
properties_data_t *properties = (properties_data_t *)data;
size_t i;
- /* de-serialize our auxilliary data structure */
+ /* de-serialize our auxiliary data structure */
svn_temp_deserializer__resolve(properties, (void**)&properties->keys);
svn_temp_deserializer__resolve(properties, (void**)&properties->values);
@@ -670,10 +638,10 @@ svn_fs_fs__deserialize_properties(void **out,
for (i = 0; i < properties->count; ++i)
{
apr_size_t len = properties->keys[i+1] - properties->keys[i] - 1;
- svn_temp_deserializer__resolve((void*)properties->keys,
+ svn_temp_deserializer__resolve(properties->keys,
(void**)&properties->keys[i]);
- deserialize_svn_string((void*)properties->values,
+ deserialize_svn_string(properties->values,
(svn_string_t **)&properties->values[i]);
apr_hash_set(hash,
@@ -785,7 +753,7 @@ return_serialized_dir_context(svn_temp_serializer__context_t *context,
*data = serialized->data;
*data_len = serialized->blocksize;
- ((hash_data_t *)serialized->data)->len = serialized->len;
+ ((dir_data_t *)serialized->data)->len = serialized->len;
return SVN_NO_ERROR;
}
@@ -796,7 +764,7 @@ svn_fs_fs__serialize_dir_entries(void **data,
void *in,
apr_pool_t *pool)
{
- apr_hash_t *dir = in;
+ apr_array_header_t *dir = in;
/* serialize the dir content into a new serialization context
* and return the serialized data */
@@ -812,10 +780,10 @@ svn_fs_fs__deserialize_dir_entries(void **out,
apr_pool_t *pool)
{
/* Copy the _full_ buffer as it also contains the sub-structures. */
- hash_data_t *hash_data = (hash_data_t *)data;
+ dir_data_t *dir_data = (dir_data_t *)data;
/* reconstruct the hash from the serialized data */
- *out = deserialize_dir(hash_data, hash_data, pool);
+ *out = deserialize_dir(dir_data, dir_data, pool);
return SVN_NO_ERROR;
}
@@ -888,22 +856,22 @@ svn_fs_fs__extract_dir_entry(void **out,
void *baton,
apr_pool_t *pool)
{
- const hash_data_t *hash_data = data;
+ const dir_data_t *dir_data = data;
const char* name = baton;
svn_boolean_t found;
/* resolve the reference to the entries array */
const svn_fs_dirent_t * const *entries =
- svn_temp_deserializer__ptr(data, (const void *const *)&hash_data->entries);
+ svn_temp_deserializer__ptr(data, (const void *const *)&dir_data->entries);
/* resolve the reference to the lengths array */
const apr_uint32_t *lengths =
- svn_temp_deserializer__ptr(data, (const void *const *)&hash_data->lengths);
+ svn_temp_deserializer__ptr(data, (const void *const *)&dir_data->lengths);
/* binary search for the desired entry by name */
apr_size_t pos = find_entry((svn_fs_dirent_t **)entries,
name,
- hash_data->count,
+ dir_data->count,
&found);
/* de-serialize that entry or return NULL, if no match has been found */
@@ -942,14 +910,33 @@ slowly_replace_dir_entry(void **data,
apr_pool_t *pool)
{
replace_baton_t *replace_baton = (replace_baton_t *)baton;
- hash_data_t *hash_data = (hash_data_t *)*data;
- apr_hash_t *dir;
+ dir_data_t *dir_data = (dir_data_t *)*data;
+ apr_array_header_t *dir;
+ int idx = -1;
+ svn_fs_dirent_t *entry;
SVN_ERR(svn_fs_fs__deserialize_dir_entries((void **)&dir,
*data,
- hash_data->len,
+ dir_data->len,
pool));
- svn_hash_sets(dir, replace_baton->name, replace_baton->new_entry);
+
+ entry = svn_fs_fs__find_dir_entry(dir, replace_baton->name, &idx);
+
+ /* Replacement or removal? */
+ if (replace_baton->new_entry)
+ {
+ /* Replace ENTRY with / insert the NEW_ENTRY */
+ if (entry)
+ APR_ARRAY_IDX(dir, idx, svn_fs_dirent_t *) = replace_baton->new_entry;
+ else
+ svn_sort__array_insert(dir, &replace_baton->new_entry, idx);
+ }
+ else
+ {
+ /* Remove the old ENTRY. */
+ if (entry)
+ svn_sort__array_delete(dir, idx, 1);
+ }
return svn_fs_fs__serialize_dir_entries(data, data_len, dir, pool);
}
@@ -961,7 +948,7 @@ svn_fs_fs__replace_dir_entry(void **data,
apr_pool_t *pool)
{
replace_baton_t *replace_baton = (replace_baton_t *)baton;
- hash_data_t *hash_data = (hash_data_t *)*data;
+ dir_data_t *dir_data = (dir_data_t *)*data;
svn_boolean_t found;
svn_fs_dirent_t **entries;
apr_uint32_t *lengths;
@@ -971,23 +958,23 @@ svn_fs_fs__replace_dir_entry(void **data,
svn_temp_serializer__context_t *context;
/* after quite a number of operations, let's re-pack everything.
- * This is to limit the number of vasted space as we cannot overwrite
+ * This is to limit the number of wasted space as we cannot overwrite
* existing data but must always append. */
- if (hash_data->operations > 2 + hash_data->count / 4)
+ if (dir_data->operations > 2 + dir_data->count / 4)
return slowly_replace_dir_entry(data, data_len, baton, pool);
/* resolve the reference to the entries array */
entries = (svn_fs_dirent_t **)
- svn_temp_deserializer__ptr((const char *)hash_data,
- (const void *const *)&hash_data->entries);
+ svn_temp_deserializer__ptr(dir_data,
+ (const void *const *)&dir_data->entries);
/* resolve the reference to the lengths array */
lengths = (apr_uint32_t *)
- svn_temp_deserializer__ptr((const char *)hash_data,
- (const void *const *)&hash_data->lengths);
+ svn_temp_deserializer__ptr(dir_data,
+ (const void *const *)&dir_data->lengths);
/* binary search for the desired entry by name */
- pos = find_entry(entries, replace_baton->name, hash_data->count, &found);
+ pos = find_entry(entries, replace_baton->name, dir_data->count, &found);
/* handle entry removal (if found at all) */
if (replace_baton->new_entry == NULL)
@@ -997,14 +984,14 @@ svn_fs_fs__replace_dir_entry(void **data,
/* remove reference to the entry from the index */
memmove(&entries[pos],
&entries[pos + 1],
- sizeof(entries[pos]) * (hash_data->count - pos));
+ sizeof(entries[pos]) * (dir_data->count - pos));
memmove(&lengths[pos],
&lengths[pos + 1],
- sizeof(lengths[pos]) * (hash_data->count - pos));
+ sizeof(lengths[pos]) * (dir_data->count - pos));
- hash_data->count--;
- hash_data->over_provision++;
- hash_data->operations++;
+ dir_data->count--;
+ dir_data->over_provision++;
+ dir_data->operations++;
}
return SVN_NO_ERROR;
@@ -1016,27 +1003,27 @@ svn_fs_fs__replace_dir_entry(void **data,
/* fallback to slow operation if there is no place left to insert an
* new entry to index. That will automatically give add some spare
* entries ("overprovision"). */
- if (hash_data->over_provision == 0)
+ if (dir_data->over_provision == 0)
return slowly_replace_dir_entry(data, data_len, baton, pool);
/* make entries[index] available for pointing to the new entry */
memmove(&entries[pos + 1],
&entries[pos],
- sizeof(entries[pos]) * (hash_data->count - pos));
+ sizeof(entries[pos]) * (dir_data->count - pos));
memmove(&lengths[pos + 1],
&lengths[pos],
- sizeof(lengths[pos]) * (hash_data->count - pos));
+ sizeof(lengths[pos]) * (dir_data->count - pos));
- hash_data->count++;
- hash_data->over_provision--;
- hash_data->operations++;
+ dir_data->count++;
+ dir_data->over_provision--;
+ dir_data->operations++;
}
/* de-serialize the new entry */
entries[pos] = replace_baton->new_entry;
- context = svn_temp_serializer__init_append(hash_data,
+ context = svn_temp_serializer__init_append(dir_data,
entries,
- hash_data->len,
+ dir_data->len,
*data_len,
pool);
serialize_dir_entry(context, &entries[pos], &length);
@@ -1050,15 +1037,45 @@ svn_fs_fs__replace_dir_entry(void **data,
* pointer may no longer point to the entry in that buffer. Therefore,
* re-map it again and store the length value after that. */
- hash_data = (hash_data_t *)*data;
+ dir_data = (dir_data_t *)*data;
lengths = (apr_uint32_t *)
- svn_temp_deserializer__ptr((const char *)hash_data,
- (const void *const *)&hash_data->lengths);
+ svn_temp_deserializer__ptr(dir_data,
+ (const void *const *)&dir_data->lengths);
lengths[pos] = length;
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 +1093,10 @@ serialize_change(svn_temp_serializer__context_t *context,
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 +1118,10 @@ deserialize_change(void *buffer, change_t **change_p)
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.
@@ -1131,18 +1148,15 @@ svn_fs_fs__serialize_changes(void **data,
svn_stringbuf_t *serialized;
int i;
- /* initialize our auxiliary data structure */
+ /* initialize our auxiliary data structure and link it to the
+ * array elements */
changes.count = array->nelts;
- changes.changes = apr_palloc(pool, sizeof(change_t*) * changes.count);
-
- /* populate it with the array elements */
- for (i = 0; i < changes.count; ++i)
- changes.changes[i] = APR_ARRAY_IDX(array, i, change_t*);
+ changes.changes = (change_t **)array->elts;
/* serialize it and all its elements */
context = svn_temp_serializer__init(&changes,
sizeof(changes),
- changes.count * 100,
+ changes.count * 250,
pool);
svn_temp_serializer__push(context,
@@ -1171,19 +1185,21 @@ svn_fs_fs__deserialize_changes(void **out,
{
int i;
changes_data_t *changes = (changes_data_t *)data;
- apr_array_header_t *array = apr_array_make(pool, changes->count,
- sizeof(change_t *));
+ apr_array_header_t *array = apr_array_make(pool, 0, sizeof(change_t *));
/* de-serialize our auxiliary data structure */
svn_temp_deserializer__resolve(changes, (void**)&changes->changes);
/* de-serialize each entry and add it to the array */
for (i = 0; i < changes->count; ++i)
- {
- deserialize_change((void*)changes->changes,
- (change_t **)&changes->changes[i]);
- APR_ARRAY_PUSH(array, change_t *) = changes->changes[i];
- }
+ deserialize_change(changes->changes,
+ (change_t **)&changes->changes[i]);
+
+ /* Use the changes buffer as the array's data buffer
+ * (DATA remains valid for at least as long as POOL). */
+ array->elts = (char *)changes->changes;
+ array->nelts = changes->count;
+ array->nalloc = changes->count;
/* done */
*out = array;
@@ -1252,7 +1268,7 @@ svn_fs_fs__serialize_mergeinfo(void **data,
i = 0;
for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
{
- svn_rangelist_t *ranges = svn__apr_hash_index_val(hi);
+ svn_rangelist_t *ranges = apr_hash_this_val(hi);
for (k = 0; k < ranges->nelts; ++k, ++i)
merges.ranges[i] = *APR_ARRAY_IDX(ranges, k, svn_merge_range_t*);
}
@@ -1274,22 +1290,19 @@ svn_fs_fs__serialize_mergeinfo(void **data,
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);
@@ -1328,7 +1341,7 @@ svn_fs_fs__deserialize_mergeinfo(void **out,
for (k = 0; k < merges->range_counts[i]; ++k, ++n)
APR_ARRAY_PUSH(ranges, svn_merge_range_t*) = &merges->ranges[n];
- svn_temp_deserializer__resolve((void*)merges->keys,
+ svn_temp_deserializer__resolve(merges->keys,
(void**)&merges->keys[i]);
apr_hash_set(mergeinfo, merges->keys[i], merges->key_lengths[i], ranges);
}