You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/07/24 15:24:44 UTC

svn commit: r1506545 [2/2] - in /subversion/branches/fsfs-improvements/subversion: include/ libsvn_fs_fs/

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.c?rev=1506545&r1=1506544&r2=1506545&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.c Wed Jul 24 13:24:44 2013
@@ -36,7 +36,6 @@
 #include "util.h"
 #include "id.h"
 #include "low_level.h"
-#include "key-gen.h"
 #include "temp_serializer.h"
 #include "cached_data.h"
 #include "lock.h"
@@ -54,7 +53,7 @@
  */
 static APR_INLINE const char *
 path_txn_sha1(svn_fs_t *fs,
-              const char *txn_id,
+              const svn_fs_fs__id_part_t *txn_id,
               svn_checksum_t *sha1,
               apr_pool_t *pool)
 {
@@ -65,7 +64,7 @@ path_txn_sha1(svn_fs_t *fs,
 
 static APR_INLINE const char *
 path_txn_changes(svn_fs_t *fs,
-                 const char *txn_id,
+                 const svn_fs_fs__id_part_t *txn_id,
                  apr_pool_t *pool)
 {
   return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, txn_id, pool),
@@ -74,7 +73,7 @@ path_txn_changes(svn_fs_t *fs,
 
 static APR_INLINE const char *
 path_txn_props(svn_fs_t *fs,
-               const char *txn_id,
+               const svn_fs_fs__id_part_t *txn_id,
                apr_pool_t *pool)
 {
   return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, txn_id, pool),
@@ -83,7 +82,7 @@ path_txn_props(svn_fs_t *fs,
 
 static APR_INLINE const char *
 path_txn_next_ids(svn_fs_t *fs,
-                  const char *txn_id,
+                  const svn_fs_fs__id_part_t *txn_id,
                   apr_pool_t *pool)
 {
   return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, txn_id, pool),
@@ -127,14 +126,14 @@ static txn_vtable_t txn_vtable = {
 typedef struct fs_txn_data_t
 {
   /* Strongly typed representation of the TXN's ID member. */
-  const char *txn_id;
+  svn_fs_fs__id_part_t txn_id;
 } fs_txn_data_t;
 
-const char *
+const svn_fs_fs__id_part_t *
 svn_fs_fs__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. */
@@ -146,7 +145,7 @@ svn_fs_fs__txn_get_id(svn_fs_txn_t *txn)
    true) or return NULL (otherwise). */
 static fs_fs_shared_txn_data_t *
 get_shared_txn(svn_fs_t *fs,
-               const char *txn_id,
+               const svn_fs_fs__id_part_t *txn_id,
                svn_boolean_t create_new)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -154,7 +153,7 @@ get_shared_txn(svn_fs_t *fs,
   fs_fs_shared_txn_data_t *txn;
 
   for (txn = ffsd->txns; txn; txn = txn->next)
-    if (svn_fs_fs__id_part_eq(txn->txn_id, txn_id))
+    if (svn_fs_fs__id_part_eq(&txn->txn_id, txn_id))
       break;
 
   if (txn || !create_new)
@@ -174,8 +173,7 @@ get_shared_txn(svn_fs_t *fs,
       txn->pool = subpool;
     }
 
-  assert(strlen(txn_id) < sizeof(txn->txn_id));
-  apr_cpystrn(txn->txn_id, txn_id, sizeof(txn->txn_id));
+  txn->txn_id = *txn_id;
   txn->being_written = FALSE;
 
   /* Link this transaction into the head of the list.  We will typically
@@ -193,14 +191,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 char *txn_id)
+free_shared_txn(svn_fs_t *fs, const svn_fs_fs__id_part_t *txn_id)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
   fs_fs_shared_data_t *ffsd = ffd->shared;
   fs_fs_shared_txn_data_t *txn, *prev = NULL;
 
   for (txn = ffsd->txns; txn; prev = txn, txn = txn->next)
-    if (svn_fs_fs__id_part_eq(txn->txn_id, txn_id))
+    if (svn_fs_fs__id_part_eq(&txn->txn_id, txn_id))
       break;
 
   if (!txn)
@@ -246,7 +244,7 @@ with_txnlist_lock(svn_fs_t *fs,
    which see. */
 struct unlock_proto_rev_baton
 {
-  const char *txn_id;
+  svn_fs_fs__id_part_t txn_id;
   void *lockcookie;
 };
 
@@ -256,7 +254,7 @@ unlock_proto_rev_body(svn_fs_t *fs, cons
 {
   const struct unlock_proto_rev_baton *b = baton;
   apr_file_t *lockfile = b->lockcookie;
-  fs_fs_shared_txn_data_t *txn = get_shared_txn(fs, b->txn_id, FALSE);
+  fs_fs_shared_txn_data_t *txn = get_shared_txn(fs, &b->txn_id, FALSE);
   apr_status_t apr_err;
 
   if (!txn)
@@ -293,13 +291,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 char *txn_id,
+                 const svn_fs_fs__id_part_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);
 }
@@ -308,13 +306,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 char *txn_id,
+                             const svn_fs_fs__id_part_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);
 }
@@ -325,7 +323,7 @@ struct get_writable_proto_rev_baton
 {
   apr_file_t **file;
   void **lockcookie;
-  const char *txn_id;
+  svn_fs_fs__id_part_t txn_id;
 };
 
 /* Callback used in the implementation of get_writable_proto_rev(). */
@@ -336,7 +334,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_fs_shared_txn_data_t *txn = get_shared_txn(fs, b->txn_id, TRUE);
+  fs_fs_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. */
@@ -359,7 +357,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_fs__path_txn_proto_rev_lock(fs, b->txn_id, pool);
+      = svn_fs_fs__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
@@ -400,7 +398,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_fs__path_txn_proto_rev(fs, b->txn_id, pool),
+                         svn_fs_fs__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
@@ -420,7 +418,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;
     }
@@ -442,14 +440,14 @@ static svn_error_t *
 get_writable_proto_rev(apr_file_t **file,
                        void **lockcookie,
                        svn_fs_t *fs,
-                       const char *txn_id,
+                       const svn_fs_fs__id_part_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);
 }
@@ -458,7 +456,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 char *txn_id = baton;
+  const svn_fs_fs__id_part_t *txn_id = baton;
 
   free_shared_txn(fs, txn_id);
   svn_fs_fs__reset_txn_caches(fs);
@@ -470,7 +468,7 @@ 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 char *txn_id,
+                 const svn_fs_fs__id_part_t *txn_id,
                  apr_pool_t *pool)
 {
   return with_txnlist_lock(fs, purge_shared_txn_body, txn_id, pool);
@@ -819,7 +817,7 @@ process_changes(apr_hash_t *changed_path
 svn_error_t *
 svn_fs_fs__txn_changes_fetch(apr_hash_t **changed_paths_p,
                              svn_fs_t *fs,
-                             const char *txn_id,
+                             const svn_fs_fs__id_part_t *txn_id,
                              apr_pool_t *pool)
 {
   apr_file_t *file;
@@ -875,12 +873,12 @@ svn_fs_fs__paths_changed(apr_hash_t **ch
    Allocations are from POOL.  */
 static svn_error_t *
 create_new_txn_noderev_from_rev(svn_fs_t *fs,
-                                const char *txn_id,
+                                const svn_fs_fs__id_part_t *txn_id,
                                 svn_fs_id_t *src,
                                 apr_pool_t *pool)
 {
   node_revision_t *noderev;
-  const char *node_id, *copy_id;
+  const svn_fs_fs__id_part_t *node_id, *copy_id;
 
   SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, src, pool));
 
@@ -905,7 +903,7 @@ create_new_txn_noderev_from_rev(svn_fs_t
 /* A structure used by get_and_increment_txn_key_body(). */
 struct get_and_increment_txn_key_baton {
   svn_fs_t *fs;
-  char *txn_id;
+  apr_uint64_t txn_number;
   apr_pool_t *pool;
 };
 
@@ -918,36 +916,29 @@ get_and_increment_txn_key_body(void *bat
   struct get_and_increment_txn_key_baton *cb = baton;
   const char *txn_current_filename
     = svn_fs_fs__path_txn_current(cb->fs, pool);
-  char next_txn_id[MAX_KEY_SIZE+3];
-  apr_size_t len;
+  char new_id_str[SVN_INT64_BUFFER_SIZE];
 
   svn_stringbuf_t *buf;
   SVN_ERR(svn_fs_fs__read_content(&buf, txn_current_filename, cb->pool));
 
   /* remove trailing newlines */
-  svn_stringbuf_strip_whitespace(buf);
-  cb->txn_id = buf->data;
-  len = buf->len;
+  cb->txn_number = svn__base36toui64(NULL, buf->data);
 
   /* Increment the key and add a trailing \n to the string so the
      txn-current file has a newline in it. */
-  svn_fs_fs__next_key(cb->txn_id, &len, next_txn_id);
-  next_txn_id[len] = '\n';
-  ++len;
-  next_txn_id[len] = '\0';
-
-  SVN_ERR(svn_io_write_atomic(txn_current_filename, next_txn_id, len,
+  SVN_ERR(svn_io_write_atomic(txn_current_filename, new_id_str,
+                              svn__ui64tobase36(new_id_str, cb->txn_number+1),
                               txn_current_filename /* copy_perms path */, pool));
 
   return SVN_NO_ERROR;
 }
 
-/* Create a unique directory for a transaction in FS based on revision
-   REV.  Return the ID for this transaction in *ID_P.  Use a sequence
+/* Create a unique directory for a transaction in FS based on revision REV.
+   Return the ID for this transaction in *ID_P and *TXN_ID.  Use a sequence
    value in the transaction ID to prevent reuse of transaction IDs. */
 static svn_error_t *
 create_txn_dir(const char **id_p,
-               const char **txn_id,
+               svn_fs_fs__id_part_t *txn_id,
                svn_fs_t *fs,
                svn_revnum_t rev,
                apr_pool_t *pool)
@@ -965,9 +956,10 @@ create_txn_dir(const char **id_p,
                                            get_and_increment_txn_key_body,
                                            &cb,
                                            pool));
-  *id_p = apr_psprintf(pool, "%ld-%s", rev, cb.txn_id);
+  txn_id->revision = rev;
+  txn_id->number = cb.txn_number;
 
-  *txn_id = *id_p;
+  *id_p = svn_fs_fs__id_txn_unparse(txn_id, pool);
   txn_dir = svn_dirent_join_many(pool,
                                  fs->path,
                                  PATH_TXNS_DIR,
@@ -986,7 +978,7 @@ create_txn_dir(const char **id_p,
    transaction IDs are possible with this implementation. */
 static svn_error_t *
 create_txn_dir_pre_1_5(const char **id_p,
-                       const char **txn_id,
+                       svn_fs_fs__id_part_t *txn_id,
                        svn_fs_t *fs,
                        svn_revnum_t rev,
                        apr_pool_t *pool)
@@ -1013,7 +1005,7 @@ create_txn_dir_pre_1_5(const char **id_p
           const char *name = svn_dirent_basename(unique_path, subpool);
           *id_p = apr_pstrndup(pool, name,
                                strlen(name) - strlen(PATH_EXT_TXN));
-          *txn_id = *id_p;
+          SVN_ERR(svn_fs_fs__id_txn_parse(txn_id, *id_p));
           svn_pool_destroy(subpool);
           return SVN_NO_ERROR;
         }
@@ -1059,24 +1051,24 @@ svn_fs_fs__create_txn(svn_fs_txn_t **txn
 
   /* Create a new root node for this transaction. */
   SVN_ERR(svn_fs_fs__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_fs__path_txn_proto_rev(fs, ftd->txn_id, pool),
+                    svn_fs_fs__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_fs__path_txn_proto_rev_lock(fs, ftd->txn_id, pool),
+               svn_fs_fs__path_txn_proto_rev_lock(fs, &ftd->txn_id, pool),
                pool));
 
   /* Create an empty changes file. */
-  SVN_ERR(svn_io_file_create_empty(path_txn_changes(fs, ftd->txn_id, pool),
+  SVN_ERR(svn_io_file_create_empty(path_txn_changes(fs, &ftd->txn_id, pool),
                                    pool));
 
   /* Create the next-ids file. */
-  return svn_io_file_create(path_txn_next_ids(fs, ftd->txn_id, pool),
+  return svn_io_file_create(path_txn_next_ids(fs, &ftd->txn_id, pool),
                             "0 0\n", pool);
 }
 
@@ -1085,14 +1077,14 @@ svn_fs_fs__create_txn(svn_fs_txn_t **txn
 static svn_error_t *
 get_txn_proplist(apr_hash_t *proplist,
                  svn_fs_t *fs,
-                 const char *txn_id,
+                 const svn_fs_fs__id_part_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_fs__id_txn_used(&txn_id))
+  if (!txn_id || !svn_fs_fs__id_txn_used(txn_id))
     return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
                             _("Internal error: a null transaction id was "
                               "passed to get_txn_proplist()"));
@@ -1135,7 +1127,7 @@ svn_fs_fs__change_txn_props(svn_fs_txn_t
   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
@@ -1158,7 +1150,7 @@ svn_fs_fs__change_txn_props(svn_fs_txn_t
   stream = svn_stream_from_stringbuf(buf, pool);
   SVN_ERR(svn_hash_write2(txn_prop, stream, SVN_HASH_TERMINATOR, pool));
   SVN_ERR(svn_stream_close(stream));
-  SVN_ERR(svn_io_write_atomic(path_txn_props(txn->fs, ftd->txn_id, pool),
+  SVN_ERR(svn_io_write_atomic(path_txn_props(txn->fs, &ftd->txn_id, pool),
                               buf->data, buf->len,
                               NULL /* copy_perms_path */, pool));
   return SVN_NO_ERROR;
@@ -1167,7 +1159,7 @@ svn_fs_fs__change_txn_props(svn_fs_txn_t
 svn_error_t *
 svn_fs_fs__get_txn(transaction_t **txn_p,
                    svn_fs_t *fs,
-                   const char *txn_id,
+                   const svn_fs_fs__id_part_t *txn_id,
                    apr_pool_t *pool)
 {
   transaction_t *txn;
@@ -1198,23 +1190,26 @@ svn_fs_fs__get_txn(transaction_t **txn_p
    POOL. */
 static svn_error_t *
 write_next_ids(svn_fs_t *fs,
-               const char *txn_id,
-               const char *node_id,
-               const char *copy_id,
+               const svn_fs_fs__id_part_t *txn_id,
+               apr_uint64_t node_id,
+               apr_uint64_t copy_id,
                apr_pool_t *pool)
 {
   apr_file_t *file;
-  svn_stream_t *out_stream;
+  char buffer[2 * SVN_INT64_BUFFER_SIZE + 2];
+  char *p = buffer;
+  
+  p += svn__ui64tobase36(p, node_id);
+  *(p++) = ' ';
+  p += svn__ui64tobase36(p, copy_id);
+  *(p++) = '\n';
+  *(p++) = '\0';
 
-  SVN_ERR(svn_io_file_open(&file, path_txn_next_ids(fs, txn_id, pool),
+  SVN_ERR(svn_io_file_open(&file,
+                           path_txn_next_ids(fs, txn_id, pool),
                            APR_WRITE | APR_TRUNCATE,
                            APR_OS_DEFAULT, pool));
-
-  out_stream = svn_stream_from_aprfile2(file, TRUE, pool);
-
-  SVN_ERR(svn_stream_printf(out_stream, pool, "%s %s\n", node_id, copy_id));
-
-  SVN_ERR(svn_stream_close(out_stream));
+  SVN_ERR(svn_io_file_write_full(file, buffer, p - buffer, NULL, pool));
   return svn_io_file_close(file, pool);
 }
 
@@ -1224,36 +1219,31 @@ write_next_ids(svn_fs_t *fs,
    nodes for the given transaction, as well as uniquifying representations.
    Perform all allocations in POOL. */
 static svn_error_t *
-read_next_ids(const char **node_id,
-              const char **copy_id,
+read_next_ids(apr_uint64_t *node_id,
+              apr_uint64_t *copy_id,
               svn_fs_t *fs,
-              const char *txn_id,
+              const svn_fs_fs__id_part_t *txn_id,
               apr_pool_t *pool)
 {
   svn_stringbuf_t *buf;
   const char *str;
-  char *last_str;
   SVN_ERR(svn_fs_fs__read_content(&buf,
                                   path_txn_next_ids(fs, txn_id, pool),
                                   pool));
 
   /* Parse this into two separate strings. */
 
-  last_str = buf->data;
-  str = svn_cstring_tokenize(" ", &last_str);
-  if (! str)
+  str = buf->data;
+  *node_id = svn__base36toui64(&str, str);
+  if (*str != ' ')
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("next-id file corrupt"));
 
-  *node_id = apr_pstrdup(pool, str);
-
-  str = svn_cstring_tokenize(" \n", &last_str);
-  if (! str)
+  *copy_id = svn__base36toui64(&str, ++str);
+  if (*str != '\n')
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("next-id file corrupt"));
 
-  *copy_id = apr_pstrdup(pool, str);
-
   return SVN_NO_ERROR;
 }
 
@@ -1262,51 +1252,41 @@ read_next_ids(const char **node_id,
    Node-ids are guaranteed to be unique to this transction, but may
    not necessarily be sequential.  Perform all allocations in POOL. */
 static svn_error_t *
-get_new_txn_node_id(const char **node_id_p,
+get_new_txn_node_id(svn_fs_fs__id_part_t *node_id_p,
                     svn_fs_t *fs,
-                    const char *txn_id,
+                    const svn_fs_fs__id_part_t *txn_id,
                     apr_pool_t *pool)
 {
-  const char *cur_node_id, *cur_copy_id;
-  char *node_id;
-  apr_size_t len;
+  apr_uint64_t node_id, copy_id;
 
   /* First read in the current next-ids file. */
-  SVN_ERR(read_next_ids(&cur_node_id, &cur_copy_id, fs, txn_id, pool));
+  SVN_ERR(read_next_ids(&node_id, &copy_id, fs, txn_id, pool));
 
-  node_id = apr_pcalloc(pool, strlen(cur_node_id) + 2);
+  node_id_p->revision = SVN_INVALID_REVNUM;
+  node_id_p->number = node_id;
 
-  len = strlen(cur_node_id);
-  svn_fs_fs__next_key(cur_node_id, &len, node_id);
-
-  SVN_ERR(write_next_ids(fs, txn_id, node_id, cur_copy_id, pool));
-
-  *node_id_p = apr_pstrcat(pool, "_", cur_node_id, (char *)NULL);
+  SVN_ERR(write_next_ids(fs, txn_id, ++node_id, copy_id, pool));
 
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
-svn_fs_fs__reserve_copy_id(const char **copy_id_p,
+svn_fs_fs__reserve_copy_id(svn_fs_fs__id_part_t *copy_id_p,
                            svn_fs_t *fs,
-                           const char *txn_id,
+                           const svn_fs_fs__id_part_t *txn_id,
                            apr_pool_t *pool)
 {
-  const char *cur_node_id, *cur_copy_id;
-  char *copy_id;
-  apr_size_t len;
+  apr_uint64_t node_id, copy_id;
 
   /* First read in the current next-ids file. */
-  SVN_ERR(read_next_ids(&cur_node_id, &cur_copy_id, fs, txn_id, pool));
-
-  copy_id = apr_pcalloc(pool, strlen(cur_copy_id) + 2);
+  SVN_ERR(read_next_ids(&node_id, &copy_id, fs, txn_id, pool));
 
-  len = strlen(cur_copy_id);
-  svn_fs_fs__next_key(cur_copy_id, &len, copy_id);
+  /* this is an in-txn ID now */
+  copy_id_p->revision = SVN_INVALID_REVNUM;
+  copy_id_p->number = copy_id;
 
-  SVN_ERR(write_next_ids(fs, txn_id, cur_node_id, copy_id, pool));
-
-  *copy_id_p = apr_pstrcat(pool, "_", cur_copy_id, (char *)NULL);
+  /* Update the ID counter file */
+  SVN_ERR(write_next_ids(fs, txn_id, node_id, ++copy_id, pool));
 
   return SVN_NO_ERROR;
 }
@@ -1315,17 +1295,17 @@ svn_error_t *
 svn_fs_fs__create_node(const svn_fs_id_t **id_p,
                        svn_fs_t *fs,
                        node_revision_t *noderev,
-                       const char *copy_id,
-                       const char *txn_id,
+                       const svn_fs_fs__id_part_t *copy_id,
+                       const svn_fs_fs__id_part_t *txn_id,
                        apr_pool_t *pool)
 {
-  const char *node_id;
+  svn_fs_fs__id_part_t node_id;
   const svn_fs_id_t *id;
 
   /* Get a new node-id for this node. */
   SVN_ERR(get_new_txn_node_id(&node_id, fs, txn_id, pool));
 
-  id = svn_fs_fs__id_txn_create(node_id, copy_id, txn_id, pool);
+  id = svn_fs_fs__id_txn_create(&node_id, copy_id, txn_id, pool);
 
   noderev->id = id;
 
@@ -1338,15 +1318,17 @@ svn_fs_fs__create_node(const svn_fs_id_t
 
 svn_error_t *
 svn_fs_fs__purge_txn(svn_fs_t *fs,
-                     const char *txn_id,
+                     const char *txn_id_str,
                      apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
+  svn_fs_fs__id_part_t txn_id;
+  SVN_ERR(svn_fs_fs__id_txn_parse(&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_fs__path_txn_dir(fs, txn_id, pool),
+  SVN_ERR(svn_io_remove_dir2(svn_fs_fs__path_txn_dir(fs, &txn_id, pool),
                              FALSE, NULL, NULL, pool));
   if (ffd->format >= SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT)
     {
@@ -1355,10 +1337,10 @@ svn_fs_fs__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_fs__path_txn_proto_rev(fs, txn_id, pool),
+                  svn_fs_fs__path_txn_proto_rev(fs, &txn_id, pool),
                   TRUE, pool));
       SVN_ERR(svn_io_remove_file2(
-                  svn_fs_fs__path_txn_proto_rev_lock(fs, txn_id, pool),
+                  svn_fs_fs__path_txn_proto_rev_lock(fs, &txn_id, pool),
                   TRUE, pool));
     }
   return SVN_NO_ERROR;
@@ -1387,11 +1369,14 @@ set_uniquifier(svn_fs_t *fs,
                representation_t *rep,
                apr_pool_t *pool)
 {
-  const char *buffer;
+  svn_fs_fs__id_part_t temp;
+  char buffer[SVN_INT64_BUFFER_SIZE];
+
+  SVN_ERR(get_new_txn_node_id(&temp, fs, &rep->txn_id, pool));
+  svn__ui64tobase36(buffer, temp.number);
 
-  SVN_ERR(get_new_txn_node_id(&buffer, fs, rep->txn_id, pool));
   rep->uniquifier
-    = apr_psprintf(pool, "%s/%s",
+    = apr_psprintf(pool, "%s/_%s",
                    svn_fs_fs__id_txn_unparse(&rep->txn_id, pool),
                    buffer);
 
@@ -1416,7 +1401,7 @@ reset_txn_in_rep(representation_t *rep)
 
 svn_error_t *
 svn_fs_fs__set_entry(svn_fs_t *fs,
-                     const char *txn_id,
+                     const svn_fs_fs__id_part_t *txn_id,
                      node_revision_t *parent_noderev,
                      const char *name,
                      const svn_fs_id_t *id,
@@ -1451,7 +1436,7 @@ svn_fs_fs__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;
+      rep->txn_id = *txn_id;
       SVN_ERR(set_uniquifier(fs, rep, pool));
       parent_noderev->data_rep = rep;
       SVN_ERR(svn_fs_fs__put_node_revision(fs, parent_noderev->id,
@@ -1514,7 +1499,7 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
 
 svn_error_t *
 svn_fs_fs__add_change(svn_fs_t *fs,
-                      const char *txn_id,
+                      const svn_fs_fs__id_part_t *txn_id,
                       const char *path,
                       const svn_fs_id_t *id,
                       svn_fs_path_change_kind_t change_kind,
@@ -1907,7 +1892,7 @@ get_shared_rep(representation_t **old_re
     {
       svn_node_kind_t kind;
       const char *file_name
-        = path_txn_sha1(fs, rep->txn_id, rep->sha1_checksum, pool);
+        = path_txn_sha1(fs, &rep->txn_id, rep->sha1_checksum, pool);
 
       /* in our txn, is there a rep file named with the wanted SHA1?
          If so, read it and use that rep.
@@ -1957,7 +1942,7 @@ 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_fs__id_txn_id(b->noderev->id);
+  rep->txn_id = *svn_fs_fs__id_txn_id(b->noderev->id);
   SVN_ERR(set_uniquifier(b->fs, rep, b->pool));
   rep->revision = SVN_INVALID_REVNUM;
 
@@ -1997,7 +1982,7 @@ rep_write_contents_close(void *baton)
     SVN_ERR(store_sha1_rep_mapping(b->fs, b->noderev, 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, &rep->txn_id, b->lockcookie, b->pool));
   svn_pool_destroy(b->pool);
 
   return SVN_NO_ERROR;
@@ -2048,8 +2033,8 @@ svn_fs_fs__create_successor(const svn_fs
                             svn_fs_t *fs,
                             const svn_fs_id_t *old_idp,
                             node_revision_t *new_noderev,
-                            const char *copy_id,
-                            const char *txn_id,
+                            const svn_fs_fs__id_part_t *copy_id,
+                            const svn_fs_fs__id_part_t *txn_id,
                             apr_pool_t *pool)
 {
   const svn_fs_id_t *id;
@@ -2099,7 +2084,7 @@ svn_fs_fs__set_proplist(svn_fs_t *fs,
   if (!noderev->prop_rep || !is_txn_rep(noderev->prop_rep))
     {
       noderev->prop_rep = apr_pcalloc(pool, sizeof(*noderev->prop_rep));
-      noderev->prop_rep->txn_id = svn_fs_fs__id_txn_id(noderev->id);
+      noderev->prop_rep->txn_id = *svn_fs_fs__id_txn_id(noderev->id);
       SVN_ERR(svn_fs_fs__put_node_revision(fs, noderev->id, noderev, FALSE,
                                            pool));
     }
@@ -2111,8 +2096,8 @@ svn_fs_fs__set_proplist(svn_fs_t *fs,
    available node id in *NODE_ID, and the next available copy id in
    *COPY_ID.  Allocations are performed from POOL. */
 static svn_error_t *
-get_next_revision_ids(const char **node_id,
-                      const char **copy_id,
+get_next_revision_ids(apr_uint64_t *node_id,
+                      apr_uint64_t *copy_id,
                       svn_fs_t *fs,
                       apr_pool_t *pool)
 {
@@ -2135,14 +2120,14 @@ get_next_revision_ids(const char **node_
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Corrupt 'current' file"));
 
-  *node_id = apr_pstrdup(pool, str);
+  *node_id = svn__base36toui64(NULL, str);
 
   str = svn_cstring_tokenize(" \n", &buf);
   if (! str)
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Corrupt 'current' file"));
 
-  *copy_id = apr_pstrdup(pool, str);
+  *copy_id = svn__base36toui64(NULL, str);
 
   return SVN_NO_ERROR;
 }
@@ -2416,21 +2401,21 @@ validate_root_noderev(svn_fs_t *fs,
  * revision.  Use the repo FORMAT to decide which implementation to use.
  */
 static void
-get_final_id(const char **part,
+get_final_id(svn_fs_fs__id_part_t *part,
              svn_revnum_t revision,
-             const char *start_id,
-             int format,
-             apr_pool_t *pool)
+             apr_uint64_t start_id,
+             int format)
 {
-  if (**part == '_')
+  if (part->revision == SVN_INVALID_REVNUM)
     {
       if (format >= SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT)
-        *part = apr_psprintf(pool, "%s-%ld", *part + 1, revision);
+        {
+          part->revision = revision;
+        }
       else
         {
-          char buf[MAX_KEY_SIZE + 2];
-          svn_fs_fs__add_keys(start_id, *part + 1, buf);
-          *part = apr_pstrdup(pool, buf);
+          part->revision = 0;
+          part->number += start_id;
         }
     }
 }
@@ -2467,8 +2452,8 @@ write_final_rev(const svn_fs_id_t **new_
                 svn_revnum_t rev,
                 svn_fs_t *fs,
                 const svn_fs_id_t *id,
-                const char *start_node_id,
-                const char *start_copy_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,
@@ -2479,7 +2464,7 @@ 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;
-  const char *node_id, *copy_id;
+  svn_fs_fs__id_part_t node_id, copy_id, rev_offset;
   fs_fs_data_t *ffd = fs->fsap_data;
   *new_id_p = NULL;
 
@@ -2578,17 +2563,19 @@ write_final_rev(const svn_fs_id_t **new_
     }
 
   /* Convert our temporary ID into a permanent revision one. */
-  SVN_ERR(svn_fs_fs__get_file_offset(&my_offset, file, pool));
-
-  node_id = svn_fs_fs__id_node_id(noderev->id);
-  get_final_id(&node_id, rev, start_node_id, ffd->format, pool);
-  copy_id = svn_fs_fs__id_copy_id(noderev->id);
-  get_final_id(&copy_id, rev, start_copy_id, ffd->format, pool);
+  node_id = *svn_fs_fs__id_node_id(noderev->id);
+  get_final_id(&node_id, rev, start_node_id, ffd->format);
+  copy_id = *svn_fs_fs__id_copy_id(noderev->id);
+  get_final_id(&copy_id, rev, start_copy_id, ffd->format);
 
   if (noderev->copyroot_rev == SVN_INVALID_REVNUM)
     noderev->copyroot_rev = rev;
 
-  new_id = svn_fs_fs__id_rev_create(node_id, copy_id, rev, my_offset, pool);
+  SVN_ERR(svn_fs_fs__get_file_offset(&my_offset, file, pool));
+  rev_offset.number = my_offset;
+
+  rev_offset.revision = rev;
+  new_id = svn_fs_fs__id_rev_create(&node_id, &copy_id, &rev_offset, pool);
 
   noderev->id = new_id;
 
@@ -2653,7 +2640,7 @@ static svn_error_t *
 write_final_changed_path_info(apr_off_t *offset_p,
                               apr_file_t *file,
                               svn_fs_t *fs,
-                              const char *txn_id,
+                              const svn_fs_fs__id_part_t *txn_id,
                               apr_pool_t *pool)
 {
   apr_hash_t *changed_paths;
@@ -2721,28 +2708,28 @@ verify_as_revision_before_current_plus_p
    set to REV.  Perform temporary allocations in POOL. */
 static svn_error_t *
 write_final_current(svn_fs_t *fs,
-                    const char *txn_id,
+                    const svn_fs_fs__id_part_t *txn_id,
                     svn_revnum_t rev,
-                    const char *start_node_id,
-                    const char *start_copy_id,
+                    apr_uint64_t start_node_id,
+                    apr_uint64_t start_copy_id,
                     apr_pool_t *pool)
 {
-  const char *txn_node_id, *txn_copy_id;
-  char new_node_id[MAX_KEY_SIZE + 2];
-  char new_copy_id[MAX_KEY_SIZE + 2];
+  apr_uint64_t txn_node_id;
+  apr_uint64_t txn_copy_id;
   fs_fs_data_t *ffd = fs->fsap_data;
 
   if (ffd->format >= SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT)
-    return svn_fs_fs__write_current(fs, rev, NULL, NULL, pool);
+    return svn_fs_fs__write_current(fs, rev, 0, 0, pool);
 
   /* To find the next available ids, we add the id that used to be in
      the 'current' file, to the next ids from the transaction file. */
   SVN_ERR(read_next_ids(&txn_node_id, &txn_copy_id, fs, txn_id, pool));
 
-  svn_fs_fs__add_keys(start_node_id, txn_node_id, new_node_id);
-  svn_fs_fs__add_keys(start_copy_id, txn_copy_id, new_copy_id);
+  start_node_id += txn_node_id;
+  start_copy_id += txn_copy_id;
 
-  return svn_fs_fs__write_current(fs, rev, new_node_id, new_copy_id, pool);
+  return svn_fs_fs__write_current(fs, rev, start_node_id, start_copy_id,
+                                  pool);
 }
 
 /* Verify that the user registed with FS has all the locks necessary to
@@ -2750,7 +2737,7 @@ write_final_current(svn_fs_t *fs,
    The FS write lock is assumed to be held by the caller. */
 static svn_error_t *
 verify_locks(svn_fs_t *fs,
-             const char *txn_id,
+             const svn_fs_fs__id_part_t *txn_id,
              apr_pool_t *pool)
 {
   apr_pool_t *subpool = svn_pool_create(pool);
@@ -2842,7 +2829,8 @@ 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;
-  const char *start_node_id = NULL, *start_copy_id = NULL;
+  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;
@@ -2850,7 +2838,7 @@ commit_body(void *baton, apr_pool_t *poo
   apr_hash_t *txnprops;
   apr_array_header_t *txnprop_list;
   svn_prop_t prop;
-  const char *txn_id = svn_fs_fs__txn_get_id(cb->txn);
+  const svn_fs_fs__id_part_t *txn_id = svn_fs_fs__txn_get_id(cb->txn);
   svn_stringbuf_t *trailer;
 
   /* Get the current youngest revision. */
@@ -3143,12 +3131,12 @@ svn_fs_fs__open_txn(svn_fs_txn_t **txn_p
   fs_txn_data_t *ftd;
   svn_node_kind_t kind;
   transaction_t *local_txn;
-  const char *txn_id;
+  svn_fs_fs__id_part_t txn_id;
 
-  txn_id = name;
+  SVN_ERR(svn_fs_fs__id_txn_parse(&txn_id, name));
 
   /* First check to see if the directory exists. */
-  SVN_ERR(svn_io_check_path(svn_fs_fs__path_txn_dir(fs, txn_id, pool),
+  SVN_ERR(svn_io_check_path(svn_fs_fs__path_txn_dir(fs, &txn_id, pool),
                             &kind, pool));
 
   /* Did we find it? */
@@ -3165,7 +3153,7 @@ svn_fs_fs__open_txn(svn_fs_txn_t **txn_p
   txn->id = apr_pstrdup(pool, name);
   txn->fs = fs;
 
-  SVN_ERR(svn_fs_fs__get_txn(&local_txn, fs, txn_id, pool));
+  SVN_ERR(svn_fs_fs__get_txn(&local_txn, fs, &txn_id, pool));
 
   txn->base_rev = svn_fs_fs__id_rev(local_txn->base_id);
 
@@ -3233,7 +3221,7 @@ svn_error_t *
 svn_fs_fs__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 char *txn_id,
+                       const svn_fs_fs__id_part_t *txn_id,
                        apr_pool_t *pool)
 {
   transaction_t *txn;

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.h?rev=1506545&r1=1506544&r2=1506545&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.h Wed Jul 24 13:24:44 2013
@@ -27,7 +27,7 @@
 
 /* Return the transaction ID of TXN.
  */
-const char *
+const svn_fs_fs__id_part_t *
 svn_fs_fs__txn_get_id(svn_fs_txn_t *txn);
 
 /* Store NODEREV as the node-revision for the node whose id is ID in
@@ -46,7 +46,7 @@ svn_fs_fs__put_node_revision(svn_fs_t *f
 svn_error_t *
 svn_fs_fs__txn_changes_fetch(apr_hash_t **changed_paths_p,
                              svn_fs_t *fs,
-                             const char *txn_id,
+                             const svn_fs_fs__id_part_t *txn_id,
                              apr_pool_t *pool);
 
 /* Find the paths which were changed in revision REV of filesystem FS
@@ -88,15 +88,15 @@ svn_fs_fs__change_txn_props(svn_fs_txn_t
 svn_error_t *
 svn_fs_fs__get_txn(transaction_t **txn_p,
                    svn_fs_t *fs,
-                   const char *txn_id,
+                   const svn_fs_fs__id_part_t *txn_id,
                    apr_pool_t *pool);
 
 /* Return the next available copy_id in *COPY_ID for the transaction
    TXN_ID in filesystem FS.  Allocate space in POOL. */
 svn_error_t *
-svn_fs_fs__reserve_copy_id(const char **copy_id,
+svn_fs_fs__reserve_copy_id(svn_fs_fs__id_part_t *copy_id_p,
                            svn_fs_t *fs,
-                           const char *txn_id,
+                           const svn_fs_fs__id_part_t *txn_id,
                            apr_pool_t *pool);
 
 /* Create an entirely new mutable node in the filesystem FS, whose
@@ -108,8 +108,8 @@ svn_error_t *
 svn_fs_fs__create_node(const svn_fs_id_t **id_p,
                        svn_fs_t *fs,
                        node_revision_t *noderev,
-                       const char *copy_id,
-                       const char *txn_id,
+                       const svn_fs_fs__id_part_t *copy_id,
+                       const svn_fs_fs__id_part_t *txn_id,
                        apr_pool_t *pool);
 
 /* Remove all references to the transaction TXN_ID from filesystem FS.
@@ -130,7 +130,7 @@ svn_fs_fs__abort_txn(svn_fs_txn_t *txn,
    KIND.  Allocations are done in POOL. */
 svn_error_t *
 svn_fs_fs__set_entry(svn_fs_t *fs,
-                     const char *txn_id,
+                     const svn_fs_fs__id_part_t *txn_id,
                      node_revision_t *parent_noderev,
                      const char *name,
                      const svn_fs_id_t *id,
@@ -147,7 +147,7 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
    from POOL. */
 svn_error_t *
 svn_fs_fs__add_change(svn_fs_t *fs,
-                      const char *txn_id,
+                      const svn_fs_fs__id_part_t *txn_id,
                       const char *path,
                       const svn_fs_id_t *id,
                       svn_fs_path_change_kind_t change_kind,
@@ -186,8 +186,8 @@ svn_fs_fs__create_successor(const svn_fs
                             svn_fs_t *fs,
                             const svn_fs_id_t *old_idp,
                             node_revision_t *new_noderev,
-                            const char *copy_id,
-                            const char *txn_id,
+                            const svn_fs_fs__id_part_t *copy_id,
+                            const svn_fs_fs__id_part_t *txn_id,
                             apr_pool_t *pool);
 
 /* Write a new property list PROPLIST for node-revision NODEREV in
@@ -259,7 +259,7 @@ svn_error_t *
 svn_fs_fs__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 char *txn_name,
+                       const svn_fs_fs__id_part_t *txn_name,
                        apr_pool_t *pool);
 
 /* Find the value of the property named PROPNAME in transaction TXN.

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/tree.c?rev=1506545&r1=1506544&r2=1506545&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/tree.c Wed Jul 24 13:24:44 2013
@@ -51,7 +51,6 @@
 #include "svn_props.h"
 
 #include "fs.h"
-#include "key-gen.h"
 #include "cached_data.h"
 #include "dag.h"
 #include "lock.h"
@@ -106,8 +105,9 @@ typedef dag_node_t fs_rev_root_data_t;
 
 typedef struct fs_txn_root_data_t
 {
-  const char *txn_id;
-
+  /* TXN_ID value from the main struct but as a struct instead of a string */
+  svn_fs_fs__id_part_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;
@@ -126,7 +126,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 char *txn,
+                                  const svn_fs_fs__id_part_t *txn,
                                   svn_revnum_t base_rev,
                                   apr_uint32_t flags,
                                   apr_pool_t *pool);
@@ -654,13 +654,13 @@ svn_fs_fs__revision_root(svn_fs_root_t *
 /* Getting dag nodes for roots.  */
 
 /* Return the transaction ID to a given transaction ROOT. */
-static const char *
+static const svn_fs_fs__id_part_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
@@ -798,7 +798,7 @@ get_copy_inheritance(copy_id_inherit_t *
                      apr_pool_t *pool)
 {
   const svn_fs_id_t *child_id, *parent_id, *copyroot_id;
-  const char *child_copy_id, *parent_copy_id;
+  const svn_fs_fs__id_part_t *child_copy_id, *parent_copy_id;
   const char *id_path = NULL;
   svn_fs_root_t *copyroot_root;
   dag_node_t *copyroot_node;
@@ -1122,7 +1122,7 @@ make_path_mutable(svn_fs_root_t *root,
                   apr_pool_t *pool)
 {
   dag_node_t *clone;
-  const char *txn_id = root_txn_id(root);
+  const svn_fs_fs__id_part_t *txn_id = root_txn_id(root);
 
   /* Is the node mutable already?  */
   if (svn_fs_fs__dag_check_mutable(parent_path->node))
@@ -1132,7 +1132,8 @@ make_path_mutable(svn_fs_root_t *root,
   if (parent_path->parent)
     {
       const svn_fs_id_t *parent_id, *child_id, *copyroot_id;
-      const char *copy_id = NULL;
+      svn_fs_fs__id_part_t copy_id = { SVN_INVALID_REVNUM, 0 };
+      svn_fs_fs__id_part_t *copy_id_ptr = &copy_id;
       copy_id_inherit_t inherit = parent_path->copy_inherit;
       const char *clone_path, *copyroot_path;
       svn_revnum_t copyroot_rev;
@@ -1149,7 +1150,7 @@ make_path_mutable(svn_fs_root_t *root,
         {
         case copy_id_inherit_parent:
           parent_id = svn_fs_fs__dag_get_id(parent_path->parent->node);
-          copy_id = svn_fs_fs__id_copy_id(parent_id);
+          copy_id = *svn_fs_fs__id_copy_id(parent_id);
           break;
 
         case copy_id_inherit_new:
@@ -1158,7 +1159,7 @@ make_path_mutable(svn_fs_root_t *root,
           break;
 
         case copy_id_inherit_self:
-          copy_id = NULL;
+          copy_id_ptr = NULL;
           break;
 
         case copy_id_inherit_unknown:
@@ -1187,7 +1188,7 @@ make_path_mutable(svn_fs_root_t *root,
                                          parent_path->parent->node,
                                          clone_path,
                                          parent_path->entry,
-                                         copy_id, txn_id,
+                                         copy_id_ptr, txn_id,
                                          is_parent_copyroot,
                                          pool));
 
@@ -1273,7 +1274,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 char *txn_id,
+           const svn_fs_fs__id_part_t *txn_id,
            const char *path,
            const svn_fs_id_t *noderev_id,
            svn_fs_path_change_kind_t change_kind,
@@ -1469,7 +1470,7 @@ fs_change_node_prop(svn_fs_root_t *root,
 {
   parent_path_t *parent_path;
   apr_hash_t *proplist;
-  const char *txn_id;
+  const svn_fs_fs__id_part_t *txn_id;
 
   if (! root->is_txn_root)
     return SVN_FS__NOT_TXN(root);
@@ -1611,7 +1612,7 @@ merge(svn_stringbuf_t *conflict_p,
       dag_node_t *target,
       dag_node_t *source,
       dag_node_t *ancestor,
-      const char *txn_id,
+      const svn_fs_fs__id_part_t *txn_id,
       apr_int64_t *mergeinfo_increment_out,
       apr_pool_t *pool)
 {
@@ -1975,7 +1976,7 @@ merge_changes(dag_node_t *ancestor_node,
 {
   dag_node_t *txn_root_node;
   svn_fs_t *fs = txn->fs;
-  const char *txn_id = svn_fs_fs__txn_get_id(txn);
+  const svn_fs_fs__id_part_t *txn_id = svn_fs_fs__txn_get_id(txn);
   
   SVN_ERR(svn_fs_fs__dag_txn_root(&txn_root_node, fs, txn_id, pool));
 
@@ -2260,7 +2261,7 @@ fs_make_dir(svn_fs_root_t *root,
 {
   parent_path_t *parent_path;
   dag_node_t *sub_dir;
-  const char *txn_id = root_txn_id(root);
+  const svn_fs_fs__id_part_t *txn_id = root_txn_id(root);
 
   SVN_ERR(check_newline(path, pool));
 
@@ -2309,7 +2310,7 @@ fs_delete_node(svn_fs_root_t *root,
                apr_pool_t *pool)
 {
   parent_path_t *parent_path;
-  const char *txn_id;
+  const svn_fs_fs__id_part_t *txn_id;
   apr_int64_t mergeinfo_count = 0;
   svn_node_kind_t kind;
 
@@ -2385,7 +2386,7 @@ copy_helper(svn_fs_root_t *from_root,
 {
   dag_node_t *from_node;
   parent_path_t *to_parent_path;
-  const char *txn_id = root_txn_id(to_root);
+  const svn_fs_fs__id_part_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
@@ -2581,7 +2582,7 @@ fs_make_file(svn_fs_root_t *root,
 {
   parent_path_t *parent_path;
   dag_node_t *child;
-  const char *txn_id = root_txn_id(root);
+  const svn_fs_fs__id_part_t *txn_id = root_txn_id(root);
 
   SVN_ERR(check_newline(path, pool));
 
@@ -2817,7 +2818,7 @@ apply_textdelta(void *baton, apr_pool_t 
 {
   txdelta_baton_t *tb = (txdelta_baton_t *) baton;
   parent_path_t *parent_path;
-  const char *txn_id = root_txn_id(tb->root);
+  const svn_fs_fs__id_part_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. */
@@ -2982,7 +2983,7 @@ apply_text(void *baton, apr_pool_t *pool
 {
   struct text_baton_t *tb = baton;
   parent_path_t *parent_path;
-  const char *txn_id = root_txn_id(tb->root);
+  const svn_fs_fs__id_part_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. */
@@ -3360,7 +3361,7 @@ fs_node_origin_rev(svn_revnum_t *revisio
 {
   svn_fs_t *fs = root->fs;
   const svn_fs_id_t *given_noderev_id, *cached_origin_id;
-  const char *node_id, *dash;
+  const svn_fs_fs__id_part_t *node_id;
 
   path = svn_fs__canonicalize_abspath(path, pool);
 
@@ -3368,27 +3369,13 @@ fs_node_origin_rev(svn_revnum_t *revisio
   SVN_ERR(svn_fs_fs__node_id(&given_noderev_id, root, path, pool));
   node_id = svn_fs_fs__id_node_id(given_noderev_id);
 
-  /* Is it a brand new uncommitted node? */
-  if (node_id[0] == '_')
-    {
-      *revision = SVN_INVALID_REVNUM;
-      return SVN_NO_ERROR;
-    }
-
-  /* Maybe this is a new-style node ID that just has the revision
-     sitting right in it. */
-  dash = strchr(node_id, '-');
-  if (dash && *(dash+1))
-    {
-      *revision = SVN_STR_TO_REV(dash + 1);
-      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 (strcmp(node_id, "0") == 0)
+  /* Is it a brand new uncommitted node or a new-style node ID?
+   * (committed old-style nodes will have a 0 revision value;
+   * rev 0, number 0 is rev 0 root node). Note that != 0 includes
+   * SVN_INVALID_REVNUM for uncommitted nodes. */
+  if (node_id->revision != 0 || node_id->number == 0)
     {
-      *revision = 0;
+      *revision = node_id->revision;
       return SVN_NO_ERROR;
     }
 
@@ -3468,7 +3455,7 @@ fs_node_origin_rev(svn_revnum_t *revisio
 
     /* Wow, I don't want to have to do all that again.  Let's cache
        the result. */
-    if (node_id[0] != '_')
+    if (node_id->revision != SVN_INVALID_REVNUM)
       SVN_ERR(svn_fs_fs__set_node_origin(fs, node_id,
                                          svn_fs_fs__dag_get_id(node), pool));
 
@@ -4194,17 +4181,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 char *txn,
+              const svn_fs_fs__id_part_t *txn,
               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 = apr_pstrdup(root->pool, txn);
+  frd->txn_id = *txn;
 
   root->is_txn_root = TRUE;
-  root->txn = apr_pstrdup(root->pool, txn);
+  root->txn = svn_fs_fs__id_txn_unparse(txn, root->pool);
   root->txn_flags = flags;
   root->rev = base_rev;
 
@@ -4375,7 +4362,7 @@ svn_fs_fs__verify_root(svn_fs_root_t *ro
   if (root->is_txn_root)
     {
       fs_txn_root_data_t *frd = root->fsap_data;
-      SVN_ERR(svn_fs_fs__dag_txn_root(&root_dir, fs, frd->txn_id, pool));
+      SVN_ERR(svn_fs_fs__dag_txn_root(&root_dir, fs, &frd->txn_id, pool));
     }
   else
     {

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.c?rev=1506545&r1=1506544&r2=1506545&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.c Wed Jul 24 13:24:44 2013
@@ -193,17 +193,17 @@ svn_fs_fs__path_revprops(svn_fs_t *fs,
  * Allocate the result in POOL.
  */
 static const char *
-combine_txn_id_string(const char *txn_id,
+combine_txn_id_string(const svn_fs_fs__id_part_t *txn_id,
                       const char *to_add,
                       apr_pool_t *pool)
 {
-  return apr_pstrcat(pool, txn_id,
+  return apr_pstrcat(pool, svn_fs_fs__id_txn_unparse(txn_id, pool),
                      to_add, (char *)NULL);
 }
 
 const char *
 svn_fs_fs__path_txn_dir(svn_fs_t *fs,
-                        const char *txn_id,
+                        const svn_fs_fs__id_part_t *txn_id,
                         apr_pool_t *pool)
 {
   SVN_ERR_ASSERT_NO_RETURN(txn_id != NULL);
@@ -215,7 +215,7 @@ svn_fs_fs__path_txn_dir(svn_fs_t *fs,
 
 const char *
 svn_fs_fs__path_txn_proto_rev(svn_fs_t *fs,
-                              const char *txn_id,
+                              const svn_fs_fs__id_part_t *txn_id,
                               apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -231,7 +231,7 @@ svn_fs_fs__path_txn_proto_rev(svn_fs_t *
 
 const char *
 svn_fs_fs__path_txn_proto_rev_lock(svn_fs_t *fs,
-                                   const char *txn_id,
+                                   const svn_fs_fs__id_part_t *txn_id,
                                    apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -251,13 +251,13 @@ svn_fs_fs__path_txn_node_rev(svn_fs_t *f
                              const svn_fs_id_t *id,
                              apr_pool_t *pool)
 {
-  const char *txn_id = svn_fs_fs__id_txn_id(id);
-  const char *node_id = svn_fs_fs__id_node_id(id);
-  const char *copy_id = svn_fs_fs__id_copy_id(id);
-  const char *name = apr_psprintf(pool, PATH_PREFIX_NODE "%s.%s",
-                                  node_id, copy_id);
+  char *filename = (char *)svn_fs_fs__id_unparse(id, pool)->data;
+  *strrchr(filename, '.') = '\0';
 
-  return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, txn_id, pool), name,
+  return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, svn_fs_fs__id_txn_id(id),
+                                                 pool),
+                         apr_psprintf(pool, PATH_PREFIX_NODE "%s",
+                                      filename),
                          pool);
 }
 
@@ -281,11 +281,17 @@ svn_fs_fs__path_txn_node_children(svn_fs
 
 const char *
 svn_fs_fs__path_node_origin(svn_fs_t *fs,
-                            const char *node_id,
+                            const svn_fs_fs__id_part_t *node_id,
                             apr_pool_t *pool)
 {
+  char buffer[SVN_INT64_BUFFER_SIZE];
+  apr_size_t len = svn__ui64tobase36(buffer, node_id->number);
+
+  if (len > 1)
+    buffer[len - 1] = '\0';
+
   return svn_dirent_join_many(pool, fs->path, PATH_NODE_ORIGINS_DIR,
-                              node_id, NULL);
+                              buffer, NULL);
 }
 
 const char *
@@ -367,19 +373,28 @@ svn_fs_fs__write_revnum_file(svn_fs_t *f
 svn_error_t *
 svn_fs_fs__write_current(svn_fs_t *fs,
                          svn_revnum_t rev,
-                         const char *next_node_id,
-                         const char *next_copy_id,
+                         apr_uint64_t next_node_id,
+                         apr_uint64_t next_copy_id,
                          apr_pool_t *pool)
 {
   char *buf;
-  const char *name;
+  const char *tmp_name, *name;
   fs_fs_data_t *ffd = fs->fsap_data;
 
   /* Now we can just write out this line. */
   if (ffd->format >= SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT)
-    buf = apr_psprintf(pool, "%ld\n", rev);
+    {
+      buf = apr_psprintf(pool, "%ld\n", rev);
+    }
   else
-    buf = apr_psprintf(pool, "%ld %s %s\n", rev, next_node_id, next_copy_id);
+    {
+      char node_id_str[SVN_INT64_BUFFER_SIZE];
+      char copy_id_str[SVN_INT64_BUFFER_SIZE];
+      svn__ui64tobase36(node_id_str, next_node_id);
+      svn__ui64tobase36(copy_id_str, next_copy_id);
+
+      buf = apr_psprintf(pool, "%ld %s %s\n", rev, node_id_str, copy_id_str);
+    }
 
   name = svn_fs_fs__path_current(fs, pool);
   SVN_ERR(svn_io_write_atomic(name, buf, strlen(buf),

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.h?rev=1506545&r1=1506544&r2=1506545&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.h Wed Jul 24 13:24:44 2013
@@ -181,7 +181,7 @@ svn_fs_fs__path_min_unpacked_rev(svn_fs_
  */
 const char *
 svn_fs_fs__path_txn_dir(svn_fs_t *fs,
-                        const char *txn_id,
+                        const svn_fs_fs__id_part_t *txn_id,
                         apr_pool_t *pool);
 
 /* Return the path of the proto-revision file for transaction TXN_ID in FS.
@@ -189,7 +189,7 @@ svn_fs_fs__path_txn_dir(svn_fs_t *fs,
  */
 const char *
 svn_fs_fs__path_txn_proto_rev(svn_fs_t *fs,
-                              const char *txn_id,
+                              const svn_fs_fs__id_part_t *txn_id,
                               apr_pool_t *pool);
 
 /* Return the path of the proto-revision lock file for transaction TXN_ID
@@ -197,7 +197,7 @@ svn_fs_fs__path_txn_proto_rev(svn_fs_t *
  */
 const char *
 svn_fs_fs__path_txn_proto_rev_lock(svn_fs_t *fs,
-                                   const char *txn_id,
+                                   const svn_fs_fs__id_part_t *txn_id,
                                    apr_pool_t *pool);
 
 /* Return the path of the file containing the in-transaction node revision
@@ -230,7 +230,7 @@ svn_fs_fs__path_txn_node_children(svn_fs
  */
 const char *
 svn_fs_fs__path_node_origin(svn_fs_t *fs,
-                            const char *node_id,
+                            const svn_fs_fs__id_part_t *node_id,
                             apr_pool_t *pool);
 
 /* Set *MIN_UNPACKED_REV to the integer value read from the file returned
@@ -279,8 +279,8 @@ svn_fs_fs__write_revnum_file(svn_fs_t *f
 svn_error_t *
 svn_fs_fs__write_current(svn_fs_t *fs,
                          svn_revnum_t rev,
-                         const char *next_node_id,
-                         const char *next_copy_id,
+                         apr_uint64_t next_node_id,
+                         apr_uint64_t next_copy_id,
                          apr_pool_t *pool);
 
 /* Read the file at PATH and return its content in *CONTENT. *CONTENT will