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/04/29 20:38:56 UTC

svn commit: r1741682 [6/26] - in /subversion/branches/authzperf: ./ build/ build/ac-macros/ build/generator/ contrib/server-side/svncutter/ notes/ notes/api-errata/1.9/ notes/move-tracking/ subversion/ subversion/bindings/ctypes-python/ subversion/bind...

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=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs/fs-loader.c Fri Apr 29 18:38:53 2016
@@ -26,7 +26,6 @@
 #include <apr.h>
 #include <apr_atomic.h>
 #include <apr_hash.h>
-#include <apr_md5.h>
 #include <apr_uuid.h>
 #include <apr_strings.h>
 
@@ -46,6 +45,7 @@
 #include "private/svn_atomic.h"
 #include "private/svn_fs_private.h"
 #include "private/svn_fs_util.h"
+#include "private/svn_fspath.h"
 #include "private/svn_utf_private.h"
 #include "private/svn_mutex.h"
 #include "private/svn_subr_private.h"
@@ -60,6 +60,22 @@
 
 #define FS_TYPE_FILENAME "fs-type"
 
+/* 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. */
+#ifndef SVN_FS_EMULATE_PATHS_CHANGED
+#define SVN_FS_EMULATE_PATHS_CHANGED TRUE
+#endif
+
+/* If a FS backend does not implement the REPORT_CHANGES 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. */
+#ifndef SVN_FS_EMULATE_REPORT_CHANGES
+#define SVN_FS_EMULATE_REPORT_CHANGES TRUE
+#endif
+
 /* A pool common to all FS objects.  See the documentation on the
    open/create functions in fs-loader.h and for svn_fs_initialize(). */
 static apr_pool_t *common_pool = NULL;
@@ -506,24 +522,28 @@ svn_fs_set_warning_func(svn_fs_t *fs, sv
 }
 
 svn_error_t *
-svn_fs_create(svn_fs_t **fs_p, const char *path, apr_hash_t *fs_config,
-              apr_pool_t *pool)
+svn_fs_create2(svn_fs_t **fs_p,
+               const char *path,
+               apr_hash_t *fs_config,
+               apr_pool_t *result_pool,
+               apr_pool_t *scratch_pool)
 {
   fs_library_vtable_t *vtable;
 
   const char *fs_type = svn_hash__get_cstring(fs_config,
                                               SVN_FS_CONFIG_FS_TYPE,
                                               DEFAULT_FS_TYPE);
-  SVN_ERR(get_library_vtable(&vtable, fs_type, pool));
+  SVN_ERR(get_library_vtable(&vtable, fs_type, scratch_pool));
 
   /* Create the FS directory and write out the fsap-name file. */
-  SVN_ERR(svn_io_dir_make_sgid(path, APR_OS_DEFAULT, pool));
-  SVN_ERR(write_fs_type(path, fs_type, pool));
+  SVN_ERR(svn_io_dir_make_sgid(path, APR_OS_DEFAULT, scratch_pool));
+  SVN_ERR(write_fs_type(path, fs_type, scratch_pool));
 
   /* Perform the actual creation. */
-  *fs_p = fs_new(fs_config, pool);
+  *fs_p = fs_new(fs_config, result_pool);
 
-  SVN_ERR(vtable->create(*fs_p, path, common_pool_lock, pool, common_pool));
+  SVN_ERR(vtable->create(*fs_p, path, common_pool_lock, scratch_pool,
+                         common_pool));
   SVN_ERR(vtable->set_svn_fs_open(*fs_p, svn_fs_open2));
 
   return SVN_NO_ERROR;
@@ -546,15 +566,6 @@ svn_fs_open2(svn_fs_t **fs_p, const char
 }
 
 svn_error_t *
-svn_fs_open(svn_fs_t **fs_p,
-            const char *path,
-            apr_hash_t *fs_config,
-            apr_pool_t *pool)
-{
-  return svn_fs_open2(fs_p, path, fs_config, pool, pool);
-}
-
-svn_error_t *
 svn_fs_upgrade2(const char *path,
                 svn_fs_upgrade_notify_t notify_func,
                 void *notify_baton,
@@ -1045,40 +1056,163 @@ svn_fs_revision_root_revision(svn_fs_roo
 }
 
 svn_error_t *
+svn_fs_path_change_get(svn_fs_path_change3_t **change,
+                       svn_fs_path_change_iterator_t *iterator)
+{
+  return iterator->vtable->get(change, iterator);
+}
+
+svn_error_t *
 svn_fs_paths_changed2(apr_hash_t **changed_paths_p,
                       svn_fs_root_t *root,
                       apr_pool_t *pool)
 {
-  return root->vtable->paths_changed(changed_paths_p, root, pool);
+  svn_boolean_t emulate =    !root->vtable->paths_changed
+                          || SVN_FS_EMULATE_PATHS_CHANGED;
+
+  if (emulate)
+    {
+      apr_pool_t *scratch_pool = svn_pool_create(pool);
+      apr_hash_t *changes = svn_hash__make(pool);
+
+      svn_fs_path_change_iterator_t *iterator;
+      svn_fs_path_change3_t *change;
+
+      SVN_ERR(svn_fs_paths_changed3(&iterator, root, scratch_pool,
+                                    scratch_pool));
+
+      SVN_ERR(svn_fs_path_change_get(&change, iterator));
+      while (change)
+        {
+          svn_fs_path_change2_t *copy;
+          const svn_fs_id_t *id_copy;
+          const char *change_path = change->path.data;
+          svn_fs_root_t *change_root = root;
+
+          /* Copy CHANGE to old API struct. */
+          if (change->change_kind == svn_fs_path_change_delete)
+            SVN_ERR(svn_fs__get_deleted_node(&change_root, &change_path,
+                                             change_root, change_path,
+                                             scratch_pool, scratch_pool));
+
+          SVN_ERR(svn_fs_node_id(&id_copy, change_root, change_path, pool));
+
+          copy = svn_fs_path_change2_create(id_copy, change->change_kind,
+                                            pool);
+          copy->copyfrom_known = change->copyfrom_known;
+          if (   copy->copyfrom_known
+              && SVN_IS_VALID_REVNUM(change->copyfrom_rev))
+            {
+              copy->copyfrom_rev = change->copyfrom_rev;
+              copy->copyfrom_path = apr_pstrdup(pool, change->copyfrom_path);
+            }
+          copy->mergeinfo_mod = change->mergeinfo_mod;
+          copy->node_kind = change->node_kind;
+          copy->prop_mod = change->prop_mod;
+          copy->text_mod = change->text_mod;
+
+          svn_hash_sets(changes, apr_pstrmemdup(pool, change->path.data,
+                                                change->path.len), copy);
+
+          /* Next change. */
+          SVN_ERR(svn_fs_path_change_get(&change, iterator));
+        }
+      svn_pool_destroy(scratch_pool);
+
+      *changed_paths_p = changes;
+    }
+  else
+    {
+      SVN_ERR(root->vtable->paths_changed(changed_paths_p, root, pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Implement svn_fs_path_change_iterator_t on top of svn_fs_paths_changed2. */
+
+/* The iterator builds upon a hash iterator, which in turn operates on the
+   full prefetched changes list. */
+typedef struct fsap_iterator_data_t
+{
+  apr_hash_index_t *hi;
+
+  /* For efficicency such that we don't need to dynamically allocate
+     yet another copy of that data. */
+  svn_fs_path_change3_t change;
+} fsap_iterator_data_t;
+
+static svn_error_t *
+changes_iterator_get(svn_fs_path_change3_t **change,
+                     svn_fs_path_change_iterator_t *iterator)
+{
+  fsap_iterator_data_t *data = iterator->fsap_data;
+
+  if (data->hi)
+    {
+      const char *path = apr_hash_this_key(data->hi);
+      svn_fs_path_change2_t *entry = apr_hash_this_val(data->hi);
+
+      data->change.path.data = path;
+      data->change.path.len = apr_hash_this_key_len(data->hi);
+      data->change.change_kind = entry->change_kind;
+      data->change.node_kind = entry->node_kind;
+      data->change.text_mod = entry->text_mod;
+      data->change.prop_mod = entry->prop_mod;
+      data->change.mergeinfo_mod = entry->mergeinfo_mod;
+      data->change.copyfrom_known = entry->copyfrom_known;
+      data->change.copyfrom_rev = entry->copyfrom_rev;
+      data->change.copyfrom_path = entry->copyfrom_path;
+
+      *change = &data->change;
+      data->hi = apr_hash_next(data->hi);
+    }
+  else
+    {
+      *change = NULL;
+    }
+
+  return SVN_NO_ERROR;
 }
 
+static changes_iterator_vtable_t iterator_vtable =
+{
+  changes_iterator_get
+};
+
 svn_error_t *
-svn_fs_paths_changed(apr_hash_t **changed_paths_p, svn_fs_root_t *root,
-                     apr_pool_t *pool)
+svn_fs_paths_changed3(svn_fs_path_change_iterator_t **iterator,
+                      svn_fs_root_t *root,
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
 {
-  apr_hash_t *changed_paths_new_structs;
-  apr_hash_index_t *hi;
+  svn_boolean_t emulate =    !root->vtable->report_changes
+                          || (   SVN_FS_EMULATE_REPORT_CHANGES
+                              && root->vtable->paths_changed);
+
+  if (emulate)
+    {
+      svn_fs_path_change_iterator_t *result;
+      fsap_iterator_data_t *data;
+
+      apr_hash_t *changes;
+      SVN_ERR(root->vtable->paths_changed(&changes, root, result_pool));
 
-  SVN_ERR(svn_fs_paths_changed2(&changed_paths_new_structs, root, pool));
-  *changed_paths_p = apr_hash_make(pool);
-  for (hi = apr_hash_first(pool, changed_paths_new_structs);
-       hi;
-       hi = apr_hash_next(hi))
-    {
-      const void *vkey;
-      apr_ssize_t klen;
-      void *vval;
-      svn_fs_path_change2_t *val;
-      svn_fs_path_change_t *change;
-      apr_hash_this(hi, &vkey, &klen, &vval);
-      val = vval;
-      change = apr_palloc(pool, sizeof(*change));
-      change->node_rev_id = val->node_rev_id;
-      change->change_kind = val->change_kind;
-      change->text_mod = val->text_mod;
-      change->prop_mod = val->prop_mod;
-      apr_hash_set(*changed_paths_p, vkey, klen, change);
+      data = apr_pcalloc(result_pool, sizeof(*data));
+      data->hi = apr_hash_first(result_pool, changes);
+
+      result = apr_pcalloc(result_pool, sizeof(*result));
+      result->fsap_data = data;
+      result->vtable = &iterator_vtable;
+
+      *iterator = result;
+    }
+  else
+    {
+      SVN_ERR(root->vtable->report_changes(iterator, root, result_pool,
+                                           scratch_pool));
     }
+
   return SVN_NO_ERROR;
 }
 
@@ -1100,14 +1234,6 @@ svn_fs_node_history2(svn_fs_history_t **
 }
 
 svn_error_t *
-svn_fs_node_history(svn_fs_history_t **history_p, svn_fs_root_t *root,
-                    const char *path, apr_pool_t *pool)
-{
-  return svn_error_trace(root->vtable->node_history(history_p, root, path,
-                                                    pool, pool));
-}
-
-svn_error_t *
 svn_fs_is_dir(svn_boolean_t *is_dir, svn_fs_root_t *root, const char *path,
               apr_pool_t *pool)
 {
@@ -1268,20 +1394,6 @@ svn_fs_get_mergeinfo2(svn_mergeinfo_cata
 }
 
 svn_error_t *
-svn_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
-                     svn_fs_root_t *root,
-                     const apr_array_header_t *paths,
-                     svn_mergeinfo_inheritance_t inherit,
-                     svn_boolean_t include_descendants,
-                     apr_pool_t *pool)
-{
-  return svn_error_trace(root->vtable->get_mergeinfo(catalog, root, paths,
-                                                     inherit,
-                                                     include_descendants,
-                                                     TRUE, pool, pool));
-}
-
-svn_error_t *
 svn_fs__get_mergeinfo_for_path(svn_mergeinfo_t *mergeinfo,
                                svn_fs_root_t *root,
                                const char *path,
@@ -1404,21 +1516,6 @@ svn_fs_file_checksum(svn_checksum_t **ch
 }
 
 svn_error_t *
-svn_fs_file_md5_checksum(unsigned char digest[],
-                         svn_fs_root_t *root,
-                         const char *path,
-                         apr_pool_t *pool)
-{
-  svn_checksum_t *md5sum;
-
-  SVN_ERR(svn_fs_file_checksum(&md5sum, svn_checksum_md5, root, path, TRUE,
-                               pool));
-  memcpy(digest, md5sum->digest, APR_MD5_DIGESTSIZE);
-
-  return SVN_NO_ERROR;
-}
-
-svn_error_t *
 svn_fs_file_contents(svn_stream_t **contents, svn_fs_root_t *root,
                      const char *path, apr_pool_t *pool)
 {
@@ -1553,19 +1650,39 @@ svn_fs_deltify_revision(svn_fs_t *fs, sv
 }
 
 svn_error_t *
-svn_fs_revision_prop(svn_string_t **value_p, svn_fs_t *fs, svn_revnum_t rev,
-                     const char *propname, apr_pool_t *pool)
+svn_fs_refresh_revision_props(svn_fs_t *fs,
+                              apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(fs->vtable->refresh_revprops(fs, scratch_pool));
+}
+
+svn_error_t *
+svn_fs_revision_prop2(svn_string_t **value_p,
+                      svn_fs_t *fs,
+                      svn_revnum_t rev,
+                      const char *propname,
+                      svn_boolean_t refresh,
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
 {
   return svn_error_trace(fs->vtable->revision_prop(value_p, fs, rev,
-                                                   propname, pool));
+                                                   propname, refresh,
+                                                   result_pool,
+                                                   scratch_pool));
 }
 
 svn_error_t *
-svn_fs_revision_proplist(apr_hash_t **table_p, svn_fs_t *fs, svn_revnum_t rev,
-                         apr_pool_t *pool)
+svn_fs_revision_proplist2(apr_hash_t **table_p,
+                          svn_fs_t *fs,
+                          svn_revnum_t rev,
+                          svn_boolean_t refresh,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool)
 {
   return svn_error_trace(fs->vtable->revision_proplist(table_p, fs, rev,
-                                                       pool));
+                                                       refresh,
+                                                       result_pool,
+                                                       scratch_pool));
 }
 
 svn_error_t *
@@ -1592,6 +1709,64 @@ svn_fs_get_file_delta_stream(svn_txdelta
 }
 
 svn_error_t *
+svn_fs__get_deleted_node(svn_fs_root_t **node_root,
+                         const char **node_path,
+                         svn_fs_root_t *root,
+                         const char *path,
+                         apr_pool_t *result_pool,
+                         apr_pool_t *scratch_pool)
+{
+  const char *parent_path, *name;
+  svn_fs_root_t *copy_root;
+  const char *copy_path;
+
+  /* History traversal does not work with transaction roots.
+   * Therefore, do it "by hand". */
+
+  /* If the parent got copied in ROOT, PATH got copied with it.
+   * Otherwise, we will find the node at PATH in the revision prior to ROOT.
+   */
+  svn_fspath__split(&parent_path, &name, path, scratch_pool);
+  SVN_ERR(svn_fs_closest_copy(&copy_root, &copy_path, root, parent_path,
+                              scratch_pool));
+
+  /* Copied in ROOT? */
+  if (   copy_root
+      && (   svn_fs_revision_root_revision(copy_root)
+          == svn_fs_revision_root_revision(root)))
+    {
+      svn_revnum_t copyfrom_rev;
+      const char *copyfrom_path;
+      const char *rel_path;
+      SVN_ERR(svn_fs_copied_from(&copyfrom_rev, &copyfrom_path,
+                                 copy_root, copy_path, scratch_pool));
+
+      SVN_ERR(svn_fs_revision_root(node_root, svn_fs_root_fs(root),
+                                   copyfrom_rev, result_pool));
+      rel_path = svn_fspath__skip_ancestor(copy_path, path);
+      *node_path = svn_fspath__join(copyfrom_path, rel_path, result_pool);
+    }
+  else
+    {
+      svn_revnum_t revision;
+      svn_revnum_t previous_rev;
+
+      /* Determine the latest revision before ROOT. */
+      revision = svn_fs_revision_root_revision(root);
+      if (SVN_IS_VALID_REVNUM(revision))
+        previous_rev = revision - 1;
+      else
+        previous_rev = svn_fs_txn_root_base_revision(root);
+
+      SVN_ERR(svn_fs_revision_root(node_root, svn_fs_root_fs(root),
+                                   previous_rev, result_pool));
+      *node_path = apr_pstrdup(result_pool, path);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_fs_get_uuid(svn_fs_t *fs, const char **uuid, apr_pool_t *pool)
 {
   /* If you change this, consider changing svn_fs__identifier(). */
@@ -1860,15 +2035,6 @@ svn_fs_history_prev2(svn_fs_history_t **
 }
 
 svn_error_t *
-svn_fs_history_prev(svn_fs_history_t **prev_history_p,
-                    svn_fs_history_t *history, svn_boolean_t cross_copies,
-                    apr_pool_t *pool)
-{
-  return svn_error_trace(history->vtable->prev(prev_history_p, history,
-                                               cross_copies, pool, pool));
-}
-
-svn_error_t *
 svn_fs_history_location(const char **path, svn_revnum_t *revision,
                         svn_fs_history_t *history, apr_pool_t *pool)
 {
@@ -1967,6 +2133,28 @@ svn_fs_path_change2_create(const svn_fs_
   return svn_fs__path_change_create_internal(node_rev_id, change_kind, pool);
 }
 
+svn_fs_path_change3_t *
+svn_fs_path_change3_create(svn_fs_path_change_kind_t change_kind,
+                           apr_pool_t *result_pool)
+{
+  return svn_fs__path_change_create_internal2(change_kind, result_pool);
+}
+
+svn_fs_path_change3_t *
+svn_fs_path_change3_dup(svn_fs_path_change3_t *change,
+                        apr_pool_t *result_pool)
+{
+  svn_fs_path_change3_t *copy = apr_pmemdup(result_pool, change,
+                                            sizeof(*copy));
+
+  copy->path.data = apr_pstrmemdup(result_pool, copy->path.data,
+                                   copy->path.len);
+  if (copy->copyfrom_path)
+    copy->copyfrom_path = apr_pstrdup(result_pool, change->copyfrom_path);
+
+  return copy;
+}
+
 /* Return the library version number. */
 const svn_version_t *
 svn_fs_version(void)

Modified: subversion/branches/authzperf/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs/fs-loader.h?rev=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs/fs-loader.h Fri Apr 29 18:38:53 2016
@@ -79,11 +79,11 @@ typedef struct fs_library_vtable_t
      parameter for allocating fs-global objects such as an env cache. */
   svn_error_t *(*create)(svn_fs_t *fs, const char *path,
                          svn_mutex__t *common_pool_lock,
-                         apr_pool_t *pool,
+                         apr_pool_t *scratch_pool,
                          apr_pool_t *common_pool);
   svn_error_t *(*open_fs)(svn_fs_t *fs, const char *path,
                           svn_mutex__t *common_pool_lock,
-                          apr_pool_t *pool,
+                          apr_pool_t *scratch_pool,
                           apr_pool_t *common_pool);
   /* open_for_recovery() is like open(), but used to fill in an fs pointer
      that will be passed to recover().  We assume that the open() method
@@ -196,11 +196,17 @@ typedef struct fs_vtable_t
 {
   svn_error_t *(*youngest_rev)(svn_revnum_t *youngest_p, svn_fs_t *fs,
                                apr_pool_t *pool);
+  svn_error_t *(*refresh_revprops)(svn_fs_t *fs, apr_pool_t *scratch_pool);
   svn_error_t *(*revision_prop)(svn_string_t **value_p, svn_fs_t *fs,
                                 svn_revnum_t rev, const char *propname,
-                                apr_pool_t *pool);
+                                svn_boolean_t refresh,
+                                apr_pool_t *result_pool, 
+                                apr_pool_t *scratch_pool);
   svn_error_t *(*revision_proplist)(apr_hash_t **table_p, svn_fs_t *fs,
-                                    svn_revnum_t rev, apr_pool_t *pool);
+                                    svn_revnum_t rev,
+                                    svn_boolean_t refresh,
+                                    apr_pool_t *result_pool, 
+                                    apr_pool_t *scratch_pool);
   svn_error_t *(*change_rev_prop)(svn_fs_t *fs, svn_revnum_t rev,
                                   const char *name,
                                   const svn_string_t *const *old_value_p,
@@ -295,6 +301,10 @@ typedef struct root_vtable_t
   svn_error_t *(*paths_changed)(apr_hash_t **changed_paths_p,
                                 svn_fs_root_t *root,
                                 apr_pool_t *pool);
+  svn_error_t *(*report_changes)(svn_fs_path_change_iterator_t **iterator,
+                                 svn_fs_root_t *root,
+                                 apr_pool_t *result_pool,
+                                 apr_pool_t *scratch_pool);
 
   /* Generic node operations */
   svn_error_t *(*check_path)(svn_node_kind_t *kind_p, svn_fs_root_t *root,
@@ -420,6 +430,13 @@ typedef struct root_vtable_t
 } root_vtable_t;
 
 
+typedef struct changes_iterator_vtable_t
+{
+  svn_error_t *(*get)(svn_fs_path_change3_t **change,
+                      svn_fs_path_change_iterator_t *iterator);
+} changes_iterator_vtable_t;
+
+
 typedef struct history_vtable_t
 {
   svn_error_t *(*prev)(svn_fs_history_t **prev_history_p,
@@ -468,7 +485,7 @@ struct svn_fs_t
   svn_fs_access_t *access_ctx;
 
   /* FSAP-specific vtable and private data */
-  fs_vtable_t *vtable;
+  const fs_vtable_t *vtable;
   void *fsap_data;
 
   /* UUID, stored by open(), create(), and set_uuid(). */
@@ -490,7 +507,7 @@ struct svn_fs_txn_t
   const char *id;
 
   /* FSAP-specific vtable and private data */
-  txn_vtable_t *vtable;
+  const txn_vtable_t *vtable;
   void *fsap_data;
 };
 
@@ -518,15 +535,21 @@ struct svn_fs_root_t
   svn_revnum_t rev;
 
   /* FSAP-specific vtable and private data */
-  root_vtable_t *vtable;
+  const root_vtable_t *vtable;
   void *fsap_data;
 };
 
+struct svn_fs_path_change_iterator_t
+{
+  /* FSAP-specific vtable and private data */
+  const changes_iterator_vtable_t *vtable;
+  void *fsap_data;
+};
 
 struct svn_fs_history_t
 {
   /* FSAP-specific vtable and private data */
-  history_vtable_t *vtable;
+  const history_vtable_t *vtable;
   void *fsap_data;
 };
 
@@ -534,7 +557,7 @@ struct svn_fs_history_t
 struct svn_fs_id_t
 {
   /* FSAP-specific vtable and private data */
-  id_vtable_t *vtable;
+  const id_vtable_t *vtable;
   void *fsap_data;
 };
 

Modified: subversion/branches/authzperf/subversion/libsvn_fs_base/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_base/dag.c?rev=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_base/dag.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_base/dag.c Fri Apr 29 18:38:53 2016
@@ -1657,8 +1657,14 @@ svn_fs_base__things_different(svn_boolea
 
   /* Compare contents keys and their (optional) uniquifiers. */
   if (contents_changed != NULL)
-    *contents_changed = (! svn_fs_base__same_keys(noderev1->data_key,
-                                                  noderev2->data_key));
+    *contents_changed =
+      (! (svn_fs_base__same_keys(noderev1->data_key,
+                                 noderev2->data_key)
+          /* Technically, these uniquifiers aren't used and "keys",
+             but keys are base-36 stringified numbers, so we'll take
+             this liberty. */
+          && (svn_fs_base__same_keys(noderev1->data_key_uniquifier,
+                                     noderev2->data_key_uniquifier))));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/authzperf/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_base/fs.c?rev=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_base/fs.c Fri Apr 29 18:38:53 2016
@@ -471,6 +471,13 @@ bdb_write_config(svn_fs_t *fs)
 }
 
 static svn_error_t *
+base_bdb_refresh_revision(svn_fs_t *fs,
+                          apr_pool_t *scratch_pool)
+{
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
 base_bdb_info_format(int *fs_format,
                      svn_version_t **supports_version,
                      svn_fs_t *fs,
@@ -545,6 +552,7 @@ base_bdb_freeze(svn_fs_t *fs,
 
 static fs_vtable_t fs_vtable = {
   svn_fs_base__youngest_rev,
+  base_bdb_refresh_revision,
   svn_fs_base__revision_prop,
   svn_fs_base__revision_proplist,
   svn_fs_base__change_rev_prop,
@@ -572,13 +580,12 @@ static fs_vtable_t fs_vtable = {
 #define FORMAT_FILE   "format"
 
 /* Depending on CREATE, create or open the environment and databases
-   for filesystem FS in PATH. Use POOL for temporary allocations. */
+   for filesystem FS in PATH. */
 static svn_error_t *
 open_databases(svn_fs_t *fs,
                svn_boolean_t create,
                int format,
-               const char *path,
-               apr_pool_t *pool)
+               const char *path)
 {
   base_fs_data_t *bfd;
 
@@ -732,7 +739,7 @@ static svn_error_t *
 base_create(svn_fs_t *fs,
             const char *path,
             svn_mutex__t *common_pool_lock,
-            apr_pool_t *pool,
+            apr_pool_t *scratch_pool,
             apr_pool_t *common_pool)
 {
   int format = SVN_FS_BASE__FORMAT_NUMBER;
@@ -743,7 +750,7 @@ base_create(svn_fs_t *fs,
     {
       svn_version_t *compatible_version;
       SVN_ERR(svn_fs__compatible_version(&compatible_version, fs->config,
-                                         pool));
+                                         scratch_pool));
 
       /* select format number */
       switch(compatible_version->minor)
@@ -765,7 +772,7 @@ base_create(svn_fs_t *fs,
     }
 
   /* Create the environment and databases. */
-  svn_err = open_databases(fs, TRUE, format, path, pool);
+  svn_err = open_databases(fs, TRUE, format, path);
   if (svn_err) goto error;
 
   /* Initialize the DAG subsystem. */
@@ -773,13 +780,14 @@ base_create(svn_fs_t *fs,
   if (svn_err) goto error;
 
   /* This filesystem is ready.  Stamp it with a format number. */
-  svn_err = svn_io_write_version_file(
-   svn_dirent_join(fs->path, FORMAT_FILE, pool), format, pool);
+  svn_err = svn_io_write_version_file(svn_dirent_join(fs->path, FORMAT_FILE,
+                                                      scratch_pool),
+                                      format, scratch_pool);
   if (svn_err) goto error;
 
   ((base_fs_data_t *) fs->fsap_data)->format = format;
 
-  SVN_ERR(populate_opened_fs(fs, pool));
+  SVN_ERR(populate_opened_fs(fs, scratch_pool));
   return SVN_NO_ERROR;
 
 error:
@@ -826,7 +834,7 @@ static svn_error_t *
 base_open(svn_fs_t *fs,
           const char *path,
           svn_mutex__t *common_pool_lock,
-          apr_pool_t *pool,
+          apr_pool_t *scratch_pool,
           apr_pool_t *common_pool)
 {
   int format;
@@ -835,8 +843,9 @@ base_open(svn_fs_t *fs,
 
   /* Read the FS format number. */
   svn_err = svn_io_read_version_file(&format,
-                                     svn_dirent_join(path, FORMAT_FILE, pool),
-                                     pool);
+                                     svn_dirent_join(path, FORMAT_FILE,
+                                                     scratch_pool),
+                                     scratch_pool);
   if (svn_err && APR_STATUS_IS_ENOENT(svn_err->apr_err))
     {
       /* Pre-1.2 filesystems did not have a format file (you could say
@@ -852,7 +861,7 @@ base_open(svn_fs_t *fs,
     goto error;
 
   /* Create the environment and databases. */
-  svn_err = open_databases(fs, FALSE, format, path, pool);
+  svn_err = open_databases(fs, FALSE, format, path);
   if (svn_err) goto error;
 
   ((base_fs_data_t *) fs->fsap_data)->format = format;
@@ -862,12 +871,12 @@ base_open(svn_fs_t *fs,
   if (write_format_file)
     {
       svn_err = svn_io_write_version_file(svn_dirent_join(path, FORMAT_FILE,
-                                                        pool),
-                                          format, pool);
+                                                        scratch_pool),
+                                          format, scratch_pool);
       if (svn_err) goto error;
     }
 
-  SVN_ERR(populate_opened_fs(fs, pool));
+  SVN_ERR(populate_opened_fs(fs, scratch_pool));
   return SVN_NO_ERROR;
 
  error:

Modified: subversion/branches/authzperf/subversion/libsvn_fs_base/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_base/fs.h?rev=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_base/fs.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_base/fs.h Fri Apr 29 18:38:53 2016
@@ -195,11 +195,7 @@ typedef struct node_revision_t
      only because one or both of us decided to pick up a shared
      representation after-the-fact."  May be NULL (if this node
      revision isn't using a shared rep, or isn't the original
-     "assignee" of a shared rep).
-
-     This is no longer used by the 1.9 code but we have to keep
-     reading and writing it to remain compatible with 1.8, and
-     earlier, that require it. */
+     "assignee" of a shared rep). */
   const char *data_key_uniquifier;
 
   /* representation key for this node's text-data-in-progess (files

Modified: subversion/branches/authzperf/subversion/libsvn_fs_base/revs-txns.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_base/revs-txns.c?rev=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_base/revs-txns.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_base/revs-txns.c Fri Apr 29 18:38:53 2016
@@ -194,7 +194,9 @@ svn_error_t *
 svn_fs_base__revision_proplist(apr_hash_t **table_p,
                                svn_fs_t *fs,
                                svn_revnum_t rev,
-                               apr_pool_t *pool)
+                               svn_boolean_t refresh,
+                               apr_pool_t *result_pool,
+                               apr_pool_t *scratch_pool)
 {
   struct revision_proplist_args args;
   apr_hash_t *table;
@@ -204,9 +206,9 @@ svn_fs_base__revision_proplist(apr_hash_
   args.table_p = &table;
   args.rev = rev;
   SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_revision_proplist, &args,
-                                 FALSE, pool));
+                                 FALSE, result_pool));
 
-  *table_p = table ? table : apr_hash_make(pool);
+  *table_p = table ? table : apr_hash_make(result_pool);
   return SVN_NO_ERROR;
 }
 
@@ -216,7 +218,9 @@ svn_fs_base__revision_prop(svn_string_t
                            svn_fs_t *fs,
                            svn_revnum_t rev,
                            const char *propname,
-                           apr_pool_t *pool)
+                           svn_boolean_t refresh,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
 {
   struct revision_proplist_args args;
   apr_hash_t *table;
@@ -227,7 +231,7 @@ svn_fs_base__revision_prop(svn_string_t
   args.table_p = &table;
   args.rev = rev;
   SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_revision_proplist, &args,
-                                 FALSE, pool));
+                                 FALSE, result_pool));
 
   /* And then the prop from that list (if there was a list). */
   *value_p = svn_hash_gets(table, propname);

Modified: subversion/branches/authzperf/subversion/libsvn_fs_base/revs-txns.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_base/revs-txns.h?rev=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_base/revs-txns.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_base/revs-txns.h Fri Apr 29 18:38:53 2016
@@ -172,12 +172,16 @@ svn_error_t *svn_fs_base__youngest_rev(s
 svn_error_t *svn_fs_base__revision_prop(svn_string_t **value_p, svn_fs_t *fs,
                                         svn_revnum_t rev,
                                         const char *propname,
-                                        apr_pool_t *pool);
+                                        svn_boolean_t refresh,
+                                        apr_pool_t *result_pool,
+                                        apr_pool_t *scratch_pool);
 
 svn_error_t *svn_fs_base__revision_proplist(apr_hash_t **table_p,
                                             svn_fs_t *fs,
                                             svn_revnum_t rev,
-                                            apr_pool_t *pool);
+                                            svn_boolean_t refresh,
+                                            apr_pool_t *result_pool,
+                                            apr_pool_t *scratch_pool);
 
 svn_error_t *svn_fs_base__change_rev_prop(svn_fs_t *fs, svn_revnum_t rev,
                                           const char *name,

Modified: subversion/branches/authzperf/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_base/tree.c?rev=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_base/tree.c Fri Apr 29 18:38:53 2016
@@ -68,6 +68,7 @@
 #include "private/svn_fspath.h"
 #include "private/svn_fs_util.h"
 #include "private/svn_mergeinfo_private.h"
+#include "private/svn_sorts_private.h"
 
 
 /* ### I believe this constant will become internal to reps-strings.c.
@@ -2580,8 +2581,7 @@ verify_locks(const char *txn_name,
       apr_hash_this(hi, &key, NULL, NULL);
       APR_ARRAY_PUSH(changed_paths, const char *) = key;
     }
-  qsort(changed_paths->elts, changed_paths->nelts,
-        changed_paths->elt_size, svn_sort_compare_paths);
+  svn_sort__array(changed_paths, svn_sort_compare_paths);
 
   /* Now, traverse the array of changed paths, verify locks.  Note
      that if we need to do a recursive verification a path, we'll skip
@@ -2661,7 +2661,7 @@ txn_body_commit(void *baton, trail_t *tr
 
   svn_revnum_t youngest_rev;
   const svn_fs_id_t *y_rev_root_id;
-  dag_node_t *txn_base_root_node;
+  dag_node_t *txn_base_root_node, *txn_root_node;
 
   /* Getting the youngest revision locks the revisions table until
      this trail is done. */
@@ -2694,6 +2694,19 @@ txn_body_commit(void *baton, trail_t *tr
      discovered locks. */
   SVN_ERR(verify_locks(txn_name, trail, trail->pool));
 
+  /* Ensure every txn has a mutable root as then the new revision will
+     have a distinct root node-revision-id.  This is necessary as
+     future transactions use the root node-revision-id as a proxy for
+     the transaction base revision. */
+  SVN_ERR(svn_fs_base__dag_txn_root(&txn_root_node, fs, txn_name,
+                                    trail, trail->pool));
+  if (!svn_fs_base__dag_check_mutable(txn_root_node, txn->id))
+    {
+      dag_node_t *clone;
+      SVN_ERR(svn_fs_base__dag_clone_root(&clone, fs, txn->id,
+                                          trail, trail->pool));
+    }
+
   /* Else, commit the txn. */
   return svn_fs_base__dag_commit_txn(&(args->new_rev), txn, trail,
                                      trail->pool);
@@ -5493,6 +5506,7 @@ base_get_mergeinfo(svn_mergeinfo_catalog
 
 static root_vtable_t root_vtable = {
   base_paths_changed,
+  NULL,
   base_check_path,
   base_node_history,
   base_node_id,

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=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/cached_data.c Fri Apr 29 18:38:53 2016
@@ -425,14 +425,13 @@ get_node_revision_body(node_revision_t *
                              scratch_pool),
                              APR_READ | APR_BUFFERED, APR_OS_DEFAULT,
                              scratch_pool);
-      if (err)
+      if (err && APR_STATUS_IS_ENOENT(err->apr_err))
+        {
+          svn_error_clear(err);
+          return svn_error_trace(err_dangling_id(fs, id));
+        }
+      else if (err)
         {
-          if (APR_STATUS_IS_ENOENT(err->apr_err))
-            {
-              svn_error_clear(err);
-              return svn_error_trace(err_dangling_id(fs, id));
-            }
-
           return svn_error_trace(err);
         }
 
@@ -747,15 +746,15 @@ typedef struct rep_state_t
   int chunk_index;  /* number of the window to read */
 } rep_state_t;
 
-/* Simple wrapper around svn_fs_fs__get_file_offset to simplify callers. */
+/* Simple wrapper around svn_io_file_get_offset to simplify callers. */
 static svn_error_t *
 get_file_offset(apr_off_t *offset,
                 rep_state_t *rs,
                 apr_pool_t *pool)
 {
-  return svn_error_trace(svn_fs_fs__get_file_offset(offset,
-                                                    rs->sfile->rfile->file,
-                                                    pool));
+  return svn_error_trace(svn_io_file_get_offset(offset,
+                                                rs->sfile->rfile->file,
+                                                pool));
 }
 
 /* Simple wrapper around svn_io_file_aligned_seek to simplify callers. */
@@ -1802,10 +1801,10 @@ get_contents_from_windows(struct rep_rea
              This is where we need the pseudo rep_state created
              by build_rep_list(). */
           apr_size_t offset = (apr_size_t)rs->current;
-          if (copy_len + offset > rb->base_window->len)
-            copy_len = offset < rb->base_window->len
-                     ? rb->base_window->len - offset
-                     : 0ul;
+          if (offset >= rb->base_window->len)
+            copy_len = 0ul;
+          else if (copy_len > rb->base_window->len - offset)
+            copy_len = rb->base_window->len - offset;
 
           memcpy (cur, rb->base_window->data + offset, copy_len);
         }
@@ -2043,7 +2042,7 @@ skip_contents(struct rep_read_baton *bat
   else if (len > 0)
     {
       /* Simply drain LEN bytes from the window stream. */
-      apr_pool_t *subpool = subpool = svn_pool_create(baton->pool);
+      apr_pool_t *subpool = svn_pool_create(baton->pool);
       char *buffer = apr_palloc(subpool, SVN__STREAM_CHUNK_SIZE);
 
       while (len > 0 && !err)
@@ -2422,12 +2421,12 @@ compare_dirent_name(const void *a, const
   return strcmp(lhs->name, rhs);
 }
 
-/* Into ENTRIES, read all directories entries from the key-value text in
+/* Into *ENTRIES_P, read all directories entries from the key-value text in
  * STREAM.  If INCREMENTAL is TRUE, read until the end of the STREAM and
  * update the data.  ID is provided for nicer error messages.
  */
 static svn_error_t *
-read_dir_entries(apr_array_header_t *entries,
+read_dir_entries(apr_array_header_t **entries_p,
                  svn_stream_t *stream,
                  svn_boolean_t incremental,
                  const svn_fs_id_t *id,
@@ -2435,8 +2434,14 @@ read_dir_entries(apr_array_header_t *ent
                  apr_pool_t *scratch_pool)
 {
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-  apr_hash_t *hash = incremental ? svn_hash__make(scratch_pool) : NULL;
+  apr_hash_t *hash = NULL;
   const char *terminator = SVN_HASH_TERMINATOR;
+  apr_array_header_t *entries = NULL;
+
+  if (incremental)
+    hash = svn_hash__make(scratch_pool);
+  else
+    entries = apr_array_make(result_pool, 16, sizeof(svn_fs_dirent_t *));
 
   /* Read until the terminator (non-incremental) or the end of STREAM
      (incremental mode).  In the latter mode, we use a temporary HASH
@@ -2448,8 +2453,11 @@ read_dir_entries(apr_array_header_t *ent
       char *str;
 
       svn_pool_clear(iterpool);
-      SVN_ERR(svn_hash__read_entry(&entry, stream, terminator,
-                                   incremental, iterpool));
+      SVN_ERR_W(svn_hash__read_entry(&entry, stream, terminator,
+                                     incremental, iterpool),
+                apr_psprintf(iterpool,
+                             _("Directory representation corrupt in '%s'"),
+                             svn_fs_fs__id_unparse(id, scratch_pool)->data));
 
       /* End of directory? */
       if (entry.key == NULL)
@@ -2517,6 +2525,9 @@ read_dir_entries(apr_array_header_t *ent
   if (incremental)
     {
       apr_hash_index_t *hi;
+
+      entries = apr_array_make(result_pool, apr_hash_count(hash),
+                               sizeof(svn_fs_dirent_t *));
       for (hi = apr_hash_first(iterpool, hash); hi; hi = apr_hash_next(hi))
         APR_ARRAY_PUSH(entries, svn_fs_dirent_t *) = apr_hash_this_val(hi);
     }
@@ -2526,6 +2537,7 @@ read_dir_entries(apr_array_header_t *ent
 
   svn_pool_destroy(iterpool);
 
+  *entries_p = entries;
   return SVN_NO_ERROR;
 }
 
@@ -2572,7 +2584,6 @@ get_dir_contents(svn_fs_fs__dir_data_t *
   svn_stream_t *contents;
 
   /* Initialize the result. */
-  dir->entries = apr_array_make(result_pool, 16, sizeof(svn_fs_dirent_t *));
   dir->txn_filesize = SVN_INVALID_FILESIZE;
 
   /* Read dir contents - unless there is none in which case we are done. */
@@ -2595,7 +2606,7 @@ get_dir_contents(svn_fs_fs__dir_data_t *
       SVN_ERR(svn_io_file_size_get(&dir->txn_filesize, file, scratch_pool));
 
       contents = svn_stream_from_aprfile2(file, FALSE, scratch_pool);
-      SVN_ERR(read_dir_entries(dir->entries, contents, TRUE, noderev->id,
+      SVN_ERR(read_dir_entries(&dir->entries, contents, TRUE, noderev->id,
                                result_pool, scratch_pool));
       SVN_ERR(svn_stream_close(contents));
     }
@@ -2615,9 +2626,13 @@ get_dir_contents(svn_fs_fs__dir_data_t *
 
       /* de-serialize hash */
       contents = svn_stream_from_stringbuf(text, scratch_pool);
-      SVN_ERR(read_dir_entries(dir->entries, contents, FALSE, noderev->id,
+      SVN_ERR(read_dir_entries(&dir->entries, contents, FALSE, noderev->id,
                                result_pool, scratch_pool));
     }
+  else
+    {
+       dir->entries = apr_array_make(result_pool, 0, sizeof(svn_fs_dirent_t *));
+    }
 
   return SVN_NO_ERROR;
 }
@@ -2636,27 +2651,27 @@ locate_dir_cache(svn_fs_t *fs,
                  apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
-  if (svn_fs_fs__id_is_txn(noderev->id))
+  if (!noderev->data_rep)
+    {
+      /* no data rep -> empty directory.
+         A NULL key causes a cache miss. */
+      *key = NULL;
+      return ffd->dir_cache;
+    }
+
+  if (svn_fs_fs__id_txn_used(&noderev->data_rep->txn_id))
     {
       /* data in txns requires the expensive fs_id-based addressing mode */
       *key = svn_fs_fs__id_unparse(noderev->id, pool)->data;
+
       return ffd->txn_dir_cache;
     }
   else
     {
       /* committed data can use simple rev,item pairs */
-      if (noderev->data_rep)
-        {
-          pair_key->revision = noderev->data_rep->revision;
-          pair_key->second = noderev->data_rep->item_index;
-          *key = pair_key;
-        }
-      else
-        {
-          /* no data rep -> empty directory.
-             A NULL key causes a cache miss. */
-          *key = NULL;
-        }
+      pair_key->revision = noderev->data_rep->revision;
+      pair_key->second = noderev->data_rep->item_index;
+      *key = pair_key;
 
       return ffd->dir_cache;
     }
@@ -2703,8 +2718,12 @@ svn_fs_fs__rep_contents_dir(apr_array_he
   SVN_ERR(get_dir_contents(dir, fs, noderev, result_pool, scratch_pool));
   *entries_p = dir->entries;
 
-  /* Update the cache, if we are to use one. */
-  if (cache)
+  /* Update the cache, if we are to use one.
+   *
+   * Don't even attempt to serialize very large directories; it would cause
+   * an unnecessary memory allocation peak.  150 bytes/entry is about right.
+   */
+  if (cache && svn_cache__is_cachable(cache, 150 * dir->entries->nelts))
     SVN_ERR(svn_cache__set(cache, key, dir, scratch_pool));
 
   return SVN_NO_ERROR;
@@ -2728,6 +2747,7 @@ svn_fs_fs__rep_contents_dir_entry(svn_fs
                                   apr_pool_t *result_pool,
                                   apr_pool_t *scratch_pool)
 {
+  extract_dir_entry_baton_t baton;
   svn_boolean_t found = FALSE;
 
   /* find the cache we may use */
@@ -2737,8 +2757,6 @@ svn_fs_fs__rep_contents_dir_entry(svn_fs
                                          scratch_pool);
   if (cache)
     {
-      extract_dir_entry_baton_t baton;
-
       svn_filesize_t filesize;
       SVN_ERR(get_txn_dir_info(&filesize, fs, noderev, scratch_pool));
 
@@ -2755,7 +2773,7 @@ svn_fs_fs__rep_contents_dir_entry(svn_fs
     }
 
   /* fetch data from disk if we did not find it in the cache */
-  if (! found)
+  if (! found || baton.out_of_date)
     {
       svn_fs_dirent_t *entry;
       svn_fs_dirent_t *entry_copy = NULL;
@@ -2765,8 +2783,12 @@ svn_fs_fs__rep_contents_dir_entry(svn_fs
       SVN_ERR(get_dir_contents(&dir, fs, noderev, scratch_pool,
                                scratch_pool));
 
-      /* Update the cache, if we are to use one. */
-      if (cache)
+      /* Update the cache, if we are to use one.
+       *
+       * Don't even attempt to serialize very large directories; it would
+       * cause an unnecessary memory allocation peak.  150 bytes / entry is
+       * about right. */
+      if (cache && svn_cache__is_cachable(cache, 150 * dir.entries->nelts))
         SVN_ERR(svn_cache__set(cache, key, &dir, scratch_pool));
 
       /* find desired entry and return a copy in POOL, if found */
@@ -3226,9 +3248,8 @@ read_rep_header(svn_fs_fs__rep_header_t
 
 /* Fetch the representation data (header, txdelta / plain windows)
  * addressed by ENTRY->ITEM in FS and cache it if caches are enabled.
- * Read the data from the already open FILE and the wrapping
- * STREAM object.  If MAX_OFFSET is not -1, don't read windows that start
- * at or beyond that offset.
+ * Read the data from REV_FILE.  If MAX_OFFSET is not -1, don't read
+ * windows that start at or beyond that offset.
  * Use SCRATCH_POOL for temporary allocations.
  */
 static svn_error_t *
@@ -3236,7 +3257,6 @@ block_read_contents(svn_fs_t *fs,
                     svn_fs_fs__revision_file_t *rev_file,
                     svn_fs_fs__p2l_entry_t* entry,
                     apr_off_t max_offset,
-                    apr_pool_t *result_pool,
                     apr_pool_t *scratch_pool)
 {
   pair_cache_key_t header_key = { 0 };
@@ -3246,9 +3266,9 @@ block_read_contents(svn_fs_t *fs,
   header_key.second = entry->item.number;
 
   SVN_ERR(read_rep_header(&rep_header, fs, rev_file->stream, &header_key,
-                          result_pool, scratch_pool));
+                          scratch_pool, scratch_pool));
   SVN_ERR(block_read_windows(rep_header, fs, rev_file, entry, max_offset,
-                             result_pool, scratch_pool));
+                             scratch_pool, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -3305,8 +3325,8 @@ read_item(svn_stream_t **stream,
 
 /* 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 the already open
- * FILE and wrapping FILE_STREAM.  Use POOL for allocations.
+ * result if caching is enabled.  Read the data from REV_FILE.  Allocate
+ * *CHANGES in RESUSLT_POOL and allocate temporaries in SCRATCH_POOL.
  */
 static svn_error_t *
 block_read_changes(apr_array_header_t **changes,
@@ -3347,10 +3367,10 @@ block_read_changes(apr_array_header_t **
   return SVN_NO_ERROR;
 }
 
-/* If not already cached or if MUST_READ is set, read the nod revision
+/* If not already cached or if MUST_READ is set, read the node revision
  * addressed by ENTRY in FS and retúrn it in *NODEREV_P.  Cache the
- * result if caching is enabled.  Read the data from the already open
- * FILE and wrapping FILE_STREAM. Use SCRATCH_POOL for temporary allocations.
+ * result if caching is enabled.  Read the data from REV_FILE.  Allocate
+ * *NODEREV_P in RESUSLT_POOL and allocate temporaries in SCRATCH_POOL.
  */
 static svn_error_t *
 block_read_noderev(node_revision_t **noderev_p,
@@ -3500,7 +3520,7 @@ block_read(void **result,
                                                 is_wanted
                                                   ? -1
                                                   : block_start + ffd->block_size,
-                                                pool, iterpool));
+                                                iterpool));
                     break;
 
                   case SVN_FS_FS__ITEM_TYPE_NODEREV:
@@ -3528,7 +3548,7 @@ block_read(void **result,
               /* if we crossed a block boundary, read the remainder of
                * the last block as well */
               offset = entry->offset + entry->size;
-              if (offset > block_start + ffd->block_size)
+              if (offset - block_start > ffd->block_size)
                 ++run_count;
             }
         }

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=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/caching.c Fri Apr 29 18:38:53 2016
@@ -66,8 +66,9 @@ normalize_key_part(const char *original,
   return normalized->data;
 }
 
-/* *CACHE_TXDELTAS, *CACHE_FULLTEXTS flags will be set according to
-   FS->CONFIG.  *CACHE_NAMESPACE receives the cache prefix to use.
+/* *CACHE_TXDELTAS, *CACHE_FULLTEXTS, *CACHE_NODEPROPS flags will be set
+   according to FS->CONFIG. *CACHE_NAMESPACE receives the cache prefix to
+   use.
 
    Use FS->pool for allocating the memcache and CACHE_NAMESPACE, and POOL
    for temporary allocations. */
@@ -75,6 +76,7 @@ static svn_error_t *
 read_config(const char **cache_namespace,
             svn_boolean_t *cache_txdeltas,
             svn_boolean_t *cache_fulltexts,
+            svn_boolean_t *cache_nodeprops,
             svn_fs_t *fs,
             apr_pool_t *pool)
 {
@@ -117,6 +119,14 @@ read_config(const char **cache_namespace
                          SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
                          TRUE);
 
+  /* by default, cache nodeprops: this will match pre-1.10
+   * behavior where node properties caching was controlled
+   * by SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS configuration option.
+   */
+  *cache_nodeprops
+    = svn_hash__get_bool(fs->config,
+                         SVN_FS_CONFIG_FSFS_CACHE_NODEPROPS,
+                         TRUE);
   return SVN_NO_ERROR;
 }
 
@@ -353,6 +363,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
   svn_boolean_t no_handler = ffd->fail_stop;
   svn_boolean_t cache_txdeltas;
   svn_boolean_t cache_fulltexts;
+  svn_boolean_t cache_nodeprops;
   const char *cache_namespace;
   svn_boolean_t has_namespace;
 
@@ -360,6 +371,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
   SVN_ERR(read_config(&cache_namespace,
                       &cache_txdeltas,
                       &cache_fulltexts,
+                      &cache_nodeprops,
                       fs,
                       pool));
 
@@ -438,7 +450,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                        svn_fs_fs__deserialize_dir_entries,
                        sizeof(pair_cache_key_t),
                        apr_pstrcat(pool, prefix, "DIR", SVN_VA_NULL),
-                       SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+                       SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
                        has_namespace,
                        fs,
                        no_handler,
@@ -506,6 +518,21 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                        no_handler,
                        fs->pool, pool));
 
+  /* if enabled, cache revprops */
+  SVN_ERR(create_cache(&(ffd->revprop_cache),
+                       NULL,
+                       membuffer,
+                       0, 0, /* Do not use inprocess cache */
+                       svn_fs_fs__serialize_revprops,
+                       svn_fs_fs__deserialize_revprops,
+                       sizeof(pair_cache_key_t),
+                       apr_pstrcat(pool, prefix, "REVPROP", SVN_VA_NULL),
+                       SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+                       TRUE, /* contents is short-lived */
+                       fs,
+                       no_handler,
+                       fs->pool, pool));
+
   /* if enabled, cache fulltext and other derived information */
   if (cache_fulltexts)
     {
@@ -523,21 +550,6 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
                            no_handler,
                            fs->pool, pool));
 
-      SVN_ERR(create_cache(&(ffd->properties_cache),
-                           NULL,
-                           membuffer,
-                           0, 0, /* Do not use the inprocess cache */
-                           svn_fs_fs__serialize_properties,
-                           svn_fs_fs__deserialize_properties,
-                           sizeof(pair_cache_key_t),
-                           apr_pstrcat(pool, prefix, "PROP",
-                                       SVN_VA_NULL),
-                           SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
-                           has_namespace,
-                           fs,
-                           no_handler,
-                           fs->pool, pool));
-
       SVN_ERR(create_cache(&(ffd->mergeinfo_cache),
                            NULL,
                            membuffer,
@@ -571,11 +583,33 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
   else
     {
       ffd->fulltext_cache = NULL;
-      ffd->properties_cache = NULL;
       ffd->mergeinfo_cache = NULL;
       ffd->mergeinfo_existence_cache = NULL;
     }
 
+  /* if enabled, cache node properties */
+  if (cache_nodeprops)
+    {
+      SVN_ERR(create_cache(&(ffd->properties_cache),
+                           NULL,
+                           membuffer,
+                           0, 0, /* Do not use the inprocess cache */
+                           svn_fs_fs__serialize_properties,
+                           svn_fs_fs__deserialize_properties,
+                           sizeof(pair_cache_key_t),
+                           apr_pstrcat(pool, prefix, "PROP",
+                                       SVN_VA_NULL),
+                           SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+                           has_namespace,
+                           fs,
+                           no_handler,
+                           fs->pool, pool));
+    }
+  else
+    {
+      ffd->properties_cache = NULL;
+    }
+
   /* if enabled, cache text deltas and their combinations */
   if (cache_txdeltas)
     {
@@ -801,18 +835,7 @@ svn_fs_fs__initialize_txn_caches(svn_fs_
                                  apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
-
-  /* Transaction content needs to be carefully prefixed to virtually
-     eliminate any chance for conflicts. The (repo, txn_id) pair
-     should be unique but if a transaction fails, it might be possible
-     to start a new transaction later that receives the same id.
-     Therefore, throw in a uuid as well - just to be sure. */
-  const char *prefix = apr_pstrcat(pool,
-                                   "fsfs:", fs->uuid,
-                                   "/", fs->path,
-                                   ":", txn_id,
-                                   ":", svn_uuid_generate(pool), ":",
-                                   SVN_VA_NULL);
+  const char *prefix;
 
   /* We don't support caching for concurrent transactions in the SAME
    * FSFS session. Maybe, you forgot to clean POOL. */
@@ -824,17 +847,39 @@ svn_fs_fs__initialize_txn_caches(svn_fs_
       return SVN_NO_ERROR;
     }
 
+  /* Transaction content needs to be carefully prefixed to virtually
+     eliminate any chance for conflicts. The (repo, txn_id) pair
+     should be unique but if the filesystem format doesn't store the
+     global transaction ID via the txn-current file, and a transaction
+     fails, it might be possible to start a new transaction later that
+     receives the same id.  For such older formats, throw in an uuid as
+     well -- just to be sure. */
+  if (ffd->format >= SVN_FS_FS__MIN_TXN_CURRENT_FORMAT)
+    prefix = apr_pstrcat(pool,
+                         "fsfs:", fs->uuid,
+                         "/", fs->path,
+                         ":", txn_id,
+                         ":", "TXNDIR",
+                         SVN_VA_NULL);
+  else
+    prefix = apr_pstrcat(pool,
+                         "fsfs:", fs->uuid,
+                         "/", fs->path,
+                         ":", txn_id,
+                         ":", svn_uuid_generate(pool),
+                         ":", "TXNDIR",
+                         SVN_VA_NULL);
+
   /* create a txn-local directory cache */
   SVN_ERR(create_cache(&ffd->txn_dir_cache,
                        NULL,
                        svn_cache__get_global_membuffer_cache(),
                        1024, 8,
-                       svn_fs_fs__serialize_dir_entries,
+                       svn_fs_fs__serialize_txndir_entries,
                        svn_fs_fs__deserialize_dir_entries,
                        APR_HASH_KEY_STRING,
-                       apr_pstrcat(pool, prefix, "TXNDIR",
-                                   SVN_VA_NULL),
-                       0,
+                       prefix,
+                       SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
                        TRUE, /* The TXN-ID is our namespace. */
                        fs,
                        TRUE,

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/dag.c?rev=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/dag.c Fri Apr 29 18:38:53 2016
@@ -753,8 +753,7 @@ svn_fs_fs__dag_clone_child(dag_node_t **
       noderev->copyfrom_rev = SVN_INVALID_REVNUM;
 
       noderev->predecessor_id = svn_fs_fs__id_copy(cur_entry->id, pool);
-      if (noderev->predecessor_count != -1)
-        noderev->predecessor_count++;
+      noderev->predecessor_count++;
       noderev->created_path = svn_fspath__join(parent_path, name, pool);
 
       SVN_ERR(svn_fs_fs__create_successor(&new_node_id, fs, cur_entry->id,
@@ -1267,8 +1266,7 @@ svn_fs_fs__dag_copy(dag_node_t *to_node,
       /* Create a successor with its predecessor pointing at the copy
          source. */
       to_noderev->predecessor_id = svn_fs_fs__id_copy(src_id, pool);
-      if (to_noderev->predecessor_count != -1)
-        to_noderev->predecessor_count++;
+      to_noderev->predecessor_count++;
       to_noderev->created_path =
         svn_fspath__join(svn_fs_fs__dag_get_created_path(to_node), entry,
                      pool);
@@ -1305,34 +1303,58 @@ svn_fs_fs__dag_things_different(svn_bool
                                 apr_pool_t *pool)
 {
   node_revision_t *noderev1, *noderev2;
-  svn_fs_t *fs;
-  svn_boolean_t same;
 
   /* If we have no place to store our results, don't bother doing
      anything. */
   if (! props_changed && ! contents_changed)
     return SVN_NO_ERROR;
 
-  fs = svn_fs_fs__dag_get_fs(node1);
-
   /* The node revision skels for these two nodes. */
   SVN_ERR(get_node_revision(&noderev1, node1));
   SVN_ERR(get_node_revision(&noderev2, node2));
 
-  /* Compare property keys. */
-  if (props_changed != NULL)
+  if (strict)
     {
-      SVN_ERR(svn_fs_fs__prop_rep_equal(&same, fs, noderev1, noderev2,
-                                        strict, pool));
-      *props_changed = !same;
-    }
+      /* In strict mode, compare text and property representations in the
+         svn_fs_contents_different() / svn_fs_props_different() manner.
 
-  /* Compare contents keys. */
-  if (contents_changed != NULL)
+         See the "No-op changes no longer dumped by 'svnadmin dump' in 1.9"
+         discussion (http://svn.haxx.se/dev/archive-2015-09/0269.shtml) and
+         issue #4598 (https://issues.apache.org/jira/browse/SVN-4598). */
+      svn_fs_t *fs = svn_fs_fs__dag_get_fs(node1);
+      svn_boolean_t same;
+
+      /* Compare property keys. */
+      if (props_changed != NULL)
+        {
+          SVN_ERR(svn_fs_fs__prop_rep_equal(&same, fs, noderev1,
+                                            noderev2, pool));
+          *props_changed = !same;
+        }
+
+      /* Compare contents keys. */
+      if (contents_changed != NULL)
+        {
+          SVN_ERR(svn_fs_fs__file_text_rep_equal(&same, fs, noderev1,
+                                                 noderev2, pool));
+          *contents_changed = !same;
+        }
+    }
+  else
     {
-      SVN_ERR(svn_fs_fs__file_text_rep_equal(&same, fs, noderev1, noderev2,
-                                             strict, pool));
-      *contents_changed = !same;
+      /* Otherwise, compare representation keys -- as in Subversion 1.8. */
+
+      /* Compare property keys. */
+      if (props_changed != NULL)
+        *props_changed =
+          !svn_fs_fs__noderev_same_rep_key(noderev1->prop_rep,
+                                           noderev2->prop_rep);
+
+      /* Compare contents keys. */
+      if (contents_changed != NULL)
+        *contents_changed =
+          !svn_fs_fs__noderev_same_rep_key(noderev1->data_rep,
+                                           noderev2->data_rep);
     }
 
   return SVN_NO_ERROR;
@@ -1399,8 +1421,7 @@ svn_fs_fs__dag_update_ancestry(dag_node_
 
   target_noderev->predecessor_id = source->id;
   target_noderev->predecessor_count = source_noderev->predecessor_count;
-  if (target_noderev->predecessor_count != -1)
-    target_noderev->predecessor_count++;
+  target_noderev->predecessor_count++;
 
   return svn_fs_fs__put_node_revision(target->fs, target->id, target_noderev,
                                       FALSE, pool);

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.c?rev=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.c Fri Apr 29 18:38:53 2016
@@ -148,6 +148,15 @@ svn_fs_fs__initialize_shared_data(svn_fs
 
 
 
+static svn_error_t *
+fs_refresh_revprops(svn_fs_t *fs,
+                    apr_pool_t *scratch_pool)
+{
+  svn_fs_fs__reset_revprop_cache(fs);
+
+  return SVN_NO_ERROR;
+}
+
 /* This function is provided for Subversion 1.0.x compatibility.  It
    has no effect for fsfs backed Subversion filesystems.  It conforms
    to the fs_library_vtable_t.bdb_set_errcall() API. */
@@ -249,6 +258,7 @@ fs_set_uuid(svn_fs_t *fs,
 /* The vtable associated with a specific open filesystem. */
 static fs_vtable_t fs_vtable = {
   svn_fs_fs__youngest_rev,
+  fs_refresh_revprops,
   svn_fs_fs__revision_prop,
   svn_fs_fs__get_revision_proplist,
   svn_fs_fs__change_rev_prop,
@@ -281,6 +291,8 @@ initialize_fs_struct(svn_fs_t *fs)
 {
   fs_fs_data_t *ffd = apr_pcalloc(fs->pool, sizeof(*ffd));
   ffd->use_log_addressing = FALSE;
+  ffd->revprop_prefix = 0;
+  ffd->flush_to_disk = TRUE;
 
   fs->vtable = &fs_vtable;
   fs->fsap_data = ffd;
@@ -304,18 +316,18 @@ static svn_error_t *
 fs_create(svn_fs_t *fs,
           const char *path,
           svn_mutex__t *common_pool_lock,
-          apr_pool_t *pool,
+          apr_pool_t *scratch_pool,
           apr_pool_t *common_pool)
 {
   SVN_ERR(svn_fs__check_fs(fs, FALSE));
 
   SVN_ERR(initialize_fs_struct(fs));
 
-  SVN_ERR(svn_fs_fs__create(fs, path, pool));
+  SVN_ERR(svn_fs_fs__create(fs, path, scratch_pool));
 
-  SVN_ERR(svn_fs_fs__initialize_caches(fs, pool));
+  SVN_ERR(svn_fs_fs__initialize_caches(fs, scratch_pool));
   SVN_MUTEX__WITH_LOCK(common_pool_lock,
-                       fs_serialized_init(fs, common_pool, pool));
+                       fs_serialized_init(fs, common_pool, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -333,10 +345,10 @@ static svn_error_t *
 fs_open(svn_fs_t *fs,
         const char *path,
         svn_mutex__t *common_pool_lock,
-        apr_pool_t *pool,
+        apr_pool_t *scratch_pool,
         apr_pool_t *common_pool)
 {
-  apr_pool_t *subpool = svn_pool_create(pool);
+  apr_pool_t *subpool = svn_pool_create(scratch_pool);
 
   SVN_ERR(svn_fs__check_fs(fs, FALSE));
 

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=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.h Fri Apr 29 18:38:53 2016
@@ -351,6 +351,15 @@ typedef struct fs_fs_data_t
      rep key (revision/offset) to svn_stringbuf_t. */
   svn_cache__t *fulltext_cache;
 
+  /* The current prefix to be used for revprop cache entries.
+     If this is 0, a new unique prefix must be chosen. */
+  apr_uint64_t revprop_prefix;
+
+  /* Revision property cache.  Maps from (rev,prefix) to apr_hash_t.
+     Unparsed svn_string_t representations of the serialized hash
+     will be written to the cache but the getter returns apr_hash_t. */
+  svn_cache__t *revprop_cache;
+
   /* Node properties cache.  Maps from rep key to apr_hash_t. */
   svn_cache__t *properties_cache;
 
@@ -467,6 +476,9 @@ typedef struct fs_fs_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 *);
@@ -476,10 +488,6 @@ typedef struct fs_fs_data_t
 /*** Filesystem Transaction ***/
 typedef struct transaction_t
 {
-  /* property list (const char * name, svn_string_t * value).
-     may be NULL if there are no properties.  */
-  apr_hash_t *proplist;
-
   /* node revision id of the root node.  */
   const svn_fs_id_t *root_id;
 
@@ -541,13 +549,7 @@ typedef struct representation_t
   /* For rep-sharing, we need a way of uniquifying node-revs which share the
      same representation (see svn_fs_fs__noderev_same_rep_key() ).  So, we
      store the original txn of the node rev (not the rep!), along with some
-     intra-node uniqification content.
-
-     This is no longer used by the 1.9 code but we have to keep
-     reading and writing it for old formats to remain compatible with
-     1.8, and earlier, that require it.  We also read/write it in
-     format 7 even though it is not currently required by any code
-     that handles that format. */
+     intra-node uniqification content. */
   struct
     {
       /* unique context, i.e. txn ID, in which the noderev (!) got created */
@@ -583,8 +585,8 @@ typedef struct node_revision_t
   svn_revnum_t copyroot_rev;
   const char *copyroot_path;
 
-  /* number of predecessors this node revision has (recursively), or
-     -1 if not known (for backward compatibility). */
+  /* 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

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.c?rev=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.c Fri Apr 29 18:38:53 2016
@@ -492,6 +492,7 @@ read_format(int *pformat,
       svn_error_clear(err);
       *pformat = 1;
       *max_files_per_dir = 0;
+      *use_log_addressing = FALSE;
 
       return SVN_NO_ERROR;
     }
@@ -623,7 +624,8 @@ svn_fs_fs__write_format(svn_fs_t *fs,
   else
     {
       SVN_ERR(svn_io_write_atomic2(path, sb->data, sb->len,
-                                   NULL /* copy_perms_path */, TRUE, pool));
+                                   NULL /* copy_perms_path */,
+                                   ffd->flush_to_disk, pool));
     }
 
   /* And set the perms to make it read only */
@@ -754,8 +756,8 @@ read_config(fs_fs_data_t *ffd,
                                    CONFIG_SECTION_PACKED_REVPROPS,
                                    CONFIG_OPTION_REVPROP_PACK_SIZE,
                                    ffd->compress_packed_revprops
-                                       ? 0x10
-                                       : 0x4));
+                                       ? 0x40
+                                       : 0x10));
 
       ffd->revprop_pack_size *= 1024;
     }
@@ -962,9 +964,9 @@ write_config(svn_fs_t *fs,
 "### latency and CPU usage reading and changing individual revprops."        NL
 "### Values smaller than 4 kByte will not improve latency any further and "  NL
 "### quickly render revprop packing ineffective."                            NL
-"### revprop-pack-size is 4 kBytes by default for non-compressed revprop"    NL
-"### pack files and 16 kBytes when compression has been enabled."            NL
-"# " CONFIG_OPTION_REVPROP_PACK_SIZE " = 4"                                  NL
+"### revprop-pack-size is 16 kBytes by default for non-compressed revprop"   NL
+"### pack files and 64 kBytes when compression has been enabled."            NL
+"# " CONFIG_OPTION_REVPROP_PACK_SIZE " = 16"                                 NL
 "###"                                                                        NL
 "### To save disk space, packed revprop files may be compressed.  Standard"  NL
 "### revprops tend to allow for very effective compression.  Reading and"    NL
@@ -1031,13 +1033,12 @@ read_global_config(svn_fs_t *fs)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
 
-  /* Providing a config hash is optional. */
-  if (fs->config)
-    ffd->use_block_read = svn_hash__get_bool(fs->config,
-                                             SVN_FS_CONFIG_FSFS_BLOCK_READ,
-                                             FALSE);
-  else
-    ffd->use_block_read = FALSE;
+  ffd->use_block_read = svn_hash__get_bool(fs->config,
+                                           SVN_FS_CONFIG_FSFS_BLOCK_READ,
+                                           FALSE);
+  ffd->flush_to_disk = !svn_hash__get_bool(fs->config,
+                                           SVN_FS_CONFIG_NO_FLUSH_TO_DISK,
+                                           FALSE);
 
   /* Ignore the user-specified larger block size if we don't use block-read.
      Defaulting to 4k gives us the same access granularity in format 7 as in
@@ -1387,12 +1388,30 @@ svn_fs_fs__file_length(svn_filesize_t *l
   return SVN_NO_ERROR;
 }
 
+svn_boolean_t
+svn_fs_fs__noderev_same_rep_key(representation_t *a,
+                                representation_t *b)
+{
+  if (a == b)
+    return TRUE;
+
+  if (a == NULL || b == NULL)
+    return FALSE;
+
+  if (a->item_index != b->item_index)
+    return FALSE;
+
+  if (a->revision != b->revision)
+    return FALSE;
+
+  return memcmp(&a->uniquifier, &b->uniquifier, sizeof(a->uniquifier)) == 0;
+}
+
 svn_error_t *
 svn_fs_fs__file_text_rep_equal(svn_boolean_t *equal,
                                svn_fs_t *fs,
                                node_revision_t *a,
                                node_revision_t *b,
-                               svn_boolean_t strict,
                                apr_pool_t *scratch_pool)
 {
   svn_stream_t *contents_a, *contents_b;
@@ -1437,19 +1456,6 @@ svn_fs_fs__file_text_rep_equal(svn_boole
       return SVN_NO_ERROR;
     }
 
-  /* Old repositories may not have the SHA1 checksum handy.
-     This check becomes expensive.  Skip it unless explicitly required.
-
-     We already have seen that the ID is different, so produce a likely
-     false negative as allowed by the API description - even though the
-     MD5 matched, there is an extremely slim chance that the SHA1 wouldn't.
-   */
-  if (!strict)
-    {
-      *equal = FALSE;
-      return SVN_NO_ERROR;
-    }
-
   SVN_ERR(svn_fs_fs__get_contents(&contents_a, fs, rep_a, TRUE,
                                   scratch_pool));
   SVN_ERR(svn_fs_fs__get_contents(&contents_b, fs, rep_b, TRUE,
@@ -1465,7 +1471,6 @@ svn_fs_fs__prop_rep_equal(svn_boolean_t
                           svn_fs_t *fs,
                           node_revision_t *a,
                           node_revision_t *b,
-                          svn_boolean_t strict,
                           apr_pool_t *scratch_pool)
 {
   representation_t *rep_a = a->prop_rep;
@@ -1512,14 +1517,6 @@ svn_fs_fs__prop_rep_equal(svn_boolean_t
       return SVN_NO_ERROR;
     }
 
-  /* Skip the expensive bits unless we are in strict mode.
-     Simply assume that there is a difference. */
-  if (!strict)
-    {
-      *equal = FALSE;
-      return SVN_NO_ERROR;
-    }
-
   /* At least one of the reps has been modified in a txn.
      Fetch and compare them. */
   SVN_ERR(svn_fs_fs__get_proplist(&proplist_a, fs, a, scratch_pool));
@@ -1872,7 +1869,7 @@ svn_fs_fs__set_uuid(svn_fs_t *fs,
      file does not exist during repository creation. */
   SVN_ERR(svn_io_write_atomic2(uuid_path, contents->data, contents->len,
                                svn_fs_fs__path_current(fs, pool) /* perms */,
-                               TRUE, pool));
+                               ffd->flush_to_disk, pool));
 
   fs->uuid = apr_pstrdup(fs->pool, uuid);
 
@@ -2058,14 +2055,17 @@ svn_fs_fs__revision_prop(svn_string_t **
                          svn_fs_t *fs,
                          svn_revnum_t rev,
                          const char *propname,
-                         apr_pool_t *pool)
+                         svn_boolean_t refresh,
+                         apr_pool_t *result_pool,
+                         apr_pool_t *scratch_pool)
 {
   apr_hash_t *table;
 
   SVN_ERR(svn_fs__check_fs(fs, TRUE));
-  SVN_ERR(svn_fs_fs__get_revision_proplist(&table, fs, rev, pool));
+  SVN_ERR(svn_fs_fs__get_revision_proplist(&table, fs, rev, refresh,
+                                           scratch_pool, scratch_pool));
 
-  *value_p = svn_hash_gets(table, propname);
+  *value_p = svn_string_dup(svn_hash_gets(table, propname), result_pool);
 
   return SVN_NO_ERROR;
 }
@@ -2090,7 +2090,10 @@ change_rev_prop_body(void *baton, apr_po
   apr_hash_t *table;
   const svn_string_t *present_value;
 
-  SVN_ERR(svn_fs_fs__get_revision_proplist(&table, cb->fs, cb->rev, pool));
+  /* We always need to read the current revprops from disk.
+   * Hence, always "refresh" here. */
+  SVN_ERR(svn_fs_fs__get_revision_proplist(&table, cb->fs, cb->rev, TRUE,
+                                           pool, pool));
   present_value = svn_hash_gets(table, cb->name);
 
   if (cb->old_value_p)

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.h?rev=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.h Fri Apr 29 18:38:53 2016
@@ -90,28 +90,29 @@ svn_error_t *svn_fs_fs__file_length(svn_
                                     node_revision_t *noderev,
                                     apr_pool_t *pool);
 
+/* Return TRUE if the representation keys in A and B both point to the
+   same representation, else return FALSE. */
+svn_boolean_t svn_fs_fs__noderev_same_rep_key(representation_t *a,
+                                              representation_t *b);
+
 /* Set *EQUAL to TRUE if the text representations in A and B within FS
-   have equal contents, else set it to FALSE.  If STRICT is not set, allow
-   for false negatives.
+   have equal contents, else set it to FALSE.
    Use SCRATCH_POOL for temporary allocations. */
 svn_error_t *
 svn_fs_fs__file_text_rep_equal(svn_boolean_t *equal,
                                svn_fs_t *fs,
                                node_revision_t *a,
                                node_revision_t *b,
-                               svn_boolean_t strict,
                                apr_pool_t *scratch_pool);
 
 /* Set *EQUAL to TRUE if the property representations in A and B within FS
-   have equal contents, else set it to FALSE.  If STRICT is not set, allow
-   for false negatives.
+   have equal contents, else set it to FALSE.
    Use SCRATCH_POOL for temporary allocations. */
 svn_error_t *
 svn_fs_fs__prop_rep_equal(svn_boolean_t *equal,
                           svn_fs_t *fs,
                           node_revision_t *a,
                           node_revision_t *b,
-                          svn_boolean_t strict,
                           apr_pool_t *scratch_pool);
 
 
@@ -224,13 +225,16 @@ svn_fs_fs__with_all_locks(svn_fs_t *fs,
                           void *baton,
                           apr_pool_t *pool);
 
-/* Find the value of the property named PROPNAME in transaction TXN.
+/* Find the value of the property named PROPNAME in revision REV.
    Return the contents in *VALUE_P.  The contents will be allocated
-   from POOL. */
+   from RESULT_POOL and SCRATCH_POOL is used for temporaries.
+   Invalidate any revprop cache is REFRESH is set. */
 svn_error_t *svn_fs_fs__revision_prop(svn_string_t **value_p, svn_fs_t *fs,
                                       svn_revnum_t rev,
                                       const char *propname,
-                                      apr_pool_t *pool);
+                                      svn_boolean_t refresh,
+                                      apr_pool_t *result_pool,
+                                      apr_pool_t *scratch_pool);
 
 /* Change, add, or delete a property on a revision REV in filesystem
    FS.  NAME gives the name of the property, and value, if non-NULL,

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/hotcopy.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/hotcopy.c?rev=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/hotcopy.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/hotcopy.c Fri Apr 29 18:38:53 2016
@@ -795,7 +795,7 @@ struct hotcopy_body_baton {
  * 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_fs/id.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/id.c?rev=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/id.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/id.c Fri Apr 29 18:38:53 2016
@@ -82,9 +82,11 @@ locale_independent_strtol(long *result_p
 
       next = result * 10 + c;
 
-      /* Overflow check.  In case of an overflow, NEXT is 0..9.
-       * In the non-overflow case, RESULT is either >= 10 or RESULT and NEXT
-       * are both 0. */
+      /* Overflow check.  In case of an overflow, NEXT is 0..9 and RESULT
+       * is much larger than 10.  We will then return FALSE.
+       *
+       * In the non-overflow case, NEXT is >= 10 * RESULT but never smaller.
+       * We will continue the loop in that case. */
       if (next < result)
         return FALSE;
 

Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/index.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/index.c?rev=1741682&r1=1741681&r2=1741682&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/index.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/index.c Fri Apr 29 18:38:53 2016
@@ -231,7 +231,7 @@ stream_error_create(svn_fs_fs__packed_nu
   apr_off_t offset;
   SVN_ERR(svn_io_file_name_get(&file_name, stream->file,
                                stream->pool));
-  SVN_ERR(svn_fs_fs__get_file_offset(&offset, stream->file, stream->pool));
+  SVN_ERR(svn_io_file_get_offset(&offset, stream->file, stream->pool));
 
   return svn_error_createf(err, NULL, message, file_name,
                            apr_psprintf(stream->pool,
@@ -1736,7 +1736,7 @@ svn_fs_fs__l2p_get_max_ids(apr_array_hea
       apr_uint64_t item_count;
       apr_size_t first_page_index, last_page_index;
 
-      if (revision >= header->first_revision + header->revision_count)
+      if (revision - header->first_revision >= header->revision_count)
         {
           /* need to read the next index. Clear up memory used for the
            * previous one.  Note that intermittent pack runs do not change
@@ -2422,6 +2422,13 @@ read_entry(svn_fs_fs__packed_number_stre
       return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL,
                  _("Empty regions must have item number 0 and checksum 0"));
 
+  /* Corrupted SIZE values might cause arithmetic overflow.
+   * The same can happen if you copy a repository from a system with 63 bit
+   * file lengths to one with 31 bit file lengths. */
+  if ((apr_uint64_t)entry.offset + (apr_uint64_t)entry.size > off_t_max)
+    return svn_error_create(SVN_ERR_FS_INDEX_OVERFLOW , NULL,
+                            _("P2L index entry size overflow."));
+
   APR_ARRAY_PUSH(result, svn_fs_fs__p2l_entry_t) = entry;
   *item_offset += entry.size;