summaryrefslogtreecommitdiffstats
path: root/subversion/libsvn_subr/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_subr/cache.c')
-rw-r--r--subversion/libsvn_subr/cache.c265
1 files changed, 265 insertions, 0 deletions
diff --git a/subversion/libsvn_subr/cache.c b/subversion/libsvn_subr/cache.c
new file mode 100644
index 0000000..70e189f
--- /dev/null
+++ b/subversion/libsvn_subr/cache.c
@@ -0,0 +1,265 @@
+/*
+ * cache.c: cache interface for Subversion
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#include "cache.h"
+
+svn_error_t *
+svn_cache__set_error_handler(svn_cache__t *cache,
+ svn_cache__error_handler_t handler,
+ void *baton,
+ apr_pool_t *scratch_pool)
+{
+ cache->error_handler = handler;
+ cache->error_baton = baton;
+ return SVN_NO_ERROR;
+}
+
+svn_boolean_t
+svn_cache__is_cachable(svn_cache__t *cache,
+ apr_size_t size)
+{
+ /* having no cache means we can't cache anything */
+ if (cache == NULL)
+ return FALSE;
+
+ return cache->vtable->is_cachable(cache->cache_internal, size);
+}
+
+/* Give the error handler callback a chance to replace or ignore the
+ error. */
+static svn_error_t *
+handle_error(svn_cache__t *cache,
+ svn_error_t *err,
+ apr_pool_t *pool)
+{
+ if (err)
+ {
+ cache->failures++;
+ if (cache->error_handler)
+ err = (cache->error_handler)(err, cache->error_baton, pool);
+ }
+
+ return err;
+}
+
+
+svn_error_t *
+svn_cache__get(void **value_p,
+ svn_boolean_t *found,
+ svn_cache__t *cache,
+ const void *key,
+ apr_pool_t *result_pool)
+{
+ svn_error_t *err;
+
+ /* In case any errors happen and are quelched, make sure we start
+ out with FOUND set to false. */
+ *found = FALSE;
+#ifdef SVN_DEBUG
+ if (getenv("SVN_X_DOES_NOT_MARK_THE_SPOT"))
+ return SVN_NO_ERROR;
+#endif
+
+ cache->reads++;
+ err = handle_error(cache,
+ (cache->vtable->get)(value_p,
+ found,
+ cache->cache_internal,
+ key,
+ result_pool),
+ result_pool);
+
+ if (*found)
+ cache->hits++;
+
+ return err;
+}
+
+svn_error_t *
+svn_cache__set(svn_cache__t *cache,
+ const void *key,
+ void *value,
+ apr_pool_t *scratch_pool)
+{
+ cache->writes++;
+ return handle_error(cache,
+ (cache->vtable->set)(cache->cache_internal,
+ key,
+ value,
+ scratch_pool),
+ scratch_pool);
+}
+
+
+svn_error_t *
+svn_cache__iter(svn_boolean_t *completed,
+ svn_cache__t *cache,
+ svn_iter_apr_hash_cb_t user_cb,
+ void *user_baton,
+ apr_pool_t *scratch_pool)
+{
+#ifdef SVN_DEBUG
+ if (getenv("SVN_X_DOES_NOT_MARK_THE_SPOT"))
+ /* Pretend CACHE is empty. */
+ return SVN_NO_ERROR;
+#endif
+
+ return (cache->vtable->iter)(completed,
+ cache->cache_internal,
+ user_cb,
+ user_baton,
+ scratch_pool);
+}
+
+svn_error_t *
+svn_cache__get_partial(void **value,
+ svn_boolean_t *found,
+ svn_cache__t *cache,
+ const void *key,
+ svn_cache__partial_getter_func_t func,
+ void *baton,
+ apr_pool_t *result_pool)
+{
+ svn_error_t *err;
+
+ /* In case any errors happen and are quelched, make sure we start
+ out with FOUND set to false. */
+ *found = FALSE;
+#ifdef SVN_DEBUG
+ if (getenv("SVN_X_DOES_NOT_MARK_THE_SPOT"))
+ return SVN_NO_ERROR;
+#endif
+
+ cache->reads++;
+ err = handle_error(cache,
+ (cache->vtable->get_partial)(value,
+ found,
+ cache->cache_internal,
+ key,
+ func,
+ baton,
+ result_pool),
+ result_pool);
+
+ if (*found)
+ cache->hits++;
+
+ return err;
+}
+
+svn_error_t *
+svn_cache__set_partial(svn_cache__t *cache,
+ const void *key,
+ svn_cache__partial_setter_func_t func,
+ void *baton,
+ apr_pool_t *scratch_pool)
+{
+ cache->writes++;
+ return handle_error(cache,
+ (cache->vtable->set_partial)(cache->cache_internal,
+ key,
+ func,
+ baton,
+ scratch_pool),
+ scratch_pool);
+}
+
+svn_error_t *
+svn_cache__get_info(svn_cache__t *cache,
+ svn_cache__info_t *info,
+ svn_boolean_t reset,
+ apr_pool_t *result_pool)
+{
+ /* write general statistics */
+
+ info->gets = cache->reads;
+ info->hits = cache->hits;
+ info->sets = cache->writes;
+ info->failures = cache->failures;
+
+ /* Call the cache implementation for filling the blanks.
+ * It might also replace some of the general stats but
+ * this is currently not done.
+ */
+ SVN_ERR((cache->vtable->get_info)(cache->cache_internal,
+ info,
+ reset,
+ result_pool));
+
+ /* reset statistics */
+
+ if (reset)
+ {
+ cache->reads = 0;
+ cache->hits = 0;
+ cache->writes = 0;
+ cache->failures = 0;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_string_t *
+svn_cache__format_info(const svn_cache__info_t *info,
+ apr_pool_t *result_pool)
+{
+ enum { _1MB = 1024 * 1024 };
+
+ apr_uint64_t misses = info->gets - info->hits;
+ double hit_rate = (100.0 * (double)info->hits)
+ / (double)(info->gets ? info->gets : 1);
+ double write_rate = (100.0 * (double)info->sets)
+ / (double)(misses ? misses : 1);
+ double data_usage_rate = (100.0 * (double)info->used_size)
+ / (double)(info->data_size ? info->data_size : 1);
+ double data_entry_rate = (100.0 * (double)info->used_entries)
+ / (double)(info->total_entries ? info->total_entries : 1);
+
+ return svn_string_createf(result_pool,
+
+ "prefix : %s\n"
+ "gets : %" APR_UINT64_T_FMT
+ ", %" APR_UINT64_T_FMT " hits (%5.2f%%)\n"
+ "sets : %" APR_UINT64_T_FMT
+ " (%5.2f%% of misses)\n"
+ "failures: %" APR_UINT64_T_FMT "\n"
+ "used : %" APR_UINT64_T_FMT " MB (%5.2f%%)"
+ " of %" APR_UINT64_T_FMT " MB data cache"
+ " / %" APR_UINT64_T_FMT " MB total cache memory\n"
+ " %" APR_UINT64_T_FMT " entries (%5.2f%%)"
+ " of %" APR_UINT64_T_FMT " total\n",
+
+ info->id,
+
+ info->gets,
+ info->hits, hit_rate,
+ info->sets, write_rate,
+ info->failures,
+
+ info->used_size / _1MB, data_usage_rate,
+ info->data_size / _1MB,
+ info->total_size / _1MB,
+
+ info->used_entries, data_entry_rate,
+ info->total_entries);
+}
OpenPOWER on IntegriCloud