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/12/16 11:35:07 UTC

svn commit: r1215083 - in /subversion/trunk/subversion: include/private/svn_cache.h libsvn_fs_fs/caching.c libsvn_subr/cache-membuffer.c tests/libsvn_subr/cache-test.c

Author: stefan2
Date: Fri Dec 16 10:35:06 2011
New Revision: 1215083

URL: http://svn.apache.org/viewvc?rev=1215083&view=rev
Log:
Offer optional thread-safety for membuffer cache frontends
(actual data container / backend is already thread-safe).
The membuffer cache is now on par with inprocess cache
features.

* subversion/include/private/svn_cache.h
  (svn_cache__create_membuffer_cache): add thread_safe parameter
* subversion/libsvn_subr/cache-membuffer.c
  (svn_membuffer_cache_t): add optional mutex
  (svn_membuffer_cache_get, svn_membuffer_cache_set,
   svn_membuffer_cache_get_partial, svn_membuffer_cache_set_partial,
   svn_membuffer_cache_is_cachable, svn_membuffer_cache_get_info,
   membuffer_cache_vtable): mark as non-sync'ing in docstring
  (svn_membuffer_cache_get_synced, svn_membuffer_cache_set_synced,
   svn_membuffer_cache_get_partial_synced,
   svn_membuffer_cache_set_partial_synced): new sync'ing wrappers
   around the non-sync'ing implementations
  (membuffer_cache_synced_vtable): new vtable for sync'ing caches
  (svn_cache__create_membuffer_cache): depending on thread_safe
   parameter, initialize mutex and select proper vtable

* subversion/libsvn_fs_fs/caching.c
  (create_cache): adapt caller to provided additional parameter
* subversion/tests/libsvn_subr/cache-test.c
  (test_membuffer_cache_basic): dito

Modified:
    subversion/trunk/subversion/include/private/svn_cache.h
    subversion/trunk/subversion/libsvn_fs_fs/caching.c
    subversion/trunk/subversion/libsvn_subr/cache-membuffer.c
    subversion/trunk/subversion/tests/libsvn_subr/cache-test.c

Modified: subversion/trunk/subversion/include/private/svn_cache.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_cache.h?rev=1215083&r1=1215082&r2=1215083&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_cache.h (original)
+++ subversion/trunk/subversion/include/private/svn_cache.h Fri Dec 16 10:35:06 2011
@@ -295,8 +295,9 @@ svn_cache__membuffer_cache_create(svn_me
  * svn_string_t; if @a serialize_func is NULL, then the data is
  * assumed to be an svn_stringbuf_t.
  *
- * These caches themselves are thread safe, the shared @a memcache may
- * be not, depending on its creation parameters.
+ * If @a thread_safe is true, and APR is compiled with threads, all
+ * accesses to the cache will be protected with a mutex, if the shared 
+ * @a memcache has also been created with thread_safe flag set.
  *
  * These caches do not support svn_cache__iter.
  */
@@ -307,6 +308,7 @@ svn_cache__create_membuffer_cache(svn_ca
                                   svn_cache__deserialize_func_t deserialize,
                                   apr_ssize_t klen,
                                   const char *prefix,
+                                  svn_boolean_t thread_safe,
                                   apr_pool_t *result_pool);
 
 /**

Modified: subversion/trunk/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/caching.c?rev=1215083&r1=1215082&r2=1215083&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/caching.c Fri Dec 16 10:35:06 2011
@@ -219,7 +219,7 @@ create_cache(svn_cache__t **cache_p,
       {
         SVN_ERR(svn_cache__create_membuffer_cache(
                   cache_p, membuffer, serializer, deserializer,
-                  klen, prefix, pool));
+                  klen, prefix, FALSE, pool));
       }
     else if (pages)
       {

Modified: subversion/trunk/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/cache-membuffer.c?rev=1215083&r1=1215082&r2=1215083&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/trunk/subversion/libsvn_subr/cache-membuffer.c Fri Dec 16 10:35:06 2011
@@ -1567,6 +1567,9 @@ typedef struct svn_membuffer_cache_t
    */
   int alloc_counter;
 
+  /* if enabled, this will serialize the access to this instance.
+   */
+  svn_mutex__t *mutex;
 #ifdef SVN_DEBUG_CACHE_MEMBUFFER
 
   /* Invariant tag info for all items stored by this cache instance.
@@ -1604,7 +1607,7 @@ combine_key(const void *prefix,
   memcpy((char *)*full_key + prefix_len, key, key_len);
 }
 
-/* Implement svn_cache__vtable_t.get
+/* Implement svn_cache__vtable_t.get (not thread-safe)
  */
 static svn_error_t *
 svn_membuffer_cache_get(void **value_p,
@@ -1655,7 +1658,7 @@ svn_membuffer_cache_get(void **value_p,
   return SVN_NO_ERROR;
 }
 
-/* Implement svn_cache__vtable_t.set
+/* Implement svn_cache__vtable_t.set (not thread-safe)
  */
 static svn_error_t *
 svn_membuffer_cache_set(void *cache_void,
@@ -1716,7 +1719,7 @@ svn_membuffer_cache_iter(svn_boolean_t *
                           _("Can't iterate a membuffer-based cache"));
 }
 
-/* Implement svn_cache__vtable_t.get_partial
+/* Implement svn_cache__vtable_t.get_partial (not thread-safe)
  */
 static svn_error_t *
 svn_membuffer_cache_get_partial(void **value_p,
@@ -1761,7 +1764,7 @@ svn_membuffer_cache_get_partial(void **v
   return SVN_NO_ERROR;
 }
 
-/* Implement svn_cache__vtable_t.set_partial
+/* Implement svn_cache__vtable_t.set_partial (not thread-safe)
  */
 static svn_error_t *
 svn_membuffer_cache_set_partial(void *cache_void,
@@ -1797,6 +1800,7 @@ svn_membuffer_cache_set_partial(void *ca
 }
 
 /* Implement svn_cache__vtable_t.is_cachable
+ * (thread-safe even without mutex)
  */
 static svn_boolean_t
 svn_membuffer_cache_is_cachable(void *cache_void, apr_size_t size)
@@ -1828,6 +1832,7 @@ svn_membuffer_get_segment_info(svn_membu
 }
 
 /* Implement svn_cache__vtable_t.get_info
+ * (thread-safe even without mutex)
  */
 static svn_error_t *
 svn_membuffer_cache_get_info(void *cache_void,
@@ -1862,7 +1867,7 @@ svn_membuffer_cache_get_info(void *cache
 }
 
 
-/* the v-table for membuffer-based caches
+/* the v-table for membuffer-based caches (single-threaded access)
  */
 static svn_cache__vtable_t membuffer_cache_vtable = {
   svn_membuffer_cache_get,
@@ -1874,6 +1879,100 @@ static svn_cache__vtable_t membuffer_cac
   svn_membuffer_cache_get_info
 };
 
+/* Implement svn_cache__vtable_t.get and serialize all cache access.
+ */
+static svn_error_t *
+svn_membuffer_cache_get_synced(void **value_p,
+                               svn_boolean_t *found,
+                               void *cache_void,
+                               const void *key,
+                               apr_pool_t *result_pool)
+{
+  svn_membuffer_cache_t *cache = cache_void;
+  SVN_MUTEX__WITH_LOCK(cache->mutex, 
+                       svn_membuffer_cache_get(value_p,
+                                               found,
+                                               cache_void,
+                                               key,
+                                               result_pool));
+  
+  return SVN_NO_ERROR;
+}
+
+/* Implement svn_cache__vtable_t.set and serialize all cache access.
+ */
+static svn_error_t *
+svn_membuffer_cache_set_synced(void *cache_void,
+                               const void *key,
+                               void *value,
+                               apr_pool_t *scratch_pool)
+{
+  svn_membuffer_cache_t *cache = cache_void;
+  SVN_MUTEX__WITH_LOCK(cache->mutex, 
+                       svn_membuffer_cache_set(cache_void,
+                                               key,
+                                               value,
+                                               scratch_pool));
+  
+  return SVN_NO_ERROR;
+}
+
+/* Implement svn_cache__vtable_t.get_partial and serialize all cache access.
+ */
+static svn_error_t *
+svn_membuffer_cache_get_partial_synced(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 *result_pool)
+{
+  svn_membuffer_cache_t *cache = cache_void;
+  SVN_MUTEX__WITH_LOCK(cache->mutex, 
+                       svn_membuffer_cache_get_partial(value_p,
+                                                       found,
+                                                       cache_void,
+                                                       key,
+                                                       func,
+                                                       baton,
+                                                       result_pool));
+  
+  return SVN_NO_ERROR;
+}
+
+/* Implement svn_cache__vtable_t.set_partial and serialize all cache access.
+ */
+static svn_error_t *
+svn_membuffer_cache_set_partial_synced(void *cache_void,
+                                       const void *key,
+                                       svn_cache__partial_setter_func_t func,
+                                       void *baton,
+                                       apr_pool_t *scratch_pool)
+{
+  svn_membuffer_cache_t *cache = cache_void;
+  SVN_MUTEX__WITH_LOCK(cache->mutex, 
+                       svn_membuffer_cache_set_partial(cache_void,
+                                                       key,
+                                                       func,
+                                                       baton,
+                                                       scratch_pool));
+  
+  return SVN_NO_ERROR;
+}
+
+/* the v-table for membuffer-based caches with multi-threading support)
+ */
+static svn_cache__vtable_t membuffer_cache_synced_vtable = {
+  svn_membuffer_cache_get_synced,
+  svn_membuffer_cache_set_synced,
+  svn_membuffer_cache_iter,               /* no sync required */
+  svn_membuffer_cache_is_cachable,        /* no sync required */
+  svn_membuffer_cache_get_partial_synced,
+  svn_membuffer_cache_set_partial_synced,
+  svn_membuffer_cache_get_info            /* no sync required */
+};
+
 /* standard serialization function for svn_stringbuf_t items.
  * Implements svn_cache__serialize_func_t.
  */
@@ -1918,6 +2017,7 @@ svn_cache__create_membuffer_cache(svn_ca
                                   svn_cache__deserialize_func_t deserializer,
                                   apr_ssize_t klen,
                                   const char *prefix,
+                                  svn_boolean_t thread_safe,
                                   apr_pool_t *pool)
 {
   svn_checksum_t *checksum;
@@ -1941,6 +2041,8 @@ svn_cache__create_membuffer_cache(svn_ca
   cache->pool = svn_pool_create(pool);
   cache->alloc_counter = 0;
 
+  SVN_ERR(svn_mutex__init(&cache->mutex, thread_safe, pool));
+  
   /* for performance reasons, we don't actually store the full prefix but a
    * hash value of it
    */
@@ -1961,7 +2063,8 @@ svn_cache__create_membuffer_cache(svn_ca
 
   /* initialize the generic cache wrapper
    */
-  wrapper->vtable = &membuffer_cache_vtable;
+  wrapper->vtable = thread_safe ? &membuffer_cache_synced_vtable 
+                                : &membuffer_cache_vtable;
   wrapper->cache_internal = cache;
   wrapper->error_handler = 0;
   wrapper->error_baton = 0;

Modified: subversion/trunk/subversion/tests/libsvn_subr/cache-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_subr/cache-test.c?rev=1215083&r1=1215082&r2=1215083&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_subr/cache-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_subr/cache-test.c Fri Dec 16 10:35:06 2011
@@ -193,6 +193,7 @@ test_membuffer_cache_basic(apr_pool_t *p
                                             deserialize_revnum,
                                             APR_HASH_KEY_STRING,
                                             "cache:",
+                                            FALSE,
                                             pool));
 
   return basic_cache_test(cache, FALSE, pool);