cache.c revision 251886
1/* 2 * cache.c: cache interface for Subversion 3 * 4 * ==================================================================== 5 * Licensed to the Apache Software Foundation (ASF) under one 6 * or more contributor license agreements. See the NOTICE file 7 * distributed with this work for additional information 8 * regarding copyright ownership. The ASF licenses this file 9 * to you under the Apache License, Version 2.0 (the 10 * "License"); you may not use this file except in compliance 11 * with the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, 16 * software distributed under the License is distributed on an 17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 * KIND, either express or implied. See the License for the 19 * specific language governing permissions and limitations 20 * under the License. 21 * ==================================================================== 22 */ 23 24#include "cache.h" 25 26svn_error_t * 27svn_cache__set_error_handler(svn_cache__t *cache, 28 svn_cache__error_handler_t handler, 29 void *baton, 30 apr_pool_t *scratch_pool) 31{ 32 cache->error_handler = handler; 33 cache->error_baton = baton; 34 return SVN_NO_ERROR; 35} 36 37svn_boolean_t 38svn_cache__is_cachable(svn_cache__t *cache, 39 apr_size_t size) 40{ 41 /* having no cache means we can't cache anything */ 42 if (cache == NULL) 43 return FALSE; 44 45 return cache->vtable->is_cachable(cache->cache_internal, size); 46} 47 48/* Give the error handler callback a chance to replace or ignore the 49 error. */ 50static svn_error_t * 51handle_error(svn_cache__t *cache, 52 svn_error_t *err, 53 apr_pool_t *pool) 54{ 55 if (err) 56 { 57 cache->failures++; 58 if (cache->error_handler) 59 err = (cache->error_handler)(err, cache->error_baton, pool); 60 } 61 62 return err; 63} 64 65 66svn_error_t * 67svn_cache__get(void **value_p, 68 svn_boolean_t *found, 69 svn_cache__t *cache, 70 const void *key, 71 apr_pool_t *result_pool) 72{ 73 svn_error_t *err; 74 75 /* In case any errors happen and are quelched, make sure we start 76 out with FOUND set to false. */ 77 *found = FALSE; 78#ifdef SVN_DEBUG 79 if (getenv("SVN_X_DOES_NOT_MARK_THE_SPOT")) 80 return SVN_NO_ERROR; 81#endif 82 83 cache->reads++; 84 err = handle_error(cache, 85 (cache->vtable->get)(value_p, 86 found, 87 cache->cache_internal, 88 key, 89 result_pool), 90 result_pool); 91 92 if (*found) 93 cache->hits++; 94 95 return err; 96} 97 98svn_error_t * 99svn_cache__set(svn_cache__t *cache, 100 const void *key, 101 void *value, 102 apr_pool_t *scratch_pool) 103{ 104 cache->writes++; 105 return handle_error(cache, 106 (cache->vtable->set)(cache->cache_internal, 107 key, 108 value, 109 scratch_pool), 110 scratch_pool); 111} 112 113 114svn_error_t * 115svn_cache__iter(svn_boolean_t *completed, 116 svn_cache__t *cache, 117 svn_iter_apr_hash_cb_t user_cb, 118 void *user_baton, 119 apr_pool_t *scratch_pool) 120{ 121#ifdef SVN_DEBUG 122 if (getenv("SVN_X_DOES_NOT_MARK_THE_SPOT")) 123 /* Pretend CACHE is empty. */ 124 return SVN_NO_ERROR; 125#endif 126 127 return (cache->vtable->iter)(completed, 128 cache->cache_internal, 129 user_cb, 130 user_baton, 131 scratch_pool); 132} 133 134svn_error_t * 135svn_cache__get_partial(void **value, 136 svn_boolean_t *found, 137 svn_cache__t *cache, 138 const void *key, 139 svn_cache__partial_getter_func_t func, 140 void *baton, 141 apr_pool_t *result_pool) 142{ 143 svn_error_t *err; 144 145 /* In case any errors happen and are quelched, make sure we start 146 out with FOUND set to false. */ 147 *found = FALSE; 148#ifdef SVN_DEBUG 149 if (getenv("SVN_X_DOES_NOT_MARK_THE_SPOT")) 150 return SVN_NO_ERROR; 151#endif 152 153 cache->reads++; 154 err = handle_error(cache, 155 (cache->vtable->get_partial)(value, 156 found, 157 cache->cache_internal, 158 key, 159 func, 160 baton, 161 result_pool), 162 result_pool); 163 164 if (*found) 165 cache->hits++; 166 167 return err; 168} 169 170svn_error_t * 171svn_cache__set_partial(svn_cache__t *cache, 172 const void *key, 173 svn_cache__partial_setter_func_t func, 174 void *baton, 175 apr_pool_t *scratch_pool) 176{ 177 cache->writes++; 178 return handle_error(cache, 179 (cache->vtable->set_partial)(cache->cache_internal, 180 key, 181 func, 182 baton, 183 scratch_pool), 184 scratch_pool); 185} 186 187svn_error_t * 188svn_cache__get_info(svn_cache__t *cache, 189 svn_cache__info_t *info, 190 svn_boolean_t reset, 191 apr_pool_t *result_pool) 192{ 193 /* write general statistics */ 194 195 info->gets = cache->reads; 196 info->hits = cache->hits; 197 info->sets = cache->writes; 198 info->failures = cache->failures; 199 200 /* Call the cache implementation for filling the blanks. 201 * It might also replace some of the general stats but 202 * this is currently not done. 203 */ 204 SVN_ERR((cache->vtable->get_info)(cache->cache_internal, 205 info, 206 reset, 207 result_pool)); 208 209 /* reset statistics */ 210 211 if (reset) 212 { 213 cache->reads = 0; 214 cache->hits = 0; 215 cache->writes = 0; 216 cache->failures = 0; 217 } 218 219 return SVN_NO_ERROR; 220} 221 222svn_string_t * 223svn_cache__format_info(const svn_cache__info_t *info, 224 apr_pool_t *result_pool) 225{ 226 enum { _1MB = 1024 * 1024 }; 227 228 apr_uint64_t misses = info->gets - info->hits; 229 double hit_rate = (100.0 * (double)info->hits) 230 / (double)(info->gets ? info->gets : 1); 231 double write_rate = (100.0 * (double)info->sets) 232 / (double)(misses ? misses : 1); 233 double data_usage_rate = (100.0 * (double)info->used_size) 234 / (double)(info->data_size ? info->data_size : 1); 235 double data_entry_rate = (100.0 * (double)info->used_entries) 236 / (double)(info->total_entries ? info->total_entries : 1); 237 238 return svn_string_createf(result_pool, 239 240 "prefix : %s\n" 241 "gets : %" APR_UINT64_T_FMT 242 ", %" APR_UINT64_T_FMT " hits (%5.2f%%)\n" 243 "sets : %" APR_UINT64_T_FMT 244 " (%5.2f%% of misses)\n" 245 "failures: %" APR_UINT64_T_FMT "\n" 246 "used : %" APR_UINT64_T_FMT " MB (%5.2f%%)" 247 " of %" APR_UINT64_T_FMT " MB data cache" 248 " / %" APR_UINT64_T_FMT " MB total cache memory\n" 249 " %" APR_UINT64_T_FMT " entries (%5.2f%%)" 250 " of %" APR_UINT64_T_FMT " total\n", 251 252 info->id, 253 254 info->gets, 255 info->hits, hit_rate, 256 info->sets, write_rate, 257 info->failures, 258 259 info->used_size / _1MB, data_usage_rate, 260 info->data_size / _1MB, 261 info->total_size / _1MB, 262 263 info->used_entries, data_entry_rate, 264 info->total_entries); 265} 266