[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PATCH] svn_fs_abort_txn and bug fixes

From: Yoshiki Hayashi <yoshiki_at_xemacs.org>
Date: 2001-02-28 11:27:12 CET

All of these changes are necessary to implement
svn_fs_abort_txn(). This was harder than I thought because
of some bugs. :-)

* dag.c (struct dag_node_t): Fix indentation.
* dag.c (svn_fs__dag_dir_entries): Fill in this function.
* dag.c (svn_fs__dag_clone_root): Update root node ID in
  transaction table.
* dag.c (svn_fs__dag_delete): Delete node from nodes table
  when node is mutable.
* dag.h (svn_fs__dag_delete): Doc fix.
* nodes-table.c (svn_fs__delete_node): New function.
* nodes-table.h (svn_fs__delete_node): New function declaration.
* txn-table.c (put_txn): Fix the order of prepend.
  Transaction skel is (transaction ROOT-ID BASE-ROOT-ID).
* txn.c (delete_nodes): New function.
* txn.c (txn_body_abort_txn): New function.
* txn.c (svn_fs_abort_txn): New function.

Index: dag.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/dag.c,v
retrieving revision 1.59
diff -u -r1.59 dag.c
--- dag.c 2001/02/28 07:53:31 1.59
+++ dag.c 2001/02/28 10:11:30
@@ -65,7 +65,7 @@
      this yourself, but you're probably better off just calling
      `get_node_revision' and `set_node_revision', which take care of
      things for you. */
- skel_t *node_revision;
+ skel_t *node_revision;
 
 };
 
@@ -367,14 +367,37 @@
 }
 
 
+
+svn_error_t *
+svn_fs__dag_dir_entries (skel_t **entries_p,
+ dag_node_t *node,
+ trail_t *trail)
+{
+ skel_t *node_rev, *entries, *entry;
+
+ if (! svn_fs__dag_is_directory (node))
+ return svn_error_create
+ (SVN_ERR_FS_NOT_DIRECTORY, 0, NULL, trail->pool,
+ "Attempted to get entry from *non*-directory node.");
+
+ /* Go get a fresh NODE-REVISION for this node. */
+ SVN_ERR (get_node_revision (&node_rev, node, trail));
+
+ /* Directory entries start at the second element of a node-revision
+ skel, itself is a list. */
+ entries = node_rev->children->next->children;
 
-svn_error_t *svn_fs__dag_dir_entries (skel_t **entries_p,
- dag_node_t *node,
- trail_t *trail)
-{
- abort();
- /* NOTREACHED */
- return NULL;
+ /* Check entries are well-formed. */
+ for (entry = entries; entry; entry = entry->next)
+ {
+ /* ENTRY must be a list which has two elements. */
+ if (svn_fs__list_length (entry) != 2)
+ return svn_error_create (SVN_ERR_FS_CORRUPT, 0, NULL, trail->pool,
+ "Malformed directory entry.");
+ }
+
+ *entries_p = entries;
+ return SVN_NO_ERROR;
 }
 
 
@@ -674,6 +697,10 @@
   /* One way or another, root_id now identifies a cloned root node. */
   SVN_ERR (create_node (root_p, fs, root_id, trail));
 
+ /* Update root_id in transactions table. */
+ SVN_ERR (svn_fs__set_txn_root (fs, svn_txn, root_id, trail));
+
+
   /* ... And when it is grown
    * Then my own little clone
    * Will be of the opposite sex!
@@ -726,10 +753,9 @@
   new_dirent_list = svn_fs__copy_skel (node_rev->children->next,
                                        trail->pool);
 
- entry = new_dirent_list->children;
   old_entry = NULL;
 
- while (entry)
+ for (entry = new_dirent_list->children; entry; entry = entry->next)
     {
       if (svn_fs__matches_atom (entry->children, name))
         {
@@ -747,10 +773,10 @@
                                               id,
                                               trail));
 
- if (svn_fs__matches_atom (entry_content->children->children,
- "dir"))
+ if (has_mutable_flag (entry_content))
             {
- if (has_mutable_flag (entry_content))
+ if (svn_fs__matches_atom (entry_content->children->children,
+ "dir"))
                 {
                   int len =
                     svn_fs__list_length (entry_content->children->next);
@@ -761,15 +787,21 @@
                        "Attempted to delete *non-empty* directory `%s'.",
                        name);
                 }
- }
 
- /* Just "lose" this entry by setting the *previous* entry's
- next ptr to the current entry's next ptr. */
- if (! old_entry)
- /* Base case: the very *first* entry matched. */
- new_dirent_list->children = entry->next;
+ /* We are aborting a transaction. Mutable nodes must be
+ removed from `nodes' table. */
+ SVN_ERR (svn_fs__delete_node (parent->fs, id, trail));
+ }
           else
- old_entry->next = entry->next;
+ {
+ /* Just "lose" this entry by setting the *previous* entry's
+ next ptr to the current entry's next ptr. */
+ if (! old_entry)
+ /* Base case: the very *first* entry matched. */
+ new_dirent_list->children = entry->next;
+ else
+ old_entry->next = entry->next;
+ }
 
           deleted = TRUE;
           break;
@@ -777,7 +809,6 @@
 
       /* No match, move to next entry. */
       old_entry = entry;
- entry = entry->next;
     }
     
   if (! deleted)
Index: dag.h
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/dag.h,v
retrieving revision 1.30
diff -u -r1.30 dag.h
--- dag.h 2001/02/27 22:03:46 1.30
+++ dag.h 2001/02/28 10:11:30
@@ -262,7 +262,8 @@
 /* Delete the directory entry named NAME from PARENT, as part of
    TRAIL. PARENT must be mutable. NAME must be a single path
    component; it cannot be a slash-separated directory path. If the
- node being deleted is a mutable directory, it must be empty. */
+ node being deleted is mutable, it will vanish from the earth. If
+ it is a mutable directory, it must be empty. */
 svn_error_t *svn_fs__dag_delete (dag_node_t *parent,
                                  const char *name,
                                  trail_t *trail);
Index: nodes-table.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/nodes-table.c,v
retrieving revision 1.9
diff -u -r1.9 nodes-table.c
--- nodes-table.c 2001/02/28 02:19:55 1.9
+++ nodes-table.c 2001/02/28 10:11:30
@@ -337,6 +337,27 @@
 
 
 
+/* Removing revisions. */
+
+
+svn_error_t *
+svn_fs__delete_node (svn_fs_t *fs,
+ const svn_fs_id_t *id,
+ trail_t *trail)
+{
+ DBT key;
+
+ SVN_ERR (DB_WRAP (fs, "deleting entry from `nodes' table",
+ fs->nodes->del (fs->nodes,
+ trail->db_txn,
+ svn_fs__id_to_dbt (&key, id, trail->pool),
+ 0)));
+
+ return SVN_NO_ERROR;
+}
+
+
+
 /* Choosing node revision ID's. */
 
 
Index: nodes-table.h
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/nodes-table.h,v
retrieving revision 1.5
diff -u -r1.5 nodes-table.h
--- nodes-table.h 2001/02/13 16:17:24 1.5
+++ nodes-table.h 2001/02/28 10:11:30
@@ -52,6 +52,12 @@
                               trail_t *trail);
 
 
+/* Remove the node ID from `nodes' table of FS, as part of TRAIL. */
+svn_error_t *svn_fs__delete_node (svn_fs_t *fs,
+ const svn_fs_id_t *id,
+ trail_t *trail);
+
+
 /* Check FS's `nodes' table to find an unused node number, and set
    *ID_P to the ID of the first revision of an entirely new node in
    FS, as part of TRAIL. Allocate the new ID, and do all temporary
Index: txn-table.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/txn-table.c,v
retrieving revision 1.16
diff -u -r1.16 txn-table.c
--- txn-table.c 2001/02/27 15:16:58 1.16
+++ txn-table.c 2001/02/28 10:11:30
@@ -80,12 +80,12 @@
   skel_t *txn_skel = svn_fs__make_empty_list (pool);
   DBT key, value;
 
- svn_fs__prepend (svn_fs__mem_atom (unparsed_root_id->data,
- unparsed_root_id->len,
- pool),
- txn_skel);
   svn_fs__prepend (svn_fs__mem_atom (unparsed_base_root_id->data,
                                      unparsed_base_root_id->len,
+ pool),
+ txn_skel);
+ svn_fs__prepend (svn_fs__mem_atom (unparsed_root_id->data,
+ unparsed_root_id->len,
                                      pool),
                    txn_skel);
   svn_fs__prepend (svn_fs__str_atom ((char *) "transaction", pool), txn_skel);
Index: txn.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/txn.c,v
retrieving revision 1.28
diff -u -r1.28 txn.c
--- txn.c 2001/02/24 09:13:31 1.28
+++ txn.c 2001/02/28 10:11:31
@@ -22,8 +22,10 @@
 #include "txn.h"
 #include "err.h"
 #include "trail.h"
+#include "nodes-table.h"
 #include "rev-table.h"
 #include "txn-table.h"
+#include "dag.h"
 #include "tree.h"
 
 
@@ -152,6 +154,112 @@
 {
   *new_rev = SVN_INVALID_REVNUM;
   abort();
+ return SVN_NO_ERROR;
+}
+
+
+/* Helper function for svn_fs_abort_txn. Remove all mutable nodes
+ recursively. NODE must be a mutable directory. */
+static svn_error_t *
+delete_nodes (svn_fs_t *fs,
+ dag_node_t *node,
+ trail_t *trail)
+{
+ svn_boolean_t is_mutable;
+
+ SVN_ERR (svn_fs__dag_check_mutable (&is_mutable, node, trail));
+
+ if (is_mutable && svn_fs__dag_is_directory (node))
+ {
+ skel_t *entries, *entry;
+ SVN_ERR (svn_fs__dag_dir_entries (&entries, node, trail));
+
+ for (entry = entries; entry; entry = entry->next)
+ {
+ dag_node_t *child;
+ skel_t *name_skel;
+ char *name;
+
+ /* ENTRY is guaranteed to be well-formed. (NAME ID). */
+ name_skel = entry->children;
+ name = apr_palloc (trail->pool, name_skel->len + 1);
+ memcpy (name, name_skel->data, name_skel->len);
+ name[name_skel->len] = '\0';
+ SVN_ERR (svn_fs__dag_open (&child, node,
+ name,
+ trail));
+
+ if (svn_fs__dag_is_file (child)
+ || svn_fs__dag_is_copy (child))
+ {
+ SVN_ERR (svn_fs__dag_delete (node, name, trail));
+ }
+ else if (svn_fs__dag_is_directory)
+ {
+ svn_boolean_t child_is_mutable;
+
+ SVN_ERR (svn_fs__dag_check_mutable (&child_is_mutable,
+ node, trail));
+ /* Recurse if this is mutable directory. */
+ if (child_is_mutable)
+ SVN_ERR (delete_nodes (fs, child, trail));
+
+ /* Delete this directory regardless of mutable flag. */
+ SVN_ERR (svn_fs__dag_delete (node, name, trail));
+ }
+ else
+ abort ();
+ }
+ }
+ else
+ /* NODE must be a mutable directory or we have logic error. */
+ abort ();
+
+ return SVN_NO_ERROR;
+}
+
+
+
+static svn_error_t *
+txn_body_abort_txn (void *baton,
+ trail_t *trail)
+{
+ svn_fs_txn_t *txn = baton;
+
+ dag_node_t *root_node;
+ svn_boolean_t is_mutable;
+
+ SVN_ERR (svn_fs__dag_txn_root (&root_node, txn->fs, txn->id, trail));
+
+ SVN_ERR (svn_fs__dag_check_mutable (&is_mutable, root_node, trail));
+
+ /* It's possible no cloning is done. */
+ if (is_mutable)
+ {
+ /* Remove all mutable node from `nodes' table. */
+ SVN_ERR (delete_nodes (txn->fs, root_node, trail));
+
+ /* Remove root node itself */
+ SVN_ERR (svn_fs__delete_node (txn->fs,
+ svn_fs__dag_get_id (root_node),
+ trail));
+ }
+
+ /* Delete transaction from `transactions' table. */
+ SVN_ERR (svn_fs__delete_txn (txn->fs, txn->id, trail));
+
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_fs_abort_txn (svn_fs_txn_t *txn)
+{
+ /* Remove all mutable nodes reachable from transaction's root. */
+ SVN_ERR (svn_fs__retry_txn (txn->fs, txn_body_abort_txn, txn, txn->pool));
+
+ SVN_ERR (svn_fs_close_txn (txn));
+
   return SVN_NO_ERROR;
 }
 

-- 
Yoshiki Hayashi
Received on Sat Oct 21 14:36:23 2006

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.