summaryrefslogtreecommitdiff
path: root/subversion/libsvn_subr/cache-inprocess.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_subr/cache-inprocess.c')
-rw-r--r--subversion/libsvn_subr/cache-inprocess.c288
1 files changed, 156 insertions, 132 deletions
diff --git a/subversion/libsvn_subr/cache-inprocess.c b/subversion/libsvn_subr/cache-inprocess.c
index 8cefe3e..6401f9f 100644
--- a/subversion/libsvn_subr/cache-inprocess.c
+++ b/subversion/libsvn_subr/cache-inprocess.c
@@ -30,6 +30,7 @@
#include "svn_private_config.h"
#include "cache.h"
+#include "private/svn_mutex.h"
/* The (internal) cache object. */
typedef struct inprocess_cache_t {
@@ -80,12 +81,10 @@ typedef struct inprocess_cache_t {
*/
apr_size_t data_size;
-#if APR_HAS_THREADS
/* A lock for intra-process synchronization to the cache, or NULL if
* the cache's creator doesn't feel the cache needs to be
* thread-safe. */
- apr_thread_mutex_t *mutex;
-#endif
+ svn_mutex__t *mutex;
} inprocess_cache_t;
/* A cache page; all items on the page are allocated from the same
@@ -182,39 +181,28 @@ duplicate_key(inprocess_cache_t *cache,
return apr_pmemdup(pool, key, cache->klen);
}
-/* If applicable, locks CACHE's mutex. */
static svn_error_t *
-lock_cache(inprocess_cache_t *cache)
+inprocess_cache_get_internal(char **buffer,
+ apr_size_t *size,
+ inprocess_cache_t *cache,
+ const void *key,
+ apr_pool_t *result_pool)
{
-#if APR_HAS_THREADS
- apr_status_t status;
- if (! cache->mutex)
- return SVN_NO_ERROR;
-
- status = apr_thread_mutex_lock(cache->mutex);
- if (status)
- return svn_error_wrap_apr(status, _("Can't lock cache mutex"));
-#endif
+ struct cache_entry *entry = apr_hash_get(cache->hash, key, cache->klen);
- return SVN_NO_ERROR;
-}
+ *buffer = NULL;
+ if (entry)
+ {
+ SVN_ERR(move_page_to_front(cache, entry->page));
-/* If applicable, unlocks CACHE's mutex, then returns ERR. */
-static svn_error_t *
-unlock_cache(inprocess_cache_t *cache,
- svn_error_t *err)
-{
-#if APR_HAS_THREADS
- apr_status_t status;
- if (! cache->mutex)
- return err;
+ /* duplicate the buffer entry */
+ *buffer = apr_palloc(result_pool, entry->size);
+ memcpy(*buffer, entry->value, entry->size);
- status = apr_thread_mutex_unlock(cache->mutex);
- if (status && !err)
- return svn_error_wrap_apr(status, _("Can't unlock cache mutex"));
-#endif
+ *size = entry->size;
+ }
- return err;
+ return SVN_NO_ERROR;
}
static svn_error_t *
@@ -225,38 +213,25 @@ inprocess_cache_get(void **value_p,
apr_pool_t *result_pool)
{
inprocess_cache_t *cache = cache_void;
- svn_error_t *err = NULL;
- struct cache_entry *entry;
- char* buffer;
-
- SVN_ERR(lock_cache(cache));
-
- entry = apr_hash_get(cache->hash, key, cache->klen);
- if (! entry)
- {
- *found = FALSE;
- return unlock_cache(cache, SVN_NO_ERROR);
- }
-
- SVN_ERR(move_page_to_front(cache, entry->page));
-
- /* duplicate the buffer entry */
- buffer = apr_palloc(result_pool, entry->size);
- memcpy(buffer, entry->value, entry->size);
+ char* buffer = NULL;
+ apr_size_t size;
- /* the cache is no longer being accessed */
- SVN_ERR(unlock_cache(cache, SVN_NO_ERROR));
+ if (key)
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_get_internal(&buffer,
+ &size,
+ cache,
+ key,
+ result_pool));
/* deserialize the buffer content. Usually, this will directly
modify the buffer content directly.
*/
- *found = TRUE;
- if (entry->value)
- err = cache->deserialize_func(value_p, buffer, entry->size, result_pool);
- else
- *value_p = NULL;
-
- return err;
+ *value_p = NULL;
+ *found = buffer != NULL;
+ return buffer && size
+ ? cache->deserialize_func(value_p, buffer, size, result_pool)
+ : SVN_NO_ERROR;
}
/* Removes PAGE from the LRU list, removes all of its entries from
@@ -292,16 +267,12 @@ erase_page(inprocess_cache_t *cache,
static svn_error_t *
-inprocess_cache_set(void *cache_void,
- const void *key,
- void *value,
- apr_pool_t *scratch_pool)
+inprocess_cache_set_internal(inprocess_cache_t *cache,
+ const void *key,
+ void *value,
+ apr_pool_t *scratch_pool)
{
- inprocess_cache_t *cache = cache_void;
struct cache_entry *existing_entry;
- svn_error_t *err = SVN_NO_ERROR;
-
- SVN_ERR(lock_cache(cache));
existing_entry = apr_hash_get(cache->hash, key, cache->klen);
@@ -333,11 +304,13 @@ inprocess_cache_set(void *cache_void,
cache->data_size -= existing_entry->size;
if (value)
{
- err = cache->serialize_func((char **)&existing_entry->value,
- &existing_entry->size,
- value,
- page->page_pool);
+ SVN_ERR(cache->serialize_func(&existing_entry->value,
+ &existing_entry->size,
+ value,
+ page->page_pool));
cache->data_size += existing_entry->size;
+ if (existing_entry->size == 0)
+ existing_entry->value = NULL;
}
else
{
@@ -345,7 +318,7 @@ inprocess_cache_set(void *cache_void,
existing_entry->size = 0;
}
- goto cleanup;
+ return SVN_NO_ERROR;
}
/* Do we not have a partial page to put it on, but we are allowed to
@@ -383,11 +356,13 @@ inprocess_cache_set(void *cache_void,
new_entry->key = duplicate_key(cache, key, page->page_pool);
if (value)
{
- err = cache->serialize_func((char **)&new_entry->value,
- &new_entry->size,
- value,
- page->page_pool);
+ SVN_ERR(cache->serialize_func(&new_entry->value,
+ &new_entry->size,
+ value,
+ page->page_pool));
cache->data_size += new_entry->size;
+ if (new_entry->size == 0)
+ new_entry->value = NULL;
}
else
{
@@ -395,9 +370,6 @@ inprocess_cache_set(void *cache_void,
new_entry->size = 0;
}
- if (err)
- goto cleanup;
-
/* Add the entry to the page's list. */
new_entry->page = page;
new_entry->next_entry = page->first_entry;
@@ -418,8 +390,25 @@ inprocess_cache_set(void *cache_void,
}
}
- cleanup:
- return unlock_cache(cache, err);
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+inprocess_cache_set(void *cache_void,
+ const void *key,
+ void *value,
+ apr_pool_t *scratch_pool)
+{
+ inprocess_cache_t *cache = cache_void;
+
+ if (key)
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_set_internal(cache,
+ key,
+ value,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
}
/* Baton type for svn_cache__iter. */
@@ -455,10 +444,33 @@ inprocess_cache_iter(svn_boolean_t *completed,
b.user_cb = user_cb;
b.user_baton = user_baton;
- SVN_ERR(lock_cache(cache));
- return unlock_cache(cache,
- svn_iter_apr_hash(completed, cache->hash, iter_cb, &b,
- scratch_pool));
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ svn_iter_apr_hash(completed, cache->hash,
+ iter_cb, &b, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+inprocess_cache_get_partial_internal(void **value_p,
+ svn_boolean_t *found,
+ inprocess_cache_t *cache,
+ const void *key,
+ svn_cache__partial_getter_func_t func,
+ void *baton,
+ apr_pool_t *result_pool)
+{
+ struct cache_entry *entry = apr_hash_get(cache->hash, key, cache->klen);
+ if (! entry)
+ {
+ *found = FALSE;
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(move_page_to_front(cache, entry->page));
+
+ *found = TRUE;
+ return func(value_p, entry->value, entry->size, baton, result_pool);
}
static svn_error_t *
@@ -471,23 +483,43 @@ inprocess_cache_get_partial(void **value_p,
apr_pool_t *result_pool)
{
inprocess_cache_t *cache = cache_void;
- struct cache_entry *entry;
- SVN_ERR(lock_cache(cache));
+ if (key)
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_get_partial_internal(value_p,
+ found,
+ cache,
+ key,
+ func,
+ baton,
+ result_pool));
+ else
+ *found = FALSE;
- entry = apr_hash_get(cache->hash, key, cache->klen);
- if (! entry)
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+inprocess_cache_set_partial_internal(inprocess_cache_t *cache,
+ const void *key,
+ svn_cache__partial_setter_func_t func,
+ void *baton,
+ apr_pool_t *scratch_pool)
+{
+ struct cache_entry *entry = apr_hash_get(cache->hash, key, cache->klen);
+ if (entry)
{
- *found = FALSE;
- return unlock_cache(cache, SVN_NO_ERROR);
+ SVN_ERR(move_page_to_front(cache, entry->page));
+
+ cache->data_size -= entry->size;
+ SVN_ERR(func(&entry->value,
+ &entry->size,
+ baton,
+ entry->page->page_pool));
+ cache->data_size += entry->size;
}
- SVN_ERR(move_page_to_front(cache, entry->page));
-
- *found = TRUE;
- return unlock_cache(cache,
- func(value_p, entry->value, entry->size, baton,
- result_pool));
+ return SVN_NO_ERROR;
}
static svn_error_t *
@@ -498,25 +530,16 @@ inprocess_cache_set_partial(void *cache_void,
apr_pool_t *scratch_pool)
{
inprocess_cache_t *cache = cache_void;
- struct cache_entry *entry;
- svn_error_t *err = SVN_NO_ERROR;
-
- SVN_ERR(lock_cache(cache));
- entry = apr_hash_get(cache->hash, key, cache->klen);
- if (! entry)
- return unlock_cache(cache, err);
-
- SVN_ERR(move_page_to_front(cache, entry->page));
+ if (key)
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_set_partial_internal(cache,
+ key,
+ func,
+ baton,
+ scratch_pool));
- cache->data_size -= entry->size;
- err = func((char **)&entry->value,
- &entry->size,
- baton,
- entry->page->page_pool);
- cache->data_size += entry->size;
-
- return unlock_cache(cache, err);
+ return SVN_NO_ERROR;
}
static svn_boolean_t
@@ -532,15 +555,10 @@ inprocess_cache_is_cachable(void *cache_void, apr_size_t size)
}
static svn_error_t *
-inprocess_cache_get_info(void *cache_void,
- svn_cache__info_t *info,
- svn_boolean_t reset,
- apr_pool_t *result_pool)
+inprocess_cache_get_info_internal(inprocess_cache_t *cache,
+ svn_cache__info_t *info,
+ apr_pool_t *result_pool)
{
- inprocess_cache_t *cache = cache_void;
-
- SVN_ERR(lock_cache(cache));
-
info->id = apr_pstrdup(result_pool, cache->id);
info->used_entries = apr_hash_count(cache->hash);
@@ -552,10 +570,26 @@ inprocess_cache_get_info(void *cache_void,
+ cache->items_per_page * sizeof(struct cache_page)
+ info->used_entries * sizeof(struct cache_entry);
- return unlock_cache(cache, SVN_NO_ERROR);
+ return SVN_NO_ERROR;
}
+static svn_error_t *
+inprocess_cache_get_info(void *cache_void,
+ svn_cache__info_t *info,
+ svn_boolean_t reset,
+ apr_pool_t *result_pool)
+{
+ inprocess_cache_t *cache = cache_void;
+
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_get_info_internal(cache,
+ info,
+ result_pool));
+
+ return SVN_NO_ERROR;
+}
+
static svn_cache__vtable_t inprocess_cache_vtable = {
inprocess_cache_get,
inprocess_cache_set,
@@ -602,17 +636,7 @@ svn_cache__create_inprocess(svn_cache__t **cache_p,
/* The sentinel doesn't need a pool. (We're happy to crash if we
* accidentally try to treat it like a real page.) */
-#if APR_HAS_THREADS
- if (thread_safe)
- {
- apr_status_t status = apr_thread_mutex_create(&(cache->mutex),
- APR_THREAD_MUTEX_DEFAULT,
- pool);
- if (status)
- return svn_error_wrap_apr(status,
- _("Can't create cache mutex"));
- }
-#endif
+ SVN_ERR(svn_mutex__init(&cache->mutex, thread_safe, pool));
cache->cache_pool = pool;