Author: philip
Date: Wed Dec 11 15:00:37 2013
New Revision: 1550164
URL: http://svn.apache.org/r1550164
Log:
FSX implementation of FSFS r1549907.
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
(svn_fs_x__change_txn_props): Rename to ...
(change_txn_props): ... this, add boolean parameter.
(svn_fs_x__change_txn_props): New wrapper.
(write_final_revprop): New.
(commit_body): Call write_final_revprop.
* subversion/libsvn_fs_fs/util.h
(svn_fs_x__path_txn_props_final): New.
* subversion/libsvn_fs_fs/util.c
(svn_fs_x__path_txn_props_final): New.
(set_txn_proplist): Add boolean final flag.
Modified:
subversion/trunk/subversion/libsvn_fs_x/fs.h
subversion/trunk/subversion/libsvn_fs_x/structure
subversion/trunk/subversion/libsvn_fs_x/transaction.c
subversion/trunk/subversion/libsvn_fs_x/util.c
subversion/trunk/subversion/libsvn_fs_x/util.h
Modified: subversion/trunk/subversion/libsvn_fs_x/fs.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/fs.h?rev=1550164&r1=1550163&r2=1550164&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/fs.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/fs.h Wed Dec 11 15:00:37 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_x/structure
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/structure?rev=1550164&r1=1550163&r2=1550164&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/structure (original)
+++ subversion/trunk/subversion/libsvn_fs_x/structure Wed Dec 11 15:00:37 2013
@@ -226,6 +226,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
@@ -241,9 +242,10 @@ 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' content is that of text rep references:
"<rev> <offset> <length> <size> <digest>"
Modified: subversion/trunk/subversion/libsvn_fs_x/transaction.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/transaction.c?rev=1550164&r1=1550163&r2=1550164&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/transaction.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/transaction.c Wed Dec 11 15:00:37
2013
@@ -1141,10 +1141,11 @@ svn_fs_x__change_txn_prop(svn_fs_txn_t *
return svn_fs_x__change_txn_props(txn, props, pool);
}
-svn_error_t *
-svn_fs_x__change_txn_props(svn_fs_txn_t *txn,
- const apr_array_header_t *props,
- apr_pool_t *pool)
+static svn_error_t *
+change_txn_props(svn_fs_txn_t *txn,
+ const apr_array_header_t *props,
+ svn_boolean_t final,
+ apr_pool_t *pool)
{
fs_txn_data_t *ftd = txn->fsap_data;
const char *txn_prop_filename;
@@ -1184,8 +1185,20 @@ svn_fs_x__change_txn_props(svn_fs_txn_t
svn_io_file_del_none,
pool));
return svn_io_file_rename(txn_prop_filename,
- svn_fs_x__path_txn_props(txn->fs, &ftd->txn_id, pool),
- pool);
+ (final
+ ? svn_fs_x__path_txn_props_final(txn->fs, &ftd->txn_id, pool)
+ : svn_fs_x__path_txn_props(txn->fs, &ftd->txn_id, pool)),
+ pool);
+}
+
+svn_error_t *
+svn_fs_x__change_txn_props(svn_fs_txn_t *txn,
+ const apr_array_header_t *props,
+ apr_pool_t *pool)
+{
+ SVN_ERR(change_txn_props(txn, props, FALSE, pool));
+
+ return SVN_NO_ERROR;
}
svn_error_t *
@@ -3014,6 +3027,68 @@ verify_moves(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_x__id_part_t *txn_id,
+ apr_pool_t *pool)
+{
+ apr_hash_t *txnprops;
+ apr_array_header_t *final_mods = NULL;
+ svn_string_t date;
+ svn_prop_t prop;
+
+ SVN_ERR(svn_fs_x__txn_proplist(&txnprops, txn, pool));
+
+ /* Remove any temporary txn props representing 'flags'. */
+ prop.value = NULL;
+ if (svn_hash_gets(txnprops, SVN_FS__PROP_TXN_CHECK_OOD))
+ {
+ if (!final_mods)
+ final_mods = apr_array_make(pool, 3, sizeof(svn_prop_t));
+ prop.name = SVN_FS__PROP_TXN_CHECK_OOD;
+ APR_ARRAY_PUSH(final_mods, svn_prop_t) = prop;
+ }
+
+ if (svn_hash_gets(txnprops, SVN_FS__PROP_TXN_CHECK_LOCKS))
+ {
+ if (!final_mods)
+ final_mods = apr_array_make(pool, 3, sizeof(svn_prop_t));
+ prop.name = SVN_FS__PROP_TXN_CHECK_LOCKS;
+ APR_ARRAY_PUSH(final_mods, svn_prop_t) = prop;
+ }
+
+ /* Update commit time to ensure that svn:date revprops remain ordered if
+ requested. */
+ if (set_timestamp)
+ {
+ if (!final_mods)
+ final_mods = apr_array_make(pool, 3, sizeof(svn_prop_t));
+ date.data = svn_time_to_cstring(apr_time_now(), pool);
+ date.len = strlen(date.data);
+ prop.name = SVN_PROP_REVISION_DATE;
+ prop.value = &date;
+ APR_ARRAY_PUSH(final_mods, svn_prop_t) = prop;
+ }
+
+ if (final_mods)
+ {
+ SVN_ERR(change_txn_props(txn, final_mods, TRUE, pool));
+ *path = svn_fs_x__path_txn_props_final(txn->fs, txn_id, pool);
+ }
+ else
+ {
+ *path = svn_fs_x__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;
@@ -3097,26 +3172,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'. */
- SVN_ERR(svn_fs_x__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_x__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. */
@@ -3177,22 +3232,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_x__change_txn_prop(cb->txn, SVN_PROP_REVISION_DATE,
- &date, pool));
- }
-
/* Move the revprops file into place. */
SVN_ERR_ASSERT(! svn_fs_x__is_packed_revprop(cb->fs, new_rev));
- revprop_filename = svn_fs_x__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_x__path_revprops(cb->fs, new_rev, pool);
SVN_ERR(svn_fs_x__move_into_place(revprop_filename, final_revprop,
old_rev_filename, pool));
Modified: subversion/trunk/subversion/libsvn_fs_x/util.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/util.c?rev=1550164&r1=1550163&r2=1550164&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/util.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/util.c Wed Dec 11 15:00:37 2013
@@ -286,6 +286,15 @@ svn_fs_x__path_txn_props(svn_fs_t *fs,
PATH_TXN_PROPS, pool);
}
+const char *
+svn_fs_x__path_txn_props_final(svn_fs_t *fs,
+ const svn_fs_x__id_part_t *txn_id,
+ apr_pool_t *pool)
+{
+ return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool),
+ PATH_TXN_PROPS_FINAL, pool);
+}
+
const char*
svn_fs_x__path_l2p_proto_index(svn_fs_t *fs,
const svn_fs_x__id_part_t *txn_id,
Modified: subversion/trunk/subversion/libsvn_fs_x/util.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/util.h?rev=1550164&r1=1550163&r2=1550164&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/util.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/util.h Wed Dec 11 15:00:37 2013
@@ -187,6 +187,11 @@ svn_fs_x__path_txn_props(svn_fs_t *fs,
apr_pool_t *pool);
const char *
+svn_fs_x__path_txn_props_final(svn_fs_t *fs,
+ const svn_fs_x__id_part_t *txn_id,
+ apr_pool_t *pool);
+
+const char *
svn_fs_x__path_txn_next_ids(svn_fs_t *fs,
const svn_fs_x__id_part_t *txn_id,
apr_pool_t *pool);