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 2013/07/19 23:21:36 UTC
svn commit: r1505026 - in /subversion/trunk: ./ subversion/include/private/
subversion/libsvn_fs_fs/ subversion/libsvn_subr/
subversion/tests/libsvn_subr/ tools/server-side/
Author: stefan2
Date: Fri Jul 19 21:21:36 2013
New Revision: 1505026
URL: http://svn.apache.org/r1505026
Log:
Merge revisions r1442051,1442504,1443803,1444690,1477166,1478055,1490674
from branches/fsfs-format7. These introduce the notion of priorities to our
caches and plus comprise all other caching improvements.
A few conflicts had to be resolved.
Modified:
subversion/trunk/ (props changed)
subversion/trunk/subversion/include/private/svn_cache.h
subversion/trunk/subversion/libsvn_fs_fs/caching.c
subversion/trunk/subversion/libsvn_subr/cache-inprocess.c
subversion/trunk/subversion/libsvn_subr/cache-membuffer.c
subversion/trunk/subversion/libsvn_subr/cache-memcache.c
subversion/trunk/subversion/libsvn_subr/cache.c
subversion/trunk/subversion/libsvn_subr/cache.h
subversion/trunk/subversion/tests/libsvn_subr/cache-test.c
subversion/trunk/tools/server-side/fsfs-stats.c
Propchange: subversion/trunk/
------------------------------------------------------------------------------
Merged /subversion/branches/fsfs-format7:r1442051,1442504,1443803,1444690,1477166,1478055,1490674
Modified: subversion/trunk/subversion/include/private/svn_cache.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_cache.h?rev=1505026&r1=1505025&r2=1505026&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_cache.h (original)
+++ subversion/trunk/subversion/include/private/svn_cache.h Fri Jul 19 21:21:36 2013
@@ -305,6 +305,33 @@ svn_cache__membuffer_cache_create(svn_me
apr_pool_t *result_pool);
/**
+ * @defgroup Standard priority classes for #svn_cache__create_membuffer_cache.
+ * @{
+ */
+
+/**
+ * Data in this priority class should not be removed from the cache unless
+ * absolutely necessary. Use of this should be very restricted.
+ */
+#define SVN_CACHE__MEMBUFFER_HIGH_PRIORITY 10000
+
+/**
+ * Data in this priority class has a good chance to remain in cache unless
+ * there is more data in this class than the cache's capcity. Use of this
+ * as the default for all information that is costly to fetch from disk.
+ */
+#define SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY 1000
+
+/**
+ * Data in this priority class will be removed as soon as the cache starts
+ * filling up. Use of this for ephemeral data that can easisly be acquired
+ * again from other sources.
+ */
+#define SVN_CACHE__MEMBUFFER_LOW_PRIORITY 100
+
+/** @} */
+
+/**
* Creates a new cache in @a *cache_p, storing the data in a potentially
* shared @a membuffer object. The elements in the cache will be indexed
* by keys of length @a klen, which may be APR_HASH_KEY_STRING if they
@@ -312,7 +339,9 @@ svn_cache__membuffer_cache_create(svn_me
* serialize_func and deserialized using @a deserialize_func. Because
* the same memcache object may cache many different kinds of values
* form multiple caches, @a prefix should be specified to differentiate
- * this cache from other caches. @a *cache_p will be allocated in @a result_pool.
+ * this cache from other caches. All entries written through this cache
+ * interface will be assigned into the given @a priority class. @a *cache_p
+ * will be allocated in @a result_pool.
*
* If @a deserialize_func is NULL, then the data is returned as an
* svn_string_t; if @a serialize_func is NULL, then the data is
@@ -331,6 +360,7 @@ svn_cache__create_membuffer_cache(svn_ca
svn_cache__deserialize_func_t deserialize,
apr_ssize_t klen,
const char *prefix,
+ apr_uint32_t priority,
svn_boolean_t thread_safe,
apr_pool_t *result_pool);
@@ -377,6 +407,18 @@ svn_cache__get(void **value,
apr_pool_t *result_pool);
/**
+ * Looks for an entry indexed by @a key in @a cache, setting @a *found
+ * to TRUE if an entry has been found and FALSE otherwise. @a key may be
+ * NULL in which case @a *found will be FALSE. Temporary allocations will
+ * be made from @a scratch_pool.
+ */
+svn_error_t *
+svn_cache__has_key(svn_boolean_t *found,
+ svn_cache__t *cache,
+ const void *key,
+ apr_pool_t *scratch_pool);
+
+/**
* Stores the value @a value under the key @a key in @a cache. Uses @a
* scratch_pool for temporary allocations. The cache makes copies of
* @a key and @a value if necessary (that is, @a key and @a value may
Modified: subversion/trunk/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/caching.c?rev=1505026&r1=1505025&r2=1505026&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/caching.c Fri Jul 19 21:21:36 2013
@@ -305,7 +305,8 @@ init_callbacks(svn_cache__t *cache,
* 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.
+ * otherwise. Use the given PRIORITY class for the new cache. If it
+ * is 0, then use the default priority class.
*
* Unless NO_HANDLER is true, register an error handler that reports errors
* as warnings to the FS warning callback.
@@ -322,6 +323,7 @@ create_cache(svn_cache__t **cache_p,
svn_cache__deserialize_func_t deserializer,
apr_ssize_t klen,
const char *prefix,
+ apr_uint32_t priority,
svn_fs_t *fs,
svn_boolean_t no_handler,
apr_pool_t *pool)
@@ -329,6 +331,8 @@ create_cache(svn_cache__t **cache_p,
svn_cache__error_handler_t error_handler = no_handler
? NULL
: warn_and_fail_on_cache_errors;
+ if (priority == 0)
+ priority = SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY;
if (memcache)
{
@@ -343,7 +347,7 @@ create_cache(svn_cache__t **cache_p,
{
SVN_ERR(svn_cache__create_membuffer_cache(
cache_p, membuffer, serializer, deserializer,
- klen, prefix, FALSE, pool));
+ klen, prefix, priority, FALSE, pool));
}
else if (pages)
{
@@ -421,6 +425,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
svn_fs_fs__deserialize_id,
sizeof(svn_revnum_t),
apr_pstrcat(pool, prefix, "RRI", (char *)NULL),
+ 0,
fs,
no_handler,
fs->pool));
@@ -435,6 +440,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
svn_fs_fs__dag_deserialize,
APR_HASH_KEY_STRING,
apr_pstrcat(pool, prefix, "DAG", (char *)NULL),
+ 0,
fs,
no_handler,
fs->pool));
@@ -451,6 +457,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
svn_fs_fs__deserialize_dir_entries,
APR_HASH_KEY_STRING,
apr_pstrcat(pool, prefix, "DIR", (char *)NULL),
+ 0,
fs,
no_handler,
fs->pool));
@@ -466,6 +473,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
sizeof(svn_revnum_t),
apr_pstrcat(pool, prefix, "PACK-MANIFEST",
(char *)NULL),
+ 0,
fs,
no_handler,
fs->pool));
@@ -479,6 +487,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
svn_fs_fs__deserialize_node_revision,
sizeof(pair_cache_key_t),
apr_pstrcat(pool, prefix, "NODEREVS", (char *)NULL),
+ 0,
fs,
no_handler,
fs->pool));
@@ -492,6 +501,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
svn_fs_fs__deserialize_changes,
sizeof(svn_revnum_t),
apr_pstrcat(pool, prefix, "CHANGES", (char *)NULL),
+ 0,
fs,
no_handler,
fs->pool));
@@ -507,6 +517,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
NULL, NULL,
sizeof(pair_cache_key_t),
apr_pstrcat(pool, prefix, "TEXT", (char *)NULL),
+ SVN_CACHE__MEMBUFFER_LOW_PRIORITY,
fs,
no_handler,
fs->pool));
@@ -520,6 +531,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
sizeof(pair_cache_key_t),
apr_pstrcat(pool, prefix, "PROP",
(char *)NULL),
+ 0,
fs,
no_handler,
fs->pool));
@@ -533,6 +545,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
APR_HASH_KEY_STRING,
apr_pstrcat(pool, prefix, "MERGEINFO",
(char *)NULL),
+ 0,
fs,
no_handler,
fs->pool));
@@ -546,6 +559,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
APR_HASH_KEY_STRING,
apr_pstrcat(pool, prefix, "HAS_MERGEINFO",
(char *)NULL),
+ 0,
fs,
no_handler,
fs->pool));
@@ -570,6 +584,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
sizeof(pair_cache_key_t),
apr_pstrcat(pool, prefix, "REVPROP",
(char *)NULL),
+ 0,
fs,
no_handler,
fs->pool));
@@ -591,6 +606,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
APR_HASH_KEY_STRING,
apr_pstrcat(pool, prefix, "TXDELTA_WINDOW",
(char *)NULL),
+ 0,
fs,
no_handler,
fs->pool));
@@ -604,6 +620,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
APR_HASH_KEY_STRING,
apr_pstrcat(pool, prefix, "COMBINED_WINDOW",
(char *)NULL),
+ SVN_CACHE__MEMBUFFER_LOW_PRIORITY,
fs,
no_handler,
fs->pool));
@@ -707,6 +724,7 @@ svn_fs_fs__initialize_txn_caches(svn_fs_
APR_HASH_KEY_STRING,
apr_pstrcat(pool, prefix, "TXNDIR",
(char *)NULL),
+ 0,
fs,
TRUE,
pool));
Modified: subversion/trunk/subversion/libsvn_subr/cache-inprocess.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/cache-inprocess.c?rev=1505026&r1=1505025&r2=1505026&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/cache-inprocess.c (original)
+++ subversion/trunk/subversion/libsvn_subr/cache-inprocess.c Fri Jul 19 21:21:36 2013
@@ -246,6 +246,37 @@ inprocess_cache_get(void **value_p,
return SVN_NO_ERROR;
}
+static svn_error_t *
+inprocess_cache_has_key_internal(svn_boolean_t *found,
+ inprocess_cache_t *cache,
+ const void *key,
+ apr_pool_t *scratch_pool)
+{
+ *found = apr_hash_get(cache->hash, key, cache->klen) != NULL;
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+inprocess_cache_has_key(svn_boolean_t *found,
+ void *cache_void,
+ const void *key,
+ apr_pool_t *scratch_pool)
+{
+ inprocess_cache_t *cache = cache_void;
+
+ if (key)
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_has_key_internal(found,
+ cache,
+ key,
+ scratch_pool));
+ else
+ *found = FALSE;
+
+ return SVN_NO_ERROR;
+}
+
/* Removes PAGE from the LRU list, removes all of its entries from
* CACHE's hash, clears its pool, and sets its entry pointer to NULL.
* Finally, puts it in the "partial page" slot in the cache and sets
@@ -604,6 +635,7 @@ inprocess_cache_get_info(void *cache_voi
static svn_cache__vtable_t inprocess_cache_vtable = {
inprocess_cache_get,
+ inprocess_cache_has_key,
inprocess_cache_set,
inprocess_cache_iter,
inprocess_cache_is_cachable,
Modified: subversion/trunk/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/cache-membuffer.c?rev=1505026&r1=1505025&r2=1505026&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/trunk/subversion/libsvn_subr/cache-membuffer.c Fri Jul 19 21:21:36 2013
@@ -361,6 +361,10 @@ typedef struct entry_t
*/
apr_uint32_t previous;
+ /* Priority of this entry. This entry will not be replaced by lower-
+ * priority items.
+ */
+ apr_uint32_t priority;
#ifdef SVN_DEBUG_CACHE_MEMBUFFER
/* Remember type, content and key hashes.
*/
@@ -1013,13 +1017,15 @@ find_entry(svn_membuffer_t *cache,
if (group->used == GROUP_SIZE)
{
/* every entry gets the same chance of being removed.
- * Otherwise, we free the first entry, fill it and
- * remove it again on the next occasion without considering
- * the other entries in this group.
+ * Otherwise, we free the first entry, fill it and remove it
+ * again on the next occasion without considering the other
+ * entries in this group. Also, apply priorities strictly.
*/
entry = &group->entries[rand() % GROUP_SIZE];
for (i = 1; i < GROUP_SIZE; ++i)
- if (entry->hit_count > group->entries[i].hit_count)
+ if ( (entry->priority > group->entries[i].priority)
+ || ( entry->priority == group->entries[i].priority
+ && entry->hit_count > group->entries[i].hit_count))
entry = &group->entries[i];
/* for the entries that don't have been removed,
@@ -1128,6 +1134,16 @@ ensure_data_insertable_l2(svn_membuffer_
apr_uint64_t average_hit_value;
apr_uint64_t threshold;
+ /* accumulated size of the entries that have been removed to make
+ * room for the new one.
+ */
+ apr_size_t moved_size = 0;
+
+ /* count the number of entries that got moved. A single large entry
+ * being moved is not enough to reject an insertion.
+ */
+ apr_size_t moved_count = 0;
+
/* accumulated "worth" of items dropped so far */
apr_size_t drop_hits = 0;
@@ -1159,10 +1175,16 @@ ensure_data_insertable_l2(svn_membuffer_
if (end >= to_fit_in->size + cache->l2.current_data)
return TRUE;
+ /* Don't be too eager to cache data. If a lot of data has been
+ * moved around, the current item has probably a relatively low
+ * priority. So, give up after some time.
+ */
+ if (moved_size > 8 * to_fit_in->size && moved_count > 3)
+ return FALSE;
+
/* if the net worth (in hits) of items removed is already larger
* than what we want to insert, reject TO_FIT_IN because it still
- * does not fit in.
- */
+ * does not fit in. */
if (drop_hits > to_fit_in->hit_count)
return FALSE;
@@ -1180,8 +1202,15 @@ ensure_data_insertable_l2(svn_membuffer_
}
else
{
+ svn_boolean_t keep;
entry = get_entry(cache, cache->l2.next);
+ /* Reject insertion for entries with low priority, if the current
+ * entry has seen recent hits. */
+ if ( entry->hit_count
+ && to_fit_in->priority < SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY)
+ return FALSE;
+
/* Keep entries that are very small. Those are likely to be data
* headers or similar management structures. So, they are probably
* important while not occupying much space.
@@ -1190,56 +1219,75 @@ ensure_data_insertable_l2(svn_membuffer_
if ( (apr_uint64_t)entry->size * cache->used_entries
< cache->data_used / 8)
{
- move_entry(cache, entry);
+ keep = TRUE;
}
else if (cache->l2.next / GROUP_SIZE == idx / GROUP_SIZE)
{
/* Special case: we cannot drop entries that are in the same
- * group as TO_FIT_IN because that might the latter to become
- * invalidated it it happens to be the highest used entry in
- * the group. So, we must keep ENTRY unconditionally.
- * (this is a very rare condition)
- */
- move_entry(cache, entry);
+ * group as TO_FIT_IN because that might the latter to become
+ * invalidated it it happens to be the highest used entry in
+ * the group. So, we must keep ENTRY unconditionally.
+ * (this is a very rare condition)
+ */
+ keep = TRUE;
}
- else
+ else if ( entry->priority < SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY
+ && to_fit_in->priority > entry->priority)
+ {
+ /* Be quick to evict low-priority entries if the one to insert
+ * is of higher priority.
+ */
+ keep = FALSE;
+ }
+ else if (to_fit_in->priority != entry->priority)
+ {
+ /* Not the same priority but the lower prio side is not a
+ * clear loser either (already checked those cases above).
+ * Keep the current entry if it has seen more hits recently
+ * or is smaller than the one to insert - both relative to
+ * their respective priority.
+ */
+ keep = to_fit_in->hit_count * to_fit_in->priority
+ < entry->hit_count * entry->priority
+ || to_fit_in->size * to_fit_in->priority
+ < entry->size * entry->priority;
+ }
+ else if (cache->hit_count > cache->used_entries)
{
- svn_boolean_t keep;
+ /* Roll the dice and determine a threshold somewhere
+ * from 0 up to 2 times the average hit count.
+ */
+ average_hit_value = cache->hit_count / cache->used_entries;
+ threshold = (average_hit_value+1) * (rand() % 4096) / 2048;
- if (cache->hit_count > cache->used_entries)
- {
- /* Roll the dice and determine a threshold somewhere from
- * 0 up to 2 times the average hit count.
- */
- average_hit_value = cache->hit_count / cache->used_entries;
- threshold = (average_hit_value+1) * (rand() % 4096) / 2048;
+ keep = entry->hit_count > threshold;
+ }
+ else
+ {
+ /* general hit count is low. Keep everything that got hit
+ * at all and assign some 50% survival chance to everything
+ * else.
+ */
+ keep = rand() & 1;
+ }
- keep = entry->hit_count >= threshold;
- }
- else
- {
- /* general hit count is low. Keep everything that got
- * hit at all and assign some 50% survival chance to
- * everything else.
- */
- keep = (entry->hit_count > 0) || (rand() & 1);
- }
+ /* keepers or destroyers? */
+ if (keep)
+ {
+ /* Moving entries around is not for free -> track costs. */
+ moved_size += entry->size;
+ moved_count++;
- /* keepers or destroyers? */
- if (keep)
- {
- /* Keep ENTRY and move the insertion window.
- */
- move_entry(cache, entry);
- }
- else
- {
- /* Drop the entry from the end of the insertion window,
- * because it had been hit less than the threshold.
- */
- drop_hits += entry->hit_count;
- drop_entry(cache, entry);
- }
+ move_entry(cache, entry);
+ }
+ else
+ {
+ /* Drop the entry from the end of the insertion window, if it
+ * has been hit less than the threshold. Otherwise, keep it and
+ * move the insertion window one entry further.
+ */
+ drop_hits += entry->hit_count;
+ drop_entry(cache, entry);
}
}
}
@@ -1582,6 +1630,7 @@ membuffer_cache_set_internal(svn_membuff
apr_uint32_t group_index,
char *buffer,
apr_size_t size,
+ apr_uint32_t priority,
DEBUG_CACHE_MEMBUFFER_TAG_ARG
apr_pool_t *scratch_pool)
{
@@ -1594,6 +1643,7 @@ membuffer_cache_set_internal(svn_membuff
{
cache->data_used += size - entry->size;
entry->size = size;
+ entry->priority = priority;
#ifdef SVN_DEBUG_CACHE_MEMBUFFER
@@ -1624,6 +1674,7 @@ membuffer_cache_set_internal(svn_membuff
entry = find_entry(cache, group_index, to_find, TRUE);
entry->size = size;
entry->offset = cache->l1.current_data;
+ entry->priority = priority;
#ifdef SVN_DEBUG_CACHE_MEMBUFFER
@@ -1673,6 +1724,7 @@ membuffer_cache_set(svn_membuffer_t *cac
entry_key_t key,
void *item,
svn_cache__serialize_func_t serializer,
+ apr_uint32_t priority,
DEBUG_CACHE_MEMBUFFER_TAG_ARG
apr_pool_t *scratch_pool)
{
@@ -1697,6 +1749,7 @@ membuffer_cache_set(svn_membuffer_t *cac
group_index,
buffer,
size,
+ priority,
DEBUG_CACHE_MEMBUFFER_TAG
scratch_pool));
return SVN_NO_ERROR;
@@ -1808,6 +1861,43 @@ membuffer_cache_get(svn_membuffer_t *cac
}
/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
+ * by the hash value TO_FIND. If no item has been stored for KEY, *FOUND
+ * will be FALSE and TRUE otherwise.
+ */
+static svn_error_t *
+membuffer_cache_has_key_internal(svn_membuffer_t *cache,
+ apr_uint32_t group_index,
+ entry_key_t to_find,
+ svn_boolean_t *found)
+{
+ *found = find_entry(cache, group_index, to_find, FALSE) != NULL;
+
+ return SVN_NO_ERROR;
+}
+
+/* Look for an entry identified by KEY. If no item has been stored
+ * for KEY, *FOUND will be set to FALSE and TRUE otherwise.
+ */
+/* Implements svn_cache__has_key for membuffer caches.
+ */
+static svn_error_t *
+membuffer_cache_has_key(svn_membuffer_t *cache,
+ entry_key_t key,
+ svn_boolean_t *found)
+{
+ /* find the entry group that will hold the key.
+ */
+ apr_uint32_t group_index = get_group_index(&cache, key);
+ WITH_READ_LOCK(cache,
+ membuffer_cache_has_key_internal(cache,
+ group_index,
+ key,
+ found));
+
+ return SVN_NO_ERROR;
+}
+
+/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
* by the hash value TO_FIND. FOUND indicates whether that entry exists.
* If not found, *ITEM will be NULL.
*
@@ -2097,6 +2187,9 @@ typedef struct svn_membuffer_cache_t
*/
apr_ssize_t key_len;
+ /* priority class for all items written through this interface */
+ apr_uint32_t priority;
+
/* Temporary buffer containing the hash key for the current access
*/
entry_key_t combined_key;
@@ -2291,6 +2384,39 @@ svn_membuffer_cache_get(void **value_p,
/* return result */
*found = *value_p != NULL;
+
+ return SVN_NO_ERROR;
+}
+
+/* Implement svn_cache__vtable_t.has_key (not thread-safe)
+ */
+static svn_error_t *
+svn_membuffer_cache_has_key(svn_boolean_t *found,
+ void *cache_void,
+ const void *key,
+ apr_pool_t *scratch_pool)
+{
+ svn_membuffer_cache_t *cache = cache_void;
+
+ /* special case */
+ if (key == NULL)
+ {
+ *found = FALSE;
+
+ return SVN_NO_ERROR;
+ }
+
+ /* construct the full, i.e. globally unique, key by adding
+ * this cache instances' prefix
+ */
+ combine_key(cache, key, cache->key_len);
+
+ /* Look the item up. */
+ SVN_ERR(membuffer_cache_has_key(cache->membuffer,
+ cache->combined_key,
+ found));
+
+ /* return result */
return SVN_NO_ERROR;
}
@@ -2332,6 +2458,7 @@ svn_membuffer_cache_set(void *cache_void
cache->combined_key,
value,
cache->serializer,
+ cache->priority,
DEBUG_CACHE_MEMBUFFER_TAG
cache->pool);
}
@@ -2488,6 +2615,7 @@ svn_membuffer_cache_get_info(void *cache
*/
static svn_cache__vtable_t membuffer_cache_vtable = {
svn_membuffer_cache_get,
+ svn_membuffer_cache_has_key,
svn_membuffer_cache_set,
svn_membuffer_cache_iter,
svn_membuffer_cache_is_cachable,
@@ -2516,6 +2644,24 @@ svn_membuffer_cache_get_synced(void **va
return SVN_NO_ERROR;
}
+/* Implement svn_cache__vtable_t.has_key and serialize all cache access.
+ */
+static svn_error_t *
+svn_membuffer_cache_has_key_synced(svn_boolean_t *found,
+ void *cache_void,
+ const void *key,
+ apr_pool_t *result_pool)
+{
+ svn_membuffer_cache_t *cache = cache_void;
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ svn_membuffer_cache_has_key(found,
+ cache_void,
+ key,
+ result_pool));
+
+ return SVN_NO_ERROR;
+}
+
/* Implement svn_cache__vtable_t.set and serialize all cache access.
*/
static svn_error_t *
@@ -2582,6 +2728,7 @@ svn_membuffer_cache_set_partial_synced(v
*/
static svn_cache__vtable_t membuffer_cache_synced_vtable = {
svn_membuffer_cache_get_synced,
+ svn_membuffer_cache_has_key_synced,
svn_membuffer_cache_set_synced,
svn_membuffer_cache_iter, /* no sync required */
svn_membuffer_cache_is_cachable, /* no sync required */
@@ -2636,6 +2783,7 @@ svn_cache__create_membuffer_cache(svn_ca
svn_cache__deserialize_func_t deserializer,
apr_ssize_t klen,
const char *prefix,
+ apr_uint32_t priority,
svn_boolean_t thread_safe,
apr_pool_t *pool)
{
@@ -2656,6 +2804,7 @@ svn_cache__create_membuffer_cache(svn_ca
? deserializer
: deserialize_svn_stringbuf;
cache->full_prefix = apr_pstrdup(pool, prefix);
+ cache->priority = priority;
cache->key_len = klen;
cache->pool = svn_pool_create(pool);
cache->alloc_counter = 0;
Modified: subversion/trunk/subversion/libsvn_subr/cache-memcache.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/cache-memcache.c?rev=1505026&r1=1505025&r2=1505026&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/cache-memcache.c (original)
+++ subversion/trunk/subversion/libsvn_subr/cache-memcache.c Fri Jul 19 21:21:36 2013
@@ -213,6 +213,26 @@ memcache_get(void **value_p,
return SVN_NO_ERROR;
}
+/* Implement vtable.has_key in terms of the getter.
+ */
+static svn_error_t *
+memcache_has_key(svn_boolean_t *found,
+ void *cache_void,
+ const void *key,
+ apr_pool_t *scratch_pool)
+{
+ char *data;
+ apr_size_t data_len;
+ SVN_ERR(memcache_internal_get(&data,
+ &data_len,
+ found,
+ cache_void,
+ key,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
/* Core functionality of our setter functions: store LENGH bytes of DATA
* to be identified by KEY in the memcached given by CACHE_VOID. Use POOL
* for temporary allocations.
@@ -371,6 +391,7 @@ memcache_get_info(void *cache_void,
static svn_cache__vtable_t memcache_vtable = {
memcache_get,
+ memcache_has_key,
memcache_set,
memcache_iter,
memcache_is_cachable,
Modified: subversion/trunk/subversion/libsvn_subr/cache.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/cache.c?rev=1505026&r1=1505025&r2=1505026&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/cache.c (original)
+++ subversion/trunk/subversion/libsvn_subr/cache.c Fri Jul 19 21:21:36 2013
@@ -96,6 +96,21 @@ svn_cache__get(void **value_p,
}
svn_error_t *
+svn_cache__has_key(svn_boolean_t *found,
+ svn_cache__t *cache,
+ const void *key,
+ apr_pool_t *scratch_pool)
+{
+ *found = FALSE;
+ return handle_error(cache,
+ (cache->vtable->has_key)(found,
+ cache->cache_internal,
+ key,
+ scratch_pool),
+ scratch_pool);
+}
+
+svn_error_t *
svn_cache__set(svn_cache__t *cache,
const void *key,
void *value,
Modified: subversion/trunk/subversion/libsvn_subr/cache.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/cache.h?rev=1505026&r1=1505025&r2=1505026&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/cache.h (original)
+++ subversion/trunk/subversion/libsvn_subr/cache.h Fri Jul 19 21:21:36 2013
@@ -38,6 +38,12 @@ typedef struct svn_cache__vtable_t {
const void *key,
apr_pool_t *result_pool);
+ /* See svn_cache__has_key(). */
+ svn_error_t *(*has_key)(svn_boolean_t *found,
+ void *cache_implementation,
+ const void *key,
+ apr_pool_t *scratch_pool);
+
/* See svn_cache__set(). */
svn_error_t *(*set)(void *cache_implementation,
const void *key,
Modified: subversion/trunk/subversion/tests/libsvn_subr/cache-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_subr/cache-test.c?rev=1505026&r1=1505025&r2=1505026&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_subr/cache-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_subr/cache-test.c Fri Jul 19 21:21:36 2013
@@ -193,6 +193,7 @@ test_membuffer_cache_basic(apr_pool_t *p
deserialize_revnum,
APR_HASH_KEY_STRING,
"cache:",
+ SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
FALSE,
pool));
Modified: subversion/trunk/tools/server-side/fsfs-stats.c
URL: http://svn.apache.org/viewvc/subversion/trunk/tools/server-side/fsfs-stats.c?rev=1505026&r1=1505025&r2=1505026&view=diff
==============================================================================
--- subversion/trunk/tools/server-side/fsfs-stats.c (original)
+++ subversion/trunk/tools/server-side/fsfs-stats.c Fri Jul 19 21:21:36 2013
@@ -1573,7 +1573,9 @@ read_revisions(fs_fs_t **fs,
svn_cache__get_global_membuffer_cache(),
NULL, NULL,
sizeof(window_cache_key_t),
- "", FALSE, pool));
+ "",
+ SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+ FALSE, pool));
/* read all packed revs */
for ( revision = start_revision