Author: philip
Date: Tue Dec 10 17:41:05 2013
New Revision: 1549907
URL: http://svn.apache.org/r1549907
Log:
Make sure that the temporary transaction properties associated with
commit flags do not disappear when svn_fs_commit_txn is interrupted.
As a side effect this also reduces by one the number of times the
proto-revprop file is written in a typical commit.
* subversion/libsvn_fs_fs/structure: Describe new file.
* subversion/libsvn_fs_fs/fs.h
(PATH_TXN_PROPS_FINAL): New.
* subversion/libsvn_fs_fs/transaction.c
(path_txn_props_final): New.
(set_txn_proplist): Add boolean final flag.
(svn_fs_fs__change_txn_props): Pass new flag.
(write_final_revprop): New.
(commit_body): Call write_final_revprop.
(svn_fs_fs__begin_txn): Pass new flag.
Modified:
subversion/trunk/subversion/libsvn_fs_fs/fs.h
subversion/trunk/subversion/libsvn_fs_fs/structure
subversion/trunk/subversion/libsvn_fs_fs/transaction.c
Modified: subversion/trunk/subversion/libsvn_fs_fs/fs.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs.h?rev=1549907&r1=1549906&r2=1549907&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs.h Tue Dec 10 17:41:05 2013
@@ -81,6 +81,8 @@ extern "C" {
/* Names of special files and file extensions for transactions */
#define PATH_CHANGES "changes" /* Records changes made so far */
#define PATH_TXN_PROPS "props" /* Transaction properties */
+#define PATH_TXN_PROPS_FINAL "props-final" /* Final transaction properties
+ before moving to revprops */
#define PATH_NEXT_IDS "next-ids" /* Next temporary ID assignments */
#define PATH_PREFIX_NODE "node." /* Prefix for node filename */
#define PATH_EXT_TXN ".txn" /* Extension of txn dir */
Modified: subversion/trunk/subversion/libsvn_fs_fs/structure
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/structure?rev=1549907&r1=1549906&r2=1549907&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/structure (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/structure Tue Dec 10 17:41:05 2013
@@ -602,6 +602,7 @@ Transaction layout
A transaction directory has the following layout:
props Transaction props
+ props-final Final transaction props (optional)
next-ids Next temporary node-ID and copy-ID
changes Changed-path information so far
node.<nid>.<cid> New node-rev data for node
@@ -629,9 +630,11 @@ they are received from the client. To e
writing to the file at a given time, the "rev-lock" file is locked for
the duration of each write.
-The two kinds of props files are all in hash dump format. The "props"
+The three kinds of props files are all in hash dump format. The "props"
file will always be present. The "node.<nid>.<cid>.props" file will
-only be present if the node-rev properties have been changed.
+only be present if the node-rev properties have been changed. The
+"props-final" only exists while converting the transaction into a revision.
+
The <sha1> files have been introduced in FS format 6. Their content
is that of text rep references: "<rev> <item_offset> <length> <size> <digest>"
Modified: subversion/trunk/subversion/libsvn_fs_fs/transaction.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/transaction.c?rev=1549907&r1=1549906&r2=1549907&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/transaction.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/transaction.c Tue Dec 10 17:41:05
2013
@@ -86,6 +86,15 @@ path_txn_props(svn_fs_t *fs,
}
static APR_INLINE const char *
+path_txn_props_final(svn_fs_t *fs,
+ const svn_fs_fs__id_part_t *txn_id,
+ apr_pool_t *pool)
+{
+ return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, txn_id, pool),
+ PATH_TXN_PROPS_FINAL, pool);
+}
+
+static APR_INLINE const char *
path_txn_next_ids(svn_fs_t *fs,
const svn_fs_fs__id_part_t *txn_id,
apr_pool_t *pool)
@@ -1144,6 +1153,7 @@ static svn_error_t *
set_txn_proplist(svn_fs_t *fs,
const svn_fs_fs__id_part_t *txn_id,
apr_hash_t *props,
+ svn_boolean_t final,
apr_pool_t *pool)
{
svn_stringbuf_t *buf;
@@ -1156,7 +1166,9 @@ set_txn_proplist(svn_fs_t *fs,
SVN_ERR(svn_stream_close(stream));
/* Open the transaction properties file and write new contents to it. */
- SVN_ERR(svn_io_write_atomic(path_txn_props(fs, txn_id, pool),
+ SVN_ERR(svn_io_write_atomic((final
+ ? path_txn_props_final(fs, txn_id, pool)
+ : path_txn_props(fs, txn_id, pool)),
buf->data, buf->len,
NULL /* copy_perms_path */, pool));
return SVN_NO_ERROR;
@@ -1208,7 +1220,7 @@ svn_fs_fs__change_txn_props(svn_fs_txn_t
/* Create a new version of the file and write out the new props. */
/* Open the transaction properties file. */
- SVN_ERR(set_txn_proplist(txn->fs, &ftd->txn_id, txn_prop, pool));
+ SVN_ERR(set_txn_proplist(txn->fs, &ftd->txn_id, txn_prop, FALSE, pool));
return SVN_NO_ERROR;
}
@@ -3620,6 +3632,60 @@ upgrade_transaction(svn_fs_t *fs,
return SVN_NO_ERROR;
}
+/* Return in *PATH the path to a file containing the properties that
+ make up the final revision properties file. This involves setting
+ svn:date and removing any temporary properties associated with the
+ commit flags. */
+static svn_error_t *
+write_final_revprop(const char **path,
+ svn_boolean_t set_timestamp,
+ svn_fs_txn_t *txn,
+ const svn_fs_fs__id_part_t *txn_id,
+ apr_pool_t *pool)
+{
+ apr_hash_t *txnprops;
+ svn_boolean_t final_mods = FALSE;
+
+ SVN_ERR(svn_fs_fs__txn_proplist(&txnprops, txn, pool));
+
+ /* Remove any temporary txn props representing 'flags'. */
+ if (svn_hash_gets(txnprops, SVN_FS__PROP_TXN_CHECK_OOD))
+ {
+ svn_hash_sets(txnprops, SVN_FS__PROP_TXN_CHECK_OOD, NULL);
+ final_mods = TRUE;
+ }
+
+ if (svn_hash_gets(txnprops, SVN_FS__PROP_TXN_CHECK_LOCKS))
+ {
+ svn_hash_sets(txnprops, SVN_FS__PROP_TXN_CHECK_LOCKS, NULL);
+ final_mods = TRUE;
+ }
+
+ /* Update commit time to ensure that svn:date revprops remain ordered if
+ requested. */
+ if (set_timestamp)
+ {
+ svn_string_t date;
+
+ date.data = svn_time_to_cstring(apr_time_now(), pool);
+ date.len = strlen(date.data);
+ svn_hash_sets(txnprops, SVN_PROP_REVISION_DATE, &date);
+ final_mods = TRUE;
+ }
+
+ if (final_mods)
+ {
+ SVN_ERR(set_txn_proplist(txn->fs, txn_id, txnprops, TRUE, pool));
+ *path = path_txn_props_final(txn->fs, txn_id, pool);
+ }
+ else
+ {
+ *path = path_txn_props(txn->fs, txn_id, pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* Baton used for commit_body below. */
struct commit_baton {
svn_revnum_t *new_rev_p;
@@ -3648,9 +3714,6 @@ commit_body(void *baton, apr_pool_t *poo
apr_file_t *proto_file;
void *proto_file_lockcookie;
apr_off_t initial_offset, changed_path_offset;
- apr_hash_t *txnprops;
- apr_array_header_t *txnprop_list;
- svn_prop_t prop;
const svn_fs_fs__id_part_t *txn_id = svn_fs_fs__txn_get_id(cb->txn);
apr_hash_t *changed_paths;
@@ -3736,30 +3799,6 @@ commit_body(void *baton, apr_pool_t *poo
race with another caller writing to the prototype revision file
before we commit it. */
- /* Remove any temporary txn props representing 'flags'.
-
- ### This is a permanent change to the transaction. If this
- ### commit does not complete for any reason the transaction will
- ### still exist but will have lost these properties. */
- SVN_ERR(svn_fs_fs__txn_proplist(&txnprops, cb->txn, pool));
- txnprop_list = apr_array_make(pool, 3, sizeof(svn_prop_t));
- prop.value = NULL;
-
- if (svn_hash_gets(txnprops, SVN_FS__PROP_TXN_CHECK_OOD))
- {
- prop.name = SVN_FS__PROP_TXN_CHECK_OOD;
- APR_ARRAY_PUSH(txnprop_list, svn_prop_t) = prop;
- }
-
- if (svn_hash_gets(txnprops, SVN_FS__PROP_TXN_CHECK_LOCKS))
- {
- prop.name = SVN_FS__PROP_TXN_CHECK_LOCKS;
- APR_ARRAY_PUSH(txnprop_list, svn_prop_t) = prop;
- }
-
- if (! apr_is_empty_array(txnprop_list))
- SVN_ERR(svn_fs_fs__change_txn_props(cb->txn, txnprop_list, pool));
-
/* Create the shard for the rev and revprop file, if we're sharding and
this is the first revision of a new shard. We don't care if this
fails because the shard already existed for some reason. */
@@ -3828,22 +3867,10 @@ commit_body(void *baton, apr_pool_t *poo
remove the transaction directory later. */
SVN_ERR(unlock_proto_rev(cb->fs, txn_id, proto_file_lockcookie, pool));
- /* Update commit time to ensure that svn:date revprops remain ordered if
- requested. */
- if (cb->set_timestamp)
- {
- svn_string_t date;
-
- date.data = svn_time_to_cstring(apr_time_now(), pool);
- date.len = strlen(date.data);
-
- SVN_ERR(svn_fs_fs__change_txn_prop(cb->txn, SVN_PROP_REVISION_DATE,
- &date, pool));
- }
-
/* Move the revprops file into place. */
SVN_ERR_ASSERT(! svn_fs_fs__is_packed_revprop(cb->fs, new_rev));
- revprop_filename = path_txn_props(cb->fs, txn_id, pool);
+ SVN_ERR(write_final_revprop(&revprop_filename, cb->set_timestamp,
+ cb->txn, txn_id, pool));
final_revprop = svn_fs_fs__path_revprops(cb->fs, new_rev, pool);
SVN_ERR(svn_fs_fs__move_into_place(revprop_filename, final_revprop,
old_rev_filename, pool));
@@ -4150,5 +4177,6 @@ svn_fs_fs__begin_txn(svn_fs_txn_t **txn_
svn_string_create("true", pool));
ftd = (*txn_p)->fsap_data;
- return svn_error_trace(set_txn_proplist(fs, &ftd->txn_id, props, pool));
+ return svn_error_trace(set_txn_proplist(fs, &ftd->txn_id, props, FALSE,
+ pool));
}