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/20 12:21:00 UTC

svn commit: r1072558 - in /subversion/branches/integrate-partial-getter: ./ subversion/include/private/ subversion/libsvn_fs_fs/ subversion/libsvn_subr/

Author: stefan2
Date: Sun Feb 20 11:20:59 2011
New Revision: 1072558

URL: http://svn.apache.org/viewvc?rev=1072558&view=rev
Log:
Introduce optimized svn_cache__get_partial() and use that to speed up
dir_entry_id_from_node() and get_packed_offset().

Merged revisions from /branches/performance:
986605, 986817, 990574, 990575

Modified:
    subversion/branches/integrate-partial-getter/   (props changed)
    subversion/branches/integrate-partial-getter/subversion/include/private/svn_cache.h
    subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/dag.c
    subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/dag.h
    subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/fs_fs.c
    subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/fs_fs.h
    subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/temp_serializer.c
    subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/temp_serializer.h
    subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-inprocess.c
    subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-membuffer.c
    subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-memcache.c
    subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache.c
    subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache.h

Propchange: subversion/branches/integrate-partial-getter/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sun Feb 20 11:20:59 2011
@@ -31,7 +31,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,981090,981189,981194,981287,981684,981827,982043,982355,983398,983406,983474,983488,983490,983764,983766,983770,984927,984973,984984,985014,985037,985046,985472,985477,985482,985487-985488,985493,985497,985500,985514,985603,985606,985669,986453,986465,986485,986491-986492,986517,986521,986608,986832,987865,987868-987869,987872,987886-987888,987893,988319,988898,990533,990535-990537,990541,990568,990572,990600,990759,992899,992911,993127,993141,994956,995478,995507,995603,998012,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,1029055,1029062,1029078,1029080,1029090,1029092-1029093,1029111,1029151,1029158,1029229,1029232,1029335-1029336,1029339-1029340,1029342,1029344,1030763,1030827,1031203,1031235,1032285,1032333,1033040,1033057,1033294,1035869,1039511,104370
 5,1053735,1056015,1066452,1067683
+/subversion/branches/performance:979193,980118,981087,981090,981189,981194,981287,981684,981827,982043,982355,983398,983406,983474,983488,983490,983764,983766,983770,984927,984973,984984,985014,985037,985046,985472,985477,985482,985487-985488,985493,985497,985500,985514,985603,985606,985669,986453,986465,986485,986491-986492,986517,986521,986605,986608,986817,986832,987865,987868-987869,987872,987886-987888,987893,988319,988898,990533,990535-990537,990541,990568,990572,990574-990575,990600,990759,992899,992911,993127,993141,994956,995478,995507,995603,998012,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,1029055,1029062,1029078,1029080,1029090,1029092-1029093,1029111,1029151,1029158,1029229,1029232,1029335-1029336,1029339-1029340,1029342,1029344,1030763,1030827,1031203,1031235,1032285,1032333,1033040,1033057,10
 33294,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-partial-getter/subversion/include/private/svn_cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-partial-getter/subversion/include/private/svn_cache.h?rev=1072558&r1=1072557&r2=1072558&view=diff
==============================================================================
--- subversion/branches/integrate-partial-getter/subversion/include/private/svn_cache.h (original)
+++ subversion/branches/integrate-partial-getter/subversion/include/private/svn_cache.h Sun Feb 20 11:20:59 2011
@@ -318,6 +318,19 @@ svn_cache__iter(svn_boolean_t *completed
                 svn_iter_apr_hash_cb_t func,
                 void *baton,
                 apr_pool_t *pool);
+
+/**
+ * Similar to @ref svn_cache__set but will call a specific de-serialization
+ * function @a func.
+ */
+svn_error_t *
+svn_cache__get_partial(void **value,
+                       svn_boolean_t *found,
+                       const svn_cache__t *cache,
+                       const void *key,
+                       svn_cache__partial_getter_func_t func,
+                       void *baton,
+                       apr_pool_t *scratch_pool);
 /** @} */
 
 

Modified: subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/dag.c?rev=1072558&r1=1072557&r2=1072558&view=diff
==============================================================================
--- subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/dag.c Sun Feb 20 11:20:59 2011
@@ -312,16 +312,10 @@ dir_entry_id_from_node(const svn_fs_id_t
                        const char *name,
                        apr_pool_t *pool)
 {
-  apr_hash_t *entries;
   svn_fs_dirent_t *dirent;
   apr_pool_t *subpool = svn_pool_create(pool);
 
-  SVN_ERR(svn_fs_fs__dag_dir_entries(&entries, parent, subpool, pool));
-  if (entries)
-    dirent = apr_hash_get(entries, name, APR_HASH_KEY_STRING);
-  else
-    dirent = NULL;
-
+  SVN_ERR(svn_fs_fs__dag_dir_entry(&dirent, parent, name, subpool, pool));
   *id_p = dirent ? svn_fs_fs__id_copy(dirent->id, pool) : NULL;
 
   svn_pool_destroy(subpool);
@@ -440,6 +434,27 @@ svn_fs_fs__dag_dir_entries(apr_hash_t **
   return svn_fs_fs__rep_contents_dir(entries, node->fs, noderev, pool);
 }
 
+svn_error_t *
+svn_fs_fs__dag_dir_entry(svn_fs_dirent_t **dirent,
+                         dag_node_t *node,
+                         const char* name,
+                         apr_pool_t *pool,
+                         apr_pool_t *node_pool)
+{
+  node_revision_t *noderev;
+  SVN_ERR(get_node_revision(&noderev, node, node_pool));
+
+  if (noderev->kind != svn_node_dir)
+    return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL,
+                            _("Can't get entries of non-directory"));
+
+  /* Get a dirent hash for this directory. */
+  return svn_fs_fs__rep_contents_dir_partial((void **)dirent, node->fs,
+                                             noderev,
+                                             svn_fs_fs__extract_dir_entry,
+                                             (void *)name, pool);
+}
+
 
 svn_error_t *
 svn_fs_fs__dag_set_entry(dag_node_t *node,

Modified: subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/dag.h
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/dag.h?rev=1072558&r1=1072557&r2=1072558&view=diff
==============================================================================
--- subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/dag.h (original)
+++ subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/dag.h Sun Feb 20 11:20:59 2011
@@ -297,6 +297,17 @@ svn_error_t *svn_fs_fs__dag_dir_entries(
                                         apr_pool_t *pool,
                                         apr_pool_t *node_pool);
 
+/* Fetches the NODE's entries and returns a copy of the entry selected
+   by the key value given in NAME and set *DIRENT to a copy of that
+   entry. If such entry was found, the copy will be allocated in POOL.
+   Otherwise, the *DIRENT will be set to NULL. NODE_POOL is used for
+   any allocation of memory that needs to live as long as NODE lives.
+ */
+svn_error_t * svn_fs_fs__dag_dir_entry(svn_fs_dirent_t **dirent,
+                                       dag_node_t *node,
+                                       const char* name,
+                                       apr_pool_t *pool,
+                                       apr_pool_t *node_pool);
 
 /* Set ENTRY_NAME in NODE to point to ID (with kind KIND), allocating
    from POOL.  NODE must be a mutable directory.  ID can refer to a

Modified: subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/fs_fs.c?rev=1072558&r1=1072557&r2=1072558&view=diff
==============================================================================
--- subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/fs_fs.c Sun Feb 20 11:20:59 2011
@@ -1930,19 +1930,24 @@ get_packed_offset(apr_off_t *rev_offset,
   svn_stream_t *manifest_stream;
   svn_boolean_t is_cached;
   apr_int64_t shard;
+  apr_int64_t shard_pos;
   apr_array_header_t *manifest;
   apr_pool_t *iterpool;
 
   shard = rev / ffd->max_files_per_dir;
-  SVN_ERR(svn_cache__get((void **) &manifest, &is_cached,
-                         ffd->packed_offset_cache, &shard, pool));
+
+  /* position of the shard within the manifest */
+  shard_pos = rev % ffd->max_files_per_dir;
+
+  /* fetch exactly that element into *rev_offset, if the manifest is found
+     in the cache */
+  SVN_ERR(svn_cache__get_partial((void **) rev_offset, &is_cached,
+                                 ffd->packed_offset_cache, &shard,
+                                 svn_fs_fs__get_sharded_offset, &shard_pos,
+                                 pool));
 
   if (is_cached)
-    {
-      *rev_offset = APR_ARRAY_IDX(manifest, rev % ffd->max_files_per_dir,
-                                  apr_off_t);
       return SVN_NO_ERROR;
-    }
 
   /* Open the manifest file. */
   SVN_ERR(svn_stream_open_readonly(&manifest_stream,
@@ -2825,7 +2830,7 @@ svn_fs_fs__rev_get_root(svn_fs_id_t **ro
   fs_fs_data_t *ffd = fs->fsap_data;
   apr_file_t *revision_file;
   apr_off_t root_offset;
-  svn_fs_id_t *root_id;
+  svn_fs_id_t *root_id = NULL;
   svn_boolean_t is_cached;
 
   SVN_ERR(ensure_revision_exists(fs, rev, pool));
@@ -3810,7 +3815,7 @@ svn_fs_fs__rep_contents_dir(apr_hash_t *
                             apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
-  const char *unparsed_id;
+  const char *unparsed_id = NULL;
   apr_hash_t *unparsed_entries, *parsed_entries;
 
   /* Are we looking for an immutable directory?  We could try the
@@ -3840,6 +3845,65 @@ svn_fs_fs__rep_contents_dir(apr_hash_t *
 }
 
 svn_error_t *
+svn_fs_fs__rep_contents_dir_partial(void **result_p,
+                                    svn_fs_t *fs,
+                                    node_revision_t *noderev,
+                                    svn_cache__partial_getter_func_t deserializer,
+                                    void *baton,
+                                    apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+  apr_hash_t *entries;
+  svn_boolean_t found = FALSE;
+
+  /* Are we looking for an immutable directory?  We could try the
+   * cache. */
+  if (! svn_fs_fs__id_txn_id(noderev->id))
+    {
+      const char *unparsed_id =
+          svn_fs_fs__id_unparse(noderev->id, pool)->data;
+
+      /* Cache lookup. Return on the requested part of the dir info. */
+      SVN_ERR(svn_cache__get_partial(result_p, &found, ffd->dir_cache,
+                                     unparsed_id, deserializer, baton,
+                                     pool));
+    }
+
+  if (! found)
+    {
+      char *serialized_entries;
+      apr_size_t serialized_len;
+
+      /* since we don't need the directory content later on, put it into
+         some sub-pool that will be reclaimed immedeately after exiting
+         this function successfully. Opon failure, it will live as long
+         as pool.
+       */
+      apr_pool_t *sub_pool = svn_pool_create(pool);
+
+      /* read the dir from the file system. It will probably be put it
+         into the cache for faster lookup in future calls. */
+      SVN_ERR(svn_fs_fs__rep_contents_dir(&entries, fs, noderev, sub_pool));
+
+      /* deserializer works on serialied data only. So, we need to provide
+         serialized dir entries */
+      SVN_ERR(svn_fs_fs__serialize_dir_entries(&serialized_entries,
+                                               &serialized_len,
+                                               entries,
+                                               sub_pool));
+      SVN_ERR(deserializer(result_p,
+                           serialized_entries,
+                           serialized_len,
+                           baton,
+                           pool));
+
+      apr_pool_destroy(sub_pool);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_fs_fs__get_proplist(apr_hash_t **proplist_p,
                         svn_fs_t *fs,
                         node_revision_t *noderev,

Modified: subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/fs_fs.h?rev=1072558&r1=1072557&r2=1072558&view=diff
==============================================================================
--- subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/fs_fs.h Sun Feb 20 11:20:59 2011
@@ -108,6 +108,20 @@ svn_error_t *svn_fs_fs__rep_contents_dir
                                          node_revision_t *noderev,
                                          apr_pool_t *pool);
 
+/* Set *RESULT_P to the object created by DESERIALIZER when applied
+   to the dirent structs that contain the directory entries of node-
+   revision NODEREV in filesystem FS.  A BATON will be passed to
+   the deserializer callback function to describe the object to find.
+   The returned object is allocated in POOL, which is also used for
+   temporary allocations. */
+svn_error_t *
+svn_fs_fs__rep_contents_dir_partial(void **result_p,
+                                    svn_fs_t *fs,
+                                    node_revision_t *noderev,
+                                    svn_cache__partial_getter_func_t deserializer,
+                                    void *baton,
+                                    apr_pool_t *pool);
+
 /* Set *CONTENTS to be a readable svn_stream_t that receives the text
    representation of node-revision NODEREV as seen in filesystem FS.
    Use POOL for temporary allocations. */

Modified: subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/temp_serializer.c?rev=1072558&r1=1072557&r2=1072558&view=diff
==============================================================================
--- subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/temp_serializer.c Sun Feb 20 11:20:59 2011
@@ -677,3 +677,89 @@ svn_fs_fs__deserialize_dir_entries(void 
   return SVN_NO_ERROR;
 }
 
+/* Implements svn_cache__partial_getter_func_t for manifests.
+ */
+svn_error_t *
+svn_fs_fs__get_sharded_offset(void **out,
+                              const char *data,
+                              apr_size_t data_len,
+                              void *baton,
+                              apr_pool_t *pool)
+{
+  apr_off_t *manifest = (apr_off_t *)data;
+  apr_int64_t shard_pos = *(apr_int64_t *)baton;
+
+  *(apr_int64_t *)out = manifest[shard_pos];
+
+  return SVN_NO_ERROR;
+}
+
+/* Implements svn_cache__partial_getter_func_t for a directory contents hash.
+ */
+svn_error_t *
+svn_fs_fs__extract_dir_entry(void **out,
+                             const char *data,
+                             apr_size_t data_len,
+                             void *baton,
+                             apr_pool_t *pool)
+{
+  hash_data_t *hash_data = (hash_data_t *)data;
+  const char* name = baton;
+
+  /* resolve the reference to the entries array */
+  const svn_fs_dirent_t * const *entries =
+      svn_temp_deserializer__ptr(data, (const void **)&hash_data->entries);
+
+  /* binary search for the desired entry by name */
+  apr_size_t lower = 0;
+  apr_size_t upper = hash_data->count;
+  apr_size_t middle;
+
+  for (middle = upper / 2; lower < upper; middle = (upper + lower) / 2)
+    {
+      const svn_fs_dirent_t *entry =
+          svn_temp_deserializer__ptr(entries, (const void **)&entries[middle]);
+      const char* entry_name =
+          svn_temp_deserializer__ptr(entry, (const void **)&entry->name);
+
+      int diff = strcmp(entry_name, name);
+      if (diff < 0)
+        lower = middle + 1;
+      else
+        upper = middle;
+    }
+
+  /* de-serialize that entry or return NULL, if no match has been found */
+  *out = NULL;
+  if (lower < hash_data->count)
+    {
+      const svn_fs_dirent_t *source =
+          svn_temp_deserializer__ptr(entries, (const void **)&entries[lower]);
+
+      /* Entries have been serialized one-by-one, each time including all
+       * nestes structures and strings. Therefore, they occupy a single
+       * block of memory whose end-offset is either the beginning of the
+       * next entry or the end of the buffer
+       */
+      apr_size_t end_offset = lower + 1 < hash_data->count
+                            ? ((apr_size_t*)entries)[lower+1]
+                            : data_len;
+      apr_size_t size = end_offset - ((apr_size_t*)entries)[lower];
+
+      /* copy & deserialize the entry */
+      svn_fs_dirent_t *new_entry = apr_palloc(pool, size);
+      memcpy(new_entry, source, size);
+
+      svn_temp_deserializer__resolve(new_entry, (void **)&new_entry->name);
+      if (strcmp(new_entry->name, name) == 0)
+        {
+          svn_fs_fs__id_deserialize(new_entry, (svn_fs_id_t **)&new_entry->id);
+          *(svn_fs_dirent_t **)out = new_entry;
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+

Modified: subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/temp_serializer.h?rev=1072558&r1=1072557&r2=1072558&view=diff
==============================================================================
--- subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/temp_serializer.h (original)
+++ subversion/branches/integrate-partial-getter/subversion/libsvn_fs_fs/temp_serializer.h Sun Feb 20 11:20:59 2011
@@ -166,4 +166,27 @@ svn_fs_fs__deserialize_dir_entries(void 
                                    apr_size_t data_len,
                                    apr_pool_t *pool);
 
+/**
+ * Implements @ref svn_cache__partial_getter_func_t for a single element
+ * identified by its offset in @a baton within a serialized manifest array.
+ */
+svn_error_t *
+svn_fs_fs__get_sharded_offset(void **out,
+                              const char *data,
+                              apr_size_t data_len,
+                              void *baton,
+                              apr_pool_t *pool);
+
+/**
+ * Implements @ref svn_cache__partial_getter_func_t for a single 
+ * @ref svn_fs_dirent_t within a serialized directory contents hash,
+ * identified by its name in @a baton.
+ */
+svn_error_t *
+svn_fs_fs__extract_dir_entry(void **out,
+                             const char *data,
+                             apr_size_t data_len,
+                             void *baton,
+                             apr_pool_t *pool);
+
 #endif

Modified: subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-inprocess.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-inprocess.c?rev=1072558&r1=1072557&r2=1072558&view=diff
==============================================================================
--- subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-inprocess.c (original)
+++ subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-inprocess.c Sun Feb 20 11:20:59 2011
@@ -435,13 +435,42 @@ inprocess_cache_iter(svn_boolean_t *comp
   return unlock_cache(cache,
                       svn_iter_apr_hash(completed, cache->hash, iter_cb, &b,
                                         pool));
+}
 
+static svn_error_t *
+inprocess_cache_get_partial(void **value_p,
+                            svn_boolean_t *found,
+                            void *cache_void,
+                            const void *key,
+                            svn_cache__partial_getter_func_t func,
+                            void *baton,
+                            apr_pool_t *pool)
+{
+  inprocess_cache_t *cache = cache_void;
+  struct cache_entry *entry;
+  svn_error_t *err;
+
+  SVN_ERR(lock_cache(cache));
+
+  entry = apr_hash_get(cache->hash, key, cache->klen);
+  if (! entry)
+  {
+    *found = FALSE;
+    return unlock_cache(cache, SVN_NO_ERROR);
+  }
+
+  move_page_to_front(cache, entry->page);
+
+  *found = TRUE;
+  err = func(value_p, entry->value, 0, baton, pool);
+  return unlock_cache(cache, err);
 }
 
 static svn_cache__vtable_t inprocess_cache_vtable = {
   inprocess_cache_get,
   inprocess_cache_set,
-  inprocess_cache_iter
+  inprocess_cache_iter,
+  inprocess_cache_get_partial
 };
 
 svn_error_t *

Modified: subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-membuffer.c?rev=1072558&r1=1072557&r2=1072558&view=diff
==============================================================================
--- subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-membuffer.c Sun Feb 20 11:20:59 2011
@@ -1029,6 +1029,48 @@ membuffer_cache_get_partial(svn_membuffe
   return unlock_cache(cache, err);
 }
 
+svn_error_t* 
+membuffer_cache_get_partial(svn_membuffer_t *cache,
+                            const void *key,
+                            apr_size_t key_len,
+                            void **item,
+                            svn_cache__partial_getter_func_t deserializer,
+                            void *baton,
+                            apr_pool_t *pool)
+{
+  apr_uint32_t group_index;
+  unsigned char to_find[KEY_SIZE];
+  entry_t *entry;
+  svn_error_t *err = SVN_NO_ERROR;
+
+  group_index = get_group_index(cache, key, key_len, to_find, pool);
+
+  SVN_ERR(lock_cache(cache));
+
+  entry = find_entry(cache, group_index, to_find, FALSE);
+  cache->total_reads++;
+  if (entry == NULL)
+    {
+      *item = NULL;
+    }
+  else
+    {
+      entry->hit_count++;
+      cache->hit_count++;
+      cache->total_hits++;
+
+      err = deserializer(item,
+                         (const char*)cache->data + entry->offset,
+                         entry->size,
+                         baton,
+                         pool);
+    }
+
+  /* done here -> unlock the cache
+   */
+  return unlock_cache(cache, err);
+}
+
 /* Implement the svn_cache__t interface on top of a shared membuffer cache.
  *
  * Because membuffer caches tend to be very large, there will be rather few
@@ -1267,7 +1309,8 @@ svn_membuffer_cache_is_cachable(void *ca
 static svn_cache__vtable_t membuffer_cache_vtable = {
   svn_membuffer_cache_get,
   svn_membuffer_cache_set,
-  svn_membuffer_cache_iter
+  svn_membuffer_cache_iter,
+  svn_membuffer_cache_get_partial
 };
 
 /* standard serialization function for svn_stringbuf_t items

Modified: subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-memcache.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-memcache.c?rev=1072558&r1=1072557&r2=1072558&view=diff
==============================================================================
--- subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-memcache.c (original)
+++ subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache-memcache.c Sun Feb 20 11:20:59 2011
@@ -215,6 +215,49 @@ memcache_set(void *cache_void,
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+memcache_get_partial(void **value_p,
+                     svn_boolean_t *found,
+                     void *cache_void,
+                     const void *key,
+                     svn_cache__partial_getter_func_t func,
+                     void *baton,
+                     apr_pool_t *pool)
+{
+  memcache_t *cache = cache_void;
+  svn_error_t *err;
+  apr_status_t apr_err;
+  char *data;
+  const char *mc_key;
+  apr_size_t data_len;
+  apr_pool_t *subpool = svn_pool_create(pool);
+
+  mc_key = build_key(cache, key, subpool);
+
+  apr_err = apr_memcache_getp(cache->memcache,
+                              subpool,
+                              mc_key,
+                              &data,
+                              &data_len,
+                              NULL /* ignore flags */);
+  if (apr_err == APR_NOTFOUND)
+    {
+      *found = FALSE;
+      svn_pool_destroy(subpool);
+      return SVN_NO_ERROR;
+    }
+  else if (apr_err != APR_SUCCESS || !data)
+    return svn_error_wrap_apr(apr_err,
+                              _("Unknown memcached error while reading"));
+
+  /* We found it! */
+  *found = TRUE;
+  err = func(value_p, data, data_len, baton, pool);
+
+  svn_pool_destroy(subpool);
+  return err;
+}
+
 
 static svn_error_t *
 memcache_iter(svn_boolean_t *completed,
@@ -230,7 +273,8 @@ memcache_iter(svn_boolean_t *completed,
 static svn_cache__vtable_t memcache_vtable = {
   memcache_get,
   memcache_set,
-  memcache_iter
+  memcache_iter,
+  memcache_get_partial
 };
 
 svn_error_t *

Modified: subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache.c?rev=1072558&r1=1072557&r2=1072558&view=diff
==============================================================================
--- subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache.c (original)
+++ subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache.c Sun Feb 20 11:20:59 2011
@@ -96,3 +96,21 @@ svn_cache__iter(svn_boolean_t *completed
                                pool);
 }
 
+svn_error_t *
+svn_cache__get_partial(void **value,
+                       svn_boolean_t *found,
+                       const svn_cache__t *cache,
+                       const void *key,
+                       svn_cache__partial_getter_func_t func,
+                       void *baton,
+                       apr_pool_t *scratch_pool)
+{
+  return (cache->vtable->get_partial)(value,
+                                      found,
+                                      cache->cache_internal,
+                                      key,
+                                      func,
+                                      baton,
+                                      scratch_pool);
+}
+

Modified: subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache.h?rev=1072558&r1=1072557&r2=1072558&view=diff
==============================================================================
--- subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache.h (original)
+++ subversion/branches/integrate-partial-getter/subversion/libsvn_subr/cache.h Sun Feb 20 11:20:59 2011
@@ -47,6 +47,14 @@ typedef struct svn_cache__vtable_t {
                        svn_iter_apr_hash_cb_t func,
                        void *baton,
                        apr_pool_t *pool);
+
+  svn_error_t *(*get_partial)(void **value,
+                              svn_boolean_t *found,
+                              void *cache_implementation,
+                              const void *key,
+                              svn_cache__partial_getter_func_t func,
+                              void *baton,
+                              apr_pool_t *pool);
 } svn_cache__vtable_t;
 
 struct svn_cache__t {