You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2015/10/26 09:43:08 UTC

svn commit: r1710531 [2/3] - in /subversion/branches/move-tracking-2: ./ build/ build/ac-macros/ subversion/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindings/swig/ subversion/bindings/s...

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/pack.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/pack.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/pack.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/pack.c Mon Oct 26 08:43:06 2015
@@ -106,9 +106,6 @@ typedef struct path_order_t
   /* when this change happened */
   svn_revnum_t revision;
 
-  /* this is a directory node */
-  svn_boolean_t is_dir;
-
   /* length of the expanded representation content */
   apr_int64_t expanded_size;
 
@@ -382,6 +379,8 @@ close_pack_context(pack_context_t *conte
   SVN_ERR(svn_io_remove_file2(proto_l2p_index_path, FALSE, scratch_pool));
   SVN_ERR(svn_io_remove_file2(proto_p2l_index_path, FALSE, scratch_pool));
 
+  /* Ensure that packed file is written to disk.*/
+  SVN_ERR(svn_io_file_flush_to_disk(context->pack_file, scratch_pool));
   SVN_ERR(svn_io_file_close(context->pack_file, scratch_pool));
 
   return SVN_NO_ERROR;
@@ -621,9 +620,6 @@ compare_dir_entries(const svn_sort__item
   const svn_fs_dirent_t *lhs = (const svn_fs_dirent_t *) a->value;
   const svn_fs_dirent_t *rhs = (const svn_fs_dirent_t *) b->value;
 
-  if (lhs->kind != rhs->kind)
-    return lhs->kind == svn_node_dir ? -1 : 1;
-
   return strcmp(lhs->name, rhs->name);
 }
 
@@ -740,7 +736,6 @@ copy_node_to_temp(pack_context_t *contex
   path_order->path = svn_prefix_string__create(context->paths, sort_path);
   path_order->node_id = noderev->node_id;
   path_order->revision = svn_fs_x__get_revnum(noderev->noderev_id.change_set);
-  path_order->is_dir = noderev->kind == svn_node_dir;
   path_order->noderev_id = noderev->noderev_id;
   APR_ARRAY_PUSH(context->path_order, path_order_t *) = path_order;
 
@@ -784,13 +779,8 @@ compare_path_order(const path_order_t *
   const path_order_t * lhs = *lhs_p;
   const path_order_t * rhs = *rhs_p;
 
-  /* cluster all directories */
-  int diff = rhs->is_dir - lhs->is_dir;
-  if (diff)
-    return diff;
-
   /* lexicographic order on path and node (i.e. latest first) */
-  diff = svn_prefix_string__compare(lhs->path, rhs->path);
+  int diff = svn_prefix_string__compare(lhs->path, rhs->path);
   if (diff)
     return diff;
 
@@ -2142,6 +2132,34 @@ pack_shard(const char *dir,
   return SVN_NO_ERROR;
 }
 
+/* Read the youngest rev and the first non-packed rev info for FS from disk.
+   Set *FULLY_PACKED when there is no completed unpacked shard.
+   Use SCRATCH_POOL for temporary allocations.
+ */
+static svn_error_t *
+get_pack_status(svn_boolean_t *fully_packed,
+                svn_fs_t *fs,
+                apr_pool_t *scratch_pool)
+{
+  svn_fs_x__data_t *ffd = fs->fsap_data;
+  apr_int64_t completed_shards;
+  svn_revnum_t youngest;
+
+  SVN_ERR(svn_fs_x__read_min_unpacked_rev(&ffd->min_unpacked_rev, fs,
+                                          scratch_pool));
+
+  SVN_ERR(svn_fs_x__youngest_rev(&youngest, fs, scratch_pool));
+  completed_shards = (youngest + 1) / ffd->max_files_per_dir;
+
+  /* See if we've already completed all possible shards thus far. */
+  if (ffd->min_unpacked_rev == (completed_shards * ffd->max_files_per_dir))
+    *fully_packed = TRUE;
+  else
+    *fully_packed = FALSE;
+
+  return SVN_NO_ERROR;
+}
+
 typedef struct pack_baton_t
 {
   svn_fs_t *fs;
@@ -2174,21 +2192,24 @@ pack_body(void *baton,
   svn_fs_x__data_t *ffd = pb->fs->fsap_data;
   apr_int64_t completed_shards;
   apr_int64_t i;
-  svn_revnum_t youngest;
   apr_pool_t *iterpool;
   const char *data_path;
+  svn_boolean_t fully_packed;
 
-  /* If we aren't using sharding, we can't do any packing, so quit. */
-  SVN_ERR(svn_fs_x__read_min_unpacked_rev(&ffd->min_unpacked_rev, pb->fs,
-                                          scratch_pool));
+  /* Since another process might have already packed the repo,
+     we need to re-read the pack status. */
+  SVN_ERR(get_pack_status(&fully_packed, pb->fs, scratch_pool));
+  if (fully_packed)
+    {
+      if (pb->notify_func)
+        (*pb->notify_func)(pb->notify_baton,
+                           ffd->min_unpacked_rev / ffd->max_files_per_dir,
+                           svn_fs_pack_notify_noop, scratch_pool);
 
-  SVN_ERR(svn_fs_x__youngest_rev(&youngest, pb->fs, scratch_pool));
-  completed_shards = (youngest + 1) / ffd->max_files_per_dir;
-
-  /* See if we've already completed all possible shards thus far. */
-  if (ffd->min_unpacked_rev == (completed_shards * ffd->max_files_per_dir))
-    return SVN_NO_ERROR;
+      return SVN_NO_ERROR;
+    }
 
+  completed_shards = (ffd->youngest_rev_cache + 1) / ffd->max_files_per_dir;
   data_path = svn_dirent_join(pb->fs->path, PATH_REVS_DIR, scratch_pool);
 
   iterpool = svn_pool_create(scratch_pool);
@@ -2224,6 +2245,23 @@ svn_fs_x__pack(svn_fs_t *fs,
                apr_pool_t *scratch_pool)
 {
   pack_baton_t pb = { 0 };
+  svn_boolean_t fully_packed;
+
+  /* Is there we even anything to do?. */
+  SVN_ERR(get_pack_status(&fully_packed, fs, scratch_pool));
+  if (fully_packed)
+    {
+      svn_fs_x__data_t *ffd = fs->fsap_data;
+
+      if (notify_func)
+        (*notify_func)(notify_baton,
+                       ffd->min_unpacked_rev / ffd->max_files_per_dir,
+                       svn_fs_pack_notify_noop, scratch_pool);
+
+      return SVN_NO_ERROR;
+    }
+
+  /* Lock the repo and start the pack process. */
   pb.fs = fs;
   pb.notify_func = notify_func;
   pb.notify_baton = notify_baton;

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/reps.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/reps.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/reps.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/reps.c Mon Oct 26 08:43:06 2015
@@ -417,8 +417,8 @@ svn_fs_x__reps_add_base(svn_fs_x__reps_b
   apr_size_t idx;
   SVN_ERR(svn_fs_x__get_contents(&stream, builder->fs, rep, FALSE,
                                  scratch_pool));
-  SVN_ERR(svn_string_from_stream(&contents, stream, scratch_pool,
-                                 scratch_pool));
+  SVN_ERR(svn_string_from_stream2(&contents, stream, SVN__STREAM_CHUNK_SIZE,
+                                  scratch_pool));
   SVN_ERR(svn_fs_x__reps_add(&idx, builder, contents));
 
   base.revision = svn_fs_x__get_revnum(rep->id.change_set);

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rev_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rev_file.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rev_file.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/rev_file.c Mon Oct 26 08:43:06 2015
@@ -331,7 +331,7 @@ auto_read_footer(svn_fs_x__revision_file
                                      &file->p2l_info.start,
                                      &file->p2l_info.checksum,
                                      footer, file->file_info.start_revision,
-                                     file->pool));
+                                     filesize - footer_length - 1, file->pool));
       file->l2p_info.end = file->p2l_info.start;
       file->p2l_info.end = filesize - footer_length - 1;
     }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/revprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/revprops.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/revprops.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/revprops.c Mon Oct 26 08:43:06 2015
@@ -407,8 +407,10 @@ parse_revprop(apr_hash_t **properties,
   svn_stream_t *stream = svn_stream_from_string(content, scratch_pool);
   *properties = apr_hash_make(result_pool);
 
-  SVN_ERR(svn_hash_read2(*properties, stream, SVN_HASH_TERMINATOR,
-                         result_pool));
+  SVN_ERR_W(svn_hash_read2(*properties, stream, SVN_HASH_TERMINATOR,
+                           result_pool),
+            apr_psprintf(scratch_pool, "Failed to parse revprops for r%ld.",
+                         revision));
   if (has_revprop_cache(fs, scratch_pool))
     {
       svn_fs_x__data_t *ffd = fs->fsap_data;
@@ -1313,16 +1315,14 @@ write_packed_revprop(const char **final_
       SVN_ERR(svn_io_open_unique_file3(&file, tmp_path, revprops->folder,
                                        svn_io_file_del_none, result_pool,
                                        scratch_pool));
-
+      stream = svn_stream_from_aprfile2(file, TRUE, scratch_pool);
       for (i = 0; i < revprops->manifest->nelts; ++i)
         {
           const char *filename = APR_ARRAY_IDX(revprops->manifest, i,
                                                const char*);
-          SVN_ERR(svn_io_file_write_full(file, filename, strlen(filename),
-                                         NULL, scratch_pool));
-          SVN_ERR(svn_io_file_putc('\n', file, scratch_pool));
+          SVN_ERR(svn_stream_printf(stream, scratch_pool, "%s\n", filename));
         }
-
+      SVN_ERR(svn_stream_close(stream));
       SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool));
       SVN_ERR(svn_io_file_close(file, scratch_pool));
     }
@@ -1500,7 +1500,6 @@ copy_revprops(svn_fs_t *fs,
   apr_file_t *pack_file;
   svn_revnum_t rev;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-  svn_stream_t *stream;
 
   /* create empty data buffer and a write stream on top of it */
   svn_stringbuf_t *uncompressed
@@ -1524,6 +1523,7 @@ copy_revprops(svn_fs_t *fs,
   for (rev = start_rev; rev <= end_rev; rev++)
     {
       const char *path;
+      svn_stream_t *stream;
 
       svn_pool_clear(iterpool);
 
@@ -1545,9 +1545,10 @@ copy_revprops(svn_fs_t *fs,
                         compressed, compression_level));
 
   /* write the pack file content to disk */
-  stream = svn_stream_from_aprfile2(pack_file, FALSE, scratch_pool);
-  SVN_ERR(svn_stream_write(stream, compressed->data, &compressed->len));
-  SVN_ERR(svn_stream_close(stream));
+  SVN_ERR(svn_io_file_write_full(pack_file, compressed->data, compressed->len,
+                                 NULL, scratch_pool));
+  SVN_ERR(svn_io_file_flush_to_disk(pack_file, scratch_pool));
+  SVN_ERR(svn_io_file_close(pack_file, scratch_pool));
 
   svn_pool_destroy(iterpool);
 
@@ -1567,6 +1568,7 @@ svn_fs_x__pack_revprops_shard(svn_fs_t *
                               apr_pool_t *scratch_pool)
 {
   const char *manifest_file_path, *pack_filename = NULL;
+  apr_file_t *manifest_file;
   svn_stream_t *manifest_stream;
   svn_revnum_t start_rev, end_rev, rev;
   apr_off_t total_size;
@@ -1578,8 +1580,12 @@ svn_fs_x__pack_revprops_shard(svn_fs_t *
                                        scratch_pool);
 
   /* Create the manifest file stream. */
-  SVN_ERR(svn_stream_open_writable(&manifest_stream, manifest_file_path,
-                                   scratch_pool, scratch_pool));
+
+  SVN_ERR(svn_io_file_open(&manifest_file, manifest_file_path,
+                           APR_WRITE | APR_BUFFERED | APR_CREATE | APR_EXCL,
+                           APR_OS_DEFAULT, scratch_pool));
+  manifest_stream = svn_stream_from_aprfile2(manifest_file, TRUE,
+                                             scratch_pool);
 
   /* revisions to handle. Special case: revision 0 */
   start_rev = (svn_revnum_t) (shard * max_files_per_dir);
@@ -1653,8 +1659,10 @@ svn_fs_x__pack_revprops_shard(svn_fs_t *
                           (apr_size_t)total_size, compression_level,
                           cancel_func, cancel_baton, iterpool));
 
-  /* flush the manifest file and update permissions */
+  /* flush the manifest file to disk and update permissions */
   SVN_ERR(svn_stream_close(manifest_stream));
+  SVN_ERR(svn_io_file_flush_to_disk(manifest_file, iterpool));
+  SVN_ERR(svn_io_file_close(manifest_file, iterpool));
   SVN_ERR(svn_io_copy_perms(shard_path, pack_file_dir, iterpool));
 
   svn_pool_destroy(iterpool);

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/temp_serializer.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/temp_serializer.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/temp_serializer.c Mon Oct 26 08:43:06 2015
@@ -190,6 +190,10 @@ typedef struct dir_data_t
    * (it's int because the directory is an APR array) */
   int count;
 
+  /** Current length of the in-txn in-disk representation of the directory.
+   * SVN_INVALID_FILESIZE if unknown (i.e. committed data). */
+  svn_filesize_t txn_filesize;
+
   /* number of unused dir entry buckets in the index */
   apr_size_t over_provision;
 
@@ -234,18 +238,19 @@ serialize_dir_entry(svn_temp_serializer_
   svn_temp_serializer__pop(context);
 }
 
-/* Utility function to serialize the ENTRIES into a new serialization
+/* Utility function to serialize the DIR into a new serialization
  * context to be returned.
  *
  * Temporary allocation will be made form SCRATCH_POOL.
  */
 static svn_temp_serializer__context_t *
-serialize_dir(apr_array_header_t *entries,
+serialize_dir(svn_fs_x__dir_data_t *dir,
               apr_pool_t *scratch_pool)
 {
   dir_data_t dir_data;
   int i = 0;
   svn_temp_serializer__context_t *context;
+  apr_array_header_t *entries = dir->entries;
 
   /* calculate sizes */
   int count = entries->nelts;
@@ -256,6 +261,7 @@ serialize_dir(apr_array_header_t *entrie
 
   /* copy the hash entries to an auxiliary struct of known layout */
   dir_data.count = count;
+  dir_data.txn_filesize = dir->txn_filesize;
   dir_data.over_provision = over_provision;
   dir_data.operations = 0;
   dir_data.entries = apr_palloc(scratch_pool, entries_len);
@@ -292,26 +298,32 @@ serialize_dir(apr_array_header_t *entrie
   return context;
 }
 
-/* Utility function to reconstruct a dir entries array from serialized data
+/* Utility function to reconstruct a dir entries struct from serialized data
  * in BUFFER and DIR_DATA. Allocation will be made form RESULT_POOL.
  */
-static apr_array_header_t *
+static svn_fs_x__dir_data_t *
 deserialize_dir(void *buffer,
                 dir_data_t *dir_data,
                 apr_pool_t *result_pool)
 {
-  apr_array_header_t *result = apr_array_make(result_pool, dir_data->count,
-                                              sizeof(svn_fs_x__dirent_t *));
+  svn_fs_x__dir_data_t *result;
   apr_size_t i;
   apr_size_t count;
   svn_fs_x__dirent_t *entry;
   svn_fs_x__dirent_t **entries;
 
+  /* Construct empty directory object. */
+  result = apr_pcalloc(result_pool, sizeof(*result));
+  result->entries
+    = apr_array_make(result_pool, dir_data->count,
+                     sizeof(svn_fs_x__dirent_t *));
+  result->txn_filesize = dir_data->txn_filesize;
+
   /* resolve the reference to the entries array */
   svn_temp_deserializer__resolve(buffer, (void **)&dir_data->entries);
   entries = dir_data->entries;
 
-  /* fixup the references within each entry and add it to the hash */
+  /* fixup the references within each entry and add it to the RESULT */
   for (i = 0, count = dir_data->count; i < count; ++i)
     {
       svn_temp_deserializer__resolve(entries, (void **)&entries[i]);
@@ -321,7 +333,7 @@ deserialize_dir(void *buffer,
       svn_temp_deserializer__resolve(entry, (void **)&entry->name);
 
       /* add the entry to the hash */
-      APR_ARRAY_PUSH(result, svn_fs_x__dirent_t *) = entry;
+      APR_ARRAY_PUSH(result->entries, svn_fs_x__dirent_t *) = entry;
     }
 
   /* return the now complete hash */
@@ -553,7 +565,7 @@ svn_fs_x__serialize_properties(void **da
   /* create our auxiliary data structure */
   properties.count = apr_hash_count(hash);
   properties.keys = apr_palloc(pool, sizeof(const char*) * (properties.count + 1));
-  properties.values = apr_palloc(pool, sizeof(const char*) * properties.count);
+  properties.values = apr_palloc(pool, sizeof(const svn_string_t *) * properties.count);
 
   /* populate it with the hash entries */
   for (hi = apr_hash_first(pool, hash), i=0; hi; hi = apr_hash_next(hi), ++i)
@@ -684,7 +696,7 @@ svn_fs_x__serialize_dir_entries(void **d
                                 void *in,
                                 apr_pool_t *pool)
 {
-  apr_array_header_t *dir = in;
+  svn_fs_x__dir_data_t *dir = in;
 
   /* serialize the dir content into a new serialization context
    * and return the serialized data */
@@ -723,6 +735,20 @@ svn_fs_x__get_sharded_offset(void **out,
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_fs_x__extract_dir_filesize(void **out,
+                               const void *data,
+                               apr_size_t data_len,
+                               void *baton,
+                               apr_pool_t *pool)
+{
+  const dir_data_t *dir_data = data;
+
+  *(svn_filesize_t *)out = dir_data->txn_filesize;
+
+  return SVN_NO_ERROR;
+}
+
 /* Utility function that returns the lowest index of the first entry in
  * *ENTRIES that points to a dir entry with a name equal or larger than NAME.
  * If an exact match has been found, *FOUND will be set to TRUE. COUNT is
@@ -832,8 +858,9 @@ svn_fs_x__extract_dir_entry(void **out,
   if (found)
     b->hint = pos;
 
-  /* de-serialize that entry or return NULL, if no match has been found */
-  if (found)
+  /* de-serialize that entry or return NULL, if no match has been found.
+   * Be sure to check that the directory contents is still up-to-date. */
+  if (found && dir_data->txn_filesize == b->txn_filesize)
     {
       const svn_fs_x__dirent_t *source =
           svn_temp_deserializer__ptr(entries, (const void *const *)&entries[pos]);
@@ -846,8 +873,7 @@ svn_fs_x__extract_dir_entry(void **out,
       apr_size_t size = lengths[pos];
 
       /* copy & deserialize the entry */
-      svn_fs_x__dirent_t *new_entry = apr_palloc(pool, size);
-      memcpy(new_entry, source, size);
+      svn_fs_x__dirent_t *new_entry = apr_pmemdup(pool, source, size);
 
       svn_temp_deserializer__resolve(new_entry, (void **)&new_entry->name);
       *(svn_fs_x__dirent_t **)out = new_entry;
@@ -867,32 +893,34 @@ slowly_replace_dir_entry(void **data,
 {
   replace_baton_t *replace_baton = (replace_baton_t *)baton;
   dir_data_t *dir_data = (dir_data_t *)*data;
-  apr_array_header_t *dir;
+  svn_fs_x__dir_data_t *dir;
   int idx = -1;
   svn_fs_x__dirent_t *entry;
+  apr_array_header_t *entries;
 
   SVN_ERR(svn_fs_x__deserialize_dir_entries((void **)&dir,
                                             *data,
                                             dir_data->len,
                                             pool));
 
-  entry = svn_fs_x__find_dir_entry(dir, replace_baton->name, &idx);
+  entries = dir->entries;
+  entry = svn_fs_x__find_dir_entry(entries, replace_baton->name, &idx);
 
   /* Replacement or removal? */
   if (replace_baton->new_entry)
     {
       /* Replace ENTRY with / insert the NEW_ENTRY */
       if (entry)
-        APR_ARRAY_IDX(dir, idx, svn_fs_x__dirent_t *)
+        APR_ARRAY_IDX(entries, idx, svn_fs_x__dirent_t *)
           = replace_baton->new_entry;
       else
-        svn_sort__array_insert(dir, &replace_baton->new_entry, idx);
+        svn_sort__array_insert(entries, &replace_baton->new_entry, idx);
     }
   else
     {
       /* Remove the old ENTRY. */
       if (entry)
-        svn_sort__array_delete(dir, idx, 1);
+        svn_sort__array_delete(entries, idx, 1);
     }
 
   return svn_fs_x__serialize_dir_entries(data, data_len, dir, pool);
@@ -914,6 +942,12 @@ svn_fs_x__replace_dir_entry(void **data,
 
   svn_temp_serializer__context_t *context;
 
+  /* update the cached file length info.
+   * Because we are writing to the cache, it is fair to assume that the
+   * caller made sure that the current contents is consistent with the
+   * previous state of the directory file. */
+  dir_data->txn_filesize = replace_baton->txn_filesize;
+
   /* after quite a number of operations, let's re-pack everything.
    * This is to limit the number of wasted space as we cannot overwrite
    * existing data but must always append. */
@@ -1002,6 +1036,18 @@ svn_fs_x__replace_dir_entry(void **data,
 
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_fs_x__reset_txn_filesize(void **data,
+                             apr_size_t *data_len,
+                             void *baton,
+                             apr_pool_t *pool)
+{
+  dir_data_t *dir_data = (dir_data_t *)*data;
+  dir_data->txn_filesize = SVN_INVALID_FILESIZE;
+
+  return SVN_NO_ERROR;
+}
 
 svn_error_t  *
 svn_fs_x__serialize_rep_header(void **data,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/temp_serializer.h?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/temp_serializer.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/temp_serializer.h Mon Oct 26 08:43:06 2015
@@ -129,7 +129,7 @@ svn_fs_x__deserialize_node_revision(void
                                     apr_pool_t *result_pool);
 
 /**
- * Implements #svn_cache__serialize_func_t for a directory contents array
+ * Implements #svn_cache__serialize_func_t for a #svn_fs_x__dir_data_t
  */
 svn_error_t *
 svn_fs_x__serialize_dir_entries(void **data,
@@ -138,7 +138,7 @@ svn_fs_x__serialize_dir_entries(void **d
                                 apr_pool_t *pool);
 
 /**
- * Implements #svn_cache__deserialize_func_t for a directory contents array
+ * Implements #svn_cache__deserialize_func_t for a #svn_fs_x__dir_data_t
  */
 svn_error_t *
 svn_fs_x__deserialize_dir_entries(void **out,
@@ -158,6 +158,18 @@ svn_fs_x__get_sharded_offset(void **out,
                              apr_pool_t *pool);
 
 /**
+ * Implements #svn_cache__partial_getter_func_t.
+ * Set (svn_filesize_t) @a *out to the filesize info stored with the
+ * serialized directory in @a data of @a data_len.  @a baton is unused.
+ */
+svn_error_t *
+svn_fs_x__extract_dir_filesize(void **out,
+                               const void *data,
+                               apr_size_t data_len,
+                               void *baton,
+                               apr_pool_t *pool);
+
+/**
  * Baton type to be used with svn_fs_x__extract_dir_entry. */
 typedef struct svn_fs_x__ede_baton_t
 {
@@ -166,12 +178,18 @@ typedef struct svn_fs_x__ede_baton_t
 
   /* Lookup hint [in / out] */
   apr_size_t hint;
+
+  /** Current length of the in-txn in-disk representation of the directory.
+   * SVN_INVALID_FILESIZE if unknown. */
+  svn_filesize_t txn_filesize;
 } svn_fs_x__ede_baton_t;
 
 /**
  * Implements #svn_cache__partial_getter_func_t for a single
  * #svn_fs_x__dirent_t within a serialized directory contents hash,
- * identified by its name (given in @a svn_fs_x__ede_baton_t @a *baton).
+ * identified by its name (in (svn_fs_x__ede_baton_t *) @a *baton).
+ * If the filesize specified in the baton does not match the cached
+ * value for this directory, @a *out will be NULL as well.
  */
 svn_error_t *
 svn_fs_x__extract_dir_entry(void **out,
@@ -184,7 +202,10 @@ svn_fs_x__extract_dir_entry(void **out,
  * Describes the change to be done to a directory: Set the entry
  * identify by @a name to the value @a new_entry. If the latter is
  * @c NULL, the entry shall be removed if it exists. Otherwise it
- * will be replaced or automatically added, respectively.
+ * will be replaced or automatically added, respectively.  The
+ * @a filesize allows readers to identify stale cache data (e.g.
+ * due to concurrent access to txns); writers use it to update the
+ * cached file size info.
  */
 typedef struct replace_baton_t
 {
@@ -193,6 +214,10 @@ typedef struct replace_baton_t
 
   /** directory entry to insert instead */
   svn_fs_x__dirent_t *new_entry;
+
+  /** Current length of the in-txn in-disk representation of the directory.
+   * SVN_INVALID_FILESIZE if unknown. */
+  svn_filesize_t txn_filesize;
 } replace_baton_t;
 
 /**
@@ -207,6 +232,17 @@ svn_fs_x__replace_dir_entry(void **data,
                             apr_pool_t *pool);
 
 /**
+ * Implements #svn_cache__partial_setter_func_t for a #svn_fs_x__dir_data_t
+ * at @a *data, resetting its txn_filesize field to SVN_INVALID_FILESIZE.
+ * &a baton should be NULL.
+ */
+svn_error_t *
+svn_fs_x__reset_txn_filesize(void **data,
+                             apr_size_t *data_len,
+                             void *baton,
+                             apr_pool_t *pool);
+
+/**
  * Implements #svn_cache__serialize_func_t for a #svn_fs_x__rep_header_t.
  */
 svn_error_t *

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/transaction.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/transaction.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/transaction.c Mon Oct 26 08:43:06 2015
@@ -25,6 +25,7 @@
 #include <assert.h>
 #include <apr_sha1.h>
 
+#include "svn_error_codes.h"
 #include "svn_hash.h"
 #include "svn_props.h"
 #include "svn_sorts.h"
@@ -280,17 +281,33 @@ with_some_lock_file(with_lock_baton_t *b
           ffd->has_write_lock = TRUE;
         }
 
-      /* nobody else will modify the repo state
-         => read HEAD & pack info once */
       if (baton->is_inner_most_lock)
         {
-          err = svn_fs_x__update_min_unpacked_rev(fs, pool);
+          /* Use a separate sub-pool for the actual function body and a few
+           * file accesses. So, the lock-pool only contains the file locks.
+           */
+          apr_pool_t *subpool = svn_pool_create(pool);
+
+          /* nobody else will modify the repo state
+             => read HEAD & pack info once */
+          err = svn_fs_x__update_min_unpacked_rev(fs, subpool);
           if (!err)
-            err = svn_fs_x__youngest_rev(&ffd->youngest_rev_cache, fs, pool);
-        }
+            err = svn_fs_x__youngest_rev(&ffd->youngest_rev_cache, fs,
+                                         subpool);
+
+          /* We performed a few file operations. Clean the pool. */
+          svn_pool_clear(subpool);
 
-      if (!err)
-        err = baton->body(baton->baton, pool);
+          if (!err)
+            err = baton->body(baton->baton, subpool);
+
+          svn_pool_destroy(subpool);
+        }
+      else
+        {
+          /* Nested lock level */
+          err = baton->body(baton->baton, pool);
+        }
     }
 
   if (baton->is_outer_most_lock)
@@ -859,16 +876,63 @@ unparse_dir_entry(svn_fs_x__dirent_t *di
                   svn_stream_t *stream,
                   apr_pool_t *scratch_pool)
 {
-  const char *val
-    = apr_psprintf(scratch_pool, "%s %s",
-                   (dirent->kind == svn_node_file) ? SVN_FS_X__KIND_FILE
-                                                   : SVN_FS_X__KIND_DIR,
-                   svn_fs_x__id_unparse(&dirent->id, scratch_pool)->data);
-
-  SVN_ERR(svn_stream_printf(stream, scratch_pool, "K %" APR_SIZE_T_FMT
-                            "\n%s\nV %" APR_SIZE_T_FMT "\n%s\n",
-                            strlen(dirent->name), dirent->name,
-                            strlen(val), val));
+  apr_size_t to_write;
+  svn_string_t *id_str = svn_fs_x__id_unparse(&dirent->id, scratch_pool);
+  apr_size_t name_len = strlen(dirent->name);
+
+  /* Note that sizeof == len + 1, i.e. accounts for the space between
+   * type and ID. */
+  apr_size_t type_len = (dirent->kind == svn_node_file)
+                      ? sizeof(SVN_FS_X__KIND_FILE)
+                      : sizeof(SVN_FS_X__KIND_DIR);
+  apr_size_t value_len = type_len + id_str->len;
+
+  /* A buffer with sufficient space for 
+   * - both string lines
+   * - 4 newlines
+   * - 2 lines K/V lines containing a number each
+   */
+  char *buffer = apr_palloc(scratch_pool,   name_len + value_len
+                                          + 4
+                                          + 2 * (2 + SVN_INT64_BUFFER_SIZE));
+
+  /* Now construct the value. */
+  char *p = buffer;
+
+  /* The "K length(name)\n" line. */
+  p[0] = 'K';
+  p[1] = ' ';
+  p += 2;
+  p += svn__i64toa(p, name_len);
+  *(p++) = '\n';
+
+  /* The line with the key, i.e. dir entry name. */
+  memcpy(p, dirent->name, name_len);
+  p += name_len;
+  *(p++) = '\n';
+
+  /* The "V length(type+id)\n" line. */
+  p[0] = 'V';
+  p[1] = ' ';
+  p += 2;
+  p += svn__i64toa(p, value_len);
+  *(p++) = '\n';
+
+  /* The line with the type and ID. */
+  memcpy(p,
+         (dirent->kind == svn_node_file) ? SVN_FS_X__KIND_FILE
+                                         : SVN_FS_X__KIND_DIR,
+         type_len - 1);
+  p += type_len - 1;
+  *(p++) = ' ';
+  memcpy(p, id_str->data, id_str->len);
+  p+=id_str->len;
+  *(p++) = '\n';
+
+  /* Add the entry to the output stream. */
+  to_write = p - buffer;
+  SVN_ERR(svn_stream_write(stream, buffer, &to_write));
+
   return SVN_NO_ERROR;
 }
 
@@ -1371,6 +1435,7 @@ get_txn_proplist(apr_hash_t *proplist,
                  apr_pool_t *scratch_pool)
 {
   svn_stream_t *stream;
+  svn_error_t *err;
 
   /* Check for issue #3696. (When we find and fix the cause, we can change
    * this to an assertion.) */
@@ -1386,8 +1451,15 @@ get_txn_proplist(apr_hash_t *proplist,
                                    scratch_pool, scratch_pool));
 
   /* Read in the property list. */
-  SVN_ERR(svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR,
-                         scratch_pool));
+  err = svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR,
+                       scratch_pool);
+  if (err)
+    {
+      err = svn_error_compose_create(err, svn_stream_close(stream));
+      return svn_error_quick_wrapf(err,
+               _("malformed property list in transaction '%s'"),
+               svn_fs_x__path_txn_props(fs, txn_id, scratch_pool));
+    }
 
   return svn_stream_close(stream);
 }
@@ -1446,11 +1518,12 @@ svn_fs_x__change_txn_props(svn_fs_txn_t
                            apr_pool_t *scratch_pool)
 {
   fs_txn_data_t *ftd = txn->fsap_data;
-  apr_hash_t *txn_prop = apr_hash_make(scratch_pool);
+  apr_pool_t *subpool = svn_pool_create(scratch_pool);
+  apr_hash_t *txn_prop = apr_hash_make(subpool);
   int i;
   svn_error_t *err;
 
-  err = get_txn_proplist(txn_prop, txn->fs, ftd->txn_id, scratch_pool);
+  err = get_txn_proplist(txn_prop, txn->fs, ftd->txn_id, subpool);
   /* 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
@@ -1467,15 +1540,16 @@ svn_fs_x__change_txn_props(svn_fs_txn_t
       if (svn_hash_gets(txn_prop, SVN_FS__PROP_TXN_CLIENT_DATE)
           && !strcmp(prop->name, SVN_PROP_REVISION_DATE))
         svn_hash_sets(txn_prop, SVN_FS__PROP_TXN_CLIENT_DATE,
-                      svn_string_create("1", scratch_pool));
+                      svn_string_create("1", subpool));
 
       svn_hash_sets(txn_prop, prop->name, prop->value);
     }
 
   /* Create a new version of the file and write out the new props. */
   /* Open the transaction properties file. */
-  SVN_ERR(set_txn_proplist(txn->fs, ftd->txn_id, txn_prop, scratch_pool));
+  SVN_ERR(set_txn_proplist(txn->fs, ftd->txn_id, txn_prop, subpool));
 
+  svn_pool_destroy(subpool);
   return SVN_NO_ERROR;
 }
 
@@ -1783,12 +1857,15 @@ svn_fs_x__set_entry(svn_fs_t *fs,
                                        scratch_pool, scratch_pool);
   apr_file_t *file;
   svn_stream_t *out;
+  svn_filesize_t filesize;
   svn_fs_x__data_t *ffd = fs->fsap_data;
   apr_pool_t *subpool = svn_pool_create(scratch_pool);
+  const svn_fs_x__id_t *key = &(parent_noderev->noderev_id);
 
   if (!rep || !svn_fs_x__is_txn(rep->id.change_set))
     {
       apr_array_header_t *entries;
+      svn_fs_x__dir_data_t dir_data;
 
       /* Before we can modify the directory, we need to dump its old
          contents into a mutable representation file. */
@@ -1800,8 +1877,6 @@ svn_fs_x__set_entry(svn_fs_t *fs,
       out = svn_stream_from_aprfile2(file, TRUE, scratch_pool);
       SVN_ERR(unparse_dir_entries(entries, out, subpool));
 
-      svn_pool_clear(subpool);
-
       /* Provide the parent with a data rep if it had none before
          (directories so far empty). */
       if (!rep)
@@ -1816,23 +1891,90 @@ svn_fs_x__set_entry(svn_fs_t *fs,
 
       /* Save noderev to disk. */
       SVN_ERR(svn_fs_x__put_node_revision(fs, parent_noderev, subpool));
+
+      /* Immediately populate the txn dir cache to avoid re-reading
+       * the file we just wrote. */
+
+      /* Flush APR buffers. */
+      SVN_ERR(svn_io_file_flush(file, subpool));
+
+      /* Obtain final file size to update txn_dir_cache. */
+      SVN_ERR(svn_io_file_size_get(&filesize, file, subpool));
+
+      /* Store in the cache. */
+      dir_data.entries = entries;
+      dir_data.txn_filesize = filesize;
+      SVN_ERR(svn_cache__set(ffd->dir_cache, key, &dir_data, subpool));
+
+      svn_pool_clear(subpool);
     }
   else
     {
+      svn_boolean_t found;
+      svn_filesize_t cached_filesize;
+
       /* The directory rep is already mutable, so just open it for append. */
       SVN_ERR(svn_io_file_open(&file, filename, APR_WRITE | APR_APPEND,
-                               APR_OS_DEFAULT, scratch_pool));
-      out = svn_stream_from_aprfile2(file, TRUE, scratch_pool);
+                               APR_OS_DEFAULT, subpool));
+      out = svn_stream_from_aprfile2(file, TRUE, subpool);
+
+      /* If the cache contents is stale, drop it.
+       *
+       * Note that the directory file is append-only, i.e. if the size
+       * did not change, the contents didn't either. */
+
+      /* Get the file size that corresponds to the cached contents
+       * (if any). */
+      SVN_ERR(svn_cache__get_partial((void **)&cached_filesize, &found,
+                                     ffd->dir_cache, key,
+                                     svn_fs_x__extract_dir_filesize,
+                                     NULL, subpool));
+
+      /* File size info still matches?
+       * If not, we need to drop the cache entry. */
+      if (found)
+        {
+          SVN_ERR(svn_io_file_size_get(&filesize, file, subpool));
+
+          if (cached_filesize != filesize)
+            SVN_ERR(svn_cache__set(ffd->dir_cache, key, NULL, subpool));
+        }
+    }
+
+  /* Append an incremental hash entry for the entry change. */
+  if (id)
+    {
+      svn_fs_x__dirent_t entry;
+      entry.name = name;
+      entry.id = *id;
+      entry.kind = kind;
+
+      SVN_ERR(unparse_dir_entry(&entry, out, subpool));
     }
+  else
+    {
+      SVN_ERR(svn_stream_printf(out, subpool, "D %" APR_SIZE_T_FMT "\n%s\n",
+                                strlen(name), name));
+    }
+
+  /* Flush APR buffers. */
+  SVN_ERR(svn_io_file_flush(file, subpool));
+
+  /* Obtain final file size to update txn_dir_cache. */
+  SVN_ERR(svn_io_file_size_get(&filesize, file, subpool));
+
+  /* Close file. */
+  SVN_ERR(svn_io_file_close(file, subpool));
+  svn_pool_clear(subpool);
 
   /* update directory cache */
     {
-      /* build parameters: (name, new entry) pair */
-      const svn_fs_x__id_t *key = &(parent_noderev->noderev_id);
+      /* build parameters: name, new entry, new file size  */
       replace_baton_t baton;
 
       baton.name = name;
       baton.new_entry = NULL;
+      baton.txn_filesize = filesize;
 
       if (id)
         {
@@ -1847,25 +1989,7 @@ svn_fs_x__set_entry(svn_fs_t *fs,
                                      svn_fs_x__replace_dir_entry, &baton,
                                      subpool));
     }
-  svn_pool_clear(subpool);
-
-  /* Append an incremental hash entry for the entry change. */
-  if (id)
-    {
-      svn_fs_x__dirent_t entry;
-      entry.name = name;
-      entry.id = *id;
-      entry.kind = kind;
-
-      SVN_ERR(unparse_dir_entry(&entry, out, subpool));
-    }
-  else
-    {
-      SVN_ERR(svn_stream_printf(out, subpool, "D %" APR_SIZE_T_FMT "\n%s\n",
-                                strlen(name), name));
-    }
 
-  SVN_ERR(svn_io_file_close(file, subpool));
   svn_pool_destroy(subpool);
   return SVN_NO_ERROR;
 }
@@ -2269,7 +2393,7 @@ rep_write_get_baton(rep_write_baton_t **
 }
 
 /* For REP->SHA1_CHECKSUM, try to find an already existing representation
-   in FS and return it in *OUT_REP.  If no such representation exists or
+   in FS and return it in *OLD_REP.  If no such representation exists or
    if rep sharing has been disabled for FS, NULL will be returned.  Since
    there may be new duplicate representations within the same uncommitted
    revision, those can be passed in REPS_HASH (maps a sha1 digest onto
@@ -2293,9 +2417,13 @@ get_shared_rep(svn_fs_x__representation_
   if (!ffd->rep_sharing_allowed)
     return SVN_NO_ERROR;
 
+  /* Can't look up if we don't know the key (happens for directories). */
+  if (!rep->has_sha1)
+    return SVN_NO_ERROR;
+
   /* Check and see if we already have a representation somewhere that's
      identical to the one we just wrote out.  Start with the hash lookup
-     because it is cheepest. */
+     because it is cheapest. */
   if (reps_hash)
     *old_rep = apr_hash_get(reps_hash,
                             rep->sha1_digest,
@@ -2365,10 +2493,46 @@ get_shared_rep(svn_fs_x__representation_
         }
     }
 
-  /* Add information that is missing in the cached data. */
-  if (*old_rep)
+  if (!*old_rep)
+    return SVN_NO_ERROR;
+
+  /* A simple guard against general rep-cache induced corruption. */
+  if ((*old_rep)->expanded_size != rep->expanded_size)
     {
-      /* Use the old rep for this content. */
+      /* Make the problem show up in the server log.
+
+         Because not sharing reps is always a safe option,
+         terminating the request would be inappropriate.
+       */
+      svn_checksum_t checksum;
+      checksum.digest = rep->sha1_digest;
+      checksum.kind = svn_checksum_sha1;
+
+      err = svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                              "Rep size %s mismatches rep-cache.db value %s "
+                              "for SHA1 %s.\n"
+                              "You should delete the rep-cache.db and "
+                              "verify the repository. The cached rep will "
+                              "not be shared.",
+                              apr_psprintf(scratch_pool,
+                                           "%" SVN_FILESIZE_T_FMT,
+                                           rep->expanded_size),
+                              apr_psprintf(scratch_pool,
+                                           "%" SVN_FILESIZE_T_FMT,
+                                           (*old_rep)->expanded_size),
+                              svn_checksum_to_cstring_display(&checksum,
+                                                              scratch_pool));
+
+      (fs->warning)(fs->warning_baton, err);
+      svn_error_clear(err);
+
+      /* Ignore the shared rep. */
+      *old_rep = NULL;
+    }
+  else
+    {
+      /* Add information that is missing in the cached data.
+         Use the old rep for this content. */
       memcpy((*old_rep)->md5_digest, rep->md5_digest, sizeof(rep->md5_digest));
     }
 
@@ -2376,6 +2540,7 @@ get_shared_rep(svn_fs_x__representation_
 }
 
 /* Copy the hash sum calculation results from MD5_CTX, SHA1_CTX into REP.
+ * SHA1 results are only be set if SHA1_CTX is not NULL.
  * Use SCRATCH_POOL for temporary allocations.
  */
 static svn_error_t *
@@ -2388,10 +2553,12 @@ digests_final(svn_fs_x__representation_t
 
   SVN_ERR(svn_checksum_final(&checksum, md5_ctx, scratch_pool));
   memcpy(rep->md5_digest, checksum->digest, svn_checksum_size(checksum));
-  SVN_ERR(svn_checksum_final(&checksum, sha1_ctx, scratch_pool));
-  rep->has_sha1 = checksum != NULL;
+  rep->has_sha1 = sha1_ctx != NULL;
   if (rep->has_sha1)
-    memcpy(rep->sha1_digest, checksum->digest, svn_checksum_size(checksum));
+    {
+      SVN_ERR(svn_checksum_final(&checksum, sha1_ctx, scratch_pool));
+      memcpy(rep->sha1_digest, checksum->digest, svn_checksum_size(checksum));
+    }
 
   return SVN_NO_ERROR;
 }
@@ -2595,6 +2762,8 @@ typedef struct write_container_baton_t
   apr_size_t size;
 
   svn_checksum_ctx_t *md5_ctx;
+
+  /* SHA1 calculation is optional. If not needed, this will be NULL. */
   svn_checksum_ctx_t *sha1_ctx;
 } write_container_baton_t;
 
@@ -2609,7 +2778,8 @@ write_container_handler(void *baton,
   write_container_baton_t *whb = baton;
 
   SVN_ERR(svn_checksum_update(whb->md5_ctx, data, *len));
-  SVN_ERR(svn_checksum_update(whb->sha1_ctx, data, *len));
+  if (whb->sha1_ctx)
+    SVN_ERR(svn_checksum_update(whb->sha1_ctx, data, *len));
 
   SVN_ERR(svn_stream_write(whb->stream, data, len));
   whb->size += *len;
@@ -2739,7 +2909,8 @@ write_container_delta_rep(svn_fs_x__repr
                                         scratch_pool);
   whb->size = 0;
   whb->md5_ctx = svn_checksum_ctx_create(svn_checksum_md5, scratch_pool);
-  whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, scratch_pool);
+  if (item_type != SVN_FS_X__ITEM_TYPE_DIR_REP)
+    whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, scratch_pool);
 
   /* serialize the hash */
   stream = svn_stream_create(whb, scratch_pool);
@@ -2750,6 +2921,7 @@ write_container_delta_rep(svn_fs_x__repr
 
   /* Store the results. */
   SVN_ERR(digests_final(rep, whb->md5_ctx, whb->sha1_ctx, scratch_pool));
+  rep->expanded_size = whb->size;
 
   /* Check and see if we already have a representation somewhere that's
      identical to the one we just wrote out. */
@@ -2793,7 +2965,6 @@ write_container_delta_rep(svn_fs_x__repr
       SVN_ERR(store_p2l_index_entry(fs, txn_id, &entry, scratch_pool));
 
       /* update the representation */
-      rep->expanded_size = whb->size;
       rep->size = rep_end - delta_start;
     }
 
@@ -2884,6 +3055,9 @@ get_final_id(svn_fs_x__id_t *part,
    INITIAL_OFFSET is the offset of the proto-rev-file on entry to
    commit_body.
 
+   Collect the pair_cache_key_t of all directories written to the
+   committed cache in DIRECTORY_IDS.
+
    If REPS_TO_CACHE is not NULL, append to it a copy (allocated in
    REPS_POOL) of each data rep that is new in this revision.
 
@@ -2903,6 +3077,7 @@ write_final_rev(svn_fs_x__id_t *new_id_p
                 svn_fs_t *fs,
                 const svn_fs_x__id_t *id,
                 apr_off_t initial_offset,
+                apr_array_header_t *directory_ids,
                 apr_array_header_t *reps_to_cache,
                 apr_hash_t *reps_hash,
                 apr_pool_t *reps_pool,
@@ -2947,7 +3122,8 @@ write_final_rev(svn_fs_x__id_t *new_id_p
 
           svn_pool_clear(subpool);
           SVN_ERR(write_final_rev(&new_id, file, rev, fs, &dirent->id,
-                                  initial_offset, reps_to_cache, reps_hash,
+                                  initial_offset, directory_ids,
+                                  reps_to_cache, reps_hash,
                                   reps_pool, FALSE, subpool));
           if (   svn_fs_x__id_used(&new_id)
               && (svn_fs_x__get_revnum(new_id.change_set) == rev))
@@ -2957,6 +3133,9 @@ write_final_rev(svn_fs_x__id_t *new_id_p
       if (noderev->data_rep
           && ! svn_fs_x__is_revision(noderev->data_rep->id.change_set))
         {
+          svn_fs_x__pair_cache_key_t *key;
+          svn_fs_x__dir_data_t dir_data;
+
           /* Write out the contents of this directory as a text rep. */
           noderev->data_rep->id.change_set = change_set;
           SVN_ERR(write_container_delta_rep(noderev->data_rep, file,
@@ -2965,6 +3144,23 @@ write_final_rev(svn_fs_x__id_t *new_id_p
                                             fs, txn_id, noderev, NULL,
                                             SVN_FS_X__ITEM_TYPE_DIR_REP,
                                             rev, scratch_pool));
+
+          /* Cache the new directory contents.  Otherwise, subsequent reads
+           * or commits will likely have to reconstruct, verify and parse
+           * it again. */
+          key = apr_array_push(directory_ids);
+          key->revision = noderev->data_rep->id.change_set;
+          key->second = noderev->data_rep->id.number;
+
+          /* Store directory contents under the new revision number but mark
+           * it as "stale" by setting the file length to 0.  Committed dirs
+           * will report -1, in-txn dirs will report > 0, so that this can
+           * never match.  We reset that to -1 after the commit is complete.
+           */
+          dir_data.entries = entries;
+          dir_data.txn_filesize = 0;
+
+          SVN_ERR(svn_cache__set(ffd->dir_cache, key, &dir_data, subpool));
         }
     }
   else
@@ -3510,6 +3706,41 @@ bump_ids(void *baton,
   return SVN_NO_ERROR;
 }
 
+/* Mark the directories cached in FS with the keys from DIRECTORY_IDS
+ * as "valid" now.  Use SCRATCH_POOL for temporaries. */
+static svn_error_t *
+promote_cached_directories(svn_fs_t *fs,
+                           apr_array_header_t *directory_ids,
+                           apr_pool_t *scratch_pool)
+{
+  svn_fs_x__data_t *ffd = fs->fsap_data;
+  apr_pool_t *iterpool;
+  int i;
+
+  if (!ffd->dir_cache)
+    return SVN_NO_ERROR;
+
+  iterpool = svn_pool_create(scratch_pool);
+  for (i = 0; i < directory_ids->nelts; ++i)
+    {
+      const svn_fs_x__pair_cache_key_t *key
+        = &APR_ARRAY_IDX(directory_ids, i, svn_fs_x__pair_cache_key_t);
+
+      svn_pool_clear(iterpool);
+
+      /* Currently, the entry for KEY - if it still exists - is marked
+       * as "stale" and would not be used.  Mark it as current for in-
+       * revison data. */
+      SVN_ERR(svn_cache__set_partial(ffd->dir_cache, key,
+                                     svn_fs_x__reset_txn_filesize, NULL,
+                                     iterpool));
+    }
+
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
 /* Baton used for commit_body below. */
 typedef struct commit_baton_t {
   svn_revnum_t *new_rev_p;
@@ -3539,6 +3770,8 @@ commit_body(void *baton,
   apr_hash_t *changed_paths;
   svn_fs_x__batch_fsync_t *batch;
   bump_ids_baton_t bump_ids_baton;
+  apr_array_header_t *directory_ids
+    = apr_array_make(scratch_pool, 4, sizeof(svn_fs_x__pair_cache_key_t));
 
   /* We perform a sequence of (potentially) large allocations.
      Keep the peak memory usage low by using a SUBPOOL and cleaning it
@@ -3600,8 +3833,8 @@ commit_body(void *baton,
   /* Write out all the node-revisions and directory contents. */
   svn_fs_x__init_txn_root(&root_id, txn_id);
   SVN_ERR(write_final_rev(&new_root_id, proto_file, new_rev, cb->fs, &root_id,
-                          initial_offset, cb->reps_to_cache, cb->reps_hash,
-                          cb->reps_pool, TRUE, subpool));
+                          initial_offset, directory_ids, cb->reps_to_cache,
+                          cb->reps_hash, cb->reps_pool, TRUE, subpool));
   svn_pool_clear(subpool);
 
   /* Write the changed-path information. */
@@ -3654,6 +3887,10 @@ commit_body(void *baton,
 
   ffd->youngest_rev_cache = new_rev;
 
+  /* Make the directory contents already cached for the new revision
+   * visible. */
+  SVN_ERR(promote_cached_directories(cb->fs, directory_ids, subpool));
+
   /* Remove this transaction directory. */
   SVN_ERR(svn_fs_x__purge_txn(cb->fs, cb->txn->id, subpool));
 

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/util.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/util.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/util.c Mon Oct 26 08:43:06 2015
@@ -716,14 +716,6 @@ svn_fs_x__read_number_from_stream(apr_in
   return SVN_NO_ERROR;
 }
 
-
-/* Move a file into place from OLD_FILENAME in the transactions
-   directory to its final location NEW_FILENAME in the repository.  On
-   Unix, match the permissions of the new file to the permissions of
-   PERMS_REFERENCE.  Temporary allocations are from SCRATCH_POOL.
-
-   This function almost duplicates svn_io_file_move(), but it tries to
-   guarantee a flush. */
 svn_error_t *
 svn_fs_x__move_into_place(const char *old_filename,
                           const char *new_filename,
@@ -731,52 +723,47 @@ svn_fs_x__move_into_place(const char *ol
                           apr_pool_t *scratch_pool)
 {
   svn_error_t *err;
+  apr_file_t *file;
 
+  /* Copying permissions is a no-op on WIN32. */
   SVN_ERR(svn_io_copy_perms(perms_reference, old_filename, scratch_pool));
 
   /* Move the file into place. */
-  err = svn_io_file_rename2(old_filename, new_filename, FALSE, scratch_pool);
+  err = svn_io_file_rename2(old_filename, new_filename, TRUE, scratch_pool);
   if (err && APR_STATUS_IS_EXDEV(err->apr_err))
     {
-      apr_file_t *file;
-
       /* Can't rename across devices; fall back to copying. */
       svn_error_clear(err);
-      err = SVN_NO_ERROR;
       SVN_ERR(svn_io_copy_file(old_filename, new_filename, TRUE,
                                scratch_pool));
 
-      /* Flush the target of the copy to disk. */
-      SVN_ERR(svn_io_file_open(&file, new_filename, APR_READ,
+      /* Flush the target of the copy to disk.
+         ### The code below is duplicates svn_io_file_rename2(), because
+             currently we don't have the svn_io_copy_file2() function with
+             a flush_to_disk argument. */
+      SVN_ERR(svn_io_file_open(&file, new_filename, APR_WRITE,
                                APR_OS_DEFAULT, scratch_pool));
-      /* ### BH: Does this really guarantee a flush of the data written
-         ### via a completely different handle on all operating systems?
-         ###
-         ### Maybe we should perform the copy ourselves instead of making
-         ### apr do that and flush the real handle? */
       SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool));
       SVN_ERR(svn_io_file_close(file, scratch_pool));
-    }
-  if (err)
-    return svn_error_trace(err);
 
-#ifdef __linux__
-  {
-    /* Linux has the unusual feature that fsync() on a file is not
-       enough to ensure that a file's directory entries have been
-       flushed to disk; you have to fsync the directory as well.
-       On other operating systems, we'd only be asking for trouble
-       by trying to open and fsync a directory. */
-    const char *dirname;
-    apr_file_t *file;
-
-    dirname = svn_dirent_dirname(new_filename, scratch_pool);
-    SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT,
-                             scratch_pool));
-    SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool));
-    SVN_ERR(svn_io_file_close(file, scratch_pool));
-  }
+#ifdef SVN_ON_POSIX
+      {
+        /* On POSIX, the file name is stored in the file's directory entry.
+           Hence, we need to fsync() that directory as well.
+           On other operating systems, we'd only be asking for trouble
+           by trying to open and fsync a directory. */
+        const char *dirname;
+
+        dirname = svn_dirent_dirname(new_filename, scratch_pool);
+        SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT,
+                                 scratch_pool));
+        SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool));
+        SVN_ERR(svn_io_file_close(file, scratch_pool));
+      }
 #endif
+    }
+  else if (err)
+    return svn_error_trace(err);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/verify.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/verify.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/verify.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/verify.c Mon Oct 26 08:43:06 2015
@@ -27,6 +27,7 @@
 
 #include "cached_data.h"
 #include "rep-cache.h"
+#include "revprops.h"
 #include "util.h"
 #include "index.h"
 
@@ -691,6 +692,10 @@ verify_revprops(svn_fs_t *fs,
   svn_revnum_t revision;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
+  /* Invalidate the revprop generation once.
+   * Use the cache inside the loop to speed up packed revprop access. */
+  svn_fs_x__invalidate_revprop_generation(fs);
+
   for (revision = start; revision < end; ++revision)
     {
       svn_string_t *date;
@@ -701,7 +706,7 @@ verify_revprops(svn_fs_t *fs,
       /* Access the svn:date revprop.
        * This implies parsing all revprops for that revision. */
       SVN_ERR(svn_fs_x__revision_prop(&date, fs, revision,
-                                      SVN_PROP_REVISION_DATE, TRUE,
+                                      SVN_PROP_REVISION_DATE, FALSE,
                                       iterpool, iterpool));
 
       /* The time stamp is the only revprop that, if given, needs to
@@ -778,8 +783,15 @@ verify_metadata_consistency(svn_fs_t *fs
       /* concurrent packing is one of the reasons why verification may fail.
          Make sure, we operate on up-to-date information. */
       if (err)
-        SVN_ERR(svn_fs_x__read_min_unpacked_rev(&ffd->min_unpacked_rev,
-                                                fs, scratch_pool));
+        {
+          svn_error_t *err2
+            = svn_fs_x__read_min_unpacked_rev(&ffd->min_unpacked_rev,
+                                              fs, scratch_pool);
+
+          /* Be careful to not leak ERR. */
+          if (err2)
+            return svn_error_trace(svn_error_compose_create(err, err2));
+        }
 
       /* retry the whole shard if it got packed in the meantime */
       if (err && count != svn_fs_x__pack_size(fs, revision))
@@ -812,14 +824,14 @@ svn_fs_x__verify(svn_fs_t *fs,
                  void *cancel_baton,
                  apr_pool_t *scratch_pool)
 {
-  svn_fs_x__data_t *ffd = fs->fsap_data;
-  svn_revnum_t youngest = ffd->youngest_rev_cache; /* cache is current */
-
   /* Input validation. */
   if (! SVN_IS_VALID_REVNUM(start))
     start = 0;
   if (! SVN_IS_VALID_REVNUM(end))
-    end = youngest;
+    {
+      SVN_ERR(svn_fs_x__youngest_rev(&end, fs, scratch_pool));
+    }
+
   SVN_ERR(svn_fs_x__ensure_revision_exists(start, fs, scratch_pool));
   SVN_ERR(svn_fs_x__ensure_revision_exists(end, fs, scratch_pool));
 

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/client.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/client.c Mon Oct 26 08:43:06 2015
@@ -50,6 +50,7 @@
 #include "svn_private_config.h"
 
 #include "private/svn_fspath.h"
+#include "private/svn_string_private.h"
 #include "private/svn_subr_private.h"
 
 #include "../libsvn_ra/ra_loader.h"
@@ -204,7 +205,7 @@ static svn_error_t *parse_prop_diffs(con
         return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                 _("Prop diffs element not a list"));
       prop = apr_array_push(*diffs);
-      SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, pool, "c(?s)",
+      SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "c(?s)",
                                       &prop->name, &prop->value));
     }
   return SVN_NO_ERROR;
@@ -218,7 +219,7 @@ static svn_error_t *parse_lock(const svn
 {
   const char *cdate, *edate;
   *lock = svn_lock_create(pool);
-  SVN_ERR(svn_ra_svn__parse_tuple(list, pool, "ccc(?c)c(?c)", &(*lock)->path,
+  SVN_ERR(svn_ra_svn__parse_tuple(list, "ccc(?c)c(?c)", &(*lock)->path,
                                   &(*lock)->token, &(*lock)->owner,
                                   &(*lock)->comment, &cdate, &edate));
   (*lock)->path = svn_fspath__canonicalize((*lock)->path, pool);
@@ -1228,7 +1229,7 @@ parse_iproplist(apr_array_header_t **inh
 
       svn_pool_clear(iterpool);
 
-      SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, iterpool, "cl",
+      SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "cl",
                                       &parent_rel_path, &iprop_list));
       SVN_ERR(svn_ra_svn__parse_proplist(iprop_list, iterpool, &iprops));
       new_iprop->path_or_url = svn_path_url_add_component2(repos_root_url,
@@ -1389,7 +1390,7 @@ static svn_error_t *ra_svn_get_dir(svn_r
       if (elt->kind != SVN_RA_SVN_LIST)
         return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                 _("Dirlist element not a list"));
-      SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, pool, "cwnbr(?c)(?c)",
+      SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "cwnbr(?c)(?c)",
                                       &name, &kind, &size, &has_props,
                                       &crev, &cdate, &cauthor));
 
@@ -1481,7 +1482,7 @@ static svn_error_t *ra_svn_get_mergeinfo
           if (elt->kind != SVN_RA_SVN_LIST)
             return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                     _("Mergeinfo element is not a list"));
-          SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, pool, "cc",
+          SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "cc",
                                           &path, &to_parse));
           SVN_ERR(svn_mergeinfo_parse(&for_path, to_parse, pool));
           /* Correct for naughty servers that send "relative" paths
@@ -1604,6 +1605,16 @@ static svn_error_t *ra_svn_diff(svn_ra_s
   return SVN_NO_ERROR;
 }
 
+/* Return TRUE if ITEM matches the word "done". */
+static svn_boolean_t
+is_done_response(const svn_ra_svn__item_t *item)
+{
+  static const svn_string_t str_done = SVN__STATIC_STRING("done");
+
+  return (   item->kind == SVN_RA_SVN_WORD
+          && svn_string_compare(&item->u.word, &str_done));
+}
+
 
 static svn_error_t *
 perform_ra_svn_log(svn_error_t **outer_error,
@@ -1695,12 +1706,12 @@ perform_ra_svn_log(svn_error_t **outer_e
 
       svn_pool_clear(iterpool);
       SVN_ERR(svn_ra_svn__read_item(conn, iterpool, &item));
-      if (item->kind == SVN_RA_SVN_WORD && strcmp(item->u.word, "done") == 0)
+      if (is_done_response(item))
         break;
       if (item->kind != SVN_RA_SVN_LIST)
         return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                 _("Log entry not a list"));
-      SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, iterpool,
+      SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list,
                                       "lr(?s)(?s)(?s)?BBnl?B",
                                       &cplist, &rev, &author, &date,
                                       &message, &has_children_param,
@@ -1915,7 +1926,7 @@ static svn_error_t *ra_svn_stat(svn_ra_s
       svn_revnum_t crev;
       apr_uint64_t size;
 
-      SVN_ERR(svn_ra_svn__parse_tuple(list, pool, "wnbr(?c)(?c)",
+      SVN_ERR(svn_ra_svn__parse_tuple(list, "wnbr(?c)(?c)",
                                       &kind, &size, &has_props,
                                       &crev, &cdate, &cauthor));
 
@@ -1971,14 +1982,14 @@ static svn_error_t *ra_svn_get_locations
       const char *ret_path;
 
       SVN_ERR(svn_ra_svn__read_item(conn, pool, &item));
-      if (item->kind == SVN_RA_SVN_WORD && strcmp(item->u.word, "done") == 0)
+      if (is_done_response(item))
         is_done = 1;
       else if (item->kind != SVN_RA_SVN_LIST)
         return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                 _("Location entry not a list"));
       else
         {
-          SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, pool, "rc",
+          SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, "rc",
                                           &revision, &ret_path));
           ret_path = svn_fspath__canonicalize(ret_path, pool);
           apr_hash_set(*locations, apr_pmemdup(pool, &revision,
@@ -2028,7 +2039,7 @@ perform_get_location_segments(svn_error_
 
       svn_pool_clear(iterpool);
       SVN_ERR(svn_ra_svn__read_item(conn, iterpool, &item));
-      if (item->kind == SVN_RA_SVN_WORD && strcmp(item->u.word, "done") == 0)
+      if (is_done_response(item))
         is_done = 1;
       else if (item->kind != SVN_RA_SVN_LIST)
         return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
@@ -2037,7 +2048,7 @@ perform_get_location_segments(svn_error_
         {
           svn_location_segment_t *segment = apr_pcalloc(iterpool,
                                                         sizeof(*segment));
-          SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, iterpool, "rr(?c)",
+          SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, "rr(?c)",
                                           &range_start, &range_end, &ret_path));
           if (! (SVN_IS_VALID_REVNUM(range_start)
                  && SVN_IS_VALID_REVNUM(range_end)))
@@ -2131,7 +2142,7 @@ static svn_error_t *ra_svn_get_file_revs
       svn_pool_clear(rev_pool);
       svn_pool_clear(chunk_pool);
       SVN_ERR(svn_ra_svn__read_item(sess_baton->conn, rev_pool, &item));
-      if (item->kind == SVN_RA_SVN_WORD && strcmp(item->u.word, "done") == 0)
+      if (is_done_response(item))
         break;
       /* Either we've got a correct revision or we will error out below. */
       had_revision = TRUE;
@@ -2139,7 +2150,7 @@ static svn_error_t *ra_svn_get_file_revs
         return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                 _("Revision entry not a list"));
 
-      SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, rev_pool,
+      SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list,
                                       "crll?B", &p, &rev, &rev_proplist,
                                       &proplist, &merged_rev_param));
       p = svn_fspath__canonicalize(p, rev_pool);
@@ -2400,18 +2411,17 @@ static svn_error_t *ra_svn_lock(svn_ra_s
          the middle of the request list.  If this happens, it will
          transmit "done" to end the lock-info early, and then the
          overall command response will talk about the fatal error. */
-      if (elt->kind == SVN_RA_SVN_WORD && strcmp(elt->u.word, "done") == 0)
+      if (is_done_response(elt))
         break;
 
       if (elt->kind != SVN_RA_SVN_LIST)
         return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                 _("Lock response not a list"));
 
-      SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, iterpool, "wl", &status,
-                                      &list));
+      SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "wl", &status, &list));
 
       if (strcmp(status, "failure") == 0)
-        err = svn_ra_svn__handle_failure_status(list, iterpool);
+        err = svn_ra_svn__handle_failure_status(list);
       else if (strcmp(status, "success") == 0)
         {
           SVN_ERR(parse_lock(list, iterpool, &lock));
@@ -2441,7 +2451,7 @@ static svn_error_t *ra_svn_lock(svn_ra_s
       svn_ra_svn__item_t *elt;
 
       SVN_ERR(svn_ra_svn__read_item(conn, pool, &elt));
-      if (elt->kind != SVN_RA_SVN_WORD || strcmp(elt->u.word, "done") != 0)
+      if (!is_done_response(elt))
         return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                 _("Didn't receive end marker for lock "
                                   "responses"));
@@ -2525,7 +2535,7 @@ static svn_error_t *ra_svn_unlock(svn_ra
          the middle of the request list.  If this happens, it will
          transmit "done" to end the lock-info early, and then the
          overall command response will talk about the fatal error. */
-      if (elt->kind == SVN_RA_SVN_WORD && (strcmp(elt->u.word, "done") == 0))
+      if (is_done_response(elt))
         break;
 
       apr_hash_this(hi, &key, NULL, NULL);
@@ -2535,14 +2545,13 @@ static svn_error_t *ra_svn_unlock(svn_ra
         return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                 _("Unlock response not a list"));
 
-      SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, iterpool, "wl", &status,
-                                      &list));
+      SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "wl", &status, &list));
 
       if (strcmp(status, "failure") == 0)
-        err = svn_ra_svn__handle_failure_status(list, iterpool);
+        err = svn_ra_svn__handle_failure_status(list);
       else if (strcmp(status, "success") == 0)
         {
-          SVN_ERR(svn_ra_svn__parse_tuple(list, iterpool, "c", &path));
+          SVN_ERR(svn_ra_svn__parse_tuple(list, "c", &path));
           err = SVN_NO_ERROR;
         }
       else
@@ -2568,7 +2577,7 @@ static svn_error_t *ra_svn_unlock(svn_ra
       svn_ra_svn__item_t *elt;
 
       SVN_ERR(svn_ra_svn__read_item(conn, pool, &elt));
-      if (elt->kind != SVN_RA_SVN_WORD || strcmp(elt->u.word, "done") != 0)
+      if (! is_done_response(elt))
         return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                 _("Didn't receive end marker for unlock "
                                   "responses"));
@@ -2754,7 +2763,7 @@ ra_svn_replay_range(svn_ra_session_t *se
       if (strcmp(word, "revprops") != 0)
         {
           if (strcmp(word, "failure") == 0)
-            SVN_ERR(svn_ra_svn__handle_failure_status(list, iterpool));
+            SVN_ERR(svn_ra_svn__handle_failure_status(list));
 
           return svn_error_createf(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                    _("Expected 'revprops', found '%s'"),

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/cyrus_auth.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/cyrus_auth.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/cyrus_auth.c Mon Oct 26 08:43:06 2015
@@ -860,7 +860,7 @@ svn_ra_svn__do_cyrus_auth(svn_ra_svn__se
           mechstring = apr_pstrcat(pool,
                                    mechstring,
                                    i == 0 ? "" : " ",
-                                   elt->u.word, SVN_VA_NULL);
+                                   elt->u.word.data, SVN_VA_NULL);
         }
     }
 

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/deprecated.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/deprecated.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/deprecated.c Mon Oct 26 08:43:06 2015
@@ -135,7 +135,7 @@ svn_ra_svn_parse_tuple(const apr_array_h
   svn_ra_svn__list_t *internal = svn_ra_svn__to_private_array(list, pool);
 
   va_start(va, fmt);
-  err = svn_ra_svn__parse_tuple(internal, pool, fmt, va);
+  err = svn_ra_svn__parse_tuple(internal, fmt, va);
   va_end(va);
 
   return svn_error_trace(err);

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/editorp.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/editorp.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/editorp.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/editorp.c Mon Oct 26 08:43:06 2015
@@ -542,7 +542,7 @@ ra_svn_handle_target_rev(svn_ra_svn_conn
 {
   svn_revnum_t rev;
 
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "r", &rev));
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "r", &rev));
   SVN_CMD_ERR(ds->editor->set_target_revision(ds->edit_baton, rev, pool));
   return SVN_NO_ERROR;
 }
@@ -558,7 +558,7 @@ ra_svn_handle_open_root(svn_ra_svn_conn_
   svn_string_t *token;
   void *root_baton;
 
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?r)s", &rev, &token));
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)s", &rev, &token));
   subpool = svn_pool_create(ds->pool);
   SVN_CMD_ERR(ds->editor->open_root(ds->edit_baton, rev, subpool,
                                     &root_baton));
@@ -577,7 +577,7 @@ ra_svn_handle_delete_entry(svn_ra_svn_co
   svn_revnum_t rev;
   ra_svn_token_entry_t *entry;
 
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)s",
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)s",
                                   &path, &rev, &token));
   SVN_ERR(lookup_token(ds, token, FALSE, &entry));
   path = svn_relpath_canonicalize(path, pool);
@@ -598,7 +598,7 @@ ra_svn_handle_add_dir(svn_ra_svn_conn_t
   apr_pool_t *subpool;
   void *child_baton;
 
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?cr)", &path, &token,
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "css(?cr)", &path, &token,
                                   &child_token, &copy_path, &copy_rev));
   SVN_ERR(lookup_token(ds, token, FALSE, &entry));
   subpool = svn_pool_create(entry->pool);
@@ -633,7 +633,7 @@ ra_svn_handle_open_dir(svn_ra_svn_conn_t
   apr_pool_t *subpool;
   void *child_baton;
 
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?r)", &path, &token,
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "css(?r)", &path, &token,
                                   &child_token, &rev));
   SVN_ERR(lookup_token(ds, token, FALSE, &entry));
   subpool = svn_pool_create(entry->pool);
@@ -655,7 +655,7 @@ ra_svn_handle_change_dir_prop(svn_ra_svn
   svn_string_t *value;
   ra_svn_token_entry_t *entry;
 
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "sc(?s)", &token, &name,
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "sc(?s)", &token, &name,
                                   &value));
   SVN_ERR(lookup_token(ds, token, FALSE, &entry));
   SVN_CMD_ERR(ds->editor->change_dir_prop(entry->baton, name, value,
@@ -673,7 +673,7 @@ ra_svn_handle_close_dir(svn_ra_svn_conn_
   ra_svn_token_entry_t *entry;
 
   /* Parse and look up the directory token. */
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s", &token));
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "s", &token));
   SVN_ERR(lookup_token(ds, token, FALSE, &entry));
 
   /* Close the directory and destroy the baton. */
@@ -694,7 +694,7 @@ ra_svn_handle_absent_dir(svn_ra_svn_conn
   ra_svn_token_entry_t *entry;
 
   /* Parse parameters and look up the directory token. */
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cs", &path, &token));
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "cs", &path, &token));
   SVN_ERR(lookup_token(ds, token, FALSE, &entry));
 
   /* Call the editor. */
@@ -713,7 +713,7 @@ ra_svn_handle_add_file(svn_ra_svn_conn_t
   svn_revnum_t copy_rev;
   ra_svn_token_entry_t *entry, *file_entry;
 
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?cr)", &path, &token,
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "css(?cr)", &path, &token,
                                   &file_token, &copy_path, &copy_rev));
   SVN_ERR(lookup_token(ds, token, FALSE, &entry));
   ds->file_refs++;
@@ -749,7 +749,7 @@ ra_svn_handle_open_file(svn_ra_svn_conn_
   svn_revnum_t rev;
   ra_svn_token_entry_t *entry, *file_entry;
 
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?r)", &path, &token,
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "css(?r)", &path, &token,
                                   &file_token, &rev));
   SVN_ERR(lookup_token(ds, token, FALSE, &entry));
   ds->file_refs++;
@@ -777,7 +777,7 @@ ra_svn_handle_apply_textdelta(svn_ra_svn
   char *base_checksum;
 
   /* Parse arguments and look up the token. */
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s(?c)",
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "s(?c)",
                                   &token, &base_checksum));
   SVN_ERR(lookup_token(ds, token, TRUE, &entry));
   if (entry->dstream)
@@ -801,7 +801,7 @@ ra_svn_handle_textdelta_chunk(svn_ra_svn
   svn_string_t *str;
 
   /* Parse arguments and look up the token. */
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ss", &token, &str));
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "ss", &token, &str));
   SVN_ERR(lookup_token(ds, token, TRUE, &entry));
   if (!entry->dstream)
     return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
@@ -820,7 +820,7 @@ ra_svn_handle_textdelta_end(svn_ra_svn_c
   ra_svn_token_entry_t *entry;
 
   /* Parse arguments and look up the token. */
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s", &token));
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "s", &token));
   SVN_ERR(lookup_token(ds, token, TRUE, &entry));
   if (!entry->dstream)
     return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
@@ -841,7 +841,7 @@ ra_svn_handle_change_file_prop(svn_ra_sv
   svn_string_t *token, *value;
   ra_svn_token_entry_t *entry;
 
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "sc(?s)", &token, &name,
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "sc(?s)", &token, &name,
                                   &value));
   SVN_ERR(lookup_token(ds, token, TRUE, &entry));
   SVN_CMD_ERR(ds->editor->change_file_prop(entry->baton, name, value, pool));
@@ -859,7 +859,7 @@ ra_svn_handle_close_file(svn_ra_svn_conn
   const char *text_checksum;
 
   /* Parse arguments and look up the file token. */
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s(?c)",
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "s(?c)",
                                   &token, &text_checksum));
   SVN_ERR(lookup_token(ds, token, TRUE, &entry));
 
@@ -882,7 +882,7 @@ ra_svn_handle_absent_file(svn_ra_svn_con
   ra_svn_token_entry_t *entry;
 
   /* Parse parameters and look up the parent directory token. */
-  SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cs", &path, &token));
+  SVN_ERR(svn_ra_svn__parse_tuple(params, "cs", &path, &token));
   SVN_ERR(lookup_token(ds, token, FALSE, &entry));
 
   /* Call the editor. */
@@ -1121,7 +1121,7 @@ svn_error_t *svn_ra_svn_drive_editor2(sv
                 command */
               if (aborted)
                 *aborted = TRUE;
-              err = svn_ra_svn__handle_failure_status(params, pool);
+              err = svn_ra_svn__handle_failure_status(params);
               return svn_error_compose_create(
                                 err,
                                 editor->abort_edit(edit_baton, subpool));

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/internal_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/internal_auth.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/internal_auth.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/internal_auth.c Mon Oct 26 08:43:06 2015
@@ -46,7 +46,7 @@ svn_boolean_t svn_ra_svn__find_mech(cons
   for (i = 0; i < mechlist->nelts; i++)
     {
       elt = &SVN_RA_SVN__LIST_ITEM(mechlist, i);
-      if (elt->kind == SVN_RA_SVN_WORD && strcmp(elt->u.word, mech) == 0)
+      if (elt->kind == SVN_RA_SVN_WORD && strcmp(elt->u.word.data, mech) == 0)
         return TRUE;
     }
   return FALSE;

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/marshal.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/marshal.c Mon Oct 26 08:43:06 2015
@@ -72,6 +72,10 @@
  */
 #define ITEM_NESTING_LIMIT 64
 
+/* The protocol words for booleans. */
+static const svn_string_t str_true = SVN__STATIC_STRING("true");
+static const svn_string_t str_false = SVN__STATIC_STRING("false");
+
 /* Return the APR socket timeout to be used for the connection depending
  * on whether there is a blockage handler or zero copy has been activated. */
 static apr_interval_time_t
@@ -97,7 +101,7 @@ svn_ra_svn__to_public_item(svn_ra_svn_it
         target->u.number = source->u.number;
         break;
       case SVN_RA_SVN_WORD:
-        target->u.word = source->u.word;
+        target->u.word = source->u.word.data;
         break;
       case SVN_RA_SVN_LIST:
         target->u.list = svn_ra_svn__to_public_array(&source->u.list,
@@ -140,7 +144,8 @@ svn_ra_svn__to_private_item(svn_ra_svn__
         target->u.number = source->u.number;
         break;
       case SVN_RA_SVN_WORD:
-        target->u.word = source->u.word;
+        target->u.word.data = source->u.word;
+        target->u.word.len = strlen(source->u.word);
         break;
       case SVN_RA_SVN_LIST:
         target->u.list = *svn_ra_svn__to_private_array(source->u.list,
@@ -248,8 +253,8 @@ svn_ra_svn__set_capabilities(svn_ra_svn_
       if (item->kind != SVN_RA_SVN_WORD)
         return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                 _("Capability entry is not a word"));
-      word = apr_pstrdup(conn->pool, item->u.word);
-      svn_hash_sets(conn->capabilities, word, word);
+      word = apr_pstrmemdup(conn->pool, item->u.word.data, item->u.word.len);
+      apr_hash_set(conn->capabilities, word, item->u.word.len, word);
     }
   return SVN_NO_ERROR;
 }
@@ -1289,8 +1294,10 @@ static svn_error_t *read_item(svn_ra_svn
       c = *p;
       *p = '\0';
 
+      /* Store the word in ITEM. */
       item->kind = SVN_RA_SVN_WORD;
-      item->u.word = buffer;
+      item->u.word.data = buffer;
+      item->u.word.len = p - buffer;
     }
   else if (c == '(')
     {
@@ -1507,7 +1514,6 @@ svn_ra_svn__skip_leading_garbage(svn_ra_
  * tuple specification and advance AP by the corresponding arguments. */
 static svn_error_t *
 vparse_tuple(const svn_ra_svn__list_t *items,
-             apr_pool_t *pool,
              const char **fmt,
              va_list *ap)
 {
@@ -1523,19 +1529,19 @@ vparse_tuple(const svn_ra_svn__list_t *i
       if (**fmt == '(' && elt->kind == SVN_RA_SVN_LIST)
         {
           (*fmt)++;
-          SVN_ERR(vparse_tuple(&elt->u.list, pool, fmt, ap));
+          SVN_ERR(vparse_tuple(&elt->u.list, fmt, ap));
         }
       else if (**fmt == 'c' && elt->kind == SVN_RA_SVN_STRING)
         *va_arg(*ap, const char **) = elt->u.string.data;
       else if (**fmt == 's' && elt->kind == SVN_RA_SVN_STRING)
         *va_arg(*ap, svn_string_t **) = &elt->u.string;
       else if (**fmt == 'w' && elt->kind == SVN_RA_SVN_WORD)
-        *va_arg(*ap, const char **) = elt->u.word;
+        *va_arg(*ap, const char **) = elt->u.word.data;
       else if (**fmt == 'b' && elt->kind == SVN_RA_SVN_WORD)
         {
-          if (strcmp(elt->u.word, "true") == 0)
+          if (svn_string_compare(&elt->u.word, &str_true))
             *va_arg(*ap, svn_boolean_t *) = TRUE;
-          else if (strcmp(elt->u.word, "false") == 0)
+          else if (svn_string_compare(&elt->u.word, &str_false))
             *va_arg(*ap, svn_boolean_t *) = FALSE;
           else
             break;
@@ -1546,18 +1552,18 @@ vparse_tuple(const svn_ra_svn__list_t *i
         *va_arg(*ap, svn_revnum_t *) = (svn_revnum_t) elt->u.number;
       else if (**fmt == 'B' && elt->kind == SVN_RA_SVN_WORD)
         {
-          if (strcmp(elt->u.word, "true") == 0)
+          if (svn_string_compare(&elt->u.word, &str_true))
             *va_arg(*ap, apr_uint64_t *) = TRUE;
-          else if (strcmp(elt->u.word, "false") == 0)
+          else if (svn_string_compare(&elt->u.word, &str_false))
             *va_arg(*ap, apr_uint64_t *) = FALSE;
           else
             break;
         }
       else if (**fmt == '3' && elt->kind == SVN_RA_SVN_WORD)
         {
-          if (strcmp(elt->u.word, "true") == 0)
+          if (svn_string_compare(&elt->u.word, &str_true))
             *va_arg(*ap, svn_tristate_t *) = svn_tristate_true;
-          else if (strcmp(elt->u.word, "false") == 0)
+          else if (svn_string_compare(&elt->u.word, &str_false))
             *va_arg(*ap, svn_tristate_t *) = svn_tristate_false;
           else
             break;
@@ -1618,14 +1624,13 @@ vparse_tuple(const svn_ra_svn__list_t *i
 
 svn_error_t *
 svn_ra_svn__parse_tuple(const svn_ra_svn__list_t *list,
-                        apr_pool_t *pool,
                         const char *fmt, ...)
 {
   svn_error_t *err;
   va_list ap;
 
   va_start(ap, fmt);
-  err = vparse_tuple(list, pool, &fmt, &ap);
+  err = vparse_tuple(list, &fmt, &ap);
   va_end(ap);
   return err;
 }
@@ -1644,7 +1649,7 @@ svn_ra_svn__read_tuple(svn_ra_svn_conn_t
     return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                             _("Malformed network data"));
   va_start(ap, fmt);
-  err = vparse_tuple(&item->u.list, pool, &fmt, &ap);
+  err = vparse_tuple(&item->u.list, &fmt, &ap);
   va_end(ap);
   return err;
 }
@@ -1679,8 +1684,7 @@ svn_ra_svn__parse_proplist(const svn_ra_
       if (elt->kind != SVN_RA_SVN_LIST)
         return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                 _("Proplist element not a list"));
-      SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, pool, "ss",
-                                      &name, &value));
+      SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "ss", &name, &value));
       apr_hash_set(*props, name->data, name->len, value);
     }
 
@@ -1706,15 +1710,13 @@ svn_error_t *svn_ra_svn__locate_real_err
 }
 
 svn_error_t *
-svn_ra_svn__handle_failure_status(const svn_ra_svn__list_t *params,
-                                  apr_pool_t *pool)
+svn_ra_svn__handle_failure_status(const svn_ra_svn__list_t *params)
 {
   const char *message, *file;
   svn_error_t *err = NULL;
   svn_ra_svn__item_t *elt;
   int i;
   apr_uint64_t apr_err, line;
-  apr_pool_t *subpool = svn_pool_create(pool);
 
   if (params->nelts == 0)
     return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
@@ -1723,12 +1725,11 @@ svn_ra_svn__handle_failure_status(const
   /* Rebuild the error list from the end, to avoid reversing the order. */
   for (i = params->nelts - 1; i >= 0; i--)
     {
-      svn_pool_clear(subpool);
       elt = &SVN_RA_SVN__LIST_ITEM(params, i);
       if (elt->kind != SVN_RA_SVN_LIST)
         return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
                                 _("Malformed error list"));
-      SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, subpool, "nccn",
+      SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "nccn",
                                       &apr_err, &message, &file, &line));
       /* The message field should have been optional, but we can't
          easily change that, so "" means a nonexistent message. */
@@ -1747,8 +1748,6 @@ svn_ra_svn__handle_failure_status(const
         }
     }
 
-  svn_pool_destroy(subpool);
-
   /* If we get here, then we failed to find a real error in the error
      chain that the server proported to be sending us.  That's bad. */
   if (! err)
@@ -1772,13 +1771,13 @@ svn_ra_svn__read_cmd_response(svn_ra_svn
   if (strcmp(status, "success") == 0)
     {
       va_start(ap, fmt);
-      err = vparse_tuple(params, pool, &fmt, &ap);
+      err = vparse_tuple(params, &fmt, &ap);
       va_end(ap);
       return err;
     }
   else if (strcmp(status, "failure") == 0)
     {
-      return svn_error_trace(svn_ra_svn__handle_failure_status(params, pool));
+      return svn_error_trace(svn_ra_svn__handle_failure_status(params));
     }
 
   return svn_error_createf(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
@@ -2869,7 +2868,7 @@ svn_ra_svn__read_word(const svn_ra_svn__
 {
   svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(items, idx);
   CHECK_PROTOCOL_COND(elt->kind == SVN_RA_SVN_WORD);
-  *result = elt->u.word;
+  *result = elt->u.word.data;
 
   return SVN_NO_ERROR;
 }
@@ -2897,9 +2896,9 @@ svn_ra_svn__read_boolean(const svn_ra_sv
 {
   svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(items, idx);
   CHECK_PROTOCOL_COND(elt->kind == SVN_RA_SVN_WORD);
-  if (elt->u.word[0] == 't' && strcmp(elt->u.word, "true") == 0)
+  if (svn_string_compare(&elt->u.word, &str_true))
     *result = TRUE;
-  else if (strcmp(elt->u.word, "false") == 0)
+  else if (svn_string_compare(&elt->u.word, &str_false))
     *result = FALSE;
   else
     CHECK_PROTOCOL_COND(FALSE);

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/ra_svn.h?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_svn/ra_svn.h Mon Oct 26 08:43:06 2015
@@ -163,11 +163,9 @@ svn_error_t *svn_ra_svn__locate_real_err
 
 /* Return an error chain based on @a params (which contains a
  * command response indicating failure).  The error chain will be
- * in the same order as the errors indicated in @a params.  Use
- * @a pool for temporary allocations. */
+ * in the same order as the errors indicated in @a params. */
 svn_error_t *
-svn_ra_svn__handle_failure_status(const svn_ra_svn__list_t *params,
-                                  apr_pool_t *pool);
+svn_ra_svn__handle_failure_status(const svn_ra_svn__list_t *params);
 
 /* Returns a stream that reads/writes from/to SOCK. */
 svn_ra_svn__stream_t *svn_ra_svn__stream_from_sock(apr_socket_t *sock,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_repos/log.c?rev=1710531&r1=1710530&r2=1710531&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_repos/log.c Mon Oct 26 08:43:06 2015
@@ -43,6 +43,7 @@
 #include "private/svn_mergeinfo_private.h"
 #include "private/svn_subr_private.h"
 #include "private/svn_sorts_private.h"
+#include "private/svn_string_private.h"
 
 
 
@@ -1151,9 +1152,9 @@ fill_log_entry(svn_log_entry_t *log_entr
              we want static initialization here and must therefore emulate
              strlen(x) by sizeof(x)-1. */
           static const svn_string_t svn_prop_revision_author
-            = {SVN_PROP_REVISION_AUTHOR, sizeof(SVN_PROP_REVISION_AUTHOR)-1};
+            = SVN__STATIC_STRING(SVN_PROP_REVISION_AUTHOR);
           static const svn_string_t svn_prop_revision_date
-            = {SVN_PROP_REVISION_DATE, sizeof(SVN_PROP_REVISION_DATE)-1};
+            = SVN__STATIC_STRING(SVN_PROP_REVISION_DATE);
 
           /* often only the standard revprops got requested and delivered.
              In that case, we can simply pass the hash on. */