You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2012/05/20 21:16:50 UTC

svn commit: r1340806 - in /subversion/trunk/subversion/libsvn_subr: internal_statements.sql sqlite.c

Author: rhuijben
Date: Sun May 20 19:16:50 2012
New Revision: 1340806

URL: http://svn.apache.org/viewvc?rev=1340806&view=rev
Log:
Speed up the Sqlite savepoint creation and releasing in our Sqlite api by
using a prepared statement instead of generated sql.

The SQL tokenizer shouldn't show up in filtered performance reports for a
simple checkout...

Sqlite allows nesting savepoints with the same name, so this doesn't require
changes to our private api. Extend the set of prepared statements with a few
library internal statements to allow using the current infrastructure.

* subversion/libsvn_subr/internal_statements.sql
  (STMT_DUMMY_SELECT_FOR_BACKUP): Remove unused dummy.
  (STMT_INTERNAL_SAVEPOINT_SVN,
   STMT_INTERNAL_RELEASE_SAVEPOINT_SVN,
   STMT_INTERNAL_ROLLBACK_TO_SAVEPOINT_SVN,
   STMT_INTERNAL_LAST): New statements.

* subversion/libsvn_subr/sqlite.c
  (get_internal_statement): New function.
  (close_apr): finalize the internal statements.
  (svn_sqlite__open): Keep space for a few extra statements.
  (svn_sqlite__with_lock): Use internal statements instead of sql text.

Modified:
    subversion/trunk/subversion/libsvn_subr/internal_statements.sql
    subversion/trunk/subversion/libsvn_subr/sqlite.c

Modified: subversion/trunk/subversion/libsvn_subr/internal_statements.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/internal_statements.sql?rev=1340806&r1=1340805&r2=1340806&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/internal_statements.sql (original)
+++ subversion/trunk/subversion/libsvn_subr/internal_statements.sql Sun May 20 19:16:50 2012
@@ -21,5 +21,15 @@
  * ====================================================================
  */
 
--- STMT_DUMMY_SELECT_FOR_BACKUP
-SELECT * FROM SQLITE_MASTER;
+-- STMT_INTERNAL_SAVEPOINT_SVN
+SAVEPOINT svn;
+
+-- STMT_INTERNAL_RELEASE_SAVEPOINT_SVN
+RELEASE SAVEPOINT svn;
+
+-- STMT_INTERNAL_ROLLBACK_TO_SAVEPOINT_SVN
+ROLLBACK TO SAVEPOINT svn;
+
+/* Dummmy statement to determine the number of internal statements */
+-- STMT_INTERNAL_LAST
+;

Modified: subversion/trunk/subversion/libsvn_subr/sqlite.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/sqlite.c?rev=1340806&r1=1340805&r2=1340806&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/sqlite.c (original)
+++ subversion/trunk/subversion/libsvn_subr/sqlite.c Sun May 20 19:16:50 2012
@@ -204,6 +204,29 @@ svn_sqlite__get_statement(svn_sqlite__st
   return SVN_NO_ERROR;
 }
 
+/* Like svn_sqlite__get_statement but gets an internal statement.
+
+   All internal statements that use this api are executed with step_done(),
+   so we don't need the fallback reset handling here or in the pool cleanup */
+svn_error_t *
+get_internal_statement(svn_sqlite__stmt_t **stmt, svn_sqlite__db_t *db,
+                       int stmt_idx)
+{
+  /* The internal statements are stored after the registered statements */
+  int prep_idx = db->nbr_statements + stmt_idx;
+  SVN_ERR_ASSERT(stmt_idx < STMT_INTERNAL_LAST);
+
+  if (db->prepared_stmts[prep_idx] == NULL)
+    SVN_ERR(prepare_statement(&db->prepared_stmts[prep_idx], db,
+                              internal_statements[stmt_idx],
+                              db->state_pool));
+
+  *stmt = db->prepared_stmts[prep_idx];
+
+  return SVN_NO_ERROR;
+}
+
+
 static svn_error_t *
 step_with_expectation(svn_sqlite__stmt_t* stmt,
                       svn_boolean_t expecting_row)
@@ -742,6 +765,15 @@ close_apr(void *data)
                         svn_sqlite__finalize(db->prepared_stmts[i]), err);
         }
     }
+  /* And finalize any used internal statements */
+  for (; i < db->nbr_statements + STMT_INTERNAL_LAST; i++)
+    {
+      if (db->prepared_stmts[i])
+        {
+          err = svn_error_compose_create(
+                        svn_sqlite__finalize(db->prepared_stmts[i]), err);
+        }
+    }
 
   result = sqlite3_close(db->db3);
 
@@ -844,11 +876,19 @@ svn_sqlite__open(svn_sqlite__db_t **db, 
           statements++;
           (*db)->nbr_statements++;
         }
-      (*db)->prepared_stmts = apr_pcalloc(result_pool, (*db)->nbr_statements
+
+      (*db)->prepared_stmts = apr_pcalloc(
+                                  result_pool,
+                                  ((*db)->nbr_statements + STMT_INTERNAL_LAST)
                                                 * sizeof(svn_sqlite__stmt_t *));
     }
   else
-    (*db)->nbr_statements = 0;
+    {
+      (*db)->nbr_statements = 0;
+      (*db)->prepared_stmts = apr_pcalloc(result_pool,
+                                          (0 + STMT_INTERNAL_LAST)
+                                                * sizeof(svn_sqlite__stmt_t *));
+    }
 
   (*db)->state_pool = result_pool;
   apr_pool_cleanup_register(result_pool, *db, close_apr, apr_pool_cleanup_null);
@@ -970,20 +1010,21 @@ svn_sqlite__with_lock(svn_sqlite__db_t *
                       apr_pool_t *scratch_pool)
 {
   svn_error_t *err;
-  int savepoint = db->savepoint_nr++;
-  /* This buffer is plenty big to hold the SAVEPOINT and RELEASE commands. */
-  char buf[32];
+  svn_sqlite__stmt_t *stmt;
 
-  snprintf(buf, sizeof(buf), "SAVEPOINT s%u", savepoint);
-  SVN_ERR(exec_sql(db, buf));
+  SVN_ERR(get_internal_statement(&stmt, db, STMT_INTERNAL_SAVEPOINT_SVN));
+  SVN_ERR(svn_sqlite__step_done(stmt));
   err = cb_func(cb_baton, db, scratch_pool);
 
   if (err)
     {
       svn_error_t *err2;
 
-      snprintf(buf, sizeof(buf), "ROLLBACK TO s%u", savepoint);
-      err2 = exec_sql(db, buf);
+      err2 = get_internal_statement(&stmt, db,
+                                    STMT_INTERNAL_ROLLBACK_TO_SAVEPOINT_SVN);
+
+      if (!err2)
+        err2 = svn_sqlite__step_done(stmt);
 
       if (err2 && err2->apr_err == SVN_ERR_SQLITE_BUSY)
         {
@@ -994,17 +1035,23 @@ svn_sqlite__with_lock(svn_sqlite__db_t *
                  further details */
 
           err2 = reset_all_statements(db, err2);
-          err2 = svn_error_compose_create(exec_sql(db, buf), err2);
+          err2 = svn_error_compose_create(svn_sqlite__step_done(stmt), err2);
         }
 
-      snprintf(buf, sizeof(buf), "RELEASE   s%u", savepoint);
-      err2 = svn_error_compose_create(exec_sql(db, buf), err2);
+      err = svn_error_compose_create(err, err2);
+      err2 = get_internal_statement(&stmt, db,
+                                    STMT_INTERNAL_RELEASE_SAVEPOINT_SVN);
+
+      if (!err2)
+        err2 = svn_sqlite__step_done(stmt);
 
       return svn_error_trace(svn_error_compose_create(err, err2));
     }
 
-  snprintf(buf, sizeof(buf), "RELEASE   s%u", savepoint);
-  return svn_error_trace(exec_sql(db, buf));
+  SVN_ERR(get_internal_statement(&stmt, db,
+                                 STMT_INTERNAL_RELEASE_SAVEPOINT_SVN));
+
+  return svn_error_trace(svn_sqlite__step_done(stmt));
 }
 
 svn_error_t *
@@ -1015,7 +1062,7 @@ svn_sqlite__hotcopy(const char *src_path
   svn_sqlite__db_t *src_db;
 
   SVN_ERR(svn_sqlite__open(&src_db, src_path, svn_sqlite__mode_readonly,
-                           internal_statements, 0, NULL,
+                           NULL, 0, NULL,
                            scratch_pool, scratch_pool));
 
   {