This patch combines all patches from the performance branch that
implement the membuffer cache configuration but without the UI change.
A process-global membuffer cache will now be used for full-texts 
unless memcached has been enabled for the respective directory.

To minimize the number of future conflicts, the configuration structure 
has been brought up to its final state even if some options (cached file
handle count, txdelta caching etc.) will have no effect right now. 

Merged revisions from /branches/performance:
981684, 982043, 988319
Merged only partially (excluding all changes not related to the
membuffer cache):
987886

* subversion/include/private/svn_fs_private.h
  (svn_fs__get_global_membuffer_cache): 
   declare new internal API function
* subversion/include/svn_fs.h
  (svn_fs_cache_config_t): new cache config struct
  (svn_fs_get_cache_config, svn_fs_set_cache_config): new public API
   to get & modify the cache config; currently evaluated by FSFS only

* subversion/libsvn_fs_util/caching.c
  (cache_settings): new global cache settings + their defaults
  (svn_fs__get_global_membuffer_cache, svn_fs_get_cache_config, 
   svn_fs_set_cache_config): implement new public and internal API functions
* subversion/libsvn_fs_fs/caching.c
  (svn_fs_fs__initialize_caches): use membuffer cache for full-texts

git-svn-id: https://svn.apache.org/repos/asf/subversion/branches/integrate-cache-membuffer@998843 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/subversion/include/private/svn_fs_private.h b/subversion/include/private/svn_fs_private.h
index 133bd78..42224ed 100644
--- a/subversion/include/private/svn_fs_private.h
+++ b/subversion/include/private/svn_fs_private.h
@@ -91,6 +91,15 @@
                                 apr_pool_t *pool);
 
 
+/* Access the process-global (singleton) membuffer cache. The first call
+ * will automatically allocate the cache using the current cache config.
+ * NULL will be returned if the desired cache size is 0.
+ *
+ * @since New in 1.7.
+ */
+struct svn_membuffer_t *
+svn_fs__get_global_membuffer_cache(void);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/subversion/include/svn_fs.h b/subversion/include/svn_fs.h
index 041933e..44a78cd 100644
--- a/subversion/include/svn_fs.h
+++ b/subversion/include/svn_fs.h
@@ -2224,8 +2224,52 @@
             apr_pool_t *pool);
 
 
+/** @defgroup svn_fs_cach_config Filesystem caching configuration
+ * @{
+ * @since New in 1.7. */
+
+/* FSFS cache settings. It controls what caches, in what size and
+   how they will be created. The settings apply for the whole process.
+ */
+typedef struct svn_fs_cache_config_t
+{
+  /* total cache size in bytes. May be 0, resulting in no cache being used */
+  apr_uint64_t cache_size;
+
+  /* maximum number of files kept open */
+  apr_size_t file_handle_count;
+
+  /* shall fulltexts be cached? */
+  svn_boolean_t cache_fulltexts;
+
+  /* shall text deltas be cached? */
+  svn_boolean_t cache_txdeltas;
+
+  /* is this a guaranteed single-threaded application? */
+  svn_boolean_t single_threaded;
+} svn_fs_cache_config_t;
+
+/* Get the current FSFS cache configuration. If it has not been set,
+   this function will return the default settings.
+ */
+const svn_fs_cache_config_t *
+svn_fs_get_cache_config(void);
+
+/* Set the FSFS cache configuration. Please note that it may not change
+   the actual configuration *in use*. Therefore, call it before reading
+   data from any FSFS repo and call it only once.
+
+   This function is not thread-safe. Therefore, it should be called once
+   from the processes' initialization code only.
+ */
+void
+svn_fs_set_cache_config(const svn_fs_cache_config_t *settings);
+
 /** @} */
 
+/** @} */
+
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/subversion/libsvn_fs_fs/caching.c b/subversion/libsvn_fs_fs/caching.c
index 484e20d..68c7a25 100644
--- a/subversion/libsvn_fs_fs/caching.c
+++ b/subversion/libsvn_fs_fs/caching.c
@@ -300,12 +300,27 @@
                                          apr_pstrcat(pool, prefix, "TEXT",
                                                      NULL),
                                          fs->pool));
-      if (! no_handler)
-        SVN_ERR(svn_cache__set_error_handler(ffd->fulltext_cache,
-                                             warn_on_cache_errors, fs, pool));
+    }
+  else if (svn_fs__get_global_membuffer_cache() && 
+           svn_fs_get_cache_config()->cache_fulltexts)
+    {
+      SVN_ERR(svn_cache__create_membuffer_cache(&(ffd->fulltext_cache),
+                                                svn_fs__get_global_membuffer_cache(),
+                                                /* Values are svn_string_t */
+                                                NULL, NULL,
+                                                APR_HASH_KEY_STRING,
+                                                apr_pstrcat(pool, prefix, "TEXT",
+                                                            NULL),
+                                                fs->pool));
     }
   else
-    ffd->fulltext_cache = NULL;
+    {
+      ffd->fulltext_cache = NULL;
+    }
+
+  if (ffd->fulltext_cache && ! no_handler)
+    SVN_ERR(svn_cache__set_error_handler(ffd->fulltext_cache,
+            warn_on_cache_errors, fs, pool));
 
   return SVN_NO_ERROR;
 }
diff --git a/subversion/libsvn_fs_util/caching.c b/subversion/libsvn_fs_util/caching.c
new file mode 100644
index 0000000..92f437a
--- /dev/null
+++ b/subversion/libsvn_fs_util/caching.c
@@ -0,0 +1,97 @@
+/* caching.c : in-memory caching
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+#include "svn_fs.h"
+#include "private/svn_fs_private.h"
+#include "private/svn_cache.h"
+
+#include "svn_pools.h"
+
+/* The cache settings as a process-wide singleton.
+ */
+static svn_fs_cache_config_t cache_settings =
+  {
+    /* default configuration:
+     */
+    0x8000000,   /* 128 MB for caches */
+    16,          /* up to 16 files kept open */
+    FALSE,       /* don't cache fulltexts */
+    FALSE,       /* don't cache text deltas */
+    FALSE        /* assume multi-threaded operation */
+  };
+
+/* Get the current FSFS cache configuration. */
+const svn_fs_cache_config_t *
+svn_fs_get_cache_config(void)
+{
+  return &cache_settings;
+}
+
+/* Access the process-global (singleton) membuffer cache. The first call
+ * will automatically allocate the cache using the current cache config.
+ * NULL will be returned if the desired cache size is 0.
+ */
+svn_membuffer_t *
+svn_fs__get_global_membuffer_cache(void)
+{
+  static svn_membuffer_t *cache = NULL;
+
+  apr_uint64_t cache_size = cache_settings.cache_size;
+  if (!cache && cache_size)
+    {
+      /* auto-allocate cache*/
+      apr_allocator_t *allocator = NULL;
+      apr_pool_t *pool = NULL;
+
+      if (apr_allocator_create(&allocator))
+        return NULL;
+
+      /* Ensure that we free partially allocated data if we run OOM
+       * before the cache is complete: If the cache cannot be allocated
+       * in its full size, the create() function will clear the pool
+       * explicitly. The allocator will make sure that any memory no
+       * longer used by the pool will actually be returned to the OS.
+       */
+      apr_allocator_max_free_set(allocator, 1);
+      pool = svn_pool_create_ex(NULL, allocator);
+
+      svn_cache__membuffer_cache_create
+          (&cache,
+           (apr_size_t)cache_size,
+           (apr_size_t)cache_size / 16,
+           ! svn_fs_get_cache_config()->single_threaded,
+           pool);
+    }
+
+  return cache;
+}
+
+void 
+svn_fs_set_cache_config(const svn_fs_cache_config_t *settings)
+{
+  cache_settings = *settings;
+
+  /* Allocate global membuffer cache as a side-effect.
+   * Only the first call will actually take affect. */
+  svn_fs__get_global_membuffer_cache();
+}
+