diff options
Diffstat (limited to 'subversion/libsvn_fs_x/caching.c')
-rw-r--r-- | subversion/libsvn_fs_x/caching.c | 351 |
1 files changed, 154 insertions, 197 deletions
diff --git a/subversion/libsvn_fs_x/caching.c b/subversion/libsvn_fs_x/caching.c index 17e80bddc6982..8c65ab11a2a84 100644 --- a/subversion/libsvn_fs_x/caching.c +++ b/subversion/libsvn_fs_x/caching.c @@ -23,8 +23,7 @@ #include "fs.h" #include "fs_x.h" #include "id.h" -#include "dag.h" -#include "tree.h" +#include "dag_cache.h" #include "index.h" #include "changes.h" #include "noderevs.h" @@ -70,9 +69,9 @@ normalize_key_part(const char *original, return normalized->data; } -/* *CACHE_TXDELTAS, *CACHE_FULLTEXTS and *CACHE_REVPROPS flags will be set - according to FS->CONFIG. *CACHE_NAMESPACE receives the cache prefix - to use. +/* *CACHE_TXDELTAS, *CACHE_FULLTEXTS, *CACHE_REVPROPS and *CACHE_NODEPROPS + flags will be set according to FS->CONFIG. *CACHE_NAMESPACE receives + the cache prefix to use. Allocate CACHE_NAMESPACE in RESULT_POOL. */ static svn_error_t * @@ -80,6 +79,7 @@ read_config(const char **cache_namespace, svn_boolean_t *cache_txdeltas, svn_boolean_t *cache_fulltexts, svn_boolean_t *cache_revprops, + svn_boolean_t *cache_nodeprops, svn_fs_t *fs, apr_pool_t *result_pool) { @@ -138,6 +138,15 @@ read_config(const char **cache_namespace, else *cache_revprops = 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; } @@ -260,42 +269,42 @@ init_callbacks(svn_cache__t *cache, svn_cache__error_handler_t error_handler, apr_pool_t *pool) { - if (cache != NULL) - { #ifdef SVN_DEBUG_CACHE_DUMP_STATS - /* schedule printing the access statistics upon pool cleanup, - * i.e. end of FSX session. - */ - dump_cache_baton_t *baton; + /* schedule printing the access statistics upon pool cleanup, + * i.e. end of FSX session. + */ + dump_cache_baton_t *baton; - baton = apr_palloc(pool, sizeof(*baton)); - baton->pool = pool; - baton->cache = cache; + baton = apr_palloc(pool, sizeof(*baton)); + baton->pool = pool; + baton->cache = cache; - apr_pool_cleanup_register(pool, - baton, - dump_cache_statistics, - apr_pool_cleanup_null); + apr_pool_cleanup_register(pool, + baton, + dump_cache_statistics, + apr_pool_cleanup_null); #endif - if (error_handler) - SVN_ERR(svn_cache__set_error_handler(cache, - error_handler, - fs, - pool)); - - } + if (error_handler) + SVN_ERR(svn_cache__set_error_handler(cache, + error_handler, + fs, + pool)); return SVN_NO_ERROR; } /* Sets *CACHE_P to cache instance based on provided options. - * Creates memcache if MEMCACHE is not NULL. Creates membuffer cache if - * MEMBUFFER is not NULL. Fallbacks to inprocess cache if MEMCACHE and - * MEMBUFFER are NULL and pages is non-zero. Sets *CACHE_P to NULL - * otherwise. Use the given PRIORITY class for the new cache. If it - * is 0, then use the default priority class. + * + * If DUMMY_CACHE is set, create a null cache. Otherwise, creates a memcache + * if MEMCACHE is not NULL or a membuffer cache if MEMBUFFER is not NULL. + * Falls back to inprocess cache if no other cache type has been selected + * and PAGES is not 0. Create a null cache otherwise. + * + * Use the given PRIORITY class for the new cache. If PRIORITY is 0, then + * use the default priority class. HAS_NAMESPACE indicates whether we + * prefixed this cache instance with a namespace. * * Unless NO_HANDLER is true, register an error handler that reports errors * as warnings to the FS warning callback. @@ -313,8 +322,10 @@ create_cache(svn_cache__t **cache_p, apr_ssize_t klen, const char *prefix, apr_uint32_t priority, + svn_boolean_t has_namespace, svn_fs_t *fs, svn_boolean_t no_handler, + svn_boolean_t dummy_cache, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -324,7 +335,11 @@ create_cache(svn_cache__t **cache_p, if (priority == 0) priority = SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY; - if (memcache) + if (dummy_cache) + { + SVN_ERR(svn_cache__create_null(cache_p, prefix, result_pool)); + } + else if (memcache) { SVN_ERR(svn_cache__create_memcache(cache_p, memcache, serializer, deserializer, klen, @@ -335,9 +350,12 @@ create_cache(svn_cache__t **cache_p, } else if (membuffer) { + /* We assume caches with namespaces to be relatively short-lived, + * i.e. their data will not be needed after a while. */ SVN_ERR(svn_cache__create_membuffer_cache( cache_p, membuffer, serializer, deserializer, - klen, prefix, priority, FALSE, result_pool, scratch_pool)); + klen, prefix, priority, FALSE, has_namespace, + result_pool, scratch_pool)); } else if (pages) { @@ -347,7 +365,7 @@ create_cache(svn_cache__t **cache_p, } else { - *cache_p = NULL; + SVN_ERR(svn_cache__create_null(cache_p, prefix, result_pool)); } SVN_ERR(init_callbacks(*cache_p, fs, error_handler, result_pool)); @@ -362,6 +380,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, svn_fs_x__data_t *ffd = fs->fsap_data; const char *prefix = apr_pstrcat(scratch_pool, "fsx:", fs->uuid, + "--", ffd->instance_id, "/", normalize_key_part(fs->path, scratch_pool), ":", @@ -371,25 +390,29 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, svn_boolean_t cache_txdeltas; svn_boolean_t cache_fulltexts; svn_boolean_t cache_revprops; + svn_boolean_t cache_nodeprops; const char *cache_namespace; + svn_boolean_t has_namespace; /* Evaluating the cache configuration. */ SVN_ERR(read_config(&cache_namespace, &cache_txdeltas, &cache_fulltexts, &cache_revprops, + &cache_nodeprops, fs, scratch_pool)); prefix = apr_pstrcat(scratch_pool, "ns:", cache_namespace, ":", prefix, SVN_VA_NULL); + has_namespace = strlen(cache_namespace) > 0; membuffer = svn_cache__get_global_membuffer_cache(); /* General rules for assigning cache priorities: * * - Data that can be reconstructed from other elements has low prio - * (e.g. fulltexts, directories etc.) + * (e.g. fulltexts etc.) * - Index data required to find any of the other data has high prio * (e.g. noderevs, L2P and P2L index pages) * - everthing else should use default prio @@ -407,21 +430,6 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pool_cleanup_null); #endif - /* Rough estimate: revision DAG nodes have size around 320 bytes, so - * let's put 16 on a page. */ - SVN_ERR(create_cache(&(ffd->rev_node_cache), - NULL, - membuffer, - 1024, 16, - svn_fs_x__dag_serialize, - svn_fs_x__dag_deserialize, - APR_HASH_KEY_STRING, - apr_pstrcat(scratch_pool, prefix, "DAG", SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_LOW_PRIORITY, - fs, - no_handler, - fs->pool, scratch_pool)); - /* 1st level DAG node cache */ ffd->dag_node_cache = svn_fs_x__create_dag_cache(fs->pool); @@ -434,25 +442,10 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, svn_fs_x__deserialize_dir_entries, sizeof(svn_fs_x__id_t), apr_pstrcat(scratch_pool, prefix, "DIR", SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, - fs, - no_handler, - fs->pool, scratch_pool)); - - /* Only 16 bytes per entry (a revision number + the corresponding offset). - Since we want ~8k pages, that means 512 entries per page. */ - SVN_ERR(create_cache(&(ffd->packed_offset_cache), - NULL, - membuffer, - 32, 1, - svn_fs_x__serialize_manifest, - svn_fs_x__deserialize_manifest, - sizeof(svn_revnum_t), - apr_pstrcat(scratch_pool, prefix, "PACK-MANIFEST", - SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); /* initialize node revision cache, if caching has been enabled */ @@ -466,8 +459,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "NODEREVS", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); /* initialize representation header cache, if caching has been enabled */ @@ -481,8 +475,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "REPHEADER", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); /* initialize node change list cache, if caching has been enabled */ @@ -492,140 +487,94 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, 1, 8, /* 1k / entry; 8 entries total, rarely used */ svn_fs_x__serialize_changes, svn_fs_x__deserialize_changes, - sizeof(svn_revnum_t), + sizeof(svn_fs_x__pair_cache_key_t), apr_pstrcat(scratch_pool, prefix, "CHANGES", SVN_VA_NULL), 0, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); /* if enabled, cache fulltext and other derived information */ - if (cache_fulltexts) - { - SVN_ERR(create_cache(&(ffd->fulltext_cache), - ffd->memcache, - membuffer, - 0, 0, /* Do not use inprocess cache */ - /* Values are svn_stringbuf_t */ - NULL, NULL, - sizeof(svn_fs_x__pair_cache_key_t), - apr_pstrcat(scratch_pool, prefix, "TEXT", - SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, - fs, - no_handler, - fs->pool, scratch_pool)); - - SVN_ERR(create_cache(&(ffd->properties_cache), - NULL, - membuffer, - 0, 0, /* Do not use inprocess cache */ - svn_fs_x__serialize_properties, - svn_fs_x__deserialize_properties, - sizeof(svn_fs_x__pair_cache_key_t), - apr_pstrcat(scratch_pool, prefix, "PROP", - SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, - fs, - no_handler, - fs->pool, scratch_pool)); - - SVN_ERR(create_cache(&(ffd->mergeinfo_cache), - NULL, - membuffer, - 0, 0, /* Do not use inprocess cache */ - svn_fs_x__serialize_mergeinfo, - svn_fs_x__deserialize_mergeinfo, - APR_HASH_KEY_STRING, - apr_pstrcat(scratch_pool, prefix, "MERGEINFO", - SVN_VA_NULL), - 0, - fs, - no_handler, - fs->pool, scratch_pool)); - - SVN_ERR(create_cache(&(ffd->mergeinfo_existence_cache), - NULL, - membuffer, - 0, 0, /* Do not use inprocess cache */ - /* Values are svn_stringbuf_t */ - NULL, NULL, - APR_HASH_KEY_STRING, - apr_pstrcat(scratch_pool, prefix, "HAS_MERGEINFO", - SVN_VA_NULL), - 0, - fs, - no_handler, - fs->pool, scratch_pool)); - } - else - { - ffd->fulltext_cache = NULL; - ffd->properties_cache = NULL; - ffd->mergeinfo_cache = NULL; - ffd->mergeinfo_existence_cache = NULL; - } + SVN_ERR(create_cache(&(ffd->fulltext_cache), + ffd->memcache, + membuffer, + 0, 0, /* Do not use inprocess cache */ + /* Values are svn_stringbuf_t */ + NULL, NULL, + sizeof(svn_fs_x__pair_cache_key_t), + apr_pstrcat(scratch_pool, prefix, "TEXT", + SVN_VA_NULL), + SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, + has_namespace, + fs, + no_handler, !cache_fulltexts, + fs->pool, scratch_pool)); + + SVN_ERR(create_cache(&(ffd->properties_cache), + NULL, + membuffer, + 0, 0, /* Do not use inprocess cache */ + svn_fs_x__serialize_properties, + svn_fs_x__deserialize_properties, + sizeof(svn_fs_x__pair_cache_key_t), + apr_pstrcat(scratch_pool, prefix, "PROP", + SVN_VA_NULL), + SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, + has_namespace, + fs, + no_handler, !cache_nodeprops, + fs->pool, scratch_pool)); /* if enabled, cache revprops */ - if (cache_revprops) - { - SVN_ERR(create_cache(&(ffd->revprop_cache), - NULL, - membuffer, - 0, 0, /* Do not use inprocess cache */ - svn_fs_x__serialize_properties, - svn_fs_x__deserialize_properties, - sizeof(svn_fs_x__pair_cache_key_t), - apr_pstrcat(scratch_pool, prefix, "REVPROP", - SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, - fs, - no_handler, - fs->pool, scratch_pool)); - } - else - { - ffd->revprop_cache = NULL; - } + SVN_ERR(create_cache(&(ffd->revprop_cache), + NULL, + membuffer, + 0, 0, /* Do not use inprocess cache */ + svn_fs_x__serialize_properties, + svn_fs_x__deserialize_properties, + sizeof(svn_fs_x__pair_cache_key_t), + apr_pstrcat(scratch_pool, prefix, "REVPROP", + SVN_VA_NULL), + SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, + has_namespace, + fs, + no_handler, !cache_revprops, + fs->pool, scratch_pool)); /* if enabled, cache text deltas and their combinations */ - if (cache_txdeltas) - { - SVN_ERR(create_cache(&(ffd->txdelta_window_cache), - NULL, - membuffer, - 0, 0, /* Do not use inprocess cache */ - svn_fs_x__serialize_txdelta_window, - svn_fs_x__deserialize_txdelta_window, - sizeof(svn_fs_x__window_cache_key_t), - apr_pstrcat(scratch_pool, prefix, "TXDELTA_WINDOW", - SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_LOW_PRIORITY, - fs, - no_handler, - fs->pool, scratch_pool)); - - SVN_ERR(create_cache(&(ffd->combined_window_cache), - NULL, - membuffer, - 0, 0, /* Do not use inprocess cache */ - /* Values are svn_stringbuf_t */ - NULL, NULL, - sizeof(svn_fs_x__window_cache_key_t), - apr_pstrcat(scratch_pool, prefix, "COMBINED_WINDOW", - SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_LOW_PRIORITY, - fs, - no_handler, - fs->pool, scratch_pool)); - } - else - { - ffd->txdelta_window_cache = NULL; - ffd->combined_window_cache = NULL; - } + SVN_ERR(create_cache(&(ffd->txdelta_window_cache), + NULL, + membuffer, + 0, 0, /* Do not use inprocess cache */ + svn_fs_x__serialize_txdelta_window, + svn_fs_x__deserialize_txdelta_window, + sizeof(svn_fs_x__window_cache_key_t), + apr_pstrcat(scratch_pool, prefix, "TXDELTA_WINDOW", + SVN_VA_NULL), + SVN_CACHE__MEMBUFFER_LOW_PRIORITY, + has_namespace, + fs, + no_handler, !cache_txdeltas, + fs->pool, scratch_pool)); + + SVN_ERR(create_cache(&(ffd->combined_window_cache), + NULL, + membuffer, + 0, 0, /* Do not use inprocess cache */ + /* Values are svn_stringbuf_t */ + NULL, NULL, + sizeof(svn_fs_x__window_cache_key_t), + apr_pstrcat(scratch_pool, prefix, "COMBINED_WINDOW", + SVN_VA_NULL), + SVN_CACHE__MEMBUFFER_LOW_PRIORITY, + has_namespace, + fs, + no_handler, !cache_txdeltas, + fs->pool, scratch_pool)); + /* Caches for our various container types. */ SVN_ERR(create_cache(&(ffd->noderevs_container_cache), NULL, membuffer, @@ -636,8 +585,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "NODEREVSCNT", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); SVN_ERR(create_cache(&(ffd->changes_container_cache), NULL, @@ -649,8 +599,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "CHANGESCNT", SVN_VA_NULL), 0, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); SVN_ERR(create_cache(&(ffd->reps_container_cache), NULL, @@ -662,10 +613,12 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "REPSCNT", SVN_VA_NULL), 0, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); + /* Cache index info. */ SVN_ERR(create_cache(&(ffd->l2p_header_cache), NULL, membuffer, @@ -677,8 +630,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "L2P_HEADER", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); SVN_ERR(create_cache(&(ffd->l2p_page_cache), NULL, @@ -691,8 +645,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "L2P_PAGE", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); SVN_ERR(create_cache(&(ffd->p2l_header_cache), NULL, @@ -704,8 +659,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "P2L_HEADER", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); SVN_ERR(create_cache(&(ffd->p2l_page_cache), NULL, @@ -717,8 +673,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "P2L_PAGE", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); return SVN_NO_ERROR; |