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/22 15:46:17 UTC

svn commit: r1710017 - in /subversion/trunk/subversion: include/private/svn_atomic.h libsvn_fs_fs/caching.c libsvn_fs_fs/fs.c libsvn_fs_fs/fs.h libsvn_fs_fs/revprops.c libsvn_subr/atomic.c

Author: stefan2
Date: Thu Oct 22 13:46:16 2015
New Revision: 1710017

URL: http://svn.apache.org/viewvc?rev=1710017&view=rev
Log:
Instead of a UUID, produce a unique 64 bit number as a key prefix to FSFS'
temporary revprop cache.

This introduces a svn_atomic__unique_counter(), which uses a thread-safe
64 bit counter implementation to produce unique values.  Switching FSFS
from a UUID string to an integer key element is straight-forward.

The rationale behind this change is that the UUID generation may be very
expensive on some systems.

Suggested by: rhuijben

* subversion/include/private/svn_atomic.h
  (svn_atomic__unique_counter): Declare the new private API.

* subversion/libsvn_subr/atomic.c
  (unique_counter,
   counter_status,
   counter_mutex): New static objects for the counter itself and its
                   access serialization support.
  (init_unique_counter,
   read_unique_counter,
   svn_atomic__unique_counter): New functions implementing the new API.

* subversion/libsvn_fs_fs/fs.h
  (fs_fs_data_t): Change the prefix type to a ui64.

* subversion/libsvn_fs_fs/fs.c
  (initialize_fs_struct): Update initialization for that struct.

* subversion/libsvn_fs_fs/caching.c
  (svn_fs_fs__initialize_caches): The cache key is now a pair_cache_key_t.

* subversion/libsvn_fs_fs/revprops.c
  (svn_fs_fs__reset_revprop_cache): Update prefix reset code.
  (prepare_revprop_cache): Call the new API to generate the prefix and
                           handle errors.
  (cache_revprops,
   svn_fs_fs__get_revision_proplist): Update cache key construction.

Modified:
    subversion/trunk/subversion/include/private/svn_atomic.h
    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/revprops.c
    subversion/trunk/subversion/libsvn_subr/atomic.c

Modified: subversion/trunk/subversion/include/private/svn_atomic.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_atomic.h?rev=1710017&r1=1710016&r2=1710017&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_atomic.h (original)
+++ subversion/trunk/subversion/include/private/svn_atomic.h Thu Oct 22 13:46:16 2015
@@ -134,6 +134,21 @@ svn_atomic__init_once_no_error(volatile
                                svn_atomic__str_init_func_t str_init_func,
                                void *baton);
 
+
+/**
+ * Query and increment the global counter and set @a value to the new
+ * counter value.
+ *
+ * This function is thread-safe and you should call it whenever you need
+ * a number that is unique within the current process. The values are > 0.
+ *
+ * @return the error object in case of a synchronization failure.
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_atomic__unique_counter(apr_uint64_t* value);
+
 /** @} */
 
 #ifdef __cplusplus

Modified: subversion/trunk/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/caching.c?rev=1710017&r1=1710016&r2=1710017&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/caching.c Thu Oct 22 13:46:16 2015
@@ -513,7 +513,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                        0, 0, /* Do not use inprocess cache */
                        svn_fs_fs__serialize_revprops,
                        svn_fs_fs__deserialize_revprops,
-                       APR_HASH_KEY_STRING,
+                       sizeof(pair_cache_key_t),
                        apr_pstrcat(pool, prefix, "REVPROP", SVN_VA_NULL),
                        SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
                        TRUE, /* contents is short-lived */

Modified: subversion/trunk/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs.c?rev=1710017&r1=1710016&r2=1710017&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs.c Thu Oct 22 13:46:16 2015
@@ -291,7 +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);
+  ffd->revprop_prefix = 0;
 
   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=1710017&r1=1710016&r2=1710017&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs.h Thu Oct 22 13:46:16 2015
@@ -352,8 +352,8 @@ typedef struct fs_fs_data_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;
+     If this is 0, a new unique prefix must be chosen. */
+  apr_uint64_t revprop_prefix;
 
   /* Revision property cache.  Maps from (rev,prefix) to apr_hash_t.
      Unparsed svn_string_t representations of the serialized hash

Modified: subversion/trunk/subversion/libsvn_fs_fs/revprops.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/revprops.c?rev=1710017&r1=1710016&r2=1710017&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/revprops.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/revprops.c Thu Oct 22 13:46:16 2015
@@ -209,19 +209,21 @@ 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);
+  ffd->revprop_prefix = 0;
 }
 
 /* If FS has not a revprop cache prefix set, generate one.
  * Always call this before accessing the revprop cache.
  */
-static void
+static svn_error_t *
 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));
+  if (!ffd->revprop_prefix)
+    SVN_ERR(svn_atomic__unique_counter(&ffd->revprop_prefix));
+
+  return SVN_NO_ERROR;
 }
 
 /* Store the unparsed revprop hash CONTENT for REVISION in FS's revprop
@@ -233,15 +235,14 @@ cache_revprops(svn_fs_t *fs,
                apr_pool_t *scratch_pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
-  const char *key;
+  pair_cache_key_t key;
 
   /* Make sure prepare_revprop_cache() has been called. */
-  SVN_ERR_ASSERT(!svn_stringbuf_isempty(ffd->revprop_prefix));
-  key = svn_fs_fs__combine_number_and_string(revision,
-                                             ffd->revprop_prefix->data,
-                                             scratch_pool);
+  SVN_ERR_ASSERT(ffd->revprop_prefix);
+  key.revision = revision;
+  key.second = ffd->revprop_prefix;
 
-  SVN_ERR(svn_cache__set(ffd->revprop_cache, key, content, scratch_pool));
+  SVN_ERR(svn_cache__set(ffd->revprop_cache, &key, content, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -666,17 +667,16 @@ svn_fs_fs__get_revision_proplist(apr_has
     {
       /* Try cache lookup first. */
       svn_boolean_t is_cached;
-      const char *key;
+      pair_cache_key_t 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);
+      SVN_ERR(prepare_revprop_cache(fs, scratch_pool));
+      key.revision = rev;
+      key.second = ffd->revprop_prefix;
 
       /* 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),
+                               ffd->revprop_cache, &key, result_pool),
                 apr_psprintf(scratch_pool,
                              "Failed to parse revprops for r%ld.",
                              rev));

Modified: subversion/trunk/subversion/libsvn_subr/atomic.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/atomic.c?rev=1710017&r1=1710016&r2=1710017&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/atomic.c (original)
+++ subversion/trunk/subversion/libsvn_subr/atomic.c Thu Oct 22 13:46:16 2015
@@ -22,8 +22,11 @@
 
 #include <assert.h>
 #include <apr_time.h>
-#include "private/svn_atomic.h"
 
+#include "svn_pools.h"
+
+#include "private/svn_atomic.h"
+#include "private/svn_mutex.h"
 
 /* Magic values for atomic initialization */
 #define SVN_ATOMIC_UNINITIALIZED 0
@@ -174,3 +177,42 @@ svn_atomic__init_once_no_error(volatile
   else
     return init_baton.errstr;
 }
+
+/* The process-global counter that we use to produce process-wide unique
+ * values.  Since APR has no 64 bit atomics, all access to this will be
+ * serialized through COUNTER_MUTEX. */
+static apr_uint64_t uniqiue_counter = 0;
+
+/* The corresponding mutex and initialization state. */
+static volatile svn_atomic_t counter_status = SVN_ATOMIC_UNINITIALIZED;
+static svn_mutex__t *counter_mutex = NULL;
+
+/* svn_atomic__err_init_func_t implementation that initializes COUNTER_MUTEX.
+ * Note that neither argument will be used and should be NULL. */
+static svn_error_t *
+init_unique_counter(void *null_baton,
+                    apr_pool_t *null_pool)
+{
+  /* COUNTER_MUTEX is global, so it needs to live in a global pool.
+   * APR also makes those thread-safe by default. */
+  SVN_ERR(svn_mutex__init(&counter_mutex, TRUE, svn_pool_create(NULL)));
+  return SVN_NO_ERROR;
+}
+
+/* Read and increment UNIQIUE_COUNTER. Return the new value in *VALUE.
+ * Call this function only while having acquired the COUNTER_MUTEX. */
+static svn_error_t *
+read_unique_counter(apr_uint64_t *value)
+{
+  *value = ++uniqiue_counter;
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_atomic__unique_counter(apr_uint64_t *value)
+{
+  SVN_ERR(svn_atomic__init_once(&counter_status, init_unique_counter, NULL,
+                                NULL));
+  SVN_MUTEX__WITH_LOCK(counter_mutex, read_unique_counter(value));
+  return SVN_NO_ERROR;
+}