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 2013/01/29 17:16:24 UTC

svn commit: r1439975 - in /subversion/trunk/subversion: libsvn_wc/wc-queries.sql libsvn_wc/wc_db_update_move.c tests/libsvn_wc/wc-queries-test.c

Author: stsp
Date: Tue Jan 29 16:16:23 2013
New Revision: 1439975

URL: http://svn.apache.org/viewvc?rev=1439975&view=rev
Log:
Make notifications during move-update transaction-safe, by only issuing
notifiations if the transaction actually succeeds.

We store notifications in a temporary wc.db table during the update-move
editor drive, and spool notifications from it when the edit completes.

* subversion/libsvn_wc/wc-queries.sql
  (STMT_CREATE_UPDATE_MOVE_LIST,
   STMT_INSERT_UPDATE_MOVE_LIST,
   STMT_FINALIZE_UPDATE_MOVE): New statements.

* subversion/libsvn_wc/wc_db_update_move.c
  (update_move_list_add, update_move_list_notify): New helper functions.
  (tc_editor_alter_directory, update_working_file): Add notifiations to
   the update-move notification list instead of sending them directly.
  (update_moved_away_conflict_victim): Create the move-update notification
   list before starting the editor drive.

* subversion/tests/libsvn_wc/wc-queries-test.c
  (schema_statements): Add STMT_CREATE_UPDATE_MOVE_LIST to this list
   of statements which create temporary tables.
  (slow_statements): Add STMT_SELECT_UPDATE_MOVE_LIST to the list of
   statements which fail if temporary tables don't exist.

Modified:
    subversion/trunk/subversion/libsvn_wc/wc-queries.sql
    subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c
    subversion/trunk/subversion/tests/libsvn_wc/wc-queries-test.c

Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1439975&r1=1439974&r2=1439975&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Tue Jan 29 16:16:23 2013
@@ -1315,6 +1315,30 @@ ORDER BY local_relpath
 -- STMT_FINALIZE_DELETE
 DROP TABLE IF EXISTS delete_list
 
+-- STMT_CREATE_UPDATE_MOVE_LIST
+DROP TABLE IF EXISTS update_move_list;
+CREATE TEMPORARY TABLE update_move_list (
+/* ### we should put the wc_id in here in case a move update spans multiple
+   ### working copies. queries, etc will need to be adjusted.  */
+  local_relpath TEXT PRIMARY KEY NOT NULL UNIQUE,
+  action INTEGER NOT NULL,
+  kind  INTEGER NOT NULL,
+  content_state INTEGER NOT NULL,
+  prop_state  INTEGER NOT NULL
+  )
+
+-- STMT_INSERT_UPDATE_MOVE_LIST
+INSERT INTO update_move_list(local_relpath, action, kind, content_state,
+  prop_state)
+VALUES (?1, ?2, ?3, ?4, ?5)
+
+-- STMT_SELECT_UPDATE_MOVE_LIST
+SELECT local_relpath, action, kind, content_state, prop_state
+FROM update_move_list
+ORDER BY local_relpath
+
+-- STMT_FINALIZE_UPDATE_MOVE
+DROP TABLE IF EXISTS update_move_list
 
 /* ------------------------------------------------------------------------- */
 

Modified: subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c?rev=1439975&r1=1439974&r2=1439975&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c Tue Jan 29 16:16:23 2013
@@ -131,6 +131,86 @@ struct tc_editor_baton {
   apr_pool_t *result_pool;
 };
 
+/* 
+ * Notifications are delayed until the entire update-move transaction
+ * completes. These functions provide the necessary support by storing
+ * notification information in a temporary db table (the "update_move_list")
+ * and spooling notifications out of that table after the transaction.
+ */
+
+/* Add an entry to the notification list. */
+static svn_error_t *
+update_move_list_add(svn_wc__db_wcroot_t *wcroot,
+                     const char *local_relpath,
+                     svn_wc_notify_action_t action,
+                     svn_node_kind_t kind,
+                     svn_wc_notify_state_t content_state,
+                     svn_wc_notify_state_t prop_state)
+
+{
+  svn_sqlite__stmt_t *stmt;
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_INSERT_UPDATE_MOVE_LIST));
+  SVN_ERR(svn_sqlite__bindf(stmt, "sdddd", local_relpath,
+                            action, kind, content_state, prop_state));
+  SVN_ERR(svn_sqlite__step_done(stmt));
+
+  return SVN_NO_ERROR;
+}
+
+/* Send all notifications stored in the notification list, and then
+ * remove the temporary database table. */
+static svn_error_t *
+update_move_list_notify(svn_wc__db_wcroot_t *wcroot,
+                        svn_revnum_t old_revision,
+                        svn_revnum_t new_revision,
+                        svn_wc_notify_func2_t notify_func,
+                        void *notify_baton,
+                        apr_pool_t *scratch_pool)
+{
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  apr_pool_t *iterpool;
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_UPDATE_MOVE_LIST));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  iterpool = svn_pool_create(scratch_pool);
+  while (have_row)
+    {
+      const char *local_relpath;
+      svn_wc_notify_action_t action;
+      svn_wc_notify_t *notify;
+
+      svn_pool_clear(iterpool);
+
+      local_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      action = svn_sqlite__column_int(stmt, 1);
+      notify = svn_wc_create_notify(svn_dirent_join(wcroot->abspath,
+                                                    local_relpath,
+                                                    iterpool),
+                                    action, iterpool);
+      notify->kind = svn_sqlite__column_int(stmt, 2);
+      notify->content_state = svn_sqlite__column_int(stmt, 3);
+      notify->prop_state = svn_sqlite__column_int(stmt, 4);
+      notify->old_revision = old_revision;
+      notify->revision = new_revision;
+      notify_func(notify_baton, notify, scratch_pool);
+
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    }
+  svn_pool_destroy(iterpool);
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_FINALIZE_UPDATE_MOVE));
+  SVN_ERR(svn_sqlite__step_done(stmt));
+
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *
 mark_tree_conflict(struct tc_editor_baton *b,
                    const char *local_relpath,
@@ -619,19 +699,11 @@ tc_editor_alter_directory(void *baton,
         }
 
       if (b->notify_func)
-        {
-          svn_wc_notify_t *notify;
-
-          notify = svn_wc_create_notify(dst_abspath,
-                                        svn_wc_notify_update_update,
-                                        scratch_pool);
-          notify->kind = svn_node_dir;
-          notify->content_state = svn_wc_notify_state_inapplicable;
-          notify->prop_state = prop_state;
-          notify->old_revision = b->old_version->peg_rev;
-          notify->revision = b->new_version->peg_rev;
-          b->notify_func(b->notify_baton, notify, scratch_pool);
-        }
+        SVN_ERR(update_move_list_add(b->wcroot, dst_relpath,
+                                     svn_wc_notify_update_update,
+                                     svn_node_dir,
+                                     svn_wc_notify_state_inapplicable,
+                                     prop_state));
     }
 
   return SVN_NO_ERROR;
@@ -749,19 +821,11 @@ update_working_file(svn_skel_t **work_it
     }
 
   if (notify_func)
-    {
-      svn_wc_notify_t *notify;
-
-      notify = svn_wc_create_notify(local_abspath,
-                                    svn_wc_notify_update_update,
-                                    scratch_pool);
-      notify->kind = svn_node_file;
-      notify->content_state = content_state;
-      notify->prop_state = prop_state;
-      notify->old_revision = old_version->location_and_kind->peg_rev;
-      notify->revision = new_version->location_and_kind->peg_rev;
-      notify_func(notify_baton, notify, scratch_pool);
-    }
+    SVN_ERR(update_move_list_add(wcroot, local_relpath,
+                                 svn_wc_notify_update_update,
+                                 svn_node_file,
+                                 content_state,
+                                 prop_state));
 
   return SVN_NO_ERROR;
 }
@@ -1015,6 +1079,12 @@ tc_editor_complete(void *baton,
 {
   struct tc_editor_baton *b = baton;
 
+  /* Send all queued up notifications. */
+  SVN_ERR(update_move_list_notify(b->wcroot,
+                                  b->old_version->peg_rev,
+                                  b->new_version->peg_rev,
+                                  b->notify_func, b->notify_baton,
+                                  scratch_pool));
   if (b->notify_func)
     {
       svn_wc_notify_t *notify;
@@ -1560,6 +1630,10 @@ update_moved_away_conflict_victim(svn_sk
                                svn_dirent_join(wcroot->abspath, victim_relpath,
                                                scratch_pool),
                                scratch_pool));
+
+  /* Create a new, and empty, list for notification information. */
+  SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
+                                      STMT_CREATE_UPDATE_MOVE_LIST));
   /* Create the editor... */
   SVN_ERR(svn_editor_create(&tc_editor, tc_editor_baton,
                             cancel_func, cancel_baton,

Modified: subversion/trunk/subversion/tests/libsvn_wc/wc-queries-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/wc-queries-test.c?rev=1439975&r1=1439974&r2=1439975&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/wc-queries-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/wc-queries-test.c Tue Jan 29 16:16:23 2013
@@ -73,6 +73,7 @@ static const int schema_statements[] =
   STMT_CREATE_TARGET_PROP_CACHE,
   STMT_CREATE_REVERT_LIST,
   STMT_CREATE_DELETE_LIST,
+  STMT_CREATE_UPDATE_MOVE_LIST,
   -1 /* final marker */
 };
 
@@ -92,6 +93,7 @@ static const int slow_statements[] =
   STMT_INSERT_ACTUAL_EMPTIES,
   STMT_SELECT_REVERT_LIST_RECURSIVE,
   STMT_SELECT_DELETE_LIST,
+  STMT_SELECT_UPDATE_MOVE_LIST,
 
   /* Designed as slow to avoid penalty on other queries */
   STMT_SELECT_UNREFERENCED_PRISTINES,