aboutsummaryrefslogtreecommitdiff
path: root/src/datacache
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-07-07 13:42:52 +0200
committerChristian Grothoff <christian@grothoff.org>2022-07-07 13:42:52 +0200
commit2906241b6a21d6009a0d195199f3a08e8f4d4e2a (patch)
treec9946fd81f343008877b41fc8471d13d0051f48a /src/datacache
parent374e3cf6de48f26f67cf93091a2bfbdab019a6eb (diff)
downloadgnunet-2906241b6a21d6009a0d195199f3a08e8f4d4e2a.tar.gz
gnunet-2906241b6a21d6009a0d195199f3a08e8f4d4e2a.zip
major modification to datacache to store route options (and clean up the API)
Diffstat (limited to 'src/datacache')
-rw-r--r--src/datacache/datacache.c32
-rw-r--r--src/datacache/plugin_datacache_heap.c220
-rw-r--r--src/datacache/plugin_datacache_postgres.c205
-rw-r--r--src/datacache/plugin_datacache_sqlite.c671
-rw-r--r--src/datacache/plugin_datacache_template.c20
-rw-r--r--src/datacache/test_datacache.c74
-rw-r--r--src/datacache/test_datacache_quota.c66
7 files changed, 769 insertions, 519 deletions
diff --git a/src/datacache/datacache.c b/src/datacache/datacache.c
index 761ab801f..c93ed58d6 100644
--- a/src/datacache/datacache.c
+++ b/src/datacache/datacache.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2015 GNUnet e.V. 3 Copyright (C) 2004-2010, 2015, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -259,26 +259,14 @@ GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h)
259 259
260enum GNUNET_GenericReturnValue 260enum GNUNET_GenericReturnValue
261GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h, 261GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
262 const struct GNUNET_HashCode *key,
263 uint32_t xor_distance, 262 uint32_t xor_distance,
264 size_t data_size, 263 const struct GNUNET_DATACACHE_Block *block)
265 const char *data,
266 enum GNUNET_BLOCK_Type type,
267 struct GNUNET_TIME_Absolute discard_time,
268 unsigned int path_info_len,
269 const struct GNUNET_DHT_PathElement *path_info)
270{ 264{
271 ssize_t used; 265 ssize_t used;
272 266
273 used = h->api->put (h->api->cls, 267 used = h->api->put (h->api->cls,
274 key,
275 xor_distance, 268 xor_distance,
276 data_size, 269 block);
277 data,
278 type,
279 discard_time,
280 path_info_len,
281 path_info);
282 if (-1 == used) 270 if (-1 == used)
283 { 271 {
284 GNUNET_break (0); 272 GNUNET_break (0);
@@ -291,10 +279,10 @@ GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
291 } 279 }
292 LOG (GNUNET_ERROR_TYPE_DEBUG, 280 LOG (GNUNET_ERROR_TYPE_DEBUG,
293 "Stored data under key `%s' in cache\n", 281 "Stored data under key `%s' in cache\n",
294 GNUNET_h2s (key)); 282 GNUNET_h2s (&block->key));
295 if (NULL != h->filter) 283 if (NULL != h->filter)
296 GNUNET_CONTAINER_bloomfilter_add (h->filter, 284 GNUNET_CONTAINER_bloomfilter_add (h->filter,
297 key); 285 &block->key);
298 GNUNET_STATISTICS_update (h->stats, 286 GNUNET_STATISTICS_update (h->stats,
299 "# bytes stored", 287 "# bytes stored",
300 used, 288 used,
@@ -325,9 +313,10 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
325 LOG (GNUNET_ERROR_TYPE_DEBUG, 313 LOG (GNUNET_ERROR_TYPE_DEBUG,
326 "Processing request for key `%s'\n", 314 "Processing request for key `%s'\n",
327 GNUNET_h2s (key)); 315 GNUNET_h2s (key));
328 if ((NULL != h->filter) && 316 if ( (NULL != h->filter) &&
329 (GNUNET_OK != 317 (GNUNET_OK !=
330 GNUNET_CONTAINER_bloomfilter_test (h->filter, key))) 318 GNUNET_CONTAINER_bloomfilter_test (h->filter,
319 key)) )
331 { 320 {
332 GNUNET_STATISTICS_update (h->stats, 321 GNUNET_STATISTICS_update (h->stats,
333 "# requests filtered by bloom filter", 322 "# requests filtered by bloom filter",
@@ -364,7 +353,8 @@ GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h,
364 key, 353 key,
365 type, 354 type,
366 num_results, 355 num_results,
367 iter, iter_cls); 356 iter,
357 iter_cls);
368} 358}
369 359
370 360
diff --git a/src/datacache/plugin_datacache_heap.c b/src/datacache/plugin_datacache_heap.c
index 5b50468a5..a2b60c8da 100644
--- a/src/datacache/plugin_datacache_heap.c
+++ b/src/datacache/plugin_datacache_heap.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2012, 2015 GNUnet e.V. 3 Copyright (C) 2012, 2015, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -63,14 +63,9 @@ struct Plugin
63struct Value 63struct Value
64{ 64{
65 /** 65 /**
66 * Key for the entry. 66 * Block data.
67 */ 67 */
68 struct GNUNET_HashCode key; 68 struct GNUNET_DATACACHE_Block block;
69
70 /**
71 * Expiration time.
72 */
73 struct GNUNET_TIME_Absolute discard_time;
74 69
75 /** 70 /**
76 * Corresponding node in the heap. 71 * Corresponding node in the heap.
@@ -78,29 +73,15 @@ struct Value
78 struct GNUNET_CONTAINER_HeapNode *hn; 73 struct GNUNET_CONTAINER_HeapNode *hn;
79 74
80 /** 75 /**
81 * Path information. 76 * Put path as a non-const pointer.
82 */
83 struct GNUNET_DHT_PathElement *path_info;
84
85 /**
86 * Payload (actual payload follows this struct)
87 */
88 size_t size;
89
90 /**
91 * Number of entries in @e path_info.
92 */ 77 */
93 unsigned int path_info_len; 78 struct GNUNET_DHT_PathElement *put_path;
94 79
95 /** 80 /**
96 * How close is the hash to us? Determines which heap we are in! 81 * How close is the hash to us? Determines which heap we are in!
97 */ 82 */
98 uint32_t distance; 83 uint32_t distance;
99 84
100 /**
101 * Type of the block.
102 */
103 enum GNUNET_BLOCK_Type type;
104}; 85};
105 86
106 87
@@ -113,39 +94,14 @@ struct Value
113struct PutContext 94struct PutContext
114{ 95{
115 /** 96 /**
116 * Expiration time for the new value. 97 * Block data.
117 */
118 struct GNUNET_TIME_Absolute discard_time;
119
120 /**
121 * Data for the new value.
122 */
123 const char *data;
124
125 /**
126 * Path information.
127 */ 98 */
128 const struct GNUNET_DHT_PathElement *path_info; 99 const struct GNUNET_DATACACHE_Block *block;
129 100
130 /** 101 /**
131 * Number of bytes in @e data. 102 * Value to set to true if an equivalent block was found.
132 */ 103 */
133 size_t size; 104 bool found;
134
135 /**
136 * Type of the node.
137 */
138 enum GNUNET_BLOCK_Type type;
139
140 /**
141 * Number of entries in @e path_info.
142 */
143 unsigned int path_info_len;
144
145 /**
146 * Value to set to #GNUNET_YES if an equivalent block was found.
147 */
148 int found;
149}; 105};
150 106
151 107
@@ -166,31 +122,31 @@ put_cb (void *cls,
166 struct PutContext *put_ctx = cls; 122 struct PutContext *put_ctx = cls;
167 struct Value *val = value; 123 struct Value *val = value;
168 124
169 if ((val->size == put_ctx->size) && 125 if ((val->block.data_size == put_ctx->block->data_size) &&
170 (val->type == put_ctx->type) && 126 (val->block.type == put_ctx->block->type) &&
171 (0 == memcmp (&val[1], 127 (0 == memcmp (val->block.data,
172 put_ctx->data, 128 put_ctx->block->data,
173 put_ctx->size))) 129 put_ctx->block->data_size)))
174 { 130 {
175 put_ctx->found = GNUNET_YES; 131 put_ctx->found = true;
176 val->discard_time = GNUNET_TIME_absolute_max (val->discard_time, 132 val->block.expiration_time
177 put_ctx->discard_time); 133 = GNUNET_TIME_absolute_max (val->block.expiration_time,
134 put_ctx->block->expiration_time);
178 /* replace old path with new path */ 135 /* replace old path with new path */
179 GNUNET_array_grow (val->path_info, 136 GNUNET_free (val->put_path);
180 val->path_info_len, 137 val->put_path = GNUNET_memdup (put_ctx->block->put_path,
181 put_ctx->path_info_len); 138 put_ctx->block->put_path_length
182 GNUNET_memcpy (val->path_info, 139 * sizeof (struct GNUNET_DHT_PathElement));
183 put_ctx->path_info, 140 val->block.put_path = val->put_path;
184 put_ctx->path_info_len * sizeof(struct 141 val->block.put_path_length = put_ctx->block->put_path_length;
185 GNUNET_DHT_PathElement));
186 GNUNET_CONTAINER_heap_update_cost (val->hn, 142 GNUNET_CONTAINER_heap_update_cost (val->hn,
187 val->discard_time.abs_value_us); 143 val->block.expiration_time.abs_value_us);
188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 144 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
189 "Got same value for key %s and type %d (size %u vs %u)\n", 145 "Got same value for key %s and type %u (size %u vs %u)\n",
190 GNUNET_h2s (key), 146 GNUNET_h2s (key),
191 val->type, 147 (unsigned int) val->block.type,
192 (unsigned int) val->size, 148 (unsigned int) val->block.data_size,
193 (unsigned int) put_ctx->size); 149 (unsigned int) put_ctx->block->data_size);
194 return GNUNET_NO; 150 return GNUNET_NO;
195 } 151 }
196 return GNUNET_YES; 152 return GNUNET_YES;
@@ -201,75 +157,58 @@ put_cb (void *cls,
201 * Store an item in the datastore. 157 * Store an item in the datastore.
202 * 158 *
203 * @param cls closure (our `struct Plugin`) 159 * @param cls closure (our `struct Plugin`)
204 * @param key key to store data under
205 * @param xor_distance how close is @a key to our PID? 160 * @param xor_distance how close is @a key to our PID?
206 * @param size number of bytes in @a data 161 * @param block data to store
207 * @param data data to store
208 * @param type type of the value
209 * @param discard_time when to discard the value in any case
210 * @param path_info_len number of entries in @a path_info
211 * @param path_info a path through the network
212 * @return 0 if duplicate, -1 on error, number of bytes used otherwise 162 * @return 0 if duplicate, -1 on error, number of bytes used otherwise
213 */ 163 */
214static ssize_t 164static ssize_t
215heap_plugin_put (void *cls, 165heap_plugin_put (void *cls,
216 const struct GNUNET_HashCode *key,
217 uint32_t xor_distance, 166 uint32_t xor_distance,
218 size_t size, 167 const struct GNUNET_DATACACHE_Block *block)
219 const char *data,
220 enum GNUNET_BLOCK_Type type,
221 struct GNUNET_TIME_Absolute discard_time,
222 unsigned int path_info_len,
223 const struct GNUNET_DHT_PathElement *path_info)
224{ 168{
225 struct Plugin *plugin = cls; 169 struct Plugin *plugin = cls;
226 struct Value *val; 170 struct Value *val;
227 struct PutContext put_ctx = { 171 struct PutContext put_ctx = {
228 .data = data, 172 .block = block,
229 .size = size, 173 .found = false
230 .path_info = path_info,
231 .path_info_len = path_info_len,
232 .discard_time = discard_time,
233 .type = type
234 }; 174 };
235 175
236 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 176 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
237 "Storing %u bytes under key %s with path length %u\n", 177 "Storing %u bytes under key %s with path length %u\n",
238 (unsigned int) size, 178 (unsigned int) block->data_size,
239 GNUNET_h2s (key), 179 GNUNET_h2s (&block->key),
240 path_info_len); 180 block->put_path_length);
241 GNUNET_CONTAINER_multihashmap_get_multiple (plugin->map, 181 GNUNET_CONTAINER_multihashmap_get_multiple (plugin->map,
242 key, 182 &block->key,
243 &put_cb, 183 &put_cb,
244 &put_ctx); 184 &put_ctx);
245 if (GNUNET_YES == put_ctx.found) 185 if (GNUNET_YES == put_ctx.found)
246 return 0; 186 return 0;
247 val = GNUNET_malloc (sizeof(struct Value) + size); 187 val = GNUNET_malloc (sizeof(struct Value)
188 + block->data_size);
248 GNUNET_memcpy (&val[1], 189 GNUNET_memcpy (&val[1],
249 data, 190 block->data,
250 size); 191 block->data_size);
251 val->key = *key; 192 val->block = *block;
252 val->type = type; 193 val->block.data = &val[1];
253 val->discard_time = discard_time;
254 val->size = size;
255 if (xor_distance >= NUM_HEAPS) 194 if (xor_distance >= NUM_HEAPS)
256 val->distance = NUM_HEAPS - 1; 195 val->distance = NUM_HEAPS - 1;
257 else 196 else
258 val->distance = xor_distance; 197 val->distance = xor_distance;
259 GNUNET_array_grow (val->path_info, 198 if (0 != block->put_path_length)
260 val->path_info_len, 199 val->block.put_path
261 path_info_len); 200 = GNUNET_memdup (block->put_path,
262 GNUNET_memcpy (val->path_info, 201 block->put_path_length
263 path_info, 202 * sizeof (struct GNUNET_DHT_PathElement));
264 path_info_len * sizeof(struct GNUNET_DHT_PathElement));
265 (void) GNUNET_CONTAINER_multihashmap_put (plugin->map, 203 (void) GNUNET_CONTAINER_multihashmap_put (plugin->map,
266 &val->key, 204 &val->block.key,
267 val, 205 val,
268 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 206 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
269 val->hn = GNUNET_CONTAINER_heap_insert (plugin->heaps[val->distance], 207 val->hn = GNUNET_CONTAINER_heap_insert (
270 val, 208 plugin->heaps[val->distance],
271 val->discard_time.abs_value_us); 209 val,
272 return size + OVERHEAD; 210 val->block.expiration_time.abs_value_us);
211 return val->block.data_size + OVERHEAD;
273} 212}
274 213
275 214
@@ -309,16 +248,16 @@ struct GetContext
309 * @param value an existing value 248 * @param value an existing value
310 * @return #GNUNET_YES to continue to iterate 249 * @return #GNUNET_YES to continue to iterate
311 */ 250 */
312static int 251static enum GNUNET_GenericReturnValue
313get_cb (void *cls, 252get_cb (void *cls,
314 const struct GNUNET_HashCode *key, 253 const struct GNUNET_HashCode *key,
315 void *value) 254 void *value)
316{ 255{
317 struct GetContext *get_ctx = cls; 256 struct GetContext *get_ctx = cls;
318 struct Value *val = value; 257 struct Value *val = value;
319 int ret; 258 enum GNUNET_GenericReturnValue ret;
320 259
321 if ( (get_ctx->type != val->type) && 260 if ( (get_ctx->type != val->block.type) &&
322 (GNUNET_BLOCK_TYPE_ANY != get_ctx->type) ) 261 (GNUNET_BLOCK_TYPE_ANY != get_ctx->type) )
323 { 262 {
324 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -327,7 +266,7 @@ get_cb (void *cls,
327 get_ctx->type); 266 get_ctx->type);
328 return GNUNET_OK; 267 return GNUNET_OK;
329 } 268 }
330 if (GNUNET_TIME_absolute_is_past (val->discard_time)) 269 if (GNUNET_TIME_absolute_is_past (val->block.expiration_time))
331 { 270 {
332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
333 "Result for key %s is expired\n", 272 "Result for key %s is expired\n",
@@ -339,13 +278,7 @@ get_cb (void *cls,
339 GNUNET_h2s (key)); 278 GNUNET_h2s (key));
340 if (NULL != get_ctx->iter) 279 if (NULL != get_ctx->iter)
341 ret = get_ctx->iter (get_ctx->iter_cls, 280 ret = get_ctx->iter (get_ctx->iter_cls,
342 key, 281 &val->block);
343 val->size,
344 (const char *) &val[1],
345 val->type,
346 val->discard_time,
347 val->path_info_len,
348 val->path_info);
349 else 282 else
350 ret = GNUNET_YES; 283 ret = GNUNET_YES;
351 get_ctx->cnt++; 284 get_ctx->cnt++;
@@ -393,7 +326,7 @@ heap_plugin_get (void *cls,
393 * @param cls closure (our `struct Plugin`) 326 * @param cls closure (our `struct Plugin`)
394 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 327 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
395 */ 328 */
396static int 329static enum GNUNET_GenericReturnValue
397heap_plugin_del (void *cls) 330heap_plugin_del (void *cls)
398{ 331{
399 struct Plugin *plugin = cls; 332 struct Plugin *plugin = cls;
@@ -409,12 +342,12 @@ heap_plugin_del (void *cls)
409 return GNUNET_SYSERR; 342 return GNUNET_SYSERR;
410 GNUNET_assert (GNUNET_YES == 343 GNUNET_assert (GNUNET_YES ==
411 GNUNET_CONTAINER_multihashmap_remove (plugin->map, 344 GNUNET_CONTAINER_multihashmap_remove (plugin->map,
412 &val->key, 345 &val->block.key,
413 val)); 346 val));
414 plugin->env->delete_notify (plugin->env->cls, 347 plugin->env->delete_notify (plugin->env->cls,
415 &val->key, 348 &val->block.key,
416 val->size + OVERHEAD); 349 val->block.data_size + OVERHEAD);
417 GNUNET_free (val->path_info); 350 GNUNET_free (val->put_path);
418 GNUNET_free (val); 351 GNUNET_free (val);
419 return GNUNET_OK; 352 return GNUNET_OK;
420} 353}
@@ -448,7 +381,7 @@ find_closest (void *cls,
448 if (1 != GNUNET_CRYPTO_hash_cmp (key, 381 if (1 != GNUNET_CRYPTO_hash_cmp (key,
449 gcc->key)) 382 gcc->key))
450 return GNUNET_OK; /* useless */ 383 return GNUNET_OK; /* useless */
451 if ( (val->type != gcc->type) && 384 if ( (val->block.type != gcc->type) &&
452 (GNUNET_BLOCK_TYPE_ANY != gcc->type) ) 385 (GNUNET_BLOCK_TYPE_ANY != gcc->type) )
453 return GNUNET_OK; /* useless */ 386 return GNUNET_OK; /* useless */
454 j = gcc->num_results; 387 j = gcc->num_results;
@@ -460,7 +393,7 @@ find_closest (void *cls,
460 break; 393 break;
461 } 394 }
462 if (1 == 395 if (1 ==
463 GNUNET_CRYPTO_hash_cmp (&gcc->values[i]->key, 396 GNUNET_CRYPTO_hash_cmp (&gcc->values[i]->block.key,
464 key)) 397 key))
465 { 398 {
466 j = i; 399 j = i;
@@ -512,14 +445,15 @@ heap_plugin_get_closest (void *cls,
512 { 445 {
513 if (NULL == values[i]) 446 if (NULL == values[i])
514 return i; 447 return i;
515 iter (iter_cls, 448 if ( (NULL != iter) &&
516 &values[i]->key, 449 (GNUNET_SYSERR ==
517 values[i]->size, 450 iter (iter_cls,
518 (void *) &values[i][1], 451 &values[i]->block)) )
519 values[i]->type, 452 {
520 values[i]->discard_time, 453 LOG (GNUNET_ERROR_TYPE_DEBUG,
521 values[i]->path_info_len, 454 "Ending iteration (client error)\n");
522 values[i]->path_info); 455 return i;
456 }
523 } 457 }
524 return num_results * 2; 458 return num_results * 2;
525} 459}
@@ -576,9 +510,9 @@ libgnunet_plugin_datacache_heap_done (void *cls)
576 { 510 {
577 GNUNET_assert (GNUNET_YES == 511 GNUNET_assert (GNUNET_YES ==
578 GNUNET_CONTAINER_multihashmap_remove (plugin->map, 512 GNUNET_CONTAINER_multihashmap_remove (plugin->map,
579 &val->key, 513 &val->block.key,
580 val)); 514 val));
581 GNUNET_free (val->path_info); 515 GNUNET_free (val->put_path);
582 GNUNET_free (val); 516 GNUNET_free (val);
583 } 517 }
584 GNUNET_CONTAINER_heap_destroy (plugin->heaps[i]); 518 GNUNET_CONTAINER_heap_destroy (plugin->heaps[i]);
diff --git a/src/datacache/plugin_datacache_postgres.c b/src/datacache/plugin_datacache_postgres.c
index 1a83cda86..d9e25992b 100644
--- a/src/datacache/plugin_datacache_postgres.c
+++ b/src/datacache/plugin_datacache_postgres.c
@@ -63,73 +63,75 @@ struct Plugin
63 * @param plugin global context 63 * @param plugin global context
64 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 64 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
65 */ 65 */
66static int 66static enum GNUNET_GenericReturnValue
67init_connection (struct Plugin *plugin) 67init_connection (struct Plugin *plugin)
68{ 68{
69 struct GNUNET_PQ_ExecuteStatement es[] = { 69 struct GNUNET_PQ_ExecuteStatement es[] = {
70 GNUNET_PQ_make_try_execute ( 70 GNUNET_PQ_make_try_execute (
71 "CREATE TEMPORARY SEQUENCE IF NOT EXISTS gn011dc_oid_seq"), 71 "CREATE TEMPORARY SEQUENCE IF NOT EXISTS gn180dc_oid_seq"),
72 GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS gn011dc (" 72 GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS gn180dc ("
73 " oid OID NOT NULL DEFAULT nextval('gn011dc_oid_seq')," 73 " oid OID NOT NULL DEFAULT nextval('gn180dc_oid_seq'),"
74 " type INTEGER NOT NULL," 74 " type INTEGER NOT NULL,"
75 " ro INTEGER NOT NULL,"
75 " prox INTEGER NOT NULL," 76 " prox INTEGER NOT NULL,"
76 " discard_time BIGINT NOT NULL," 77 " expiration_time BIGINT NOT NULL,"
77 " key BYTEA NOT NULL," 78 " key BYTEA NOT NULL,"
78 " value BYTEA NOT NULL," 79 " value BYTEA NOT NULL,"
79 " path BYTEA DEFAULT NULL)"), 80 " path BYTEA DEFAULT NULL)"),
80 GNUNET_PQ_make_try_execute ( 81 GNUNET_PQ_make_try_execute (
81 "ALTER SEQUENCE gnu011dc_oid_seq OWNED BY gn011dc.oid"), 82 "ALTER SEQUENCE gnu011dc_oid_seq OWNED BY gn180dc.oid"),
82 GNUNET_PQ_make_try_execute ( 83 GNUNET_PQ_make_try_execute (
83 "CREATE INDEX IF NOT EXISTS idx_oid ON gn011dc (oid)"), 84 "CREATE INDEX IF NOT EXISTS idx_oid ON gn180dc (oid)"),
84 GNUNET_PQ_make_try_execute ( 85 GNUNET_PQ_make_try_execute (
85 "CREATE INDEX IF NOT EXISTS idx_key ON gn011dc (key)"), 86 "CREATE INDEX IF NOT EXISTS idx_key ON gn180dc (key)"),
86 GNUNET_PQ_make_try_execute ( 87 GNUNET_PQ_make_try_execute (
87 "CREATE INDEX IF NOT EXISTS idx_dt ON gn011dc (discard_time)"), 88 "CREATE INDEX IF NOT EXISTS idx_dt ON gn180dc (expiration_time)"),
88 GNUNET_PQ_make_execute ( 89 GNUNET_PQ_make_execute (
89 "ALTER TABLE gn011dc ALTER value SET STORAGE EXTERNAL"), 90 "ALTER TABLE gn180dc ALTER value SET STORAGE EXTERNAL"),
90 GNUNET_PQ_make_execute ("ALTER TABLE gn011dc ALTER key SET STORAGE PLAIN"), 91 GNUNET_PQ_make_execute ("ALTER TABLE gn180dc ALTER key SET STORAGE PLAIN"),
91 GNUNET_PQ_EXECUTE_STATEMENT_END 92 GNUNET_PQ_EXECUTE_STATEMENT_END
92 }; 93 };
93 struct GNUNET_PQ_PreparedStatement ps[] = { 94 struct GNUNET_PQ_PreparedStatement ps[] = {
94 GNUNET_PQ_make_prepare ("getkt", 95 GNUNET_PQ_make_prepare ("getkt",
95 "SELECT discard_time,type,value,path FROM gn011dc " 96 "SELECT expiration_time,type,ro,value,path FROM gn180dc "
96 "WHERE key=$1 AND type=$2 AND discard_time >= $3", 97 "WHERE key=$1 AND type=$2 AND expiration_time >= $3",
97 3), 98 3),
98 GNUNET_PQ_make_prepare ("getk", 99 GNUNET_PQ_make_prepare ("getk",
99 "SELECT discard_time,type,value,path FROM gn011dc " 100 "SELECT expiration_time,type,ro,value,path FROM gn180dc "
100 "WHERE key=$1 AND discard_time >= $2", 101 "WHERE key=$1 AND expiration_time >= $2",
101 2), 102 2),
102 GNUNET_PQ_make_prepare ("getex", 103 GNUNET_PQ_make_prepare ("getex",
103 "SELECT length(value) AS len,oid,key FROM gn011dc" 104 "SELECT LENGTH(value) AS len,oid,key FROM gn180dc"
104 " WHERE discard_time < $1" 105 " WHERE expiration_time < $1"
105 " ORDER BY discard_time ASC LIMIT 1", 106 " ORDER BY expiration_time ASC LIMIT 1",
106 1), 107 1),
107 GNUNET_PQ_make_prepare ("getm", 108 GNUNET_PQ_make_prepare ("getm",
108 "SELECT length(value) AS len,oid,key FROM gn011dc" 109 "SELECT LENGTH(value) AS len,oid,key FROM gn180dc"
109 " ORDER BY prox ASC, discard_time ASC LIMIT 1", 110 " ORDER BY prox ASC, expiration_time ASC LIMIT 1",
110 0), 111 0),
111 GNUNET_PQ_make_prepare ("get_closest", 112 GNUNET_PQ_make_prepare ("get_closest",
112 "(SELECT discard_time,type,value,path,key FROM gn011dc" 113 "(SELECT expiration_time,type,ro,value,path,key FROM gn180dc"
113 " WHERE key >= $1" 114 " WHERE key >= $1"
114 " AND discard_time >= $2" 115 " AND expiration_time >= $2"
115 " AND ( (type = $3) OR ( 0 = $3) )" 116 " AND ( (type = $3) OR ( 0 = $3) )"
116 " ORDER BY key ASC" 117 " ORDER BY key ASC"
117 " LIMIT $4)" 118 " LIMIT $4)"
118 " UNION " 119 " UNION "
119 "(SELECT discard_time,type,value,path,key FROM gn011dc" 120 "(SELECT expiration_time,type,ro,value,path,key FROM gn180dc"
120 " WHERE key <= $1" 121 " WHERE key <= $1"
121 " AND discard_time >= $2" 122 " AND expiration_time >= $2"
122 " AND ( (type = $3) OR ( 0 = $3) )" 123 " AND ( (type = $3) OR ( 0 = $3) )"
123 " ORDER BY key DESC" 124 " ORDER BY key DESC"
124 " LIMIT $4)", 125 " LIMIT $4)",
125 4), 126 4),
126 GNUNET_PQ_make_prepare ("delrow", 127 GNUNET_PQ_make_prepare ("delrow",
127 "DELETE FROM gn011dc WHERE oid=$1", 128 "DELETE FROM gn180dc WHERE oid=$1",
128 1), 129 1),
129 GNUNET_PQ_make_prepare ("put", 130 GNUNET_PQ_make_prepare ("put",
130 "INSERT INTO gn011dc (type, prox, discard_time, key, value, path) " 131 "INSERT INTO gn180dc"
131 "VALUES ($1, $2, $3, $4, $5, $6)", 132 " (type, ro, prox, expiration_time, key, value, path) "
132 6), 133 "VALUES ($1, $2, $3, $4, $5, $6, $7)",
134 7),
133 GNUNET_PQ_PREPARED_STATEMENT_END 135 GNUNET_PQ_PREPARED_STATEMENT_END
134 }; 136 };
135 137
@@ -148,38 +150,29 @@ init_connection (struct Plugin *plugin)
148 * Store an item in the datastore. 150 * Store an item in the datastore.
149 * 151 *
150 * @param cls closure (our `struct Plugin`) 152 * @param cls closure (our `struct Plugin`)
151 * @param key key to store @a data under
152 * @param prox proximity of @a key to my PID 153 * @param prox proximity of @a key to my PID
153 * @param data_size number of bytes in @a data 154 * @param block data to store
154 * @param data data to store
155 * @param type type of the value
156 * @param discard_time when to discard the value in any case
157 * @param path_info_len number of entries in @a path_info
158 * @param path_info a path through the network
159 * @return 0 if duplicate, -1 on error, number of bytes used otherwise 155 * @return 0 if duplicate, -1 on error, number of bytes used otherwise
160 */ 156 */
161static ssize_t 157static ssize_t
162postgres_plugin_put (void *cls, 158postgres_plugin_put (void *cls,
163 const struct GNUNET_HashCode *key,
164 uint32_t prox, 159 uint32_t prox,
165 size_t data_size, 160 const struct GNUNET_DATACACHE_Block *block)
166 const char *data,
167 enum GNUNET_BLOCK_Type type,
168 struct GNUNET_TIME_Absolute discard_time,
169 unsigned int path_info_len,
170 const struct GNUNET_DHT_PathElement *path_info)
171{ 161{
172 struct Plugin *plugin = cls; 162 struct Plugin *plugin = cls;
173 uint32_t type32 = (uint32_t) type; 163 uint32_t type32 = (uint32_t) block->type;
164 uint32_t ro32 = (uint32_t) block->type;
174 struct GNUNET_PQ_QueryParam params[] = { 165 struct GNUNET_PQ_QueryParam params[] = {
175 GNUNET_PQ_query_param_uint32 (&type32), 166 GNUNET_PQ_query_param_uint32 (&type32),
167 GNUNET_PQ_query_param_uint32 (&ro32),
176 GNUNET_PQ_query_param_uint32 (&prox), 168 GNUNET_PQ_query_param_uint32 (&prox),
177 GNUNET_PQ_query_param_absolute_time (&discard_time), 169 GNUNET_PQ_query_param_absolute_time (&block->expiration_time),
178 GNUNET_PQ_query_param_auto_from_type (key), 170 GNUNET_PQ_query_param_auto_from_type (&block->key),
179 GNUNET_PQ_query_param_fixed_size (data, data_size), 171 GNUNET_PQ_query_param_fixed_size (block->data,
180 GNUNET_PQ_query_param_fixed_size (path_info, 172 block->data_size),
181 path_info_len * sizeof(struct 173 GNUNET_PQ_query_param_fixed_size (block->put_path,
182 GNUNET_DHT_PathElement)), 174 block->put_path_length
175 * sizeof(struct GNUNET_DHT_PathElement)),
183 GNUNET_PQ_query_param_end 176 GNUNET_PQ_query_param_end
184 }; 177 };
185 enum GNUNET_DB_QueryStatus ret; 178 enum GNUNET_DB_QueryStatus ret;
@@ -190,7 +183,7 @@ postgres_plugin_put (void *cls,
190 if (0 > ret) 183 if (0 > ret)
191 return -1; 184 return -1;
192 plugin->num_items++; 185 plugin->num_items++;
193 return data_size + OVERHEAD; 186 return block->data_size + OVERHEAD;
194} 187}
195 188
196 189
@@ -234,23 +227,25 @@ handle_results (void *cls,
234 227
235 for (unsigned int i = 0; i < num_results; i++) 228 for (unsigned int i = 0; i < num_results; i++)
236 { 229 {
237 struct GNUNET_TIME_Absolute expiration_time; 230 uint32_t type32;
238 uint32_t type; 231 uint32_t bro32;
239 void *data; 232 void *data;
240 size_t data_size; 233 struct GNUNET_DATACACHE_Block block;
241 struct GNUNET_DHT_PathElement *path; 234 void *path;
242 size_t path_len; 235 size_t path_size;
243 struct GNUNET_PQ_ResultSpec rs[] = { 236 struct GNUNET_PQ_ResultSpec rs[] = {
244 GNUNET_PQ_result_spec_absolute_time ("discard_time", 237 GNUNET_PQ_result_spec_absolute_time ("expiration_time",
245 &expiration_time), 238 &block.expiration_time),
246 GNUNET_PQ_result_spec_uint32 ("type", 239 GNUNET_PQ_result_spec_uint32 ("type",
247 &type), 240 &type32),
241 GNUNET_PQ_result_spec_uint32 ("ro",
242 &bro32),
248 GNUNET_PQ_result_spec_variable_size ("value", 243 GNUNET_PQ_result_spec_variable_size ("value",
249 &data, 244 &data,
250 &data_size), 245 &block.data_size),
251 GNUNET_PQ_result_spec_variable_size ("path", 246 GNUNET_PQ_result_spec_variable_size ("path",
252 (void **) &path, 247 &path,
253 &path_len), 248 &path_size),
254 GNUNET_PQ_result_spec_end 249 GNUNET_PQ_result_spec_end
255 }; 250 };
256 251
@@ -262,26 +257,27 @@ handle_results (void *cls,
262 GNUNET_break (0); 257 GNUNET_break (0);
263 return; 258 return;
264 } 259 }
265 if (0 != (path_len % sizeof(struct GNUNET_DHT_PathElement))) 260 if (0 != (path_size % sizeof(struct GNUNET_DHT_PathElement)))
266 { 261 {
267 GNUNET_break (0); 262 GNUNET_break (0);
268 path_len = 0; 263 path_size = 0;
264 path = NULL;
269 } 265 }
270 path_len %= sizeof(struct GNUNET_DHT_PathElement); 266 block.data = data;
267 block.put_path = path;
268 block.put_path_length
269 = path_size / sizeof (struct GNUNET_DHT_PathElement);
270 block.type = (enum GNUNET_BLOCK_Type) type32;
271 block.ro = (enum GNUNET_DHT_RouteOption) bro32;
272 block.key = *hrc->key;
271 LOG (GNUNET_ERROR_TYPE_DEBUG, 273 LOG (GNUNET_ERROR_TYPE_DEBUG,
272 "Found result of size %u bytes and type %u in database\n", 274 "Found result of size %u bytes and type %u in database\n",
273 (unsigned int) data_size, 275 (unsigned int) block.data_size,
274 (unsigned int) type); 276 (unsigned int) block.type);
275 if ((NULL != hrc->iter) && 277 if ( (NULL != hrc->iter) &&
276 (GNUNET_SYSERR == 278 (GNUNET_SYSERR ==
277 hrc->iter (hrc->iter_cls, 279 hrc->iter (hrc->iter_cls,
278 hrc->key, 280 &block)) )
279 data_size,
280 data,
281 (enum GNUNET_BLOCK_Type) type,
282 expiration_time,
283 path_len,
284 path)))
285 { 281 {
286 LOG (GNUNET_ERROR_TYPE_DEBUG, 282 LOG (GNUNET_ERROR_TYPE_DEBUG,
287 "Ending iteration (client error)\n"); 283 "Ending iteration (client error)\n");
@@ -350,7 +346,7 @@ postgres_plugin_get (void *cls,
350 * @param cls closure (our `struct Plugin`) 346 * @param cls closure (our `struct Plugin`)
351 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 347 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
352 */ 348 */
353static int 349static enum GNUNET_GenericReturnValue
354postgres_plugin_del (void *cls) 350postgres_plugin_del (void *cls)
355{ 351{
356 struct Plugin *plugin = cls; 352 struct Plugin *plugin = cls;
@@ -453,26 +449,27 @@ extract_result_cb (void *cls,
453 return; 449 return;
454 for (unsigned int i = 0; i < num_results; i++) 450 for (unsigned int i = 0; i < num_results; i++)
455 { 451 {
456 struct GNUNET_TIME_Absolute expiration_time; 452 uint32_t type32;
457 uint32_t type; 453 uint32_t bro32;
454 struct GNUNET_DATACACHE_Block block;
458 void *data; 455 void *data;
459 size_t data_size; 456 void *path;
460 struct GNUNET_DHT_PathElement *path; 457 size_t path_size;
461 size_t path_len;
462 struct GNUNET_HashCode key;
463 struct GNUNET_PQ_ResultSpec rs[] = { 458 struct GNUNET_PQ_ResultSpec rs[] = {
464 GNUNET_PQ_result_spec_absolute_time ("", 459 GNUNET_PQ_result_spec_absolute_time ("expiration_time",
465 &expiration_time), 460 &block.expiration_time),
466 GNUNET_PQ_result_spec_uint32 ("type", 461 GNUNET_PQ_result_spec_uint32 ("type",
467 &type), 462 &type32),
463 GNUNET_PQ_result_spec_uint32 ("ro",
464 &bro32),
468 GNUNET_PQ_result_spec_variable_size ("value", 465 GNUNET_PQ_result_spec_variable_size ("value",
469 &data, 466 &data,
470 &data_size), 467 &block.data_size),
471 GNUNET_PQ_result_spec_variable_size ("path", 468 GNUNET_PQ_result_spec_variable_size ("path",
472 (void **) &path, 469 &path,
473 &path_len), 470 &path_size),
474 GNUNET_PQ_result_spec_auto_from_type ("key", 471 GNUNET_PQ_result_spec_auto_from_type ("key",
475 &key), 472 &block.key),
476 GNUNET_PQ_result_spec_end 473 GNUNET_PQ_result_spec_end
477 }; 474 };
478 475
@@ -484,25 +481,25 @@ extract_result_cb (void *cls,
484 GNUNET_break (0); 481 GNUNET_break (0);
485 return; 482 return;
486 } 483 }
487 if (0 != (path_len % sizeof(struct GNUNET_DHT_PathElement))) 484 if (0 != (path_size % sizeof(struct GNUNET_DHT_PathElement)))
488 { 485 {
489 GNUNET_break (0); 486 GNUNET_break (0);
490 path_len = 0; 487 path_size = 0;
488 path = NULL;
491 } 489 }
492 path_len %= sizeof(struct GNUNET_DHT_PathElement); 490 block.type = (enum GNUNET_BLOCK_Type) type32;
491 block.ro = (enum GNUNET_DHT_RouteOption) bro32;
492 block.data = data;
493 block.put_path = path;
494 block.put_path_length = path_size / sizeof (struct GNUNET_DHT_PathElement);
493 LOG (GNUNET_ERROR_TYPE_DEBUG, 495 LOG (GNUNET_ERROR_TYPE_DEBUG,
494 "Found result of size %u bytes and type %u in database\n", 496 "Found result of size %u bytes and type %u in database\n",
495 (unsigned int) data_size, 497 (unsigned int) block.data_size,
496 (unsigned int) type); 498 (unsigned int) block.type);
497 if (GNUNET_SYSERR == 499 if ( (NULL != erc->iter) &&
498 erc->iter (erc->iter_cls, 500 (GNUNET_SYSERR ==
499 &key, 501 erc->iter (erc->iter_cls,
500 data_size, 502 &block)) )
501 data,
502 (enum GNUNET_BLOCK_Type) type,
503 expiration_time,
504 path_len,
505 path))
506 { 503 {
507 LOG (GNUNET_ERROR_TYPE_DEBUG, 504 LOG (GNUNET_ERROR_TYPE_DEBUG,
508 "Ending iteration (client error)\n"); 505 "Ending iteration (client error)\n");
diff --git a/src/datacache/plugin_datacache_sqlite.c b/src/datacache/plugin_datacache_sqlite.c
index 6f2165433..22ae5c0f5 100644
--- a/src/datacache/plugin_datacache_sqlite.c
+++ b/src/datacache/plugin_datacache_sqlite.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2006, 2009, 2015 GNUnet e.V. 3 Copyright (C) 2006, 2009, 2015, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -74,9 +74,19 @@ struct Plugin
74 /** 74 /**
75 * Prepared statement for #sqlite_plugin_get. 75 * Prepared statement for #sqlite_plugin_get.
76 */ 76 */
77 sqlite3_stmt *get_count_any_stmt;
78
79 /**
80 * Prepared statement for #sqlite_plugin_get.
81 */
77 sqlite3_stmt *get_stmt; 82 sqlite3_stmt *get_stmt;
78 83
79 /** 84 /**
85 * Prepared statement for #sqlite_plugin_get.
86 */
87 sqlite3_stmt *get_any_stmt;
88
89 /**
80 * Prepared statement for #sqlite_plugin_del. 90 * Prepared statement for #sqlite_plugin_del.
81 */ 91 */
82 sqlite3_stmt *del_select_stmt; 92 sqlite3_stmt *del_select_stmt;
@@ -133,9 +143,10 @@ struct Plugin
133 do \ 143 do \
134 { \ 144 { \
135 emsg = NULL; \ 145 emsg = NULL; \
136 if (SQLITE_OK != sqlite3_exec (db, cmd, NULL, NULL, &emsg)) \ 146 if (SQLITE_OK != \
147 sqlite3_exec (db, cmd, NULL, NULL, &emsg)) \
137 { \ 148 { \
138 LOG (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, \ 149 LOG (GNUNET_ERROR_TYPE_ERROR, \
139 _ ("`%s' failed at %s:%d with error: %s\n"), \ 150 _ ("`%s' failed at %s:%d with error: %s\n"), \
140 "sqlite3_exec", \ 151 "sqlite3_exec", \
141 __FILE__, \ 152 __FILE__, \
@@ -173,67 +184,222 @@ sq_prepare (sqlite3 *dbh,
173 * Store an item in the datastore. 184 * Store an item in the datastore.
174 * 185 *
175 * @param cls closure (our `struct Plugin`) 186 * @param cls closure (our `struct Plugin`)
176 * @param key key to store @a data under
177 * @param xor_distance how close is @a key to our PID? 187 * @param xor_distance how close is @a key to our PID?
178 * @param size number of bytes in @a data 188 * @param block data to store
179 * @param data data to store
180 * @param type type of the value
181 * @param discard_time when to discard the value in any case
182 * @param path_info_len number of entries in @a path_info
183 * @param path_info array of peers that have processed the request
184 * @return 0 if duplicate, -1 on error, number of bytes used otherwise 189 * @return 0 if duplicate, -1 on error, number of bytes used otherwise
185 */ 190 */
186static ssize_t 191static ssize_t
187sqlite_plugin_put (void *cls, 192sqlite_plugin_put (void *cls,
188 const struct GNUNET_HashCode *key,
189 uint32_t xor_distance, 193 uint32_t xor_distance,
190 size_t size, 194 const struct GNUNET_DATACACHE_Block *block)
191 const char *data,
192 enum GNUNET_BLOCK_Type type,
193 struct GNUNET_TIME_Absolute discard_time,
194 unsigned int path_info_len,
195 const struct GNUNET_DHT_PathElement *path_info)
196{ 195{
197 struct Plugin *plugin = cls; 196 struct Plugin *plugin = cls;
198 uint32_t type32 = type; 197 uint32_t type32 = (uint32_t) block->type;
199 struct GNUNET_SQ_QueryParam params[] = 198 uint32_t ro32 = (uint32_t) block->ro;
200 { GNUNET_SQ_query_param_uint32 (&type32), 199 struct GNUNET_SQ_QueryParam params[] = {
201 GNUNET_SQ_query_param_absolute_time (&discard_time), 200 GNUNET_SQ_query_param_uint32 (&type32),
202 GNUNET_SQ_query_param_auto_from_type (key), 201 GNUNET_SQ_query_param_uint32 (&ro32),
202 GNUNET_SQ_query_param_absolute_time (&block->expiration_time),
203 GNUNET_SQ_query_param_auto_from_type (&block->key),
203 GNUNET_SQ_query_param_uint32 (&xor_distance), 204 GNUNET_SQ_query_param_uint32 (&xor_distance),
204 GNUNET_SQ_query_param_fixed_size (data, size), 205 GNUNET_SQ_query_param_fixed_size (block->data,
205 GNUNET_SQ_query_param_fixed_size (path_info, 206 block->data_size),
206 path_info_len 207 GNUNET_SQ_query_param_fixed_size (block->put_path,
208 block->put_path_length
207 * sizeof(struct GNUNET_DHT_PathElement)), 209 * sizeof(struct GNUNET_DHT_PathElement)),
208 GNUNET_SQ_query_param_end }; 210 GNUNET_SQ_query_param_end
211 };
209 212
210 LOG (GNUNET_ERROR_TYPE_DEBUG, 213 LOG (GNUNET_ERROR_TYPE_DEBUG,
211 "Processing PUT of %u bytes with key `%s' and expiration %s\n", 214 "Processing PUT of %u bytes with key `%s' and expiration %s\n",
212 (unsigned int) size, 215 (unsigned int) block->data_size,
213 GNUNET_h2s (key), 216 GNUNET_h2s (&block->key),
214 GNUNET_STRINGS_relative_time_to_string ( 217 GNUNET_STRINGS_relative_time_to_string (
215 GNUNET_TIME_absolute_get_remaining ( 218 GNUNET_TIME_absolute_get_remaining (
216 discard_time), 219 block->expiration_time),
217 GNUNET_YES)); 220 GNUNET_YES));
218 if (GNUNET_OK != GNUNET_SQ_bind (plugin->insert_stmt, params)) 221 if (GNUNET_OK !=
222 GNUNET_SQ_bind (plugin->insert_stmt,
223 params))
219 { 224 {
220 LOG_SQLITE (plugin->dbh, 225 LOG_SQLITE (plugin->dbh,
221 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 226 GNUNET_ERROR_TYPE_ERROR,
222 "sqlite3_bind_xxx"); 227 "sqlite3_bind_xxx");
223 GNUNET_SQ_reset (plugin->dbh, plugin->insert_stmt); 228 GNUNET_SQ_reset (plugin->dbh,
229 plugin->insert_stmt);
224 return -1; 230 return -1;
225 } 231 }
226 if (SQLITE_DONE != sqlite3_step (plugin->insert_stmt)) 232 if (SQLITE_DONE !=
233 sqlite3_step (plugin->insert_stmt))
227 { 234 {
228 LOG_SQLITE (plugin->dbh, 235 LOG_SQLITE (plugin->dbh,
229 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 236 GNUNET_ERROR_TYPE_ERROR,
230 "sqlite3_step"); 237 "sqlite3_step");
231 GNUNET_SQ_reset (plugin->dbh, plugin->insert_stmt); 238 GNUNET_SQ_reset (plugin->dbh,
239 plugin->insert_stmt);
232 return -1; 240 return -1;
233 } 241 }
234 plugin->num_items++; 242 plugin->num_items++;
235 GNUNET_SQ_reset (plugin->dbh, plugin->insert_stmt); 243 GNUNET_SQ_reset (plugin->dbh,
236 return size + OVERHEAD; 244 plugin->insert_stmt);
245 return block->data_size + OVERHEAD;
246}
247
248
249/**
250 * Iterate over the results for a particular key
251 * in the datastore.
252 *
253 * @param cls closure (our `struct Plugin`)
254 * @param key
255 * @param iter maybe NULL (to just count)
256 * @param iter_cls closure for @a iter
257 * @return the number of results found
258 */
259static unsigned int
260get_any (void *cls,
261 const struct GNUNET_HashCode *key,
262 GNUNET_DATACACHE_Iterator iter,
263 void *iter_cls)
264{
265 struct Plugin *plugin = cls;
266 struct GNUNET_TIME_Absolute now;
267 unsigned int cnt;
268 uint32_t off;
269 uint32_t btype32;
270 uint32_t bro32;
271 unsigned int total;
272 struct GNUNET_DATACACHE_Block block;
273 void *path;
274 void *data;
275 size_t path_size;
276 struct GNUNET_SQ_QueryParam params_count[] = {
277 GNUNET_SQ_query_param_auto_from_type (key),
278 GNUNET_SQ_query_param_absolute_time (&now),
279 GNUNET_SQ_query_param_end
280 };
281 struct GNUNET_SQ_QueryParam params_select[] = {
282 GNUNET_SQ_query_param_auto_from_type (key),
283 GNUNET_SQ_query_param_absolute_time (&now),
284 GNUNET_SQ_query_param_uint32 (&off),
285 GNUNET_SQ_query_param_end
286 };
287 struct GNUNET_SQ_ResultSpec rs[] = {
288 GNUNET_SQ_result_spec_variable_size (&data,
289 &block.data_size),
290 GNUNET_SQ_result_spec_absolute_time (&block.expiration_time),
291 GNUNET_SQ_result_spec_variable_size (&path,
292 &path_size),
293 GNUNET_SQ_result_spec_uint32 (&btype32),
294 GNUNET_SQ_result_spec_uint32 (&bro32),
295 GNUNET_SQ_result_spec_end
296 };
297
298 now = GNUNET_TIME_absolute_get ();
299 LOG (GNUNET_ERROR_TYPE_DEBUG,
300 "Processing GET for key `%s'\n",
301 GNUNET_h2s (key));
302
303 if (GNUNET_OK !=
304 GNUNET_SQ_bind (plugin->get_count_any_stmt,
305 params_count))
306 {
307 LOG_SQLITE (plugin->dbh,
308 GNUNET_ERROR_TYPE_ERROR,
309 "sqlite3_bind_xxx");
310 GNUNET_SQ_reset (plugin->dbh,
311 plugin->get_count_any_stmt);
312 return 0;
313 }
314 if (SQLITE_ROW !=
315 sqlite3_step (plugin->get_count_any_stmt))
316 {
317 LOG_SQLITE (plugin->dbh,
318 GNUNET_ERROR_TYPE_ERROR,
319 "sqlite_step");
320 GNUNET_SQ_reset (plugin->dbh,
321 plugin->get_count_any_stmt);
322 LOG (GNUNET_ERROR_TYPE_DEBUG,
323 "No content found when processing GET for key `%s'\n",
324 GNUNET_h2s (key));
325 return 0;
326 }
327 total = sqlite3_column_int (plugin->get_count_any_stmt,
328 0);
329 GNUNET_SQ_reset (plugin->dbh,
330 plugin->get_count_any_stmt);
331 if ( (0 == total) ||
332 (NULL == iter) )
333 {
334 if (0 == total)
335 LOG (GNUNET_ERROR_TYPE_DEBUG,
336 "No content found when processing GET for key `%s'\n",
337 GNUNET_h2s (key));
338 return total;
339 }
340
341 cnt = 0;
342 block.key = *key;
343 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
344 total);
345 while (cnt < total)
346 {
347 off = (off + 1) % total;
348 if (GNUNET_OK !=
349 GNUNET_SQ_bind (plugin->get_any_stmt,
350 params_select))
351 {
352 LOG_SQLITE (plugin->dbh,
353 GNUNET_ERROR_TYPE_ERROR,
354 "sqlite3_bind_xxx");
355 GNUNET_SQ_reset (plugin->dbh,
356 plugin->get_any_stmt);
357 return cnt;
358 }
359 if (SQLITE_ROW !=
360 sqlite3_step (plugin->get_any_stmt))
361 break;
362 if (GNUNET_OK !=
363 GNUNET_SQ_extract_result (plugin->get_any_stmt,
364 rs))
365 {
366 GNUNET_break (0);
367 GNUNET_SQ_reset (plugin->dbh,
368 plugin->get_any_stmt);
369 break;
370 }
371 if (0 != path_size % sizeof(struct GNUNET_DHT_PathElement))
372 {
373 GNUNET_break (0);
374 path_size = 0;
375 path = NULL;
376 }
377 block.data = data;
378 block.put_path = path;
379 block.put_path_length = path_size / sizeof(struct GNUNET_DHT_PathElement);
380 block.type = (enum GNUNET_BLOCK_Type) btype32;
381 block.ro = (enum GNUNET_DHT_RouteOption) bro32;
382 cnt++;
383 LOG (GNUNET_ERROR_TYPE_DEBUG,
384 "Found %u-byte result when processing GET for key `%s'\n",
385 (unsigned int) block.data_size,
386 GNUNET_h2s (&block.key));
387 if (GNUNET_OK !=
388 iter (iter_cls,
389 &block))
390 {
391 GNUNET_SQ_cleanup_result (rs);
392 GNUNET_SQ_reset (plugin->dbh,
393 plugin->get_any_stmt);
394 break;
395 }
396 GNUNET_SQ_cleanup_result (rs);
397 GNUNET_SQ_reset (plugin->dbh,
398 plugin->get_any_stmt);
399 }
400 GNUNET_SQ_reset (plugin->dbh,
401 plugin->get_any_stmt);
402 return cnt;
237} 403}
238 404
239 405
@@ -249,67 +415,81 @@ sqlite_plugin_put (void *cls,
249 * @return the number of results found 415 * @return the number of results found
250 */ 416 */
251static unsigned int 417static unsigned int
252sqlite_plugin_get (void *cls, 418get_typed (void *cls,
253 const struct GNUNET_HashCode *key, 419 const struct GNUNET_HashCode *key,
254 enum GNUNET_BLOCK_Type type, 420 enum GNUNET_BLOCK_Type type,
255 GNUNET_DATACACHE_Iterator iter, 421 GNUNET_DATACACHE_Iterator iter,
256 void *iter_cls) 422 void *iter_cls)
257{ 423{
258 struct Plugin *plugin = cls; 424 struct Plugin *plugin = cls;
259 uint32_t type32 = type; 425 uint32_t type32 = type;
260 struct GNUNET_TIME_Absolute now; 426 struct GNUNET_TIME_Absolute now;
261 struct GNUNET_TIME_Absolute exp;
262 size_t size;
263 void *dat;
264 unsigned int cnt; 427 unsigned int cnt;
265 uint32_t off; 428 uint32_t off;
429 uint32_t bro32;
266 unsigned int total; 430 unsigned int total;
267 size_t psize; 431 struct GNUNET_DATACACHE_Block block;
268 struct GNUNET_DHT_PathElement *path; 432 void *path;
269 struct GNUNET_SQ_QueryParam params_count[] = 433 void *data;
270 { GNUNET_SQ_query_param_auto_from_type (key), 434 size_t path_size;
435 struct GNUNET_SQ_QueryParam params_count[] = {
436 GNUNET_SQ_query_param_auto_from_type (key),
271 GNUNET_SQ_query_param_uint32 (&type32), 437 GNUNET_SQ_query_param_uint32 (&type32),
272 GNUNET_SQ_query_param_absolute_time (&now), 438 GNUNET_SQ_query_param_absolute_time (&now),
273 GNUNET_SQ_query_param_end }; 439 GNUNET_SQ_query_param_end
274 struct GNUNET_SQ_QueryParam params_select[] = 440 };
275 { GNUNET_SQ_query_param_auto_from_type (key), 441 struct GNUNET_SQ_QueryParam params_select[] = {
442 GNUNET_SQ_query_param_auto_from_type (key),
276 GNUNET_SQ_query_param_uint32 (&type32), 443 GNUNET_SQ_query_param_uint32 (&type32),
277 GNUNET_SQ_query_param_absolute_time (&now), 444 GNUNET_SQ_query_param_absolute_time (&now),
278 GNUNET_SQ_query_param_uint32 (&off), 445 GNUNET_SQ_query_param_uint32 (&off),
279 GNUNET_SQ_query_param_end }; 446 GNUNET_SQ_query_param_end
280 struct GNUNET_SQ_ResultSpec rs[] = 447 };
281 { GNUNET_SQ_result_spec_variable_size (&dat, &size), 448 struct GNUNET_SQ_ResultSpec rs[] = {
282 GNUNET_SQ_result_spec_absolute_time (&exp), 449 GNUNET_SQ_result_spec_variable_size (&data,
283 GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize), 450 &block.data_size),
284 GNUNET_SQ_result_spec_end }; 451 GNUNET_SQ_result_spec_absolute_time (&block.expiration_time),
452 GNUNET_SQ_result_spec_variable_size (&path,
453 &path_size),
454 GNUNET_SQ_result_spec_uint32 (&bro32),
455 GNUNET_SQ_result_spec_end
456 };
285 457
286 now = GNUNET_TIME_absolute_get (); 458 now = GNUNET_TIME_absolute_get ();
287 LOG (GNUNET_ERROR_TYPE_DEBUG, 459 LOG (GNUNET_ERROR_TYPE_DEBUG,
288 "Processing GET for key `%s'\n", 460 "Processing GET for key `%s'\n",
289 GNUNET_h2s (key)); 461 GNUNET_h2s (key));
290 462
291 if (GNUNET_OK != GNUNET_SQ_bind (plugin->get_count_stmt, params_count)) 463 if (GNUNET_OK !=
464 GNUNET_SQ_bind (plugin->get_count_stmt,
465 params_count))
292 { 466 {
293 LOG_SQLITE (plugin->dbh, 467 LOG_SQLITE (plugin->dbh,
294 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 468 GNUNET_ERROR_TYPE_ERROR,
295 "sqlite3_bind_xxx"); 469 "sqlite3_bind_xxx");
296 GNUNET_SQ_reset (plugin->dbh, plugin->get_count_stmt); 470 GNUNET_SQ_reset (plugin->dbh,
471 plugin->get_count_stmt);
297 return 0; 472 return 0;
298 } 473 }
299 if (SQLITE_ROW != sqlite3_step (plugin->get_count_stmt)) 474 if (SQLITE_ROW !=
475 sqlite3_step (plugin->get_count_stmt))
300 { 476 {
301 LOG_SQLITE (plugin->dbh, 477 LOG_SQLITE (plugin->dbh,
302 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 478 GNUNET_ERROR_TYPE_ERROR,
303 "sqlite_step"); 479 "sqlite_step");
304 GNUNET_SQ_reset (plugin->dbh, plugin->get_count_stmt); 480 GNUNET_SQ_reset (plugin->dbh,
481 plugin->get_count_stmt);
305 LOG (GNUNET_ERROR_TYPE_DEBUG, 482 LOG (GNUNET_ERROR_TYPE_DEBUG,
306 "No content found when processing GET for key `%s'\n", 483 "No content found when processing GET for key `%s'\n",
307 GNUNET_h2s (key)); 484 GNUNET_h2s (key));
308 return 0; 485 return 0;
309 } 486 }
310 total = sqlite3_column_int (plugin->get_count_stmt, 0); 487 total = sqlite3_column_int (plugin->get_count_stmt,
311 GNUNET_SQ_reset (plugin->dbh, plugin->get_count_stmt); 488 0);
312 if ((0 == total) || (NULL == iter)) 489 GNUNET_SQ_reset (plugin->dbh,
490 plugin->get_count_stmt);
491 if ( (0 == total) ||
492 (NULL == iter) )
313 { 493 {
314 if (0 == total) 494 if (0 == total)
315 LOG (GNUNET_ERROR_TYPE_DEBUG, 495 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -319,129 +499,206 @@ sqlite_plugin_get (void *cls,
319 } 499 }
320 500
321 cnt = 0; 501 cnt = 0;
322 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total); 502 block.key = *key;
503 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
504 total);
323 while (cnt < total) 505 while (cnt < total)
324 { 506 {
325 off = (off + 1) % total; 507 off = (off + 1) % total;
326 if (GNUNET_OK != GNUNET_SQ_bind (plugin->get_stmt, params_select)) 508 if (GNUNET_OK !=
509 GNUNET_SQ_bind (plugin->get_stmt,
510 params_select))
327 { 511 {
328 LOG_SQLITE (plugin->dbh, 512 LOG_SQLITE (plugin->dbh,
329 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 513 GNUNET_ERROR_TYPE_ERROR,
330 "sqlite3_bind_xxx"); 514 "sqlite3_bind_xxx");
331 GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt); 515 GNUNET_SQ_reset (plugin->dbh,
516 plugin->get_stmt);
332 return cnt; 517 return cnt;
333 } 518 }
334 if (SQLITE_ROW != sqlite3_step (plugin->get_stmt)) 519 if (SQLITE_ROW !=
520 sqlite3_step (plugin->get_stmt))
335 break; 521 break;
336 if (GNUNET_OK != GNUNET_SQ_extract_result (plugin->get_stmt, rs)) 522 if (GNUNET_OK !=
523 GNUNET_SQ_extract_result (plugin->get_stmt,
524 rs))
337 { 525 {
338 GNUNET_break (0); 526 GNUNET_break (0);
339 GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt); 527 GNUNET_SQ_reset (plugin->dbh,
528 plugin->get_stmt);
340 break; 529 break;
341 } 530 }
342 if (0 != psize % sizeof(struct GNUNET_DHT_PathElement)) 531 if (0 != path_size % sizeof(struct GNUNET_DHT_PathElement))
343 { 532 {
344 GNUNET_break (0); 533 GNUNET_break (0);
345 psize = 0; 534 path_size = 0;
346 path = NULL; 535 path = NULL;
347 } 536 }
348 psize /= sizeof(struct GNUNET_DHT_PathElement); 537 block.data = data;
538 block.put_path = path;
539 block.put_path_length = path_size / sizeof(struct GNUNET_DHT_PathElement);
540 block.type = type;
541 block.ro = (enum GNUNET_DHT_RouteOption) bro32;
349 cnt++; 542 cnt++;
350 LOG (GNUNET_ERROR_TYPE_DEBUG, 543 LOG (GNUNET_ERROR_TYPE_DEBUG,
351 "Found %u-byte result when processing GET for key `%s'\n", 544 "Found %u-byte result when processing GET for key `%s'\n",
352 (unsigned int) size, 545 (unsigned int) block.data_size,
353 GNUNET_h2s (key)); 546 GNUNET_h2s (&block.key));
354 if (GNUNET_OK != iter (iter_cls, key, size, dat, type, exp, psize, path)) 547 if ( (NULL != iter) &&
548 (GNUNET_OK !=
549 iter (iter_cls,
550 &block)) )
355 { 551 {
356 GNUNET_SQ_cleanup_result (rs); 552 GNUNET_SQ_cleanup_result (rs);
357 GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt); 553 GNUNET_SQ_reset (plugin->dbh,
554 plugin->get_stmt);
358 break; 555 break;
359 } 556 }
360 GNUNET_SQ_cleanup_result (rs); 557 GNUNET_SQ_cleanup_result (rs);
361 GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt); 558 GNUNET_SQ_reset (plugin->dbh,
559 plugin->get_stmt);
362 } 560 }
363 GNUNET_SQ_reset (plugin->dbh, plugin->get_stmt); 561 GNUNET_SQ_reset (plugin->dbh,
562 plugin->get_stmt);
364 return cnt; 563 return cnt;
365} 564}
366 565
367 566
368/** 567/**
568 * Iterate over the results for a particular key
569 * in the datastore.
570 *
571 * @param cls closure (our `struct Plugin`)
572 * @param key
573 * @param type entries of which type are relevant?
574 * @param iter maybe NULL (to just count)
575 * @param iter_cls closure for @a iter
576 * @return the number of results found
577 */
578static unsigned int
579sqlite_plugin_get (void *cls,
580 const struct GNUNET_HashCode *key,
581 enum GNUNET_BLOCK_Type type,
582 GNUNET_DATACACHE_Iterator iter,
583 void *iter_cls)
584{
585 if (GNUNET_BLOCK_TYPE_ANY == type)
586 return get_any (cls,
587 key,
588 iter,
589 iter_cls);
590 return get_typed (cls,
591 key,
592 type,
593 iter,
594 iter_cls);
595}
596
597
598/**
369 * Delete the entry with the lowest expiration value 599 * Delete the entry with the lowest expiration value
370 * from the datacache right now. 600 * from the datacache right now.
371 * 601 *
372 * @param cls closure (our `struct Plugin`) 602 * @param cls closure (our `struct Plugin`)
373 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 603 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
374 */ 604 */
375static int 605static enum GNUNET_GenericReturnValue
376sqlite_plugin_del (void *cls) 606sqlite_plugin_del (void *cls)
377{ 607{
378 struct Plugin *plugin = cls; 608 struct Plugin *plugin = cls;
379 uint64_t rowid; 609 uint64_t rowid;
380 void *data; 610 void *data;
381 size_t dsize; 611 size_t data_size;
382 struct GNUNET_HashCode hc; 612 struct GNUNET_HashCode hc;
383 struct GNUNET_TIME_Absolute now; 613 struct GNUNET_TIME_Absolute now;
384 struct GNUNET_SQ_ResultSpec rs[] = 614 struct GNUNET_SQ_ResultSpec rs[] = {
385 { GNUNET_SQ_result_spec_uint64 (&rowid), 615 GNUNET_SQ_result_spec_uint64 (&rowid),
386 GNUNET_SQ_result_spec_auto_from_type (&hc), 616 GNUNET_SQ_result_spec_auto_from_type (&hc),
387 GNUNET_SQ_result_spec_variable_size ((void **) &data, &dsize), 617 GNUNET_SQ_result_spec_variable_size (&data,
388 GNUNET_SQ_result_spec_end }; 618 &data_size),
389 struct GNUNET_SQ_QueryParam params[] = { GNUNET_SQ_query_param_uint64 ( 619 GNUNET_SQ_result_spec_end
390 &rowid), 620 };
391 GNUNET_SQ_query_param_end }; 621 struct GNUNET_SQ_QueryParam params[] = {
392 struct GNUNET_SQ_QueryParam time_params[] = 622 GNUNET_SQ_query_param_uint64 (&rowid),
393 { GNUNET_SQ_query_param_absolute_time (&now), GNUNET_SQ_query_param_end }; 623 GNUNET_SQ_query_param_end
394 624 };
395 LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing DEL\n"); 625 struct GNUNET_SQ_QueryParam time_params[] = {
626 GNUNET_SQ_query_param_absolute_time (&now),
627 GNUNET_SQ_query_param_end
628 };
629
630 LOG (GNUNET_ERROR_TYPE_DEBUG,
631 "Processing DEL\n");
396 now = GNUNET_TIME_absolute_get (); 632 now = GNUNET_TIME_absolute_get ();
397 if (GNUNET_OK != GNUNET_SQ_bind (plugin->del_expired_stmt, time_params)) 633 if (GNUNET_OK !=
634 GNUNET_SQ_bind (plugin->del_expired_stmt,
635 time_params))
398 { 636 {
399 LOG_SQLITE (plugin->dbh, 637 LOG_SQLITE (plugin->dbh,
400 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 638 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
401 "sqlite3_bind"); 639 "sqlite3_bind");
402 GNUNET_SQ_reset (plugin->dbh, plugin->del_expired_stmt); 640 GNUNET_SQ_reset (plugin->dbh,
641 plugin->del_expired_stmt);
403 return GNUNET_SYSERR; 642 return GNUNET_SYSERR;
404 } 643 }
405 if ((SQLITE_ROW != sqlite3_step (plugin->del_expired_stmt)) || 644 if ( (SQLITE_ROW !=
406 (GNUNET_OK != GNUNET_SQ_extract_result (plugin->del_expired_stmt, rs))) 645 sqlite3_step (plugin->del_expired_stmt)) ||
646 (GNUNET_OK !=
647 GNUNET_SQ_extract_result (plugin->del_expired_stmt,
648 rs)))
407 { 649 {
408 GNUNET_SQ_reset (plugin->dbh, plugin->del_expired_stmt); 650 GNUNET_SQ_reset (plugin->dbh,
409 if (SQLITE_ROW != sqlite3_step (plugin->del_select_stmt)) 651 plugin->del_expired_stmt);
652 if (SQLITE_ROW !=
653 sqlite3_step (plugin->del_select_stmt))
410 { 654 {
411 LOG_SQLITE (plugin->dbh, 655 LOG_SQLITE (plugin->dbh,
412 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 656 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
413 "sqlite3_step"); 657 "sqlite3_step");
414 GNUNET_SQ_reset (plugin->dbh, plugin->del_select_stmt); 658 GNUNET_SQ_reset (plugin->dbh,
659 plugin->del_select_stmt);
415 return GNUNET_SYSERR; 660 return GNUNET_SYSERR;
416 } 661 }
417 if (GNUNET_OK != GNUNET_SQ_extract_result (plugin->del_select_stmt, rs)) 662 if (GNUNET_OK !=
663 GNUNET_SQ_extract_result (plugin->del_select_stmt,
664 rs))
418 { 665 {
419 GNUNET_SQ_reset (plugin->dbh, plugin->del_select_stmt); 666 GNUNET_SQ_reset (plugin->dbh,
667 plugin->del_select_stmt);
420 GNUNET_break (0); 668 GNUNET_break (0);
421 return GNUNET_SYSERR; 669 return GNUNET_SYSERR;
422 } 670 }
423 } 671 }
424 GNUNET_SQ_cleanup_result (rs); 672 GNUNET_SQ_cleanup_result (rs);
425 GNUNET_SQ_reset (plugin->dbh, plugin->del_select_stmt); 673 GNUNET_SQ_reset (plugin->dbh,
426 if (GNUNET_OK != GNUNET_SQ_bind (plugin->del_stmt, params)) 674 plugin->del_select_stmt);
675 if (GNUNET_OK !=
676 GNUNET_SQ_bind (plugin->del_stmt,
677 params))
427 { 678 {
428 LOG_SQLITE (plugin->dbh, 679 LOG_SQLITE (plugin->dbh,
429 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 680 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
430 "sqlite3_bind"); 681 "sqlite3_bind");
431 GNUNET_SQ_reset (plugin->dbh, plugin->del_stmt); 682 GNUNET_SQ_reset (plugin->dbh,
683 plugin->del_stmt);
432 return GNUNET_SYSERR; 684 return GNUNET_SYSERR;
433 } 685 }
434 if (SQLITE_DONE != sqlite3_step (plugin->del_stmt)) 686 if (SQLITE_DONE !=
687 sqlite3_step (plugin->del_stmt))
435 { 688 {
436 LOG_SQLITE (plugin->dbh, 689 LOG_SQLITE (plugin->dbh,
437 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 690 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
438 "sqlite3_step"); 691 "sqlite3_step");
439 GNUNET_SQ_reset (plugin->dbh, plugin->del_stmt); 692 GNUNET_SQ_reset (plugin->dbh,
693 plugin->del_stmt);
440 return GNUNET_SYSERR; 694 return GNUNET_SYSERR;
441 } 695 }
442 plugin->num_items--; 696 plugin->num_items--;
443 plugin->env->delete_notify (plugin->env->cls, &hc, dsize + OVERHEAD); 697 plugin->env->delete_notify (plugin->env->cls,
444 GNUNET_SQ_reset (plugin->dbh, plugin->del_stmt); 698 &hc,
699 data_size + OVERHEAD);
700 GNUNET_SQ_reset (plugin->dbh,
701 plugin->del_stmt);
445 return GNUNET_OK; 702 return GNUNET_OK;
446} 703}
447 704
@@ -472,14 +729,13 @@ sqlite_plugin_get_closest (void *cls,
472 uint32_t type32 = type; 729 uint32_t type32 = type;
473 uint32_t num_results32 = num_results; 730 uint32_t num_results32 = num_results;
474 struct GNUNET_TIME_Absolute now; 731 struct GNUNET_TIME_Absolute now;
475 struct GNUNET_TIME_Absolute exp; 732 void *data;
476 size_t size; 733 void *path;
477 void *dat; 734 size_t path_size;
478 unsigned int cnt; 735 unsigned int cnt;
479 size_t psize; 736 uint32_t bro32;
480 uint32_t rtype; 737 struct GNUNET_DATACACHE_Block block;
481 struct GNUNET_HashCode hc; 738 uint32_t rtype32;
482 struct GNUNET_DHT_PathElement *path;
483 struct GNUNET_SQ_QueryParam params[] = { 739 struct GNUNET_SQ_QueryParam params[] = {
484 GNUNET_SQ_query_param_auto_from_type (key), 740 GNUNET_SQ_query_param_auto_from_type (key),
485 GNUNET_SQ_query_param_absolute_time (&now), 741 GNUNET_SQ_query_param_absolute_time (&now),
@@ -488,11 +744,14 @@ sqlite_plugin_get_closest (void *cls,
488 GNUNET_SQ_query_param_end 744 GNUNET_SQ_query_param_end
489 }; 745 };
490 struct GNUNET_SQ_ResultSpec rs[] = { 746 struct GNUNET_SQ_ResultSpec rs[] = {
491 GNUNET_SQ_result_spec_variable_size (&dat, &size), 747 GNUNET_SQ_result_spec_variable_size (&data,
492 GNUNET_SQ_result_spec_absolute_time (&exp), 748 &block.data_size),
493 GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize), 749 GNUNET_SQ_result_spec_absolute_time (&block.expiration_time),
494 GNUNET_SQ_result_spec_uint32 (&rtype), 750 GNUNET_SQ_result_spec_variable_size (&path,
495 GNUNET_SQ_result_spec_auto_from_type (&hc), 751 &path_size),
752 GNUNET_SQ_result_spec_uint32 (&rtype32),
753 GNUNET_SQ_result_spec_uint32 (&bro32),
754 GNUNET_SQ_result_spec_auto_from_type (&block.key),
496 GNUNET_SQ_result_spec_end 755 GNUNET_SQ_result_spec_end
497 }; 756 };
498 757
@@ -512,7 +771,8 @@ sqlite_plugin_get_closest (void *cls,
512 return 0; 771 return 0;
513 } 772 }
514 cnt = 0; 773 cnt = 0;
515 while (SQLITE_ROW == sqlite3_step (plugin->get_closest_stmt)) 774 while (SQLITE_ROW ==
775 sqlite3_step (plugin->get_closest_stmt))
516 { 776 {
517 if (GNUNET_OK != 777 if (GNUNET_OK !=
518 GNUNET_SQ_extract_result (plugin->get_closest_stmt, 778 GNUNET_SQ_extract_result (plugin->get_closest_stmt,
@@ -521,26 +781,27 @@ sqlite_plugin_get_closest (void *cls,
521 GNUNET_break (0); 781 GNUNET_break (0);
522 break; 782 break;
523 } 783 }
524 if (0 != psize % sizeof(struct GNUNET_DHT_PathElement)) 784 if (0 != path_size % sizeof(struct GNUNET_DHT_PathElement))
525 { 785 {
526 GNUNET_break (0); 786 GNUNET_break (0);
527 psize = 0; 787 path_size = 0;
528 path = NULL; 788 path = NULL;
529 } 789 }
530 psize /= sizeof(struct GNUNET_DHT_PathElement); 790 block.put_path_length
791 = path_size / sizeof(struct GNUNET_DHT_PathElement);
792 block.put_path = path;
793 block.data = data;
794 block.type = (enum GNUNET_BLOCK_Type) rtype32;
795 block.ro = (enum GNUNET_DHT_RouteOption) bro32;
531 cnt++; 796 cnt++;
532 LOG (GNUNET_ERROR_TYPE_DEBUG, 797 LOG (GNUNET_ERROR_TYPE_DEBUG,
533 "Found %u-byte result at %s when processing GET_CLOSE\n", 798 "Found %u-byte result at %s when processing GET_CLOSE\n",
534 (unsigned int) size, 799 (unsigned int) block.data_size,
535 GNUNET_h2s (&hc)); 800 GNUNET_h2s (&block.key));
536 if (GNUNET_OK != iter (iter_cls, 801
537 &hc, 802 if (GNUNET_OK !=
538 size, 803 iter (iter_cls,
539 dat, 804 &block))
540 rtype,
541 exp,
542 psize,
543 path))
544 { 805 {
545 GNUNET_SQ_cleanup_result (rs); 806 GNUNET_SQ_cleanup_result (rs);
546 break; 807 break;
@@ -570,25 +831,30 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
570 sqlite3 *dbh; 831 sqlite3 *dbh;
571 char *emsg; 832 char *emsg;
572 833
573 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg, 834 if (GNUNET_YES ==
574 "datacache-sqlite", 835 GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
575 "IN_MEMORY")) 836 "datacache-sqlite",
837 "IN_MEMORY"))
576 { 838 {
577 if (SQLITE_OK != sqlite3_open (":memory:", &dbh)) 839 if (SQLITE_OK !=
840 sqlite3_open (":memory:",
841 &dbh))
578 return NULL; 842 return NULL;
579 fn_utf8 = NULL; 843 fn_utf8 = NULL;
580 } 844 }
581 else 845 else
582 { 846 {
583 fn = GNUNET_DISK_mktemp ("gnunet-datacache"); 847 fn = GNUNET_DISK_mktemp ("gnunet-datacache");
584 if (fn == NULL) 848 if (NULL == fn)
585 { 849 {
586 GNUNET_break (0); 850 GNUNET_break (0);
587 return NULL; 851 return NULL;
588 } 852 }
589 /* fn should be UTF-8-encoded. If it isn't, it's a bug. */ 853 /* fn should be UTF-8-encoded. If it isn't, it's a bug. */
590 fn_utf8 = GNUNET_strdup (fn); 854 fn_utf8 = GNUNET_strdup (fn);
591 if (SQLITE_OK != sqlite3_open (fn_utf8, &dbh)) 855 if (SQLITE_OK !=
856 sqlite3_open (fn_utf8,
857 &dbh))
592 { 858 {
593 GNUNET_free (fn); 859 GNUNET_free (fn);
594 GNUNET_free (fn_utf8); 860 GNUNET_free (fn_utf8);
@@ -602,22 +868,30 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
602 SQLITE3_EXEC (dbh, "PRAGMA journal_mode=OFF"); 868 SQLITE3_EXEC (dbh, "PRAGMA journal_mode=OFF");
603 SQLITE3_EXEC (dbh, "PRAGMA synchronous=OFF"); 869 SQLITE3_EXEC (dbh, "PRAGMA synchronous=OFF");
604 SQLITE3_EXEC (dbh, "PRAGMA page_size=4092"); 870 SQLITE3_EXEC (dbh, "PRAGMA page_size=4092");
605 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg, 871 if (GNUNET_YES ==
606 "datacache-sqlite", 872 GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
607 "IN_MEMORY")) 873 "datacache-sqlite",
874 "IN_MEMORY"))
608 SQLITE3_EXEC (dbh, "PRAGMA sqlite_temp_store=3"); 875 SQLITE3_EXEC (dbh, "PRAGMA sqlite_temp_store=3");
609 876
610 SQLITE3_EXEC (dbh, 877 SQLITE3_EXEC (dbh,
611 "CREATE TABLE ds091 (" 878 "CREATE TABLE ds180 ("
612 " type INTEGER NOT NULL DEFAULT 0," 879 " type INTEGER NOT NULL DEFAULT 0,"
880 " ro INTEGER NOT NULL DEFAULT 0,"
613 " expire INTEGER NOT NULL," 881 " expire INTEGER NOT NULL,"
614 " key BLOB NOT NULL DEFAULT ''," 882 " key BLOB NOT NULL DEFAULT '',"
615 " prox INTEGER NOT NULL," 883 " prox INTEGER NOT NULL,"
616 " value BLOB NOT NULL," 884 " value BLOB NOT NULL,"
617 " path BLOB DEFAULT '')"); 885 " path BLOB DEFAULT '')");
618 SQLITE3_EXEC (dbh, "CREATE INDEX idx_hashidx ON ds091 (key,type,expire)"); 886 SQLITE3_EXEC (dbh,
619 SQLITE3_EXEC (dbh, "CREATE INDEX idx_prox_expire ON ds091 (prox,expire)"); 887 "CREATE INDEX idx_hashidx"
620 SQLITE3_EXEC (dbh, "CREATE INDEX idx_expire_only ON ds091 (expire)"); 888 " ON ds180 (key,type,expire)");
889 SQLITE3_EXEC (dbh,
890 "CREATE INDEX idx_prox_expire"
891 " ON ds180 (prox,expire)");
892 SQLITE3_EXEC (dbh,
893 "CREATE INDEX idx_expire_only"
894 " ON ds180 (expire)");
621 plugin = GNUNET_new (struct Plugin); 895 plugin = GNUNET_new (struct Plugin);
622 plugin->env = env; 896 plugin->env = env;
623 plugin->dbh = dbh; 897 plugin->dbh = dbh;
@@ -625,41 +899,67 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
625 899
626 if ((SQLITE_OK != 900 if ((SQLITE_OK !=
627 sq_prepare (plugin->dbh, 901 sq_prepare (plugin->dbh,
628 "INSERT INTO ds091 (type, expire, key, prox, value, path) " 902 "INSERT INTO ds180"
629 "VALUES (?, ?, ?, ?, ?, ?)", 903 " (type, ro, expire, key, prox, value, path)"
904 " VALUES (?, ?, ?, ?, ?, ?, ?)",
630 &plugin->insert_stmt)) || 905 &plugin->insert_stmt)) ||
631 (SQLITE_OK != sq_prepare (plugin->dbh,
632 "SELECT count(*) FROM ds091 "
633 "WHERE key=? AND type=? AND expire >= ?",
634 &plugin->get_count_stmt)) ||
635 (SQLITE_OK != 906 (SQLITE_OK !=
636 sq_prepare (plugin->dbh, 907 sq_prepare (plugin->dbh,
637 "SELECT value,expire,path FROM ds091" 908 "SELECT COUNT(*) FROM ds180 "
638 " WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET ?", 909 "WHERE key=?"
910 " AND type=?"
911 " AND expire >= ?",
912 &plugin->get_count_stmt)) ||
913 (SQLITE_OK !=
914 sq_prepare (plugin->dbh,
915 "SELECT COUNT(*) FROM ds180 "
916 "WHERE key=? AND expire >= ?",
917 &plugin->get_count_any_stmt)) ||
918 (SQLITE_OK !=
919 sq_prepare (plugin->dbh,
920 "SELECT value,expire,path,ro"
921 " FROM ds180"
922 " WHERE key=?"
923 " AND type=?"
924 " AND expire >= ?"
925 " LIMIT 1 OFFSET ?",
639 &plugin->get_stmt)) || 926 &plugin->get_stmt)) ||
640 (SQLITE_OK != sq_prepare (plugin->dbh, 927 (SQLITE_OK !=
641 "SELECT _ROWID_,key,value FROM ds091" 928 sq_prepare (plugin->dbh,
642 " WHERE expire < ?1" 929 "SELECT value,expire,path,type,ro"
643 " ORDER BY expire ASC LIMIT 1", 930 " FROM ds180"
644 &plugin->del_expired_stmt)) || 931 " WHERE key=?"
645 (SQLITE_OK != sq_prepare (plugin->dbh, 932 " AND expire >= ?"
646 "SELECT _ROWID_,key,value FROM ds091" 933 " LIMIT 1 OFFSET ?",
647 " ORDER BY prox ASC, expire ASC LIMIT 1", 934 &plugin->get_any_stmt)) ||
648 &plugin->del_select_stmt)) || 935 (SQLITE_OK !=
649 (SQLITE_OK != sq_prepare (plugin->dbh, 936 sq_prepare (plugin->dbh,
650 "DELETE FROM ds091 WHERE _ROWID_=?", 937 "SELECT _ROWID_,key,value FROM ds180"
651 &plugin->del_stmt)) || 938 " WHERE expire < ?1"
939 " ORDER BY expire ASC LIMIT 1",
940 &plugin->del_expired_stmt)) ||
941 (SQLITE_OK !=
942 sq_prepare (plugin->dbh,
943 "SELECT _ROWID_,key,value FROM ds180"
944 " ORDER BY prox ASC, expire ASC LIMIT 1",
945 &plugin->del_select_stmt)) ||
946 (SQLITE_OK !=
947 sq_prepare (plugin->dbh,
948 "DELETE FROM ds180 WHERE _ROWID_=?",
949 &plugin->del_stmt)) ||
652 (SQLITE_OK != 950 (SQLITE_OK !=
653 sq_prepare (plugin->dbh, 951 sq_prepare (plugin->dbh,
654 "SELECT * FROM (" 952 "SELECT * FROM ("
655 " SELECT value,expire,path,type,key FROM ds091 " 953 " SELECT value,expire,path,type,ro,key"
954 " FROM ds180 "
656 " WHERE key>=?1 " 955 " WHERE key>=?1 "
657 " AND expire >= ?2" 956 " AND expire >= ?2"
658 " AND ( (type=?3) or (0 == ?3) )" 957 " AND ( (type=?3) or (0 == ?3) )"
659 " ORDER BY KEY ASC LIMIT ?4)" 958 " ORDER BY KEY ASC LIMIT ?4)"
660 "UNION " 959 "UNION "
661 "SELECT * FROM (" 960 "SELECT * FROM ("
662 " SELECT value,expire,path,type,key FROM ds091 " 961 " SELECT value,expire,path,type,ro,key"
962 " FROM ds180 "
663 " WHERE key<=?1 " 963 " WHERE key<=?1 "
664 " AND expire >= ?2" 964 " AND expire >= ?2"
665 " AND ( (type=?3) or (0 == ?3) )" 965 " AND ( (type=?3) or (0 == ?3) )"
@@ -669,7 +969,8 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
669 LOG_SQLITE (plugin->dbh, 969 LOG_SQLITE (plugin->dbh,
670 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 970 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
671 "sq_prepare"); 971 "sq_prepare");
672 GNUNET_break (SQLITE_OK == sqlite3_close (plugin->dbh)); 972 GNUNET_break (SQLITE_OK ==
973 sqlite3_close (plugin->dbh));
673 GNUNET_free (plugin); 974 GNUNET_free (plugin);
674 return NULL; 975 return NULL;
675 } 976 }
@@ -680,7 +981,8 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
680 api->put = &sqlite_plugin_put; 981 api->put = &sqlite_plugin_put;
681 api->del = &sqlite_plugin_del; 982 api->del = &sqlite_plugin_del;
682 api->get_closest = &sqlite_plugin_get_closest; 983 api->get_closest = &sqlite_plugin_get_closest;
683 LOG (GNUNET_ERROR_TYPE_INFO, "Sqlite datacache running\n"); 984 LOG (GNUNET_ERROR_TYPE_INFO,
985 "Sqlite datacache running\n");
684 return api; 986 return api;
685} 987}
686 988
@@ -703,13 +1005,18 @@ libgnunet_plugin_datacache_sqlite_done (void *cls)
703#endif 1005#endif
704 1006
705#if ! WINDOWS || defined(__CYGWIN__) 1007#if ! WINDOWS || defined(__CYGWIN__)
706 if ((NULL != plugin->fn) && (0 != unlink (plugin->fn))) 1008 if ( (NULL != plugin->fn) &&
707 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", plugin->fn); 1009 (0 != unlink (plugin->fn)) )
1010 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
1011 "unlink",
1012 plugin->fn);
708 GNUNET_free (plugin->fn); 1013 GNUNET_free (plugin->fn);
709#endif 1014#endif
710 sqlite3_finalize (plugin->insert_stmt); 1015 sqlite3_finalize (plugin->insert_stmt);
711 sqlite3_finalize (plugin->get_count_stmt); 1016 sqlite3_finalize (plugin->get_count_stmt);
1017 sqlite3_finalize (plugin->get_count_any_stmt);
712 sqlite3_finalize (plugin->get_stmt); 1018 sqlite3_finalize (plugin->get_stmt);
1019 sqlite3_finalize (plugin->get_any_stmt);
713 sqlite3_finalize (plugin->del_select_stmt); 1020 sqlite3_finalize (plugin->del_select_stmt);
714 sqlite3_finalize (plugin->del_expired_stmt); 1021 sqlite3_finalize (plugin->del_expired_stmt);
715 sqlite3_finalize (plugin->del_stmt); 1022 sqlite3_finalize (plugin->del_stmt);
@@ -721,7 +1028,8 @@ libgnunet_plugin_datacache_sqlite_done (void *cls)
721 LOG (GNUNET_ERROR_TYPE_WARNING, 1028 LOG (GNUNET_ERROR_TYPE_WARNING,
722 _ ( 1029 _ (
723 "Tried to close sqlite without finalizing all prepared statements.\n")); 1030 "Tried to close sqlite without finalizing all prepared statements.\n"));
724 stmt = sqlite3_next_stmt (plugin->dbh, NULL); 1031 stmt = sqlite3_next_stmt (plugin->dbh,
1032 NULL);
725 while (NULL != stmt) 1033 while (NULL != stmt)
726 { 1034 {
727 result = sqlite3_finalize (stmt); 1035 result = sqlite3_finalize (stmt);
@@ -730,13 +1038,16 @@ libgnunet_plugin_datacache_sqlite_done (void *cls)
730 "Failed to close statement %p: %d\n", 1038 "Failed to close statement %p: %d\n",
731 stmt, 1039 stmt,
732 result); 1040 result);
733 stmt = sqlite3_next_stmt (plugin->dbh, NULL); 1041 stmt = sqlite3_next_stmt (plugin->dbh,
1042 NULL);
734 } 1043 }
735 result = sqlite3_close (plugin->dbh); 1044 result = sqlite3_close (plugin->dbh);
736 } 1045 }
737#endif 1046#endif
738 if (SQLITE_OK != result) 1047 if (SQLITE_OK != result)
739 LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close"); 1048 LOG_SQLITE (plugin->dbh,
1049 GNUNET_ERROR_TYPE_ERROR,
1050 "sqlite3_close");
740 1051
741 GNUNET_free (plugin); 1052 GNUNET_free (plugin);
742 GNUNET_free (api); 1053 GNUNET_free (api);
diff --git a/src/datacache/plugin_datacache_template.c b/src/datacache/plugin_datacache_template.c
index 2f7b41dbe..1bd712d39 100644
--- a/src/datacache/plugin_datacache_template.c
+++ b/src/datacache/plugin_datacache_template.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2006, 2009, 2015 GNUnet e.V. 3 Copyright (C) 2006, 2009, 2015, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -44,26 +44,14 @@ struct Plugin
44 * Store an item in the datastore. 44 * Store an item in the datastore.
45 * 45 *
46 * @param cls closure (our `struct Plugin`) 46 * @param cls closure (our `struct Plugin`)
47 * @param key key to store @a data under
48 * @param xor_distance distance of @a key to our PID 47 * @param xor_distance distance of @a key to our PID
49 * @param size number of bytes in @a data 48 * @param block data to store
50 * @param data data to store
51 * @param type type of the value
52 * @param discard_time when to discard the value in any case
53 * @param path_info_len number of entries in @a path_info
54 * @param path_info a path through the network
55 * @return 0 if duplicate, -1 on error, number of bytes used otherwise 49 * @return 0 if duplicate, -1 on error, number of bytes used otherwise
56 */ 50 */
57static ssize_t 51static ssize_t
58template_plugin_put (void *cls, 52template_plugin_put (void *cls,
59 const struct GNUNET_HashCode *key,
60 uint32_t xor_distance, 53 uint32_t xor_distance,
61 size_t size, 54 const struct GNUNET_DATACACHE_Block *block)
62 const char *data,
63 enum GNUNET_BLOCK_Type type,
64 struct GNUNET_TIME_Absolute discard_time,
65 unsigned int path_info_len,
66 const struct GNUNET_DHT_PathElement *path_info)
67{ 55{
68 GNUNET_break (0); 56 GNUNET_break (0);
69 return -1; 57 return -1;
@@ -100,7 +88,7 @@ template_plugin_get (void *cls,
100 * @param cls closure (our `struct Plugin`) 88 * @param cls closure (our `struct Plugin`)
101 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 89 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
102 */ 90 */
103static int 91static enum GNUNET_GenericReturnValue
104template_plugin_del (void *cls) 92template_plugin_del (void *cls)
105{ 93{
106 GNUNET_break (0); 94 GNUNET_break (0);
diff --git a/src/datacache/test_datacache.c b/src/datacache/test_datacache.c
index 5740d2b7d..b5d978995 100644
--- a/src/datacache/test_datacache.c
+++ b/src/datacache/test_datacache.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2006, 2009, 2010 GNUnet e.V. 3 Copyright (C) 2006, 2009, 2010, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -39,26 +39,18 @@ static int ok;
39static const char *plugin_name; 39static const char *plugin_name;
40 40
41 41
42static int 42static enum GNUNET_GenericReturnValue
43checkIt (void *cls, 43checkIt (void *cls,
44 const struct GNUNET_HashCode *key, 44 const struct GNUNET_DATACACHE_Block *block)
45 size_t size, const char *data,
46 enum GNUNET_BLOCK_Type type,
47 struct GNUNET_TIME_Absolute exp,
48 unsigned int path_len,
49 const struct GNUNET_DHT_PathElement *path)
50{ 45{
51 (void) key; 46 if (block->data_size != sizeof(struct GNUNET_HashCode))
52 (void) type;
53 (void) exp;
54 (void) path_len;
55 (void) path;
56 if (size != sizeof(struct GNUNET_HashCode))
57 { 47 {
58 GNUNET_break (0); 48 GNUNET_break (0);
59 ok = 2; 49 ok = 2;
60 } 50 }
61 if (0 != memcmp (data, cls, size)) 51 if (0 != memcmp (block->data,
52 cls,
53 block->data_size))
62 { 54 {
63 GNUNET_break (0); 55 GNUNET_break (0);
64 ok = 3; 56 ok = 3;
@@ -74,9 +66,9 @@ run (void *cls,
74 const struct GNUNET_CONFIGURATION_Handle *cfg) 66 const struct GNUNET_CONFIGURATION_Handle *cfg)
75{ 67{
76 struct GNUNET_DATACACHE_Handle *h; 68 struct GNUNET_DATACACHE_Handle *h;
69 struct GNUNET_DATACACHE_Block block;
77 struct GNUNET_HashCode k; 70 struct GNUNET_HashCode k;
78 struct GNUNET_HashCode n; 71 struct GNUNET_HashCode n;
79 struct GNUNET_TIME_Absolute exp;
80 72
81 (void) cls; 73 (void) cls;
82 (void) args; 74 (void) args;
@@ -84,7 +76,7 @@ run (void *cls,
84 ok = 0; 76 ok = 0;
85 h = GNUNET_DATACACHE_create (cfg, 77 h = GNUNET_DATACACHE_create (cfg,
86 "testcache"); 78 "testcache");
87 if (h == NULL) 79 if (NULL == h)
88 { 80 {
89 fprintf (stderr, 81 fprintf (stderr,
90 "%s", 82 "%s",
@@ -92,19 +84,28 @@ run (void *cls,
92 ok = 77; /* mark test as skipped */ 84 ok = 77; /* mark test as skipped */
93 return; 85 return;
94 } 86 }
95 exp = GNUNET_TIME_absolute_get (); 87 block.expiration_time = GNUNET_TIME_absolute_get ();
96 exp.abs_value_us += 5 * 60 * 1000 * 1000LL; 88 block.expiration_time.abs_value_us += 5 * 60 * 1000 * 1000LL;
97 memset (&k, 0, sizeof(struct GNUNET_HashCode)); 89 memset (&k,
90 0,
91 sizeof(struct GNUNET_HashCode));
98 for (unsigned int i = 0; i < 100; i++) 92 for (unsigned int i = 0; i < 100; i++)
99 { 93 {
100 GNUNET_CRYPTO_hash (&k, sizeof(struct GNUNET_HashCode), &n); 94 GNUNET_CRYPTO_hash (&k,
95 sizeof(struct GNUNET_HashCode),
96 &n);
97 block.key = k;
98 block.data = &n;
99 block.data_size = sizeof (n);
100 block.ro = 42;
101 block.type = (enum GNUNET_BLOCK_Type) (1 + i % 16);
102 block.put_path = NULL;
103 block.put_path_length = 0;
104 block.ro = GNUNET_DHT_RO_RECORD_ROUTE;
101 ASSERT (GNUNET_OK == 105 ASSERT (GNUNET_OK ==
102 GNUNET_DATACACHE_put (h, 106 GNUNET_DATACACHE_put (h,
103 &k, 107 42,
104 GNUNET_YES, 108 &block));
105 sizeof(struct GNUNET_HashCode),
106 (const char *) &n, 1 + i % 16, exp,
107 0, NULL));
108 k = n; 109 k = n;
109 } 110 }
110 memset (&k, 111 memset (&k,
@@ -117,7 +118,7 @@ run (void *cls,
117 &n); 118 &n);
118 ASSERT (1 == GNUNET_DATACACHE_get (h, 119 ASSERT (1 == GNUNET_DATACACHE_get (h,
119 &k, 120 &k,
120 1 + i % 16, 121 (enum GNUNET_BLOCK_Type) (1 + i % 16),
121 &checkIt, 122 &checkIt,
122 &n)); 123 &n));
123 k = n; 124 k = n;
@@ -129,16 +130,19 @@ run (void *cls,
129 GNUNET_CRYPTO_hash (&k, 130 GNUNET_CRYPTO_hash (&k,
130 sizeof(struct GNUNET_HashCode), 131 sizeof(struct GNUNET_HashCode),
131 &n); 132 &n);
133 block.key = k;
134 block.data = &n;
135 block.data_size = sizeof (n);
136 block.ro = 42;
137 block.type = (enum GNUNET_BLOCK_Type) 792;
138 block.put_path = NULL;
139 block.put_path_length = 0;
140 block.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS;
141 block.ro = GNUNET_DHT_RO_RECORD_ROUTE;
132 ASSERT (GNUNET_OK == 142 ASSERT (GNUNET_OK ==
133 GNUNET_DATACACHE_put (h, 143 GNUNET_DATACACHE_put (h,
134 &k, 144 42,
135 GNUNET_YES, 145 &block));
136 sizeof(struct GNUNET_HashCode),
137 (const char *) &n,
138 792,
139 GNUNET_TIME_UNIT_FOREVER_ABS,
140 0,
141 NULL));
142 ASSERT (0 != GNUNET_DATACACHE_get (h, 146 ASSERT (0 != GNUNET_DATACACHE_get (h,
143 &k, 147 &k,
144 792, 148 792,
diff --git a/src/datacache/test_datacache_quota.c b/src/datacache/test_datacache_quota.c
index 92807fbe2..0b647ee99 100644
--- a/src/datacache/test_datacache_quota.c
+++ b/src/datacache/test_datacache_quota.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2006, 2009, 2010 GNUnet e.V. 3 Copyright (C) 2006, 2009, 2010, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -53,8 +53,8 @@ run (void *cls,
53 struct GNUNET_DATACACHE_Handle *h; 53 struct GNUNET_DATACACHE_Handle *h;
54 struct GNUNET_HashCode k; 54 struct GNUNET_HashCode k;
55 struct GNUNET_HashCode n; 55 struct GNUNET_HashCode n;
56 struct GNUNET_DATACACHE_Block block;
56 char buf[3200]; 57 char buf[3200];
57 struct GNUNET_TIME_Absolute exp;
58 58
59 (void) cls; 59 (void) cls;
60 (void) args; 60 (void) args;
@@ -70,9 +70,14 @@ run (void *cls,
70 "Failed to initialize datacache. Database likely not setup, skipping test.\n"); 70 "Failed to initialize datacache. Database likely not setup, skipping test.\n");
71 return; 71 return;
72 } 72 }
73 exp = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS); 73 block.expiration_time = GNUNET_TIME_relative_to_absolute (
74 memset (buf, 1, sizeof(buf)); 74 GNUNET_TIME_UNIT_HOURS);
75 memset (&k, 0, sizeof(struct GNUNET_HashCode)); 75 memset (buf,
76 1,
77 sizeof(buf));
78 memset (&k,
79 0,
80 sizeof(struct GNUNET_HashCode));
76 for (unsigned int i = 0; i < 10; i++) 81 for (unsigned int i = 0; i < 10; i++)
77 { 82 {
78 fprintf (stderr, 83 fprintf (stderr,
@@ -83,35 +88,56 @@ run (void *cls,
83 &n); 88 &n);
84 for (unsigned int j = i; j < sizeof(buf); j += 10) 89 for (unsigned int j = i; j < sizeof(buf); j += 10)
85 { 90 {
86 exp.abs_value_us++;
87 buf[j] = i; 91 buf[j] = i;
92 block.key = k;
93 block.data = buf;
94 block.data_size = j;
95 block.ro = 42;
96 block.type = (enum GNUNET_BLOCK_Type) (1 + i);
97 block.put_path = NULL;
98 block.put_path_length = 0;
99 block.ro = GNUNET_DHT_RO_RECORD_ROUTE;
100 block.expiration_time.abs_value_us++;
88 ASSERT (GNUNET_OK == 101 ASSERT (GNUNET_OK ==
89 GNUNET_DATACACHE_put (h, 102 GNUNET_DATACACHE_put (h,
90 &k, 103 42,
91 GNUNET_YES, 104 &block));
92 j, 105 ASSERT (0 < GNUNET_DATACACHE_get (h,
93 buf, 106 &k,
94 1 + i, 107 1 + i,
95 exp, 108 NULL,
96 0, 109 NULL));
97 NULL));
98 ASSERT (0 < GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL));
99 } 110 }
100 k = n; 111 k = n;
101 } 112 }
102 fprintf (stderr, "%s", "\n"); 113 fprintf (stderr, "%s", "\n");
103 memset (&k, 0, sizeof(struct GNUNET_HashCode)); 114 memset (&k,
115 0,
116 sizeof(struct GNUNET_HashCode));
104 for (unsigned int i = 0; i < 10; i++) 117 for (unsigned int i = 0; i < 10; i++)
105 { 118 {
106 fprintf (stderr, "%s", "."); 119 fprintf (stderr, "%s", ".");
107 GNUNET_CRYPTO_hash (&k, sizeof(struct GNUNET_HashCode), &n); 120 GNUNET_CRYPTO_hash (&k,
121 sizeof(struct GNUNET_HashCode),
122 &n);
108 if (i < 2) 123 if (i < 2)
109 ASSERT (0 == GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL)); 124 ASSERT (0 ==
125 GNUNET_DATACACHE_get (h,
126 &k,
127 1 + i,
128 NULL,
129 NULL));
110 if (i == 9) 130 if (i == 9)
111 ASSERT (0 < GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL)); 131 ASSERT (0 < GNUNET_DATACACHE_get (h,
132 &k,
133 1 + i,
134 NULL,
135 NULL));
112 k = n; 136 k = n;
113 } 137 }
114 fprintf (stderr, "%s", "\n"); 138 fprintf (stderr,
139 "%s",
140 "\n");
115 GNUNET_DATACACHE_destroy (h); 141 GNUNET_DATACACHE_destroy (h);
116 return; 142 return;
117FAILURE: 143FAILURE: