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 2015/10/11 16:48:13 UTC

svn commit: r1707988 - in /subversion/trunk/subversion/libsvn_fs_fs: caching.c fs.c fs.h fs_fs.c revprops.c revprops.h temp_serializer.c temp_serializer.h

Author: stefan2
Date: Sun Oct 11 14:48:13 2015
New Revision: 1707988

URL: http://svn.apache.org/viewvc?rev=1707988&view=rev
Log:
In FSFS, add the revprop cache object and its invalidation logic.
Do not write to the cache, yet.

Note that in an attempt to minimize the CPU overhead when reading
whole revprop pack files, we don't fully parse them before caching
them.  Instead, the cache expects the plain serialized hash in set()
and only parses it during get().  The overhead for the getter is very
small while the setter gets significantly faster. 

Also note that svn_fs_fs__get_revision_proplist will be the only
place where we may ever read cached revprops.  Therefore, functions
like svn_fs_fs__set_revision_proplist will never write (partially)
outdated revprops.

* subversion/libsvn_fs_fs/fs.h
  (fs_fs_data_t): Add the revprop cache and its key prefix.

* subversion/libsvn_fs_fs/caching.c
  (svn_fs_fs__initialize_caches): Construct the new cache as well.

* subversion/libsvn_fs_fs/fs.c
  (fs_refresh_revprops): This is now "invalidate revprop cache".
  (initialize_fs_struct): Initialize the new struct element.

* subversion/libsvn_fs_fs/temp_serializer.h
  (svn_fs_fs__serialize_revprops,
   svn_fs_fs__deserialize_revprops): Declare (de-)serialization functions
                                     for the new cache.

* subversion/libsvn_fs_fs/temp_serializer.c
  (svn_fs_fs__serialize_revprops,
   svn_fs_fs__deserialize_revprops): Implement them asymmetrically.

* subversion/libsvn_fs_fs/revprops.h
  (svn_fs_fs__reset_revprop_cache): Declare our new cache invalidation
                                    function.

* subversion/libsvn_fs_fs/revprops.c
  (svn_fs_fs__reset_revprop_cache): Implement.
  (prepare_revprop_cache): New utility function.
  (svn_fs_fs__get_revision_proplist): Actually evaluate the REFRESH option/
                                      sync barrier now and return cached
                                      data if available - which currently
                                      is never the case.
  (svn_fs_fs__set_revision_proplist): After we changed revprops, we *know*
                                      our cache is invalid. IOW, write
                                      implies a barrier.

* subversion/libsvn_fs_fs/fs_fs.c
  (change_rev_prop_body): Document why we need the "refresh" option here.

Modified:
    subversion/trunk/subversion/libsvn_fs_fs/caching.c
    subversion/trunk/subversion/libsvn_fs_fs/fs.c
    subversion/trunk/subversion/libsvn_fs_fs/fs.h
    subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c
    subversion/trunk/subversion/libsvn_fs_fs/revprops.c
    subversion/trunk/subversion/libsvn_fs_fs/revprops.h
    subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c
    subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.h

Modified: subversion/trunk/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/caching.c?rev=1707988&r1=1707987&r2=1707988&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/caching.c Sun Oct 11 14:48:13 2015
@@ -506,6 +506,21 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                        no_handler,
                        fs->pool, pool));
 
+  /* if enabled, cache revprops */
+  SVN_ERR(create_cache(&(ffd->revprop_cache),
+                       NULL,
+                       membuffer,
+                       0, 0, /* Do not use inprocess cache */
+                       svn_fs_fs__serialize_revprops,
+                       svn_fs_fs__deserialize_revprops,
+                       APR_HASH_KEY_STRING,
+                       apr_pstrcat(pool, prefix, "REVPROP", SVN_VA_NULL),
+                       SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+                       TRUE, /* contents is short-lived */
+                       fs,
+                       no_handler,
+                       fs->pool, pool));
+
   /* if enabled, cache fulltext and other derived information */
   if (cache_fulltexts)
     {

Modified: subversion/trunk/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs.c?rev=1707988&r1=1707987&r2=1707988&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs.c Sun Oct 11 14:48:13 2015
@@ -152,6 +152,8 @@ static svn_error_t *
 fs_refresh_revprops(svn_fs_t *fs,
                     apr_pool_t *scratch_pool)
 {
+  svn_fs_fs__reset_revprop_cache(fs);
+
   return SVN_NO_ERROR;
 }
 
@@ -289,6 +291,7 @@ initialize_fs_struct(svn_fs_t *fs)
 {
   fs_fs_data_t *ffd = apr_pcalloc(fs->pool, sizeof(*ffd));
   ffd->use_log_addressing = FALSE;
+  ffd->revprop_prefix = svn_stringbuf_create_empty(fs->pool);
 
   fs->vtable = &fs_vtable;
   fs->fsap_data = ffd;

Modified: subversion/trunk/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs.h?rev=1707988&r1=1707987&r2=1707988&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs.h Sun Oct 11 14:48:13 2015
@@ -351,6 +351,15 @@ typedef struct fs_fs_data_t
      rep key (revision/offset) to svn_stringbuf_t. */
   svn_cache__t *fulltext_cache;
 
+  /* The current prefix to be used for revprop cache entries.
+     If this string is empty, a new unique prefix must be chosen. */
+  svn_stringbuf_t *revprop_prefix;
+
+  /* Revision property cache.  Maps from (rev,prefix) to apr_hash_t.
+     Unparsed svn_string_t representations of the serialized hash
+     will be written to the cache but the getter returns apr_hash_t. */
+  svn_cache__t *revprop_cache;
+
   /* Node properties cache.  Maps from rep key to apr_hash_t. */
   svn_cache__t *properties_cache;
 

Modified: subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c?rev=1707988&r1=1707987&r2=1707988&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c Sun Oct 11 14:48:13 2015
@@ -2093,6 +2093,8 @@ change_rev_prop_body(void *baton, apr_po
   apr_hash_t *table;
   const svn_string_t *present_value;
 
+  /* We always need to read the current revprops from disk.
+   * Hence, always "refresh" here. */
   SVN_ERR(svn_fs_fs__get_revision_proplist(&table, cb->fs, cb->rev, TRUE,
                                            pool, pool));
   present_value = svn_hash_gets(table, cb->name);

Modified: subversion/trunk/subversion/libsvn_fs_fs/revprops.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/revprops.c?rev=1707988&r1=1707987&r2=1707988&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/revprops.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/revprops.c Sun Oct 11 14:48:13 2015
@@ -28,6 +28,7 @@
 
 #include "fs_fs.h"
 #include "revprops.h"
+#include "temp_serializer.h"
 #include "util.h"
 
 #include "private/svn_subr_private.h"
@@ -204,6 +205,25 @@ parse_revprop(apr_hash_t **properties,
   return SVN_NO_ERROR;
 }
 
+void
+svn_fs_fs__reset_revprop_cache(svn_fs_t *fs)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+  svn_stringbuf_setempty(ffd->revprop_prefix);
+}
+
+/* If FS has not a revprop cache prefix set, generate one.
+ * Always call this before accessing the revprop cache.
+ */
+static void
+prepare_revprop_cache(svn_fs_t *fs,
+                      apr_pool_t *scratch_pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+  if (svn_stringbuf_isempty(ffd->revprop_prefix))
+    svn_stringbuf_set(ffd->revprop_prefix, svn_uuid_generate(scratch_pool));
+}
+
 /* Read the non-packed revprops for revision REV in FS, put them into the
  * revprop cache if activated and return them in *PROPERTIES. 
  *
@@ -599,6 +619,33 @@ svn_fs_fs__get_revision_proplist(apr_has
   /* should they be available at all? */
   SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, scratch_pool));
 
+  if (refresh)
+    {
+      /* Previous cache contents is invalid now. */
+      svn_fs_fs__reset_revprop_cache(fs);
+    }
+  else
+    {
+      /* Try cache lookup first. */
+      svn_boolean_t is_cached;
+      const char *key;
+
+      /* Auto-alloc prefix and construct the key. */
+      prepare_revprop_cache(fs, scratch_pool);
+      key = svn_fs_fs__combine_number_and_string(rev,
+                                                 ffd->revprop_prefix->data,
+                                                 scratch_pool);
+
+      /* The only way that this might error out is due to parser error. */
+      SVN_ERR_W(svn_cache__get((void **) proplist_p, &is_cached,
+                               ffd->revprop_cache, key, result_pool),
+                apr_psprintf(scratch_pool,
+                             "Failed to parse revprops for r%ld.",
+                             rev));
+      if (is_cached)
+        return SVN_NO_ERROR;
+    }
+
   /* if REV had not been packed when we began, try reading it from the
    * non-packed shard.  If that fails, we will fall through to packed
    * shard reads. */
@@ -1061,6 +1108,9 @@ svn_fs_fs__set_revision_proplist(svn_fs_
     SVN_ERR(write_non_packed_revprop(&final_path, &tmp_path,
                                      fs, rev, proplist, pool));
 
+  /* Previous cache contents is invalid now. */
+  svn_fs_fs__reset_revprop_cache(fs);
+
   /* We use the rev file of this revision as the perms reference,
    * because when setting revprops for the first time, the revprop
    * file won't exist and therefore can't serve as its own reference.

Modified: subversion/trunk/subversion/libsvn_fs_fs/revprops.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/revprops.h?rev=1707988&r1=1707987&r2=1707988&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/revprops.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/revprops.h Sun Oct 11 14:48:13 2015
@@ -58,6 +58,10 @@ svn_fs_fs__upgrade_cleanup_pack_revprops
                                          void *cancel_baton,
                                          apr_pool_t *scratch_pool);
 
+/* Invalidate the revprop cache in FS. */
+void
+svn_fs_fs__reset_revprop_cache(svn_fs_t *fs);
+
 /* Read the revprops for revision REV in FS and return them in *PROPERTIES_P.
  * If REFRESH is set, clear the revprop cache before accessing the data.
  *

Modified: subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c?rev=1707988&r1=1707987&r2=1707988&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c Sun Oct 11 14:48:13 2015
@@ -663,6 +663,44 @@ svn_fs_fs__deserialize_properties(void *
 }
 
 svn_error_t *
+svn_fs_fs__serialize_revprops(void **data,
+                              apr_size_t *data_len,
+                              void *in,
+                              apr_pool_t *pool)
+{
+  svn_string_t *buffer = in;
+
+  *data = (void *)buffer->data;
+  *data_len = buffer->len;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__deserialize_revprops(void **out,
+                                void *data,
+                                apr_size_t data_len,
+                                apr_pool_t *pool)
+{
+  apr_hash_t *properties;
+  svn_stream_t *stream;
+
+  svn_string_t buffer;
+  buffer.data = data;
+  buffer.len = data_len;
+
+  stream = svn_stream_from_string(&buffer, pool);
+  properties = svn_hash__make(pool);
+
+  SVN_ERR(svn_hash_read2(properties, stream, SVN_HASH_TERMINATOR, pool));
+
+  /* done */
+  *out = properties;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_fs_fs__serialize_id(void **data,
                         apr_size_t *data_len,
                         void *in,

Modified: subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.h?rev=1707988&r1=1707987&r2=1707988&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.h Sun Oct 11 14:48:13 2015
@@ -156,6 +156,26 @@ svn_fs_fs__deserialize_properties(void *
                                   apr_pool_t *pool);
 
 /**
+ * Implements #svn_cache__serialize_func_t for a properties hash
+ * (@a in is an #apr_hash_t of svn_string_t elements, keyed by const char*).
+ */
+svn_error_t *
+svn_fs_fs__serialize_revprops(void **data,
+                              apr_size_t *data_len,
+                              void *in,
+                              apr_pool_t *pool);
+
+/**
+ * Implements #svn_cache__deserialize_func_t for a properties hash
+ * (@a *out is an #apr_hash_t of svn_string_t elements, keyed by const char*).
+ */
+svn_error_t *
+svn_fs_fs__deserialize_revprops(void **out,
+                                void *data,
+                                apr_size_t data_len,
+                                apr_pool_t *pool);
+
+/**
  * Implements #svn_cache__serialize_func_t for #svn_fs_id_t
  */
 svn_error_t *