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 2011/02/09 03:04:07 UTC
svn commit: r1068739 - in
/subversion/branches/integrate-cache-item-serialization/subversion:
libsvn_fs_fs/caching.c libsvn_fs_fs/id.c libsvn_fs_fs/temp_serializer.c
libsvn_fs_fs/temp_serializer.h libsvn_subr/svn_temp_serializer.c
Author: stefan2
Date: Wed Feb 9 02:04:07 2011
New Revision: 1068739
URL: http://svn.apache.org/viewvc?rev=1068739&view=rev
Log:
Well, the cherry-picking merge with lots of tree conflicts did not really work well.
Fix all the artifacts.
* subversion/libsvn_fs_fs/temp_serializer.c,
subversion/libsvn_fs_fs/temp_serializer.h: add missing files
* subversion/libsvn_fs_fs/caching.c,
subversion/libsvn_fs_fs/id.c
subversion/libsvn_fs_fs/svn_temp_serializer.c: fix the conflict resolution
Added:
subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/temp_serializer.c
subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/temp_serializer.h
Modified:
subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/caching.c
subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/id.c
subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/svn_temp_serializer.c
Modified: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/caching.c?rev=1068739&r1=1068738&r2=1068739&view=diff
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/caching.c Wed Feb 9 02:04:07 2011
@@ -88,23 +88,23 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
* default pool size is 8192, so about a hundred should fit
* comfortably. */
if (svn_fs__get_global_membuffer_cache())
- SVN_ERR(svn_cache__create_membuffer_cache(&(ffd->rev_root_id_cache),
- svn_fs__get_global_membuffer_cache(),
- svn_fs_fs__serialize_id,
- svn_fs_fs__deserialize_id,
- sizeof(svn_revnum_t),
- apr_pstrcat(pool, prefix, "RRI",
- (char *)NULL),
- fs->pool));
+ SVN_ERR(svn_cache__create_membuffer_cache(&(ffd->rev_root_id_cache),
+ svn_fs__get_global_membuffer_cache(),
+ svn_fs_fs__serialize_id,
+ svn_fs_fs__deserialize_id,
+ sizeof(svn_revnum_t),
+ apr_pstrcat(pool, prefix, "RRI",
+ (char *)NULL),
+ fs->pool));
else
- SVN_ERR(svn_cache__create_inprocess(&(ffd->rev_root_id_cache),
- svn_fs_fs__serialize_id,
- svn_fs_fs__deserialize_id,
- sizeof(svn_revnum_t),
- 1, 100, FALSE, fs->pool));
+ SVN_ERR(svn_cache__create_inprocess(&(ffd->rev_root_id_cache),
+ svn_fs_fs__serialize_id,
+ svn_fs_fs__deserialize_id,
+ sizeof(svn_revnum_t),
+ 1, 100, FALSE, fs->pool));
if (! no_handler)
- SVN_ERR(svn_cache__set_error_handler(ffd->rev_root_id_cache,
- warn_on_cache_errors, fs, pool));
+ SVN_ERR(svn_cache__set_error_handler(ffd->rev_root_id_cache,
+ warn_on_cache_errors, fs, pool));
/* Rough estimate: revision DAG nodes have size around 320 bytes, so
Modified: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/id.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/id.c?rev=1068739&r1=1068738&r2=1068739&view=diff
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/id.c (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/id.c Wed Feb 9 02:04:07 2011
@@ -187,6 +187,7 @@ svn_fs_fs__id_txn_create(const char *nod
pvt->txn_id = apr_pstrdup(pool, txn_id);
pvt->rev = SVN_INVALID_REVNUM;
pvt->offset = -1;
+
id->vtable = &id_vtable;
id->fsap_data = pvt;
return id;
@@ -208,6 +209,7 @@ svn_fs_fs__id_rev_create(const char *nod
pvt->txn_id = NULL;
pvt->rev = rev;
pvt->offset = offset;
+
id->vtable = &id_vtable;
id->fsap_data = pvt;
return id;
@@ -226,6 +228,7 @@ svn_fs_fs__id_copy(const svn_fs_id_t *id
new_pvt->txn_id = pvt->txn_id ? apr_pstrdup(pool, pvt->txn_id) : NULL;
new_pvt->rev = pvt->rev;
new_pvt->offset = pvt->offset;
+
new_id->vtable = &id_vtable;
new_id->fsap_data = new_pvt;
return new_id;
Added: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/temp_serializer.c?rev=1068739&view=auto
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/temp_serializer.c (added)
+++ subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/temp_serializer.c Wed Feb 9 02:04:07 2011
@@ -0,0 +1,679 @@
+/* temp_serializer.c: serialization functions for caching of FSFS structures
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#include <apr_pools.h>
+
+#include "svn_pools.h"
+#include "svn_hash.h"
+
+#include "id.h"
+#include "svn_fs.h"
+
+#include "private/svn_fs_util.h"
+#include "private/svn_temp_serializer.h"
+
+#include "temp_serializer.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.
+ *
+ * Numbers will be stored in 7 bits / byte and using byte values above
+ * 32 (' ') to make them combinable with other string by simply separating
+ * individual parts with spaces.
+ */
+static char*
+encode_number(apr_int64_t number, char *key_buffer)
+{
+ /* encode the sign in the first byte */
+ if (number < 0)
+ {
+ number = -number;
+ *key_buffer = (number & 63) + ' ' + 65;
+ }
+ else
+ *key_buffer = (number & 63) + ' ' + 1;
+ number /= 64;
+
+ /* write 7 bits / byte until no significant bits are left */
+ while (number)
+ {
+ *++key_buffer = (number & 127) + ' ' + 1;
+ number /= 128;
+ }
+
+ /* return the last written position */
+ return key_buffer;
+}
+
+/* Prepend the NUMBER to the STRING in a space efficient way that no other
+ * (number,string) combination can produce the same result.
+ * Allocate temporaries as well as the result from POOL.
+ */
+const char*
+svn_fs_fs__combine_number_and_string(apr_int64_t number,
+ const char *string,
+ apr_pool_t *pool)
+{
+ apr_size_t len = strlen(string);
+
+ /* number part requires max. 10x7 bits + 1 space.
+ * Add another 1 for the terminal 0 */
+ char *key_buffer = apr_palloc(pool, len + 12);
+ const char *key = key_buffer;
+
+ /* Prepend the number to the string and separate them by space. No other
+ * number can result in the same prefix, no other string in the same
+ * postfix nor can the boundary between them be ambiguous. */
+ key_buffer = encode_number(number, key_buffer);
+ *++key_buffer = ' ';
+ memcpy(++key_buffer, string, len+1);
+
+ /* return the start of the key */
+ return key;
+}
+
+/* Combine the numbers A and B a space efficient way that no other
+ * combination of numbers can produce the same result.
+ * Allocate temporaries as well as the result from POOL.
+ */
+const char*
+svn_fs_fs__combine_two_numbers(apr_int64_t a,
+ apr_int64_t b,
+ apr_pool_t *pool)
+{
+ /* encode numbers as 2x 10x7 bits + 1 space + 1 terminating \0*/
+ char *key_buffer = apr_palloc(pool, 22);
+ const char *key = key_buffer;
+
+ /* combine the numbers. Since the separator is disjoint from any part
+ * of the encoded numbers, there is no other combination that can yield
+ * the same result */
+ key_buffer = encode_number(a, key_buffer);
+ *++key_buffer = ' ';
+ key_buffer = encode_number(b, ++key_buffer);
+ *++key_buffer = '\0';
+
+ /* return the start of the key */
+ return key;
+}
+
+/* Utility function to serialize string S in the given serialization CONTEXT.
+ */
+static void
+serialize_svn_string(svn_temp_serializer__context_t *context,
+ const svn_string_t * const *s)
+{
+ const svn_string_t *string = *s;
+
+ /* Nothing to do for NULL string references. */
+ if (string == NULL)
+ return;
+
+ svn_temp_serializer__push(context,
+ (const void * const *)s,
+ sizeof(*string));
+
+ /* 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);
+
+ /* 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.
+ */
+static void
+deserialize_svn_string(void *buffer, svn_string_t **string)
+{
+ svn_temp_deserializer__resolve(buffer, (void **)string);
+ if (*string == NULL)
+ return;
+
+ 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 * const *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.
+ */
+static void
+serialize_representation(svn_temp_serializer__context_t *context,
+ representation_t * const *representation)
+{
+ const representation_t * rep = *representation;
+ if (rep == NULL)
+ 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);
+}
+
+/* auxilliary structure representing the content of a directory hash */
+typedef struct hash_data_t
+{
+ /* number of entries in the directory */
+ apr_size_t count;
+
+ /* reference to the entries */
+ svn_fs_dirent_t **entries;
+} 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);
+}
+
+/* Utility function to serialize the ENTRIES into a new serialization
+ * 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)
+{
+ hash_data_t hash_data;
+ apr_hash_index_t *hi;
+ apr_size_t i = 0;
+ svn_temp_serializer__context_t *context;
+
+ /* calculate sizes */
+ apr_size_t count = apr_hash_count(entries);
+ apr_size_t entries_len = count * sizeof(svn_fs_dirent_t*);
+
+ /* copy the hash entries to an auxilliary struct of known layout */
+ hash_data.count = count;
+ hash_data.entries = apr_palloc(pool, entries_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);
+
+ /* 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),
+ 50 + count * 200 + entries_len,
+ pool);
+
+ /* serialize entries references */
+ svn_temp_serializer__push(context,
+ (const void * const *)&hash_data.entries,
+ entries_len);
+
+ /* serialize the individual entries and their sub-structures */
+ for (i = 0; i < count; ++i)
+ {
+ svn_fs_dirent_t **entry = &hash_data.entries[i];
+ svn_temp_serializer__push(context,
+ (const void * const *)entry,
+ sizeof(svn_fs_dirent_t));
+
+ svn_fs_fs__id_serialize(context, &(*entry)->id);
+ svn_temp_serializer__add_string(context, &(*entry)->name);
+
+ svn_temp_serializer__pop(context);
+ }
+
+ return context;
+}
+
+/* Utility function to reconstruct a dir entries hash from serialized data
+ * in BUFFER and HASH_DATA. Allocation will be made form POOL.
+ */
+static apr_hash_t *
+deserialize_dir(void *buffer, hash_data_t *hash_data, apr_pool_t *pool)
+{
+ apr_hash_t *result = apr_hash_make(pool);
+ 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;
+
+ /* fixup the references within each entry and add it to the hash */
+ for (i = 0, count = hash_data->count; i < count; ++i)
+ {
+ svn_temp_deserializer__resolve(entries, (void **)&entries[i]);
+ entry = hash_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 */
+ apr_hash_set(result, entry->name, APR_HASH_KEY_STRING, entry);
+ }
+
+ /* return the now complete hash */
+ return result;
+}
+
+/* Serialize a NODEREV_P within the serialization CONTEXT.
+ */
+void
+svn_fs_fs__noderev_serialize(svn_temp_serializer__context_t *context,
+ node_revision_t * const *noderev_p)
+{
+ const node_revision_t *noderev = *noderev_p;
+ if (noderev == NULL)
+ return;
+
+ /* serialize the representation struct itself */
+ svn_temp_serializer__push(context,
+ (const void * const *)noderev_p,
+ sizeof(*noderev));
+
+ /* serialize sub-structures */
+ svn_fs_fs__id_serialize(context, &noderev->id);
+ svn_fs_fs__id_serialize(context, &noderev->predecessor_id);
+ serialize_representation(context, &noderev->prop_rep);
+ serialize_representation(context, &noderev->data_rep);
+
+ svn_temp_serializer__add_string(context, &noderev->copyfrom_path);
+ svn_temp_serializer__add_string(context, &noderev->copyroot_path);
+ svn_temp_serializer__add_string(context, &noderev->created_path);
+
+ /* return to the caller's nesting level */
+ svn_temp_serializer__pop(context);
+}
+
+
+/* Deserialize a NODEREV_P within the BUFFER.
+ */
+void
+svn_fs_fs__noderev_deserialize(void *buffer,
+ node_revision_t **noderev_p)
+{
+ node_revision_t *noderev;
+
+ /* fixup the reference to the representation itself,
+ * if this is part of a parent structure. */
+ if (buffer != *noderev_p)
+ svn_temp_deserializer__resolve(buffer, (void **)noderev_p);
+
+ noderev = *noderev_p;
+ if (noderev == NULL)
+ return;
+
+ /* 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->copyfrom_path);
+ svn_temp_deserializer__resolve(noderev, (void **)&noderev->copyroot_path);
+ svn_temp_deserializer__resolve(noderev, (void **)&noderev->created_path);
+}
+
+
+/* Utility function to serialize COUNT svn_txdelta_op_t objects
+ * at OPS in the given serialization CONTEXT.
+ */
+static void
+serialize_txdelta_ops(svn_temp_serializer__context_t *context,
+ const svn_txdelta_op_t * const * ops,
+ apr_size_t count)
+{
+ if (*ops == NULL)
+ 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);
+}
+
+/* Utility function to serialize W in the given serialization CONTEXT.
+ */
+static void
+serialize_txdeltawindow(svn_temp_serializer__context_t *context,
+ svn_txdelta_window_t * const * w)
+{
+ svn_txdelta_window_t *window = *w;
+
+ /* serialize the window struct itself */
+ svn_temp_serializer__push(context,
+ (const void * const *)w,
+ sizeof(svn_txdelta_window_t));
+
+ /* serialize its sub-structures */
+ serialize_txdelta_ops(context, &window->ops, window->num_ops);
+ serialize_svn_string(context, &window->new_data);
+
+ svn_temp_serializer__pop(context);
+}
+
+/* Implements svn_cache__serialize_fn_t for svn_fs_fs__txdelta_cached_window_t
+ */
+svn_error_t *
+svn_fs_fs__serialize_txdelta_window(char **buffer,
+ apr_size_t *buffer_size,
+ void *item,
+ apr_pool_t *pool)
+{
+ svn_fs_fs__txdelta_cached_window_t *window_info = item;
+ svn_stringbuf_t *serialized;
+
+ /* initialize the serialization process and allocate a buffer large
+ * enough to do without the need of re-allocations in most cases. */
+ apr_size_t text_len = window_info->window->new_data
+ ? window_info->window->new_data->len
+ : 0;
+ svn_temp_serializer__context_t *context =
+ svn_temp_serializer__init(window_info,
+ sizeof(*window_info),
+ 500 + text_len,
+ pool);
+
+ /* serialize the sub-structure(s) */
+ serialize_txdeltawindow(context, &window_info->window);
+
+ /* return the serialized result */
+ serialized = svn_temp_serializer__get(context);
+
+ *buffer = serialized->data;
+ *buffer_size = serialized->len;
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements svn_cache__deserialize_fn_t for
+ * svn_fs_fs__txdelta_cached_window_t.
+ */
+svn_error_t *
+svn_fs_fs__deserialize_txdelta_window(void **item,
+ const char *buffer,
+ apr_size_t buffer_size,
+ apr_pool_t *pool)
+{
+ svn_txdelta_window_t *window;
+
+ /* Copy the _full_ buffer as it also contains the sub-structures. */
+ svn_fs_fs__txdelta_cached_window_t *window_info =
+ (svn_fs_fs__txdelta_cached_window_t *)buffer;
+
+ /* pointer reference fixup */
+ svn_temp_deserializer__resolve(window_info,
+ (void **)&window_info->window);
+ window = window_info->window;
+
+ svn_temp_deserializer__resolve(window, (void **)&window->ops);
+
+ deserialize_svn_string(window, (svn_string_t**)&window->new_data);
+
+ /* done */
+ *item = window_info;
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements svn_cache__serialize_fn_t for manifests.
+ */
+svn_error_t *
+svn_fs_fs__serialize_manifest(char **data,
+ apr_size_t *data_len,
+ void *in,
+ apr_pool_t *pool)
+{
+ apr_array_header_t *manifest = in;
+
+ *data_len = sizeof(apr_off_t) *manifest->nelts;
+ *data = apr_palloc(pool, *data_len);
+ memcpy(*data, manifest->elts, *data_len);
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements svn_cache__deserialize_fn_t for manifests.
+ */
+svn_error_t *
+svn_fs_fs__deserialize_manifest(void **out,
+ const char *data,
+ apr_size_t data_len,
+ apr_pool_t *pool)
+{
+ apr_array_header_t *manifest = apr_array_make(pool, 1, sizeof(apr_off_t));
+
+ manifest->nelts = data_len / sizeof(apr_off_t);
+ manifest->nalloc = data_len / sizeof(apr_off_t);
+ manifest->elts = (char*)data;
+
+ *out = manifest;
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements svn_cache__serialize_fn_t for svn_fs_id_t
+ */
+svn_error_t *
+svn_fs_fs__serialize_id(char **data,
+ apr_size_t *data_len,
+ void *in,
+ apr_pool_t *pool)
+{
+ const svn_fs_id_t *id = in;
+ svn_stringbuf_t *serialized;
+
+ /* create an (empty) serialization context with plenty of buffer space */
+ svn_temp_serializer__context_t *context =
+ svn_temp_serializer__init(NULL, 0, 250, pool);
+
+ /* serialize the id */
+ svn_fs_fs__id_serialize(context, &id);
+
+ /* return serialized data */
+ serialized = svn_temp_serializer__get(context);
+ *data = serialized->data;
+ *data_len = serialized->len;
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements svn_cache__deserialize_fn_t for svn_fs_id_t
+ */
+svn_error_t *
+svn_fs_fs__deserialize_id(void **out,
+ const char *data,
+ apr_size_t data_len,
+ apr_pool_t *pool)
+{
+ /* Copy the _full_ buffer as it also contains the sub-structures. */
+ svn_fs_id_t *id = (svn_fs_id_t *)data;
+
+ /* fixup of all pointers etc. */
+ svn_fs_fs__id_deserialize(id, &id);
+
+ /* done */
+ *out = id;
+ return SVN_NO_ERROR;
+}
+
+/** Caching node_revision_t objects. **/
+
+/* Implements svn_cache__serialize_fn_t for node_revision_t.
+ */
+svn_error_t *
+svn_fs_fs__serialize_node_revision(char **buffer,
+ apr_size_t *buffer_size,
+ void *item,
+ apr_pool_t *pool)
+{
+ svn_stringbuf_t *serialized;
+ node_revision_t *noderev = item;
+
+ /* create an (empty) serialization context with plenty of buffer space */
+ svn_temp_serializer__context_t *context =
+ svn_temp_serializer__init(NULL, 0, 503, pool);
+
+ /* serialize the noderev */
+ svn_fs_fs__noderev_serialize(context, &noderev);
+
+ /* return serialized data */
+ serialized = svn_temp_serializer__get(context);
+ *buffer = serialized->data;
+ *buffer_size = serialized->len;
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements svn_cache__deserialize_fn_t for node_revision_t
+ */
+svn_error_t *
+svn_fs_fs__deserialize_node_revision(void **item,
+ const char *buffer,
+ apr_size_t buffer_size,
+ apr_pool_t *pool)
+{
+ /* Copy the _full_ buffer as it also contains the sub-structures. */
+ node_revision_t *noderev = (node_revision_t *)buffer;
+
+ /* fixup of all pointers etc. */
+ svn_fs_fs__noderev_deserialize(noderev, &noderev);
+
+ /* done */
+ *item = noderev;
+ return SVN_NO_ERROR;
+}
+
+/* Implements svn_cache__serialize_func_t for a directory contents hash.
+ */
+svn_error_t *
+svn_fs_fs__serialize_dir_entries(char **data,
+ apr_size_t *data_len,
+ void *in,
+ apr_pool_t *pool)
+{
+ apr_hash_t *dir = in;
+
+ /* serialize the dir content into a new serialization context */
+ svn_temp_serializer__context_t *context = serialize_dir(dir, pool);
+
+ /* return serialized data */
+ svn_stringbuf_t *serialized = svn_temp_serializer__get(context);
+ *data = serialized->data;
+ *data_len = serialized->len;
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements svn_cache__deserialize_func_t for a directory contents hash
+ */
+svn_error_t *
+svn_fs_fs__deserialize_dir_entries(void **out,
+ const char *data,
+ apr_size_t data_len,
+ apr_pool_t *pool)
+{
+ /* Copy the _full_ buffer as it also contains the sub-structures. */
+ hash_data_t *hash_data = (hash_data_t *)data;
+
+ /* reconstruct the hash from the serialized data */
+ *out = deserialize_dir(hash_data, hash_data, pool);
+
+ return SVN_NO_ERROR;
+}
+
Added: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/temp_serializer.h?rev=1068739&view=auto
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/temp_serializer.h (added)
+++ subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/temp_serializer.h Wed Feb 9 02:04:07 2011
@@ -0,0 +1,169 @@
+/* temp_serializer.h : serialization functions for caching of FSFS structures
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#ifndef SVN_LIBSVN_FS__TEMP_SERIALIZER_H
+#define SVN_LIBSVN_FS__TEMP_SERIALIZER_H
+
+#include "fs.h"
+
+/**
+ * Prepend the @a number to the @c string in a space efficient way that
+ * no other (number,string) combination can produce the same result.
+ * Allocate temporaries as well as the result from @a pool.
+ */
+const char*
+svn_fs_fs__combine_number_and_string(apr_int64_t number,
+ const char *string,
+ apr_pool_t *pool);
+
+/**
+ * Combine the numbers @a a and @a b a space efficient way that no other
+ * combination of numbers can produce the same result.
+ * Allocate temporaries as well as the result from @a pool.
+ */
+const char*
+svn_fs_fs__combine_two_numbers(apr_int64_t a,
+ apr_int64_t b,
+ apr_pool_t *pool);
+
+/**
+ * Serialize a @a noderev_p within the serialization @a context.
+ */
+void
+svn_fs_fs__noderev_serialize(struct svn_temp_serializer__context_t *context,
+ node_revision_t * const *noderev_p);
+
+/**
+ * Deserialize a @a noderev_p within the @a buffer.
+ */
+void
+svn_fs_fs__noderev_deserialize(void *buffer,
+ node_revision_t **noderev_p);
+
+/**
+ * @ref svn_txdelta_window_t is not sufficient for caching the data it
+ * represents because data read process needs auxilliary information.
+ */
+typedef struct
+{
+ /* the txdelta window information cached / to be cached */
+ svn_txdelta_window_t *window;
+
+ /* the revision file read pointer position right after reading the window */
+ apr_off_t end_offset;
+} svn_fs_fs__txdelta_cached_window_t;
+
+/**
+ * Implements @ref svn_cache__serialize_fn_t for
+ * @ref svn_fs_fs__txdelta_cached_window_t.
+ */
+svn_error_t *
+svn_fs_fs__serialize_txdelta_window(char **buffer,
+ apr_size_t *buffer_size,
+ void *item,
+ apr_pool_t *pool);
+
+/**
+ * Implements @ref svn_cache__deserialize_fn_t for
+ * @ref svn_fs_fs__txdelta_cached_window_t.
+ */
+svn_error_t *
+svn_fs_fs__deserialize_txdelta_window(void **item,
+ const char *buffer,
+ apr_size_t buffer_size,
+ apr_pool_t *pool);
+
+/**
+ * Implements @ref svn_cache__serialize_fn_t for manifests
+ * (@a apr_array_header_t).
+ */
+svn_error_t *
+svn_fs_fs__serialize_manifest(char **data,
+ apr_size_t *data_len,
+ void *in,
+ apr_pool_t *pool);
+
+/**
+ * Implements @ref svn_cache__deserialize_fn_t for manifests
+ * (@a apr_array_header_t).
+ */
+svn_error_t *
+svn_fs_fs__deserialize_manifest(void **out,
+ const char *data,
+ apr_size_t data_len,
+ apr_pool_t *pool);
+
+/**
+ * Implements @ref svn_cache__serialize_fn_t for @ref svn_fs_id_t
+ */
+svn_error_t *
+svn_fs_fs__serialize_id(char **data,
+ apr_size_t *data_len,
+ void *in,
+ apr_pool_t *pool);
+
+/**
+ * Implements @ref svn_cache__deserialize_fn_t for @ref svn_fs_id_t
+ */
+svn_error_t *
+svn_fs_fs__deserialize_id(void **out,
+ const char *data,
+ apr_size_t data_len,
+ apr_pool_t *pool);
+
+/**
+ * Implements @ref svn_cache__serialize_fn_t for @ref node_revision_t
+ */
+svn_error_t *
+svn_fs_fs__serialize_node_revision(char **buffer,
+ apr_size_t *buffer_size,
+ void *item,
+ apr_pool_t *pool);
+
+/**
+ * Implements @ref svn_cache__deserialize_fn_t for @ref node_revision_t
+ */
+svn_error_t *
+svn_fs_fs__deserialize_node_revision(void **item,
+ const char *buffer,
+ apr_size_t buffer_size,
+ apr_pool_t *pool);
+
+/**
+ * Implements @ref svn_cache__serialize_func_t for a directory contents hash
+ */
+svn_error_t *
+svn_fs_fs__serialize_dir_entries(char **data,
+ apr_size_t *data_len,
+ void *in,
+ apr_pool_t *pool);
+
+/**
+ * Implements @ref svn_cache__deserialize_func_t for a directory contents hash
+ */
+svn_error_t *
+svn_fs_fs__deserialize_dir_entries(void **out,
+ const char *data,
+ apr_size_t data_len,
+ apr_pool_t *pool);
+
+#endif
Modified: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/svn_temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/svn_temp_serializer.c?rev=1068739&r1=1068738&r2=1068739&view=diff
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/svn_temp_serializer.c (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/svn_temp_serializer.c Wed Feb 9 02:04:07 2011
@@ -1,4 +1,3 @@
-<<<<<<< .working
/*
* svn_serializer.c: implement the tempoary structure serialization API
*
@@ -59,7 +58,7 @@ typedef struct source_stack_t
/* Serialization context info. It basically consists of the buffer holding
* the serialized result and the stack of source structure information.
*/
-struct svn__temp_serializer__context_t
+struct svn_temp_serializer__context_t
{
/* allocations are made from this pool */
apr_pool_t *pool;
@@ -78,7 +77,7 @@ struct svn__temp_serializer__context_t
* guarantees.
*/
static void
-align_buffer_end(svn__temp_serializer__context_t *context)
+align_buffer_end(svn_temp_serializer__context_t *context)
{
apr_size_t current_len = context->buffer->len;
apr_size_t aligned_len = APR_ALIGN_DEFAULT(current_len);
@@ -96,30 +95,39 @@ align_buffer_end(svn__temp_serializer__c
* re-allocations during the serialization process. All allocations will
* be made from POOL.
*/
-svn__temp_serializer__context_t *
-svn__temp_serializer__init(const void *source_struct,
- apr_size_t struct_size,
- apr_size_t suggested_buffer_size,
- apr_pool_t *pool)
+svn_temp_serializer__context_t *
+svn_temp_serializer__init(const void *source_struct,
+ apr_size_t struct_size,
+ apr_size_t suggested_buffer_size,
+ apr_pool_t *pool)
{
/* select a meaningful initial memory buffer capacity */
apr_size_t init_size = suggested_buffer_size < struct_size
? struct_size
: suggested_buffer_size;
- /* create the serialization context and initialize it, including the
- * structure stack */
- svn__temp_serializer__context_t *context = apr_palloc(pool,
- sizeof(*context));
+ /* create the serialization context and initialize it */
+ svn_temp_serializer__context_t *context = apr_palloc(pool, sizeof(*context));
context->pool = pool;
context->buffer = svn_stringbuf_create_ensure(init_size, pool);
- context->source = apr_palloc(pool, sizeof(*context->source));
- context->source->source_struct = source_struct;
- context->source->target_offset = 0;
- context->source->upper = NULL;
- /* serialize, i.e. append, the content of the first structure */
- svn_stringbuf_appendbytes(context->buffer, source_struct, struct_size);
+ /* If a source struct has been given, make it the root struct. */
+ if (source_struct)
+ {
+ context->source = apr_palloc(pool, sizeof(*context->source));
+ context->source->source_struct = source_struct;
+ context->source->target_offset = 0;
+ context->source->upper = NULL;
+
+ /* serialize, i.e. append, the content of the first structure */
+ svn_stringbuf_appendbytes(context->buffer, source_struct, struct_size);
+ }
+ else
+ {
+ /* The root struct will be set with the first push() op, or not at all
+ * (in case of a plain string). */
+ context->source = NULL;
+ }
/* done */
return context;
@@ -130,25 +138,34 @@ svn__temp_serializer__init(const void *s
* right after this function call.
*/
static void
-store_current_end_pointer(svn__temp_serializer__context_t *context,
+store_current_end_pointer(svn_temp_serializer__context_t *context,
const void * const * source_pointer)
{
- /* relative position of the serialized pointer to the begin of the buffer */
- apr_size_t offset = (const char *)source_pointer
- - (const char *)context->source->source_struct
- + context->source->target_offset;
+ apr_size_t ptr_offset;
+ apr_size_t *target_ptr;
- /* use the serialized pointer as a storage for the offset */
- apr_size_t *target_string_ptr =
- (apr_size_t*)(context->buffer->data + offset);
+ /* if *source_pointer is the root struct, there will be no parent structure
+ * to relate it to */
+ if (context->source == NULL)
+ return;
+
+ /* position of the serialized pointer relative to the begin of the buffer */
+ ptr_offset = (const char *)source_pointer
+ - (const char *)context->source->source_struct
+ + context->source->target_offset;
/* the offset must be within the serialized data. Otherwise, you forgot
* to serialize the respective sub-struct. */
- assert(context->buffer->len > offset);
+ assert(context->buffer->len > ptr_offset);
+
+ /* use the serialized pointer as a storage for the offset */
+ target_ptr = (apr_size_t*)(context->buffer->data + ptr_offset);
/* store the current buffer length because that's where we will append
* the serialized data of the sub-struct or string */
- *target_string_ptr = *source_pointer == NULL ? 0 : context->buffer->len;
+ *target_ptr = *source_pointer == NULL
+ ? 0
+ : context->buffer->len - context->source->target_offset;
}
/* Begin serialization of a referenced sub-structure within the
@@ -158,7 +175,6 @@ store_current_end_pointer(svn__temp_seri
* result of sizeof() of the actual structure.
*/
void
-
svn_temp_serializer__push(svn_temp_serializer__context_t *context,
const void * const * source_struct,
apr_size_t struct_size)
@@ -223,7 +239,7 @@ svn_temp_serializer__add_string(svn_temp
* useful if the pointer is not NULL in the source structure.
*/
void
-svn_temp_serializer__set_NULL(svn_temp_serializer__context_t *context,
+svn_temp_serializer__set_null(svn_temp_serializer__context_t *context,
const void * const * ptr)
{
apr_size_t offset;
@@ -231,7 +247,7 @@ svn_temp_serializer__set_NULL(svn_temp_s
/* there must be a parent structure */
assert(context->source);
- /* relative position of the serialized pointer to the begin of the buffer */
+ /* position of the serialized pointer relative to the begin of the buffer */
offset = (const char *)ptr
- (const char *)context->source->source_struct
+ context->source->target_offset;
@@ -263,6 +279,7 @@ svn_temp_deserializer__resolve(void *buf
{
/* replace the offset in *ptr with the pointer to buffer[*ptr] */
(*(const char **)ptr) = (const char*)buffer + (apr_size_t)*ptr;
+ assert(*ptr > buffer);
}
else
{