aboutsummaryrefslogtreecommitdiff
path: root/src/datacache/datacache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/datacache/datacache.c')
-rw-r--r--src/datacache/datacache.c338
1 files changed, 168 insertions, 170 deletions
diff --git a/src/datacache/datacache.c b/src/datacache/datacache.c
index 57e0b0bb7..52c755a49 100644
--- a/src/datacache/datacache.c
+++ b/src/datacache/datacache.c
@@ -11,12 +11,12 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 17
18 SPDX-License-Identifier: AGPL3.0-or-later 18 SPDX-License-Identifier: AGPL3.0-or-later
19*/ 19 */
20/** 20/**
21 * @file datacache/datacache.c 21 * @file datacache/datacache.c
22 * @brief datacache API implementation 22 * @brief datacache API implementation
@@ -29,17 +29,15 @@
29#include "gnunet_datacache_plugin.h" 29#include "gnunet_datacache_plugin.h"
30 30
31 31
32#define LOG(kind, ...) GNUNET_log_from (kind, "datacache", __VA_ARGS__) 32#define LOG(kind, ...) GNUNET_log_from(kind, "datacache", __VA_ARGS__)
33 33
34#define LOG_STRERROR_FILE(kind, op, fn) \ 34#define LOG_STRERROR_FILE(kind, op, fn) \
35 GNUNET_log_from_strerror_file (kind, "datacache", op, fn) 35 GNUNET_log_from_strerror_file(kind, "datacache", op, fn)
36 36
37/** 37/**
38 * Internal state of the datacache library. 38 * Internal state of the datacache library.
39 */ 39 */
40struct GNUNET_DATACACHE_Handle 40struct GNUNET_DATACACHE_Handle {
41{
42
43 /** 41 /**
44 * Bloomfilter to quickly tell if we don't have the content. 42 * Bloomfilter to quickly tell if we don't have the content.
45 */ 43 */
@@ -102,24 +100,24 @@ struct GNUNET_DATACACHE_Handle
102 * @param size number of bytes that were made available 100 * @param size number of bytes that were made available
103 */ 101 */
104static void 102static void
105env_delete_notify (void *cls, const struct GNUNET_HashCode *key, size_t size) 103env_delete_notify(void *cls, const struct GNUNET_HashCode *key, size_t size)
106{ 104{
107 struct GNUNET_DATACACHE_Handle *h = cls; 105 struct GNUNET_DATACACHE_Handle *h = cls;
108 106
109 LOG (GNUNET_ERROR_TYPE_DEBUG, 107 LOG(GNUNET_ERROR_TYPE_DEBUG,
110 "Content under key `%s' discarded\n", 108 "Content under key `%s' discarded\n",
111 GNUNET_h2s (key)); 109 GNUNET_h2s(key));
112 GNUNET_assert (h->utilization >= size); 110 GNUNET_assert(h->utilization >= size);
113 h->utilization -= size; 111 h->utilization -= size;
114 GNUNET_CONTAINER_bloomfilter_remove (h->filter, key); 112 GNUNET_CONTAINER_bloomfilter_remove(h->filter, key);
115 GNUNET_STATISTICS_update (h->stats, 113 GNUNET_STATISTICS_update(h->stats,
116 gettext_noop ("# bytes stored"), 114 gettext_noop("# bytes stored"),
117 -(long long) size, 115 -(long long)size,
118 GNUNET_NO); 116 GNUNET_NO);
119 GNUNET_STATISTICS_update (h->stats, 117 GNUNET_STATISTICS_update(h->stats,
120 gettext_noop ("# items stored"), 118 gettext_noop("# items stored"),
121 -1, 119 -1,
122 GNUNET_NO); 120 GNUNET_NO);
123} 121}
124 122
125 123
@@ -131,8 +129,8 @@ env_delete_notify (void *cls, const struct GNUNET_HashCode *key, size_t size)
131 * @return handle to use to access the service 129 * @return handle to use to access the service
132 */ 130 */
133struct GNUNET_DATACACHE_Handle * 131struct GNUNET_DATACACHE_Handle *
134GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg, 132GNUNET_DATACACHE_create(const struct GNUNET_CONFIGURATION_Handle *cfg,
135 const char *section) 133 const char *section)
136{ 134{
137 unsigned int bf_size; 135 unsigned int bf_size;
138 unsigned long long quota; 136 unsigned long long quota;
@@ -141,65 +139,65 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
141 char *name; 139 char *name;
142 140
143 if (GNUNET_OK != 141 if (GNUNET_OK !=
144 GNUNET_CONFIGURATION_get_value_size (cfg, section, "QUOTA", &quota)) 142 GNUNET_CONFIGURATION_get_value_size(cfg, section, "QUOTA", &quota))
145 { 143 {
146 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, "QUOTA"); 144 GNUNET_log_config_missing(GNUNET_ERROR_TYPE_ERROR, section, "QUOTA");
147 return NULL; 145 return NULL;
148 } 146 }
149 if (GNUNET_OK != 147 if (GNUNET_OK !=
150 GNUNET_CONFIGURATION_get_value_string (cfg, section, "DATABASE", &name)) 148 GNUNET_CONFIGURATION_get_value_string(cfg, section, "DATABASE", &name))
151 { 149 {
152 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, "DATABASE"); 150 GNUNET_log_config_missing(GNUNET_ERROR_TYPE_ERROR, section, "DATABASE");
153 return NULL; 151 return NULL;
154 } 152 }
155 bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */ 153 bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */
156 154
157 ret = GNUNET_new (struct GNUNET_DATACACHE_Handle); 155 ret = GNUNET_new(struct GNUNET_DATACACHE_Handle);
158 156
159 if (GNUNET_YES != 157 if (GNUNET_YES !=
160 GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "DISABLE_BF")) 158 GNUNET_CONFIGURATION_get_value_yesno(cfg, section, "DISABLE_BF"))
161 {
162 if (GNUNET_YES !=
163 GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "DISABLE_BF_RC"))
164 {
165 ret->bloom_name = GNUNET_DISK_mktemp ("gnunet-datacachebloom");
166 }
167 if (NULL != ret->bloom_name)
168 { 159 {
169 ret->filter = GNUNET_CONTAINER_bloomfilter_load ( 160 if (GNUNET_YES !=
170 ret->bloom_name, 161 GNUNET_CONFIGURATION_get_value_yesno(cfg, section, "DISABLE_BF_RC"))
171 quota / 1024, /* 8 bit per entry in DB, expect 1k entries */ 162 {
172 5); 163 ret->bloom_name = GNUNET_DISK_mktemp("gnunet-datacachebloom");
164 }
165 if (NULL != ret->bloom_name)
166 {
167 ret->filter = GNUNET_CONTAINER_bloomfilter_load(
168 ret->bloom_name,
169 quota / 1024, /* 8 bit per entry in DB, expect 1k entries */
170 5);
171 }
172 if (NULL == ret->filter)
173 {
174 ret->filter =
175 GNUNET_CONTAINER_bloomfilter_init(NULL,
176 bf_size,
177 5); /* approx. 3% false positives at max use */
178 }
173 } 179 }
174 if (NULL == ret->filter) 180 ret->stats = GNUNET_STATISTICS_create("datacache", cfg);
175 { 181 ret->section = GNUNET_strdup(section);
176 ret->filter =
177 GNUNET_CONTAINER_bloomfilter_init (NULL,
178 bf_size,
179 5); /* approx. 3% false positives at max use */
180 }
181 }
182 ret->stats = GNUNET_STATISTICS_create ("datacache", cfg);
183 ret->section = GNUNET_strdup (section);
184 ret->env.cfg = cfg; 182 ret->env.cfg = cfg;
185 ret->env.delete_notify = &env_delete_notify; 183 ret->env.delete_notify = &env_delete_notify;
186 ret->env.section = ret->section; 184 ret->env.section = ret->section;
187 ret->env.cls = ret; 185 ret->env.cls = ret;
188 ret->env.delete_notify = &env_delete_notify; 186 ret->env.delete_notify = &env_delete_notify;
189 ret->env.quota = quota; 187 ret->env.quota = quota;
190 LOG (GNUNET_ERROR_TYPE_INFO, _ ("Loading `%s' datacache plugin\n"), name); 188 LOG(GNUNET_ERROR_TYPE_INFO, _("Loading `%s' datacache plugin\n"), name);
191 GNUNET_asprintf (&libname, "libgnunet_plugin_datacache_%s", name); 189 GNUNET_asprintf(&libname, "libgnunet_plugin_datacache_%s", name);
192 ret->short_name = name; 190 ret->short_name = name;
193 ret->lib_name = libname; 191 ret->lib_name = libname;
194 ret->api = GNUNET_PLUGIN_load (libname, &ret->env); 192 ret->api = GNUNET_PLUGIN_load(libname, &ret->env);
195 if (ret->api == NULL) 193 if (ret->api == NULL)
196 { 194 {
197 LOG (GNUNET_ERROR_TYPE_ERROR, 195 LOG(GNUNET_ERROR_TYPE_ERROR,
198 _ ("Failed to load datacache plugin for `%s'\n"), 196 _("Failed to load datacache plugin for `%s'\n"),
199 name); 197 name);
200 GNUNET_DATACACHE_destroy (ret); 198 GNUNET_DATACACHE_destroy(ret);
201 return NULL; 199 return NULL;
202 } 200 }
203 return ret; 201 return ret;
204} 202}
205 203
@@ -210,26 +208,26 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
210 * @param h handle to the datastore 208 * @param h handle to the datastore
211 */ 209 */
212void 210void
213GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h) 211GNUNET_DATACACHE_destroy(struct GNUNET_DATACACHE_Handle *h)
214{ 212{
215 if (NULL != h->filter) 213 if (NULL != h->filter)
216 GNUNET_CONTAINER_bloomfilter_free (h->filter); 214 GNUNET_CONTAINER_bloomfilter_free(h->filter);
217 if (NULL != h->api) 215 if (NULL != h->api)
218 GNUNET_break (NULL == GNUNET_PLUGIN_unload (h->lib_name, h->api)); 216 GNUNET_break(NULL == GNUNET_PLUGIN_unload(h->lib_name, h->api));
219 GNUNET_free (h->lib_name); 217 GNUNET_free(h->lib_name);
220 GNUNET_free (h->short_name); 218 GNUNET_free(h->short_name);
221 GNUNET_free (h->section); 219 GNUNET_free(h->section);
222 if (NULL != h->bloom_name) 220 if (NULL != h->bloom_name)
223 { 221 {
224 if (0 != unlink (h->bloom_name)) 222 if (0 != unlink(h->bloom_name))
225 GNUNET_log_from_strerror_file (GNUNET_ERROR_TYPE_WARNING, 223 GNUNET_log_from_strerror_file(GNUNET_ERROR_TYPE_WARNING,
226 "datacache", 224 "datacache",
227 "unlink", 225 "unlink",
228 h->bloom_name); 226 h->bloom_name);
229 GNUNET_free (h->bloom_name); 227 GNUNET_free(h->bloom_name);
230 } 228 }
231 GNUNET_STATISTICS_destroy (h->stats, GNUNET_NO); 229 GNUNET_STATISTICS_destroy(h->stats, GNUNET_NO);
232 GNUNET_free (h); 230 GNUNET_free(h);
233} 231}
234 232
235 233
@@ -248,52 +246,52 @@ GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h)
248 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error, #GNUNET_NO if duplicate 246 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error, #GNUNET_NO if duplicate
249 */ 247 */
250int 248int
251GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h, 249GNUNET_DATACACHE_put(struct GNUNET_DATACACHE_Handle *h,
252 const struct GNUNET_HashCode *key, 250 const struct GNUNET_HashCode *key,
253 uint32_t xor_distance, 251 uint32_t xor_distance,
254 size_t data_size, 252 size_t data_size,
255 const char *data, 253 const char *data,
256 enum GNUNET_BLOCK_Type type, 254 enum GNUNET_BLOCK_Type type,
257 struct GNUNET_TIME_Absolute discard_time, 255 struct GNUNET_TIME_Absolute discard_time,
258 unsigned int path_info_len, 256 unsigned int path_info_len,
259 const struct GNUNET_PeerIdentity *path_info) 257 const struct GNUNET_PeerIdentity *path_info)
260{ 258{
261 ssize_t used; 259 ssize_t used;
262 260
263 used = h->api->put (h->api->cls, 261 used = h->api->put(h->api->cls,
264 key, 262 key,
265 xor_distance, 263 xor_distance,
266 data_size, 264 data_size,
267 data, 265 data,
268 type, 266 type,
269 discard_time, 267 discard_time,
270 path_info_len, 268 path_info_len,
271 path_info); 269 path_info);
272 if (-1 == used) 270 if (-1 == used)
273 { 271 {
274 GNUNET_break (0); 272 GNUNET_break(0);
275 return GNUNET_SYSERR; 273 return GNUNET_SYSERR;
276 } 274 }
277 if (0 == used) 275 if (0 == used)
278 { 276 {
279 /* duplicate */ 277 /* duplicate */
280 return GNUNET_NO; 278 return GNUNET_NO;
281 } 279 }
282 LOG (GNUNET_ERROR_TYPE_DEBUG, 280 LOG(GNUNET_ERROR_TYPE_DEBUG,
283 "Stored data under key `%s' in cache\n", 281 "Stored data under key `%s' in cache\n",
284 GNUNET_h2s (key)); 282 GNUNET_h2s(key));
285 if (NULL != h->filter) 283 if (NULL != h->filter)
286 GNUNET_CONTAINER_bloomfilter_add (h->filter, key); 284 GNUNET_CONTAINER_bloomfilter_add(h->filter, key);
287 GNUNET_STATISTICS_update (h->stats, 285 GNUNET_STATISTICS_update(h->stats,
288 gettext_noop ("# bytes stored"), 286 gettext_noop("# bytes stored"),
289 used, 287 used,
290 GNUNET_NO); 288 GNUNET_NO);
291 GNUNET_STATISTICS_update (h->stats, 289 GNUNET_STATISTICS_update(h->stats,
292 gettext_noop ("# items stored"), 290 gettext_noop("# items stored"),
293 1, 291 1,
294 GNUNET_NO); 292 GNUNET_NO);
295 while (h->utilization + used > h->env.quota) 293 while (h->utilization + used > h->env.quota)
296 GNUNET_assert (GNUNET_OK == h->api->del (h->api->cls)); 294 GNUNET_assert(GNUNET_OK == h->api->del(h->api->cls));
297 h->utilization += used; 295 h->utilization += used;
298 return GNUNET_OK; 296 return GNUNET_OK;
299} 297}
@@ -311,33 +309,33 @@ GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
311 * @return the number of results found 309 * @return the number of results found
312 */ 310 */
313unsigned int 311unsigned int
314GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h, 312GNUNET_DATACACHE_get(struct GNUNET_DATACACHE_Handle *h,
315 const struct GNUNET_HashCode *key, 313 const struct GNUNET_HashCode *key,
316 enum GNUNET_BLOCK_Type type, 314 enum GNUNET_BLOCK_Type type,
317 GNUNET_DATACACHE_Iterator iter, 315 GNUNET_DATACACHE_Iterator iter,
318 void *iter_cls) 316 void *iter_cls)
319{ 317{
320 GNUNET_STATISTICS_update (h->stats, 318 GNUNET_STATISTICS_update(h->stats,
321 gettext_noop ("# requests received"), 319 gettext_noop("# requests received"),
322 1, 320 1,
323 GNUNET_NO); 321 GNUNET_NO);
324 LOG (GNUNET_ERROR_TYPE_DEBUG, 322 LOG(GNUNET_ERROR_TYPE_DEBUG,
325 "Processing request for key `%s'\n", 323 "Processing request for key `%s'\n",
326 GNUNET_h2s (key)); 324 GNUNET_h2s(key));
327 if ((NULL != h->filter) && 325 if ((NULL != h->filter) &&
328 (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_test (h->filter, key))) 326 (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_test(h->filter, key)))
329 { 327 {
330 GNUNET_STATISTICS_update (h->stats, 328 GNUNET_STATISTICS_update(h->stats,
331 gettext_noop ( 329 gettext_noop(
332 "# requests filtered by bloom filter"), 330 "# requests filtered by bloom filter"),
333 1, 331 1,
334 GNUNET_NO); 332 GNUNET_NO);
335 LOG (GNUNET_ERROR_TYPE_DEBUG, 333 LOG(GNUNET_ERROR_TYPE_DEBUG,
336 "Bloomfilter filters request for key `%s'\n", 334 "Bloomfilter filters request for key `%s'\n",
337 GNUNET_h2s (key)); 335 GNUNET_h2s(key));
338 return 0; /* can not be present */ 336 return 0; /* can not be present */
339 } 337 }
340 return h->api->get (h->api->cls, key, type, iter, iter_cls); 338 return h->api->get(h->api->cls, key, type, iter, iter_cls);
341} 339}
342 340
343 341
@@ -350,17 +348,17 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
350 * @return the number of results found (zero or 1) 348 * @return the number of results found (zero or 1)
351 */ 349 */
352unsigned int 350unsigned int
353GNUNET_DATACACHE_get_random (struct GNUNET_DATACACHE_Handle *h, 351GNUNET_DATACACHE_get_random(struct GNUNET_DATACACHE_Handle *h,
354 GNUNET_DATACACHE_Iterator iter, 352 GNUNET_DATACACHE_Iterator iter,
355 void *iter_cls) 353 void *iter_cls)
356{ 354{
357 GNUNET_STATISTICS_update (h->stats, 355 GNUNET_STATISTICS_update(h->stats,
358 gettext_noop ( 356 gettext_noop(
359 "# requests for random value received"), 357 "# requests for random value received"),
360 1, 358 1,
361 GNUNET_NO); 359 GNUNET_NO);
362 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing request for random value\n"); 360 LOG(GNUNET_ERROR_TYPE_DEBUG, "Processing request for random value\n");
363 return h->api->get_random (h->api->cls, iter, iter_cls); 361 return h->api->get_random(h->api->cls, iter, iter_cls);
364} 362}
365 363
366 364
@@ -378,21 +376,21 @@ GNUNET_DATACACHE_get_random (struct GNUNET_DATACACHE_Handle *h,
378 * @return the number of results found 376 * @return the number of results found
379 */ 377 */
380unsigned int 378unsigned int
381GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h, 379GNUNET_DATACACHE_get_closest(struct GNUNET_DATACACHE_Handle *h,
382 const struct GNUNET_HashCode *key, 380 const struct GNUNET_HashCode *key,
383 unsigned int num_results, 381 unsigned int num_results,
384 GNUNET_DATACACHE_Iterator iter, 382 GNUNET_DATACACHE_Iterator iter,
385 void *iter_cls) 383 void *iter_cls)
386{ 384{
387 GNUNET_STATISTICS_update (h->stats, 385 GNUNET_STATISTICS_update(h->stats,
388 gettext_noop ( 386 gettext_noop(
389 "# proximity search requests received"), 387 "# proximity search requests received"),
390 1, 388 1,
391 GNUNET_NO); 389 GNUNET_NO);
392 LOG (GNUNET_ERROR_TYPE_DEBUG, 390 LOG(GNUNET_ERROR_TYPE_DEBUG,
393 "Processing proximity search at `%s'\n", 391 "Processing proximity search at `%s'\n",
394 GNUNET_h2s (key)); 392 GNUNET_h2s(key));
395 return h->api->get_closest (h->api->cls, key, num_results, iter, iter_cls); 393 return h->api->get_closest(h->api->cls, key, num_results, iter, iter_cls);
396} 394}
397 395
398 396