Author: stefan2
Date: Sat Apr 27 16:57:10 2013
New Revision: 1476623

URL: http://svn.apache.org/r1476623
Log:
On the fsfs-format7 branch: cache change list containters

* subversion/libsvn_fs_fs/fs.h
  (fs_fs_data_t.changes_container_cache): add cache as new member
* subversion/libsvn_fs_fs/caching.c
  (svn_fs_fs__initialize_caches): initialize the new cache for fsfs-f7

* subversion/libsvn_fs_fs/changes.h
  (svn_fs_fs__serialize_changes_container,
   svn_fs_fs__deserialize_changes_container): declare cache serialization /
                                              deserialization functions
* subversion/libsvn_fs_fs/changes.c
  (svn_fs_fs__serialize_changes_container,
   svn_fs_fs__deserialize_changes_container): implement them

* subversion/libsvn_fs_fs/cached_data.c
  (svn_fs_fs__get_changes): hit the right cache
  (block_read_changes_container): populate the new cache

Modified:
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/cached_data.c
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/caching.c
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.h
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/fs.h

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/cached_data.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/cached_data.c?rev=1476623&r1=1476622&r2=1476623&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/cached_data.c 
(original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/cached_data.c Sat 
Apr 27 16:57:10 2013
@@ -2141,50 +2141,64 @@ svn_fs_fs__get_changes(apr_array_header_
 
   /* try cache lookup first */
 
-  if (ffd->changes_cache)
+  if (ffd->changes_container_cache && is_packed_rev(fs, rev))
     {
-      SVN_ERR(svn_cache__get((void **) changes, &found, ffd->changes_cache,
-                             &rev, pool));
-      if (found)
-        {
-          SVN_ERR(dgb__log_access(fs, rev, SVN_FS_FS__ITEM_INDEX_CHANGES,
-                                  *changes, SVN_FS_FS__ITEM_TYPE_CHANGES,
-                                  pool));
+      svn_fs_fs__changes_t *container;
+      apr_off_t offset;
+      apr_uint32_t sub_item;
+      pair_cache_key_t key;
+
+      SVN_ERR(svn_fs_fs__item_offset(&offset, &sub_item, fs, rev, NULL,
+                                    SVN_FS_FS__ITEM_INDEX_CHANGES, pool));
+      key.revision = packed_base_rev(fs, rev);
+      key.second = offset;
 
-          return SVN_NO_ERROR;
-        }
+      SVN_ERR(svn_cache__get((void **)&container, &found,
+                            ffd->changes_container_cache, &key, pool));
+      if (found)
+        SVN_ERR(svn_fs_fs__changes_get_list(changes, container, sub_item,
+                                            pool));
     }
-
-  /* read changes from revision file */
-  
-  SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, pool));
-  SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&revision_file, fs, rev, pool));
-
-  if (ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT)
+  else if (ffd->changes_cache)
     {
-      /* 'block-read' will also provide us with the desired data */
-      SVN_ERR(block_read((void **)changes, fs,
-                         rev, SVN_FS_FS__ITEM_INDEX_CHANGES,
-                         revision_file, pool, pool));
+      SVN_ERR(svn_cache__get((void **) changes, &found, ffd->changes_cache,
+                             &rev, pool));
     }
-  else
+
+  if (!found)
     {
-      /* pre-format7 code path */
-      SVN_ERR(get_root_changes_offset(NULL, &changes_offset, revision_file,
-                                      fs, rev, pool));
-      SVN_ERR(svn_io_file_seek(revision_file, APR_SET, &changes_offset, pool));
-      SVN_ERR(svn_fs_fs__read_changes(changes,
-                                      svn_stream_from_aprfile2(revision_file,
-                                                               TRUE, pool),
-                                      pool));
+      /* read changes from revision file */
 
-      /* cache for future reference */
+      SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, pool));
+      SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&revision_file, fs, rev,
+                                               pool));
 
-      if (ffd->changes_cache)
-        SVN_ERR(svn_cache__set(ffd->changes_cache, &rev, *changes, pool));
-    }
+      if (ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT)
+        {
+          /* 'block-read' will also provide us with the desired data */
+          SVN_ERR(block_read((void **)changes, fs,
+                            rev, SVN_FS_FS__ITEM_INDEX_CHANGES,
+                            revision_file, pool, pool));
+        }
+      else
+        {
+          /* pre-format7 code path */
+          SVN_ERR(get_root_changes_offset(NULL, &changes_offset,
+                                          revision_file, fs, rev, pool));
+          SVN_ERR(svn_io_file_seek(revision_file, APR_SET, &changes_offset,
+                                   pool));
+          SVN_ERR(svn_fs_fs__read_changes(changes,
+                      svn_stream_from_aprfile2(revision_file, TRUE, pool),
+                                          pool));
+
+          /* cache for future reference */
 
-  SVN_ERR(svn_io_file_close(revision_file, pool));
+          if (ffd->changes_cache)
+            SVN_ERR(svn_cache__set(ffd->changes_cache, &rev, *changes, pool));
+        }
+
+      SVN_ERR(svn_io_file_close(revision_file, pool));
+    }
 
   SVN_ERR(dgb__log_access(fs, rev, SVN_FS_FS__ITEM_INDEX_CHANGES, *changes,
                           SVN_FS_FS__ITEM_TYPE_CHANGES, pool));
@@ -2419,10 +2433,23 @@ block_read_changes_container(apr_array_h
                              svn_boolean_t must_read,
                              apr_pool_t *pool)
 {
+  fs_fs_data_t *ffd = fs->fsap_data;
   svn_fs_fs__changes_t *container;
+  pair_cache_key_t key;
   svn_stream_t *stream;
-  if (!must_read)
-    return SVN_NO_ERROR;
+
+  key.revision = packed_base_rev(fs, entry->items[0].revision);
+  key.second = entry->offset;
+
+  /* already in cache? */
+  if (!must_read && ffd->changes_container_cache)
+    {
+      svn_boolean_t is_cached = FALSE;
+      SVN_ERR(svn_cache__has_key(&is_cached, ffd->changes_container_cache,
+                                 &key, pool));
+      if (is_cached)
+        return SVN_NO_ERROR;
+    }
 
   SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry, pool));
 
@@ -2432,7 +2459,12 @@ block_read_changes_container(apr_array_h
 
   /* extract requested data */
 
-  SVN_ERR(svn_fs_fs__changes_get_list(changes, container, sub_item, pool));
+  if (must_read)
+    SVN_ERR(svn_fs_fs__changes_get_list(changes, container, sub_item, pool));
+
+  if (ffd->changes_container_cache)
+    SVN_ERR(svn_cache__set(ffd->changes_container_cache, &key, container,
+                           pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/caching.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/caching.c?rev=1476623&r1=1476622&r2=1476623&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/caching.c 
(original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/caching.c Sat Apr 
27 16:57:10 2013
@@ -26,6 +26,7 @@
 #include "dag.h"
 #include "tree.h"
 #include "index.h"
+#include "changes.h"
 #include "temp_serializer.h"
 #include "../libsvn_fs/fs-loader.h"
 
@@ -581,6 +582,20 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
 
   if (ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT)
     {
+      SVN_ERR(create_cache(&(ffd->changes_container_cache),
+                           NULL,
+                           membuffer,
+                           0, 0, /* Do not use inprocess cache */
+                           svn_fs_fs__serialize_changes_container,
+                           svn_fs_fs__deserialize_changes_container,
+                           sizeof(pair_cache_key_t),
+                           apr_pstrcat(pool, prefix, "CHANGESCNT",
+                                       (char *)NULL),
+                           SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+                           fs,
+                           no_handler,
+                           fs->pool));
+
       SVN_ERR(create_cache(&(ffd->l2p_header_cache),
                            NULL,
                            membuffer,
@@ -636,6 +651,8 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
     }
   else
     {
+      ffd->changes_container_cache = NULL;
+
       ffd->l2p_header_cache = NULL;
       ffd->l2p_page_cache = NULL;
       ffd->p2l_header_cache = NULL;

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c?rev=1476623&r1=1476622&r2=1476623&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c 
(original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c Sat Apr 
27 16:57:10 2013
@@ -420,3 +420,57 @@ svn_fs_fs__read_changes_container(svn_fs
   
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_fs_fs__serialize_changes_container(void **data,
+                                       apr_size_t *data_len,
+                                       void *in,
+                                       apr_pool_t *pool)
+{
+  svn_fs_fs__changes_t *changes = in;
+  svn_stringbuf_t *serialized;
+
+  /* make a guesstimate on the size of the serialized data.  Erring on the
+   * low side will cause the serializer to re-alloc its buffer. */
+  apr_size_t size
+    = changes->changes->elt_size * changes->changes->nelts
+    + changes->offsets->elt_size * changes->offsets->nelts
+    + 10 * changes->changes->elt_size
+    + 100;
+
+  /* serialize array header and all its elements */
+  svn_temp_serializer__context_t *context
+    = svn_temp_serializer__init(changes, sizeof(*changes), size, pool);
+
+  /* serialize sub-structures */
+  svn_fs_fs__serialize_string_table(context, &changes->paths);
+  svn_fs_fs__serialize_apr_array(context, &changes->changes);
+  svn_fs_fs__serialize_apr_array(context, &changes->offsets);
+
+  /* return the serialized result */
+  serialized = svn_temp_serializer__get(context);
+
+  *data = serialized->data;
+  *data_len = serialized->len;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__deserialize_changes_container(void **out,
+                                         void *data,
+                                         apr_size_t data_len,
+                                         apr_pool_t *pool)
+{
+  svn_fs_fs__changes_t *changes = (svn_fs_fs__changes_t *)data;
+
+  /* de-serialize sub-structures */
+  svn_fs_fs__deserialize_string_table(changes, &changes->paths);
+  svn_fs_fs__deserialize_apr_array(changes, &changes->changes, pool);
+  svn_fs_fs__deserialize_apr_array(changes, &changes->offsets, pool);
+
+  /* done */
+  *out = changes;
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.h?rev=1476623&r1=1476622&r2=1476623&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.h 
(original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.h Sat Apr 
27 16:57:10 2013
@@ -98,4 +98,20 @@ svn_fs_fs__read_changes_container(svn_fs
                                   apr_pool_t *result_pool,
                                   apr_pool_t *scratch_pool);
 
+/* Implements #svn_cache__serialize_func_t for svn_fs_fs__changes_t objects.
+ */
+svn_error_t *
+svn_fs_fs__serialize_changes_container(void **data,
+                                       apr_size_t *data_len,
+                                       void *in,
+                                       apr_pool_t *pool);
+
+/* Implements #svn_cache__deserialize_func_t for svn_fs_fs__changes_t objects.
+ */
+svn_error_t *
+svn_fs_fs__deserialize_changes_container(void **out,
+                                         void *data,
+                                         apr_size_t data_len,
+                                         apr_pool_t *pool);
+
 #endif
\ No newline at end of file

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/fs.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/fs.h?rev=1476623&r1=1476622&r2=1476623&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/fs.h Sat Apr 27 
16:57:10 2013
@@ -344,6 +344,10 @@ typedef struct fs_fs_data_t
      is the revision */
   svn_cache__t *changes_cache;
 
+  /* Cache for change_list_t conatiners;
+     the key is a (pack file revision, file offset) pair */
+  svn_cache__t *changes_container_cache;
+
   /* Cache for svn_fs_fs__rep_header_t objects; the key is a
      (revision, item index) pair */
   svn_cache__t *rep_header_cache;


Reply via email to