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 02:35:50 UTC

svn commit: r1068724 - in /subversion/branches/integrate-cache-item-serialization: ./ subversion/include/private/ subversion/libsvn_fs_fs/ subversion/libsvn_subr/ subversion/tests/libsvn_subr/

Author: stefan2
Date: Wed Feb  9 01:35:49 2011
New Revision: 1068724

URL: http://svn.apache.org/viewvc?rev=1068724&view=rev
Log:
Introduce a simple serialization framework that basically concatenates
all (sub-)structs of a given item and replaces pointers with offsets.

Use that to switch cache interface from item duplication to serialization 
into a buffer & back and allow the new membuffer cache to be used on any
cacheable item.

Where feasible, move the serialization code to svn_temp_serializer.*

Merged revisions from /branches/performance:
981090, 981189, 981194, 983398, 983406, 983474, 983488, 983490, 985603, 
986521, 986608, 986832, 987865, 987868, 987869, 987872, 987886, 988898, 
990533, 990535, 990536, 1029229

Partially merged:
981204, 981665, 981828

Added:
    subversion/branches/integrate-cache-item-serialization/subversion/include/private/svn_temp_serializer.h   (contents, props changed)
      - copied, changed from r981189, subversion/branches/performance/subversion/include/private/svn_temp_serializer.h
    subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/svn_temp_serializer.c   (contents, props changed)
      - copied, changed from r981189, subversion/branches/performance/subversion/libsvn_subr/svn_temp_serializer.c
Modified:
    subversion/branches/integrate-cache-item-serialization/   (props changed)
    subversion/branches/integrate-cache-item-serialization/subversion/include/private/svn_cache.h
    subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/caching.c
    subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/dag.c
    subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/dag.h
    subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/fs_fs.c
    subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/fs_fs.h
    subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/id.c
    subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/id.h
    subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/tree.c
    subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/cache-inprocess.c
    subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/cache-memcache.c
    subversion/branches/integrate-cache-item-serialization/subversion/tests/libsvn_subr/cache-test.c

Propchange: subversion/branches/integrate-cache-item-serialization/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Feb  9 01:35:49 2011
@@ -27,7 +27,7 @@
 /subversion/branches/log-g-performance:870941-871032
 /subversion/branches/merge-skips-obstructions:874525-874615
 /subversion/branches/nfc-nfd-aware-client:870276,870376
-/subversion/branches/performance:979193,980118,981087,981684,982043,982355,983764,983766,984927,984973,984984,985014,985037,985046,985472,985477,985482,985500,985606,985669,986453,987888,987893,988319,990541,990568,990572,990600,990759,992899,992911,993127,993141,994956,995478,995507,995603,998858,999098,1001413,1001417,1004291,1022668,1022670,1022676,1022715,1022719,1025660,1025672,1027193,1027203,1027206,1027214,1027227,1028077,1028092,1028094,1028104,1028107,1028111,1028354,1029038,1029042-1029043,1029078,1029080,1029090,1029092-1029093,1029111,1029151,1029158,1029232,1029335,1029340,1029342,1029344,1030763,1030827,1031203,1031235,1032285,1032333,1033040,1033057,1033294,1035869,1039511,1043705,1053735,1056015,1066452,1067683
+/subversion/branches/performance:979193,980118,981087,981090,981189,981194,981684,982043,982355,983398,983406,983474,983488,983490,983764,983766,984927,984973,984984,985014,985037,985046,985472,985477,985482,985500,985603,985606,985669,986453,986521,986608,986832,987865,987868-987869,987872,987886,987888,987893,988319,988898,990533,990535-990536,990541,990568,990572,990600,990759,992899,992911,993127,993141,994956,995478,995507,995603,998858,999098,1001413,1001417,1004291,1022668,1022670,1022676,1022715,1022719,1025660,1025672,1027193,1027203,1027206,1027214,1027227,1028077,1028092,1028094,1028104,1028107,1028111,1028354,1029038,1029042-1029043,1029078,1029080,1029090,1029092-1029093,1029111,1029151,1029158,1029229,1029232,1029335,1029340,1029342,1029344,1030763,1030827,1031203,1031235,1032285,1032333,1033040,1033057,1033294,1035869,1039511,1043705,1053735,1056015,1066452,1067683
 /subversion/branches/py-tests-as-modules:956579-1033052
 /subversion/branches/ra_serf-digest-authn:875693-876404
 /subversion/branches/reintegrate-improvements:873853-874164

Modified: subversion/branches/integrate-cache-item-serialization/subversion/include/private/svn_cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/include/private/svn_cache.h?rev=1068724&r1=1068723&r2=1068724&view=diff
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/include/private/svn_cache.h (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/include/private/svn_cache.h Wed Feb  9 01:35:49 2011
@@ -120,7 +120,7 @@ typedef struct svn_cache__t svn_cache__t
  * for all of its storage needs.  The elements in the cache will be
  * indexed by keys of length @a klen, which may be APR_HASH_KEY_STRING
  * if they are strings.  Cached values will be copied in and out of
- * the cache using @a dup_func.
+ * the cache using @a serialize_func and @a deserialize_func, respectively.
  *
  * The cache stores up to @a pages * @a items_per_page items at a
  * time.  The exact cache invalidation strategy is not defined here,
@@ -140,7 +140,8 @@ typedef struct svn_cache__t svn_cache__t
  */
 svn_error_t *
 svn_cache__create_inprocess(svn_cache__t **cache_p,
-                            svn_cache__dup_func_t dup_func,
+                            svn_cache__serialize_func_t serialize_func,
+                            svn_cache__deserialize_func_t deserialize_func,
                             apr_ssize_t klen,
                             apr_int64_t pages,
                             apr_int64_t items_per_page,
@@ -207,7 +208,7 @@ svn_cache__make_memcache_from_config(svn
  *
  * Allocations will be made in @a pool, in particular the data buffers.
  */
-svn_error_t* 
+svn_error_t *
 svn_cache__membuffer_cache_create(svn_membuffer_t **cache,
                                   apr_size_t total_size,
                                   apr_size_t directory_size,

Copied: subversion/branches/integrate-cache-item-serialization/subversion/include/private/svn_temp_serializer.h (from r981189, subversion/branches/performance/subversion/include/private/svn_temp_serializer.h)
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/include/private/svn_temp_serializer.h?p2=subversion/branches/integrate-cache-item-serialization/subversion/include/private/svn_temp_serializer.h&p1=subversion/branches/performance/subversion/include/private/svn_temp_serializer.h&r1=981189&r2=1068724&rev=1068724&view=diff
==============================================================================
--- subversion/branches/performance/subversion/include/private/svn_temp_serializer.h (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/include/private/svn_temp_serializer.h Wed Feb  9 01:35:49 2011
@@ -34,15 +34,6 @@
 /* forward declaration */
 struct svn_stringbuf_t;
 
-/* We often use references to pointers. Although converting a pointer to
- * a pointer can safely be cast to references to constant pointers to
- * constant data, C compilers tend to reject them. Provide a couple of
- * typedefs to simplify explicit casts.
- */
-typedef const char * const * PCPCSTR;
-typedef const void * const * PCPCVOID;
-typedef void * * PPVOID;
-
 /**
  * Opaque structure controlling the serialization process and holding the
  * intermediate as well as final results.
@@ -55,6 +46,12 @@ typedef struct svn_temp_serializer__cont
  * of the actual structure. Due to the generic nature of the init function
  * we can't determine the structure size as part of the function.
  *
+ * It is possible to specify a @c NULL source_struct in which case the first
+ * call to @ref svn_temp_serializer__push will provide the root struct.
+ * Alternatively, one may even call @ref svn_temp_serializer__add_string
+ * but there is generally no point in doing so because the result will be
+ * simple string object in a @ref svn_stringbuf_t.
+ *
  * You may suggest a larger initial buffer size in @a suggested_buffer_size
  * to minimize the number of internal buffer re-allocations during the
  * serialization process. All allocations will be made from @a pool.
@@ -79,13 +76,18 @@ svn_temp_serializer__init(const void *so
  * the serialized structure can be established. @a struct_size must match
  * the result of @c sizeof() of the actual structure.
  *
+ * Only in case that @ref svn_temp_serializer__init has not been provided
+ * with a root structure and this is the first call after the initialization,
+ * @a source_struct will point to a reference to the root structure instead
+ * of being related to some other. 
+ *
  * Sub-structures and strings will be added in a FIFO fashion. If you need
  * add further sub-structures on the same level, you need to call @ref
  * svn_serializer__pop to realign the serialization context.
  */
 void
 svn_temp_serializer__push(svn_temp_serializer__context_t *context,
-                          PCPCVOID source_struct,
+                          const void * const * source_struct,
                           apr_size_t struct_size);
 
 /**
@@ -104,9 +106,24 @@ svn_temp_serializer__pop(svn_temp_serial
  * serialization @a context. @a s must be a reference to the @c char*
  * pointer in the original structure so that the correspondence in the
  * serialized structure can be established.
+ *
+ * Only in case that @ref svn_temp_serializer__init has not been provided
+ * with a root structure and this is the first call after the initialization,
+ * @a s will not be related to some struct.
  */
 void
-svn_temp_serializer__add_string(svn_temp_serializer__context_t *context, PCPCSTR s);
+svn_temp_serializer__add_string(svn_temp_serializer__context_t *context,
+                                const char * const * s);
+
+/**
+ * Set the serialized representation of the pointer @a ptr inside the
+ * current structure within the serialization @a context to @c NULL.
+ * This is particularly useful if the pointer is not @c NULL in the
+ * source structure.
+ */
+void
+svn_temp_serializer__set_null(svn_temp_serializer__context_t *context,
+                              const void * const * ptr);
 
 /**
  * @return a reference to the data buffer containing the data serialialized
@@ -125,4 +142,12 @@ svn_temp_serializer__get(svn_temp_serial
  * the pointer to resolve in @a ptr.
  */
 void
-svn_temp_deserializer__resolve(void *buffer, PPVOID ptr);
+svn_temp_deserializer__resolve(void *buffer, void **ptr);
+
+/**
+ * Similar to @ref svn_temp_deserializer__resolve but instead of modifying
+ * the buffer content, the resulting pointer is passed back to the caller
+ * a the return value.
+ */
+const void *
+svn_temp_deserializer__ptr(const void *buffer, const void **ptr);

Propchange: subversion/branches/integrate-cache-item-serialization/subversion/include/private/svn_temp_serializer.h
------------------------------------------------------------------------------
    svn:eol-style = native

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=1068724&r1=1068723&r2=1068724&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 01:35:49 2011
@@ -24,138 +24,13 @@
 #include "fs_fs.h"
 #include "id.h"
 #include "dag.h"
+#include "temp_serializer.h"
 #include "../libsvn_fs/fs-loader.h"
 
 #include "svn_config.h"
 
 #include "svn_private_config.h"
 
-/*** Dup/serialize/deserialize functions. ***/
-
-
-/** Caching SVN_FS_ID_T values. **/
-/* Implements svn_cache__dup_func_t */
-static svn_error_t *
-dup_id(void **out,
-       const void *in,
-       apr_pool_t *pool)
-{
-  const svn_fs_id_t *id = in;
-  *out = svn_fs_fs__id_copy(id, pool);
-  return SVN_NO_ERROR;
-}
-
-/* Implements svn_cache__serialize_func_t */
-static svn_error_t *
-serialize_id(char **data,
-             apr_size_t *data_len,
-             void *in,
-             apr_pool_t *pool)
-{
-  svn_fs_id_t *id = in;
-  svn_string_t *id_str = svn_fs_fs__id_unparse(id, pool);
-  *data = (char *) id_str->data;
-  *data_len = id_str->len;
-
-  return SVN_NO_ERROR;
-}
-
-
-/* Implements svn_cache__deserialize_func_t */
-static svn_error_t *
-deserialize_id(void **out,
-               const char *data,
-               apr_size_t data_len,
-               apr_pool_t *pool)
-{
-  svn_fs_id_t *id = svn_fs_fs__id_parse(data, data_len, pool);
-  if (id == NULL)
-    {
-      return svn_error_create(SVN_ERR_FS_NOT_ID, NULL,
-                              _("Bad ID in cache"));
-    }
-
-  *out = id;
-  return SVN_NO_ERROR;
-}
-
-
-/** Caching directory listings. **/
-/* Implements svn_cache__dup_func_t */
-static svn_error_t *
-dup_dir_listing(void **out,
-                const void *in,
-                apr_pool_t *pool)
-{
-  apr_hash_t *new_entries = apr_hash_make(pool);
-  apr_hash_t *entries = (void*)in; /* Cast away const only */
-  apr_hash_index_t *hi;
-
-  for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))
-    {
-      svn_fs_dirent_t *dirent = svn__apr_hash_index_val(hi);
-      svn_fs_dirent_t *new_dirent;
-
-      new_dirent = apr_palloc(pool, sizeof(*new_dirent));
-      new_dirent->name = apr_pstrdup(pool, dirent->name);
-      new_dirent->kind = dirent->kind;
-      new_dirent->id = svn_fs_fs__id_copy(dirent->id, pool);
-      apr_hash_set(new_entries, new_dirent->name, APR_HASH_KEY_STRING,
-                   new_dirent);
-    }
-
-  *out = new_entries;
-  return SVN_NO_ERROR;
-}
-
-
-/** Caching packed rev offsets. **/
-/* Implements svn_cache__serialize_func_t */
-static svn_error_t *
-manifest_serialize(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_func_t */
-static svn_error_t *
-manifest_deserialize(void **out,
-                     const char *data,
-                     apr_size_t data_len,
-                     apr_pool_t *pool)
-{
-  apr_array_header_t *manifest = apr_array_make(pool,
-                                       (int) (data_len / sizeof(apr_off_t)),
-                                       sizeof(apr_off_t));
-  memcpy(manifest->elts, data, data_len);
-  manifest->nelts = (int) (data_len / sizeof(apr_off_t));
-  *out = manifest;
-
-  return SVN_NO_ERROR;
-}
-
-/* Implements svn_cache__dup_func_t */
-static svn_error_t *
-dup_pack_manifest(void **out,
-                  const void *in,
-                  apr_pool_t *pool)
-{
-  const apr_array_header_t *manifest = in;
-
-  *out = apr_array_copy(pool, manifest);
-  return SVN_NO_ERROR;
-}
-
-
 /* Return a memcache in *MEMCACHE_P for FS if it's configured to use
    memcached, or NULL otherwise.  Also, sets *FAIL_STOP to a boolean
    indicating whether cache errors should be returned to the caller or
@@ -212,18 +87,20 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
    * id_private_t + 3 strings for value, and the cache_entry); the
    * default pool size is 8192, so about a hundred should fit
    * comfortably. */
-  if (memcache)
-    SVN_ERR(svn_cache__create_memcache(&(ffd->rev_root_id_cache),
-                                       memcache,
-                                       serialize_id,
-                                       deserialize_id,
-                                       sizeof(svn_revnum_t),
-                                       apr_pstrcat(pool, prefix, "RRI",
-                                                   (char *)NULL),
-                                       fs->pool));
+  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));
   else
     SVN_ERR(svn_cache__create_inprocess(&(ffd->rev_root_id_cache),
-                                        dup_id, sizeof(svn_revnum_t),
+                                        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,
@@ -232,18 +109,19 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
 
   /* Rough estimate: revision DAG nodes have size around 320 bytes, so
    * let's put 16 on a page. */
-  if (memcache)
-    SVN_ERR(svn_cache__create_memcache(&(ffd->rev_node_cache),
-                                       memcache,
-                                       svn_fs_fs__dag_serialize,
-                                       svn_fs_fs__dag_deserialize,
-                                       APR_HASH_KEY_STRING,
-                                       apr_pstrcat(pool, prefix, "DAG",
-                                                   (char *)NULL),
-                                       fs->pool));
+  if (svn_fs__get_global_membuffer_cache())
+    SVN_ERR(svn_cache__create_membuffer_cache(&(ffd->rev_node_cache),
+                                              svn_fs__get_global_membuffer_cache(),
+                                              svn_fs_fs__dag_serialize,
+                                              svn_fs_fs__dag_deserialize,
+                                              APR_HASH_KEY_STRING,
+                                              apr_pstrcat(pool, prefix, "DAG",
+                                                          (char *)NULL),
+                                              fs->pool));
   else
     SVN_ERR(svn_cache__create_inprocess(&(ffd->rev_node_cache),
-                                        svn_fs_fs__dag_dup_for_cache,
+                                        svn_fs_fs__dag_serialize,
+                                        svn_fs_fs__dag_deserialize,
                                         APR_HASH_KEY_STRING,
                                         1024, 16, FALSE, fs->pool));
   if (! no_handler)
@@ -252,18 +130,20 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
 
 
   /* Very rough estimate: 1K per directory. */
-  if (memcache)
-    SVN_ERR(svn_cache__create_memcache(&(ffd->dir_cache),
-                                       memcache,
-                                       svn_fs_fs__dir_entries_serialize,
-                                       svn_fs_fs__dir_entries_deserialize,
-                                       APR_HASH_KEY_STRING,
-                                       apr_pstrcat(pool, prefix, "DIR",
-                                                   (char *)NULL),
-                                       fs->pool));
+  if (svn_fs__get_global_membuffer_cache())
+    SVN_ERR(svn_cache__create_membuffer_cache(&(ffd->dir_cache),
+                                              svn_fs__get_global_membuffer_cache(),
+                                              svn_fs_fs__serialize_dir_entries,
+                                              svn_fs_fs__deserialize_dir_entries,
+                                              APR_HASH_KEY_STRING,
+                                              apr_pstrcat(pool, prefix, "DIR",
+                                                          (char *)NULL),
+                                              fs->pool));
   else
     SVN_ERR(svn_cache__create_inprocess(&(ffd->dir_cache),
-                                        dup_dir_listing, APR_HASH_KEY_STRING,
+                                        svn_fs_fs__serialize_dir_entries,
+                                        svn_fs_fs__deserialize_dir_entries,
+                                        APR_HASH_KEY_STRING,
                                         1024, 8, FALSE, fs->pool));
 
   if (! no_handler)
@@ -272,24 +152,27 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
 
   /* Only 16 bytes per entry (a revision number + the corresponding offset).
      Since we want ~8k pages, that means 512 entries per page. */
-  if (memcache)
-    SVN_ERR(svn_cache__create_memcache(&(ffd->packed_offset_cache),
-                                       memcache,
-                                       manifest_serialize,
-                                       manifest_deserialize,
-                                       sizeof(svn_revnum_t),
-                                       apr_pstrcat(pool, prefix, "PACK-MANIFEST",
-                                                   (char *)NULL),
-                                       fs->pool));
+  if (svn_fs__get_global_membuffer_cache())
+    SVN_ERR(svn_cache__create_membuffer_cache(&(ffd->packed_offset_cache),
+                                              svn_fs__get_global_membuffer_cache(),
+                                              svn_fs_fs__serialize_manifest,
+                                              svn_fs_fs__deserialize_manifest,
+                                              sizeof(svn_revnum_t),
+                                              apr_pstrcat(pool, prefix, "PACK-MANIFEST",
+                                                          (char *)NULL),
+                                              fs->pool));
   else
     SVN_ERR(svn_cache__create_inprocess(&(ffd->packed_offset_cache),
-                                        dup_pack_manifest, sizeof(svn_revnum_t),
+                                        svn_fs_fs__serialize_manifest,
+                                        svn_fs_fs__deserialize_manifest,
+                                        sizeof(svn_revnum_t),
                                         32, 1, FALSE, fs->pool));
 
   if (! no_handler)
     SVN_ERR(svn_cache__set_error_handler(ffd->packed_offset_cache,
                                          warn_on_cache_errors, fs, pool));
 
+  /* initialize fulltext cache as configured */
   if (memcache)
     {
       SVN_ERR(svn_cache__create_memcache(&(ffd->fulltext_cache),

Modified: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/dag.c?rev=1068724&r1=1068723&r2=1068724&view=diff
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/dag.c Wed Feb  9 01:35:49 2011
@@ -38,6 +38,8 @@
 
 #include "private/svn_fspath.h"
 #include "svn_private_config.h"
+#include "private/svn_temp_serializer.h"
+#include "temp_serializer.h"
 
 
 /* Initializing a filesystem.  */
@@ -1063,59 +1065,38 @@ svn_fs_fs__dag_dup(const dag_node_t *nod
 }
 
 svn_error_t *
-svn_fs_fs__dag_dup_for_cache(void **out,
-                             const void *in,
-                             apr_pool_t *pool)
-{
-  const dag_node_t *in_node = in;
-  dag_node_t *out_node;
-
-  out_node = svn_fs_fs__dag_dup(in_node, pool);
-  out_node->fs = NULL;
-  *out = out_node;
-  return SVN_NO_ERROR;
-}
-
-/* The cache serialization format is:
- *
- * - For mutable nodes: the character 'M', then 'F' for files or 'D'
- *   for directories, then the ID, then '\n', then the created path.
- *
- * - For immutable nodes: the character 'I' followed by the noderev
- *   hash dump (the other fields can be reconstructed from this).  (We
- *   assume that, once constructed, immutable nodes always contain
- *   their noderev.)
- */
-
-svn_error_t *
 svn_fs_fs__dag_serialize(char **data,
                          apr_size_t *data_len,
                          void *in,
                          apr_pool_t *pool)
 {
   dag_node_t *node = in;
-  svn_stringbuf_t *buf = svn_stringbuf_create("", pool);
+  svn_stringbuf_t *serialized;
 
-  if (svn_fs_fs__dag_check_mutable(node))
-    {
-      svn_stringbuf_appendcstr(buf, "M");
-      svn_stringbuf_appendcstr(buf, (node->kind == svn_node_file ? "F" : "D"));
-      svn_stringbuf_appendcstr(buf, svn_fs_fs__id_unparse(node->id,
-                                                          pool)->data);
-      svn_stringbuf_appendcstr(buf, "\n");
-      svn_stringbuf_appendcstr(buf, node->created_path);
-    }
+  /* create an serialization context and serialize the dag node as root */
+  svn_temp_serializer__context_t *context =
+      svn_temp_serializer__init(node,
+                                sizeof(*node),
+                                503,
+                                pool);
+
+  /* for mutable nodes, we will _never_ cache the noderev */
+  if (node->node_revision && !svn_fs_fs__dag_check_mutable(node))
+    svn_fs_fs__noderev_serialize(context, &node->node_revision);
   else
-    {
-      fs_fs_data_t *ffd = node->fs->fsap_data;
-      svn_stringbuf_appendcstr(buf, "I");
-      SVN_ERR(svn_fs_fs__write_noderev(svn_stream_from_stringbuf(buf, pool),
-                                       node->node_revision, ffd->format,
-                                       TRUE, pool));
-    }
+    svn_temp_serializer__set_null(context,
+                                  (const void * const *)&node->node_revision);
+
+  /* serialize other sub-structures */
+  svn_fs_fs__id_serialize(context, (const svn_fs_id_t **)&node->id);
+  svn_fs_fs__id_serialize(context, &node->fresh_root_predecessor_id);
+  svn_temp_serializer__add_string(context, &node->created_path);
+
+  /* return serialized data */
+  serialized = svn_temp_serializer__get(context);
+  *data = serialized->data;
+  *data_len = serialized->len;
 
-  *data = buf->data;
-  *data_len = buf->len;
   return SVN_NO_ERROR;
 }
 
@@ -1125,74 +1106,23 @@ svn_fs_fs__dag_deserialize(void **out,
                            apr_size_t data_len,
                            apr_pool_t *pool)
 {
-  dag_node_t *node = apr_pcalloc(pool, sizeof(*node));
-
+  dag_node_t *node = (dag_node_t *)data;
   if (data_len == 0)
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Empty noderev in cache"));
 
-  if (*data == 'M')
-    {
-      const char *newline;
-      size_t id_len;
-
-      data++; data_len--;
-      if (data_len == 0)
-        return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
-                                _("Kindless noderev in cache"));
-      if (*data == 'F')
-        node->kind = svn_node_file;
-      else if (*data == 'D')
-        node->kind = svn_node_dir;
-      else
-        return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
-                                 _("Unknown kind for noderev in cache: '%c'"),
-                                 *data);
-
-      data++; data_len--;
-      newline = memchr(data, '\n', data_len);
-      if (!newline)
-        return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
-                                _("Unterminated ID in cache"));
-      id_len = newline - 1 - data;
-      node->id = svn_fs_fs__id_parse(data, id_len, pool);
-      if (! node->id)
-        return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
-                                 _("Bogus ID '%s' in cache"),
-                                 apr_pstrndup(pool, data, id_len));
-
-      data += id_len; data_len -= id_len;
-      data++; data_len--;
-      if (data_len == 0)
-        return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
-                                _("No created path"));
-      node->created_path = apr_pstrndup(pool, data, data_len);
-    }
-  else if (*data == 'I')
-    {
-      node_revision_t *noderev;
-      apr_pool_t *subpool = svn_pool_create(pool);
-      svn_stream_t *stream =
-        svn_stream_from_stringbuf(svn_stringbuf_ncreate(data + 1,
-                                                        data_len - 1,
-                                                        subpool),
-                                  subpool);
-      SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, pool));
-      node->kind = noderev->kind;
-      node->id = svn_fs_fs__id_copy(noderev->id, pool);
-      node->created_path = apr_pstrdup(pool, noderev->created_path);
-
-      if (noderev->is_fresh_txn_root)
-        node->fresh_root_predecessor_id = noderev->predecessor_id;
+  /* Copy the _full_ buffer as it also contains the sub-structures. */
+  node->fs = NULL;
 
-      node->node_revision = noderev;
+  /* fixup all references to sub-structures */
+  svn_fs_fs__id_deserialize(node, &node->id);
+  svn_fs_fs__id_deserialize(node,
+                            (svn_fs_id_t **)&node->fresh_root_predecessor_id);
+  svn_fs_fs__noderev_deserialize(node, &node->node_revision);
 
-      svn_pool_destroy(subpool);
-    }
-  else
-    return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
-                             _("Unknown node type in cache: '%c'"), *data);
+  svn_temp_deserializer__resolve(node, (void**)&node->created_path);
 
+  /* return result */
   *out = node;
 
   return SVN_NO_ERROR;

Modified: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/dag.h
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/dag.h?rev=1068724&r1=1068723&r2=1068724&view=diff
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/dag.h (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/dag.h Wed Feb  9 01:35:49 2011
@@ -78,13 +78,6 @@ dag_node_t *
 svn_fs_fs__dag_dup(const dag_node_t *node,
                    apr_pool_t *pool);
 
-/* Like svn_fs_fs__dag_dup, but implementing the svn_cache__dup_func_t
-   prototype, and NULLing the FS field. */
-svn_error_t *
-svn_fs_fs__dag_dup_for_cache(void **out,
-                             const void *in,
-                             apr_pool_t *pool);
-
 /* Serialize a DAG node.
    Implements svn_cache__serialize_func_t */
 svn_error_t *

Modified: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/fs_fs.c?rev=1068724&r1=1068723&r2=1068724&view=diff
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/fs_fs.c Wed Feb  9 01:35:49 2011
@@ -3748,26 +3748,6 @@ unparse_dir_entries(apr_hash_t **str_ent
 }
 
 
-svn_error_t *
-svn_fs_fs__dir_entries_serialize(char **data,
-                                 apr_size_t *data_len,
-                                 void *in,
-                                 apr_pool_t *pool)
-{
-  apr_hash_t *entries = in;
-  svn_stringbuf_t *buf = svn_stringbuf_create("", pool);
-  svn_stream_t *stream = svn_stream_from_stringbuf(buf, pool);
-
-  SVN_ERR(unparse_dir_entries(&entries, entries, pool));
-  SVN_ERR(svn_hash_write2(entries, stream, SVN_HASH_TERMINATOR, pool));
-
-  *data = buf->data;
-  *data_len = buf->len;
-
-  return SVN_NO_ERROR;
-}
-
-
 /* Given a hash STR_ENTRIES with values as svn_string_t as specified
    in an FSFS directory contents listing, return a hash of dirents in
    *ENTRIES_P.  Perform allocations in POOL. */
@@ -3824,24 +3804,6 @@ parse_dir_entries(apr_hash_t **entries_p
 }
 
 svn_error_t *
-svn_fs_fs__dir_entries_deserialize(void **out,
-                                   const char *data,
-                                   apr_size_t data_len,
-                                   apr_pool_t *pool)
-{
-  apr_hash_t *entries = apr_hash_make(pool);
-  svn_stringbuf_t *buf = svn_stringbuf_ncreate(data, data_len, pool);
-  svn_stream_t *stream = svn_stream_from_stringbuf(buf, pool);
-
-  SVN_ERR(svn_hash_read2(entries, stream, SVN_HASH_TERMINATOR, pool));
-  SVN_ERR(parse_dir_entries(&entries, entries, pool));
-
-  *out = entries;
-  return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
 svn_fs_fs__rep_contents_dir(apr_hash_t **entries_p,
                             svn_fs_t *fs,
                             node_revision_t *noderev,

Modified: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/fs_fs.h?rev=1068724&r1=1068723&r2=1068724&view=diff
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/fs_fs.h Wed Feb  9 01:35:49 2011
@@ -99,22 +99,6 @@ svn_error_t *svn_fs_fs__rev_get_root(svn
                                      svn_revnum_t rev,
                                      apr_pool_t *pool);
 
-/* Serialize a directory contents hash.
-   Implements svn_cache__serialize_func_t */
-svn_error_t *
-svn_fs_fs__dir_entries_serialize(char **data,
-                                 apr_size_t *data_len,
-                                 void *in,
-                                 apr_pool_t *pool);
-
-/* Deserialize a directory contents hash.
-   Implements svn_cache__deserialize_func_t */
-svn_error_t *
-svn_fs_fs__dir_entries_deserialize(void **out,
-                                   const char *data,
-                                   apr_size_t data_len,
-                                   apr_pool_t *pool);
-
 /* Set *ENTRIES to an apr_hash_t of dirent structs that contain the
    directory entries of node-revision NODEREV in filesystem FS.  The
    returned table (and its keys and values) is allocated in POOL,

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=1068724&r1=1068723&r2=1068724&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 01:35:49 2011
@@ -25,7 +25,7 @@
 
 #include "id.h"
 #include "../libsvn_fs/fs-loader.h"
-
+#include "private/svn_temp_serializer.h"
 
 
 typedef struct id_private_t {
@@ -309,3 +309,88 @@ svn_fs_fs__id_parse(const char *data,
 
   return id;
 }
+
+/* (de-)serialization support */
+
+/* Serialization of the PVT sub-structure within the CONTEXT.
+ */
+static void
+serialize_id_private(svn_temp_serializer__context_t *context,
+                     const id_private_t * const *pvt)
+{
+  const id_private_t *private = *pvt;
+
+  /* serialize the pvt data struct itself */
+  svn_temp_serializer__push(context,
+                            (const void * const *)pvt,
+                            sizeof(*private));
+
+  /* append the referenced strings */
+  svn_temp_serializer__add_string(context, &private->node_id);
+  svn_temp_serializer__add_string(context, &private->copy_id);
+  svn_temp_serializer__add_string(context, &private->txn_id);
+
+  /* return to caller's nesting level */
+  svn_temp_serializer__pop(context);
+}
+
+/* Serialize an ID within the serialization CONTECT.
+ */
+void
+svn_fs_fs__id_serialize(svn_temp_serializer__context_t *context,
+                        const struct svn_fs_id_t * const *id)
+{
+  /* nothing to do for NULL ids */
+  if (*id == NULL)
+    return;
+
+  /* serialize the id data struct itself */
+  svn_temp_serializer__push(context,
+                            (const void * const *)id,
+                            sizeof(**id));
+
+  /* serialize the id_private_t data sub-struct */
+  serialize_id_private(context,
+                       (const id_private_t * const *)&(*id)->fsap_data);
+
+  /* return to caller's nesting level */
+  svn_temp_serializer__pop(context);
+}
+
+/* Deserialization of the PVT sub-structure in BUFFER.
+ */
+static void
+deserialize_id_private(void *buffer, id_private_t **pvt)
+{
+  /* fixup the reference to the only sub-structure */
+  id_private_t *private;
+  svn_temp_deserializer__resolve(buffer, (void**)pvt);
+
+  /* fixup the sub-structure itself */
+  private = *pvt;
+  svn_temp_deserializer__resolve(private, (void**)&private->node_id);
+  svn_temp_deserializer__resolve(private, (void**)&private->copy_id);
+  svn_temp_deserializer__resolve(private, (void**)&private->txn_id);
+}
+
+/* Deserialize an ID inside the BUFFER.
+ */
+void
+svn_fs_fs__id_deserialize(void *buffer, svn_fs_id_t **id)
+{
+  /* The id maybe all what is in the whole buffer.
+   * Don't try to fixup the pointer in that case*/
+  if (*id != buffer)
+    svn_temp_deserializer__resolve(buffer, (void**)id);
+
+  /* no id, no sub-structure fixup necessary */
+  if (*id == NULL)
+    return;
+
+  /* the stored vtable is bogus at best -> set the right one */
+  (*id)->vtable = &id_vtable;
+
+  /* handle sub-structures */
+  deserialize_id_private(*id, (id_private_t **)&(*id)->fsap_data);
+}
+

Modified: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/id.h
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/id.h?rev=1068724&r1=1068723&r2=1068724&view=diff
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/id.h (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/id.h Wed Feb  9 01:35:49 2011
@@ -90,6 +90,25 @@ svn_fs_id_t *svn_fs_fs__id_parse(const c
                                  apr_size_t len,
                                  apr_pool_t *pool);
 
+
+/* (de-)serialization support*/
+
+struct svn_temp_serializer__context_t;
+
+/**
+ * Serialize an @a id within the serialization @a context.
+ */
+void
+svn_fs_fs__id_serialize(struct svn_temp_serializer__context_t *context,
+                        const svn_fs_id_t * const *id);
+
+/**
+ * Deserialize an @a id within the @a buffer.
+ */
+void
+svn_fs_fs__id_deserialize(void *buffer,
+                          svn_fs_id_t **id);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/tree.c?rev=1068724&r1=1068723&r2=1068724&view=diff
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/libsvn_fs_fs/tree.c Wed Feb  9 01:35:49 2011
@@ -3917,9 +3917,10 @@ make_txn_root(svn_fs_root_t **root_p,
      Note that since dag_node_cache_invalidate uses svn_cache__iter,
      this *cannot* be a memcache-based cache.  */
   SVN_ERR(svn_cache__create_inprocess(&(frd->txn_node_cache),
-                                     svn_fs_fs__dag_dup_for_cache,
-                                     APR_HASH_KEY_STRING,
-                                     32, 20, FALSE, root->pool));
+                                      svn_fs_fs__dag_serialize,
+                                      svn_fs_fs__dag_deserialize,
+                                      APR_HASH_KEY_STRING,
+                                      32, 20, FALSE, root->pool));
 
   root->fsap_data = frd;
 

Modified: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/cache-inprocess.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/cache-inprocess.c?rev=1068724&r1=1068723&r2=1068724&view=diff
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/cache-inprocess.c (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/cache-inprocess.c Wed Feb  9 01:35:49 2011
@@ -37,8 +37,11 @@ typedef struct inprocess_cache_t {
   apr_hash_t *hash;
   apr_ssize_t klen;
 
-  /* Used to copy values in and out of the cache. */
-  svn_cache__dup_func_t dup_func;
+  /* Used to copy values into the cache. */
+  svn_cache__serialize_func_t serialize_func;
+
+  /* Used to copy values out of the cache. */
+  svn_cache__deserialize_func_t deserialize_func;
 
   /* The number of pages we're allowed to allocate before having to
    * try to reuse one. */
@@ -94,8 +97,13 @@ struct cache_page {
 /* An cache entry. */
 struct cache_entry {
   const void *key;
+
+  /* serialized value */
   void *value;
 
+  /* length of the serialized value in bytes */
+  apr_size_t size;
+
   /* The page it's on (needed so that the LRU list can be
    * maintained). */
   struct cache_page *page;
@@ -142,21 +150,6 @@ move_page_to_front(inprocess_cache_t *ca
   insert_page(cache, page);
 }
 
-/* Uses CACHE->dup_func to copy VALUE into *VALUE_P inside POOL, or
-   just sets *VALUE_P to NULL if VALUE is NULL. */
-static svn_error_t *
-duplicate_value(void **value_p,
-                inprocess_cache_t *cache,
-                void *value,
-                apr_pool_t *pool)
-{
-  if (value)
-    SVN_ERR((cache->dup_func)(value_p, value, pool));
-  else
-    *value_p = NULL;
-  return SVN_NO_ERROR;
-}
-
 /* Return a copy of KEY inside POOL, using CACHE->KLEN to figure out
  * how. */
 static const void *
@@ -214,7 +207,7 @@ inprocess_cache_get(void **value_p,
 {
   inprocess_cache_t *cache = cache_void;
   struct cache_entry *entry;
-  svn_error_t *err;
+  char* buffer;
 
   SVN_ERR(lock_cache(cache));
 
@@ -227,9 +220,23 @@ inprocess_cache_get(void **value_p,
 
   move_page_to_front(cache, entry->page);
 
+  /* duplicate the buffer entry */
+  buffer = apr_palloc(pool, entry->size);
+  memcpy(buffer, entry->value, entry->size);
+
+  /* the cache is no longer being accessed */
+  SVN_ERR(unlock_cache(cache, SVN_NO_ERROR));
+
+  /* deserialize the buffer content. Usually, this will directly
+     modify the buffer content directly.
+   */
   *found = TRUE;
-  err = duplicate_value(value_p, cache, entry->value, pool);
-  return unlock_cache(cache, err);
+  if (entry->value)
+    return cache->deserialize_func(value_p, buffer, entry->size, pool);
+  else
+    *value_p = NULL;
+
+  return unlock_cache(cache, SVN_NO_ERROR);
 }
 
 /* Removes PAGE from the LRU list, removes all of its entries from
@@ -302,8 +309,19 @@ inprocess_cache_set(void *cache_void,
       struct cache_page *page = existing_entry->page;
 
       move_page_to_front(cache, page);
-      err = duplicate_value(&(existing_entry->value), cache,
-                            value, page->page_pool);
+      if (value)
+        {
+          err = cache->serialize_func((char **)&existing_entry->value,
+                                      &existing_entry->size,
+                                      value,
+                                      page->page_pool);
+        }
+      else
+        {
+          existing_entry->value = NULL;
+          existing_entry->size = 0;
+        }
+
       goto cleanup;
     }
 
@@ -340,8 +358,19 @@ inprocess_cache_set(void *cache_void,
 
     /* Copy the key and value into the page's pool.  */
     new_entry->key = duplicate_key(cache, key, page->page_pool);
-    err = duplicate_value(&(new_entry->value), cache, value,
-                          page->page_pool);
+    if (value)
+      {
+        err = cache->serialize_func((char **)&new_entry->value,
+                                    &new_entry->size,
+                                    value,
+                                    page->page_pool);
+      }
+    else
+      {
+        new_entry->value = NULL;
+        new_entry->size = 0;
+      }
+
     if (err)
       goto cleanup;
 
@@ -417,7 +446,8 @@ static svn_cache__vtable_t inprocess_cac
 
 svn_error_t *
 svn_cache__create_inprocess(svn_cache__t **cache_p,
-                            svn_cache__dup_func_t dup_func,
+                            svn_cache__serialize_func_t serialize,
+                            svn_cache__deserialize_func_t deserialize,
                             apr_ssize_t klen,
                             apr_int64_t pages,
                             apr_int64_t items_per_page,
@@ -430,7 +460,8 @@ svn_cache__create_inprocess(svn_cache__t
   cache->hash = apr_hash_make(pool);
   cache->klen = klen;
 
-  cache->dup_func = dup_func;
+  cache->serialize_func = serialize;
+  cache->deserialize_func = deserialize;
 
   SVN_ERR_ASSERT(pages >= 1);
   cache->unallocated_pages = pages;

Modified: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/cache-memcache.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/cache-memcache.c?rev=1068724&r1=1068723&r2=1068724&view=diff
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/cache-memcache.c (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/cache-memcache.c Wed Feb  9 01:35:49 2011
@@ -144,7 +144,7 @@ memcache_get(void **value_p,
   SVN_ERR(build_key(&mc_key, cache, key, subpool));
 
   apr_err = apr_memcache_getp(cache->memcache,
-                              (cache->deserialize_func ? subpool : pool),
+                              pool,
                               mc_key,
                               &data,
                               &data_len,

Copied: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/svn_temp_serializer.c (from r981189, subversion/branches/performance/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?p2=subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/svn_temp_serializer.c&p1=subversion/branches/performance/subversion/libsvn_subr/svn_temp_serializer.c&r1=981189&r2=1068724&rev=1068724&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_subr/svn_temp_serializer.c (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/svn_temp_serializer.c Wed Feb  9 01:35:49 2011
@@ -1,3 +1,4 @@
+<<<<<<< .working
 /*
  * svn_serializer.c: implement the tempoary structure serialization API
  *
@@ -58,7 +59,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;
@@ -77,7 +78,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);
@@ -95,11 +96,11 @@ align_buffer_end(svn_temp_serializer__co
  * 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
@@ -108,7 +109,8 @@ svn_temp_serializer__init(const void *so
 
   /* create the serialization context and initialize it, including the
    * structure stack */
-  svn_temp_serializer__context_t *context = apr_palloc(pool, sizeof(*context));
+  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));
@@ -128,8 +130,8 @@ svn_temp_serializer__init(const void *so
  * right after this function call.
  */
 static void
-store_current_end_pointer(svn_temp_serializer__context_t *context,
-                          PCPCVOID source_pointer)
+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
@@ -137,7 +139,8 @@ store_current_end_pointer(svn_temp_seria
                     + context->source->target_offset;
 
   /* use the serialized pointer as a storage for the offset */
-  apr_size_t *target_string_ptr = (apr_size_t*)(context->buffer->data + offset);
+  apr_size_t *target_string_ptr = 
+    (apr_size_t*)(context->buffer->data + offset);
 
   /* the offset must be within the serialized data. Otherwise, you forgot
    * to serialize the respective sub-struct. */
@@ -155,8 +158,9 @@ store_current_end_pointer(svn_temp_seria
  * result of sizeof() of the actual structure.
  */
 void
+
 svn_temp_serializer__push(svn_temp_serializer__context_t *context,
-                          PCPCVOID source_struct,
+                          const void * const * source_struct,
                           apr_size_t struct_size)
 {
   /* create a new entry for the structure stack */
@@ -202,7 +206,8 @@ svn_temp_serializer__pop(svn_temp_serial
  * structure can be established.
  */
 void
-svn_temp_serializer__add_string(svn_temp_serializer__context_t *context, PCPCSTR s)
+svn_temp_serializer__add_string(svn_temp_serializer__context_t *context,
+                                const char * const * s)
 {
   /* Store the offset at which the string data that will the appended.
    * Write 0 for NULL pointers. Strings don't need special alignment. */
@@ -213,6 +218,32 @@ svn_temp_serializer__add_string(svn_temp
     svn_stringbuf_appendbytes(context->buffer, *s, strlen(*s) + 1);
 }
 
+/* Set the serialized representation of the pointer PTR inside the current
+ * structure within the serialization CONTEXT to NULL. This is particularly
+ * useful if the pointer is not NULL in the source structure.
+ */
+void
+svn_temp_serializer__set_NULL(svn_temp_serializer__context_t *context,
+                              const void * const * ptr)
+{
+  apr_size_t offset;
+
+  /* there must be a parent structure */
+  assert(context->source);
+
+  /* relative position of the serialized pointer to the begin of the buffer */
+  offset = (const char *)ptr
+         - (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);
+
+  /* use the serialized pointer as a storage for the offset */
+  *(apr_size_t*)(context->buffer->data + offset) = 0;
+}
+
 /* Return the the data buffer that receives the serialialized data from
  * the given serialization CONTEXT.
  */
@@ -226,7 +257,7 @@ svn_temp_serializer__get(svn_temp_serial
  * proper pointer value.
  */
 void
-svn_temp_deserializer__resolve(void *buffer, PPVOID ptr)
+svn_temp_deserializer__resolve(void *buffer, void **ptr)
 {
   if ((apr_size_t)*ptr)
     {
@@ -240,3 +271,11 @@ svn_temp_deserializer__resolve(void *buf
       *ptr = NULL;
     }
 }
+
+const void *
+svn_temp_deserializer__ptr(const void *buffer, const void **ptr)
+{
+  return (apr_size_t)*ptr == 0
+      ? NULL
+      : (const char*)buffer + (apr_size_t)*ptr;
+}

Propchange: subversion/branches/integrate-cache-item-serialization/subversion/libsvn_subr/svn_temp_serializer.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/branches/integrate-cache-item-serialization/subversion/tests/libsvn_subr/cache-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-cache-item-serialization/subversion/tests/libsvn_subr/cache-test.c?rev=1068724&r1=1068723&r2=1068724&view=diff
==============================================================================
--- subversion/branches/integrate-cache-item-serialization/subversion/tests/libsvn_subr/cache-test.c (original)
+++ subversion/branches/integrate-cache-item-serialization/subversion/tests/libsvn_subr/cache-test.c Wed Feb  9 01:35:49 2011
@@ -34,22 +34,6 @@
 
 #include "../svn_test.h"
 
-/* Implements svn_cache__dup_func_t */
-static svn_error_t *
-dup_revnum(void **out,
-           const void *in,
-           apr_pool_t *pool)
-{
-  const svn_revnum_t *in_rn = in;
-  svn_revnum_t *duped = apr_palloc(pool, sizeof(*duped));
-
-  *duped = *in_rn;
-
-  *out = duped;
-
-  return SVN_NO_ERROR;
-}
-
 /* Implements svn_cache__serialize_func_t */
 static svn_error_t *
 serialize_revnum(char **data,
@@ -146,12 +130,13 @@ test_inprocess_cache_basic(apr_pool_t *p
 
   /* Create a cache with just one entry. */
   SVN_ERR(svn_cache__create_inprocess(&cache,
-                                     dup_revnum,
-                                     APR_HASH_KEY_STRING,
-                                     1,
-                                     1,
-                                     TRUE,
-                                     pool));
+                                      serialize_revnum,
+                                      deserialize_revnum,
+                                      APR_HASH_KEY_STRING,
+                                      1,
+                                      1,
+                                      TRUE,
+                                      pool));
 
   return basic_cache_test(cache, TRUE, pool);
 }