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

[PATCH] svn_fs_commit_txn

From: Yoshiki Hayashi <yoshiki_at_xemacs.org>
Date: 2001-03-05 06:41:48 CET

I examined nodes table and revisions table by db_dump and
this works fine. There will also be test cases for this.

* dag.c (make_node_immutable): New helper function for
  stabilize_node.
* dag.c (stabilize_node): New helper function for
  svn_fs__dag_commit_txn.
* dag.c (svn_fs__dag_commit_txn): New function.
* dag.h (svn_fs__dag_commit_txn): Add svn_revnum_t argument
  so that svn_fs_commit_txn can get new revision number.
* rev-table.c (svn_fs__youngest_rev): New function.
* rev-table.c (txn_body_youngest_rev): Call
  svn_fs__youngest_rev.
* rev-table.h (svn_fs__youngest_rev): New function declaration.
* txn.c (struct commit_txn_args): New struct.
* txn.c (txn_body_commit_txn): New helper function for
  svn_fs_commit_txn.
* txn.c (svn_fs_commit_txn): Fill in this function.

Index: subversion/libsvn_fs/dag.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/dag.c,v
retrieving revision 1.70
diff -u -r1.70 dag.c
--- subversion/libsvn_fs/dag.c 2001/03/03 21:10:13 1.70
+++ subversion/libsvn_fs/dag.c 2001/03/05 03:59:27
@@ -574,6 +572,122 @@
 }
 
 
+static svn_error_t *
+make_node_immutable (dag_node_t *node, trail_t *trail)
+{
+ skel_t *node_rev;
+ skel_t *header;
+ skel_t *flag, *prev = NULL;
+
+ /* Go get a fresh NODE-REVISION for this node. */
+ SVN_ERR (get_node_revision (&node_rev, node, trail));
+ /* The node "header" is the first element of a node-revision skel,
+ itself a list. */
+ header = node_rev->children;
+
+ /* Flag is the 3rd element of the header. */
+ for (flag = header->children->next->next; flag; flag = flag->next)
+ {
+ if (! flag->is_atom && svn_fs__matches_atom (flag->children, "mutable"))
+ {
+ /* We found it. */
+ if (prev)
+ prev->next = flag->next;
+ else
+ header->children->next->next = 0;
+
+ SVN_ERR (set_node_revision (node, node_rev, trail));
+ return SVN_NO_ERROR;
+ }
+ prev = flag;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+stabilize_node (dag_node_t *node, trail_t *trail)
+{
+ if (svn_fs__dag_is_directory (node))
+ {
+ skel_t *entries;
+ skel_t *entry;
+
+ SVN_ERR (svn_fs__dag_dir_entries (&entries, node, trail));
+
+ /* Each entry looks like (NAME ID). */
+ for (entry = entries->children; entry; entry = entry->next)
+ {
+ dag_node_t *child;
+ skel_t *id_skel = entry->children->next;
+ svn_boolean_t is_mutable;
+
+ SVN_ERR (svn_fs__dag_get_node (&child, node->fs,
+ svn_fs_parse_id (id_skel->data,
+ id_skel->len,
+ trail->pool),
+ trail));
+ SVN_ERR (svn_fs__dag_check_mutable (&is_mutable, child, trail));
+
+ if (is_mutable)
+ SVN_ERR (stabilize_node (child, trail));
+ }
+ }
+ else if (svn_fs__dag_is_file (node)
+ || svn_fs__dag_is_copy (node))
+ ;
+ else
+ abort ();
+
+ SVN_ERR (make_node_immutable (node, trail));
+ SVN_ERR (svn_fs__stable_node (node->fs, node->id, trail));
+
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_fs__dag_commit_txn (svn_revnum_t *new_rev,
+ svn_fs_t *fs,
+ const char *svn_txn,
+ trail_t *trail)
+{
+ dag_node_t *root;
+ svn_boolean_t is_mutable;
+
+ SVN_ERR (svn_fs__dag_txn_root (&root, fs, svn_txn, trail));
+ SVN_ERR (svn_fs__dag_check_mutable (&is_mutable, root, trail));
+
+ /* Nothing is changed in this transaction. */
+ if (! is_mutable)
+ return SVN_NO_ERROR;
+
+ /* Make all mutable node immutable and stable. */
+ SVN_ERR (stabilize_node (root, trail));
+
+ {
+ /* Add rew revision entry to `revisions' table. */
+ skel_t *new_revision_skel;
+ svn_string_t *id_string = svn_fs_unparse_id (root->id, trail->pool);
+
+ new_revision_skel = svn_fs__make_empty_list (trail->pool);
+ svn_fs__prepend (svn_fs__make_empty_list (trail->pool),
+ new_revision_skel);
+ svn_fs__prepend (svn_fs__mem_atom (id_string->data,
+ id_string->len, trail->pool),
+ new_revision_skel);
+ svn_fs__prepend (svn_fs__str_atom ((char *) "revision", trail->pool),
+ new_revision_skel);
+ SVN_ERR (svn_fs__put_rev (new_rev, fs, new_revision_skel, trail));
+ }
+ /* Delete transaction from `transactions' table. */
+ SVN_ERR (svn_fs__delete_txn (fs, svn_txn, trail));
+
+ return SVN_NO_ERROR;
+}
+
+
 /* Helper function for svn_fs__dag_clone_child.
    Given a PARENT directory, and the NAME of an entry in that
    directory, update the PARENT's ENTRY list item for the NAMEd entry
Index: subversion/libsvn_fs/dag.h
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/dag.h,v
retrieving revision 1.31
diff -u -r1.31 dag.h
--- subversion/libsvn_fs/dag.h 2001/03/02 20:32:36 1.31
+++ subversion/libsvn_fs/dag.h 2001/03/05 03:59:27
@@ -158,7 +158,8 @@
                                      trail_t *trail);
 
 
-/* Commit the transaction SVN_TXN in FS, as part of TRAIL. This entails:
+/* Commit the transaction SVN_TXN in FS, as part of TRAIL. Store the
+ new revision number in NEW_REV. This entails:
    - marking the tree of mutable nodes at SVN_TXN's root as immutable,
      and marking all their contents as stable
    - creating a new revision, with SVN_TXN's root as its root directory
@@ -171,7 +172,8 @@
    Do any necessary temporary allocation in a subpool of TRAIL->pool.
    Consume temporary space at most proportional to the maximum depth
    of SVN_TXN's tree of mutable nodes. */
-svn_error_t *svn_fs__dag_commit_txn (svn_fs_t *fs,
+svn_error_t *svn_fs__dag_commit_txn (svn_revnum_t *new_rev,
+ svn_fs_t *fs,
                                      const char *svn_txn,
                                      trail_t *trail);
 
Index: subversion/libsvn_fs/rev-table.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/rev-table.c,v
retrieving revision 1.8
diff -u -r1.8 rev-table.c
--- subversion/libsvn_fs/rev-table.c 2001/03/03 10:18:01 1.8
+++ subversion/libsvn_fs/rev-table.c 2001/03/05 03:59:27
@@ -161,25 +161,16 @@
 /* Getting the youngest revision. */
 
 
-struct youngest_rev_args {
- svn_revnum_t *youngest_p;
- svn_fs_t *fs;
-};
-
-
-static svn_error_t *
-txn_body_youngest_rev (void *baton,
- trail_t *trail)
+svn_error_t *
+svn_fs__youngest_rev (svn_revnum_t *youngest_p,
+ svn_fs_t *fs,
+ trail_t *trail)
 {
- struct youngest_rev_args *args = baton;
-
   int db_err;
   DBC *cursor = 0;
   DBT key, value;
   db_recno_t recno;
 
- svn_fs_t *fs = args->fs;
-
   /* Create a database cursor. */
   SVN_ERR (DB_WRAP (fs, "getting youngest revision (creating cursor)",
                     fs->revisions->cursor (fs->revisions, trail->db_txn,
@@ -218,7 +209,24 @@
   /* Turn the record number into a Subversion revision number.
      Revisions are numbered starting with zero; Berkeley DB record
      numbers begin with one. */
- *args->youngest_p = recno - 1;
+ *youngest_p = recno - 1;
+
+ return SVN_NO_ERROR;
+}
+
+struct youngest_rev_args {
+ svn_revnum_t *youngest_p;
+ svn_fs_t *fs;
+};
+
+
+static svn_error_t *
+txn_body_youngest_rev (void *baton,
+ trail_t *trail)
+{
+ struct youngest_rev_args *args = baton;
+ SVN_ERR (svn_fs__youngest_rev (args->youngest_p, args->fs, trail));
+
   return SVN_NO_ERROR;
 }
 
Index: subversion/libsvn_fs/rev-table.h
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/rev-table.h,v
retrieving revision 1.5
diff -u -r1.5 rev-table.h
--- subversion/libsvn_fs/rev-table.h 2001/03/03 10:18:01 1.5
+++ subversion/libsvn_fs/rev-table.h 2001/03/05 03:59:27
@@ -63,6 +63,13 @@
                                    trail_t *trail);
 
 
+/* Set *YOUNGEST_P to the number of the youngest revision in filesystem FS,
+ as part of TRAIL. Use TRAIL->pool for all temporary allocation. */
+svn_error_t *svn_fs__youngest_rev (svn_revnum_t *youngest_p,
+ svn_fs_t *fs,
+ trail_t *trail);
+
+
 #endif /* SVN_LIBSVN_FS_REV_TABLE_H */
 
 
Index: subversion/libsvn_fs/txn.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/txn.c,v
retrieving revision 1.29
diff -u -r1.29 txn.c
--- subversion/libsvn_fs/txn.c 2001/03/03 17:25:38 1.29
+++ subversion/libsvn_fs/txn.c 2001/03/05 05:34:51
@@ -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"
 
 
@@ -146,12 +148,50 @@
 }
 
 
+struct commit_txn_args {
+ svn_revnum_t *new_rev;
+ svn_fs_txn_t *txn;
+};
+
+
+static svn_error_t *
+txn_body_commit_txn (void *baton, trail_t *trail)
+{
+ struct commit_txn_args *args = baton;
+
+ svn_fs_txn_t *txn = args->txn;
+ svn_revnum_t youngest_rev;
+ svn_fs_id_t *ignored, *base_root_id, *current_root_id;
+
+ /* Is there already a new revision? */
+ SVN_ERR (svn_fs__get_txn (&ignored, &base_root_id, txn->fs,
+ txn->id, trail));
+ SVN_ERR (svn_fs__youngest_rev (&youngest_rev, txn->fs, trail));
+ SVN_ERR (svn_fs__rev_get_root (&current_root_id, txn->fs,
+ youngest_rev, trail));
+ if (! svn_fs_id_eq (base_root_id, current_root_id))
+ return svn_error_createf (SVN_ERR_FS_CONFLICT, 0, 0, trail->pool,
+ "Trying to commit old transaction, ID `%s'",
+ txn->id);
+
+ SVN_ERR (svn_fs__dag_commit_txn (args->new_rev, txn->fs, txn->id, trail));
+
+ return SVN_NO_ERROR;
+}
+
+
 svn_error_t *
 svn_fs_commit_txn (svn_revnum_t *new_rev,
                    svn_fs_txn_t *txn)
 {
+ struct commit_txn_args args;
+
   *new_rev = SVN_INVALID_REVNUM;
- abort();
+ args.new_rev = new_rev;
+ args.txn = txn;
+
+ SVN_ERR (svn_fs__retry_txn (txn->fs, txn_body_commit_txn, &args, txn->pool));
+
   return SVN_NO_ERROR;
 }
 

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

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