]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/subversion/subversion/libsvn_fs_x/caching.c
MFC r275385 (by bapt):
[FreeBSD/stable/10.git] / contrib / subversion / subversion / libsvn_fs_x / caching.c
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 }