You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by sv...@apache.org on 2013/11/13 05:02:46 UTC

svn commit: r1541379 - in /subversion/branches/1.7.x: ./ STATUS subversion/libsvn_subr/svn_cache_config.c

Author: svn-role
Date: Wed Nov 13 04:02:45 2013
New Revision: 1541379

URL: http://svn.apache.org/r1541379
Log:
Merge the 1.7.x-r1527103 branch:

 * r1527112
   Fix OOM with concurrent requests right after threaded server start.
   Changes:
     This was a common condition in my load tests.  Affects threaded
     servers only.  Apache will just respawn a new worker process.
   Branch:
     ^/subversion/branches/1.7.x-r1527103
   Votes:
     +1: stefan2, brane, breser

Modified:
    subversion/branches/1.7.x/   (props changed)
    subversion/branches/1.7.x/STATUS
    subversion/branches/1.7.x/subversion/libsvn_subr/svn_cache_config.c   (contents, props changed)

Propchange: subversion/branches/1.7.x/
------------------------------------------------------------------------------
  Merged /subversion/trunk:r1527103,1527105
  Merged /subversion/branches/1.7.x-r1527103:r1527110-1541378

Modified: subversion/branches/1.7.x/STATUS
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/STATUS?rev=1541379&r1=1541378&r2=1541379&view=diff
==============================================================================
--- subversion/branches/1.7.x/STATUS (original)
+++ subversion/branches/1.7.x/STATUS Wed Nov 13 04:02:45 2013
@@ -95,16 +95,6 @@ Veto-blocked changes:
 Approved changes:
 =================
 
- * r1527112
-   Fix OOM with concurrent requests right after threaded server start.
-   Changes:
-     This was a common condition in my load tests.  Affects threaded
-     servers only.  Apache will just respawn a new worker process.
-   Branch:
-     ^/subversion/branches/1.7.x-r1527103
-   Votes:
-     +1: stefan2, brane, breser
-
  * r1536790
    Limit the time spent in committing files with deep change histories
    Justification:

Modified: subversion/branches/1.7.x/subversion/libsvn_subr/svn_cache_config.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/libsvn_subr/svn_cache_config.c?rev=1541379&r1=1541378&r2=1541379&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/libsvn_subr/svn_cache_config.c (original)
+++ subversion/branches/1.7.x/subversion/libsvn_subr/svn_cache_config.c Wed Nov 13 04:02:45 2013
@@ -23,6 +23,7 @@
 #include <apr_atomic.h>
 
 #include "svn_cache_config.h"
+#include "private/svn_atomic.h"
 #include "private/svn_cache.h"
 
 #include "svn_pools.h"
@@ -69,30 +70,27 @@ svn_cache_config_get(void)
   return &cache_settings;
 }
 
-/* Access the process-global (singleton) membuffer cache. The first call
- * will automatically allocate the cache using the current cache config.
- * NULL will be returned if the desired cache size is 0 or if the cache
- * could not be created for some reason.
+/* Initializer function as required by svn_atomic__init_once.  Allocate
+ * the process-global (singleton) membuffer cache and return it in the
+ * svn_membuffer_t * in *BATON.  UNUSED_POOL is unused and should be NULL.
  */
-svn_membuffer_t *
-svn_cache__get_global_membuffer_cache(void)
+static svn_error_t *
+initialize_cache(void *baton, apr_pool_t *unused_pool)
 {
-  static svn_membuffer_t * volatile cache = NULL;
+  svn_membuffer_t **cache_p = baton;
+  svn_membuffer_t *cache = NULL;
 
   apr_uint64_t cache_size = cache_settings.cache_size;
-  if (!cache && cache_size)
+  if (cache_size)
     {
       svn_error_t *err;
 
-      svn_membuffer_t *old_cache = NULL;
-      svn_membuffer_t *new_cache = NULL;
-
       /* auto-allocate cache */
       apr_allocator_t *allocator = NULL;
       apr_pool_t *pool = NULL;
 
       if (apr_allocator_create(&allocator))
-        return NULL;
+        return SVN_NO_ERROR;
 
       /* Ensure that we free partially allocated data if we run OOM
        * before the cache is complete: If the cache cannot be allocated
@@ -112,48 +110,55 @@ svn_cache__get_global_membuffer_cache(vo
        */
       apr_pool_create_ex(&pool, NULL, NULL, allocator);
       if (pool == NULL)
-        return NULL;
+        return SVN_NO_ERROR;
       apr_allocator_owner_set(allocator, pool);
 
       err = svn_cache__membuffer_cache_create(
-          &new_cache,
+          &cache,
           (apr_size_t)cache_size,
           (apr_size_t)(cache_size / 16),
           ! svn_cache_config_get()->single_threaded,
           pool);
 
-      /* Some error occured. Most likely it's an OOM error but we don't
+      /* Some error occurred. Most likely it's an OOM error but we don't
        * really care. Simply release all cache memory and disable caching
        */
       if (err)
         {
-          /* Memory and error cleanup */
-          svn_error_clear(err);
-          apr_pool_destroy(pool);
-
-          /* Prevent future attempts to create the cache. However, an
-           * existing cache instance (see next comment) remains valid.
-           */
+          /* Memory cleanup */
+          svn_pool_destroy(pool);
+
+          /* Document that we actually don't have a cache. */
           cache_settings.cache_size = 0;
 
-          /* The current caller won't get the cache object.
-           * However, a concurrent call might have succeeded in creating
-           * the cache object. That call and all following ones will then
-           * use the successfully created cache instance.
-           */
-          return NULL;
+          return svn_error_trace(err);
         }
 
-      /* Handle race condition: if we are the first to create a
-       * cache object, make it our global singleton. Otherwise,
-       * discard the new cache and keep the existing one.
-       *
-       * Cast is necessary because of APR bug:
-       * https://issues.apache.org/bugzilla/show_bug.cgi?id=50731
-       */
-      old_cache = apr_atomic_casptr((volatile void **)&cache, new_cache, NULL);
-      if (old_cache != NULL)
-        apr_pool_destroy(pool);
+      /* done */
+      *cache_p = cache;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Access the process-global (singleton) membuffer cache. The first call
+ * will automatically allocate the cache using the current cache config.
+ * NULL will be returned if the desired cache size is 0 or if the cache
+ * could not be created for some reason.
+ */
+svn_membuffer_t *
+svn_cache__get_global_membuffer_cache(void)
+{
+  static svn_membuffer_t *cache = NULL;
+  static svn_atomic_t initialized = 0;
+
+  svn_error_t *err
+    = svn_atomic__init_once(&initialized, initialize_cache, &cache, NULL);
+  if (err)
+    {
+      /* no caches today ... */
+      svn_error_clear(err);
+      return NULL;
     }
 
   return cache;

Propchange: subversion/branches/1.7.x/subversion/libsvn_subr/svn_cache_config.c
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-r1527103/subversion/libsvn_subr/svn_cache_config.c:r1527110-1541378