]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/subversion/subversion/libsvn_subr/cache.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / subversion / subversion / libsvn_subr / cache.c
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
26 svn_error_t *
27 svn_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
37 svn_boolean_t
38 svn_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. */
50 static svn_error_t *
51 handle_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
66 svn_error_t *
67 svn_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
98 svn_error_t *
99 svn_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
114 svn_error_t *
115 svn_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
134 svn_error_t *
135 svn_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
170 svn_error_t *
171 svn_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
187 svn_error_t *
188 svn_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
222 svn_string_t *
223 svn_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 }