Author: stefan2
Date: Sun Apr 17 14:48:33 2011
New Revision: 1094150

URL: http://svn.apache.org/viewvc?rev=1094150&view=rev
Log:
Support concurrent transactions on FSFS: reset txn-local caches upon
closing the txn (i.e. don't wait until pool cleanup) and support concurrency
by simply disabling these caches permanently for the respective session
once a concurrency has been detected.

* subversion/libsvn_fs_fs/fs.h
  (fs_fs_data_t): add concurrent_transactions member
  (svn_fs_fs__reset_txn_caches): declare new private API function

* subversion/libsvn_fs_fs/caching.c
  (txn_cleanup_baton_t): new utility struct
  (remove_txn_cache): reset txn-local only if they match the ones to clean up
  (init_txn_callbacks): new destructor init utility
  (svn_fs_fs__initialize_txn_caches): gracefully support multiple concurrent 
txns
   in the *same* FSFS session by permanently disabling txn-local caches
  (svn_fs_fs__reset_txn_caches): implement new private API function

* subversion/libsvn_fs_fs/fs_fs.c
  (purge_shared_txn_body): reset txn-local caches immediately at the end
   of the given txn
* subversion/libsvn_fs_fs/tree.c
  (svn_fs_fs__commit_txn): dito

Modified:
    subversion/trunk/subversion/libsvn_fs_fs/caching.c
    subversion/trunk/subversion/libsvn_fs_fs/fs.h
    subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c
    subversion/trunk/subversion/libsvn_fs_fs/fs_fs.h
    subversion/trunk/subversion/libsvn_fs_fs/tree.c

Modified: subversion/trunk/subversion/libsvn_fs_fs/caching.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/caching.c?rev=1094150&r1=1094149&r2=1094150&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/caching.c Sun Apr 17 14:48:33 2011
@@ -331,17 +331,51 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
   return SVN_NO_ERROR;
 }
 
+/* Baton to be used for the remove_txn_cache() pool cleanup function, */
+struct txn_cleanup_baton_t
+{
+  /* the cache to reset */
+  svn_cache__t *txn_cache;
+
+  /* the position where to reset it */
+  svn_cache__t **to_reset;
+};
+
 /* APR pool cleanup handler that will reset the cache pointer given in
    BATON_VOID. */
 static apr_status_t
 remove_txn_cache(void *baton_void)
 {
-  svn_cache__t **cache_p = baton_void;
-  *cache_p = NULL;
+  struct txn_cleanup_baton_t *baton = baton_void;
+
+  /* be careful not to hurt performance by resetting newer txn's caches */
+  if (*baton->to_reset == baton->txn_cache)
+    *baton->to_reset  = NULL;
 
   return  APR_SUCCESS;
 }
 
+static svn_error_t *
+init_txn_callbacks(svn_cache__t **cache,
+                   apr_pool_t *pool)
+{
+  if (cache != NULL)
+    {
+      struct txn_cleanup_baton_t *baton;
+
+      baton = apr_palloc(pool, sizeof(*baton));
+      baton->txn_cache = *cache;
+      baton->to_reset = cache;
+
+      apr_pool_cleanup_register(pool,
+                                baton,
+                                remove_txn_cache,
+                                apr_pool_cleanup_null);
+    }
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_fs_fs__initialize_txn_caches(svn_fs_t *fs,
                                  const char *txn_id,
@@ -361,9 +395,15 @@ svn_fs_fs__initialize_txn_caches(svn_fs_
                                    ":", svn_uuid_generate(pool), ":",
                                    (char *)NULL);
 
-  /* There must be no concurrent transactions in progress for the same
-     FSFS access / session object. Maybe, you forgot to clean POOL. */
-  SVN_ERR_ASSERT(ffd->txn_dir_cache == NULL);
+  /* We don't support caching for concurrent transactions in the SAME
+   * FSFS session. Maybe, you forgot to clean POOL. */
+  if (ffd->txn_dir_cache != NULL || ffd->concurrent_transactions)
+    {
+      ffd->txn_dir_cache = NULL;
+      ffd->concurrent_transactions = TRUE;
+
+      return SVN_NO_ERROR;
+    }
 
   /* create a txn-local directory cache */
   if (svn_fs__get_global_membuffer_cache())
@@ -386,10 +426,17 @@ svn_fs_fs__initialize_txn_caches(svn_fs_
                                         pool));
 
   /* reset the transaction-specific cache if the pool gets cleaned up. */
-  apr_pool_cleanup_register(pool,
-                            &(ffd->txn_dir_cache),
-                            remove_txn_cache,
-                            apr_pool_cleanup_null);
+  init_txn_callbacks(&(ffd->txn_dir_cache), pool);
 
   return SVN_NO_ERROR;
 }
+
+void
+svn_fs_fs__reset_txn_caches(svn_fs_t *fs)
+{
+  /* we can always just reset the caches. This may degrade performance but
+   * can never cause in incorrect behavior. */
+
+  fs_fs_data_t *ffd = fs->fsap_data;
+  ffd->txn_dir_cache = NULL;
+}
\ No newline at end of file

Modified: subversion/trunk/subversion/libsvn_fs_fs/fs.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs.h?rev=1094150&r1=1094149&r2=1094150&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs.h Sun Apr 17 14:48:33 2011
@@ -248,6 +248,9 @@ typedef struct fs_fs_data_t
   /* Cache for node_revision_t objects; the key is (revision, id offset) */
   svn_cache__t *node_revision_cache;
 
+  /* If set, there are or have been more than one concurrent transaction */
+  svn_boolean_t concurrent_transactions;
+
   /* Tempoary cache for changed directories yet to be committed; maps from
      unparsed FS ID to ###x.  NULL outside transactions. */
   svn_cache__t *txn_dir_cache;

Modified: subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c?rev=1094150&r1=1094149&r2=1094150&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c Sun Apr 17 14:48:33 2011
@@ -853,6 +853,8 @@ purge_shared_txn_body(svn_fs_t *fs, cons
   const char *txn_id = baton;
 
   free_shared_txn(fs, txn_id);
+  svn_fs_fs__reset_txn_caches(fs);
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/libsvn_fs_fs/fs_fs.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs_fs.h?rev=1094150&r1=1094149&r2=1094150&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs_fs.h Sun Apr 17 14:48:33 2011
@@ -517,6 +517,11 @@ svn_fs_fs__initialize_txn_caches(svn_fs_
                                  const char *txn_id,
                                  apr_pool_t *pool);
 
+/* Resets the svn_cache__t structures local to the current transaction in FS.
+   Calling it more than once per txn or from outside any txn is allowed. */
+void
+svn_fs_fs__reset_txn_caches(svn_fs_t *fs);
+
 /* Possibly pack the repository at PATH.  This just take full shards, and
    combines all the revision files into a single one, with a manifest header.
    Use optional CANCEL_FUNC/CANCEL_BATON for cancellation support.

Modified: subversion/trunk/subversion/libsvn_fs_fs/tree.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/tree.c?rev=1094150&r1=1094149&r2=1094150&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/tree.c Sun Apr 17 14:48:33 2011
@@ -1728,6 +1728,9 @@ svn_fs_fs__commit_txn(const char **confl
     }
 
  cleanup:
+
+  svn_fs_fs__reset_txn_caches(fs);
+
   svn_pool_destroy(iterpool);
   return svn_error_return(err);
 }


Reply via email to