Author: stefan2
Date: Thu May 16 15:57:11 2013
New Revision: 1483422

URL: http://svn.apache.org/r1483422
Log:
On the fsfs-format7 branch:  Modify the change_t structure to be easier
to use with loggy functions.

The path member will be a proper svn_string_t to allow for efficient
hashing, duplicating data etc.  The remainder now uses an instance of
the svn_fs_path_change2_t which we have to hand our to the API anyway.
Callers / users usually only need one extra syntactic indirection.

Operations that need to copy and / or "fold" changes can now be simplified,
require fewer temporary copies and will become much faster as a result.

* subversion/libsvn_fs_fs/fs.h
  (change_t): change the definition but leave contents almost unchanged

* subversion/libsvn_fs_fs/changes.c
  (append_change,
   svn_fs_fs__changes_get_list,
   svn_fs_fs__changes_get_list_func): update

* subversion/libsvn_fs_fs/low_level.c
  (read_change): ditto

* subversion/libsvn_fs_fs/temp_serializer.c
  (serialize_change,
   deserialize_change): ditto

* subversion/libsvn_fs_fs/transaction.c
  (fold_change): update and simplify
  (process_changes): update; no longer use this for pre-folded lists at all
  (svn_fs_fs__txn_changes_fetch): update caller
  (svn_fs_fs__paths_changed): build result hash directly

Modified:
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/fs.h
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/low_level.c
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/temp_serializer.c
    subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/transaction.c

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c?rev=1483422&r1=1483421&r2=1483422&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c 
(original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/changes.c Thu May 
16 15:57:11 2013
@@ -138,30 +138,34 @@ append_change(svn_fs_fs__changes_t *chan
 {
   binary_change_t binary_change = { 0 };
   svn_boolean_t is_txn_id;
+  svn_fs_path_change2_t *info;
 
   /* CHANGE must be sufficiently complete */
   SVN_ERR_ASSERT(change);
-  SVN_ERR_ASSERT(change->path);
+  SVN_ERR_ASSERT(change->path.data);
 
   /* define the kind of change and what specific information is present */
-  is_txn_id = change->noderev_id && svn_fs_fs__id_is_txn(change->noderev_id);
-  binary_change.flags = (change->text_mod ? CHANGE_TEXT_MOD : 0)
-                      | (change->prop_mod ? CHANGE_PROP_MOD : 0)
+  info = &change->info;
+  is_txn_id = info->node_rev_id && svn_fs_fs__id_is_txn(info->node_rev_id);
+  binary_change.flags = (info->text_mod ? CHANGE_TEXT_MOD : 0)
+                      | (info->prop_mod ? CHANGE_PROP_MOD : 0)
                       | (is_txn_id ? CHANGE_TXN_NODE : 0)
-                      | ((int)change->kind << CHANGE_KIND_SHIFT)
-                      | ((int)change->node_kind << CHANGE_NODE_SHIFT);
+                      | ((int)info->change_kind << CHANGE_KIND_SHIFT)
+                      | ((int)info->node_kind << CHANGE_NODE_SHIFT);
 
   /* Path of the change. */
   binary_change.path
-    = svn_fs_fs__string_table_builder_add(changes->builder, change->path, 0);
+    = svn_fs_fs__string_table_builder_add(changes->builder,
+                                          change->path.data,
+                                          change->path.len);
 
   /* copy-from information, if presence is indicated by FLAGS */
-  if (SVN_IS_VALID_REVNUM(change->copyfrom_rev))
+  if (SVN_IS_VALID_REVNUM(info->copyfrom_rev))
     {
-      binary_change.copyfrom_rev = change->copyfrom_rev;
+      binary_change.copyfrom_rev = info->copyfrom_rev;
       binary_change.copyfrom_path
         = svn_fs_fs__string_table_builder_add(changes->builder,
-                                              change->copyfrom_path,
+                                              info->copyfrom_path,
                                               0);
     }
   else
@@ -171,13 +175,13 @@ append_change(svn_fs_fs__changes_t *chan
     }
 
   /* Relevant parts of the revision ID of the change. */
-  if (change->noderev_id)
+  if (info->node_rev_id)
     {
-      binary_change.node_id = *svn_fs_fs__id_node_id(change->noderev_id);
-      binary_change.copy_id = *svn_fs_fs__id_copy_id(change->noderev_id);
+      binary_change.node_id = *svn_fs_fs__id_node_id(info->node_rev_id);
+      binary_change.copy_id = *svn_fs_fs__id_copy_id(info->node_rev_id);
       binary_change.rev_id = is_txn_id
-                           ? *svn_fs_fs__id_txn_id(change->noderev_id)
-                           : *svn_fs_fs__id_rev_item(change->noderev_id);
+                           ? *svn_fs_fs__id_txn_id(info->node_rev_id)
+                           : *svn_fs_fs__id_rev_item(info->node_rev_id);
     }
   else
     {
@@ -260,13 +264,14 @@ svn_fs_fs__changes_get_list(apr_array_he
 
       /* convert BINARY_CHANGE into a standard FSFS change_t */
       change_t *change = apr_pcalloc(pool, sizeof(*change));
-      change->path = svn_fs_fs__string_table_get(changes->paths,
-                                                 binary_change->path,
-                                                 NULL,
-                                                 pool);
+      svn_fs_path_change2_t *info = &change->info;
+      change->path.data = svn_fs_fs__string_table_get(changes->paths,
+                                                      binary_change->path,
+                                                      &change->path.len,
+                                                      pool);
 
       if (svn_fs_fs__id_txn_used(&binary_change->rev_id))
-        change->noderev_id
+        info->node_rev_id
           = (binary_change->flags & CHANGE_TXN_NODE)
           ? svn_fs_fs__id_txn_create(&binary_change->node_id,
                                      &binary_change->copy_id,
@@ -277,16 +282,17 @@ svn_fs_fs__changes_get_list(apr_array_he
                                      &binary_change->rev_id,
                                      pool);
 
-      change->kind = (svn_fs_path_change_kind_t)
+      info->change_kind = (svn_fs_path_change_kind_t)
         ((binary_change->flags & CHANGE_KIND_MASK) >> CHANGE_KIND_SHIFT);
-      change->text_mod = (binary_change->flags & CHANGE_TEXT_MOD) != 0;
-      change->prop_mod = (binary_change->flags & CHANGE_PROP_MOD) != 0;
-      change->node_kind = (svn_node_kind_t)
+      info->text_mod = (binary_change->flags & CHANGE_TEXT_MOD) != 0;
+      info->prop_mod = (binary_change->flags & CHANGE_PROP_MOD) != 0;
+      info->node_kind = (svn_node_kind_t)
         ((binary_change->flags & CHANGE_NODE_MASK) >> CHANGE_NODE_SHIFT);
 
-      change->copyfrom_rev = binary_change->copyfrom_rev;
+      info->copyfrom_rev = binary_change->copyfrom_rev;
+      info->copyfrom_known = TRUE;
       if (SVN_IS_VALID_REVNUM(binary_change->copyfrom_rev))
-        change->copyfrom_path 
+        info->copyfrom_path 
           = svn_fs_fs__string_table_get(changes->paths,
                                         binary_change->copyfrom_path,
                                         NULL,
@@ -530,13 +536,13 @@ svn_fs_fs__changes_get_list_func(void **
 
       /* convert BINARY_CHANGE into a standard FSFS change_t */
       change_t *change = apr_pcalloc(pool, sizeof(*change));
-      change->path = svn_fs_fs__string_table_get_func(paths,
-                                                      binary_change->path,
-                                                      NULL,
-                                                      pool);
+      svn_fs_path_change2_t *info = &change->info;
+      change->path.data
+        = svn_fs_fs__string_table_get_func(paths, binary_change->path,
+                                           &change->path.len, pool);
 
       if (svn_fs_fs__id_txn_used(&binary_change->rev_id))
-        change->noderev_id
+        info->node_rev_id
           = (binary_change->flags & CHANGE_TXN_NODE)
           ? svn_fs_fs__id_txn_create(&binary_change->node_id,
                                      &binary_change->copy_id,
@@ -547,16 +553,17 @@ svn_fs_fs__changes_get_list_func(void **
                                      &binary_change->rev_id,
                                      pool);
 
-      change->kind = (svn_fs_path_change_kind_t)
+      info->change_kind = (svn_fs_path_change_kind_t)
         ((binary_change->flags & CHANGE_KIND_MASK) >> CHANGE_KIND_SHIFT);
-      change->text_mod = (binary_change->flags & CHANGE_TEXT_MOD) != 0;
-      change->prop_mod = (binary_change->flags & CHANGE_PROP_MOD) != 0;
-      change->node_kind = (svn_node_kind_t)
+      info->text_mod = (binary_change->flags & CHANGE_TEXT_MOD) != 0;
+      info->prop_mod = (binary_change->flags & CHANGE_PROP_MOD) != 0;
+      info->node_kind = (svn_node_kind_t)
         ((binary_change->flags & CHANGE_NODE_MASK) >> CHANGE_NODE_SHIFT);
 
-      change->copyfrom_rev = binary_change->copyfrom_rev;
+      info->copyfrom_rev = binary_change->copyfrom_rev;
+      info->copyfrom_known = TRUE;
       if (SVN_IS_VALID_REVNUM(binary_change->copyfrom_rev))
-        change->copyfrom_path 
+        info->copyfrom_path 
           = svn_fs_fs__string_table_get_func(paths,
                                              binary_change->copyfrom_path,
                                              NULL,

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/fs.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/fs.h?rev=1483422&r1=1483421&r2=1483422&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/fs.h Thu May 16 
15:57:11 2013
@@ -561,25 +561,10 @@ typedef struct node_revision_t
 typedef struct change_t
 {
   /* Path of the change. */
-  const char *path;
-
-  /* Node revision ID of the change. */
-  const svn_fs_id_t *noderev_id;
-
-  /* The kind of change. */
-  svn_fs_path_change_kind_t kind;
-
-  /* Text or property mods? */
-  svn_boolean_t text_mod;
-  svn_boolean_t prop_mod;
-
-  /* Node kind (possibly svn_node_unknown). */
-  svn_node_kind_t node_kind;
-
-  /* Copyfrom revision and path. */
-  svn_revnum_t copyfrom_rev;
-  const char * copyfrom_path;
+  svn_string_t path;
 
+  /* API compatible change description */
+  svn_fs_path_change2_t info;
 } change_t;
 
 

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/low_level.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/low_level.c?rev=1483422&r1=1483421&r2=1483422&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/low_level.c 
(original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/low_level.c Thu 
May 16 15:57:11 2013
@@ -721,6 +721,7 @@ read_change(change_t **change_p,
   svn_boolean_t eof = TRUE;
   change_t *change;
   char *str, *last_str, *kind_str;
+  svn_fs_path_change2_t *info;
 
   /* Default return value. */
   *change_p = NULL;
@@ -732,6 +733,7 @@ read_change(change_t **change_p,
     return SVN_NO_ERROR;
 
   change = apr_pcalloc(pool, sizeof(*change));
+  info = &change->info;
   last_str = line->data;
 
   /* Get the node-id of the change. */
@@ -740,8 +742,8 @@ read_change(change_t **change_p,
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Invalid changes line in rev-file"));
 
-  change->noderev_id = svn_fs_fs__id_parse(str, strlen(str), pool);
-  if (change->noderev_id == NULL)
+  info->node_rev_id = svn_fs_fs__id_parse(str, strlen(str), pool);
+  if (info->node_rev_id == NULL)
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Invalid changes line in rev-file"));
 
@@ -753,7 +755,7 @@ read_change(change_t **change_p,
 
   /* Don't bother to check the format number before looking for
    * node-kinds: just read them if you find them. */
-  change->node_kind = svn_node_unknown;
+  info->node_kind = svn_node_unknown;
   kind_str = strchr(str, '-');
   if (kind_str)
     {
@@ -761,9 +763,9 @@ read_change(change_t **change_p,
       *kind_str = '\0';
       kind_str++;
       if (strcmp(kind_str, SVN_FS_FS__KIND_FILE) == 0)
-        change->node_kind = svn_node_file;
+        info->node_kind = svn_node_file;
       else if (strcmp(kind_str, SVN_FS_FS__KIND_DIR) == 0)
-        change->node_kind = svn_node_dir;
+        info->node_kind = svn_node_dir;
       else
         return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                                 _("Invalid changes line in rev-file"));
@@ -771,23 +773,23 @@ read_change(change_t **change_p,
 
   if (strcmp(str, ACTION_MODIFY) == 0)
     {
-      change->kind = svn_fs_path_change_modify;
+      info->change_kind = svn_fs_path_change_modify;
     }
   else if (strcmp(str, ACTION_ADD) == 0)
     {
-      change->kind = svn_fs_path_change_add;
+      info->change_kind = svn_fs_path_change_add;
     }
   else if (strcmp(str, ACTION_DELETE) == 0)
     {
-      change->kind = svn_fs_path_change_delete;
+      info->change_kind = svn_fs_path_change_delete;
     }
   else if (strcmp(str, ACTION_REPLACE) == 0)
     {
-      change->kind = svn_fs_path_change_replace;
+      info->change_kind = svn_fs_path_change_replace;
     }
   else if (strcmp(str, ACTION_RESET) == 0)
     {
-      change->kind = svn_fs_path_change_reset;
+      info->change_kind = svn_fs_path_change_reset;
     }
   else
     {
@@ -803,11 +805,11 @@ read_change(change_t **change_p,
 
   if (strcmp(str, FLAG_TRUE) == 0)
     {
-      change->text_mod = TRUE;
+      info->text_mod = TRUE;
     }
   else if (strcmp(str, FLAG_FALSE) == 0)
     {
-      change->text_mod = FALSE;
+      info->text_mod = FALSE;
     }
   else
     {
@@ -823,11 +825,11 @@ read_change(change_t **change_p,
 
   if (strcmp(str, FLAG_TRUE) == 0)
     {
-      change->prop_mod = TRUE;
+      info->prop_mod = TRUE;
     }
   else if (strcmp(str, FLAG_FALSE) == 0)
     {
-      change->prop_mod = FALSE;
+      info->prop_mod = FALSE;
     }
   else
     {
@@ -836,15 +838,16 @@ read_change(change_t **change_p,
     }
 
   /* Get the changed path. */
-  change->path = apr_pstrdup(pool, last_str);
-
+  change->path.len = strlen(last_str);
+  change->path.data = apr_pstrmemdup(pool, last_str, change->path.len);
 
   /* Read the next line, the copyfrom line. */
   SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, pool));
+  info->copyfrom_known = TRUE;
   if (eof || line->len == 0)
     {
-      change->copyfrom_rev = SVN_INVALID_REVNUM;
-      change->copyfrom_path = NULL;
+      info->copyfrom_rev = SVN_INVALID_REVNUM;
+      info->copyfrom_path = NULL;
     }
   else
     {
@@ -853,13 +856,13 @@ read_change(change_t **change_p,
       if (! str)
         return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                                 _("Invalid changes line in rev-file"));
-      change->copyfrom_rev = SVN_STR_TO_REV(str);
+      info->copyfrom_rev = SVN_STR_TO_REV(str);
 
       if (! last_str)
         return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                                 _("Invalid changes line in rev-file"));
 
-      change->copyfrom_path = apr_pstrdup(pool, last_str);
+      info->copyfrom_path = apr_pstrdup(pool, last_str);
     }
 
   *change_p = change;

Modified: 
subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/temp_serializer.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/temp_serializer.c?rev=1483422&r1=1483421&r2=1483422&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/temp_serializer.c 
(original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/temp_serializer.c 
Thu May 16 15:57:11 2013
@@ -1072,10 +1072,10 @@ serialize_change(svn_temp_serializer__co
                             sizeof(*change));
 
   /* serialize sub-structures */
-  svn_fs_fs__id_serialize(context, &change->noderev_id);
+  svn_fs_fs__id_serialize(context, &change->info.node_rev_id);
 
-  svn_temp_serializer__add_string(context, &change->path);
-  svn_temp_serializer__add_string(context, &change->copyfrom_path);
+  svn_temp_serializer__add_string(context, &change->path.data);
+  svn_temp_serializer__add_string(context, &change->info.copyfrom_path);
 
   /* return to the caller's nesting level */
   svn_temp_serializer__pop(context);
@@ -1097,10 +1097,10 @@ deserialize_change(void *buffer, change_
     return;
 
   /* fix-up of sub-structures */
-  svn_fs_fs__id_deserialize(change, (svn_fs_id_t **)&change->noderev_id);
+  svn_fs_fs__id_deserialize(change, (svn_fs_id_t **)&change->info.node_rev_id);
 
-  svn_temp_deserializer__resolve(change, (void **)&change->path);
-  svn_temp_deserializer__resolve(change, (void **)&change->copyfrom_path);
+  svn_temp_deserializer__resolve(change, (void **)&change->path.data);
+  svn_temp_deserializer__resolve(change, (void **)&change->info.copyfrom_path);
 }
 
 /* Auxiliary structure representing the content of a change_t array.

Modified: subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/transaction.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/transaction.c?rev=1483422&r1=1483421&r2=1483422&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/transaction.c 
(original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_fs_fs/transaction.c Thu 
May 16 15:57:11 2013
@@ -657,17 +657,18 @@ fold_change(apr_hash_t *changes,
 {
   apr_pool_t *pool = apr_hash_pool_get(changes);
   svn_fs_path_change2_t *old_change, *new_change;
-  const char *path;
-  apr_size_t path_len = strlen(change->path);
+  const svn_string_t *path = &change->path;
+  const svn_fs_path_change2_t *info = &change->info;
 
-  if ((old_change = apr_hash_get(changes, change->path, path_len)))
+  if (old_change = apr_hash_get(changes, path->data, path->len))
     {
       /* This path already exists in the hash, so we have to merge
          this change into the already existing one. */
 
       /* Sanity check:  only allow NULL node revision ID in the
          `reset' case. */
-      if ((! change->noderev_id) && (change->kind != svn_fs_path_change_reset))
+      if ((! info->node_rev_id)
+           && (info->change_kind != svn_fs_path_change_reset))
         return svn_error_create
           (SVN_ERR_FS_CORRUPT, NULL,
            _("Missing required node revision ID"));
@@ -675,8 +676,8 @@ fold_change(apr_hash_t *changes,
       /* Sanity check: we should be talking about the same node
          revision ID as our last change except where the last change
          was a deletion. */
-      if (change->noderev_id
-          && (! svn_fs_fs__id_eq(old_change->node_rev_id, change->noderev_id))
+      if (info->node_rev_id
+          && (! svn_fs_fs__id_eq(old_change->node_rev_id, info->node_rev_id))
           && (old_change->change_kind != svn_fs_path_change_delete))
         return svn_error_create
           (SVN_ERR_FS_CORRUPT, NULL,
@@ -686,16 +687,16 @@ fold_change(apr_hash_t *changes,
       /* Sanity check: an add, replacement, or reset must be the first
          thing to follow a deletion. */
       if ((old_change->change_kind == svn_fs_path_change_delete)
-          && (! ((change->kind == svn_fs_path_change_replace)
-                 || (change->kind == svn_fs_path_change_reset)
-                 || (change->kind == svn_fs_path_change_add))))
+          && (! ((info->change_kind == svn_fs_path_change_replace)
+                 || (info->change_kind == svn_fs_path_change_reset)
+                 || (info->change_kind == svn_fs_path_change_add))))
         return svn_error_create
           (SVN_ERR_FS_CORRUPT, NULL,
            _("Invalid change ordering: non-add change on deleted path"));
 
       /* Sanity check: an add can't follow anything except
          a delete or reset.  */
-      if ((change->kind == svn_fs_path_change_add)
+      if ((info->change_kind == svn_fs_path_change_add)
           && (old_change->change_kind != svn_fs_path_change_delete)
           && (old_change->change_kind != svn_fs_path_change_reset))
         return svn_error_create
@@ -703,7 +704,7 @@ fold_change(apr_hash_t *changes,
            _("Invalid change ordering: add change on preexisting path"));
 
       /* Now, merge that change in. */
-      switch (change->kind)
+      switch (info->change_kind)
         {
         case svn_fs_path_change_reset:
           /* A reset here will simply remove the path change from the
@@ -723,8 +724,8 @@ fold_change(apr_hash_t *changes,
             {
               /* A deletion overrules all previous changes. */
               old_change->change_kind = svn_fs_path_change_delete;
-              old_change->text_mod = change->text_mod;
-              old_change->prop_mod = change->prop_mod;
+              old_change->text_mod = info->text_mod;
+              old_change->prop_mod = info->prop_mod;
               old_change->copyfrom_rev = SVN_INVALID_REVNUM;
               old_change->copyfrom_path = NULL;
             }
@@ -735,72 +736,54 @@ fold_change(apr_hash_t *changes,
           /* An add at this point must be following a previous delete,
              so treat it just like a replace. */
           old_change->change_kind = svn_fs_path_change_replace;
-          old_change->node_rev_id = svn_fs_fs__id_copy(change->noderev_id,
+          old_change->node_rev_id = svn_fs_fs__id_copy(info->node_rev_id,
                                                        pool);
-          old_change->text_mod = change->text_mod;
-          old_change->prop_mod = change->prop_mod;
-          if (change->copyfrom_rev == SVN_INVALID_REVNUM)
+          old_change->text_mod = info->text_mod;
+          old_change->prop_mod = info->prop_mod;
+          if (info->copyfrom_rev == SVN_INVALID_REVNUM)
             {
               old_change->copyfrom_rev = SVN_INVALID_REVNUM;
               old_change->copyfrom_path = NULL;
             }
           else
             {
-              old_change->copyfrom_rev = change->copyfrom_rev;
+              old_change->copyfrom_rev = info->copyfrom_rev;
               old_change->copyfrom_path = apr_pstrdup(pool,
-                                                      change->copyfrom_path);
+                                                      info->copyfrom_path);
             }
           break;
 
         case svn_fs_path_change_modify:
         default:
-          if (change->text_mod)
+          if (info->text_mod)
             old_change->text_mod = TRUE;
-          if (change->prop_mod)
+          if (info->prop_mod)
             old_change->prop_mod = TRUE;
           break;
         }
 
-      /* Point our new_change to our (possibly modified) old_change. */
-      new_change = old_change;
+      /* remove old_change from the cache if it is no longer needed. */
+      if (old_change == NULL)
+        apr_hash_set(changes, path->data, path->len, NULL);
     }
   else
     {
       /* This change is new to the hash, so make a new public change
          structure from the internal one (in the hash's pool), and dup
          the path into the hash's pool, too. */
-      new_change = apr_pcalloc(pool, sizeof(*new_change));
-      new_change->node_rev_id = svn_fs_fs__id_copy(change->noderev_id, pool);
-      new_change->change_kind = change->kind;
-      new_change->text_mod = change->text_mod;
-      new_change->prop_mod = change->prop_mod;
-      /* In FSFS, copyfrom_known is *always* true, since we've always
-       * stored copyfroms in changed paths lists. */
-      new_change->copyfrom_known = TRUE;
-      if (change->copyfrom_rev != SVN_INVALID_REVNUM)
-        {
-          new_change->copyfrom_rev = change->copyfrom_rev;
-          new_change->copyfrom_path = apr_pstrdup(pool, change->copyfrom_path);
-        }
-      else
-        {
-          new_change->copyfrom_rev = SVN_INVALID_REVNUM;
-          new_change->copyfrom_path = NULL;
-        }
+      new_change = apr_pmemdup(pool, info, sizeof(*new_change));
+      new_change->node_rev_id = svn_fs_fs__id_copy(info->node_rev_id, pool);
+      if (info->copyfrom_path)
+        new_change->copyfrom_path = apr_pstrdup(pool, info->copyfrom_path);
+
+      /* Add this path.  The API makes no guarantees that this (new) key
+        will not be retained.  Thus, we copy the key into the target pool
+        to ensure a proper lifetime.  */
+      apr_hash_set(changes,
+                   apr_pstrmemdup(pool, path->data, path->len), path->len,
+                   new_change);
     }
 
-  if (new_change)
-    new_change->node_kind = change->node_kind;
-
-  /* Add (or update) this path.
-
-     Note: this key might already be present, and it would be nice to
-     re-use its value, but there is no way to fetch it. The API makes no
-     guarantees that this (new) key will not be retained. Thus, we (again)
-     copy the key into the target pool to ensure a proper lifetime.  */
-  path = apr_pstrmemdup(pool, change->path, path_len);
-  apr_hash_set(changes, path, path_len, new_change);
-
   return SVN_NO_ERROR;
 }
 
@@ -815,7 +798,6 @@ fold_change(apr_hash_t *changes,
 static svn_error_t *
 process_changes(apr_hash_t *changed_paths,
                 apr_array_header_t *changes,
-                svn_boolean_t prefolded,
                 apr_pool_t *pool)
 {
   apr_pool_t *iterpool = svn_pool_create(pool);
@@ -838,9 +820,8 @@ process_changes(apr_hash_t *changed_path
          is already a temporary subpool.
       */
 
-      if (((change->kind == svn_fs_path_change_delete)
-           || (change->kind == svn_fs_path_change_replace))
-          && ! prefolded)
+      if ((change->info.change_kind == svn_fs_path_change_delete)
+           || (change->info.change_kind == svn_fs_path_change_replace))
         {
           apr_hash_index_t *hi;
 
@@ -849,12 +830,12 @@ process_changes(apr_hash_t *changed_path
              Also, we should not assume that all paths have been normalized
              i.e. some might have trailing path separators.
           */
-          apr_ssize_t change_path_len = strlen(change->path);
-          apr_ssize_t min_child_len = change_path_len == 0
+          apr_ssize_t path_len = change->path.len;
+          apr_ssize_t min_child_len = path_len == 0
                                     ? 1
-                                    : change->path[change_path_len-1] == '/'
-                                        ? change_path_len + 1
-                                        : change_path_len + 2;
+                                    : change->path.data[path_len-1] == '/'
+                                        ? path_len + 1
+                                        : path_len + 2;
 
           /* CAUTION: This is the inner loop of an O(n^2) algorithm.
              The number of changes to process may be >> 1000.
@@ -874,13 +855,13 @@ process_changes(apr_hash_t *changed_path
                  this is actually a sub-path.
                */
               if (   klen >= min_child_len
-                  && svn_dirent_is_child(change->path, path, iterpool))
+                  && svn_dirent_is_child(change->path.data, path, iterpool))
                 apr_hash_set(changed_paths, path, klen, NULL);
             }
-        }
 
-      /* Clear the per-iteration subpool. */
-      svn_pool_clear(iterpool);
+          /* Clear the per-iteration subpool. */
+          svn_pool_clear(iterpool);
+        }
     }
 
   /* Destroy the per-iteration subpool. */
@@ -908,7 +889,7 @@ svn_fs_fs__txn_changes_fetch(apr_hash_t 
                                   svn_stream_from_aprfile2(file, TRUE,
                                                            scratch_pool),
                                   scratch_pool));
-  SVN_ERR(process_changes(changed_paths, changes, FALSE, pool));
+  SVN_ERR(process_changes(changed_paths, changes, pool));
   svn_pool_destroy(scratch_pool);
 
   *changed_paths_p = changed_paths;
@@ -925,14 +906,17 @@ svn_fs_fs__paths_changed(apr_hash_t **ch
 {
   apr_hash_t *changed_paths;
   apr_array_header_t *changes;
-  apr_pool_t *scratch_pool = svn_pool_create(pool);
+  int i;
 
-  SVN_ERR(svn_fs_fs__get_changes(&changes, fs, rev, scratch_pool));
+  SVN_ERR(svn_fs_fs__get_changes(&changes, fs, rev, pool));
 
   changed_paths = svn_hash__make(pool);
-
-  SVN_ERR(process_changes(changed_paths, changes, TRUE, pool));
-  svn_pool_destroy(scratch_pool);
+  for (i = 0; i < changes->nelts; ++i)
+    {
+      change_t *change = APR_ARRAY_IDX(changes, i, change_t *);
+      apr_hash_set(changed_paths, change->path.data, change->path.len,
+                   &change->info);
+    }
 
   *changed_paths_p = changed_paths;
 


Reply via email to