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
     {