You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2014/02/17 06:53:26 UTC

svn commit: r1568883 [4/6] - in /subversion/branches/fsfs-ucsnorm: ./ build/generator/ contrib/client-side/ contrib/client-side/emacs/ contrib/hook-scripts/ contrib/server-side/ notes/ notes/meetings/ notes/wc-ng/ subversion/bindings/ctypes-python/csvn...

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/transaction.c?rev=1568883&r1=1568882&r2=1568883&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/transaction.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/transaction.c Mon Feb 17 05:53:23 2014
@@ -66,14 +66,14 @@ static txn_vtable_t txn_vtable = {
 typedef struct fs_txn_data_t
 {
   /* Strongly typed representation of the TXN's ID member. */
-  svn_fs_x__id_part_t txn_id;
+  svn_fs_x__txn_id_t txn_id;
 } fs_txn_data_t;
 
-const svn_fs_x__id_part_t *
+svn_fs_x__txn_id_t
 svn_fs_x__txn_get_id(svn_fs_txn_t *txn)
 {
   fs_txn_data_t *ftd = txn->fsap_data;
-  return &ftd->txn_id;
+  return ftd->txn_id;
 }
 
 /* Functions for working with shared transaction data. */
@@ -85,7 +85,7 @@ svn_fs_x__txn_get_id(svn_fs_txn_t *txn)
    true) or return NULL (otherwise). */
 static fs_x_shared_txn_data_t *
 get_shared_txn(svn_fs_t *fs,
-               const svn_fs_x__id_part_t *txn_id,
+               svn_fs_x__txn_id_t txn_id,
                svn_boolean_t create_new)
 {
   fs_x_data_t *ffd = fs->fsap_data;
@@ -93,7 +93,7 @@ get_shared_txn(svn_fs_t *fs,
   fs_x_shared_txn_data_t *txn;
 
   for (txn = ffsd->txns; txn; txn = txn->next)
-    if (svn_fs_x__id_part_eq(&txn->txn_id, txn_id))
+    if (txn->txn_id == txn_id)
       break;
 
   if (txn || !create_new)
@@ -113,7 +113,7 @@ get_shared_txn(svn_fs_t *fs,
       txn->pool = subpool;
     }
 
-  txn->txn_id = *txn_id;
+  txn->txn_id = txn_id;
   txn->being_written = FALSE;
 
   /* Link this transaction into the head of the list.  We will typically
@@ -131,14 +131,14 @@ get_shared_txn(svn_fs_t *fs,
    locked via the txn_list_lock mutex).  Do nothing if the transaction
    does not exist. */
 static void
-free_shared_txn(svn_fs_t *fs, const svn_fs_x__id_part_t *txn_id)
+free_shared_txn(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id)
 {
   fs_x_data_t *ffd = fs->fsap_data;
   fs_x_shared_data_t *ffsd = ffd->shared;
   fs_x_shared_txn_data_t *txn, *prev = NULL;
 
   for (txn = ffsd->txns; txn; prev = txn, txn = txn->next)
-    if (svn_fs_x__id_part_eq(&txn->txn_id, txn_id))
+    if (txn->txn_id == txn_id)
       break;
 
   if (!txn)
@@ -299,7 +299,7 @@ with_txn_current_lock(svn_fs_t *fs,
    which see. */
 struct unlock_proto_rev_baton
 {
-  svn_fs_x__id_part_t txn_id;
+  svn_fs_x__txn_id_t txn_id;
   void *lockcookie;
 };
 
@@ -309,30 +309,30 @@ unlock_proto_rev_body(svn_fs_t *fs, cons
 {
   const struct unlock_proto_rev_baton *b = baton;
   apr_file_t *lockfile = b->lockcookie;
-  fs_x_shared_txn_data_t *txn = get_shared_txn(fs, &b->txn_id, FALSE);
+  fs_x_shared_txn_data_t *txn = get_shared_txn(fs, b->txn_id, FALSE);
   apr_status_t apr_err;
 
   if (!txn)
     return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                              _("Can't unlock unknown transaction '%s'"),
-                             svn_fs_x__id_txn_unparse(&b->txn_id, pool));
+                             svn_fs_x__txn_name(b->txn_id, pool));
   if (!txn->being_written)
     return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                              _("Can't unlock nonlocked transaction '%s'"),
-                             svn_fs_x__id_txn_unparse(&b->txn_id, pool));
+                             svn_fs_x__txn_name(b->txn_id, pool));
 
   apr_err = apr_file_unlock(lockfile);
   if (apr_err)
     return svn_error_wrap_apr
       (apr_err,
        _("Can't unlock prototype revision lockfile for transaction '%s'"),
-       svn_fs_x__id_txn_unparse(&b->txn_id, pool));
+       svn_fs_x__txn_name(b->txn_id, pool));
   apr_err = apr_file_close(lockfile);
   if (apr_err)
     return svn_error_wrap_apr
       (apr_err,
        _("Can't close prototype revision lockfile for transaction '%s'"),
-       svn_fs_x__id_txn_unparse(&b->txn_id, pool));
+       svn_fs_x__txn_name(b->txn_id, pool));
 
   txn->being_written = FALSE;
 
@@ -346,13 +346,13 @@ unlock_proto_rev_body(svn_fs_t *fs, cons
    Perform temporary allocations in POOL. */
 static svn_error_t *
 unlock_proto_rev(svn_fs_t *fs,
-                 const svn_fs_x__id_part_t *txn_id,
+                 svn_fs_x__txn_id_t txn_id,
                  void *lockcookie,
                  apr_pool_t *pool)
 {
   struct unlock_proto_rev_baton b;
 
-  b.txn_id = *txn_id;
+  b.txn_id = txn_id;
   b.lockcookie = lockcookie;
   return with_txnlist_lock(fs, unlock_proto_rev_body, &b, pool);
 }
@@ -361,13 +361,13 @@ unlock_proto_rev(svn_fs_t *fs,
    lock is already held. */
 static svn_error_t *
 unlock_proto_rev_list_locked(svn_fs_t *fs,
-                             const svn_fs_x__id_part_t *txn_id,
+                             svn_fs_x__txn_id_t txn_id,
                              void *lockcookie,
                              apr_pool_t *pool)
 {
   struct unlock_proto_rev_baton b;
 
-  b.txn_id = *txn_id;
+  b.txn_id = txn_id;
   b.lockcookie = lockcookie;
   return unlock_proto_rev_body(fs, &b, pool);
 }
@@ -378,7 +378,7 @@ struct get_writable_proto_rev_baton
 {
   apr_file_t **file;
   void **lockcookie;
-  svn_fs_x__id_part_t txn_id;
+  svn_fs_x__txn_id_t txn_id;
 };
 
 /* Callback used in the implementation of get_writable_proto_rev(). */
@@ -389,7 +389,7 @@ get_writable_proto_rev_body(svn_fs_t *fs
   apr_file_t **file = b->file;
   void **lockcookie = b->lockcookie;
   svn_error_t *err;
-  fs_x_shared_txn_data_t *txn = get_shared_txn(fs, &b->txn_id, TRUE);
+  fs_x_shared_txn_data_t *txn = get_shared_txn(fs, b->txn_id, TRUE);
 
   /* First, ensure that no thread in this process (including this one)
      is currently writing to this transaction's proto-rev file. */
@@ -399,7 +399,7 @@ get_writable_proto_rev_body(svn_fs_t *fs
                                "of transaction '%s' because a previous "
                                "representation is currently being written by "
                                "this process"),
-                             svn_fs_x__id_txn_unparse(&b->txn_id, pool));
+                             svn_fs_x__txn_name(b->txn_id, pool));
 
 
   /* We know that no thread in this process is writing to the proto-rev
@@ -412,7 +412,7 @@ get_writable_proto_rev_body(svn_fs_t *fs
     apr_file_t *lockfile;
     apr_status_t apr_err;
     const char *lockfile_path
-      = svn_fs_x__path_txn_proto_rev_lock(fs, &b->txn_id, pool);
+      = svn_fs_x__path_txn_proto_rev_lock(fs, b->txn_id, pool);
 
     /* Open the proto-rev lockfile, creating it if necessary, as it may
        not exist if the transaction dates from before the lockfiles were
@@ -436,8 +436,7 @@ get_writable_proto_rev_body(svn_fs_t *fs
                                      "file of transaction '%s' because a "
                                      "previous representation is currently "
                                      "being written by another process"),
-                                   svn_fs_x__id_txn_unparse(&b->txn_id,
-                                                            pool));
+                                   svn_fs_x__txn_name(b->txn_id, pool));
 
         return svn_error_wrap_apr(apr_err,
                                   _("Can't get exclusive lock on file '%s'"),
@@ -453,7 +452,7 @@ get_writable_proto_rev_body(svn_fs_t *fs
 
   /* Now open the prototype revision file and seek to the end. */
   err = svn_io_file_open(file,
-                         svn_fs_x__path_txn_proto_rev(fs, &b->txn_id, pool),
+                         svn_fs_x__path_txn_proto_rev(fs, b->txn_id, pool),
                          APR_WRITE | APR_BUFFERED, APR_OS_DEFAULT, pool);
 
   /* You might expect that we could dispense with the following seek
@@ -473,7 +472,7 @@ get_writable_proto_rev_body(svn_fs_t *fs
     {
       err = svn_error_compose_create(
               err,
-              unlock_proto_rev_list_locked(fs, &b->txn_id, *lockcookie, pool));
+              unlock_proto_rev_list_locked(fs, b->txn_id, *lockcookie, pool));
 
       *lockcookie = NULL;
     }
@@ -495,14 +494,14 @@ static svn_error_t *
 get_writable_proto_rev(apr_file_t **file,
                        void **lockcookie,
                        svn_fs_t *fs,
-                       const svn_fs_x__id_part_t *txn_id,
+                       svn_fs_x__txn_id_t txn_id,
                        apr_pool_t *pool)
 {
   struct get_writable_proto_rev_baton b;
 
   b.file = file;
   b.lockcookie = lockcookie;
-  b.txn_id = *txn_id;
+  b.txn_id = txn_id;
 
   return with_txnlist_lock(fs, get_writable_proto_rev_body, &b, pool);
 }
@@ -511,7 +510,7 @@ get_writable_proto_rev(apr_file_t **file
 static svn_error_t *
 purge_shared_txn_body(svn_fs_t *fs, const void *baton, apr_pool_t *pool)
 {
-  const svn_fs_x__id_part_t *txn_id = baton;
+  svn_fs_x__txn_id_t txn_id = *(const svn_fs_x__txn_id_t *)baton;
 
   free_shared_txn(fs, txn_id);
   svn_fs_x__reset_txn_caches(fs);
@@ -523,10 +522,10 @@ purge_shared_txn_body(svn_fs_t *fs, cons
    Perform all allocations in POOL. */
 static svn_error_t *
 purge_shared_txn(svn_fs_t *fs,
-                 const svn_fs_x__id_part_t *txn_id,
+                 svn_fs_x__txn_id_t txn_id,
                  apr_pool_t *pool)
 {
-  return with_txnlist_lock(fs, purge_shared_txn_body, txn_id, pool);
+  return with_txnlist_lock(fs, purge_shared_txn_body, &txn_id, pool);
 }
 
 
@@ -579,8 +578,10 @@ store_sha1_rep_mapping(svn_fs_t *fs,
       && noderev->data_rep->has_sha1)
     {
       apr_file_t *rep_file;
+      apr_int64_t txn_id
+        = svn_fs_x__get_txn_id(noderev->data_rep->id.change_set);
       const char *file_name
-        = svn_fs_x__path_txn_sha1(fs,  &noderev->data_rep->txn_id,
+        = svn_fs_x__path_txn_sha1(fs, txn_id,
                                   noderev->data_rep->sha1_digest, pool);
       svn_stringbuf_t *rep_string
         = svn_fs_x__unparse_representation(noderev->data_rep,
@@ -893,7 +894,7 @@ process_changes(apr_hash_t *changed_path
 svn_error_t *
 svn_fs_x__txn_changes_fetch(apr_hash_t **changed_paths_p,
                             svn_fs_t *fs,
-                            const svn_fs_x__id_part_t *txn_id,
+                            svn_fs_x__txn_id_t txn_id,
                             apr_pool_t *pool)
 {
   apr_file_t *file;
@@ -949,15 +950,17 @@ svn_fs_x__paths_changed(apr_hash_t **cha
    Allocations are from POOL.  */
 static svn_error_t *
 create_new_txn_noderev_from_rev(svn_fs_t *fs,
-                                const svn_fs_x__id_part_t *txn_id,
+                                svn_fs_x__txn_id_t txn_id,
                                 svn_fs_id_t *src,
                                 apr_pool_t *pool)
 {
   node_revision_t *noderev;
-  const svn_fs_x__id_part_t *node_id, *copy_id;
 
   SVN_ERR(svn_fs_x__get_node_revision(&noderev, fs, src, pool));
 
+  /* This must be a root node. */
+  SVN_ERR_ASSERT(svn_fs_x__id_node_id(noderev->id)->number == 0);
+
   if (svn_fs_x__id_is_txn(noderev->id))
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Copying from transactions not allowed"));
@@ -969,9 +972,7 @@ create_new_txn_noderev_from_rev(svn_fs_t
 
   /* For the transaction root, the copyroot never changes. */
 
-  node_id = svn_fs_x__id_node_id(noderev->id);
-  copy_id = svn_fs_x__id_copy_id(noderev->id);
-  noderev->id = svn_fs_x__id_txn_create(node_id, copy_id, txn_id, pool);
+  noderev->id = svn_fs_x__id_txn_create_root(txn_id, pool);
 
   return svn_fs_x__put_node_revision(fs, noderev->id, noderev, TRUE, pool);
 }
@@ -1018,9 +1019,8 @@ get_and_increment_txn_key_body(void *bat
    value in the transaction ID to prevent reuse of transaction IDs. */
 static svn_error_t *
 create_txn_dir(const char **id_p,
-               svn_fs_x__id_part_t *txn_id,
+               svn_fs_x__txn_id_t *txn_id,
                svn_fs_t *fs,
-               svn_revnum_t rev,
                apr_pool_t *pool)
 {
   struct get_and_increment_txn_key_baton cb;
@@ -1036,10 +1036,9 @@ create_txn_dir(const char **id_p,
                                 get_and_increment_txn_key_body,
                                 &cb,
                                 pool));
-  txn_id->revision = rev;
-  txn_id->number = cb.txn_number;
+  *txn_id = cb.txn_number;
 
-  *id_p = svn_fs_x__id_txn_unparse(txn_id, pool);
+  *id_p = svn_fs_x__txn_name(*txn_id, pool);
   txn_dir = svn_dirent_join_many(pool,
                                  fs->path,
                                  PATH_TXNS_DIR,
@@ -1064,7 +1063,7 @@ svn_fs_x__create_txn(svn_fs_txn_t **txn_
   ftd = apr_pcalloc(pool, sizeof(*ftd));
 
   /* Get the txn_id. */
-  SVN_ERR(create_txn_dir(&txn->id, &ftd->txn_id, fs, rev, pool));
+  SVN_ERR(create_txn_dir(&txn->id, &ftd->txn_id, fs, pool));
 
   txn->fs = fs;
   txn->base_rev = rev;
@@ -1075,26 +1074,26 @@ svn_fs_x__create_txn(svn_fs_txn_t **txn_
 
   /* Create a new root node for this transaction. */
   SVN_ERR(svn_fs_x__rev_get_root(&root_id, fs, rev, pool));
-  SVN_ERR(create_new_txn_noderev_from_rev(fs, &ftd->txn_id, root_id, pool));
+  SVN_ERR(create_new_txn_noderev_from_rev(fs, ftd->txn_id, root_id, pool));
 
   /* Create an empty rev file. */
   SVN_ERR(svn_io_file_create_empty(
-              svn_fs_x__path_txn_proto_rev(fs, &ftd->txn_id, pool),
+              svn_fs_x__path_txn_proto_rev(fs, ftd->txn_id, pool),
               pool));
 
   /* Create an empty rev-lock file. */
   SVN_ERR(svn_io_file_create_empty(
-              svn_fs_x__path_txn_proto_rev_lock(fs, &ftd->txn_id, pool),
+              svn_fs_x__path_txn_proto_rev_lock(fs, ftd->txn_id, pool),
               pool));
 
   /* Create an empty changes file. */
   SVN_ERR(svn_io_file_create_empty(
-              svn_fs_x__path_txn_changes(fs, &ftd->txn_id, pool),
+              svn_fs_x__path_txn_changes(fs, ftd->txn_id, pool),
               pool));
 
   /* Create the next-ids file. */
   return svn_io_file_create(
-              svn_fs_x__path_txn_next_ids(fs, &ftd->txn_id, pool),
+              svn_fs_x__path_txn_next_ids(fs, ftd->txn_id, pool),
               "0 0\n", pool);
 }
 
@@ -1103,14 +1102,14 @@ svn_fs_x__create_txn(svn_fs_txn_t **txn_
 static svn_error_t *
 get_txn_proplist(apr_hash_t *proplist,
                  svn_fs_t *fs,
-                 const svn_fs_x__id_part_t *txn_id,
+                 svn_fs_x__txn_id_t txn_id,
                  apr_pool_t *pool)
 {
   svn_stream_t *stream;
 
   /* Check for issue #3696. (When we find and fix the cause, we can change
    * this to an assertion.) */
-  if (!txn_id || !svn_fs_x__id_txn_used(txn_id))
+  if (txn_id == SVN_FS_X__INVALID_TXN_ID)
     return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
                             _("Internal error: a null transaction id was "
                               "passed to get_txn_proplist()"));
@@ -1156,7 +1155,7 @@ change_txn_props(svn_fs_txn_t *txn,
   int i;
   svn_error_t *err;
 
-  err = get_txn_proplist(txn_prop, txn->fs, &ftd->txn_id, pool);
+  err = get_txn_proplist(txn_prop, txn->fs, ftd->txn_id, pool);
   /* Here - and here only - we need to deal with the possibility that the
      transaction property file doesn't yet exist.  The rest of the
      implementation assumes that the file exists, but we're called to set the
@@ -1185,15 +1184,15 @@ change_txn_props(svn_fs_txn_t *txn,
   SVN_ERR(svn_hash_write2(txn_prop, stream, SVN_HASH_TERMINATOR, pool));
   SVN_ERR(svn_stream_close(stream));
   SVN_ERR(svn_io_write_unique(&txn_prop_filename,
-                      svn_fs_x__path_txn_dir(txn->fs, &ftd->txn_id, pool),
+                      svn_fs_x__path_txn_dir(txn->fs, ftd->txn_id, pool),
                       buf->data,
                       buf->len,
                       svn_io_file_del_none,
                       pool));
   return svn_io_file_rename(txn_prop_filename,
                 (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)),
+                 ? 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);
 }
 
@@ -1210,7 +1209,7 @@ svn_fs_x__change_txn_props(svn_fs_txn_t 
 svn_error_t *
 svn_fs_x__get_txn(transaction_t **txn_p,
                   svn_fs_t *fs,
-                  const svn_fs_x__id_part_t *txn_id,
+                  svn_fs_x__txn_id_t txn_id,
                   apr_pool_t *pool)
 {
   transaction_t *txn;
@@ -1234,6 +1233,92 @@ svn_fs_x__get_txn(transaction_t **txn_p,
   return SVN_NO_ERROR;
 }
 
+/* If it is supported by the format of file system FS, store the (ITEM_INDEX,
+ * OFFSET) pair in the log-to-phys proto index file of transaction TXN_ID.
+ * Use POOL for allocations.
+ */
+static svn_error_t *
+store_l2p_index_entry(svn_fs_t *fs,
+                      svn_fs_x__txn_id_t txn_id,
+                      apr_off_t offset,
+                      apr_uint64_t item_index,
+                      apr_pool_t *pool)
+{
+  const char *path = svn_fs_x__path_l2p_proto_index(fs, txn_id, pool);
+  apr_file_t *file;
+  SVN_ERR(svn_fs_x__l2p_proto_index_open(&file, path, pool));
+  SVN_ERR(svn_fs_x__l2p_proto_index_add_entry(file, offset, 0,
+                                              item_index, pool));
+  SVN_ERR(svn_io_file_close(file, pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* If it is supported by the format of file system FS, store ENTRY in the
+ * phys-to-log proto index file of transaction TXN_ID.
+ * Use POOL for allocations.
+ */
+static svn_error_t *
+store_p2l_index_entry(svn_fs_t *fs,
+                      svn_fs_x__txn_id_t txn_id,
+                      svn_fs_x__p2l_entry_t *entry,
+                      apr_pool_t *pool)
+{
+  const char *path = svn_fs_x__path_p2l_proto_index(fs, txn_id, pool);
+  apr_file_t *file;
+  SVN_ERR(svn_fs_x__p2l_proto_index_open(&file, path, pool));
+  SVN_ERR(svn_fs_x__p2l_proto_index_add_entry(file, entry, pool));
+  SVN_ERR(svn_io_file_close(file, pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* Allocate an item index for the given MY_OFFSET in the transaction TXN_ID
+ * of file system FS and return it in *ITEM_INDEX.  For old formats, it
+ * will simply return the offset as item index; in new formats, it will
+ * increment the txn's item index counter file and store the mapping in
+ * the proto index file.
+ * Use POOL for allocations.
+ */
+static svn_error_t *
+allocate_item_index(apr_uint64_t *item_index,
+                    svn_fs_t *fs,
+                    svn_fs_x__txn_id_t txn_id,
+                    apr_off_t my_offset,
+                    apr_pool_t *pool)
+{
+  apr_file_t *file;
+  char buffer[SVN_INT64_BUFFER_SIZE] = { 0 };
+  svn_boolean_t eof = FALSE;
+  apr_size_t to_write;
+  apr_size_t read;
+  apr_off_t offset = 0;
+
+  /* read number, increment it and write it back to disk */
+  SVN_ERR(svn_io_file_open(&file,
+                            svn_fs_x__path_txn_item_index(fs, txn_id, pool),
+                            APR_READ | APR_WRITE
+                            | APR_CREATE | APR_BUFFERED,
+                            APR_OS_DEFAULT, pool));
+  SVN_ERR(svn_io_file_read_full2(file, buffer, sizeof(buffer)-1,
+                                  &read, &eof, pool));
+  if (read)
+    SVN_ERR(svn_cstring_atoui64(item_index, buffer));
+  else
+    *item_index = SVN_FS_X__ITEM_INDEX_FIRST_USER;
+
+  to_write = svn__ui64toa(buffer, *item_index + 1);
+  SVN_ERR(svn_io_file_seek(file, SEEK_SET, &offset, pool));
+  SVN_ERR(svn_io_file_write_full(file, buffer, to_write, NULL, pool));
+  SVN_ERR(svn_io_file_close(file, pool));
+
+  /* write log-to-phys index */
+  SVN_ERR(store_l2p_index_entry(fs, txn_id, my_offset, *item_index,
+                                pool));
+
+  return SVN_NO_ERROR;
+}
+
 /* Write out the currently available next node_id NODE_ID and copy_id
    COPY_ID for transaction TXN_ID in filesystem FS.  The next node-id is
    used both for creating new unique nodes for the given transaction, as
@@ -1241,7 +1326,7 @@ svn_fs_x__get_txn(transaction_t **txn_p,
    POOL. */
 static svn_error_t *
 write_next_ids(svn_fs_t *fs,
-               const svn_fs_x__id_part_t *txn_id,
+               svn_fs_x__txn_id_t txn_id,
                apr_uint64_t node_id,
                apr_uint64_t copy_id,
                apr_pool_t *pool)
@@ -1273,7 +1358,7 @@ static svn_error_t *
 read_next_ids(apr_uint64_t *node_id,
               apr_uint64_t *copy_id,
               svn_fs_t *fs,
-              const svn_fs_x__id_part_t *txn_id,
+              svn_fs_x__txn_id_t txn_id,
               apr_pool_t *pool)
 {
   svn_stringbuf_t *buf;
@@ -1305,7 +1390,7 @@ read_next_ids(apr_uint64_t *node_id,
 static svn_error_t *
 get_new_txn_node_id(svn_fs_x__id_part_t *node_id_p,
                     svn_fs_t *fs,
-                    const svn_fs_x__id_part_t *txn_id,
+                    svn_fs_x__txn_id_t txn_id,
                     apr_pool_t *pool)
 {
   apr_uint64_t node_id, copy_id;
@@ -1313,7 +1398,7 @@ get_new_txn_node_id(svn_fs_x__id_part_t 
   /* First read in the current next-ids file. */
   SVN_ERR(read_next_ids(&node_id, &copy_id, fs, txn_id, pool));
 
-  node_id_p->revision = SVN_INVALID_REVNUM;
+  node_id_p->change_set = SVN_FS_X__INVALID_CHANGE_SET;
   node_id_p->number = node_id;
 
   SVN_ERR(write_next_ids(fs, txn_id, ++node_id, copy_id, pool));
@@ -1324,7 +1409,7 @@ get_new_txn_node_id(svn_fs_x__id_part_t 
 svn_error_t *
 svn_fs_x__reserve_copy_id(svn_fs_x__id_part_t *copy_id_p,
                           svn_fs_t *fs,
-                          const svn_fs_x__id_part_t *txn_id,
+                          svn_fs_x__txn_id_t txn_id,
                           apr_pool_t *pool)
 {
   apr_uint64_t node_id, copy_id;
@@ -1332,7 +1417,7 @@ svn_fs_x__reserve_copy_id(svn_fs_x__id_p
   /* First read in the current next-ids file. */
   SVN_ERR(read_next_ids(&node_id, &copy_id, fs, txn_id, pool));
 
-  copy_id_p->revision = SVN_INVALID_REVNUM;
+  copy_id_p->change_set = SVN_FS_X__INVALID_CHANGE_SET;
   copy_id_p->number = copy_id;
 
   SVN_ERR(write_next_ids(fs, txn_id, node_id, ++copy_id, pool));
@@ -1345,7 +1430,7 @@ svn_fs_x__create_node(const svn_fs_id_t 
                       svn_fs_t *fs,
                       node_revision_t *noderev,
                       const svn_fs_x__id_part_t *copy_id,
-                      const svn_fs_x__id_part_t *txn_id,
+                      svn_fs_x__txn_id_t txn_id,
                       apr_pool_t *pool)
 {
   svn_fs_x__id_part_t node_id;
@@ -1370,13 +1455,13 @@ svn_fs_x__purge_txn(svn_fs_t *fs,
                     const char *txn_id_str,
                     apr_pool_t *pool)
 {
-  svn_fs_x__id_part_t txn_id;
-  SVN_ERR(svn_fs_x__id_txn_parse(&txn_id, txn_id_str));
+  svn_fs_x__txn_id_t txn_id;
+  SVN_ERR(svn_fs_x__txn_by_name(&txn_id, txn_id_str));
 
   /* Remove the shared transaction object associated with this transaction. */
-  SVN_ERR(purge_shared_txn(fs, &txn_id, pool));
+  SVN_ERR(purge_shared_txn(fs, txn_id, pool));
   /* Remove the directory associated with this transaction. */
-  SVN_ERR(svn_io_remove_dir2(svn_fs_x__path_txn_dir(fs, &txn_id, pool),
+  SVN_ERR(svn_io_remove_dir2(svn_fs_x__path_txn_dir(fs, txn_id, pool),
                              FALSE, NULL, NULL, pool));
 
   /* Delete protorev and its lock, which aren't in the txn
@@ -1384,10 +1469,10 @@ svn_fs_x__purge_txn(svn_fs_t *fs,
       is post-commit and the proto-rev has been moved into
       place). */
   SVN_ERR(svn_io_remove_file2(
-                  svn_fs_x__path_txn_proto_rev(fs, &txn_id, pool),
+                  svn_fs_x__path_txn_proto_rev(fs, txn_id, pool),
                   TRUE, pool));
   SVN_ERR(svn_io_remove_file2(
-                  svn_fs_x__path_txn_proto_rev_lock(fs, &txn_id, pool),
+                  svn_fs_x__path_txn_proto_rev_lock(fs, txn_id, pool),
                   TRUE, pool));
 
   return SVN_NO_ERROR;
@@ -1408,26 +1493,9 @@ svn_fs_x__abort_txn(svn_fs_txn_t *txn,
   return SVN_NO_ERROR;
 }
 
-/* Assign the UNIQUIFIER member of REP based on the current state of TXN_ID
- * in FS.  Allocate the uniquifier in POOL.
- */
-static svn_error_t *
-set_uniquifier(svn_fs_t *fs,
-               representation_t *rep,
-               apr_pool_t *pool)
-{
-  svn_fs_x__id_part_t temp;
-
-  SVN_ERR(get_new_txn_node_id(&temp, fs, &rep->txn_id, pool));
-  rep->uniquifier.txn_id = rep->txn_id;
-  rep->uniquifier.number = temp.number;
-
-  return SVN_NO_ERROR;
-}
-
 svn_error_t *
 svn_fs_x__set_entry(svn_fs_t *fs,
-                    const svn_fs_x__id_part_t *txn_id,
+                    svn_fs_x__txn_id_t txn_id,
                     node_revision_t *parent_noderev,
                     const char *name,
                     const svn_fs_id_t *id,
@@ -1442,7 +1510,7 @@ svn_fs_x__set_entry(svn_fs_t *fs,
   fs_x_data_t *ffd = fs->fsap_data;
   apr_pool_t *subpool = svn_pool_create(pool);
 
-  if (!rep || !svn_fs_x__id_txn_used(&rep->txn_id))
+  if (!rep || !svn_fs_x__is_txn(rep->id.change_set))
     {
       apr_hash_t *entries;
 
@@ -1461,9 +1529,8 @@ svn_fs_x__set_entry(svn_fs_t *fs,
 
       /* Mark the node-rev's data rep as mutable. */
       rep = apr_pcalloc(pool, sizeof(*rep));
-      rep->revision = SVN_INVALID_REVNUM;
-      rep->txn_id = *txn_id;
-      SVN_ERR(set_uniquifier(fs, rep, pool));
+      rep->id.change_set = svn_fs_x__change_set_by_txn(txn_id);
+      rep->id.number = SVN_FS_X__ITEM_INDEX_UNUSED;
       parent_noderev->data_rep = rep;
       SVN_ERR(svn_fs_x__put_node_revision(fs, parent_noderev->id,
                                           parent_noderev, FALSE, pool));
@@ -1525,7 +1592,7 @@ svn_fs_x__set_entry(svn_fs_t *fs,
 
 svn_error_t *
 svn_fs_x__add_change(svn_fs_t *fs,
-                     const svn_fs_x__id_part_t *txn_id,
+                     svn_fs_x__txn_id_t txn_id,
                      const char *path,
                      const svn_fs_id_t *id,
                      svn_fs_path_change_kind_t change_kind,
@@ -1559,92 +1626,6 @@ svn_fs_x__add_change(svn_fs_t *fs,
   return svn_io_file_close(file, pool);
 }
 
-/* If it is supported by the format of file system FS, store the (ITEM_INDEX,
- * OFFSET) pair in the log-to-phys proto index file of transaction TXN_ID.
- * Use POOL for allocations.
- */
-static svn_error_t *
-store_l2p_index_entry(svn_fs_t *fs,
-                      const svn_fs_x__id_part_t *txn_id,
-                      apr_off_t offset,
-                      apr_uint64_t item_index,
-                      apr_pool_t *pool)
-{
-  const char *path = svn_fs_x__path_l2p_proto_index(fs, txn_id, pool);
-  apr_file_t *file;
-  SVN_ERR(svn_fs_x__l2p_proto_index_open(&file, path, pool));
-  SVN_ERR(svn_fs_x__l2p_proto_index_add_entry(file, offset, 0,
-                                              item_index, pool));
-  SVN_ERR(svn_io_file_close(file, pool));
-
-  return SVN_NO_ERROR;
-}
-
-/* If it is supported by the format of file system FS, store ENTRY in the
- * phys-to-log proto index file of transaction TXN_ID.
- * Use POOL for allocations.
- */
-static svn_error_t *
-store_p2l_index_entry(svn_fs_t *fs,
-                      const svn_fs_x__id_part_t *txn_id,
-                      svn_fs_x__p2l_entry_t *entry,
-                      apr_pool_t *pool)
-{
-  const char *path = svn_fs_x__path_p2l_proto_index(fs, txn_id, pool);
-  apr_file_t *file;
-  SVN_ERR(svn_fs_x__p2l_proto_index_open(&file, path, pool));
-  SVN_ERR(svn_fs_x__p2l_proto_index_add_entry(file, entry, pool));
-  SVN_ERR(svn_io_file_close(file, pool));
-
-  return SVN_NO_ERROR;
-}
-
-/* Allocate an item index for the given MY_OFFSET in the transaction TXN_ID
- * of file system FS and return it in *ITEM_INDEX.  For old formats, it
- * will simply return the offset as item index; in new formats, it will
- * increment the txn's item index counter file and store the mapping in
- * the proto index file.
- * Use POOL for allocations.
- */
-static svn_error_t *
-allocate_item_index(apr_uint64_t *item_index,
-                    svn_fs_t *fs,
-                    const svn_fs_x__id_part_t *txn_id,
-                    apr_off_t my_offset,
-                    apr_pool_t *pool)
-{
-  apr_file_t *file;
-  char buffer[SVN_INT64_BUFFER_SIZE] = { 0 };
-  svn_boolean_t eof = FALSE;
-  apr_size_t to_write;
-  apr_size_t read;
-  apr_off_t offset = 0;
-
-  /* read number, increment it and write it back to disk */
-  SVN_ERR(svn_io_file_open(&file,
-                            svn_fs_x__path_txn_item_index(fs, txn_id, pool),
-                            APR_READ | APR_WRITE
-                            | APR_CREATE | APR_BUFFERED,
-                            APR_OS_DEFAULT, pool));
-  SVN_ERR(svn_io_file_read_full2(file, buffer, sizeof(buffer)-1,
-                                  &read, &eof, pool));
-  if (read)
-    SVN_ERR(svn_cstring_atoui64(item_index, buffer));
-  else
-    *item_index = SVN_FS_X__ITEM_INDEX_FIRST_USER;
-
-  to_write = svn__ui64toa(buffer, *item_index + 1);
-  SVN_ERR(svn_io_file_seek(file, SEEK_SET, &offset, pool));
-  SVN_ERR(svn_io_file_write_full(file, buffer, to_write, NULL, pool));
-  SVN_ERR(svn_io_file_close(file, pool));
-
-  /* write log-to-phys index */
-  SVN_ERR(store_l2p_index_entry(fs, txn_id, my_offset, *item_index,
-                                pool));
-
-  return SVN_NO_ERROR;
-}
-
 /* This baton is used by the representation writing streams.  It keeps
    track of the checksum information as well as the total size of the
    representation so far. */
@@ -1785,12 +1766,14 @@ choose_delta_base(representation_t **rep
       base_revision = svn_fs_x__id_rev(base->id);
       if (props)
         {
-          if (base->prop_rep && base_revision > base->prop_rep->revision)
+          if (base->prop_rep &&
+              base_revision > svn_fs_x__get_revnum(base->prop_rep->id.change_set))
             maybe_shared_rep = TRUE;
         }
       else
         {
-          if (base->data_rep && base_revision > base->data_rep->revision)
+          if (base->data_rep &&
+              base_revision > svn_fs_x__get_revnum(base->data_rep->id.change_set))
             maybe_shared_rep = TRUE;
         }
     }
@@ -1894,8 +1877,8 @@ rep_write_get_baton(struct rep_write_bat
   /* Write out the rep header. */
   if (base_rep)
     {
-      header.base_revision = base_rep->revision;
-      header.base_item_index = base_rep->item_index;
+      header.base_revision = svn_fs_x__get_revnum(base_rep->id.change_set);
+      header.base_item_index = base_rep->id.number;
       header.base_length = base_rep->size;
       header.type = svn_fs_x__rep_delta;
     }
@@ -1999,11 +1982,13 @@ get_shared_rep(representation_t **old_re
   /* look for intra-revision matches (usually data reps but not limited
      to them in case props happen to look like some data rep)
    */
-  if (*old_rep == NULL && svn_fs_x__id_txn_used(&rep->txn_id))
+  if (*old_rep == NULL && svn_fs_x__is_txn(rep->id.change_set))
     {
       svn_node_kind_t kind;
       const char *file_name
-        = svn_fs_x__path_txn_sha1(fs, &rep->txn_id, rep->sha1_digest, pool);
+        = svn_fs_x__path_txn_sha1(fs,
+                                  svn_fs_x__get_txn_id(rep->id.change_set),
+                                  rep->sha1_digest, pool);
 
       /* in our txn, is there a rep file named with the wanted SHA1?
          If so, read it and use that rep.
@@ -2022,7 +2007,6 @@ get_shared_rep(representation_t **old_re
     {
       /* Use the old rep for this content. */
       memcpy((*old_rep)->md5_digest, rep->md5_digest, sizeof(rep->md5_digest));
-      (*old_rep)->uniquifier = rep->uniquifier;
     }
 
   return SVN_NO_ERROR;
@@ -2059,6 +2043,7 @@ rep_write_contents_close(void *baton)
   representation_t *rep;
   representation_t *old_rep;
   apr_off_t offset;
+  apr_int64_t txn_id;
 
   rep = apr_pcalloc(b->parent_pool, sizeof(*rep));
 
@@ -2073,9 +2058,8 @@ rep_write_contents_close(void *baton)
 
   /* Fill in the rest of the representation field. */
   rep->expanded_size = b->rep_size;
-  rep->txn_id = *svn_fs_x__id_txn_id(b->noderev->id);
-  SVN_ERR(set_uniquifier(b->fs, rep, b->pool));
-  rep->revision = SVN_INVALID_REVNUM;
+  txn_id = svn_fs_x__id_txn_id(b->noderev->id);
+  rep->id.change_set = svn_fs_x__change_set_by_txn(txn_id);
 
   /* Finalize the checksum. */
   SVN_ERR(digests_final(rep, b->md5_checksum_ctx, b->sha1_checksum_ctx,
@@ -2097,7 +2081,7 @@ rep_write_contents_close(void *baton)
     {
       /* Write out our cosmetic end marker. */
       SVN_ERR(svn_stream_puts(b->rep_stream, "ENDREP\n"));
-      SVN_ERR(allocate_item_index(&rep->item_index, b->fs, &rep->txn_id,
+      SVN_ERR(allocate_item_index(&rep->id.number, b->fs, txn_id,
                                   b->rep_offset, b->pool));
 
       b->noderev->data_rep = rep;
@@ -2112,23 +2096,23 @@ rep_write_contents_close(void *baton)
   if (!old_rep)
     {
       svn_fs_x__p2l_entry_t entry;
-      svn_fs_x__id_part_t rev_item;
-      rev_item.revision = SVN_INVALID_REVNUM;
-      rev_item.number = rep->item_index;
+      svn_fs_x__id_part_t noderev_id;
+      noderev_id.change_set = SVN_FS_X__INVALID_CHANGE_SET;
+      noderev_id.number = rep->id.number;
 
       entry.offset = b->rep_offset;
       SVN_ERR(svn_fs_x__get_file_offset(&offset, b->file, b->pool));
       entry.size = offset - b->rep_offset;
       entry.type = SVN_FS_X__ITEM_TYPE_FILE_REP;
       entry.item_count = 1;
-      entry.items = &rev_item;
+      entry.items = &noderev_id;
 
       SVN_ERR(store_sha1_rep_mapping(b->fs, b->noderev, b->pool));
-      SVN_ERR(store_p2l_index_entry(b->fs, &rep->txn_id, &entry, b->pool));
+      SVN_ERR(store_p2l_index_entry(b->fs, txn_id, &entry, b->pool));
     }
 
   SVN_ERR(svn_io_file_close(b->file, b->pool));
-  SVN_ERR(unlock_proto_rev(b->fs, &rep->txn_id, b->lockcookie, b->pool));
+  SVN_ERR(unlock_proto_rev(b->fs, txn_id, b->lockcookie, b->pool));
   svn_pool_destroy(b->pool);
 
   return SVN_NO_ERROR;
@@ -2180,7 +2164,7 @@ svn_fs_x__create_successor(const svn_fs_
                            const svn_fs_id_t *old_idp,
                            node_revision_t *new_noderev,
                            const svn_fs_x__id_part_t *copy_id,
-                           const svn_fs_x__id_part_t *txn_id,
+                           svn_fs_x__txn_id_t txn_id,
                            apr_pool_t *pool)
 {
   const svn_fs_id_t *id;
@@ -2228,10 +2212,11 @@ svn_fs_x__set_proplist(svn_fs_t *fs,
 
   /* Mark the node-rev's prop rep as mutable, if not already done. */
   if (!noderev->prop_rep
-      || !svn_fs_x__id_txn_used(&noderev->prop_rep->txn_id))
+      || svn_fs_x__is_revision(noderev->prop_rep->id.change_set))
     {
       noderev->prop_rep = apr_pcalloc(pool, sizeof(*noderev->prop_rep));
-      noderev->prop_rep->txn_id = *svn_fs_x__id_txn_id(noderev->id);
+      noderev->prop_rep->id.change_set
+        = svn_fs_x__change_set_by_txn(svn_fs_x__id_txn_id(noderev->id));
       SVN_ERR(svn_fs_x__put_node_revision(fs, noderev->id, noderev, FALSE,
                                           pool));
     }
@@ -2282,7 +2267,7 @@ write_hash_delta_rep(representation_t *r
                      apr_file_t *file,
                      apr_hash_t *hash,
                      svn_fs_t *fs,
-                     const svn_fs_x__id_part_t *txn_id,
+                     svn_fs_x__txn_id_t txn_id,
                      node_revision_t *noderev,
                      apr_hash_t *reps_hash,
                      int item_type,
@@ -2316,8 +2301,8 @@ write_hash_delta_rep(representation_t *r
   /* Write out the rep header. */
   if (base_rep)
     {
-      header.base_revision = base_rep->revision;
-      header.base_item_index = base_rep->item_index;
+      header.base_revision = svn_fs_x__get_revnum(base_rep->id.change_set);
+      header.base_item_index = base_rep->id.number;
       header.base_length = base_rep->size;
       header.type = svn_fs_x__rep_delta;
     }
@@ -2369,24 +2354,24 @@ write_hash_delta_rep(representation_t *r
   else
     {
       svn_fs_x__p2l_entry_t entry;
-      svn_fs_x__id_part_t rev_item;
+      svn_fs_x__id_part_t noderev_id;
 
       /* Write out our cosmetic end marker. */
       SVN_ERR(svn_fs_x__get_file_offset(&rep_end, file, pool));
       SVN_ERR(svn_stream_puts(file_stream, "ENDREP\n"));
 
-      SVN_ERR(allocate_item_index(&rep->item_index, fs, txn_id, offset,
+      SVN_ERR(allocate_item_index(&rep->id.number, fs, txn_id, offset,
                                   pool));
 
-      rev_item.revision = SVN_INVALID_REVNUM;
-      rev_item.number = rep->item_index;
+      noderev_id.change_set = SVN_FS_X__INVALID_CHANGE_SET;
+      noderev_id.number = rep->id.number;
 
       entry.offset = offset;
       SVN_ERR(svn_fs_x__get_file_offset(&offset, file, pool));
       entry.size = offset - entry.offset;
       entry.type = item_type;
       entry.item_count = 1;
-      entry.items = &rev_item;
+      entry.items = &noderev_id;
 
       SVN_ERR(store_p2l_index_entry(fs, txn_id, &entry, pool));
 
@@ -2460,17 +2445,14 @@ validate_root_noderev(svn_fs_t *fs,
 }
 
 /* Given the potentially txn-local id PART, update that to a permanent ID
- * based on the REVISION currently being written and the START_ID for that
- * revision.  Use the repo FORMAT to decide which implementation to use.
+ * based on the REVISION.
  */
 static void
 get_final_id(svn_fs_x__id_part_t *part,
-             svn_revnum_t revision,
-             apr_uint64_t start_id,
-             int format)
+             svn_revnum_t revision)
 {
-  if (part->revision == SVN_INVALID_REVNUM)
-    part->revision = revision;
+  if (part->change_set == SVN_FS_X__INVALID_CHANGE_SET)
+    part->change_set = svn_fs_x__change_set_by_rev(revision);
 }
 
 /* Copy a node-revision specified by id ID in fileystem FS from a
@@ -2505,8 +2487,6 @@ write_final_rev(const svn_fs_id_t **new_
                 svn_revnum_t rev,
                 svn_fs_t *fs,
                 const svn_fs_id_t *id,
-                apr_uint64_t start_node_id,
-                apr_uint64_t start_copy_id,
                 apr_off_t initial_offset,
                 apr_array_header_t *reps_to_cache,
                 apr_hash_t *reps_hash,
@@ -2517,10 +2497,11 @@ write_final_rev(const svn_fs_id_t **new_
   node_revision_t *noderev;
   apr_off_t my_offset;
   const svn_fs_id_t *new_id;
-  svn_fs_x__id_part_t node_id, copy_id, rev_item;
+  svn_fs_x__id_part_t node_id, copy_id, noderev_id;
   fs_x_data_t *ffd = fs->fsap_data;
-  const svn_fs_x__id_part_t *txn_id = svn_fs_x__id_txn_id(id);
+  svn_fs_x__txn_id_t txn_id = svn_fs_x__id_txn_id(id);
   svn_fs_x__p2l_entry_t entry;
+  svn_fs_x__change_set_t change_set = svn_fs_x__change_set_by_rev(rev);
 
   *new_id_p = NULL;
 
@@ -2554,7 +2535,6 @@ write_final_rev(const svn_fs_id_t **new_
 
           svn_pool_clear(subpool);
           SVN_ERR(write_final_rev(&new_id, file, rev, fs, dirent->id,
-                                  start_node_id, start_copy_id,
                                   initial_offset, reps_to_cache, reps_hash,
                                   reps_pool, FALSE, subpool));
           if (new_id && (svn_fs_x__id_rev(new_id) == rev))
@@ -2563,18 +2543,16 @@ write_final_rev(const svn_fs_id_t **new_
       svn_pool_destroy(subpool);
 
       if (noderev->data_rep
-          && svn_fs_x__id_txn_used(&noderev->data_rep->txn_id))
+          && ! svn_fs_x__is_revision(noderev->data_rep->id.change_set))
         {
           /* Write out the contents of this directory as a text rep. */
           SVN_ERR(unparse_dir_entries(&str_entries, entries, pool));
-          noderev->data_rep->revision = rev;
+          noderev->data_rep->id.change_set = change_set;
 
           SVN_ERR(write_hash_delta_rep(noderev->data_rep, file,
                                        str_entries, fs, txn_id, noderev,
                                        NULL, SVN_FS_X__ITEM_TYPE_DIR_REP,
                                        pool));
-
-          svn_fs_x__id_txn_reset(&noderev->data_rep->txn_id);
         }
     }
   else
@@ -2584,16 +2562,15 @@ write_final_rev(const svn_fs_id_t **new_
          num. */
 
       if (noderev->data_rep
-          && svn_fs_x__id_txn_used(&noderev->data_rep->txn_id))
+          && svn_fs_x__is_txn(noderev->data_rep->id.change_set))
         {
-          svn_fs_x__id_txn_reset(&noderev->data_rep->txn_id);
-          noderev->data_rep->revision = rev;
+          noderev->data_rep->id.change_set = change_set;
         }
     }
 
   /* Fix up the property reps. */
   if (noderev->prop_rep
-      && svn_fs_x__id_txn_used(&noderev->prop_rep->txn_id))
+      && svn_fs_x__is_txn(noderev->prop_rep->id.change_set))
     {
       apr_hash_t *proplist;
       int item_type = noderev->kind == svn_node_dir
@@ -2601,8 +2578,7 @@ write_final_rev(const svn_fs_id_t **new_
                     : SVN_FS_X__ITEM_TYPE_FILE_PROPS;
       SVN_ERR(svn_fs_x__get_proplist(&proplist, fs, noderev, pool));
 
-      svn_fs_x__id_txn_reset(&noderev->prop_rep->txn_id);
-      noderev->prop_rep->revision = rev;
+      noderev->prop_rep->id.change_set = change_set;
 
       SVN_ERR(write_hash_delta_rep(noderev->prop_rep, file,
                                    proplist, fs, txn_id, noderev,
@@ -2611,9 +2587,9 @@ write_final_rev(const svn_fs_id_t **new_
 
   /* Convert our temporary ID into a permanent revision one. */
   node_id = *svn_fs_x__id_node_id(noderev->id);
-  get_final_id(&node_id, rev, start_node_id, ffd->format);
+  get_final_id(&node_id, rev);
   copy_id = *svn_fs_x__id_copy_id(noderev->id);
-  get_final_id(&copy_id, rev, start_copy_id, ffd->format);
+  get_final_id(&copy_id, rev);
 
   if (noderev->copyroot_rev == SVN_INVALID_REVNUM)
     noderev->copyroot_rev = rev;
@@ -2622,16 +2598,16 @@ write_final_rev(const svn_fs_id_t **new_
   if (at_root)
     {
       /* reference the root noderev from the log-to-phys index */
-      rev_item.number = SVN_FS_X__ITEM_INDEX_ROOT_NODE;
-      SVN_ERR(store_l2p_index_entry(fs, txn_id, my_offset, rev_item.number,
+      noderev_id.number = SVN_FS_X__ITEM_INDEX_ROOT_NODE;
+      SVN_ERR(store_l2p_index_entry(fs, txn_id, my_offset, noderev_id.number,
                                     pool));
     }
   else
-    SVN_ERR(allocate_item_index(&rev_item.number, fs, txn_id, my_offset,
+    SVN_ERR(allocate_item_index(&noderev_id.number, fs, txn_id, my_offset,
                                 pool));
 
-  rev_item.revision = rev;
-  new_id = svn_fs_x__id_rev_create(&node_id, &copy_id, &rev_item, pool);
+  noderev_id.change_set = change_set;
+  new_id = svn_fs_x__id_create(&node_id, &copy_id, &noderev_id, pool);
 
   noderev->id = new_id;
 
@@ -2639,14 +2615,15 @@ write_final_rev(const svn_fs_id_t **new_
     {
       /* Save the data representation's hash in the rep cache. */
       if (   noderev->data_rep && noderev->kind == svn_node_file
-          && noderev->data_rep->revision == rev)
+          && svn_fs_x__get_revnum(noderev->data_rep->id.change_set) == rev)
         {
           SVN_ERR_ASSERT(reps_to_cache && reps_pool);
           APR_ARRAY_PUSH(reps_to_cache, representation_t *)
             = svn_fs_x__rep_copy(noderev->data_rep, reps_pool);
         }
 
-      if (noderev->prop_rep && noderev->prop_rep->revision == rev)
+      if (   noderev->prop_rep
+          && svn_fs_x__get_revnum(noderev->prop_rep->id.change_set) == rev)
         {
           /* Add new property reps to hash and on-disk cache. */
           representation_t *copy
@@ -2681,14 +2658,14 @@ write_final_rev(const svn_fs_id_t **new_
                                   noderev, ffd->format, pool));
 
   /* reference the root noderev from the log-to-phys index */
-  rev_item.revision = SVN_INVALID_REVNUM;
+  noderev_id.change_set = SVN_FS_X__INVALID_CHANGE_SET;
 
   entry.offset = my_offset;
   SVN_ERR(svn_fs_x__get_file_offset(&my_offset, file, pool));
   entry.size = my_offset - entry.offset;
   entry.type = SVN_FS_X__ITEM_TYPE_NODEREV;
   entry.item_count = 1;
-  entry.items = &rev_item;
+  entry.items = &noderev_id;
 
   SVN_ERR(store_p2l_index_entry(fs, txn_id, &entry, pool));
 
@@ -2706,7 +2683,7 @@ static svn_error_t *
 write_final_changed_path_info(apr_off_t *offset_p,
                               apr_file_t *file,
                               svn_fs_t *fs,
-                              const svn_fs_x__id_part_t *txn_id,
+                              svn_fs_x__txn_id_t txn_id,
                               apr_hash_t *changed_paths,
                               svn_revnum_t new_rev,
                               apr_pool_t *pool)
@@ -2799,7 +2776,7 @@ verify_as_revision_before_current_plus_p
    The FS write lock is assumed to be held by the caller. */
 static svn_error_t *
 verify_locks(svn_fs_t *fs,
-             const svn_fs_x__id_part_t *txn_id,
+             svn_fs_x__txn_id_t txn_id,
              apr_pool_t *pool)
 {
   apr_pool_t *subpool = svn_pool_create(pool);
@@ -2903,7 +2880,7 @@ check_for_duplicate_move_source(apr_hash
    txn.  Use POOL for temporary allocations. */
 static svn_error_t *
 verify_moves(svn_fs_t *fs,
-             const svn_fs_x__id_part_t *txn_id,
+             const svn_fs_txn_t *txn,
              svn_revnum_t old_rev,
              apr_hash_t *changed_paths,
              apr_pool_t *pool)
@@ -2988,7 +2965,7 @@ verify_moves(svn_fs_t *fs,
                           APR_ARRAY_IDX(moves, i, svn_sort__item_t).value,
                           pool));
 
-  for (revision = txn_id->revision + 1; revision <= old_rev; ++revision)
+  for (revision = txn->base_rev + 1; revision <= old_rev; ++revision)
     {
       apr_array_header_t *changes;
       change_t **changes_p;
@@ -3040,7 +3017,7 @@ verify_moves(svn_fs_t *fs,
 static svn_error_t *
 write_final_revprop(const char **path,
                     svn_fs_txn_t *txn,
-                    const svn_fs_x__id_part_t *txn_id,
+                    svn_fs_x__txn_id_t txn_id,
                     apr_pool_t *pool)
 {
   apr_hash_t *txnprops;
@@ -3125,13 +3102,11 @@ commit_body(void *baton, apr_pool_t *poo
   const char *old_rev_filename, *rev_filename, *proto_filename;
   const char *revprop_filename, *final_revprop;
   const svn_fs_id_t *root_id, *new_root_id;
-  apr_uint64_t start_node_id = 0;
-  apr_uint64_t start_copy_id = 0;
   svn_revnum_t old_rev, new_rev;
   apr_file_t *proto_file;
   void *proto_file_lockcookie;
   apr_off_t initial_offset, changed_path_offset;
-  const svn_fs_x__id_part_t *txn_id = svn_fs_x__txn_get_id(cb->txn);
+  svn_fs_x__txn_id_t txn_id = svn_fs_x__txn_get_id(cb->txn);
   apr_hash_t *changed_paths;
 
   /* Get the current youngest revision. */
@@ -3154,7 +3129,7 @@ commit_body(void *baton, apr_pool_t *poo
   SVN_ERR(svn_fs_x__txn_changes_fetch(&changed_paths, cb->fs, txn_id,
                                       pool));
 
-  SVN_ERR(verify_moves(cb->fs, txn_id, old_rev, changed_paths, pool));
+  SVN_ERR(verify_moves(cb->fs, cb->txn, old_rev, changed_paths, pool));
 
   /* We are going to be one better than this puny old revision. */
   new_rev = old_rev + 1;
@@ -3167,9 +3142,8 @@ commit_body(void *baton, apr_pool_t *poo
   /* Write out all the node-revisions and directory contents. */
   root_id = svn_fs_x__id_txn_create_root(txn_id, pool);
   SVN_ERR(write_final_rev(&new_root_id, proto_file, new_rev, cb->fs, root_id,
-                          start_node_id, start_copy_id, initial_offset,
-                          cb->reps_to_cache, cb->reps_hash, cb->reps_pool,
-                          TRUE, pool));
+                          initial_offset, cb->reps_to_cache, cb->reps_hash,
+                          cb->reps_pool, TRUE, pool));
 
   /* Write the changed-path information. */
   SVN_ERR(write_final_changed_path_info(&changed_path_offset, proto_file,
@@ -3393,12 +3367,12 @@ svn_fs_x__open_txn(svn_fs_txn_t **txn_p,
   fs_txn_data_t *ftd;
   svn_node_kind_t kind;
   transaction_t *local_txn;
-  svn_fs_x__id_part_t txn_id;
+  svn_fs_x__txn_id_t txn_id;
 
-  SVN_ERR(svn_fs_x__id_txn_parse(&txn_id, name));
+  SVN_ERR(svn_fs_x__txn_by_name(&txn_id, name));
 
   /* First check to see if the directory exists. */
-  SVN_ERR(svn_io_check_path(svn_fs_x__path_txn_dir(fs, &txn_id, pool),
+  SVN_ERR(svn_io_check_path(svn_fs_x__path_txn_dir(fs, txn_id, pool),
                             &kind, pool));
 
   /* Did we find it? */
@@ -3415,7 +3389,7 @@ svn_fs_x__open_txn(svn_fs_txn_t **txn_p,
   txn->id = apr_pstrdup(pool, name);
   txn->fs = fs;
 
-  SVN_ERR(svn_fs_x__get_txn(&local_txn, fs, &txn_id, pool));
+  SVN_ERR(svn_fs_x__get_txn(&local_txn, fs, txn_id, pool));
 
   txn->base_rev = svn_fs_x__id_rev(local_txn->base_id);
 
@@ -3450,13 +3424,13 @@ svn_fs_x__delete_node_revision(svn_fs_t 
 
   /* Delete any mutable property representation. */
   if (noderev->prop_rep
-      && svn_fs_x__id_txn_used(&noderev->prop_rep->txn_id))
+      && svn_fs_x__is_txn(noderev->prop_rep->id.change_set))
     SVN_ERR(svn_io_remove_file2(svn_fs_x__path_txn_node_props(fs, id, pool),
                                 FALSE, pool));
 
   /* Delete any mutable data representation. */
   if (noderev->data_rep
-      && svn_fs_x__id_txn_used(&noderev->data_rep->txn_id)
+      && svn_fs_x__is_txn(noderev->data_rep->id.change_set)
       && noderev->kind == svn_node_dir)
     {
       fs_x_data_t *ffd = fs->fsap_data;
@@ -3484,7 +3458,7 @@ svn_error_t *
 svn_fs_x__get_txn_ids(const svn_fs_id_t **root_id_p,
                       const svn_fs_id_t **base_root_id_p,
                       svn_fs_t *fs,
-                      const svn_fs_x__id_part_t *txn_id,
+                      svn_fs_x__txn_id_t txn_id,
                       apr_pool_t *pool)
 {
   transaction_t *txn;

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/transaction.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/transaction.h?rev=1568883&r1=1568882&r2=1568883&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/transaction.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/transaction.h Mon Feb 17 05:53:23 2014
@@ -27,7 +27,7 @@
 
 /* Return the transaction ID of TXN.
  */
-const svn_fs_x__id_part_t *
+svn_fs_x__txn_id_t
 svn_fs_x__txn_get_id(svn_fs_txn_t *txn);
 
 /* Obtain a write lock on the filesystem FS in a subpool of POOL, call
@@ -56,7 +56,7 @@ svn_fs_x__put_node_revision(svn_fs_t *fs
 svn_error_t *
 svn_fs_x__txn_changes_fetch(apr_hash_t **changed_paths_p,
                             svn_fs_t *fs,
-                            const svn_fs_x__id_part_t *txn_id,
+                            svn_fs_x__txn_id_t txn_id,
                             apr_pool_t *pool);
 
 /* Find the paths which were changed in revision REV of filesystem FS
@@ -97,7 +97,7 @@ svn_fs_x__change_txn_props(svn_fs_txn_t 
 svn_error_t *
 svn_fs_x__get_txn(transaction_t **txn_p,
                   svn_fs_t *fs,
-                  const svn_fs_x__id_part_t *txn_id,
+                  svn_fs_x__txn_id_t txn_id,
                   apr_pool_t *pool);
 
 /* Return the next available copy_id in *COPY_ID for the transaction
@@ -105,7 +105,7 @@ svn_fs_x__get_txn(transaction_t **txn_p,
 svn_error_t *
 svn_fs_x__reserve_copy_id(svn_fs_x__id_part_t *copy_id_p,
                           svn_fs_t *fs,
-                          const svn_fs_x__id_part_t *txn_id,
+                          svn_fs_x__txn_id_t txn_id,
                           apr_pool_t *pool);
 
 /* Create an entirely new mutable node in the filesystem FS, whose
@@ -118,7 +118,7 @@ svn_fs_x__create_node(const svn_fs_id_t 
                       svn_fs_t *fs,
                       node_revision_t *noderev,
                       const svn_fs_x__id_part_t *copy_id,
-                      const svn_fs_x__id_part_t *txn_id,
+                      svn_fs_x__txn_id_t txn_id,
                       apr_pool_t *pool);
 
 /* Remove all references to the transaction TXN_ID from filesystem FS.
@@ -139,7 +139,7 @@ svn_fs_x__abort_txn(svn_fs_txn_t *txn,
    KIND.  Allocations are done in POOL. */
 svn_error_t *
 svn_fs_x__set_entry(svn_fs_t *fs,
-                    const svn_fs_x__id_part_t *txn_id,
+                    svn_fs_x__txn_id_t txn_id,
                     node_revision_t *parent_noderev,
                     const char *name,
                     const svn_fs_id_t *id,
@@ -156,7 +156,7 @@ svn_fs_x__set_entry(svn_fs_t *fs,
    from POOL. */
 svn_error_t *
 svn_fs_x__add_change(svn_fs_t *fs,
-                     const svn_fs_x__id_part_t *txn_id,
+                     svn_fs_x__txn_id_t txn_id,
                      const char *path,
                      const svn_fs_id_t *id,
                      svn_fs_path_change_kind_t change_kind,
@@ -196,7 +196,7 @@ svn_fs_x__create_successor(const svn_fs_
                            const svn_fs_id_t *old_idp,
                            node_revision_t *new_noderev,
                            const svn_fs_x__id_part_t *copy_id,
-                           const svn_fs_x__id_part_t *txn_id,
+                           svn_fs_x__txn_id_t txn_id,
                            apr_pool_t *pool);
 
 /* Write a new property list PROPLIST for node-revision NODEREV in
@@ -266,7 +266,7 @@ svn_error_t *
 svn_fs_x__get_txn_ids(const svn_fs_id_t **root_id_p,
                       const svn_fs_id_t **base_root_id_p,
                       svn_fs_t *fs,
-                      const svn_fs_x__id_part_t *txn_name,
+                      svn_fs_x__txn_id_t txn_id,
                       apr_pool_t *pool);
 
 /* Find the value of the property named PROPNAME in transaction TXN.

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/tree.c?rev=1568883&r1=1568882&r2=1568883&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/tree.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/tree.c Mon Feb 17 05:53:23 2014
@@ -60,6 +60,7 @@
 #include "cached_data.h"
 #include "transaction.h"
 #include "pack.h"
+#include "util.h"
 
 #include "private/svn_mergeinfo_private.h"
 #include "private/svn_subr_private.h"
@@ -107,8 +108,8 @@ typedef dag_node_t fs_rev_root_data_t;
 typedef struct fs_txn_root_data_t
 {
   /* TXN_ID value from the main struct but as a struct instead of a string */
-  svn_fs_x__id_part_t txn_id;
-  
+  svn_fs_x__txn_id_t txn_id;
+
   /* Cache of txn DAG nodes (without their nested noderevs, because
    * it's mutable). Same keys/values as ffd->rev_node_cache. */
   svn_cache__t *txn_node_cache;
@@ -127,7 +128,7 @@ static svn_fs_root_t *make_revision_root
 
 static svn_error_t *make_txn_root(svn_fs_root_t **root_p,
                                   svn_fs_t *fs,
-                                  const svn_fs_x__id_part_t *txn,
+                                  svn_fs_x__txn_id_t txn_id,
                                   svn_revnum_t base_rev,
                                   apr_uint32_t flags,
                                   apr_pool_t *pool);
@@ -640,13 +641,13 @@ svn_fs_x__revision_root(svn_fs_root_t **
 /* Getting dag nodes for roots.  */
 
 /* Return the transaction ID to a given transaction ROOT. */
-static const svn_fs_x__id_part_t *
+static svn_fs_x__txn_id_t
 root_txn_id(svn_fs_root_t *root)
 {
   fs_txn_root_data_t *frd = root->fsap_data;
   assert(root->is_txn_root);
-  
-  return &frd->txn_id;
+
+  return frd->txn_id;
 }
 
 /* Set *NODE_P to a freshly opened dag node referring to the root
@@ -1108,7 +1109,7 @@ make_path_mutable(svn_fs_root_t *root,
                   apr_pool_t *pool)
 {
   dag_node_t *clone;
-  const svn_fs_x__id_part_t *txn_id = root_txn_id(root);
+  svn_fs_x__txn_id_t txn_id = root_txn_id(root);
 
   /* Is the node mutable already?  */
   if (svn_fs_x__dag_check_mutable(parent_path->node))
@@ -1260,7 +1261,7 @@ get_dag(dag_node_t **dag_node_p,
    be SVN_INVALID_REVNUM.  Do all this as part of POOL.  */
 static svn_error_t *
 add_change(svn_fs_t *fs,
-           const svn_fs_x__id_part_t *txn_id,
+           svn_fs_x__txn_id_t txn_id,
            const char *path,
            const svn_fs_id_t *noderev_id,
            svn_fs_path_change_kind_t change_kind,
@@ -1318,7 +1319,7 @@ x_node_relation(svn_fs_node_relation_t *
 {
   dag_node_t *node;
   const svn_fs_id_t *id;
-  svn_fs_x__id_part_t rev_item_a, rev_item_b, node_id_a, node_id_b;
+  svn_fs_x__id_part_t noderev_id_a, noderev_id_b, node_id_a, node_id_b;
 
   /* Root paths are a common special case. */
   svn_boolean_t a_is_root_dir
@@ -1356,15 +1357,15 @@ x_node_relation(svn_fs_node_relation_t *
    * Now, we can simply test for the ID values themselves. */
   SVN_ERR(get_dag(&node, root_a, path_a, FALSE, pool));
   id = svn_fs_x__dag_get_id(node);
-  rev_item_a = *svn_fs_x__id_rev_item(id);
+  noderev_id_a = *svn_fs_x__id_noderev_id(id);
   node_id_a = *svn_fs_x__id_node_id(id);
 
   SVN_ERR(get_dag(&node, root_b, path_b, FALSE, pool));
   id = svn_fs_x__dag_get_id(node);
-  rev_item_b = *svn_fs_x__id_rev_item(id);
+  noderev_id_b = *svn_fs_x__id_noderev_id(id);
   node_id_b = *svn_fs_x__id_node_id(id);
 
-  if (svn_fs_x__id_part_eq(&rev_item_a, &rev_item_b))
+  if (svn_fs_x__id_part_eq(&noderev_id_a, &noderev_id_b))
     *relation = svn_fs_node_same;
   else if (svn_fs_x__id_part_eq(&node_id_a, &node_id_b))
     *relation = svn_fs_node_common_anchestor;
@@ -1519,7 +1520,7 @@ x_change_node_prop(svn_fs_root_t *root,
 {
   parent_path_t *parent_path;
   apr_hash_t *proplist;
-  const svn_fs_x__id_part_t *txn_id;
+  svn_fs_x__txn_id_t txn_id;
 
   if (! root->is_txn_root)
     return SVN_FS__NOT_TXN(root);
@@ -1709,7 +1710,7 @@ merge(svn_stringbuf_t *conflict_p,
       dag_node_t *target,
       dag_node_t *source,
       dag_node_t *ancestor,
-      const svn_fs_x__id_part_t *txn_id,
+      svn_fs_x__txn_id_t txn_id,
       apr_int64_t *mergeinfo_increment_out,
       apr_pool_t *pool)
 {
@@ -2072,7 +2073,7 @@ merge_changes(dag_node_t *ancestor_node,
 {
   dag_node_t *txn_root_node;
   svn_fs_t *fs = txn->fs;
-  const svn_fs_x__id_part_t *txn_id = svn_fs_x__txn_get_id(txn);
+  svn_fs_x__txn_id_t txn_id = svn_fs_x__txn_get_id(txn);
   
   SVN_ERR(svn_fs_x__dag_txn_root(&txn_root_node, fs, txn_id, pool));
 
@@ -2352,7 +2353,7 @@ x_make_dir(svn_fs_root_t *root,
 {
   parent_path_t *parent_path;
   dag_node_t *sub_dir;
-  const svn_fs_x__id_part_t *txn_id = root_txn_id(root);
+  svn_fs_x__txn_id_t txn_id = root_txn_id(root);
 
   path = svn_fs__canonicalize_abspath(path, pool);
   SVN_ERR(open_path(&parent_path, root, path, open_path_last_optional,
@@ -2399,7 +2400,7 @@ x_delete_node(svn_fs_root_t *root,
               apr_pool_t *pool)
 {
   parent_path_t *parent_path;
-  const svn_fs_x__id_part_t *txn_id;
+  svn_fs_x__txn_id_t txn_id;
   apr_int64_t mergeinfo_count = 0;
   svn_node_kind_t kind;
 
@@ -2548,7 +2549,7 @@ copy_helper(svn_fs_root_t *from_root,
 {
   dag_node_t *from_node;
   parent_path_t *to_parent_path;
-  const svn_fs_x__id_part_t *txn_id = root_txn_id(to_root);
+  svn_fs_x__txn_id_t txn_id = root_txn_id(to_root);
   svn_boolean_t same_p;
 
   /* Use an error check, not an assert, because even the caller cannot
@@ -2576,11 +2577,11 @@ copy_helper(svn_fs_root_t *from_root,
     {
       /* if we don't copy from the TXN's base rev, check that the path has
          not been touched in that revision range */
-      if (from_root->rev != txn_id->revision)
+      if (from_root->rev != to_root->rev)
         {
           svn_boolean_t changed = TRUE;
           svn_error_t *err = is_changed_node(&changed, from_root,
-                                             from_path, txn_id->revision,
+                                             from_path, to_root->rev,
                                              pool);
 
           /* Only "not found" is considered to be caused by out-of-date-ness.
@@ -2598,7 +2599,7 @@ copy_helper(svn_fs_root_t *from_root,
 
           /* always move from the txn's base rev */
           SVN_ERR(svn_fs_x__revision_root(&from_root, from_root->fs,
-                                          txn_id->revision, pool));
+                                          to_root->rev, pool));
         }
     }
 
@@ -2801,7 +2802,7 @@ x_make_file(svn_fs_root_t *root,
 {
   parent_path_t *parent_path;
   dag_node_t *child;
-  const svn_fs_x__id_part_t *txn_id = root_txn_id(root);
+  svn_fs_x__txn_id_t txn_id = root_txn_id(root);
 
   path = svn_fs__canonicalize_abspath(path, pool);
   SVN_ERR(open_path(&parent_path, root, path, open_path_last_optional,
@@ -3035,7 +3036,7 @@ apply_textdelta(void *baton, apr_pool_t 
 {
   txdelta_baton_t *tb = (txdelta_baton_t *) baton;
   parent_path_t *parent_path;
-  const svn_fs_x__id_part_t *txn_id = root_txn_id(tb->root);
+  svn_fs_x__txn_id_t txn_id = root_txn_id(tb->root);
 
   /* Call open_path with no flags, as we want this to return an error
      if the node for which we are searching doesn't exist. */
@@ -3200,7 +3201,7 @@ apply_text(void *baton, apr_pool_t *pool
 {
   struct text_baton_t *tb = baton;
   parent_path_t *parent_path;
-  const svn_fs_x__id_part_t *txn_id = root_txn_id(tb->root);
+  svn_fs_x__txn_id_t txn_id = root_txn_id(tb->root);
 
   /* Call open_path with no flags, as we want this to return an error
      if the node for which we are searching doesn't exist. */
@@ -3518,172 +3519,22 @@ svn_error_t *x_closest_copy(svn_fs_root_
 }
 
 
-/* Set *PREV_PATH and *PREV_REV to the path and revision which
-   represent the location at which PATH in FS was located immediately
-   prior to REVISION iff there was a copy operation (to PATH or one of
-   its parent directories) between that previous location and
-   PATH@REVISION.
-
-   If there was no such copy operation in that portion of PATH's
-   history, set *PREV_PATH to NULL and *PREV_REV to SVN_INVALID_REVNUM.  */
-static svn_error_t *
-prev_location(const char **prev_path,
-              svn_revnum_t *prev_rev,
-              svn_fs_t *fs,
-              svn_fs_root_t *root,
-              const char *path,
-              apr_pool_t *pool)
-{
-  const char *copy_path, *copy_src_path, *remainder_path;
-  svn_fs_root_t *copy_root;
-  svn_revnum_t copy_src_rev;
-
-  /* Ask about the most recent copy which affected PATH@REVISION.  If
-     there was no such copy, we're done.  */
-  SVN_ERR(x_closest_copy(&copy_root, &copy_path, root, path, pool));
-  if (! copy_root)
-    {
-      *prev_rev = SVN_INVALID_REVNUM;
-      *prev_path = NULL;
-      return SVN_NO_ERROR;
-    }
-
-  /* Ultimately, it's not the path of the closest copy's source that
-     we care about -- it's our own path's location in the copy source
-     revision.  So we'll tack the relative path that expresses the
-     difference between the copy destination and our path in the copy
-     revision onto the copy source path to determine this information.
-
-     In other words, if our path is "/branches/my-branch/foo/bar", and
-     we know that the closest relevant copy was a copy of "/trunk" to
-     "/branches/my-branch", then that relative path under the copy
-     destination is "/foo/bar".  Tacking that onto the copy source
-     path tells us that our path was located at "/trunk/foo/bar"
-     before the copy.
-  */
-  SVN_ERR(x_copied_from(&copy_src_rev, &copy_src_path,
-                        copy_root, copy_path, pool));
-  remainder_path = svn_fspath__skip_ancestor(copy_path, path);
-  *prev_path = svn_fspath__join(copy_src_path, remainder_path, pool);
-  *prev_rev = copy_src_rev;
-  return SVN_NO_ERROR;
-}
-
-
 static svn_error_t *
 x_node_origin_rev(svn_revnum_t *revision,
                   svn_fs_root_t *root,
                   const char *path,
                   apr_pool_t *pool)
 {
-  svn_fs_t *fs = root->fs;
-  const svn_fs_id_t *given_noderev_id, *cached_origin_id;
+  const svn_fs_id_t *given_noderev_id;
   const svn_fs_x__id_part_t *node_id;
 
   path = svn_fs__canonicalize_abspath(path, pool);
 
-  /* Check the cache first. */
   SVN_ERR(svn_fs_x__node_id(&given_noderev_id, root, path, pool));
   node_id = svn_fs_x__id_node_id(given_noderev_id);
+  *revision = svn_fs_x__get_revnum(node_id->change_set);
 
-  /* Is it a brand new uncommitted node or a new-style one?
-   * (committed old-style nodes will have a 0 revision value;
-   * rev 0, number 0 is rev 0 root node) */
-  if (node_id->revision != 0 || node_id->number == 0)
-    {
-      *revision = node_id->revision;
-      return SVN_NO_ERROR;
-    }
-
-  /* The root node always has ID 0, created in revision 0 and will never
-     use the new-style ID format. */
-  if (node_id->number == 0)
-    {
-      *revision = 0;
-      return SVN_NO_ERROR;
-    }
-
-  /* OK, it's an old-style ID?  Maybe it's cached. */
-  SVN_ERR(svn_fs_x__get_node_origin(&cached_origin_id, fs, node_id, pool));
-  if (cached_origin_id != NULL)
-    {
-      *revision = svn_fs_x__id_rev(cached_origin_id);
-      return SVN_NO_ERROR;
-    }
-
-  {
-    /* Ah well, the answer isn't in the ID itself or in the cache.
-       Let's actually calculate it, then. */
-    svn_fs_root_t *curroot = root;
-    apr_pool_t *subpool = svn_pool_create(pool);
-    apr_pool_t *predidpool = svn_pool_create(pool);
-    svn_stringbuf_t *lastpath = svn_stringbuf_create(path, pool);
-    svn_revnum_t lastrev = SVN_INVALID_REVNUM;
-    dag_node_t *node;
-    const svn_fs_id_t *pred_id;
-
-    /* Walk the closest-copy chain back to the first copy in our history.
-
-       NOTE: We merely *assume* that this is faster than walking the
-       predecessor chain, because we *assume* that copies of parent
-       directories happen less often than modifications to a given item. */
-    while (1)
-      {
-        svn_revnum_t currev;
-        const char *curpath = lastpath->data;
-
-        svn_pool_clear(subpool);
-
-        /* Get a root pointing to LASTREV.  (The first time around,
-           LASTREV is invalid, but that's cool because CURROOT is
-           already initialized.)  */
-        if (SVN_IS_VALID_REVNUM(lastrev))
-          SVN_ERR(svn_fs_x__revision_root(&curroot, fs, lastrev, subpool));
-
-        /* Find the previous location using the closest-copy shortcut. */
-        SVN_ERR(prev_location(&curpath, &currev, fs, curroot, curpath,
-                              subpool));
-        if (! curpath)
-          break;
-
-        /* Update our LASTPATH and LASTREV variables (which survive
-           SUBPOOL). */
-        svn_stringbuf_set(lastpath, curpath);
-        lastrev = currev;
-      }
-
-    /* Walk the predecessor links back to origin. */
-    SVN_ERR(svn_fs_x__node_id(&pred_id, curroot, lastpath->data, predidpool));
-    do
-      {
-        svn_pool_clear(subpool);
-        SVN_ERR(svn_fs_x__dag_get_node(&node, fs, pred_id, subpool));
-
-        /* Why not just fetch the predecessor ID in PREDIDPOOL?
-           Because svn_fs_x__dag_get_predecessor_id() doesn't
-           necessarily honor the passed-in pool, and might return a
-           value cached in the node (which is allocated in
-           SUBPOOL... maybe). */
-        svn_pool_clear(predidpool);
-        SVN_ERR(svn_fs_x__dag_get_predecessor_id(&pred_id, node));
-        pred_id = pred_id ? svn_fs_x__id_copy(pred_id, predidpool) : NULL;
-      }
-    while (pred_id);
-
-    /* When we get here, NODE should be the first node-revision in our
-       chain. */
-    SVN_ERR(svn_fs_x__dag_get_revision(revision, node, pool));
-
-    /* Wow, I don't want to have to do all that again.  Let's cache
-       the result. */
-    if (node_id->revision != SVN_INVALID_REVNUM)
-      SVN_ERR(svn_fs_x__set_node_origin(fs, node_id,
-                                        svn_fs_x__dag_get_id(node), pool));
-
-    svn_pool_destroy(subpool);
-    svn_pool_destroy(predidpool);
-    return SVN_NO_ERROR;
-  }
+  return SVN_NO_ERROR;
 }
 
 
@@ -4394,17 +4245,17 @@ make_revision_root(svn_fs_t *fs,
 static svn_error_t *
 make_txn_root(svn_fs_root_t **root_p,
               svn_fs_t *fs,
-              const svn_fs_x__id_part_t *txn,
+              svn_fs_x__txn_id_t txn_id,
               svn_revnum_t base_rev,
               apr_uint32_t flags,
               apr_pool_t *pool)
 {
   svn_fs_root_t *root = make_root(fs, pool);
   fs_txn_root_data_t *frd = apr_pcalloc(root->pool, sizeof(*frd));
-  frd->txn_id = *txn;
+  frd->txn_id = txn_id;
 
   root->is_txn_root = TRUE;
-  root->txn = svn_fs_x__id_txn_unparse(txn, root->pool);
+  root->txn = svn_fs_x__txn_name(txn_id, root->pool);
   root->txn_flags = flags;
   root->rev = base_rev;
 
@@ -4418,7 +4269,7 @@ make_txn_root(svn_fs_root_t **root_p,
                                       svn_fs_x__dag_deserialize,
                                       APR_HASH_KEY_STRING,
                                       32, 20, FALSE,
-                                      apr_pstrcat(pool, txn, ":TXN",
+                                      apr_pstrcat(pool, root->txn, ":TXN",
                                                   SVN_VA_NULL),
                                       root->pool));
 
@@ -4581,7 +4432,7 @@ svn_fs_x__verify_root(svn_fs_root_t *roo
   if (root->is_txn_root)
     {
       fs_txn_root_data_t *frd = root->fsap_data;
-      SVN_ERR(svn_fs_x__dag_txn_root(&root_dir, fs, &frd->txn_id, pool));
+      SVN_ERR(svn_fs_x__dag_txn_root(&root_dir, fs, frd->txn_id, pool));
     }
   else
     {

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/util.c?rev=1568883&r1=1568882&r2=1568883&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/util.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/util.c Mon Feb 17 05:53:23 2014
@@ -226,24 +226,47 @@ svn_fs_x__path_revprops(svn_fs_t *fs, sv
                          pool);
 }
 
+const char *
+svn_fs_x__txn_name(svn_fs_x__txn_id_t txn_id,
+                   apr_pool_t *pool)
+{
+  char *p = apr_palloc(pool, SVN_INT64_BUFFER_SIZE);
+  svn__ui64tobase36(p, txn_id);
+  return p;
+}
+
+svn_error_t *
+svn_fs_x__txn_by_name(svn_fs_x__txn_id_t *txn_id,
+                      const char *txn_name)
+{
+  const char *next;
+  apr_uint64_t id = svn__base36toui64(&next, txn_name);
+  if (next == NULL || *next != 0 || *txn_name == 0)
+    return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                             "Malformed TXN name '%s'", txn_name);
+
+  *txn_id = id;
+  return SVN_NO_ERROR;
+}
+
+
 /* Return TO_ADD appended to the C string representation of TXN_ID.
  * Allocate the result in POOL.
  */
 static const char *
-combine_txn_id_string(const svn_fs_x__id_part_t *txn_id,
+combine_txn_id_string(svn_fs_x__txn_id_t txn_id,
                       const char *to_add,
                       apr_pool_t *pool)
 {
-  return apr_pstrcat(pool, svn_fs_x__id_txn_unparse(txn_id, pool),
+  return apr_pstrcat(pool, svn_fs_x__txn_name(txn_id, pool),
                      to_add, SVN_VA_NULL);
 }
 
 const char *
 svn_fs_x__path_txn_dir(svn_fs_t *fs,
-                       const svn_fs_x__id_part_t *txn_id,
+                       svn_fs_x__txn_id_t txn_id,
                        apr_pool_t *pool)
 {
-  SVN_ERR_ASSERT_NO_RETURN(txn_id != NULL);
   return svn_dirent_join_many(pool, fs->path, PATH_TXNS_DIR,
                               combine_txn_id_string(txn_id, PATH_EXT_TXN,
                                                     pool),
@@ -255,7 +278,7 @@ svn_fs_x__path_txn_dir(svn_fs_t *fs,
  */
 const char *
 svn_fs_x__path_txn_sha1(svn_fs_t *fs,
-                        const svn_fs_x__id_part_t *txn_id,
+                        svn_fs_x__txn_id_t txn_id,
                         const unsigned char *sha1,
                         apr_pool_t *pool)
 {
@@ -270,7 +293,7 @@ svn_fs_x__path_txn_sha1(svn_fs_t *fs,
 
 const char *
 svn_fs_x__path_txn_changes(svn_fs_t *fs,
-                           const svn_fs_x__id_part_t *txn_id,
+                           svn_fs_x__txn_id_t txn_id,
                            apr_pool_t *pool)
 {
   return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool),
@@ -279,7 +302,7 @@ svn_fs_x__path_txn_changes(svn_fs_t *fs,
 
 const char *
 svn_fs_x__path_txn_props(svn_fs_t *fs,
-                         const svn_fs_x__id_part_t *txn_id,
+                         svn_fs_x__txn_id_t txn_id,
                          apr_pool_t *pool)
 {
   return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool),
@@ -288,7 +311,7 @@ svn_fs_x__path_txn_props(svn_fs_t *fs,
 
 const char *
 svn_fs_x__path_txn_props_final(svn_fs_t *fs,
-                               const svn_fs_x__id_part_t *txn_id,
+                               svn_fs_x__txn_id_t txn_id,
                                apr_pool_t *pool)
 {
   return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool),
@@ -297,7 +320,7 @@ svn_fs_x__path_txn_props_final(svn_fs_t 
 
 const char*
 svn_fs_x__path_l2p_proto_index(svn_fs_t *fs,
-                               const svn_fs_x__id_part_t *txn_id,
+                               svn_fs_x__txn_id_t txn_id,
                                apr_pool_t *pool)
 {
   return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool),
@@ -306,7 +329,7 @@ svn_fs_x__path_l2p_proto_index(svn_fs_t 
 
 const char*
 svn_fs_x__path_p2l_proto_index(svn_fs_t *fs,
-                               const svn_fs_x__id_part_t *txn_id,
+                               svn_fs_x__txn_id_t txn_id,
                                apr_pool_t *pool)
 {
   return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool),
@@ -315,7 +338,7 @@ svn_fs_x__path_p2l_proto_index(svn_fs_t 
 
 const char *
 svn_fs_x__path_txn_next_ids(svn_fs_t *fs,
-                            const svn_fs_x__id_part_t *txn_id,
+                            svn_fs_x__txn_id_t txn_id,
                             apr_pool_t *pool)
 {
   return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool),
@@ -330,7 +353,7 @@ svn_fs_x__path_min_unpacked_rev(svn_fs_t
 
 const char *
 svn_fs_x__path_txn_item_index(svn_fs_t *fs,
-                              const svn_fs_x__id_part_t *txn_id,
+                              svn_fs_x__txn_id_t txn_id,
                               apr_pool_t *pool)
 {
   return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool),
@@ -339,7 +362,7 @@ svn_fs_x__path_txn_item_index(svn_fs_t *
 
 const char *
 svn_fs_x__path_txn_proto_rev(svn_fs_t *fs,
-                             const svn_fs_x__id_part_t *txn_id,
+                             svn_fs_x__txn_id_t txn_id,
                              apr_pool_t *pool)
 {
   return svn_dirent_join_many(pool, fs->path, PATH_TXN_PROTOS_DIR,
@@ -350,7 +373,7 @@ svn_fs_x__path_txn_proto_rev(svn_fs_t *f
 
 const char *
 svn_fs_x__path_txn_proto_rev_lock(svn_fs_t *fs,
-                                  const svn_fs_x__id_part_t *txn_id,
+                                  svn_fs_x__txn_id_t txn_id,
                                   apr_pool_t *pool)
 {
   return svn_dirent_join_many(pool, fs->path, PATH_TXN_PROTOS_DIR,

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/util.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/util.h?rev=1568883&r1=1568882&r2=1568883&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/util.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/util.h Mon Feb 17 05:53:23 2014
@@ -153,8 +153,16 @@ svn_fs_x__path_revprops(svn_fs_t *fs,
                         apr_pool_t *pool);
 
 const char *
+svn_fs_x__txn_name(svn_fs_x__txn_id_t txn_id,
+                   apr_pool_t *pool);
+
+svn_error_t *
+svn_fs_x__txn_by_name(svn_fs_x__txn_id_t *txn_id,
+                      const char *txn_name);
+
+const char *
 svn_fs_x__path_txn_dir(svn_fs_t *fs,
-                       const svn_fs_x__id_part_t *txn_id,
+                       svn_fs_x__txn_id_t txn_id,
                        apr_pool_t *pool);
 
 /* Return the name of the sha1->rep mapping file in transaction TXN_ID
@@ -162,38 +170,38 @@ svn_fs_x__path_txn_dir(svn_fs_t *fs,
  */
 const char *
 svn_fs_x__path_txn_sha1(svn_fs_t *fs,
-                        const svn_fs_x__id_part_t *txn_id,
+                        svn_fs_x__txn_id_t txn_id,
                         const unsigned char *sha1,
                         apr_pool_t *pool);
 
 const char *
 svn_fs_x__path_txn_changes(svn_fs_t *fs,
-                           const svn_fs_x__id_part_t *txn_id,
+                           svn_fs_x__txn_id_t txn_id,
                            apr_pool_t *pool);
 
 const char*
 svn_fs_x__path_l2p_proto_index(svn_fs_t *fs,
-                               const svn_fs_x__id_part_t *txn_id,
+                               svn_fs_x__txn_id_t txn_id,
                                apr_pool_t *pool);
 
 const char*
 svn_fs_x__path_p2l_proto_index(svn_fs_t *fs,
-                               const svn_fs_x__id_part_t *txn_id,
+                               svn_fs_x__txn_id_t txn_id,
                                apr_pool_t *pool);
 
 const char *
 svn_fs_x__path_txn_props(svn_fs_t *fs,
-                         const svn_fs_x__id_part_t *txn_id,
+                         svn_fs_x__txn_id_t txn_id,
                          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,
+                               svn_fs_x__txn_id_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,
+                            svn_fs_x__txn_id_t txn_id,
                             apr_pool_t *pool);
 
 const char *
@@ -203,17 +211,17 @@ svn_fs_x__path_min_unpacked_rev(svn_fs_t
 
 const char *
 svn_fs_x__path_txn_item_index(svn_fs_t *fs,
-                              const svn_fs_x__id_part_t *txn_id,
+                              svn_fs_x__txn_id_t txn_id,
                               apr_pool_t *pool);
 
 const char *
 svn_fs_x__path_txn_proto_rev(svn_fs_t *fs,
-                             const svn_fs_x__id_part_t *txn_id,
+                             svn_fs_x__txn_id_t txn_id,
                              apr_pool_t *pool);
 
 const char *
 svn_fs_x__path_txn_proto_rev_lock(svn_fs_t *fs,
-                                  const svn_fs_x__id_part_t *txn_id,
+                                  svn_fs_x__txn_id_t txn_id,
                                   apr_pool_t *pool);
 
 const char *

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/verify.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/verify.c?rev=1568883&r1=1568882&r2=1568883&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/verify.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_x/verify.c Mon Feb 17 05:53:23 2014
@@ -78,13 +78,14 @@ verify_walker(representation_t *rep,
   if (   walker_baton->iteration_count > 1000
       || walker_baton->file_count > 16)
     {
+      svn_revnum_t revision = svn_fs_x__get_revnum(rep->id.change_set);
       if (   walker_baton->notify_func
-          && rep->revision != walker_baton->last_notified_revision)
+          && revision != walker_baton->last_notified_revision)
         {
-          walker_baton->notify_func(rep->revision,
+          walker_baton->notify_func(revision,
                                     walker_baton->notify_baton,
                                     scratch_pool);
-          walker_baton->last_notified_revision = rep->revision;
+          walker_baton->last_notified_revision = revision;
         }
 
       svn_pool_clear(walker_baton->pool);
@@ -186,11 +187,15 @@ compare_l2p_to_p2l_index(svn_fs_t *fs,
         {
           apr_off_t offset;
           apr_uint32_t sub_item;
+          svn_fs_x__id_part_t l2p_item;
           svn_fs_x__id_part_t *p2l_item;
 
+          l2p_item.change_set = svn_fs_x__change_set_by_rev(revision);
+          l2p_item.number = k;
+
           /* get L2P entry.  Ignore unused entries. */
-          SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs,
-                                        revision, NULL, k, iterpool));
+          SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, &l2p_item,
+                                        iterpool));
           if (offset == -1)
             continue;
 
@@ -207,13 +212,13 @@ compare_l2p_to_p2l_index(svn_fs_t *fs,
                                      apr_off_t_toa(pool, offset),
                                      (long)sub_item, revision, (long)k);
 
-          if (p2l_item->number != k || p2l_item->revision != revision)
+          if (!svn_fs_x__id_part_eq(&l2p_item, p2l_item))
             return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT,
                                      NULL,
                                      _("p2l index info LOG r%ld:i%ld"
                                        " does not match "
                                        "l2p index for LOG r%ld:i%ld"),
-                                     p2l_item->revision,
+                                     svn_fs_x__get_revnum(p2l_item->change_set),
                                      (long)p2l_item->number, revision,
                                      (long)k);
 
@@ -287,10 +292,11 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
               apr_off_t l2p_offset;
               apr_uint32_t sub_item;
               svn_fs_x__id_part_t *p2l_item = &entry->items[k];
+              svn_revnum_t revision
+                = svn_fs_x__get_revnum(p2l_item->change_set);
 
               SVN_ERR(svn_fs_x__item_offset(&l2p_offset, &sub_item, fs,
-                                            p2l_item->revision, NULL,
-                                            p2l_item->number, iterpool));
+                                            p2l_item, iterpool));
 
               if (sub_item != k || l2p_offset != entry->offset)
                 return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT,
@@ -300,7 +306,7 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
                                            "LOG r%ld:i%ld for PHYS o%s:s%ld"),
                                          apr_off_t_toa(pool, l2p_offset),
                                          (long)sub_item,
-                                         p2l_item->revision,
+                                         revision,
                                          (long)p2l_item->number,
                                          apr_off_t_toa(pool, entry->offset),
                                          (long)k);

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/log.c?rev=1568883&r1=1568882&r2=1568883&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/log.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/log.c Mon Feb 17 05:53:23 2014
@@ -602,7 +602,7 @@ svn_ra_serf__get_log(svn_ra_session_t *r
   /* At this point, we may have a deleted file.  So, we'll match ra_neon's
    * behavior and use the larger of start or end as our 'peg' rev.
    */
-  peg_rev = (start > end) ? start : end;
+  peg_rev = (start == SVN_INVALID_REVNUM || start > end) ? start : end;
 
   SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
                                       session, NULL /* conn */,

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/options.c?rev=1568883&r1=1568882&r2=1568883&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/options.c Mon Feb 17 05:53:23 2014
@@ -368,7 +368,7 @@ options_response_handler(serf_request_t 
       serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback,
                              opt_ctx);
 
-      /* Assume mergeinfo capability unsupported, if didn't recieve information
+      /* Assume mergeinfo capability unsupported, if didn't receive information
          about server or repository mergeinfo capability. */
       if (!svn_hash_gets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO))
         svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/util.c?rev=1568883&r1=1568882&r2=1568883&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/util.c Mon Feb 17 05:53:23 2014
@@ -213,7 +213,6 @@ ssl_server_cert(void *baton, int failure
   apr_hash_t *subject = NULL;
   apr_hash_t *serf_cert = NULL;
   void *creds;
-  int found_matching_hostname = 0;
 
   svn_failures = (ssl_convert_serf_failures(failures)
       | conn->server_cert_failures);
@@ -225,26 +224,36 @@ ssl_server_cert(void *baton, int failure
       ### This should really be handled by serf, which should pass an error
           for this case, but that has backwards compatibility issues. */
       apr_array_header_t *san;
+      svn_boolean_t found_san_entry = FALSE;
+      svn_boolean_t found_matching_hostname = FALSE;
 
       serf_cert = serf_ssl_cert_certificate(cert, scratch_pool);
 
       san = svn_hash_gets(serf_cert, "subjectAltName");
       /* Try to find matching server name via subjectAltName first... */
-      if (san) {
+      if (san)
+        {
           int i;
-          for (i = 0; i < san->nelts; i++) {
+          found_san_entry = san->nelts > 0;
+          for (i = 0; i < san->nelts; i++)
+            {
               const char *s = APR_ARRAY_IDX(san, i, const char*);
-              if (apr_fnmatch(s, conn->session->session_url.hostname,
-                  APR_FNM_PERIOD | APR_FNM_CASE_BLIND) == APR_SUCCESS)
-              {
-                  found_matching_hostname = 1;
+              if (APR_SUCCESS == apr_fnmatch(s,
+                                            conn->session->session_url.hostname,
+                                            APR_FNM_PERIOD |
+                                            APR_FNM_CASE_BLIND))
+                {
+                  found_matching_hostname = TRUE;
                   break;
-              }
-          }
-      }
+                }
+            }
+        }
 
-      /* Match server certificate CN with the hostname of the server */
-      if (!found_matching_hostname)
+      /* Match server certificate CN with the hostname of the server iff
+       * we didn't find any subjectAltName fields and try to match them.
+       * Per RFC 2818 they are authoritative if present and CommonName
+       * should be ignored. */
+      if (!found_matching_hostname && !found_san_entry)
         {
           const char *hostname = NULL;
 
@@ -253,13 +262,16 @@ ssl_server_cert(void *baton, int failure
           if (subject)
             hostname = svn_hash_gets(subject, "CN");
 
-          if (!hostname
-              || apr_fnmatch(hostname, conn->session->session_url.hostname,
-                             APR_FNM_PERIOD | APR_FNM_CASE_BLIND) != APR_SUCCESS)
-          {
-              svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
-          }
-      }
+          if (hostname
+              && apr_fnmatch(hostname, conn->session->session_url.hostname,
+                             APR_FNM_PERIOD | APR_FNM_CASE_BLIND) == APR_SUCCESS)
+            {
+              found_matching_hostname = TRUE;
+            }
+        }
+
+      if (!found_matching_hostname)
+        svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
     }
 
   if (!svn_failures)