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

svn commit: r1679169 - in /subversion/trunk/subversion: libsvn_fs_fs/fs.c libsvn_fs_fs/rep-cache-db.sql libsvn_fs_fs/rep-cache.c libsvn_fs_fs/rep-cache.h tests/libsvn_fs/fs-test.c

Author: danielsh
Date: Wed May 13 09:47:51 2015
New Revision: 1679169

URL: http://svn.apache.org/r1679169
Log:
fsfs freeze: Unlock rep-cache.db as part of unfreezing.

Without this, after calling svn_fs_freeze(fs), calling svn_fs_commit_txn() or
svn_fs_freeze() on that svn_fs_t object would fail with an SQLite error:

    subversion/tests/libsvn_fs/fs-test.c:124: (apr_err=SVN_ERR_SQLITE_ERROR)
    svn_tests: E200030: commit succeeded but something else failed
    ...
    subversion/libsvn_subr/sqlite.c:360: (apr_err=SVN_ERR_SQLITE_ERROR)
    svn_tests: E200030: sqlite[S1]: cannot start a transaction within a transaction

* subversion/tests/libsvn_fs/fs-test.c
  (freeze_and_commit): New test.
  (noop_freeze_func): New helper function.

* subversion/libsvn_fs_fs/rep-cache.h
  (svn_fs_fs__lock_rep_cache): Remove declaration.
  (svn_fs_fs__with_rep_cache_lock): New declaration.

* subversion/libsvn_fs_fs/rep-cache-db.sql
  (STMT_UNLOCK_REP): New statement.

* subversion/libsvn_fs_fs/fs.c
  (fs_freeze_body): Unlock the rep cache after calling freeze_func().

* subversion/libsvn_fs_fs/rep-cache.c
  (svn_fs_fs__lock_rep_cache): Demote to a static function, renaming to..
  (lock_rep_cache): .. this.
  (unlock_rep_cache): New static function.
  (svn_fs_fs__with_rep_cache_lock): New function.

Modified:
    subversion/trunk/subversion/libsvn_fs_fs/fs.c
    subversion/trunk/subversion/libsvn_fs_fs/rep-cache-db.sql
    subversion/trunk/subversion/libsvn_fs_fs/rep-cache.c
    subversion/trunk/subversion/libsvn_fs_fs/rep-cache.h
    subversion/trunk/subversion/tests/libsvn_fs/fs-test.c

Modified: subversion/trunk/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs.c?rev=1679169&r1=1679168&r2=1679169&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs.c Wed May 13 09:47:51 2015
@@ -162,9 +162,11 @@ fs_freeze_body(void *baton,
 
   SVN_ERR(svn_fs_fs__exists_rep_cache(&exists, b->fs, pool));
   if (exists)
-    SVN_ERR(svn_fs_fs__lock_rep_cache(b->fs, pool));
-
-  SVN_ERR(b->freeze_func(b->freeze_baton, pool));
+    SVN_ERR(svn_fs_fs__with_rep_cache_lock(b->fs,
+                                           b->freeze_func, b->freeze_baton,
+                                           pool));
+  else
+    SVN_ERR(b->freeze_func(b->freeze_baton, pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/libsvn_fs_fs/rep-cache-db.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/rep-cache-db.sql?rev=1679169&r1=1679168&r2=1679169&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/rep-cache-db.sql (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/rep-cache-db.sql Wed May 13 09:47:51 2015
@@ -63,3 +63,6 @@ WHERE revision > ?1
 -- STMT_LOCK_REP
 BEGIN TRANSACTION;
 INSERT INTO rep_cache VALUES ('dummy', 0, 0, 0, 0)
+
+-- STMT_UNLOCK_REP
+ROLLBACK TRANSACTION;

Modified: subversion/trunk/subversion/libsvn_fs_fs/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/rep-cache.c?rev=1679169&r1=1679168&r2=1679169&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/rep-cache.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/rep-cache.c Wed May 13 09:47:51 2015
@@ -374,9 +374,13 @@ svn_fs_fs__del_rep_reference(svn_fs_t *f
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_fs_fs__lock_rep_cache(svn_fs_t *fs,
-                          apr_pool_t *pool)
+/* Start a transaction to take an SQLite reserved lock that prevents
+   other writes.
+
+   See unlock_rep_cache(). */
+static svn_error_t *
+lock_rep_cache(svn_fs_t *fs,
+               apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
 
@@ -387,3 +391,31 @@ svn_fs_fs__lock_rep_cache(svn_fs_t *fs,
 
   return SVN_NO_ERROR;
 }
+
+/* End the transaction started by lock_rep_cache(). */
+static svn_error_t *
+unlock_rep_cache(svn_fs_t *fs,
+                 apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+
+  SVN_ERR_ASSERT(ffd->rep_cache_db); /* was opened by lock_rep_cache() */
+
+  SVN_ERR(svn_sqlite__exec_statements(ffd->rep_cache_db, STMT_UNLOCK_REP));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__with_rep_cache_lock(svn_fs_t *fs,
+                               svn_error_t *(*body)(void *,
+                                                    apr_pool_t *),
+                               void *baton,
+                               apr_pool_t *pool)
+{
+  svn_error_t *err;
+
+  SVN_ERR(lock_rep_cache(fs, pool));
+  err = body(baton, pool);
+  return svn_error_compose_create(err, unlock_rep_cache(fs, pool));
+}

Modified: subversion/trunk/subversion/libsvn_fs_fs/rep-cache.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/rep-cache.h?rev=1679169&r1=1679168&r2=1679169&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/rep-cache.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/rep-cache.h Wed May 13 09:47:51 2015
@@ -87,10 +87,14 @@ svn_fs_fs__del_rep_reference(svn_fs_t *f
                              apr_pool_t *pool);
 
 /* Start a transaction to take an SQLite reserved lock that prevents
-   other writes. */
+   other writes, call BODY, end the transaction, and return what BODY returned.
+ */
 svn_error_t *
-svn_fs_fs__lock_rep_cache(svn_fs_t *fs,
-                          apr_pool_t *pool);
+svn_fs_fs__with_rep_cache_lock(svn_fs_t *fs,
+                               svn_error_t *(*body)(void *baton,
+                                                    apr_pool_t *pool),
+                               void *baton,
+                               apr_pool_t *pool);
 
 #ifdef __cplusplus
 }

Modified: subversion/trunk/subversion/tests/libsvn_fs/fs-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_fs/fs-test.c?rev=1679169&r1=1679168&r2=1679169&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_fs/fs-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_fs/fs-test.c Wed May 13 09:47:51 2015
@@ -6891,6 +6891,53 @@ test_internal_txn_props(const svn_test_o
   return SVN_NO_ERROR;
 }
 
+/* This function implements svn_fs_freeze_func_t. */
+static svn_error_t *
+noop_freeze_func(void *baton, apr_pool_t *pool)
+{
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+freeze_and_commit(const svn_test_opts_t *opts,
+                  apr_pool_t *pool)
+{
+  svn_fs_t *fs;
+  svn_fs_txn_t *txn;
+  svn_fs_root_t *txn_root;
+  svn_revnum_t new_rev = 0;
+  apr_pool_t *subpool = svn_pool_create(pool);
+
+  SVN_ERR(svn_test__create_fs(&fs, "test-freeze-and-commit", opts, subpool));
+
+  /* This test used to FAIL with an SQLite error since svn_fs_freeze()
+   * wouldn't unlock rep-cache.db.  Therefore, part of the role of creating
+   * the Greek tree is to create a rep-cache.db, in order to test that
+   * svn_fs_freeze() unlocks it. */
+
+  /* r1: Commit the Greek tree. */
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, new_rev, subpool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
+  SVN_ERR(svn_test__create_greek_tree(txn_root, subpool));
+  SVN_ERR(test_commit_txn(&new_rev, txn, NULL, subpool));
+
+  /* Freeze and unfreeze. */
+  SVN_ERR(svn_fs_freeze(fs, noop_freeze_func, NULL, pool));
+
+  /* And the same once again, for good measure. */
+  SVN_ERR(svn_fs_freeze(fs, noop_freeze_func, NULL, pool));
+
+  /* Make some commit. */
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, new_rev, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_fs_change_node_prop(txn_root, "", "temperature",
+                                  svn_string_create("310.05", pool),
+                                  pool));
+  SVN_ERR(test_commit_txn(&new_rev, txn, NULL, pool));
+
+  return SVN_NO_ERROR;
+}
+
 /* ------------------------------------------------------------------------ */
 
 /* The test table.  */
@@ -7023,6 +7070,8 @@ static struct svn_test_descriptor_t test
                        "test setting and getting internal txn props"),
     SVN_TEST_OPTS_PASS(check_txn_related,
                        "test svn_fs_check_related for transactions"),
+    SVN_TEST_OPTS_PASS(freeze_and_commit,
+                       "freeze and commit"),
     SVN_TEST_NULL
   };