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 (¤t_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