You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2016/06/05 15:03:54 UTC

svn commit: r1746927 [4/8] - in /subversion/branches/authzperf: ./ build/ contrib/client-side/ contrib/client-side/svnmerge/ contrib/hook-scripts/ contrib/server-side/ contrib/server-side/fsfsfixer/fixer/ notes/directory-index/ notes/move-tracking/ sub...

Modified: subversion/branches/authzperf/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_client/copy.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_client/copy.c Sun Jun  5 15:03:52 2016
@@ -2415,10 +2415,10 @@ repos_to_wc_copy_single(svn_boolean_t *t
 
           *timestamp_sleep = TRUE;
 
-      /* Schedule dst_path for addition in parent, with copy history.
-         Don't send any notification here.
-         Then remove the temporary checkout's .svn dir in preparation for
-         moving the rest of it into the final destination. */
+          /* Schedule dst_path for addition in parent, with copy history.
+             Don't send any notification here.
+             Then remove the temporary checkout's .svn dir in preparation for
+             moving the rest of it into the final destination. */
           SVN_ERR(svn_wc_copy3(ctx->wc_ctx, tmp_abspath, dst_abspath,
                                TRUE /* metadata_only */,
                                ctx->cancel_func, ctx->cancel_baton,

Modified: subversion/branches/authzperf/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs/fs-loader.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs/fs-loader.c Sun Jun  5 15:03:52 2016
@@ -63,9 +63,9 @@
 /* If a FS backend does not implement the PATHS_CHANGED vtable function,
    it will get emulated.  However, if this macro is defined to non-null
    then the API will always be emulated when feasible, i.e. the calls
-   get "re-directed" to the old API implementation. */
+   get "re-directed" to the new API implementation. */
 #ifndef SVN_FS_EMULATE_PATHS_CHANGED
-#define SVN_FS_EMULATE_PATHS_CHANGED TRUE
+#define SVN_FS_EMULATE_PATHS_CHANGED FALSE
 #endif
 
 /* If a FS backend does not implement the REPORT_CHANGES vtable function,
@@ -73,7 +73,7 @@
    then the API will always be emulated when feasible, i.e. the calls
    get "re-directed" to the old API implementation. */
 #ifndef SVN_FS_EMULATE_REPORT_CHANGES
-#define SVN_FS_EMULATE_REPORT_CHANGES TRUE
+#define SVN_FS_EMULATE_REPORT_CHANGES FALSE
 #endif
 
 /* A pool common to all FS objects.  See the documentation on the

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/cached_data.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/cached_data.c Sun Jun  5 15:03:52 2016
@@ -2884,23 +2884,42 @@ svn_fs_fs__get_proplist(apr_hash_t **pro
 }
 
 svn_error_t *
+svn_fs_fs__create_changes_context(svn_fs_fs__changes_context_t **context,
+                                  svn_fs_t *fs,
+                                  svn_revnum_t rev,
+                                  apr_pool_t *result_pool)
+{
+  svn_fs_fs__changes_context_t *result = apr_pcalloc(result_pool,
+                                                     sizeof(*result));
+  result->fs = fs;
+  result->revision = rev;
+  result->rev_file_pool = result_pool;
+
+  *context = result;
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_fs_fs__get_changes(apr_array_header_t **changes,
-                       svn_fs_t *fs,
-                       svn_revnum_t rev,
-                       apr_pool_t *result_pool)
+                       svn_fs_fs__changes_context_t *context,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
 {
   apr_off_t item_index = SVN_FS_FS__ITEM_INDEX_CHANGES;
-  svn_fs_fs__revision_file_t *revision_file;
   svn_boolean_t found;
-  fs_fs_data_t *ffd = fs->fsap_data;
-  apr_pool_t *scratch_pool = svn_pool_create(result_pool);
+  fs_fs_data_t *ffd = context->fs->fsap_data;
+  svn_fs_fs__changes_list_t *changes_list;
+
+  pair_cache_key_t key;
+  key.revision = context->revision;
+  key.second = context->next;
 
   /* try cache lookup first */
 
   if (ffd->changes_cache)
     {
-      SVN_ERR(svn_cache__get((void **) changes, &found, ffd->changes_cache,
-                             &rev, result_pool));
+      SVN_ERR(svn_cache__get((void **)&changes_list, &found,
+                             ffd->changes_cache, &key, result_pool));
     }
   else
     {
@@ -2911,34 +2930,54 @@ svn_fs_fs__get_changes(apr_array_header_
     {
       /* read changes from revision file */
 
-      SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, scratch_pool));
-      SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&revision_file, fs, rev,
-                                               scratch_pool, scratch_pool));
+      if (!context->revision_file)
+        {
+          SVN_ERR(svn_fs_fs__ensure_revision_exists(context->revision,
+                                                    context->fs,
+                                                    scratch_pool));
+          SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&context->revision_file,
+                                                   context->fs,
+                                                   context->revision,
+                                                   context->rev_file_pool,
+                                                   scratch_pool));
+        }
 
-      if (use_block_read(fs))
+      if (use_block_read(context->fs))
         {
-          /* 'block-read' will also provide us with the desired data */
-          SVN_ERR(block_read((void **)changes, fs,
-                             rev, SVN_FS_FS__ITEM_INDEX_CHANGES,
-                             revision_file, result_pool, scratch_pool));
+          /* 'block-read' will probably populate the cache with the data
+           * that we want.  However, we won't want to force it to process
+           * very large change lists as part of this prefetching mechanism.
+           * Those would be better handled by the iterative code below. */
+          SVN_ERR(block_read(NULL, context->fs,
+                             context->revision, SVN_FS_FS__ITEM_INDEX_CHANGES,
+                             context->revision_file, scratch_pool,
+                             scratch_pool));
+
+          /* This may succeed now ... */
+          SVN_ERR(svn_cache__get((void **)&changes_list, &found,
+                                 ffd->changes_cache, &key, result_pool));
         }
-      else
+
+      /* If we still have no data, read it here. */
+      if (!found)
         {
           apr_off_t changes_offset;
 
           /* Addressing is very different for old formats
            * (needs to read the revision trailer). */
-          if (svn_fs_fs__use_log_addressing(fs))
+          if (svn_fs_fs__use_log_addressing(context->fs))
             {
-              SVN_ERR(svn_fs_fs__item_offset(&changes_offset, fs,
-                                             revision_file, rev, NULL,
+              SVN_ERR(svn_fs_fs__item_offset(&changes_offset, context->fs,
+                                             context->revision_file,
+                                             context->revision, NULL,
                                              SVN_FS_FS__ITEM_INDEX_CHANGES,
                                              scratch_pool));
             }
           else
             {
               SVN_ERR(get_root_changes_offset(NULL, &changes_offset,
-                                              revision_file, fs, rev,
+                                              context->revision_file,
+                                              context->fs, context->revision,
                                               scratch_pool));
 
               /* This variable will be used for debug logging only. */
@@ -2946,35 +2985,58 @@ svn_fs_fs__get_changes(apr_array_header_
             }
 
           /* Actual reading and parsing are the same, though. */
-          SVN_ERR(aligned_seek(fs, revision_file->file, NULL, changes_offset,
+          SVN_ERR(aligned_seek(context->fs, context->revision_file->file,
+                               NULL, changes_offset + context->next_offset,
                                scratch_pool));
-          SVN_ERR(svn_fs_fs__read_changes(changes, revision_file->stream,
+
+          SVN_ERR(svn_fs_fs__read_changes(changes,
+                                          context->revision_file->stream,
+                                          SVN_FS_FS__CHANGES_BLOCK_SIZE,
                                           result_pool, scratch_pool));
 
+          /* Construct the info object for the entries block we just read. */
+          changes_list = apr_pcalloc(scratch_pool, sizeof(*changes_list));
+          SVN_ERR(svn_io_file_get_offset(&changes_list->end_offset,
+                                         context->revision_file->file,
+                                         scratch_pool));
+          changes_list->end_offset -= changes_offset;
+          changes_list->start_offset = context->next_offset;
+          changes_list->count = (*changes)->nelts;
+          changes_list->changes = (change_t **)(*changes)->elts;
+          changes_list->eol = changes_list->count < SVN_FS_FS__CHANGES_BLOCK_SIZE;
+
           /* cache for future reference */
 
           if (ffd->changes_cache)
-            {
-              /* Guesstimate for the size of the in-cache representation. */
-              apr_size_t estimated_size = (apr_size_t)250 * (*changes)->nelts;
-
-              /* Don't even serialize data that probably won't fit into the
-               * cache.  This often implies that either CHANGES is very
-               * large, memory is scarce or both.  Having a huge temporary
-               * copy would not be a good thing in either case. */
-              if (svn_cache__is_cachable(ffd->changes_cache, estimated_size))
-                SVN_ERR(svn_cache__set(ffd->changes_cache, &rev, *changes,
-                                       scratch_pool));
-            }
+            SVN_ERR(svn_cache__set(ffd->changes_cache, &key, changes_list,
+                                   scratch_pool));
         }
+    }
 
-      SVN_ERR(svn_fs_fs__close_revision_file(revision_file));
+  if (found)
+    {
+      /* Return the block as a "proper" APR array. */
+      (*changes) = apr_array_make(result_pool, 0, sizeof(void *));
+      (*changes)->elts = (char *)changes_list->changes;
+      (*changes)->nelts = changes_list->count;
+      (*changes)->nalloc = changes_list->count;
+    }
+
+  /* Where to look next - if there is more data. */
+  context->next += (*changes)->nelts;
+  context->next_offset = changes_list->end_offset;
+  context->eol = changes_list->eol;
+
+  /* Close the revision file after we read all data. */
+  if (context->eol && context->revision_file)
+    {
+      SVN_ERR(svn_fs_fs__close_revision_file(context->revision_file));
+      context->revision_file = NULL;
     }
 
-  SVN_ERR(dbg_log_access(fs, rev, item_index, *changes,
+  SVN_ERR(dbg_log_access(context->fs, context->revision, item_index, *changes,
                          SVN_FS_FS__ITEM_TYPE_CHANGES, scratch_pool));
 
-  svn_pool_destroy(scratch_pool);
   return SVN_NO_ERROR;
 }
 
@@ -3323,31 +3385,33 @@ read_item(svn_stream_t **stream,
                  entry->item.revision);
 }
 
-/* If not already cached or if MUST_READ is set, read the changed paths
- * list addressed by ENTRY in FS and retúrn it in *CHANGES.  Cache the
- * result if caching is enabled.  Read the data from REV_FILE.  Allocate
- * *CHANGES in RESUSLT_POOL and allocate temporaries in SCRATCH_POOL.
+/* If not already cached, read the changed paths list addressed by ENTRY in
+ * FS and cache it if it has no more than SVN_FS_FS__CHANGES_BLOCK_SIZE
+ * entries and caching is enabled.  Read the data from REV_FILE.
+ * Allocate temporaries in SCRATCH_POOL.
  */
 static svn_error_t *
-block_read_changes(apr_array_header_t **changes,
-                   svn_fs_t *fs,
+block_read_changes(svn_fs_t *fs,
                    svn_fs_fs__revision_file_t *rev_file,
                    svn_fs_fs__p2l_entry_t *entry,
-                   svn_boolean_t must_read,
-                   apr_pool_t *result_pool,
                    apr_pool_t *scratch_pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
   svn_stream_t *stream;
-  if (!must_read && !ffd->changes_cache)
+  apr_array_header_t *changes;
+
+  pair_cache_key_t key;
+  key.revision = entry->item.revision;
+  key.second = 0;
+
+  if (!ffd->changes_cache)
     return SVN_NO_ERROR;
 
   /* already in cache? */
-  if (!must_read && ffd->changes_cache)
+  if (ffd->changes_cache)
     {
       svn_boolean_t is_cached;
-      SVN_ERR(svn_cache__has_key(&is_cached, ffd->changes_cache,
-                                 &entry->item.revision,
+      SVN_ERR(svn_cache__has_key(&is_cached, ffd->changes_cache, &key,
                                  scratch_pool));
       if (is_cached)
         return SVN_NO_ERROR;
@@ -3355,14 +3419,32 @@ block_read_changes(apr_array_header_t **
 
   SVN_ERR(read_item(&stream, fs, rev_file, entry, scratch_pool));
 
-  /* read changes from revision file */
-  SVN_ERR(svn_fs_fs__read_changes(changes, stream, result_pool,
-                                  scratch_pool));
+  /* Read changes from revision file.  But read just past the first block to
+     enable us to determine whether the first block already hit the EOL.
 
-  /* cache for future reference */
-  if (ffd->changes_cache)
-    SVN_ERR(svn_cache__set(ffd->changes_cache, &entry->item.revision,
-                           *changes, scratch_pool));
+     Note: A 100 entries block is already > 10kB on disk.  With a 4kB default
+           disk block size, this function won't even be called for larger
+           changed paths lists. */
+  SVN_ERR(svn_fs_fs__read_changes(&changes, stream,
+                                  SVN_FS_FS__CHANGES_BLOCK_SIZE + 1,
+                                  scratch_pool, scratch_pool));
+
+  /* We can only cache small lists that don't need to be split up.
+     For longer lists, we miss the file offset info for the respective */
+  if (changes->nelts <= SVN_FS_FS__CHANGES_BLOCK_SIZE)
+    {
+      svn_fs_fs__changes_list_t changes_list;
+
+      /* Construct the info object for the entries block we just read. */
+      changes_list.end_offset = entry->size;
+      changes_list.start_offset = 0;
+      changes_list.count = changes->nelts;
+      changes_list.changes = (change_t **)changes->elts;
+      changes_list.eol = TRUE;
+
+      SVN_ERR(svn_cache__set(ffd->changes_cache, &key, &changes_list,
+                             scratch_pool));
+    }
 
   return SVN_NO_ERROR;
 }
@@ -3532,10 +3614,8 @@ block_read(void **result,
                     break;
 
                   case SVN_FS_FS__ITEM_TYPE_CHANGES:
-                    SVN_ERR(block_read_changes((apr_array_header_t **)&item,
-                                               fs, revision_file,
-                                               entry, is_result,
-                                               pool, iterpool));
+                    SVN_ERR(block_read_changes(fs, revision_file,
+                                               entry, iterpool));
                     break;
 
                   default:

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/cached_data.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/cached_data.h?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/cached_data.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/cached_data.h Sun Jun  5 15:03:52 2016
@@ -158,13 +158,22 @@ svn_fs_fs__get_proplist(apr_hash_t **pro
                         node_revision_t *noderev,
                         apr_pool_t *pool);
 
-/* Fetch the list of change in revision REV in FS and return it in *CHANGES.
- * Allocate the result in POOL.
+/* Create a changes retrieval context object in *RESULT_POOL and return it
+ * in *CONTEXT.  It will allow svn_fs_x__get_changes to fetch consecutive
+ * blocks (one per invocation) from REV's changed paths list in FS. */
+svn_error_t *
+svn_fs_fs__create_changes_context(svn_fs_fs__changes_context_t **context,
+                                  svn_fs_t *fs,
+                                  svn_revnum_t rev,
+                                  apr_pool_t *result_pool);
+
+/* Fetch the block of changes from the CONTEXT and return it in *CHANGES.
+ * Allocate the result in RESULT_POOL and use SCRATCH_POOL for temporaries.
  */
 svn_error_t *
 svn_fs_fs__get_changes(apr_array_header_t **changes,
-                       svn_fs_t *fs,
-                       svn_revnum_t rev,
-                       apr_pool_t *pool);
+                       svn_fs_fs__changes_context_t *context,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool);
 
 #endif

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/caching.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/caching.c Sun Jun  5 15:03:52 2016
@@ -510,7 +510,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                        1, 8, /* 1k / entry; 8 entries total, rarely used */
                        svn_fs_fs__serialize_changes,
                        svn_fs_fs__deserialize_changes,
-                       sizeof(svn_revnum_t),
+                       sizeof(pair_cache_key_t),
                        apr_pstrcat(pool, prefix, "CHANGES", SVN_VA_NULL),
                        0,
                        has_namespace,

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.h?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.h Sun Jun  5 15:03:52 2016
@@ -37,7 +37,7 @@
 #include "private/svn_sqlite.h"
 #include "private/svn_mutex.h"
 
-#include "id.h"
+#include "rev_file.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -193,6 +193,11 @@ extern "C" {
 #define SVN_FS_FS__USE_LOCK_MUTEX 0
 #endif
 
+/* Maximum number of changes we deliver per request when listing the
+   changed paths for a given revision.   Anything > 0 will do.
+   At 100..300 bytes per entry, this limits the allocation to ~30kB. */
+#define SVN_FS_FS__CHANGES_BLOCK_SIZE 100
+
 /* Private FSFS-specific data shared between all svn_txn_t objects that
    relate to a particular transaction in a filesystem (as identified
    by transaction id and filesystem UUID).  Objects of this type are
@@ -383,8 +388,8 @@ typedef struct fs_fs_data_t
   /* Cache for node_revision_t objects; the key is (revision, item_index) */
   svn_cache__t *node_revision_cache;
 
-  /* Cache for change lists as APR arrays of change_t * objects; the key
-     is the revision */
+  /* Cache for change lists n blocks as svn_fs_fs__changes_list_t * objects;
+     the key is the (revision, first-element-in-block) pair. */
   svn_cache__t *changes_cache;
 
   /* Cache for svn_fs_fs__rep_header_t objects; the key is a
@@ -624,6 +629,33 @@ typedef struct change_t
 } change_t;
 
 
+/*** Context for reading changed paths lists iteratively. */
+typedef struct svn_fs_fs__changes_context_t
+{
+  /* Repository to fetch from. */
+  svn_fs_t *fs;
+
+  /* Revision that we read from. */
+  svn_revnum_t revision;
+
+  /* Revision file object to use when needed.  NULL until the first access. */
+  svn_fs_fs__revision_file_t *revision_file;
+
+  /* Pool to create REVISION_FILE in. */
+  apr_pool_t *rev_file_pool;
+
+  /* Index of the next change to fetch. */
+  apr_size_t next;
+
+  /* Offset, within the changed paths list on disk, of the next change to
+     fetch. */
+  apr_off_t next_offset;
+
+  /* Has the end of the list been reached? */
+  svn_boolean_t eol;
+
+} svn_fs_fs__changes_context_t;
+
 /*** Directory (only used at the cache interface) ***/
 typedef struct svn_fs_fs__dir_data_t
 {

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/low_level.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/low_level.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/low_level.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/low_level.c Sun Jun  5 15:03:52 2016
@@ -482,10 +482,10 @@ read_change(change_t **change_p,
 svn_error_t *
 svn_fs_fs__read_changes(apr_array_header_t **changes,
                         svn_stream_t *stream,
+                        int max_count,
                         apr_pool_t *result_pool,
                         apr_pool_t *scratch_pool)
 {
-  change_t *change;
   apr_pool_t *iterpool;
 
   /* Pre-allocate enough room for most change lists.
@@ -498,13 +498,16 @@ svn_fs_fs__read_changes(apr_array_header
    */
   *changes = apr_array_make(result_pool, 63, sizeof(change_t *));
 
-  SVN_ERR(read_change(&change, stream, result_pool, scratch_pool));
   iterpool = svn_pool_create(scratch_pool);
-  while (change)
+  for (; max_count > 0; --max_count)
     {
-      APR_ARRAY_PUSH(*changes, change_t*) = change;
-      SVN_ERR(read_change(&change, stream, result_pool, iterpool));
+      change_t *change;
       svn_pool_clear(iterpool);
+      SVN_ERR(read_change(&change, stream, result_pool, iterpool));
+      if (!change)
+        break;
+ 
+      APR_ARRAY_PUSH(*changes, change_t*) = change;
     }
   svn_pool_destroy(iterpool);
 

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/low_level.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/low_level.h?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/low_level.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/low_level.h Sun Jun  5 15:03:52 2016
@@ -97,11 +97,13 @@ svn_fs_fs__unparse_footer(apr_off_t l2p_
                           apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool);
 
-/* Read all the changes from STREAM and store them in *CHANGES,
-   allocated in RESULT_POOL. Do temporary allocations in SCRATCH_POOL. */
+/* Read up to MAX_COUNT of the changes from STREAM and store them in
+   *CHANGES, allocated in RESULT_POOL.  Do temporary allocations in
+   SCRATCH_POOL. */
 svn_error_t *
 svn_fs_fs__read_changes(apr_array_header_t **changes,
                         svn_stream_t *stream,
+                        int max_count,
                         apr_pool_t *result_pool,
                         apr_pool_t *scratch_pool);
 

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/rep-cache.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/rep-cache.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/rep-cache.c Sun Jun  5 15:03:52 2016
@@ -51,13 +51,6 @@ path_rep_cache_db(const char *fs_path,
   return svn_dirent_join(fs_path, REP_CACHE_DB_NAME, result_pool);
 }
 
-#define SVN_ERR_CLOSE(x, db) do                                       \
-{                                                                     \
-  svn_error_t *svn__err = (x);                                        \
-  if (svn__err)                                                       \
-    return svn_error_compose_create(svn__err, svn_sqlite__close(db)); \
-} while (0)
-
 
 /** Library-private API's. **/
 
@@ -107,12 +100,15 @@ open_rep_cache(void *baton,
                            0, NULL, 0,
                            fs->pool, pool));
 
-  SVN_ERR_CLOSE(svn_sqlite__read_schema_version(&version, sdb, pool), sdb);
+  SVN_SQLITE__ERR_CLOSE(svn_sqlite__read_schema_version(&version, sdb, pool),
+                        sdb);
   if (version < REP_CACHE_SCHEMA_FORMAT)
     {
       /* Must be 0 -- an uninitialized (no schema) database. Create
          the schema. Results in schema version of 1.  */
-      SVN_ERR_CLOSE(svn_sqlite__exec_statements(sdb, STMT_CREATE_SCHEMA), sdb);
+      SVN_SQLITE__ERR_CLOSE(svn_sqlite__exec_statements(sdb,
+                                                        STMT_CREATE_SCHEMA),
+                            sdb);
     }
 
   /* This is used as a flag that the database is available so don't

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/stats.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/stats.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/stats.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/stats.c Sun Jun  5 15:03:52 2016
@@ -681,19 +681,25 @@ get_phys_change_count(query_t *query,
                       revision_info_t *revision_info,
                       apr_pool_t *scratch_pool)
 {
-  /* We are going to use our own sub-pool here because the changes object
-   * may well be >100MB and SCRATCH_POOL may not get cleared until all other
-   * info has been read by read_phys_revision().  Therefore, tidy up early.
-   */
-  apr_pool_t *subpool = svn_pool_create(scratch_pool);
-  apr_array_header_t *changes;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  svn_fs_fs__changes_context_t *context;
 
-  SVN_ERR(svn_fs_fs__get_changes(&changes, query->fs,
-                                 revision_info->revision, subpool));
-  revision_info->change_count = changes->nelts;
+  /* Fetch the first block of data. */
+  SVN_ERR(svn_fs_fs__create_changes_context(&context, query->fs,
+                                            revision_info->revision,
+                                            scratch_pool));
 
-  /* Release potentially tons of memory. */
-  svn_pool_destroy(subpool);
+  revision_info->change_count = 0;
+  while (!context->eol)
+    {
+      apr_array_header_t *changes;
+
+      svn_pool_clear(iterpool);
+      SVN_ERR(svn_fs_fs__get_changes(&changes, context, iterpool, iterpool));
+      revision_info->change_count = changes->nelts;
+    }
+
+  svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/temp_serializer.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/temp_serializer.c Sun Jun  5 15:03:52 2016
@@ -1224,47 +1224,29 @@ deserialize_change(void *buffer, change_
   svn_temp_deserializer__resolve(change, (void **)&change->info.copyfrom_path);
 }
 
-/* Auxiliary structure representing the content of a change_t array.
-   This structure is much easier to (de-)serialize than an APR array.
- */
-typedef struct changes_data_t
-{
-  /* number of entries in the array */
-  int count;
-
-  /* reference to the changes */
-  change_t **changes;
-} changes_data_t;
-
 svn_error_t *
 svn_fs_fs__serialize_changes(void **data,
                              apr_size_t *data_len,
                              void *in,
                              apr_pool_t *pool)
 {
-  apr_array_header_t *array = in;
-  changes_data_t changes;
+  svn_fs_fs__changes_list_t *changes = in;
   svn_temp_serializer__context_t *context;
   svn_stringbuf_t *serialized;
   int i;
 
-  /* initialize our auxiliary data structure and link it to the
-   * array elements */
-  changes.count = array->nelts;
-  changes.changes = (change_t **)array->elts;
-
   /* serialize it and all its elements */
-  context = svn_temp_serializer__init(&changes,
-                                      sizeof(changes),
-                                      changes.count * 250,
+  context = svn_temp_serializer__init(changes,
+                                      sizeof(*changes),
+                                      changes->count * 250,
                                       pool);
 
   svn_temp_serializer__push(context,
-                            (const void * const *)&changes.changes,
-                            changes.count * sizeof(change_t*));
+                            (const void * const *)&changes->changes,
+                            changes->count * sizeof(*changes->changes));
 
-  for (i = 0; i < changes.count; ++i)
-    serialize_change(context, &changes.changes[i]);
+  for (i = 0; i < changes->count; ++i)
+    serialize_change(context, &changes->changes[i]);
 
   svn_temp_serializer__pop(context);
 
@@ -1284,8 +1266,7 @@ svn_fs_fs__deserialize_changes(void **ou
                                apr_pool_t *pool)
 {
   int i;
-  changes_data_t *changes = (changes_data_t *)data;
-  apr_array_header_t *array = apr_array_make(pool, 0, sizeof(change_t *));
+  svn_fs_fs__changes_list_t *changes = (svn_fs_fs__changes_list_t *)data;
 
   /* de-serialize our auxiliary data structure */
   svn_temp_deserializer__resolve(changes, (void**)&changes->changes);
@@ -1295,14 +1276,8 @@ svn_fs_fs__deserialize_changes(void **ou
     deserialize_change(changes->changes,
                        (change_t **)&changes->changes[i]);
 
-  /* Use the changes buffer as the array's data buffer
-   * (DATA remains valid for at least as long as POOL). */
-  array->elts = (char *)changes->changes;
-  array->nelts = changes->count;
-  array->nalloc = changes->count;
-
   /* done */
-  *out = array;
+  *out = changes;
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/temp_serializer.h?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/temp_serializer.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/temp_serializer.h Sun Jun  5 15:03:52 2016
@@ -359,9 +359,34 @@ svn_fs_fs__deserialize_rep_header(void *
                                   apr_size_t data_len,
                                   apr_pool_t *pool);
 
+/*** Block of changes in a changed paths list. */
+typedef struct svn_fs_fs__changes_list_t
+{
+  /* Offset of the first element in CHANGES within the changed paths list
+     on disk. */
+  apr_off_t start_offset;
+
+  /* Offset of the first element behind CHANGES within the changed paths
+     list on disk. */
+  apr_off_t end_offset;
+
+  /* End of list reached? This may have false negatives in case the number
+     of elements in the list is a multiple of our block / range size. */
+  svn_boolean_t eol;
+
+  /* Array of #svn_fs_x__change_t * representing a consecutive sub-range of
+     elements in a changed paths list. */
+
+  /* number of entries in the array */
+  int count;
+
+  /* reference to the changes */
+  change_t **changes;
+
+} svn_fs_fs__changes_list_t;
+
 /**
- * Implements #svn_cache__serialize_func_t for an #apr_array_header_t of
- * #change_t *.
+ * Implements #svn_cache__serialize_func_t for a #svn_fs_fs__changes_list_t.
  */
 svn_error_t *
 svn_fs_fs__serialize_changes(void **data,
@@ -370,8 +395,7 @@ svn_fs_fs__serialize_changes(void **data
                              apr_pool_t *pool);
 
 /**
- * Implements #svn_cache__deserialize_func_t for an #apr_array_header_t of
- * #change_t *.
+ * Implements #svn_cache__deserialize_func_t for a #svn_fs_fs__changes_list_t.
  */
 svn_error_t *
 svn_fs_fs__deserialize_changes(void **out,

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/transaction.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/transaction.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/transaction.c Sun Jun  5 15:03:52 2016
@@ -932,20 +932,36 @@ svn_fs_fs__paths_changed(apr_hash_t **ch
                          svn_revnum_t rev,
                          apr_pool_t *pool)
 {
-  apr_hash_t *changed_paths;
-  apr_array_header_t *changes;
-  int i;
+  apr_hash_t *changed_paths = svn_hash__make(pool);
+  svn_fs_fs__changes_context_t *context;
 
-  SVN_ERR(svn_fs_fs__get_changes(&changes, fs, rev, pool));
+  apr_pool_t *iterpool = svn_pool_create(pool);
 
-  changed_paths = svn_hash__make(pool);
-  for (i = 0; i < changes->nelts; ++i)
+  /* Fetch all data block-by-block. */
+  SVN_ERR(svn_fs_fs__create_changes_context(&context, fs, rev, pool));
+  while (!context->eol)
     {
-      change_t *change = APR_ARRAY_IDX(changes, i, change_t *);
-      apr_hash_set(changed_paths, change->path.data, change->path.len,
-                   &change->info);
+      apr_array_header_t *changes;
+      int i;
+
+      svn_pool_clear(iterpool);
+
+      /* Be sure to allocate the changes in the result POOL, even though
+         we don't need the array itself afterwards.  Copying the entries
+         from a temp pool to the result POOL would be expensive and saves
+         use less then 10% memory. */
+      SVN_ERR(svn_fs_fs__get_changes(&changes, context, pool, iterpool));
+
+      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);
+        }
     }
 
+  svn_pool_destroy(iterpool);
+
   *changed_paths_p = changed_paths;
 
   return SVN_NO_ERROR;

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/tree.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/tree.c Sun Jun  5 15:03:52 2016
@@ -3281,6 +3281,187 @@ fs_paths_changed(apr_hash_t **changed_pa
 }
 
 
+/* Copy the contents of ENTRY at PATH with LEN to OUTPUT. */
+static void
+convert_path_change(svn_fs_path_change3_t *output,
+                    const char *path,
+                    size_t path_len,
+                    svn_fs_path_change2_t *entry)
+{
+  output->path.data = path;
+  output->path.len = path_len;
+  output->change_kind = entry->change_kind;
+  output->node_kind = entry->node_kind;
+  output->text_mod = entry->text_mod;
+  output->prop_mod = entry->prop_mod;
+  output->mergeinfo_mod = entry->mergeinfo_mod;
+  output->copyfrom_known = entry->copyfrom_known;
+  output->copyfrom_rev = entry->copyfrom_rev;
+  output->copyfrom_path = entry->copyfrom_path;
+}
+
+/* FSAP data structure for in-txn changes list iterators. */
+typedef struct fs_txn_changes_iterator_data_t
+{
+  /* Current iterator position. */
+  apr_hash_index_t *hi;
+
+  /* For efficiency such that we don't need to dynamically allocate
+     yet another copy of that data. */
+  svn_fs_path_change3_t change;
+} fs_txn_changes_iterator_data_t;
+
+/* Implement changes_iterator_vtable_t.get for in-txn change lists. */
+static svn_error_t *
+fs_txn_changes_iterator_get(svn_fs_path_change3_t **change,
+                            svn_fs_path_change_iterator_t *iterator)
+{
+  fs_txn_changes_iterator_data_t *data = iterator->fsap_data;
+
+  if (data->hi)
+    {
+      const void *key;
+      apr_ssize_t length;
+      void *value;
+      apr_hash_this(data->hi, &key, &length, &value);
+
+      convert_path_change(&data->change, key, length, value);
+
+      *change = &data->change;
+      data->hi = apr_hash_next(data->hi);
+    }
+  else
+    {
+      *change = NULL;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static changes_iterator_vtable_t txn_changes_iterator_vtable =
+{
+  fs_txn_changes_iterator_get
+};
+
+/* FSAP data structure for in-revision changes list iterators. */
+typedef struct fs_revision_changes_iterator_data_t
+{
+  /* Context that tells the lower layers from where to fetch the next
+     block of changes. */
+  svn_fs_fs__changes_context_t *context;
+
+  /* Changes to send. */
+  apr_array_header_t *changes;
+
+  /* Current indexes within CHANGES. */
+  int idx;
+
+  /* For efficiency such that we don't need to dynamically allocate
+     yet another copy of that data. */
+  svn_fs_path_change3_t change;
+
+  /* A cleanable scratch pool in case we need one.
+     No further sub-pool creation necessary. */
+  apr_pool_t *scratch_pool;
+} fs_revision_changes_iterator_data_t;
+
+/* Implement changes_iterator_vtable_t.get for in-revision change lists. */
+static svn_error_t *
+fs_revision_changes_iterator_get(svn_fs_path_change3_t **change,
+                                 svn_fs_path_change_iterator_t *iterator)
+{
+  fs_revision_changes_iterator_data_t *data = iterator->fsap_data;
+
+  /* If we exhausted our block of changes and did not reach the end of the
+     list, yet, fetch the next block.  Note that that block may be empty. */
+  if ((data->idx >= data->changes->nelts) && !data->context->eol)
+    {
+      apr_pool_t *changes_pool = data->changes->pool;
+
+      /* Drop old changes block, read new block. */
+      svn_pool_clear(changes_pool);
+      SVN_ERR(svn_fs_fs__get_changes(&data->changes, data->context,
+                                     changes_pool, data->scratch_pool));
+      data->idx = 0;
+
+      /* Immediately release any temporary data. */
+      svn_pool_clear(data->scratch_pool);
+    }
+
+  if (data->idx < data->changes->nelts)
+    {
+      change_t *entry = APR_ARRAY_IDX(data->changes, data->idx, change_t *);
+      convert_path_change(&data->change, entry->path.data, entry->path.len,
+                          &entry->info);
+
+      *change = &data->change;
+      ++data->idx;
+    }
+  else
+    {
+      *change = NULL;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static changes_iterator_vtable_t rev_changes_iterator_vtable =
+{
+  fs_revision_changes_iterator_get
+};
+
+static svn_error_t *
+fs_report_changes(svn_fs_path_change_iterator_t **iterator,
+                  svn_fs_root_t *root,
+                  apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool)
+{
+  svn_fs_path_change_iterator_t *result = apr_pcalloc(result_pool,
+                                                      sizeof(*result));
+  if (root->is_txn_root)
+    {
+      fs_txn_changes_iterator_data_t *data = apr_pcalloc(result_pool,
+                                                         sizeof(*data));
+      apr_hash_t *changed_paths;
+      SVN_ERR(svn_fs_fs__txn_changes_fetch(&changed_paths, root->fs,
+                                           root_txn_id(root), result_pool));
+
+      data->hi = apr_hash_first(result_pool, changed_paths);
+      result->fsap_data = data;
+      result->vtable = &txn_changes_iterator_vtable;
+    }
+  else
+    {
+      /* The block of changes that we retrieve need to live in a separately
+         cleanable pool. */
+      apr_pool_t *changes_pool = svn_pool_create(result_pool);
+
+      /* Our iteration context info. */
+      fs_revision_changes_iterator_data_t *data = apr_pcalloc(result_pool,
+                                                              sizeof(*data));
+
+      /* This pool must remain valid as long as ITERATOR lives but will
+         be used only for temporary allocations and will be cleaned up
+         frequently.  So, this must be a sub-pool of RESULT_POOL. */
+      data->scratch_pool = svn_pool_create(result_pool);
+
+      /* Fetch the first block of data. */
+      SVN_ERR(svn_fs_fs__create_changes_context(&data->context,
+                                                root->fs, root->rev,
+                                                result_pool));
+      SVN_ERR(svn_fs_fs__get_changes(&data->changes, data->context,
+                                     changes_pool, scratch_pool));
+
+      /* Return the fully initialized object. */
+      result->fsap_data = data;
+      result->vtable = &rev_changes_iterator_vtable;
+    }
+
+  *iterator = result;
+
+  return SVN_NO_ERROR;
+}
+
 
 /* Our coolio opaque history object. */
 typedef struct fs_history_data_t
@@ -4325,7 +4506,7 @@ fs_get_mergeinfo(svn_mergeinfo_catalog_t
 /* The vtable associated with root objects. */
 static root_vtable_t root_vtable = {
   fs_paths_changed,
-  NULL,
+  fs_report_changes,
   svn_fs_fs__check_path,
   fs_node_history,
   svn_fs_fs__node_id,

Propchange: subversion/branches/authzperf/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sun Jun  5 15:03:52 2016
@@ -94,5 +94,5 @@
 /subversion/branches/verify-at-commit/subversion/libsvn_fs_x:1462039-1462408
 /subversion/branches/verify-keep-going/subversion/libsvn_fs_x:1439280-1492639,1546002-1546110
 /subversion/branches/wc-collate-path/subversion/libsvn_fs_x:1402685-1480384
-/subversion/trunk/subversion/libsvn_fs_fs:1415133-1596500,1596567,1597414,1597989,1598273,1599140,1600872,1601633,1603485-1603487,1603499,1603605,1604128,1604188,1604413-1604414,1604416-1604417,1604421,1604442,1604700,1604717,1604720,1604726,1604755,1604794,1604802,1604824,1604836,1604844,1604902-1604903,1604911,1604925,1604933,1604947,1605059-1605060,1605064-1605065,1605068,1605071-1605073,1605075,1605123,1605188-1605189,1605191,1605197,1605444,1605633,1606132,1606142,1606144,1606514,1606526,1606528,1606551,1606554,1606564,1606598-1606599,1606656,1606658,1606662,1606744,1606840,1607085,1607572,1612407,1612810,1613339,1613872,1614611,1615348,1615351-1615352,1615356,1616338-1616339,1616613,1617586,1617688,1618138,1618151,1618153,1618226,1618641,1618653,1618662,1619068,1619358,1619413,1619769,1619774,1620602,1620909,1620912,1620928,1620930,1621275,1621635,1622931,1622937,1622942,1622946,1622959-1622960,1622963,1622987,1623007,1623368,1623373,1623377,1623379,1623381,1623398,1623402,162
 4011,1624265,1624512,1626246,1626871,1626873,1626886,1627497-1627498,1627502,1627947-1627949,1627966,1628083,1628093,1628158-1628159,1628161,1628392-1628393,1628415,1628427,1628676,1628738,1628762,1628764,1629854-1629855,1629857,1629865,1629873,1629875,1629879,1630067,1630070,1631049-1631051,1631075,1631115,1631171,1631180,1631185-1631186,1631196-1631197,1631239-1631240,1631548,1631550,1631563,1631567,1631588,1631598,1632646,1632776,1632849,1632851-1632853,1632856-1632857,1632868,1632908,1632926,1633232,1633617-1633618,1634872,1634875,1634879-1634880,1634920,1636478,1636483,1636629,1636644,1637184,1637186,1637330,1637358,1637363,1637393,1639319,1639322,1639335,1639348,1639352,1639355,1639358,1639414,1639419,1639426,1639430,1639436,1639440,1639549,1640061-1640062,1640197,1640915,1640966,1641013,1643139,1643233,1645567,1646021,1646712,1646716,1647537,1647540-1647541,1647820,1647905,1648230,1648238,1648241-1648243,1648253,1648272,1648532,1648537-1648539,1648542,1648591,1648612,1649590,
 1651567,1652068,1652076,1652441,1652451,1653608,1654932,1654934,1654937,1655635,1655649,1655651,1655664,1656176,1657525,1657972,1657978,1658482,1659212,1659217,1659314,1659509,1662668,1665318,1665854,1665894,1667090,1667101,1667538,1669743,1669746,1669749,1669945,1670139,1670953,1673170,1673197,1673202,1673204,1673445,1673454,1673685,1673689,1673875,1674165,1674341,1674400,1674404,1674631,1674669,1674673,1675396,1676667,1677431,1678149,1678151,1678718,1678725,1679169,1679907,1679920-1679924,1679926,1680347,1680460,1680464,1680476,1680819,1681949,1681966,1681974,1681994,1682008,1682076,1682086,1682093,1682259,1682265,1682739,1682864,1683311,1683330,1683378,1683544,1683553,1684047,1686232,1686542,1686546,1686554,1686557,1687061,1687064,1687070-1687071,1687074,1687078-1687079,1688270,1688425,1692650,1693886,1694489,1694848,1696171,1696185,1696627-1696628,1696630,1696758,1697372,1697381,1697387,1697393,1697403,1697405,1701017,1701053,1702600,1702922,1703069,1703142,1703237,1703240,17052
 66,1705638,1705643,1705646,1705724,1705730,1705739,1706612,1706615,1706617,1706619,1706675-1706676,1706679,1706979-1706980,1707308,1707971-1707973,1707986,1707988-1707989,1708004,1709388,1709799,1710017,1710359,1710368,1710370,1711507,1711582,1711672,1712927,1715793,1715947,1716047,1716067,1716784,1716973-1716974,1717332,1717334,1717864,1719269,1719336,1719413,1719730,1720015,1721285,1723715,1723720,1723834,1723839,1725179-1725180,1726004
-/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1613053-1741675
+/subversion/trunk/subversion/libsvn_fs_fs:1415133-1596500,1596567,1597414,1597989,1598273,1599140,1600872,1601633,1603485-1603487,1603499,1603605,1604128,1604188,1604413-1604414,1604416-1604417,1604421,1604442,1604700,1604717,1604720,1604726,1604755,1604794,1604802,1604824,1604836,1604844,1604902-1604903,1604911,1604925,1604933,1604947,1605059-1605060,1605064-1605065,1605068,1605071-1605073,1605075,1605123,1605188-1605189,1605191,1605197,1605444,1605633,1606132,1606142,1606144,1606514,1606526,1606528,1606551,1606554,1606564,1606598-1606599,1606656,1606658,1606662,1606744,1606840,1607085,1607572,1612407,1612810,1613339,1613872,1614611,1615348,1615351-1615352,1615356,1616338-1616339,1616613,1617586,1617688,1618138,1618151,1618153,1618226,1618641,1618653,1618662,1619068,1619358,1619413,1619769,1619774,1620602,1620909,1620912,1620928,1620930,1621275,1621635,1622931,1622937,1622942,1622946,1622959-1622960,1622963,1622987,1623007,1623368,1623373,1623377,1623379,1623381,1623398,1623402,162
 4011,1624265,1624512,1626246,1626871,1626873,1626886,1627497-1627498,1627502,1627947-1627949,1627966,1628083,1628093,1628158-1628159,1628161,1628392-1628393,1628415,1628427,1628676,1628738,1628762,1628764,1629854-1629855,1629857,1629865,1629873,1629875,1629879,1630067,1630070,1631049-1631051,1631075,1631115,1631171,1631180,1631185-1631186,1631196-1631197,1631239-1631240,1631548,1631550,1631563,1631567,1631588,1631598,1632646,1632776,1632849,1632851-1632853,1632856-1632857,1632868,1632908,1632926,1633232,1633617-1633618,1634872,1634875,1634879-1634880,1634920,1636478,1636483,1636629,1636644,1637184,1637186,1637330,1637358,1637363,1637393,1639319,1639322,1639335,1639348,1639352,1639355,1639358,1639414,1639419,1639426,1639430,1639436,1639440,1639549,1640061-1640062,1640197,1640915,1640966,1641013,1643139,1643233,1645567,1646021,1646712,1646716,1647537,1647540-1647541,1647820,1647905,1648230,1648238,1648241-1648243,1648253,1648272,1648532,1648537-1648539,1648542,1648591,1648612,1649590,
 1651567,1652068,1652076,1652441,1652451,1653608,1654932,1654934,1654937,1655635,1655649,1655651,1655664,1656176,1657525,1657972,1657978,1658482,1659212,1659217,1659314,1659509,1662668,1665318,1665854,1665894,1667090,1667101,1667538,1669743,1669746,1669749,1669945,1670139,1670953,1673170,1673197,1673202,1673204,1673445,1673454,1673685,1673689,1673875,1674165,1674341,1674400,1674404,1674631,1674669,1674673,1675396,1676667,1677431,1678149,1678151,1678718,1678725,1679169,1679907,1679920-1679924,1679926,1680347,1680460,1680464,1680476,1680819,1681949,1681966,1681974,1681994,1682008,1682076,1682086,1682093,1682259,1682265,1682739,1682864,1683311,1683330,1683378,1683544,1683553,1684047,1686232,1686542,1686546,1686554,1686557,1687061,1687064,1687070-1687071,1687074,1687078-1687079,1688270,1688425,1692650,1693886,1694489,1694848,1696171,1696185,1696627-1696628,1696630,1696758,1697372,1697381,1697387,1697393,1697403,1697405,1701017,1701053,1702600,1702922,1703069,1703142,1703237,1703240,17052
 66,1705638,1705643,1705646,1705724,1705730,1705739,1706612,1706615,1706617,1706619,1706675-1706676,1706679,1706979-1706980,1707308,1707971-1707973,1707986,1707988-1707989,1708004,1709388,1709799,1710017,1710359,1710368,1710370,1711507,1711582,1711672,1712927,1715793,1715947,1716047,1716067,1716784,1716973-1716974,1717332,1717334,1717864,1719269,1719336,1719413,1719730,1720015,1721285,1723715,1723720,1723834,1723839,1725179-1725180,1726004,1726099,1726116,1726897,1726995,1727006-1727007,1727028,1727040,1727707,1727822,1730491,1735916,1736357,1736359,1737355-1737356,1740721-1740722,1741096,1741200,1741206,1741214,1741224,1742540,1745055,1745107,1745852,1746006,1746012,1746026
+/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1613053-1746926

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/batch_fsync.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/batch_fsync.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/batch_fsync.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/batch_fsync.c Sun Jun  5 15:03:52 2016
@@ -203,6 +203,9 @@ struct svn_fs_x__batch_fsync_t
 
   /* Counts the number of completed fsync tasks. */
   waitable_counter_t *counter;
+
+  /* Perform fsyncs only if this flag has been set. */
+  svn_boolean_t flush_to_disk;
 };
 
 /* Data structures for concurrent fsync execution are only available if
@@ -299,10 +302,12 @@ fsync_batch_cleanup(void *data)
 
 svn_error_t *
 svn_fs_x__batch_fsync_create(svn_fs_x__batch_fsync_t **result_p,
+                             svn_boolean_t flush_to_disk,
                              apr_pool_t *result_pool)
 {
   svn_fs_x__batch_fsync_t *result = apr_pcalloc(result_pool, sizeof(*result));
   result->files = svn_hash__make(result_pool);
+  result->flush_to_disk = flush_to_disk;
 
   SVN_ERR(waitable_counter__create(&result->counter, result_pool));
   apr_pool_cleanup_register(result_pool, result, fsync_batch_cleanup,
@@ -493,33 +498,38 @@ svn_fs_x__batch_fsync_run(svn_fs_x__batc
                                    waitable_counter__reset(batch->counter));
 
   /* Start the actual fsyncing process. */
-  for (hi = apr_hash_first(scratch_pool, batch->files);
-       hi;
-       hi = apr_hash_next(hi))
+  if (batch->flush_to_disk)
     {
-      to_sync_t *to_sync = apr_hash_this_val(hi);
+      for (hi = apr_hash_first(scratch_pool, batch->files);
+           hi;
+           hi = apr_hash_next(hi))
+        {
+          to_sync_t *to_sync = apr_hash_this_val(hi);
 
 #if APR_HAS_THREADS
 
-      /* If there are multiple fsyncs to perform, run them in parallel.
-       * Otherwise, skip the thread-pool and synchronization overhead. */
-      if (apr_hash_count(batch->files) > 1)
-        {
-          apr_status_t status = APR_SUCCESS;
-          status = apr_thread_pool_push(thread_pool, flush_task, to_sync,
-                                        0, NULL);
-          if (status)
-            to_sync->result = svn_error_wrap_apr(status, _("Can't push task"));
+          /* If there are multiple fsyncs to perform, run them in parallel.
+           * Otherwise, skip the thread-pool and synchronization overhead. */
+          if (apr_hash_count(batch->files) > 1)
+            {
+              apr_status_t status = APR_SUCCESS;
+              status = apr_thread_pool_push(thread_pool, flush_task, to_sync,
+                                            0, NULL);
+              if (status)
+                to_sync->result = svn_error_wrap_apr(status,
+                                                     _("Can't push task"));
+              else
+                tasks++;
+            }
           else
-            tasks++;
-        }
-      else
 
 #endif
 
-        {
-          to_sync->result = svn_error_trace(svn_io_file_flush_to_disk
-                                              (to_sync->file, to_sync->pool));
+            {
+              to_sync->result = svn_error_trace(svn_io_file_flush_to_disk
+                                                  (to_sync->file,
+                                                   to_sync->pool));
+            }
         }
     }
 
@@ -534,7 +544,9 @@ svn_fs_x__batch_fsync_run(svn_fs_x__batc
        hi = apr_hash_next(hi))
     {
       to_sync_t *to_sync = apr_hash_this_val(hi);
-      chain = svn_error_compose_create(chain, to_sync->result);
+      if (batch->flush_to_disk)
+        chain = svn_error_compose_create(chain, to_sync->result);
+
       chain = svn_error_compose_create(chain,
                                        svn_io_file_close(to_sync->file,
                                                          scratch_pool));

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/batch_fsync.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/batch_fsync.h?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/batch_fsync.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/batch_fsync.h Sun Jun  5 15:03:52 2016
@@ -52,9 +52,12 @@ typedef struct svn_fs_x__batch_fsync_t s
 svn_error_t *
 svn_fs_x__batch_fsync_init(void);
 
-/* Set *RESULT_P to a new batch fsync structure, allocated in RESULT_POOL. */
+/* Set *RESULT_P to a new batch fsync structure, allocated in RESULT_POOL.
+ * If FLUSH_TO_DISK is not set, the resulting struct will not actually use
+ * fsync. */
 svn_error_t *
 svn_fs_x__batch_fsync_create(svn_fs_x__batch_fsync_t **result_p,
+                             svn_boolean_t flush_to_disk,
                              apr_pool_t *result_pool);
 
 /* Open the file at FILENAME for read and write access.  Return it in *FILE

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/cached_data.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/cached_data.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/cached_data.c Sun Jun  5 15:03:52 2016
@@ -2861,14 +2861,26 @@ svn_fs_x__get_changes(apr_array_header_t
     }
   else
     {
-      svn_fs_x__read_changes_block_baton_t baton;
-      baton.start = (int)context->next;
-      baton.eol = &context->eol;
-
-      SVN_ERR(svn_cache__get_partial((void **)changes, &found,
-                                     ffd->changes_cache, &context->revision,
-                                     svn_fs_x__read_changes_block,
-                                     &baton, result_pool));
+      svn_fs_x__changes_list_t *changes_list;
+      svn_fs_x__pair_cache_key_t key;
+      key.revision = context->revision;
+      key.second = context->next;
+
+      SVN_ERR(svn_cache__get((void **)&changes_list, &found,
+                             ffd->changes_cache, &key, result_pool));
+
+      if (found)
+        {
+          /* Where to look next - if there is more data. */
+          context->eol = changes_list->eol;
+          context->next_offset = changes_list->end_offset;
+
+          /* Return the block as a "proper" APR array. */
+          (*changes) = apr_array_make(result_pool, 0, sizeof(void *));
+          (*changes)->elts = (char *)changes_list->changes;
+          (*changes)->nelts = changes_list->count;
+          (*changes)->nalloc = changes_list->count;
+        }
     }
 
   if (!found)
@@ -2982,58 +2994,64 @@ block_read_changes(apr_array_header_t **
 {
   svn_fs_x__data_t *ffd = fs->fsap_data;
   svn_stream_t *stream;
-  svn_revnum_t revision = svn_fs_x__get_revnum(entry->items[0].change_set);
-  apr_size_t estimated_size;
+  svn_fs_x__pair_cache_key_t key;
+  svn_fs_x__changes_list_t changes_list;
+
+  /* If we don't have to return any data, just read and cache the first
+     block.  This means we won't cache the remaining blocks from longer
+     lists right away but only if they are actually needed. */
+  apr_size_t next = must_read ? context->next : 0;
+  apr_size_t next_offset = must_read ? context->next_offset : 0;
 
   /* we don't support containers, yet */
   SVN_ERR_ASSERT(entry->item_count == 1);
 
+  /* The item to read / write. */
+  key.revision = svn_fs_x__get_revnum(entry->items[0].change_set);
+  key.second = next;
+
   /* already in cache? */
   if (!must_read)
     {
       svn_boolean_t is_cached = FALSE;
-      SVN_ERR(svn_cache__has_key(&is_cached, ffd->changes_cache, &revision,
+      SVN_ERR(svn_cache__has_key(&is_cached, ffd->changes_cache, &key,
                                  scratch_pool));
       if (is_cached)
         return SVN_NO_ERROR;
     }
 
-  SVN_ERR(read_item(&stream, fs, rev_file, entry, scratch_pool));
+  /* Verify the whole list only once.  We don't use the STREAM any further. */
+  if (!must_read || next == 0)
+    SVN_ERR(read_item(&stream, fs, rev_file, entry, scratch_pool));
+
+  /* Seek to the block to read within the changes list. */
+  SVN_ERR(svn_fs_x__rev_file_seek(rev_file, NULL,
+                                  entry->offset + next_offset));
+  SVN_ERR(svn_fs_x__rev_file_stream(&stream, rev_file));
 
   /* read changes from revision file */
-  SVN_ERR(svn_fs_x__read_changes(changes, stream, result_pool, scratch_pool));
+  SVN_ERR(svn_fs_x__read_changes(changes, stream, SVN_FS_X__CHANGES_BLOCK_SIZE,
+                                 result_pool, scratch_pool));
 
-  /* cache for future reference */
+  SVN_ERR(svn_fs_x__rev_file_offset(&changes_list.end_offset, rev_file));
+  changes_list.end_offset -= entry->offset;
+  changes_list.start_offset = next_offset;
+  changes_list.count = (*changes)->nelts;
+  changes_list.changes = (svn_fs_x__change_t **)(*changes)->elts;
+  changes_list.eol =    (changes_list.count < SVN_FS_X__CHANGES_BLOCK_SIZE)
+                     || (changes_list.end_offset + 1 >= entry->size);
 
-  /* Guesstimate for the size of the in-cache representation. */
-  estimated_size = (apr_size_t)250 * (*changes)->nelts;
+  /* cache for future reference */
 
-  /* Don't even serialize data that probably won't fit into the
-   * cache.  This often implies that either CHANGES is very
-   * large, memory is scarce or both.  Having a huge temporary
-   * copy would not be a good thing in either case. */
-  if (svn_cache__is_cachable(ffd->changes_cache, estimated_size))
-    SVN_ERR(svn_cache__set(ffd->changes_cache, &revision, *changes,
-                           scratch_pool));
+  SVN_ERR(svn_cache__set(ffd->changes_cache, &key, &changes_list,
+                         scratch_pool));
 
   /* Trim the result:
    * Remove the entries that already been reported. */
-
-  /* TODO: This is transitional code.
-   *       The final implementation will read and cache only sections of
-   *       the changes list. */
   if (must_read)
     {
-      int i;
-      for (i = 0; i + context->next < (*changes)->nelts; ++i)
-        {
-          APR_ARRAY_IDX(*changes, i, svn_fs_x__change_t *)
-            = APR_ARRAY_IDX(*changes, i + context->next,
-                            svn_fs_x__change_t *);
-        }
-      (*changes)->nelts = i;
-
-      context->eol = TRUE;
+      context->next_offset = changes_list.end_offset;
+      context->eol = changes_list.eol;
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/caching.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/caching.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/caching.c Sun Jun  5 15:03:52 2016
@@ -487,7 +487,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
                        1, 8, /* 1k / entry; 8 entries total, rarely used */
                        svn_fs_x__serialize_changes,
                        svn_fs_x__deserialize_changes,
-                       sizeof(svn_revnum_t),
+                       sizeof(svn_fs_x__pair_cache_key_t),
                        apr_pstrcat(scratch_pool, prefix, "CHANGES",
                                    SVN_VA_NULL),
                        0,

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/changes.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/changes.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/changes.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/changes.c Sun Jun  5 15:03:52 2016
@@ -221,10 +221,6 @@ svn_fs_x__changes_get_list(apr_array_hea
   int last;
   int i;
 
-  /* Return up to this many entries.  Anything > 0 will do.
-   * At 100..300 bytes per entry, this limits the allocation to ~30kB. */
-  enum { BLOCK_SIZE = 100 };
-
   /* CHANGES must be in 'finalized' mode */
   SVN_ERR_ASSERT(changes->builder == NULL);
   SVN_ERR_ASSERT(changes->paths);
@@ -245,7 +241,7 @@ svn_fs_x__changes_get_list(apr_array_hea
   /* Restrict it to the sub-range requested by the caller.
    * Clip the range to never exceed the list's content. */
   first = MIN(context->next + list_first, list_last);
-  last = MIN(first + BLOCK_SIZE, list_last);
+  last = MIN(first + SVN_FS_X__CHANGES_BLOCK_SIZE, list_last);
 
   /* Indicate to the caller whether the end of the list has been reached. */
   context->eol = last == list_last;
@@ -461,7 +457,6 @@ svn_fs_x__changes_get_list_func(void **o
   int last;
   int i;
   apr_array_header_t *list;
-  enum { BLOCK_SIZE = 100 };
 
   svn_fs_x__changes_get_list_baton_t *b = baton;
   apr_uint32_t idx = b->sub_item;
@@ -498,7 +493,7 @@ svn_fs_x__changes_get_list_func(void **o
   /* Restrict range to the block requested by the BATON.
    * Tell the caller whether we reached the end of the list. */
   first = MIN(first + b->start, last);
-  last = MIN(first + BLOCK_SIZE, last);
+  last = MIN(first + SVN_FS_X__CHANGES_BLOCK_SIZE, last);
   *b->eol = last == offsets[idx+1];
 
   /* construct result */

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/fs.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/fs.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/fs.c Sun Jun  5 15:03:52 2016
@@ -322,6 +322,7 @@ initialize_fs_struct(svn_fs_t *fs)
 {
   svn_fs_x__data_t *ffd = apr_pcalloc(fs->pool, sizeof(*ffd));
   ffd->revprop_generation = -1;
+  ffd->flush_to_disk = TRUE;
 
   fs->vtable = &fs_vtable;
   fs->fsap_data = ffd;

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/fs.h?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/fs.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/fs.h Sun Jun  5 15:03:52 2016
@@ -137,6 +137,11 @@ extern "C" {
 #define SVN_FS_X__USE_LOCK_MUTEX 0
 #endif
 
+/* Maximum number of changes we deliver per request when listing the
+   changed paths for a given revision.   Anything > 0 will do.
+   At 100..300 bytes per entry, this limits the allocation to ~30kB. */
+#define SVN_FS_X__CHANGES_BLOCK_SIZE 100
+
 /* Private FSX-specific data shared between all svn_txn_t objects that
    relate to a particular transaction in a filesystem (as identified
    by transaction id and filesystem UUID).  Objects of this type are
@@ -319,8 +324,8 @@ typedef struct svn_fs_x__data_t
      the key is a (pack file revision, file offset) pair */
   svn_cache__t *noderevs_container_cache;
 
-  /* Cache for change lists as APR arrays of svn_fs_x__change_t * objects;
-     the key is the revision */
+  /* Cache for change lists n blocks as svn_fs_x__changes_list_t * objects;
+     the key is the (revision, first-element-in-block) pair. */
   svn_cache__t *changes_cache;
 
   /* Cache for change_list_t containers;
@@ -398,6 +403,9 @@ typedef struct svn_fs_x__data_t
      or dump / load cycles). */
   const char *instance_id;
 
+  /* Ensure that all filesystem changes are written to disk. */
+  svn_boolean_t flush_to_disk;
+
   /* Pointer to svn_fs_open. */
   svn_error_t *(*svn_fs_open_)(svn_fs_t **, const char *, apr_hash_t *,
                                apr_pool_t *, apr_pool_t *);
@@ -481,7 +489,8 @@ typedef struct svn_fs_x__noderev_t
   /* node kind */
   svn_node_kind_t kind;
 
-  /* number of predecessors this node revision has (recursively). */
+  /* Number of predecessors this node revision has (recursively).
+     A difference from the BDB backend is that it cannot be -1. */
   int predecessor_count;
 
   /* representation key for this node's properties.  may be NULL if
@@ -538,6 +547,10 @@ typedef struct svn_fs_x__changes_context
   /* Index of the next change to fetch. */
   apr_size_t next;
 
+  /* Offset, within the changed paths list on disk, of the next change to
+     fetch. */
+  apr_off_t next_offset;
+
   /* Has the end of the list been reached? */
   svn_boolean_t eol;
 

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/fs_x.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/fs_x.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/fs_x.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/fs_x.c Sun Jun  5 15:03:52 2016
@@ -201,7 +201,7 @@ svn_fs_x__write_format(svn_fs_t *fs,
     {
       SVN_ERR(svn_io_write_atomic2(path, sb->data, sb->len,
                                    NULL /* copy_perms_path */,
-                                   TRUE, scratch_pool));
+                                   ffd->flush_to_disk, scratch_pool));
     }
 
   /* And set the perms to make it read only */
@@ -535,6 +535,20 @@ write_config(svn_fs_t *fs,
                             fsx_conf_contents, scratch_pool);
 }
 
+/* Read / Evaluate the global configuration in FS->CONFIG to set up
+ * parameters in FS. */
+static svn_error_t *
+read_global_config(svn_fs_t *fs)
+{
+  svn_fs_x__data_t *ffd = fs->fsap_data;
+
+  ffd->flush_to_disk = !svn_hash__get_bool(fs->config,
+                                           SVN_FS_CONFIG_NO_FLUSH_TO_DISK,
+                                           FALSE);
+
+  return SVN_NO_ERROR;
+}
+
 /* Read FS's UUID file and store the data in the FS struct. */
 static svn_error_t *
 read_uuid(svn_fs_t *fs,
@@ -603,6 +617,9 @@ svn_fs_x__open(svn_fs_t *fs,
   /* Read the configuration file. */
   SVN_ERR(read_config(ffd, fs->path, fs->pool, scratch_pool));
 
+  /* Global configuration options. */
+  SVN_ERR(read_global_config(fs));
+
   ffd->youngest_rev_cache = 0;
 
   return SVN_NO_ERROR;
@@ -986,6 +1003,9 @@ svn_fs_x__create_file_tree(svn_fs_t *fs,
   SVN_ERR(write_config(fs, scratch_pool));
   SVN_ERR(read_config(ffd, fs->path, fs->pool, scratch_pool));
 
+  /* Global configuration options. */
+  SVN_ERR(read_global_config(fs));
+
   /* Add revision 0. */
   SVN_ERR(write_revision_zero(fs, scratch_pool));
 
@@ -1096,7 +1116,7 @@ svn_fs_x__set_uuid(svn_fs_t *fs,
       SVN_ERR(svn_io_write_atomic2(uuid_path, contents->data, contents->len,
                                    /* perms */
                                    svn_fs_x__path_current(fs, scratch_pool),
-                                   TRUE, scratch_pool));
+                                   ffd->flush_to_disk, scratch_pool));
     }
 
   fs->uuid = apr_pstrdup(fs->pool, uuid);

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/hotcopy.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/hotcopy.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/hotcopy.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/hotcopy.c Sun Jun  5 15:03:52 2016
@@ -555,7 +555,7 @@ typedef struct hotcopy_body_baton_t {
  * An incremental hotcopy copies only changed or new files to the destination,
  * and removes files from the destination no longer present in the source.
  * While the incremental hotcopy is running, readers should still be able
- * to access the destintation repository without error and should not see
+ * to access the destination repository without error and should not see
  * revisions currently in progress of being copied. Readers are able to see
  * new fully copied revisions even if the entire incremental hotcopy procedure
  * has not yet completed.

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/index.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/index.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/index.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/index.c Sun Jun  5 15:03:52 2016
@@ -57,7 +57,7 @@ const apr_uint64_t off_t_max = (sizeof(a
                              : APR_INT32_MAX;
 
 /* We store P2L proto-index entries as 6 values, 64 bits each on disk.
- * See also svn_fs_fs__p2l_proto_index_add_entry().
+ * See also svn_fs_x__p2l_proto_index_add_entry().
  */
 #define P2L_PROTO_INDEX_ENTRY_SIZE (6 * sizeof(apr_uint64_t))
 
@@ -3166,7 +3166,7 @@ compare_p2l_entry_offsets(const void *lh
 }
 
 /* Cached data extraction utility.  DATA is a P2L index page, e.g. an APR
- * array of svn_fs_fs__p2l_entry_t elements.  Return the entry for the item,
+ * array of svn_fs_x__p2l_entry_t elements.  Return the entry for the item,
  * allocated in RESULT_POOL, starting at OFFSET or NULL if that's not an
  * the start offset of any item. Use SCRATCH_POOL for temporary allocations.
  */

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/index.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/index.h?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/index.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/index.h Sun Jun  5 15:03:52 2016
@@ -206,7 +206,7 @@ svn_fs_x__p2l_index_append(svn_checksum_
 /* Use the phys-to-log mapping files in FS to build a list of entries
  * that (at least partly) overlap with the range given by BLOCK_START
  * offset and BLOCK_SIZE in the rep / pack file containing REVISION.
- * Return the array in *ENTRIES with svn_fs_fs__p2l_entry_t as elements,
+ * Return the array in *ENTRIES with svn_fs_x__p2l_entry_t as elements,
  * allocated in RESULT_POOL.  REV_FILE determines whether to access single
  * rev or pack file data.  If that is not available anymore (neither in
  * cache nor on disk), return an error.  Use SCRATCH_POOL for temporary
@@ -309,7 +309,7 @@ svn_fs_x__p2l_get_max_offset(apr_off_t *
 
 /* For FS, create a new L2P auto-deleting proto index file in POOL and return
  * its name in *PROTONAME.  All entries to write are given in ENTRIES and
- * entries are of type svn_fs_fs__p2l_entry_t* (sic!).  The ENTRIES array
+ * entries are of type svn_fs_x__p2l_entry_t* (sic!).  The ENTRIES array
  * will be reordered.  Give the proto index file the lifetime of RESULT_POOL
  * and use SCRATCH_POOL for temporary allocations.
  */
@@ -322,7 +322,7 @@ svn_fs_x__l2p_index_from_p2l_entries(con
 
 /* For FS, create a new P2L auto-deleting proto index file in POOL and return
  * its name in *PROTONAME.  All entries to write are given in ENTRIES and
- * of type svn_fs_fs__p2l_entry_t*.  The FVN1 checksums are not taken from
+ * of type svn_fs_x__p2l_entry_t*.  The FVN1 checksums are not taken from
  * ENTRIES but are begin calculated from the current contents of REV_FILE
  * as we go.  Give the proto index file the lifetime of RESULT_POOL and use
  * SCRATCH_POOL for temporary allocations.

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/lock.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/lock.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/lock.c Sun Jun  5 15:03:52 2016
@@ -937,7 +937,7 @@ lock_body(void *baton,
                                                   lb->result_pool));
 
           /* The INFO->PATH is already allocated in LB->RESULT_POOL as a result
-             of svn_fspath__canonicalize() (see svn_fs_fs__lock()). */
+             of svn_fspath__canonicalize() (see svn_fs_x__lock()). */
           info->lock->path = info->path;
           info->lock->owner = apr_pstrdup(lb->result_pool,
                                           lb->fs->access_ctx->username);

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.c Sun Jun  5 15:03:52 2016
@@ -974,10 +974,10 @@ read_change(svn_fs_x__change_t **change_
 svn_error_t *
 svn_fs_x__read_changes(apr_array_header_t **changes,
                        svn_stream_t *stream,
+                       int max_count,
                        apr_pool_t *result_pool,
                        apr_pool_t *scratch_pool)
 {
-  svn_fs_x__change_t *change;
   apr_pool_t *iterpool;
 
   /* Pre-allocate enough room for most change lists.
@@ -990,13 +990,16 @@ svn_fs_x__read_changes(apr_array_header_
    */
   *changes = apr_array_make(result_pool, 63, sizeof(svn_fs_x__change_t *));
 
-  SVN_ERR(read_change(&change, stream, result_pool, scratch_pool));
   iterpool = svn_pool_create(scratch_pool);
-  while (change)
+  for (; max_count > 0; --max_count)
     {
-      APR_ARRAY_PUSH(*changes, svn_fs_x__change_t*) = change;
-      SVN_ERR(read_change(&change, stream, result_pool, iterpool));
+      svn_fs_x__change_t *change;
       svn_pool_clear(iterpool);
+      SVN_ERR(read_change(&change, stream, result_pool, iterpool));
+      if (!change)
+        break;
+ 
+      APR_ARRAY_PUSH(*changes, svn_fs_x__change_t*) = change;
     }
   svn_pool_destroy(iterpool);
 

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.h?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/low_level.h Sun Jun  5 15:03:52 2016
@@ -170,15 +170,17 @@ svn_fs_x__write_rep_header(svn_fs_x__rep
                            svn_stream_t *stream,
                            apr_pool_t *scratch_pool);
 
-/* Read all the changes from STREAM and store them in *CHANGES,
-   allocated in RESULT_POOL. Do temporary allocations in SCRATCH_POOL. */
+/* Read up to MAX_COUNT of the changes from STREAM and store them in
+   *CHANGES, allocated in RESULT_POOL.  Do temporary allocations in
+   SCRATCH_POOL. */
 svn_error_t *
 svn_fs_x__read_changes(apr_array_header_t **changes,
                        svn_stream_t *stream,
+                       int max_count,
                        apr_pool_t *result_pool,
                        apr_pool_t *scratch_pool);
 
-/* Callback function used by svn_fs_fs__read_changes_incrementally(),
+/* Callback function used by svn_fs_x__read_changes_incrementally(),
  * asking the receiver to process to process CHANGE using BATON.  CHANGE
  * and SCRATCH_POOL will not be valid beyond the current callback invocation.
  */

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/pack.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/pack.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/pack.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/pack.c Sun Jun  5 15:03:52 2016
@@ -1603,8 +1603,8 @@ write_changes_containers(pack_context_t
        * the container */
       SVN_ERR(svn_io_file_seek(temp_file, APR_SET, &entry->offset,
                                iterpool));
-      SVN_ERR(svn_fs_x__read_changes(&changes, temp_stream, scratch_pool,
-                                     iterpool));
+      SVN_ERR(svn_fs_x__read_changes(&changes, temp_stream, INT_MAX,
+                                     scratch_pool, iterpool));
       SVN_ERR(svn_fs_x__changes_append_list(&list_index, container, changes));
       SVN_ERR_ASSERT(list_index == sub_items->nelts);
       block_left -= estimated_size;
@@ -2078,7 +2078,8 @@ pack_shard(const char *dir,
                         scratch_pool));
 
   /* Perform all fsyncs through this instance. */
-  SVN_ERR(svn_fs_x__batch_fsync_create(&batch, scratch_pool));
+  SVN_ERR(svn_fs_x__batch_fsync_create(&batch, ffd->flush_to_disk,
+                                       scratch_pool));
 
   /* Some useful paths. */
   pack_file_dir = svn_dirent_join(dir,

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/rep-cache.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/rep-cache.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/rep-cache.c Sun Jun  5 15:03:52 2016
@@ -100,12 +100,16 @@ open_rep_cache(void *baton,
                            0, NULL, 0,
                            fs->pool, scratch_pool));
 
-  SVN_ERR(svn_sqlite__read_schema_version(&version, sdb, scratch_pool));
+  SVN_SQLITE__ERR_CLOSE(svn_sqlite__read_schema_version(&version, sdb,
+                                                        scratch_pool),
+                        sdb);
   if (version < REP_CACHE_SCHEMA_FORMAT)
     {
       /* Must be 0 -- an uninitialized (no schema) database. Create
          the schema. Results in schema version of 1.  */
-      SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_CREATE_SCHEMA));
+      SVN_SQLITE__ERR_CLOSE(svn_sqlite__exec_statements(sdb,
+                                                        STMT_CREATE_SCHEMA),
+                            sdb);
     }
 
   /* This is used as a flag that the database is available so don't
@@ -126,6 +130,21 @@ svn_fs_x__open_rep_cache(svn_fs_t *fs,
 }
 
 svn_error_t *
+svn_fs_x__close_rep_cache(svn_fs_t *fs)
+{
+  svn_fs_x__data_t *ffd = fs->fsap_data;
+
+  if (ffd->rep_cache_db)
+    {
+      SVN_ERR(svn_sqlite__close(ffd->rep_cache_db));
+      ffd->rep_cache_db = NULL;
+      ffd->rep_cache_db_opened = 0;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_fs_x__exists_rep_cache(svn_boolean_t *exists,
                            svn_fs_t *fs,
                            apr_pool_t *scratch_pool)
@@ -236,7 +255,7 @@ svn_fs_x__walk_rep_reference(svn_fs_t *f
    If you extend this function, check the callsite to see if you have
    to make it not-ignore additional error codes.  */
 svn_error_t *
-svn_fs_x__get_rep_reference(svn_fs_x__representation_t **rep,
+svn_fs_x__get_rep_reference(svn_fs_x__representation_t **rep_p,
                             svn_fs_t *fs,
                             svn_checksum_t *checksum,
                             apr_pool_t *result_pool,
@@ -245,6 +264,7 @@ svn_fs_x__get_rep_reference(svn_fs_x__re
   svn_fs_x__data_t *ffd = fs->fsap_data;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
+  svn_fs_x__representation_t *rep;
 
   SVN_ERR_ASSERT(ffd->rep_sharing_allowed);
   if (! ffd->rep_cache_db)
@@ -263,24 +283,23 @@ svn_fs_x__get_rep_reference(svn_fs_x__re
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
   if (have_row)
     {
-      *rep = apr_pcalloc(result_pool, sizeof(**rep));
-      memcpy((*rep)->sha1_digest, checksum->digest,
-             sizeof((*rep)->sha1_digest));
-      (*rep)->has_sha1 = TRUE;
-      (*rep)->id.change_set = svn_sqlite__column_revnum(stmt, 0);
-      (*rep)->id.number = svn_sqlite__column_int64(stmt, 1);
-      (*rep)->size = svn_sqlite__column_int64(stmt, 2);
-      (*rep)->expanded_size = svn_sqlite__column_int64(stmt, 3);
+      rep = apr_pcalloc(result_pool, sizeof(*rep));
+      memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest));
+      rep->has_sha1 = TRUE;
+      rep->id.change_set = svn_sqlite__column_revnum(stmt, 0);
+      rep->id.number = svn_sqlite__column_int64(stmt, 1);
+      rep->size = svn_sqlite__column_int64(stmt, 2);
+      rep->expanded_size = svn_sqlite__column_int64(stmt, 3);
     }
   else
-    *rep = NULL;
+    rep = NULL;
 
   SVN_ERR(svn_sqlite__reset(stmt));
 
-  if (*rep)
+  if (rep)
     {
       /* Check that REP refers to a revision that exists in FS. */
-      svn_revnum_t revision = svn_fs_x__get_revnum((*rep)->id.change_set);
+      svn_revnum_t revision = svn_fs_x__get_revnum(rep->id.change_set);
       svn_error_t *err = svn_fs_x__ensure_revision_exists(revision, fs,
                                                           scratch_pool);
       if (err)
@@ -289,6 +308,7 @@ svn_fs_x__get_rep_reference(svn_fs_x__re
                    svn_checksum_to_cstring_display(checksum, scratch_pool));
     }
 
+  *rep_p = rep;
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/rep-cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/rep-cache.h?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/rep-cache.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/rep-cache.h Sun Jun  5 15:03:52 2016
@@ -40,6 +40,10 @@ svn_error_t *
 svn_fs_x__open_rep_cache(svn_fs_t *fs,
                          apr_pool_t *scratch_pool);
 
+/* Close the rep cache database associated with FS. */
+svn_error_t *
+svn_fs_x__close_rep_cache(svn_fs_t *fs);
+
 /* Set *EXISTS to TRUE iff the rep-cache DB file exists. */
 svn_error_t *
 svn_fs_x__exists_rep_cache(svn_boolean_t *exists,
@@ -61,11 +65,12 @@ svn_fs_x__walk_rep_reference(svn_fs_t *f
                              apr_pool_t *scratch_pool);
 
 /* Return the representation REP in FS which has fulltext CHECKSUM.
-   REP is allocated in RESULT_POOL.  If the rep cache database has not been
-   opened, just set *REP to NULL.  Returns SVN_ERR_FS_CORRUPT if a reference
-   beyond HEAD is detected.  Uses SCRATCH_POOL for temporary allocations. */
+   *REP_P is allocated in RESULT_POOL.  If the rep cache database has not
+   been opened, just set *REP_P to NULL.  Returns SVN_ERR_FS_CORRUPT if
+   a reference beyond HEAD is detected.  Uses SCRATCH_POOL for temporary
+   allocations.*/
 svn_error_t *
-svn_fs_x__get_rep_reference(svn_fs_x__representation_t **rep,
+svn_fs_x__get_rep_reference(svn_fs_x__representation_t **rep_p,
                             svn_fs_t *fs,
                             svn_checksum_t *checksum,
                             apr_pool_t *result_pool,

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/rev_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/rev_file.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/rev_file.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/rev_file.c Sun Jun  5 15:03:52 2016
@@ -192,7 +192,7 @@ get_file_pool(svn_fs_x__revision_file_t
   return file->pool;
 }
 
-/* Core implementation of svn_fs_fs__open_pack_or_rev_file working on an
+/* Core implementation of svn_fs_x__open_pack_or_rev_file working on an
  * existing, initialized FILE structure.  If WRITABLE is TRUE, give write
  * access to the file - temporarily resetting the r/o state if necessary.
  */

Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/revprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/revprops.c?rev=1746927&r1=1746926&r2=1746927&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_x/revprops.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_x/revprops.c Sun Jun  5 15:03:52 2016
@@ -1390,11 +1390,13 @@ svn_fs_x__set_revision_proplist(svn_fs_t
   const char *perms_reference;
   apr_array_header_t *files_to_delete = NULL;
   svn_fs_x__batch_fsync_t *batch;
+  svn_fs_x__data_t *ffd = fs->fsap_data;
 
   SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, scratch_pool));
 
   /* Perform all fsyncs through this instance. */
-  SVN_ERR(svn_fs_x__batch_fsync_create(&batch, scratch_pool));
+  SVN_ERR(svn_fs_x__batch_fsync_create(&batch, ffd->flush_to_disk,
+                                       scratch_pool));
 
   /* this info will not change while we hold the global FS write lock */
   is_packed = svn_fs_x__is_packed_revprop(fs, rev);