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;
+}