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 2017/05/27 14:14:56 UTC

svn commit: r1796399 - in /subversion/trunk/subversion: libsvn_fs_x/batch_fsync.c libsvn_ra/ra_loader.c libsvn_repos/dump.c libsvn_subr/pool.c svnadmin/svnadmin.c

Author: stefan2
Date: Sat May 27 14:14:55 2017
New Revision: 1796399

URL: http://svn.apache.org/viewvc?rev=1796399&view=rev
Log:
m

Modified:
    subversion/trunk/subversion/libsvn_fs_x/batch_fsync.c
    subversion/trunk/subversion/libsvn_ra/ra_loader.c
    subversion/trunk/subversion/libsvn_repos/dump.c
    subversion/trunk/subversion/libsvn_subr/pool.c
    subversion/trunk/subversion/svnadmin/svnadmin.c

Modified: subversion/trunk/subversion/libsvn_fs_x/batch_fsync.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/batch_fsync.c?rev=1796399&r1=1796398&r2=1796399&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/batch_fsync.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/batch_fsync.c Sat May 27 14:14:55 2017
@@ -228,6 +228,7 @@ struct svn_fs_x__batch_fsync_t
 
 /* Thread pool to execute the fsync tasks. */
 static apr_thread_pool_t *thread_pool = NULL;
+static apr_pool_t *threadsafe_pool = NULL;
 
 #endif
 
@@ -247,14 +248,18 @@ static svn_atomic_t thread_pool_initiali
 static apr_status_t
 thread_pool_pre_cleanup(void *data)
 {
+  apr_status_t result;
   apr_thread_pool_t *tp = thread_pool;
   if (!thread_pool)
     return APR_SUCCESS;
 
   thread_pool = NULL;
+  threadsafe_pool = NULL;
   thread_pool_initialized = FALSE;
 
-  return apr_thread_pool_destroy(tp);
+  result = apr_thread_pool_destroy(tp);
+  apr_sleep(1000);
+  return result;
 }
 
 #endif
@@ -267,7 +272,11 @@ create_thread_pool(void *baton,
 #if APR_HAS_THREADS
   /* The thread-pool must be allocated from a thread-safe pool.
      GLOBAL_POOL may be single-threaded, though. */
-  apr_pool_t *pool = svn_pool_create(NULL);
+  apr_allocator_t *allocator = apr_pool_allocator_get(owning_pool);
+  apr_pool_t *pool = apr_allocator_mutex_get(allocator)
+                   ? owning_pool
+                   : svn_pool_create(NULL);
+  pool = owning_pool;
 
   /* This thread pool will get cleaned up automatically when GLOBAL_POOL
      gets cleared.  No additional cleanup callback is needed. */
@@ -277,8 +286,9 @@ create_thread_pool(void *baton,
   /* Work around an APR bug:  The cleanup must happen in the pre-cleanup
      hook instead of the normal cleanup hook.  Otherwise, the sub-pools
      containing the thread objects would already be invalid. */
-  apr_pool_pre_cleanup_register(pool, NULL, thread_pool_pre_cleanup);
   apr_pool_pre_cleanup_register(owning_pool, NULL, thread_pool_pre_cleanup);
+  if (pool != owning_pool)
+    apr_pool_pre_cleanup_register(pool, NULL, thread_pool_pre_cleanup);
 
   /* let idle threads linger for a while in case more requests are
      coming in */

Modified: subversion/trunk/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra/ra_loader.c?rev=1796399&r1=1796398&r2=1796399&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/trunk/subversion/libsvn_ra/ra_loader.c Sat May 27 14:14:55 2017
@@ -56,7 +56,10 @@
 #include "private/svn_ra_private.h"
 #include "svn_private_config.h"
 
-
+#ifdef SVN_LIBSVN_RA_LINKS_RA_LOCAL
+/* for svn_fs_initialize(). */
+#include "svn_fs.h"
+#endif
 
 
 /* These are the URI schemes that the respective libraries *may* support.
@@ -237,6 +240,20 @@ svn_error_t *svn_ra_initialize(apr_pool_
      we're going to use it. */
   SVN_ERR(svn_dso_initialize2());
 #endif
+
+#ifdef SVN_LIBSVN_RA_LINKS_RA_LOCAL
+  /* Make sure we initialize the FS layer with an appropriate base pool.
+   * POOL will live long enough but can be cleaned up explicitly by the
+   * using application.  That prevents cleanup / threading races during
+   * the termination phase.  See also http://www.luke1410.de/blog/?p=95
+   *
+   * The client does not know that the FS layer needs to be initialized
+   * when it wants to use RA local.  Due to missing interface guarantees,
+   * we cannot pass an appropriate pool to ra_local's initialization
+   * routine.  Hence the explicit call here.
+   */
+  SVN_ERR(svn_fs_initialize(pool));
+#endif
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/dump.c?rev=1796399&r1=1796398&r2=1796399&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/dump.c (original)
+++ subversion/trunk/subversion/libsvn_repos/dump.c Sat May 27 14:14:55 2017
@@ -20,8 +20,9 @@
  * ====================================================================
  */
 
-
 #include <stdarg.h>
+#include <apr_thread_pool.h>
+#include <apr_time.h>
 
 #include "svn_private_config.h"
 #include "svn_pools.h"
@@ -44,6 +45,7 @@
 #include "private/svn_sorts_private.h"
 #include "private/svn_utf_private.h"
 #include "private/svn_cache.h"
+#include "private/svn_subr_private.h"
 
 #define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
 
@@ -2391,6 +2393,202 @@ report_error(svn_revnum_t revision,
     }
 }
 
+typedef struct verification_job_t
+{
+  svn_fs_t *fs;
+  svn_revnum_t first_rev;
+  svn_revnum_t last_rev;
+  svn_revnum_t start_rev;
+  svn_boolean_t check_normalization;
+  svn_repos_notify_func_t notify_func;
+  void *notify_baton;
+  svn_cancel_func_t cancel_func;
+  void *cancel_baton;
+  svn_root_pools__t *pools;
+  svn_error_t *result;
+  svn_mutex__t *mutex;
+  apr_array_header_t *fs_instances;
+} verification_job_t;
+
+typedef struct fs_instance_t
+{
+  svn_fs_t *fs;
+  apr_pool_t *pool;
+} fs_instance_t;
+
+/* Thread-pool task Flush the to_sync_t instance given by DATA. */
+static void * APR_THREAD_FUNC
+verify_task(apr_thread_t *tid,
+            void *data)
+{
+  verification_job_t *baton = data;
+  fs_instance_t *instance;
+  svn_error_t *err = SVN_NO_ERROR;
+
+  SVN_ERR(svn_mutex__lock(baton->mutex));
+  if (baton->fs_instances->nelts)
+    {
+      instance = *(fs_instance_t **)apr_array_pop(baton->fs_instances);
+    }
+  else
+    {
+      apr_pool_t *pool = svn_root_pools__acquire_pool(baton->pools);
+      instance = apr_pcalloc(pool, sizeof(*instance));
+      instance->pool = pool;
+
+      SVN_ERR(svn_fs_open2(&instance->fs,
+                           svn_fs_path(baton->fs, pool),
+                           svn_fs_config(baton->fs, pool),
+                           pool, pool));
+    }
+  SVN_ERR(svn_mutex__unlock(baton->mutex, SVN_NO_ERROR));
+
+  if (!err)
+    {
+      svn_revnum_t rev;
+      apr_pool_t *iterpool = svn_pool_create(instance->pool);
+      for (rev = baton->first_rev; rev < baton->last_rev; ++rev)
+        {
+          svn_pool_clear(iterpool);
+          err = svn_error_trace(verify_one_revision(instance->fs,
+                                                    rev,
+                                                    baton->notify_func,
+                                                    baton->notify_baton,
+                                                    baton->start_rev,
+                                                    baton->check_normalization,
+                                                    baton->cancel_func,
+                                                    baton->cancel_baton,
+                                                    iterpool));
+        }
+      svn_pool_destroy(iterpool);
+    }
+  baton->result = err;
+
+  SVN_ERR(svn_mutex__lock(baton->mutex));
+  APR_ARRAY_PUSH(baton->fs_instances, fs_instance_t *) = instance;
+  SVN_ERR(svn_mutex__unlock(baton->mutex, SVN_NO_ERROR));
+
+  return NULL;
+}
+
+#define WRAP_APR_ERR(x,msg)                     \
+  {                                             \
+    apr_status_t status_ = (x);                 \
+    if (status_)                                \
+      return svn_error_wrap_apr(status_, msg);  \
+  }
+
+static svn_error_t *
+verify_mt(svn_fs_t *fs,
+          svn_revnum_t start_rev,
+          svn_revnum_t end_rev,
+          svn_boolean_t check_normalization,
+          svn_repos_notify_t *notify,
+          svn_repos_notify_func_t notify_func,
+          void *notify_baton,
+          svn_repos_verify_callback_t verify_callback,
+          void *verify_baton,
+          svn_cancel_func_t cancel_func,
+          void *cancel_baton,
+          apr_pool_t *scratch_pool)
+{
+  svn_revnum_t rev;
+  svn_root_pools__t *root_pools;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  svn_error_t *err = SVN_NO_ERROR;
+  apr_array_header_t *jobs = apr_array_make(scratch_pool,
+                                            end_rev - start_rev + 1,
+                                            sizeof(verification_job_t));
+
+  /* Number of tasks sent to the thread pool. */
+  int tasks = 0;
+  int i;
+
+#if APR_HAS_THREADS
+  apr_thread_pool_t *thread_pool = NULL;
+  enum { MAX_THREADS = 24, STRIDE = 5 };
+
+  /* The thread-pool must be allocated from a thread-safe pool.
+     GLOBAL_POOL may be single-threaded, though. */
+  apr_pool_t *pool = svn_pool_create(NULL);
+
+  svn_mutex__t * mutex;
+  apr_array_header_t *fs_instances = apr_array_make(pool, MAX_THREADS,
+                                                    sizeof(fs_instance_t *));
+
+  SVN_ERR(svn_mutex__init(&mutex, TRUE, pool));
+
+  /* This thread pool will get cleaned up automatically when GLOBAL_POOL
+     gets cleared.  No additional cleanup callback is needed. */
+  WRAP_APR_ERR(apr_thread_pool_create(&thread_pool, 0, MAX_THREADS, pool),
+               _("Can't create verification thread pool"));
+
+#endif
+
+  SVN_ERR(svn_root_pools__create(&root_pools));
+
+  for (rev = start_rev; rev <= end_rev && err == SVN_NO_ERROR; rev += STRIDE)
+    {
+      apr_status_t status = APR_SUCCESS;
+      verification_job_t *job = apr_array_push(jobs);
+
+      job->fs = fs;
+      job->first_rev = rev;
+      job->last_rev = MIN(rev + STRIDE, end_rev + 1);
+      job->start_rev = start_rev;
+      job->check_normalization = check_normalization;
+      job->notify_func = notify_func;
+      job->notify_baton = notify_baton;
+      job->cancel_func = cancel_func;
+      job->cancel_baton = cancel_baton;
+      job->pools = root_pools;
+      job->result = SVN_NO_ERROR;
+      job->mutex = mutex;
+      job->fs_instances = fs_instances;
+
+      status = apr_thread_pool_push(thread_pool, verify_task, job, 0, NULL);
+      if (status)
+        job->result = svn_error_wrap_apr(status, _("Can't push task"));
+      else
+        tasks++;
+    }
+
+  while (apr_thread_pool_tasks_run_count(thread_pool) < tasks)
+    apr_sleep(10000);
+
+  for (i = 0; i < tasks; i++)
+    {
+      verification_job_t *job = &APR_ARRAY_IDX(jobs, i, verification_job_t);
+      err = job->result;
+      rev = job->first_rev;
+      svn_pool_clear(iterpool);
+
+      if (err && err->apr_err == SVN_ERR_CANCELLED)
+        {
+          ;
+        }
+      else if (err)
+        {
+          err = report_error(rev, err, verify_callback, verify_baton,
+                             iterpool);
+        }
+      else if (notify_func)
+        {
+          /* Tell the caller that we're done with this revision. */
+          notify->revision = rev;
+          notify_func(notify_baton, notify, iterpool);
+        }
+
+      svn_error_clear(err);
+    }
+
+  WRAP_APR_ERR(apr_thread_pool_destroy(thread_pool),
+               _("Can't destroy verification thread pool"));
+  svn_pool_destroy(pool);
+
+  return svn_error_trace(err);
+}
+
 svn_error_t *
 svn_repos_verify_fs3(svn_repos_t *repos,
                      svn_revnum_t start_rev,
@@ -2470,32 +2668,44 @@ svn_repos_verify_fs3(svn_repos_t *repos,
     }
 
   if (!metadata_only)
-    for (rev = start_rev; rev <= end_rev; rev++)
-      {
-        svn_pool_clear(iterpool);
-
-        /* Wrapper function to catch the possible errors. */
-        err = verify_one_revision(fs, rev, notify_func, notify_baton,
-                                  start_rev, check_normalization,
-                                  cancel_func, cancel_baton,
-                                  iterpool);
+    {
+#if APR_HAS_THREADS
+      if (start_rev < end_rev)
+        {
+          SVN_ERR(verify_mt(fs, start_rev, end_rev, check_normalization,
+                            notify, notify_func, notify_baton,
+                            verify_callback, verify_baton,
+                            cancel_func, cancel_baton, iterpool));
+        }
+      else
+#endif
+      for (rev = start_rev; rev <= end_rev; rev++)
+        {
+          svn_pool_clear(iterpool);
 
-        if (err && err->apr_err == SVN_ERR_CANCELLED)
-          {
-            return svn_error_trace(err);
-          }
-        else if (err)
-          {
-            SVN_ERR(report_error(rev, err, verify_callback, verify_baton,
-                                 iterpool));
-          }
-        else if (notify_func)
-          {
-            /* Tell the caller that we're done with this revision. */
-            notify->revision = rev;
-            notify_func(notify_baton, notify, iterpool);
-          }
-      }
+          /* Wrapper function to catch the possible errors. */
+          err = verify_one_revision(fs, rev, notify_func, notify_baton,
+                                    start_rev, check_normalization,
+                                    cancel_func, cancel_baton,
+                                    iterpool);
+
+          if (err && err->apr_err == SVN_ERR_CANCELLED)
+            {
+              return svn_error_trace(err);
+            }
+          else if (err)
+            {
+              SVN_ERR(report_error(rev, err, verify_callback, verify_baton,
+                                  iterpool));
+            }
+          else if (notify_func)
+            {
+              /* Tell the caller that we're done with this revision. */
+              notify->revision = rev;
+              notify_func(notify_baton, notify, iterpool);
+            }
+        }
+    }
 
   /* We're done. */
   if (notify_func)

Modified: subversion/trunk/subversion/libsvn_subr/pool.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/pool.c?rev=1796399&r1=1796398&r2=1796399&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/pool.c (original)
+++ subversion/trunk/subversion/libsvn_subr/pool.c Sat May 27 14:14:55 2017
@@ -136,7 +136,7 @@ svn_pool_create_allocator(svn_boolean_t
    * if we want thread-safety for that mutex. */
 
 #if APR_HAS_THREADS
-  if (thread_safe)
+  if (1)
     {
       apr_thread_mutex_t *mutex;
       apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, pool);

Modified: subversion/trunk/subversion/svnadmin/svnadmin.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnadmin/svnadmin.c?rev=1796399&r1=1796398&r2=1796399&view=diff
==============================================================================
--- subversion/trunk/subversion/svnadmin/svnadmin.c (original)
+++ subversion/trunk/subversion/svnadmin/svnadmin.c Sat May 27 14:14:55 2017
@@ -2992,7 +2992,7 @@ sub_main(int *exit_code, int argc, const
     svn_cache_config_t settings = *svn_cache_config_get();
 
     settings.cache_size = opt_state.memory_cache_size;
-    settings.single_threaded = TRUE;
+    settings.single_threaded = FALSE;
 
     svn_cache_config_set(&settings);
   }



Re: svn commit: r1796399 - in /subversion/trunk/subversion: libsvn_fs_x/batch_fsync.c libsvn_ra/ra_loader.c libsvn_repos/dump.c libsvn_subr/pool.c svnadmin/svnadmin.c

Posted by Stefan Fuhrmann <st...@apache.org>.
Oops.. sorry!
A test script ran commit in the wrong folder :/

Thanks for notifying!

-- Stefan^2.

On 27.05.2017 16:24, Stefan Sperling wrote:
> On Sat, May 27, 2017 at 02:14:56PM -0000, stefan2@apache.org wrote:
>> Author: stefan2
>> Date: Sat May 27 14:14:55 2017
>> New Revision: 1796399
>>
>> URL: http://svn.apache.org/viewvc?rev=1796399&view=rev
>> Log:
>> m
>>
> 
> Hmmm? :)
> 
>> Modified:
>>      subversion/trunk/subversion/libsvn_fs_x/batch_fsync.c
>>      subversion/trunk/subversion/libsvn_ra/ra_loader.c
>>      subversion/trunk/subversion/libsvn_repos/dump.c
>>      subversion/trunk/subversion/libsvn_subr/pool.c
>>      subversion/trunk/subversion/svnadmin/svnadmin.c
> 

Re: svn commit: r1796399 - in /subversion/trunk/subversion: libsvn_fs_x/batch_fsync.c libsvn_ra/ra_loader.c libsvn_repos/dump.c libsvn_subr/pool.c svnadmin/svnadmin.c

Posted by Stefan Sperling <st...@elego.de>.
On Sat, May 27, 2017 at 02:14:56PM -0000, stefan2@apache.org wrote:
> Author: stefan2
> Date: Sat May 27 14:14:55 2017
> New Revision: 1796399
> 
> URL: http://svn.apache.org/viewvc?rev=1796399&view=rev
> Log:
> m
> 

Hmmm? :)

> Modified:
>     subversion/trunk/subversion/libsvn_fs_x/batch_fsync.c
>     subversion/trunk/subversion/libsvn_ra/ra_loader.c
>     subversion/trunk/subversion/libsvn_repos/dump.c
>     subversion/trunk/subversion/libsvn_subr/pool.c
>     subversion/trunk/subversion/svnadmin/svnadmin.c