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

Re: [PATCH][merge-tracking]sqlite mergeinfo indexing for bdb repositories

From: Kamesh Jayachandran <kamesh_at_collab.net>
Date: 2006-10-13 18:03:14 CEST

Daniel Rall wrote:
> On Thu, 12 Oct 2006, Kamesh Jayachandran wrote:
>
>
>> Patch looks fine to me.
>> Let me leverage on it with the suggested change to fs_skel.
>>
>
> Sounds good, Kamesh. I'll commit the patch after you've made those
> changes.
>
> - Dan
>
Attaching the patch/log having the 'svn:txn-mergeinfo' as an atomic blob.

Focus on subversion/libsvn_fs_base/revs-txn.c alone as that alone
changed majorly in this new patch.

With regards
Kamesh Jayachandran

On the merge-tracking branch: Implement 'txn-mergeinfo' change,
storage and retrieval for 'bdb' repositories.

Store the transaction merge info as a temporary transaction property
(svn:txn-mergeinfo) with a value as 'serialized form of apr_hash_t'.

* subversion/libsvn_fs_base/dag.h
   (svn_fs_base__dag_commit_txn): Change the signature to accept
    "svn_fs_txn_t *" (needed by svn_fs_merge_info__update_index()).
    From "svn_fs_txn_t *", derive "svn_fs_t *" and "const char
    *txn_id" rather than passing them explicitly.

* subversion/libsvn_fs_base/tree.c
  Include "svn_mergeinfo.h".
  (struct change_merge_info_args): New structure used as the baton for
   txn_body_change_merge_info().
  (txn_body_change_merge_info): New helper function for
   base_change_merge_info()'s usage of the svn_fs_base__retry_txn()
   callback parameter.
  (base_change_merge_info): New hook function implementing root_vtable_t's
   "change_merge_info" hook.
  (change_txn_merge_info): New function to update the transaction
   merge info upon modification of the "svn:mergeinfo" property.
  (txn_body_change_node_prop): Call change_txn_merge_info() if the
   property getting modified is "svn:mergeinfo".
  (txn_body_commit): Update for API change to svn_fs_base__dag_commit_txn().
  (root_vtable): Set the "change_merge_info" hook to "base_change_merge_info".

* subversion/libsvn_fs_base/tree.h
  Include "svn_props.h"
  (SVN_FS_PROP_TXN_MERGEINFO): New macro.

* subversion/libsvn_fs_base/revs-txns.c
  Include "svn_hash.h" "svn_io.h" for serializing the mergeinfo.
  (svn_fs_base__set_txn_merge_info): New function to record the
   transaction merge info.
  (base_txn_merge_info): New function that retrieves the stored
   transaction mergeinfo implementing txn_vtable_t->get_mergeinfo hook.
  (txn_vtable): Set 'get_mergeinfo' hook to 'base_txn_merge_info'.
 
* subversion/libsvn_fs_base/revs-txns.h
  (svn_fs_base__set_txn_merge_info): Add prototype.

* subversion/libsvn_fs_base/dag.c
  Include "tree.h" and "private/svn_fs_merge_info.h".
  (svn_fs_base__dag_commit_txn): Changed function signature. Record
   merge info by calling svn_fs_merge_info__update_index().

Patch by: Kamesh Jayachandran <kamesh@collab.net>
(Tweaked by me.)

Index: subversion/libsvn_fs_base/tree.c
===================================================================
--- subversion/libsvn_fs_base/tree.c (revision 21898)
+++ subversion/libsvn_fs_base/tree.c (working copy)
@@ -38,6 +38,7 @@
 #include "svn_error.h"
 #include "svn_path.h"
 #include "svn_md5.h"
+#include "svn_mergeinfo.h"
 #include "svn_fs.h"
 #include "svn_sorts.h"
 #include "fs.h"
@@ -1281,7 +1282,48 @@
   return SVN_NO_ERROR;
 }
 
+/* The input for txn_body_change_merge_info(). */
+struct change_merge_info_args
+{
+ svn_fs_root_t *root;
+ const char *path;
+ const svn_string_t *value;
+};
 
+/* Set the merge info on the transaction in BATON (expected to be of
+ type "struct change_merge_info_args"). Conforms to the callback
+ API used by svn_fs_base__retry_txn(). */
+static svn_error_t *
+txn_body_change_merge_info(void *baton,
+ trail_t *trail)
+{
+ struct change_merge_info_args *args = baton;
+ SVN_ERR(svn_fs_base__set_txn_merge_info(args->root->fs, args->root->txn,
+ args->path, args->value,
+ trail, trail->pool));
+ return SVN_NO_ERROR;
+}
+
+/* Change the merge info for the specified PATH to MERGE_INFO. */
+static svn_error_t *
+base_change_merge_info(svn_fs_root_t *root,
+ const char *path,
+ apr_hash_t *merge_info,
+ apr_pool_t *pool)
+{
+ svn_stringbuf_t *minfostr;
+ struct change_merge_info_args args;
+
+ if (! root->is_txn_root)
+ return NOT_TXN(root);
+ SVN_ERR(svn_mergeinfo_to_string(&minfostr, merge_info, pool));
+ args.root = root;
+ args.path = path;
+ args.value = svn_string_create_from_buf(minfostr, pool);
+ return svn_fs_base__retry_txn(root->fs, txn_body_change_merge_info, &args,
+ pool);
+}
+
 struct change_node_prop_args {
   svn_fs_root_t *root;
   const char *path;
@@ -1291,6 +1333,24 @@
 
 
 static svn_error_t *
+change_txn_merge_info(struct change_node_prop_args *args, trail_t *trail)
+{
+ const char *txn_id = args->root->txn;
+
+ /* At least for single file merges, nodes which are direct
+ children of the root are received without a leading slash
+ (e.g. "/file.txt" is received as "file.txt"), so must be made
+ absolute. */
+ const char *canon_path = svn_fs_base__canonicalize_abspath(args->path,
+ trail->pool);
+ SVN_ERR(svn_fs_base__set_txn_merge_info(args->root->fs, txn_id, canon_path,
+ args->value, trail, trail->pool));
+
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
 txn_body_change_node_prop(void *baton,
                           trail_t *trail)
 {
@@ -1321,6 +1381,9 @@
   if (! proplist)
     proplist = apr_hash_make(trail->pool);
 
+ if (strcmp(args->name, SVN_PROP_MERGE_INFO) == 0)
+ SVN_ERR(change_txn_merge_info(args, trail));
+
   /* Set the property. */
   apr_hash_set(proplist, args->name, APR_HASH_KEY_STRING, args->value);
 
@@ -2382,8 +2445,8 @@
   SVN_ERR(verify_locks(txn_name, trail, trail->pool));
 
   /* Else, commit the txn. */
- SVN_ERR(svn_fs_base__dag_commit_txn(&(args->new_rev), fs, txn_name,
- trail, trail->pool));
+ SVN_ERR(svn_fs_base__dag_commit_txn(&(args->new_rev), txn, trail,
+ trail->pool));
 
   return SVN_NO_ERROR;
 }
@@ -4374,7 +4437,7 @@
   base_contents_changed,
   base_get_file_delta_stream,
   base_merge,
- NULL,
+ base_change_merge_info,
   svn_fs_merge_info__get_merge_info
 };
 
Index: subversion/libsvn_fs_base/dag.h
===================================================================
--- subversion/libsvn_fs_base/dag.h (revision 21898)
+++ subversion/libsvn_fs_base/dag.h (working copy)
@@ -1,7 +1,7 @@
 /* dag.h : DAG-like interface filesystem, private to libsvn_fs
  *
  * ====================================================================
- * Copyright (c) 2000-2004 CollabNet. All rights reserved.
+ * Copyright (c) 2000-2006 CollabNet. All rights reserved.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -199,23 +199,22 @@
                                          apr_pool_t *pool);
 
 
-/* Commit the transaction TXN_ID in FS, as part of TRAIL. Store the
+/* Commit the transaction TXN->id in TXN->FS, as part of TRAIL. Store the
    new revision number in *NEW_REV. This entails:
- - marking the tree of mutable nodes at TXN_ID's root as immutable,
+ - marking the tree of mutable nodes at TXN->id's root as immutable,
      and marking all their contents as stable
- - creating a new revision, with TXN_ID's root as its root directory
- - promoting TXN_ID to a "committed" transaction.
+ - creating a new revision, with TXN->id's root as its root directory
+ - promoting TXN->id to a "committed" transaction.
 
- Beware! This does not make sure that TXN_ID is based on the very
- latest revision in FS. If the caller doesn't take care of this,
+ Beware! This does not make sure that TXN->id is based on the very
+ latest revision in TXN->FS. If the caller doesn't take care of this,
    you may lose people's work!
 
    Do any necessary temporary allocation in a subpool of POOL.
    Consume temporary space at most proportional to the maximum depth
    of SVN_TXN's tree of mutable nodes. */
 svn_error_t *svn_fs_base__dag_commit_txn(svn_revnum_t *new_rev,
- svn_fs_t *fs,
- const char *txn_id,
+ svn_fs_txn_t *txn,
                                          trail_t *trail,
                                          apr_pool_t *pool);
 
Index: subversion/libsvn_fs_base/tree.h
===================================================================
--- subversion/libsvn_fs_base/tree.h (revision 21898)
+++ subversion/libsvn_fs_base/tree.h (working copy)
@@ -1,7 +1,7 @@
 /* tree.h : internal interface to tree node functions
  *
  * ====================================================================
- * Copyright (c) 2000-2004 CollabNet. All rights reserved.
+ * Copyright (c) 2000-2006 CollabNet. All rights reserved.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,12 @@
 extern "C" {
 #endif /* __cplusplus */
 
+#include "svn_props.h"
+
+/* A transaction property which maps to a skel form of apr_hash_t
+ (target wc path char * -> actual merge info). */
+#define SVN_FS_PROP_TXN_MERGEINFO SVN_PROP_PREFIX "txn-mergeinfo"
+
 
 
 /* These functions implement some of the calls in the FS loader
Index: subversion/libsvn_fs_base/revs-txns.c
===================================================================
--- subversion/libsvn_fs_base/revs-txns.c (revision 21898)
+++ subversion/libsvn_fs_base/revs-txns.c (working copy)
@@ -1,7 +1,7 @@
 /* revs-txns.c : operations on revision and transactions
  *
  * ====================================================================
- * Copyright (c) 2000-2004 CollabNet. All rights reserved.
+ * Copyright (c) 2000-2006 CollabNet. All rights reserved.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -25,6 +25,8 @@
 #include "svn_time.h"
 #include "svn_fs.h"
 #include "svn_props.h"
+#include "svn_hash.h"
+#include "svn_io.h"
 
 #include "fs.h"
 #include "dag.h"
@@ -558,7 +560,65 @@
   return put_txn(fs, txn, txn_name, trail, pool);
 }
 
+svn_error_t *
+svn_fs_base__set_txn_merge_info(svn_fs_t *fs,
+ const char *txn_name,
+ const char *path,
+ const svn_string_t *value,
+ trail_t *trail,
+ apr_pool_t *pool)
+{
+ transaction_t *txn;
+ apr_hash_t *target_mergeinfo;
+ svn_stringbuf_t* serialized_stringbuf;
+ const svn_string_t* serialized_string;
+ svn_stream_t *stream;
 
+ SVN_ERR(get_txn(&txn, fs, txn_name, FALSE, trail, pool));
+ if (txn->kind != transaction_kind_normal)
+ return svn_fs_base__err_txn_not_mutable(fs, txn_name);
+
+ if (txn->proplist == NULL)
+ {
+ /* If we're deleting a property, exit now. Otherwise, create a
+ proplist. */
+ if (value == NULL)
+ return SVN_NO_ERROR;
+
+ txn->proplist = apr_hash_make(pool);
+ }
+
+ target_mergeinfo = apr_hash_make(pool);
+ serialized_string = apr_hash_get(txn->proplist, SVN_FS_PROP_TXN_MERGEINFO,
+ APR_HASH_KEY_STRING);
+ if (serialized_string)
+ {
+ serialized_stringbuf = svn_stringbuf_create_from_string(serialized_string,
+ pool);
+ stream = svn_stream_from_stringbuf(serialized_stringbuf, pool);
+ SVN_ERR(svn_hash_read2(target_mergeinfo, stream, NULL, pool));
+ }
+ else
+ {
+ serialized_stringbuf = svn_stringbuf_create("", pool);
+ stream = svn_stream_from_stringbuf(serialized_stringbuf, pool);
+ }
+
+ /* Set the mergeinfo for the path. */
+ apr_hash_set(target_mergeinfo, path, APR_HASH_KEY_STRING, value);
+
+ /* Serialize the hash for storage. */
+ SVN_ERR(svn_hash_write2(target_mergeinfo, stream, NULL, pool));
+ serialized_string = svn_string_create_from_buf(serialized_stringbuf, pool);
+
+ /* Set the property. */
+ apr_hash_set(txn->proplist, SVN_FS_PROP_TXN_MERGEINFO,
+ APR_HASH_KEY_STRING, serialized_string);
+
+ /* Now overwrite the transaction. */
+ return put_txn(fs, txn, txn_name, trail, pool);
+}
+
 static svn_error_t *
 txn_body_change_txn_prop(void *baton, trail_t *trail)
 {
@@ -587,7 +647,46 @@
   return SVN_NO_ERROR;
 }
 
+/* txn_vtable's get_mergeinfo hook. Set TABLE_P to a merge info hash
+ (possibly empty), or NULL if there are no transaction
+ properties. */
+static svn_error_t *
+base_txn_merge_info(apr_hash_t **table_p,
+ svn_fs_txn_t *txn,
+ apr_pool_t *pool)
+{
+ apr_hash_t *txnprops = NULL;
+ apr_hash_t *target_mergeinfo = NULL;
+ struct txn_proplist_args args;
+ svn_fs_t *fs = txn->fs;
 
+ SVN_ERR(svn_fs_base__check_fs(fs));
+
+ args.table_p = &txnprops;
+ args.id = txn->id;
+ SVN_ERR(svn_fs_base__retry(fs, txn_body_txn_proplist, &args, pool));
+
+ if (txnprops)
+ {
+ const svn_string_t *serialized_string = apr_hash_get(txnprops,
+ SVN_FS_PROP_TXN_MERGEINFO,
+ APR_HASH_KEY_STRING);
+ if (serialized_string)
+ {
+ target_mergeinfo = apr_hash_make(pool);
+ svn_stringbuf_t* serialized_stringbuf =
+ svn_stringbuf_create_from_string(serialized_string, pool);
+ svn_stream_t *stream = svn_stream_from_stringbuf(serialized_stringbuf,
+ pool);
+ SVN_ERR(svn_hash_read2(target_mergeinfo, stream, NULL, pool));
+ }
+ }
+ *table_p = target_mergeinfo;
+
+ return SVN_NO_ERROR;
+}
+
+
 
 /* Creating a transaction */
 
@@ -598,7 +697,7 @@
   svn_fs_base__txn_proplist,
   svn_fs_base__change_txn_prop,
   svn_fs_base__txn_root,
- NULL
+ base_txn_merge_info
 };
 
 
Index: subversion/libsvn_fs_base/revs-txns.h
===================================================================
--- subversion/libsvn_fs_base/revs-txns.h (revision 21898)
+++ subversion/libsvn_fs_base/revs-txns.h (working copy)
@@ -1,7 +1,7 @@
 /* revs-txns.h : internal interface to revision and transactions operations
  *
  * ====================================================================
- * Copyright (c) 2000-2004 CollabNet. All rights reserved.
+ * Copyright (c) 2000-2006 CollabNet. All rights reserved.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -144,6 +144,20 @@
                                        apr_pool_t *pool);
 
 
+/* Set a PATH to VALUE for the SVN_FS_PROP_TXN_MERGEINFO property (a
+ hash table) on transaction TXN_NAME's proplist in FS as part of
+ TRAIL. Use POOL for any necessary allocations.
+
+ Return SVN_ERR_FS_TRANSACTION_NOT_MUTABLE if TXN_NAME refers to a
+ transaction that has already been committed. */
+svn_error_t *
+svn_fs_base__set_txn_merge_info(svn_fs_t *fs,
+ const char *txn_name,
+ const char *path,
+ const svn_string_t *value,
+ trail_t *trail,
+ apr_pool_t *pool);
+
 /* Set a property NAME to VALUE on transaction TXN_NAME in FS as part
    of TRAIL. Use POOL for any necessary allocations.
 
Index: subversion/libsvn_fs_base/dag.c
===================================================================
--- subversion/libsvn_fs_base/dag.c (revision 21898)
+++ subversion/libsvn_fs_base/dag.c (working copy)
@@ -1,7 +1,7 @@
 /* dag.c : DAG-like interface filesystem, private to libsvn_fs
  *
  * ====================================================================
- * Copyright (c) 2000-2004 CollabNet. All rights reserved.
+ * Copyright (c) 2000-2006 CollabNet. All rights reserved.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -34,6 +34,7 @@
 #include "reps-strings.h"
 #include "revs-txns.h"
 #include "id.h"
+#include "tree.h" /* needed for SVN_FS_PROP_TXN_MERGEINFO */
 
 #include "util/fs_skels.h"
 
@@ -44,6 +45,7 @@
 #include "bdb/reps-table.h"
 #include "bdb/strings-table.h"
 
+#include "private/svn_fs_merge_info.h"
 #include "../libsvn_fs/fs-loader.h"
 
 #include "svn_private_config.h"
@@ -1416,18 +1418,35 @@
 
 svn_error_t *
 svn_fs_base__dag_commit_txn(svn_revnum_t *new_rev,
- svn_fs_t *fs,
- const char *txn_id,
+ svn_fs_txn_t *txn,
                             trail_t *trail,
                             apr_pool_t *pool)
 {
   revision_t revision;
   svn_string_t date;
   apr_hash_t *txnprops;
+ svn_fs_t *fs = txn->fs;
+ const char *txn_id = txn->id;
+ const svn_string_t *target_mergeinfo;
 
   /* Remove any temporary transaction properties initially created by
      begin_txn(). */
   SVN_ERR(svn_fs_base__txn_proplist_in_trail(&txnprops, txn_id, trail));
+
+ /* Add new revision entry to `revisions' table. */
+ revision.txn_id = txn_id;
+ *new_rev = SVN_INVALID_REVNUM;
+ SVN_ERR(svn_fs_bdb__put_rev(new_rev, fs, &revision, trail, pool));
+
+ target_mergeinfo = apr_hash_get(txnprops, SVN_FS_PROP_TXN_MERGEINFO,
+ APR_HASH_KEY_STRING);
+ if (target_mergeinfo)
+ {
+ SVN_ERR(svn_fs_merge_info__update_index(txn, *new_rev, TRUE, pool));
+ SVN_ERR(svn_fs_base__set_txn_prop
+ (fs, txn_id, SVN_FS_PROP_TXN_MERGEINFO, NULL, trail, pool));
+ }
+
   if (txnprops)
     {
       if (apr_hash_get(txnprops, SVN_FS_PROP_TXN_CHECK_OOD,
@@ -1440,12 +1459,6 @@
         SVN_ERR(svn_fs_base__set_txn_prop
                 (fs, txn_id, SVN_FS_PROP_TXN_CHECK_LOCKS, NULL, trail, pool));
     }
-
- /* Add new revision entry to `revisions' table. */
- revision.txn_id = txn_id;
- *new_rev = SVN_INVALID_REVNUM;
- SVN_ERR(svn_fs_bdb__put_rev(new_rev, fs, &revision, trail, pool));
-
   /* Promote the unfinished transaction to a committed one. */
   SVN_ERR(svn_fs_base__txn_make_committed(fs, txn_id, *new_rev,
                                           trail, pool));

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri Oct 13 18:02:47 2006

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