~ubuntu-branches/debian/sid/subversion/sid

« back to all changes in this revision

Viewing changes to subversion/libsvn_fs_x/caching.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2015-08-07 21:32:47 UTC
  • mfrom: (0.2.15) (4.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20150807213247-ozyewtmgsr6tkewl
Tags: 1.9.0-1
* Upload to unstable
* New upstream release.
  + Security fixes
    - CVE-2015-3184: Mixed anonymous/authenticated path-based authz with
      httpd 2.4
    - CVE-2015-3187: svn_repos_trace_node_locations() reveals paths hidden
      by authz
* Add >= 2.7 requirement for python-all-dev Build-Depends, needed to run
  tests.
* Remove Build-Conflicts against ruby-test-unit.  (Closes: #791844)
* Remove patches/apache_module_dependency in favor of expressing the
  dependencies in authz_svn.load/dav_svn.load.
* Build-Depend on apache2-dev (>= 2.4.16) to ensure ap_some_authn_required()
  is available when building mod_authz_svn and Depend on apache2-bin (>=
  2.4.16) for runtime support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* caching.c : in-memory caching
 
2
 *
 
3
 * ====================================================================
 
4
 *    Licensed to the Apache Software Foundation (ASF) under one
 
5
 *    or more contributor license agreements.  See the NOTICE file
 
6
 *    distributed with this work for additional information
 
7
 *    regarding copyright ownership.  The ASF licenses this file
 
8
 *    to you under the Apache License, Version 2.0 (the
 
9
 *    "License"); you may not use this file except in compliance
 
10
 *    with the License.  You may obtain a copy of the License at
 
11
 *
 
12
 *      http://www.apache.org/licenses/LICENSE-2.0
 
13
 *
 
14
 *    Unless required by applicable law or agreed to in writing,
 
15
 *    software distributed under the License is distributed on an
 
16
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 
17
 *    KIND, either express or implied.  See the License for the
 
18
 *    specific language governing permissions and limitations
 
19
 *    under the License.
 
20
 * ====================================================================
 
21
 */
 
22
 
 
23
#include "fs.h"
 
24
#include "fs_x.h"
 
25
#include "id.h"
 
26
#include "dag.h"
 
27
#include "tree.h"
 
28
#include "index.h"
 
29
#include "changes.h"
 
30
#include "noderevs.h"
 
31
#include "temp_serializer.h"
 
32
#include "reps.h"
 
33
#include "../libsvn_fs/fs-loader.h"
 
34
 
 
35
#include "svn_config.h"
 
36
#include "svn_cache_config.h"
 
37
 
 
38
#include "svn_private_config.h"
 
39
#include "svn_hash.h"
 
40
#include "svn_pools.h"
 
41
 
 
42
#include "private/svn_debug.h"
 
43
#include "private/svn_subr_private.h"
 
44
 
 
45
/* Take the ORIGINAL string and replace all occurrences of ":" without
 
46
 * limiting the key space.  Allocate the result in RESULT_POOL.
 
47
 */
 
48
static const char *
 
49
normalize_key_part(const char *original,
 
50
                   apr_pool_t *result_pool)
 
51
{
 
52
  apr_size_t i;
 
53
  apr_size_t len = strlen(original);
 
54
  svn_stringbuf_t *normalized = svn_stringbuf_create_ensure(len,
 
55
                                                            result_pool);
 
56
 
 
57
  for (i = 0; i < len; ++i)
 
58
    {
 
59
      char c = original[i];
 
60
      switch (c)
 
61
        {
 
62
        case ':': svn_stringbuf_appendbytes(normalized, "%_", 2);
 
63
                  break;
 
64
        case '%': svn_stringbuf_appendbytes(normalized, "%%", 2);
 
65
                  break;
 
66
        default : svn_stringbuf_appendbyte(normalized, c);
 
67
        }
 
68
    }
 
69
 
 
70
  return normalized->data;
 
71
}
 
72
 
 
73
/* *CACHE_TXDELTAS, *CACHE_FULLTEXTS and *CACHE_REVPROPS flags will be set
 
74
   according to FS->CONFIG.  *CACHE_NAMESPACE receives the cache prefix
 
75
   to use.
 
76
 
 
77
   Allocate CACHE_NAMESPACE in RESULT_POOL. */
 
78
static svn_error_t *
 
79
read_config(const char **cache_namespace,
 
80
            svn_boolean_t *cache_txdeltas,
 
81
            svn_boolean_t *cache_fulltexts,
 
82
            svn_boolean_t *cache_revprops,
 
83
            svn_fs_t *fs,
 
84
            apr_pool_t *result_pool)
 
85
{
 
86
  /* No cache namespace by default.  I.e. all FS instances share the
 
87
   * cached data.  If you specify different namespaces, the data will
 
88
   * share / compete for the same cache memory but keys will not match
 
89
   * across namespaces and, thus, cached data will not be shared between
 
90
   * namespaces.
 
91
   *
 
92
   * Since the namespace will be concatenated with other elements to form
 
93
   * the complete key prefix, we must make sure that the resulting string
 
94
   * is unique and cannot be created by any other combination of elements.
 
95
   */
 
96
  *cache_namespace
 
97
    = normalize_key_part(svn_hash__get_cstring(fs->config,
 
98
                                               SVN_FS_CONFIG_FSFS_CACHE_NS,
 
99
                                               ""),
 
100
                         result_pool);
 
101
 
 
102
  /* don't cache text deltas by default.
 
103
   * Once we reconstructed the fulltexts from the deltas,
 
104
   * these deltas are rarely re-used. Therefore, only tools
 
105
   * like svnadmin will activate this to speed up operations
 
106
   * dump and verify.
 
107
   */
 
108
  *cache_txdeltas
 
109
    = svn_hash__get_bool(fs->config,
 
110
                         SVN_FS_CONFIG_FSFS_CACHE_DELTAS,
 
111
                         TRUE);
 
112
 
 
113
  /* by default, cache fulltexts.
 
114
   * Most SVN tools care about reconstructed file content.
 
115
   * Thus, this is a reasonable default.
 
116
   * SVN admin tools may set that to FALSE because fulltexts
 
117
   * won't be re-used rendering the cache less effective
 
118
   * by squeezing wanted data out.
 
119
   */
 
120
  *cache_fulltexts
 
121
    = svn_hash__get_bool(fs->config,
 
122
                         SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
 
123
                         TRUE);
 
124
 
 
125
  /* don't cache revprops by default.
 
126
   * Revprop caching significantly speeds up operations like
 
127
   * svn ls -v. However, it requires synchronization that may
 
128
   * not be available or efficient in the current server setup.
 
129
   * Option "2" is equivalent to "1".
 
130
   */
 
131
  if (strcmp(svn_hash__get_cstring(fs->config,
 
132
                                   SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
 
133
                                   ""), "2"))
 
134
    *cache_revprops
 
135
      = svn_hash__get_bool(fs->config,
 
136
                          SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
 
137
                          FALSE);
 
138
  else
 
139
    *cache_revprops = TRUE;
 
140
 
 
141
  return SVN_NO_ERROR;
 
142
}
 
143
 
 
144
 
 
145
/* Implements svn_cache__error_handler_t
 
146
 * This variant clears the error after logging it.
 
147
 */
 
148
static svn_error_t *
 
149
warn_and_continue_on_cache_errors(svn_error_t *err,
 
150
                                  void *baton,
 
151
                                  apr_pool_t *pool)
 
152
{
 
153
  svn_fs_t *fs = baton;
 
154
  (fs->warning)(fs->warning_baton, err);
 
155
  svn_error_clear(err);
 
156
 
 
157
  return SVN_NO_ERROR;
 
158
}
 
159
 
 
160
/* Implements svn_cache__error_handler_t
 
161
 * This variant logs the error and passes it on to the callers.
 
162
 */
 
163
static svn_error_t *
 
164
warn_and_fail_on_cache_errors(svn_error_t *err,
 
165
                              void *baton,
 
166
                              apr_pool_t *pool)
 
167
{
 
168
  svn_fs_t *fs = baton;
 
169
  (fs->warning)(fs->warning_baton, err);
 
170
  return err;
 
171
}
 
172
 
 
173
#ifdef SVN_DEBUG_CACHE_DUMP_STATS
 
174
/* Baton to be used for the dump_cache_statistics() pool cleanup function, */
 
175
typedef struct dump_cache_baton_t
 
176
{
 
177
  /* the pool about to be cleaned up. Will be used for temp. allocations. */
 
178
  apr_pool_t *pool;
 
179
 
 
180
  /* the cache to dump the statistics for */
 
181
  svn_cache__t *cache;
 
182
} dump_cache_baton_t;
 
183
 
 
184
/* APR pool cleanup handler that will printf the statistics of the
 
185
   cache referenced by the baton in BATON_VOID. */
 
186
static apr_status_t
 
187
dump_cache_statistics(void *baton_void)
 
188
{
 
189
  dump_cache_baton_t *baton = baton_void;
 
190
 
 
191
  apr_status_t result = APR_SUCCESS;
 
192
  svn_cache__info_t info;
 
193
  svn_string_t *text_stats;
 
194
  apr_array_header_t *lines;
 
195
  int i;
 
196
 
 
197
  svn_error_t *err = svn_cache__get_info(baton->cache,
 
198
                                         &info,
 
199
                                         TRUE,
 
200
                                         baton->pool);
 
201
 
 
202
  /* skip unused caches */
 
203
  if (! err && (info.gets > 0 || info.sets > 0))
 
204
    {
 
205
      text_stats = svn_cache__format_info(&info, TRUE, baton->pool);
 
206
      lines = svn_cstring_split(text_stats->data, "\n", FALSE, baton->pool);
 
207
 
 
208
      for (i = 0; i < lines->nelts; ++i)
 
209
        {
 
210
          const char *line = APR_ARRAY_IDX(lines, i, const char *);
 
211
#ifdef SVN_DEBUG
 
212
          SVN_DBG(("%s\n", line));
 
213
#endif
 
214
        }
 
215
    }
 
216
 
 
217
  /* process error returns */
 
218
  if (err)
 
219
    {
 
220
      result = err->apr_err;
 
221
      svn_error_clear(err);
 
222
    }
 
223
 
 
224
  return result;
 
225
}
 
226
 
 
227
static apr_status_t
 
228
dump_global_cache_statistics(void *baton_void)
 
229
{
 
230
  apr_pool_t *pool = baton_void;
 
231
 
 
232
  svn_cache__info_t *info = svn_cache__membuffer_get_global_info(pool);
 
233
  svn_string_t *text_stats = svn_cache__format_info(info, FALSE, pool);
 
234
  apr_array_header_t *lines = svn_cstring_split(text_stats->data, "\n",
 
235
                                                FALSE, pool);
 
236
 
 
237
  int i;
 
238
  for (i = 0; i < lines->nelts; ++i)
 
239
    {
 
240
      const char *line = APR_ARRAY_IDX(lines, i, const char *);
 
241
#ifdef SVN_DEBUG
 
242
      SVN_DBG(("%s\n", line));
 
243
#endif
 
244
    }
 
245
 
 
246
  return APR_SUCCESS;
 
247
}
 
248
 
 
249
#endif /* SVN_DEBUG_CACHE_DUMP_STATS */
 
250
 
 
251
/* This function sets / registers the required callbacks for a given
 
252
 * not transaction-specific CACHE object in FS, if CACHE is not NULL.
 
253
 *
 
254
 * All these svn_cache__t instances shall be handled uniformly. Unless
 
255
 * ERROR_HANDLER is NULL, register it for the given CACHE in FS.
 
256
 */
 
257
static svn_error_t *
 
258
init_callbacks(svn_cache__t *cache,
 
259
               svn_fs_t *fs,
 
260
               svn_cache__error_handler_t error_handler,
 
261
               apr_pool_t *pool)
 
262
{
 
263
  if (cache != NULL)
 
264
    {
 
265
#ifdef SVN_DEBUG_CACHE_DUMP_STATS
 
266
 
 
267
      /* schedule printing the access statistics upon pool cleanup,
 
268
       * i.e. end of FSX session.
 
269
       */
 
270
      dump_cache_baton_t *baton;
 
271
 
 
272
      baton = apr_palloc(pool, sizeof(*baton));
 
273
      baton->pool = pool;
 
274
      baton->cache = cache;
 
275
 
 
276
      apr_pool_cleanup_register(pool,
 
277
                                baton,
 
278
                                dump_cache_statistics,
 
279
                                apr_pool_cleanup_null);
 
280
#endif
 
281
 
 
282
      if (error_handler)
 
283
        SVN_ERR(svn_cache__set_error_handler(cache,
 
284
                                             error_handler,
 
285
                                             fs,
 
286
                                             pool));
 
287
 
 
288
    }
 
289
 
 
290
  return SVN_NO_ERROR;
 
291
}
 
292
 
 
293
/* Sets *CACHE_P to cache instance based on provided options.
 
294
 * Creates memcache if MEMCACHE is not NULL. Creates membuffer cache if
 
295
 * MEMBUFFER is not NULL. Fallbacks to inprocess cache if MEMCACHE and
 
296
 * MEMBUFFER are NULL and pages is non-zero.  Sets *CACHE_P to NULL
 
297
 * otherwise.  Use the given PRIORITY class for the new cache.  If it
 
298
 * is 0, then use the default priority class.
 
299
 *
 
300
 * Unless NO_HANDLER is true, register an error handler that reports errors
 
301
 * as warnings to the FS warning callback.
 
302
 *
 
303
 * Cache is allocated in RESULT_POOL, temporaries in SCRATCH_POOL.
 
304
 * */
 
305
static svn_error_t *
 
306
create_cache(svn_cache__t **cache_p,
 
307
             svn_memcache_t *memcache,
 
308
             svn_membuffer_t *membuffer,
 
309
             apr_int64_t pages,
 
310
             apr_int64_t items_per_page,
 
311
             svn_cache__serialize_func_t serializer,
 
312
             svn_cache__deserialize_func_t deserializer,
 
313
             apr_ssize_t klen,
 
314
             const char *prefix,
 
315
             apr_uint32_t priority,
 
316
             svn_fs_t *fs,
 
317
             svn_boolean_t no_handler,
 
318
             apr_pool_t *result_pool,
 
319
             apr_pool_t *scratch_pool)
 
320
{
 
321
  svn_cache__error_handler_t error_handler = no_handler
 
322
                                           ? NULL
 
323
                                           : warn_and_fail_on_cache_errors;
 
324
  if (priority == 0)
 
325
    priority = SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY;
 
326
 
 
327
  if (memcache)
 
328
    {
 
329
      SVN_ERR(svn_cache__create_memcache(cache_p, memcache,
 
330
                                         serializer, deserializer, klen,
 
331
                                         prefix, result_pool));
 
332
      error_handler = no_handler
 
333
                    ? NULL
 
334
                    : warn_and_continue_on_cache_errors;
 
335
    }
 
336
  else if (membuffer)
 
337
    {
 
338
      SVN_ERR(svn_cache__create_membuffer_cache(
 
339
                cache_p, membuffer, serializer, deserializer,
 
340
                klen, prefix, priority, FALSE, result_pool, scratch_pool));
 
341
    }
 
342
  else if (pages)
 
343
    {
 
344
      SVN_ERR(svn_cache__create_inprocess(
 
345
                cache_p, serializer, deserializer, klen, pages,
 
346
                items_per_page, FALSE, prefix, result_pool));
 
347
    }
 
348
  else
 
349
    {
 
350
      *cache_p = NULL;
 
351
    }
 
352
 
 
353
  SVN_ERR(init_callbacks(*cache_p, fs, error_handler, result_pool));
 
354
 
 
355
  return SVN_NO_ERROR;
 
356
}
 
357
 
 
358
svn_error_t *
 
359
svn_fs_x__initialize_caches(svn_fs_t *fs,
 
360
                            apr_pool_t *scratch_pool)
 
361
{
 
362
  svn_fs_x__data_t *ffd = fs->fsap_data;
 
363
  const char *prefix = apr_pstrcat(scratch_pool,
 
364
                                   "fsx:", fs->uuid,
 
365
                                   "/", normalize_key_part(fs->path,
 
366
                                                           scratch_pool),
 
367
                                   ":",
 
368
                                   SVN_VA_NULL);
 
369
  svn_membuffer_t *membuffer;
 
370
  svn_boolean_t no_handler = ffd->fail_stop;
 
371
  svn_boolean_t cache_txdeltas;
 
372
  svn_boolean_t cache_fulltexts;
 
373
  svn_boolean_t cache_revprops;
 
374
  const char *cache_namespace;
 
375
 
 
376
  /* Evaluating the cache configuration. */
 
377
  SVN_ERR(read_config(&cache_namespace,
 
378
                      &cache_txdeltas,
 
379
                      &cache_fulltexts,
 
380
                      &cache_revprops,
 
381
                      fs,
 
382
                      scratch_pool));
 
383
 
 
384
  prefix = apr_pstrcat(scratch_pool, "ns:", cache_namespace, ":", prefix,
 
385
                       SVN_VA_NULL);
 
386
 
 
387
  membuffer = svn_cache__get_global_membuffer_cache();
 
388
 
 
389
  /* General rules for assigning cache priorities:
 
390
   *
 
391
   * - Data that can be reconstructed from other elements has low prio
 
392
   *   (e.g. fulltexts, directories etc.)
 
393
   * - Index data required to find any of the other data has high prio
 
394
   *   (e.g. noderevs, L2P and P2L index pages)
 
395
   * - everthing else should use default prio
 
396
   */
 
397
 
 
398
#ifdef SVN_DEBUG_CACHE_DUMP_STATS
 
399
 
 
400
  /* schedule printing the global access statistics upon pool cleanup,
 
401
   * i.e. end of FSX session.
 
402
   */
 
403
  if (membuffer)
 
404
    apr_pool_cleanup_register(fs->pool,
 
405
                              fs->pool,
 
406
                              dump_global_cache_statistics,
 
407
                              apr_pool_cleanup_null);
 
408
#endif
 
409
 
 
410
  /* Rough estimate: revision DAG nodes have size around 320 bytes, so
 
411
   * let's put 16 on a page. */
 
412
  SVN_ERR(create_cache(&(ffd->rev_node_cache),
 
413
                       NULL,
 
414
                       membuffer,
 
415
                       1024, 16,
 
416
                       svn_fs_x__dag_serialize,
 
417
                       svn_fs_x__dag_deserialize,
 
418
                       APR_HASH_KEY_STRING,
 
419
                       apr_pstrcat(scratch_pool, prefix, "DAG", SVN_VA_NULL),
 
420
                       SVN_CACHE__MEMBUFFER_LOW_PRIORITY,
 
421
                       fs,
 
422
                       no_handler,
 
423
                       fs->pool, scratch_pool));
 
424
 
 
425
  /* 1st level DAG node cache */
 
426
  ffd->dag_node_cache = svn_fs_x__create_dag_cache(fs->pool);
 
427
 
 
428
  /* Very rough estimate: 1K per directory. */
 
429
  SVN_ERR(create_cache(&(ffd->dir_cache),
 
430
                       NULL,
 
431
                       membuffer,
 
432
                       1024, 8,
 
433
                       svn_fs_x__serialize_dir_entries,
 
434
                       svn_fs_x__deserialize_dir_entries,
 
435
                       sizeof(svn_fs_x__id_t),
 
436
                       apr_pstrcat(scratch_pool, prefix, "DIR", SVN_VA_NULL),
 
437
                       SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
 
438
                       fs,
 
439
                       no_handler,
 
440
                       fs->pool, scratch_pool));
 
441
 
 
442
  /* Only 16 bytes per entry (a revision number + the corresponding offset).
 
443
     Since we want ~8k pages, that means 512 entries per page. */
 
444
  SVN_ERR(create_cache(&(ffd->packed_offset_cache),
 
445
                       NULL,
 
446
                       membuffer,
 
447
                       32, 1,
 
448
                       svn_fs_x__serialize_manifest,
 
449
                       svn_fs_x__deserialize_manifest,
 
450
                       sizeof(svn_revnum_t),
 
451
                       apr_pstrcat(scratch_pool, prefix, "PACK-MANIFEST",
 
452
                                   SVN_VA_NULL),
 
453
                       SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
 
454
                       fs,
 
455
                       no_handler,
 
456
                       fs->pool, scratch_pool));
 
457
 
 
458
  /* initialize node revision cache, if caching has been enabled */
 
459
  SVN_ERR(create_cache(&(ffd->node_revision_cache),
 
460
                       NULL,
 
461
                       membuffer,
 
462
                       32, 32, /* ~200 byte / entry; 1k entries total */
 
463
                       svn_fs_x__serialize_node_revision,
 
464
                       svn_fs_x__deserialize_node_revision,
 
465
                       sizeof(svn_fs_x__pair_cache_key_t),
 
466
                       apr_pstrcat(scratch_pool, prefix, "NODEREVS",
 
467
                                   SVN_VA_NULL),
 
468
                       SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
 
469
                       fs,
 
470
                       no_handler,
 
471
                       fs->pool, scratch_pool));
 
472
 
 
473
  /* initialize representation header cache, if caching has been enabled */
 
474
  SVN_ERR(create_cache(&(ffd->rep_header_cache),
 
475
                       NULL,
 
476
                       membuffer,
 
477
                       1, 1000, /* ~8 bytes / entry; 1k entries total */
 
478
                       svn_fs_x__serialize_rep_header,
 
479
                       svn_fs_x__deserialize_rep_header,
 
480
                       sizeof(svn_fs_x__representation_cache_key_t),
 
481
                       apr_pstrcat(scratch_pool, prefix, "REPHEADER",
 
482
                                   SVN_VA_NULL),
 
483
                       SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
 
484
                       fs,
 
485
                       no_handler,
 
486
                       fs->pool, scratch_pool));
 
487
 
 
488
  /* initialize node change list cache, if caching has been enabled */
 
489
  SVN_ERR(create_cache(&(ffd->changes_cache),
 
490
                       NULL,
 
491
                       membuffer,
 
492
                       1, 8, /* 1k / entry; 8 entries total, rarely used */
 
493
                       svn_fs_x__serialize_changes,
 
494
                       svn_fs_x__deserialize_changes,
 
495
                       sizeof(svn_revnum_t),
 
496
                       apr_pstrcat(scratch_pool, prefix, "CHANGES",
 
497
                                   SVN_VA_NULL),
 
498
                       0,
 
499
                       fs,
 
500
                       no_handler,
 
501
                       fs->pool, scratch_pool));
 
502
 
 
503
  /* if enabled, cache fulltext and other derived information */
 
504
  if (cache_fulltexts)
 
505
    {
 
506
      SVN_ERR(create_cache(&(ffd->fulltext_cache),
 
507
                           ffd->memcache,
 
508
                           membuffer,
 
509
                           0, 0, /* Do not use inprocess cache */
 
510
                           /* Values are svn_stringbuf_t */
 
511
                           NULL, NULL,
 
512
                           sizeof(svn_fs_x__pair_cache_key_t),
 
513
                           apr_pstrcat(scratch_pool, prefix, "TEXT",
 
514
                                       SVN_VA_NULL),
 
515
                           SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
 
516
                           fs,
 
517
                           no_handler,
 
518
                           fs->pool, scratch_pool));
 
519
 
 
520
      SVN_ERR(create_cache(&(ffd->properties_cache),
 
521
                           NULL,
 
522
                           membuffer,
 
523
                           0, 0, /* Do not use inprocess cache */
 
524
                           svn_fs_x__serialize_properties,
 
525
                           svn_fs_x__deserialize_properties,
 
526
                           sizeof(svn_fs_x__pair_cache_key_t),
 
527
                           apr_pstrcat(scratch_pool, prefix, "PROP",
 
528
                                       SVN_VA_NULL),
 
529
                           SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
 
530
                           fs,
 
531
                           no_handler,
 
532
                           fs->pool, scratch_pool));
 
533
 
 
534
      SVN_ERR(create_cache(&(ffd->mergeinfo_cache),
 
535
                           NULL,
 
536
                           membuffer,
 
537
                           0, 0, /* Do not use inprocess cache */
 
538
                           svn_fs_x__serialize_mergeinfo,
 
539
                           svn_fs_x__deserialize_mergeinfo,
 
540
                           APR_HASH_KEY_STRING,
 
541
                           apr_pstrcat(scratch_pool, prefix, "MERGEINFO",
 
542
                                       SVN_VA_NULL),
 
543
                           0,
 
544
                           fs,
 
545
                           no_handler,
 
546
                           fs->pool, scratch_pool));
 
547
 
 
548
      SVN_ERR(create_cache(&(ffd->mergeinfo_existence_cache),
 
549
                           NULL,
 
550
                           membuffer,
 
551
                           0, 0, /* Do not use inprocess cache */
 
552
                           /* Values are svn_stringbuf_t */
 
553
                           NULL, NULL,
 
554
                           APR_HASH_KEY_STRING,
 
555
                           apr_pstrcat(scratch_pool, prefix, "HAS_MERGEINFO",
 
556
                                       SVN_VA_NULL),
 
557
                           0,
 
558
                           fs,
 
559
                           no_handler,
 
560
                           fs->pool, scratch_pool));
 
561
    }
 
562
  else
 
563
    {
 
564
      ffd->fulltext_cache = NULL;
 
565
      ffd->properties_cache = NULL;
 
566
      ffd->mergeinfo_cache = NULL;
 
567
      ffd->mergeinfo_existence_cache = NULL;
 
568
    }
 
569
 
 
570
  /* if enabled, cache revprops */
 
571
  if (cache_revprops)
 
572
    {
 
573
      SVN_ERR(create_cache(&(ffd->revprop_cache),
 
574
                           NULL,
 
575
                           membuffer,
 
576
                           0, 0, /* Do not use inprocess cache */
 
577
                           svn_fs_x__serialize_properties,
 
578
                           svn_fs_x__deserialize_properties,
 
579
                           sizeof(svn_fs_x__pair_cache_key_t),
 
580
                           apr_pstrcat(scratch_pool, prefix, "REVPROP",
 
581
                                       SVN_VA_NULL),
 
582
                           SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
 
583
                           fs,
 
584
                           no_handler,
 
585
                           fs->pool, scratch_pool));
 
586
    }
 
587
  else
 
588
    {
 
589
      ffd->revprop_cache = NULL;
 
590
    }
 
591
 
 
592
  /* if enabled, cache text deltas and their combinations */
 
593
  if (cache_txdeltas)
 
594
    {
 
595
      SVN_ERR(create_cache(&(ffd->txdelta_window_cache),
 
596
                           NULL,
 
597
                           membuffer,
 
598
                           0, 0, /* Do not use inprocess cache */
 
599
                           svn_fs_x__serialize_txdelta_window,
 
600
                           svn_fs_x__deserialize_txdelta_window,
 
601
                           sizeof(svn_fs_x__window_cache_key_t),
 
602
                           apr_pstrcat(scratch_pool, prefix, "TXDELTA_WINDOW",
 
603
                                       SVN_VA_NULL),
 
604
                           SVN_CACHE__MEMBUFFER_LOW_PRIORITY,
 
605
                           fs,
 
606
                           no_handler,
 
607
                           fs->pool, scratch_pool));
 
608
 
 
609
      SVN_ERR(create_cache(&(ffd->combined_window_cache),
 
610
                           NULL,
 
611
                           membuffer,
 
612
                           0, 0, /* Do not use inprocess cache */
 
613
                           /* Values are svn_stringbuf_t */
 
614
                           NULL, NULL,
 
615
                           sizeof(svn_fs_x__window_cache_key_t),
 
616
                           apr_pstrcat(scratch_pool, prefix, "COMBINED_WINDOW",
 
617
                                       SVN_VA_NULL),
 
618
                           SVN_CACHE__MEMBUFFER_LOW_PRIORITY,
 
619
                           fs,
 
620
                           no_handler,
 
621
                           fs->pool, scratch_pool));
 
622
    }
 
623
  else
 
624
    {
 
625
      ffd->txdelta_window_cache = NULL;
 
626
      ffd->combined_window_cache = NULL;
 
627
    }
 
628
 
 
629
  SVN_ERR(create_cache(&(ffd->noderevs_container_cache),
 
630
                       NULL,
 
631
                       membuffer,
 
632
                       16, 4, /* Important, largish objects */
 
633
                       svn_fs_x__serialize_noderevs_container,
 
634
                       svn_fs_x__deserialize_noderevs_container,
 
635
                       sizeof(svn_fs_x__pair_cache_key_t),
 
636
                       apr_pstrcat(scratch_pool, prefix, "NODEREVSCNT",
 
637
                                   SVN_VA_NULL),
 
638
                       SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
 
639
                       fs,
 
640
                       no_handler,
 
641
                       fs->pool, scratch_pool));
 
642
  SVN_ERR(create_cache(&(ffd->changes_container_cache),
 
643
                       NULL,
 
644
                       membuffer,
 
645
                       0, 0, /* Do not use inprocess cache */
 
646
                       svn_fs_x__serialize_changes_container,
 
647
                       svn_fs_x__deserialize_changes_container,
 
648
                       sizeof(svn_fs_x__pair_cache_key_t),
 
649
                       apr_pstrcat(scratch_pool, prefix, "CHANGESCNT",
 
650
                                   SVN_VA_NULL),
 
651
                       0,
 
652
                       fs,
 
653
                       no_handler,
 
654
                       fs->pool, scratch_pool));
 
655
  SVN_ERR(create_cache(&(ffd->reps_container_cache),
 
656
                       NULL,
 
657
                       membuffer,
 
658
                       0, 0, /* Do not use inprocess cache */
 
659
                       svn_fs_x__serialize_reps_container,
 
660
                       svn_fs_x__deserialize_reps_container,
 
661
                       sizeof(svn_fs_x__pair_cache_key_t),
 
662
                       apr_pstrcat(scratch_pool, prefix, "REPSCNT",
 
663
                                   SVN_VA_NULL),
 
664
                       0,
 
665
                       fs,
 
666
                       no_handler,
 
667
                       fs->pool, scratch_pool));
 
668
 
 
669
  SVN_ERR(create_cache(&(ffd->l2p_header_cache),
 
670
                       NULL,
 
671
                       membuffer,
 
672
                       64, 16, /* entry size varies but we must cover
 
673
                                  a reasonable number of revisions (1k) */
 
674
                       svn_fs_x__serialize_l2p_header,
 
675
                       svn_fs_x__deserialize_l2p_header,
 
676
                       sizeof(svn_fs_x__pair_cache_key_t),
 
677
                       apr_pstrcat(scratch_pool, prefix, "L2P_HEADER",
 
678
                                   SVN_VA_NULL),
 
679
                       SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
 
680
                       fs,
 
681
                       no_handler,
 
682
                       fs->pool, scratch_pool));
 
683
  SVN_ERR(create_cache(&(ffd->l2p_page_cache),
 
684
                       NULL,
 
685
                       membuffer,
 
686
                       64, 16, /* entry size varies but we must cover
 
687
                                  a reasonable number of revisions (1k) */
 
688
                       svn_fs_x__serialize_l2p_page,
 
689
                       svn_fs_x__deserialize_l2p_page,
 
690
                       sizeof(svn_fs_x__page_cache_key_t),
 
691
                       apr_pstrcat(scratch_pool, prefix, "L2P_PAGE",
 
692
                                   SVN_VA_NULL),
 
693
                       SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
 
694
                       fs,
 
695
                       no_handler,
 
696
                       fs->pool, scratch_pool));
 
697
  SVN_ERR(create_cache(&(ffd->p2l_header_cache),
 
698
                       NULL,
 
699
                       membuffer,
 
700
                       4, 1, /* Large entries. Rarely used. */
 
701
                       svn_fs_x__serialize_p2l_header,
 
702
                       svn_fs_x__deserialize_p2l_header,
 
703
                       sizeof(svn_fs_x__pair_cache_key_t),
 
704
                       apr_pstrcat(scratch_pool, prefix, "P2L_HEADER",
 
705
                                   SVN_VA_NULL),
 
706
                       SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
 
707
                       fs,
 
708
                       no_handler,
 
709
                       fs->pool, scratch_pool));
 
710
  SVN_ERR(create_cache(&(ffd->p2l_page_cache),
 
711
                       NULL,
 
712
                       membuffer,
 
713
                       4, 16, /* Variably sized entries. Rarely used. */
 
714
                       svn_fs_x__serialize_p2l_page,
 
715
                       svn_fs_x__deserialize_p2l_page,
 
716
                       sizeof(svn_fs_x__page_cache_key_t),
 
717
                       apr_pstrcat(scratch_pool, prefix, "P2L_PAGE",
 
718
                                   SVN_VA_NULL),
 
719
                       SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
 
720
                       fs,
 
721
                       no_handler,
 
722
                       fs->pool, scratch_pool));
 
723
 
 
724
  return SVN_NO_ERROR;
 
725
}