GNUnet 0.28.1-dev.5-1-gae1c02d74
 
Loading...
Searching...
No Matches
plugin_datacache_heap.c File Reference

heap-only implementation of a database backend for the datacache More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_datacache_plugin.h"
Include dependency graph for plugin_datacache_heap.c:

Go to the source code of this file.

Data Structures

struct  Plugin
 Handle for a plugin. More...
 
struct  Value
 Entry in the hash map. More...
 
struct  PutContext
 Closure for put_cb(). More...
 
struct  GetContext
 Closure for get_cb(). More...
 
struct  GetClosestContext
 Closure for find_closest(). More...
 

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "datacache-heap", __VA_ARGS__)
 
#define LOG_STRERROR_FILE(kind, op, fn)
 
#define NUM_HEAPS   24
 
#define OVERHEAD   (sizeof(struct Value) + 64)
 

Functions

static enum GNUNET_GenericReturnValue put_cb (void *cls, const struct GNUNET_HashCode *key, void *value)
 Function called during PUT to detect if an equivalent block already exists.
 
static ssize_t heap_plugin_put (void *cls, uint32_t xor_distance, const struct GNUNET_DATACACHE_Block *block)
 Store an item in the datastore.
 
static enum GNUNET_GenericReturnValue get_cb (void *cls, const struct GNUNET_HashCode *key, void *value)
 Function called during GET to find matching blocks.
 
static int cmp_expiration (const void *a, const void *b)
 Sort values by expiration time, latest first.
 
static unsigned int heap_plugin_get (void *cls, const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, GNUNET_DATACACHE_Iterator iter, void *iter_cls)
 Iterate over the results for a particular key in the datastore.
 
static enum GNUNET_GenericReturnValue heap_plugin_del (void *cls)
 Delete the entry with the lowest expiration value from the datacache right now.
 
static enum GNUNET_GenericReturnValue find_closest (void *cls, const struct GNUNET_HashCode *key, void *value)
 
static unsigned int heap_plugin_get_closest (void *cls, const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, unsigned int num_results, GNUNET_DATACACHE_Iterator iter, void *iter_cls)
 Iterate over the results that are "close" to a particular key in the datacache.
 
void * libgnunet_plugin_datacache_heap_init (void *cls)
 Entry point for the plugin.
 
void * libgnunet_plugin_datacache_heap_done (void *cls)
 Exit point from the plugin.
 

Detailed Description

heap-only implementation of a database backend for the datacache

Author
Christian Grothoff

Definition in file plugin_datacache_heap.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "datacache-heap", __VA_ARGS__)

Definition at line 30 of file plugin_datacache_heap.c.

◆ LOG_STRERROR_FILE

#define LOG_STRERROR_FILE (   kind,
  op,
  fn 
)
Value:
"datacache-heap", \
op, fn)
static struct GNUNET_ARM_Operation * op
Current operation.
Definition gnunet-arm.c:143
#define GNUNET_log_from_strerror_file(level, component, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...

Definition at line 32 of file plugin_datacache_heap.c.

41{
46
51
55 struct GNUNET_CONTAINER_Heap *heaps[NUM_HEAPS];
56};
57
58
62struct Value
63{
68
73
78
82 uint32_t distance;
83
84};
85
86
87#define OVERHEAD (sizeof(struct Value) + 64)
88
89
93struct PutContext
94{
98 const struct GNUNET_DATACACHE_Block *block;
99
103 bool found;
104};
105
106
117put_cb (void *cls,
118 const struct GNUNET_HashCode *key,
119 void *value)
120{
121 struct PutContext *put_ctx = cls;
122 struct Value *val = value;
123
124 if ((val->block.data_size == put_ctx->block->data_size) &&
125 (val->block.type == put_ctx->block->type) &&
126 (0 == memcmp (val->block.data,
127 put_ctx->block->data,
128 put_ctx->block->data_size)))
129 {
130 put_ctx->found = true;
133 put_ctx->block->expiration_time);
134 /* replace old path with new path */
135 GNUNET_free (val->put_path);
136 val->put_path = GNUNET_memdup (put_ctx->block->put_path,
137 put_ctx->block->put_path_length
138 * sizeof (struct GNUNET_DHT_PathElement));
139 val->block.put_path = val->put_path;
144 "Got same value for key %s and type %u (size %u vs %u)\n",
145 GNUNET_h2s (key),
146 (unsigned int) val->block.type,
147 (unsigned int) val->block.data_size,
148 (unsigned int) put_ctx->block->data_size);
149 return GNUNET_NO;
150 }
151 return GNUNET_YES;
152}
153
154
163static ssize_t
164heap_plugin_put (void *cls,
165 uint32_t xor_distance,
166 const struct GNUNET_DATACACHE_Block *block)
167{
168 struct Plugin *plugin = cls;
169 struct Value *val;
170 struct PutContext put_ctx = {
171 .block = block,
172 .found = false
173 };
174
176 "Storing %u bytes under key %s with path length %u\n",
177 (unsigned int) block->data_size,
178 GNUNET_h2s (&block->key),
181 &block->key,
182 &put_cb,
183 &put_ctx);
184 if (GNUNET_YES == put_ctx.found)
185 return 0;
186 val = GNUNET_malloc (sizeof(struct Value)
187 + block->data_size);
188 GNUNET_memcpy (&val[1],
189 block->data,
191 val->block = *block;
192 val->block.data = &val[1];
193 if (xor_distance >= NUM_HEAPS)
194 val->distance = NUM_HEAPS - 1;
195 else
196 val->distance = xor_distance;
197 if (0 != block->put_path_length)
198 {
199 val->put_path
202 * sizeof (struct GNUNET_DHT_PathElement));
203 val->block.put_path = val->put_path;
204 }
206 &val->block.key,
207 val,
210 plugin->heaps[val->distance],
211 val,
213 return val->block.data_size + OVERHEAD;
214}
215
216
220struct GetContext
221{
226 struct Value **values;
227
231 unsigned int cnt;
232
237};
238
239
250get_cb (void *cls,
251 const struct GNUNET_HashCode *key,
252 void *value)
253{
254 struct GetContext *get_ctx = cls;
255 struct Value *val = value;
256
257 if ( (get_ctx->type != val->block.type) &&
258 (GNUNET_BLOCK_TYPE_ANY != get_ctx->type) )
259 {
261 "Result for key %s does not match block type %d\n",
262 GNUNET_h2s (key),
263 get_ctx->type);
264 return GNUNET_OK;
265 }
267 {
269 "Result for key %s is expired\n",
270 GNUNET_h2s (key));
271 return GNUNET_OK;
272 }
274 "Found result for key %s\n",
275 GNUNET_h2s (key));
276 GNUNET_array_append (get_ctx->values,
277 get_ctx->cnt,
278 val);
279 return GNUNET_OK;
280}
281
282
286static int
287cmp_expiration (const void *a,
288 const void *b)
289{
290 const struct Value *va = *(struct Value **) a;
291 const struct Value *vb = *(struct Value **) b;
292
295 return -1;
298 return 1;
299 return 0;
300}
301
302
314static unsigned int
315heap_plugin_get (void *cls,
316 const struct GNUNET_HashCode *key,
319 void *iter_cls)
320{
321 struct Plugin *plugin = cls;
322 struct GetContext get_ctx = {
323 .type = type
324 };
325 unsigned int ret;
326
328 key,
329 &get_cb,
330 &get_ctx);
331 /* Hand out the freshest block first: a key may hold several
332 versions of the same (mutable) block, and a requester that stops
333 at the first reply must not be given a nearly expired one. */
334 qsort (get_ctx.values,
335 get_ctx.cnt,
336 sizeof (struct Value *),
338 ret = 0;
339 for (unsigned int i = 0; i < get_ctx.cnt; i++)
340 {
341 ret++;
342 if ( (NULL != iter) &&
343 (GNUNET_OK != iter (iter_cls,
344 &get_ctx.values[i]->block)) )
345 break;
346 }
347 GNUNET_array_grow (get_ctx.values,
348 get_ctx.cnt,
349 0);
350 return ret;
351}
352
353
362heap_plugin_del (void *cls)
363{
364 struct Plugin *plugin = cls;
365 struct Value *val;
366
367 for (unsigned int i = 0; i < NUM_HEAPS; i++)
368 {
370 if (NULL != val)
371 break;
372 }
373 if (NULL == val)
374 return GNUNET_SYSERR;
377 &val->block.key,
378 val));
379 plugin->env->delete_notify (plugin->env->cls,
380 &val->block.key,
381 val->block.data_size + OVERHEAD);
382 GNUNET_free (val->put_path);
383 GNUNET_free (val);
384 return GNUNET_OK;
385}
386
387
392{
393 struct Value **values;
394
395 const struct GNUNET_HashCode *key;
396
398
399 unsigned int num_results;
400
401};
402
403
405find_closest (void *cls,
406 const struct GNUNET_HashCode *key,
407 void *value)
408{
409 struct GetClosestContext *gcc = cls;
410 struct Value *val = value;
411 unsigned int j;
412
413 if (1 != GNUNET_CRYPTO_hash_cmp (key,
414 gcc->key))
415 return GNUNET_OK; /* useless */
416 if ( (val->block.type != gcc->type) &&
417 (GNUNET_BLOCK_TYPE_ANY != gcc->type) )
418 return GNUNET_OK; /* useless */
419 j = gcc->num_results;
420 for (unsigned int i = 0; i < gcc->num_results; i++)
421 {
422 if (NULL == gcc->values[i])
423 {
424 j = i;
425 break;
426 }
427 if (1 ==
429 key))
430 {
431 j = i;
432 break;
433 }
434 }
435 if (j == gcc->num_results)
436 return GNUNET_OK;
437 gcc->values[j] = val;
438 return GNUNET_OK;
439}
440
441
456static unsigned int
457heap_plugin_get_closest (void *cls,
458 const struct GNUNET_HashCode *key,
460 unsigned int num_results,
462 void *iter_cls)
463{
464 struct Plugin *plugin = cls;
465 struct Value *values[num_results];
466 struct GetClosestContext gcc = {
467 .values = values,
468 .type = type,
469 .num_results = num_results * 2,
470 .key = key
471 };
472
475 &gcc);
476 for (unsigned int i = 0; i < num_results * 2; i++)
477 {
478 if (NULL == values[i])
479 return i;
480 if ( (NULL != iter) &&
481 (GNUNET_SYSERR ==
482 iter (iter_cls,
483 &values[i]->block)) )
484 {
486 "Ending iteration (client error)\n");
487 return i;
488 }
489 }
490 return num_results * 2;
491}
492
493
494void *
496
503void *
505{
508 struct Plugin *plugin;
509
510 plugin = GNUNET_new (struct Plugin);
511 plugin->map = GNUNET_CONTAINER_multihashmap_create (1024, /* FIXME: base on quota! */
512 GNUNET_YES);
513 for (unsigned int i = 0; i < NUM_HEAPS; i++)
516 plugin->env = env;
518 api->cls = plugin;
519 api->get = &heap_plugin_get;
520 api->put = &heap_plugin_put;
521 api->del = &heap_plugin_del;
522 api->get_closest = &heap_plugin_get_closest;
524 _ ("Heap datacache running\n"));
525 return api;
526}
527
528
529void *
531
538void *
540{
542 struct Plugin *plugin = api->cls;
543 struct Value *val;
544
545 for (unsigned int i = 0; i < NUM_HEAPS; i++)
546 {
547 while (NULL != (val = GNUNET_CONTAINER_heap_remove_root (plugin->heaps[i])))
548 {
551 &val->block.key,
552 val));
553 GNUNET_free (val->put_path);
554 GNUNET_free (val);
555 }
557 }
560 GNUNET_free (api);
561 return NULL;
562}
563
564
565/* end of plugin_datacache_heap.c */
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
static int ret
Final status code.
Definition gnunet-arm.c:93
static struct GNUNET_TESTING_PluginFunctions * plugin
Plugin to dynamically load a test case.
struct GNUNET_HashCode key
The key used in the DHT.
static char * value
Value of the record to add/remove.
static uint32_t type
Type string converted to DNS type value.
static struct GNUNET_CONTAINER_MultiHashMap * values
Collection of all values (represented with ValueSet).
GNUNET_BLOCK_Type
WARNING: This header is generated! In order to add DHT block types, you must register them in GANA,...
@ GNUNET_BLOCK_TYPE_ANY
Identifier for any block.
enum GNUNET_GenericReturnValue(* GNUNET_DATACACHE_Iterator)(void *cls, const struct GNUNET_DATACACHE_Block *block)
An iterator over a set of items stored in the datacache.
int GNUNET_CRYPTO_hash_cmp(const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2)
Compare function for HashCodes, producing a total ordering of all hashcodes.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_get_multiple(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
void GNUNET_CONTAINER_heap_update_cost(struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost)
Updates the cost of any node in the tree.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition time.c:368
bool GNUNET_TIME_absolute_is_past(struct GNUNET_TIME_Absolute abs)
Test if abs is truly in the past (excluding now).
Definition time.c:667
static struct GNUNET_CONTAINER_MultiPeerMap * map
Peermap of PeerIdentities to "struct PeerEntry" (for fast lookup).
Definition peer.c:63
#define _(String)
GNU gettext support macro.
Definition platform.h:179
static int cmp_expiration(const void *a, const void *b)
Sort values by expiration time, latest first.
static enum GNUNET_GenericReturnValue get_cb(void *cls, const struct GNUNET_HashCode *key, void *value)
Function called during GET to find matching blocks.
void * libgnunet_plugin_datacache_heap_init(void *cls)
Entry point for the plugin.
#define OVERHEAD
static enum GNUNET_GenericReturnValue put_cb(void *cls, const struct GNUNET_HashCode *key, void *value)
Function called during PUT to detect if an equivalent block already exists.
static unsigned int heap_plugin_get(void *cls, const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, GNUNET_DATACACHE_Iterator iter, void *iter_cls)
Iterate over the results for a particular key in the datastore.
static unsigned int heap_plugin_get_closest(void *cls, const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, unsigned int num_results, GNUNET_DATACACHE_Iterator iter, void *iter_cls)
Iterate over the results that are "close" to a particular key in the datacache.
static enum GNUNET_GenericReturnValue find_closest(void *cls, const struct GNUNET_HashCode *key, void *value)
#define NUM_HEAPS
void * libgnunet_plugin_datacache_heap_done(void *cls)
Exit point from the plugin.
static enum GNUNET_GenericReturnValue heap_plugin_del(void *cls)
Delete the entry with the lowest expiration value from the datacache right now.
static ssize_t heap_plugin_put(void *cls, uint32_t xor_distance, const struct GNUNET_DATACACHE_Block *block)
Store an item in the datastore.
#define LOG(kind,...)
void * cls
Closure for all of the callbacks.
Handle to a node in a heap.
Internal representation of the hash map.
Information about a block stored in the datacache.
const struct GNUNET_DHT_PathElement * put_path
PUT path taken by the block, array of peer identities.
enum GNUNET_BLOCK_Type type
Type of the block.
const void * data
Actual block data.
struct GNUNET_HashCode key
Key of the block.
size_t data_size
Number of bytes in data.
unsigned int put_path_length
Length of the put_path array.
struct GNUNET_TIME_Absolute expiration_time
When does the block expire?
The datastore service will pass a pointer to a struct of this type as the first and only argument to ...
void * cls
Closure to use for callbacks.
struct returned by the initialization function of the plugin
void * cls
Closure to pass to all plugin functions.
A (signed) path tracking a block's flow through the DHT is represented by an array of path elements,...
A 512-bit hashcode.
void * cls
Closure to pass to start_testcase.
uint64_t abs_value_us
The actual value.
Closure for find_closest().
enum GNUNET_BLOCK_Type type
const struct GNUNET_HashCode * key
Closure for get_cb().
enum GNUNET_BLOCK_Type type
Block type requested.
struct Value ** values
Matching values, collected before they are handed to the iterator so that they can be sorted by expir...
unsigned int cnt
Number of entries in values.
Handle for a plugin.
Definition block.c:38
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition block.c:47
Closure for put_cb().
const struct GNUNET_DATACACHE_Block * block
Block data.
bool found
Value to set to true if an equivalent block was found.
Entry in the hash map.
struct GNUNET_CONTAINER_HeapNode * hn
Corresponding node in the heap.
struct GNUNET_DATACACHE_Block block
Block data.
struct GNUNET_DHT_PathElement * put_path
Put path as a non-const pointer.
uint32_t distance
How close is the hash to us? Determines which heap we are in!

◆ NUM_HEAPS

#define NUM_HEAPS   24

Definition at line 36 of file plugin_datacache_heap.c.

◆ OVERHEAD

#define OVERHEAD   (sizeof(struct Value) + 64)

Definition at line 88 of file plugin_datacache_heap.c.

Function Documentation

◆ put_cb()

static enum GNUNET_GenericReturnValue put_cb ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Function called during PUT to detect if an equivalent block already exists.

Parameters
clsthe struct PutContext
keythe key for the value(s)
valuean existing value
Returns
GNUNET_YES if not found (to continue to iterate)

Definition at line 118 of file plugin_datacache_heap.c.

121{
122 struct PutContext *put_ctx = cls;
123 struct Value *val = value;
124
125 if ((val->block.data_size == put_ctx->block->data_size) &&
126 (val->block.type == put_ctx->block->type) &&
127 (0 == memcmp (val->block.data,
128 put_ctx->block->data,
129 put_ctx->block->data_size)))
130 {
131 put_ctx->found = true;
134 put_ctx->block->expiration_time);
135 /* replace old path with new path */
136 GNUNET_free (val->put_path);
137 val->put_path = GNUNET_memdup (put_ctx->block->put_path,
138 put_ctx->block->put_path_length
139 * sizeof (struct GNUNET_DHT_PathElement));
140 val->block.put_path = val->put_path;
145 "Got same value for key %s and type %u (size %u vs %u)\n",
146 GNUNET_h2s (key),
147 (unsigned int) val->block.type,
148 (unsigned int) val->block.data_size,
149 (unsigned int) put_ctx->block->data_size);
150 return GNUNET_NO;
151 }
152 return GNUNET_YES;
153}

References GNUNET_TIME_Absolute::abs_value_us, Value::block, PutContext::block, GNUNET_DATACACHE_Block::data, GNUNET_DATACACHE_Block::data_size, GNUNET_DATACACHE_Block::expiration_time, PutContext::found, GNUNET_CONTAINER_heap_update_cost(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_h2s(), GNUNET_log, GNUNET_memdup, GNUNET_NO, GNUNET_TIME_absolute_max(), GNUNET_YES, Value::hn, key, GNUNET_DATACACHE_Block::put_path, Value::put_path, GNUNET_DATACACHE_Block::put_path_length, GNUNET_DATACACHE_Block::type, and value.

Referenced by heap_plugin_put().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ heap_plugin_put()

static ssize_t heap_plugin_put ( void *  cls,
uint32_t  xor_distance,
const struct GNUNET_DATACACHE_Block block 
)
static

Store an item in the datastore.

Parameters
clsclosure (our struct Plugin)
xor_distancehow close is key to our PID?
blockdata to store
Returns
0 if duplicate, -1 on error, number of bytes used otherwise

Definition at line 165 of file plugin_datacache_heap.c.

168{
169 struct Plugin *plugin = cls;
170 struct Value *val;
171 struct PutContext put_ctx = {
172 .block = block,
173 .found = false
174 };
175
177 "Storing %u bytes under key %s with path length %u\n",
178 (unsigned int) block->data_size,
179 GNUNET_h2s (&block->key),
182 &block->key,
183 &put_cb,
184 &put_ctx);
185 if (GNUNET_YES == put_ctx.found)
186 return 0;
187 val = GNUNET_malloc (sizeof(struct Value)
188 + block->data_size);
189 GNUNET_memcpy (&val[1],
190 block->data,
192 val->block = *block;
193 val->block.data = &val[1];
194 if (xor_distance >= NUM_HEAPS)
195 val->distance = NUM_HEAPS - 1;
196 else
197 val->distance = xor_distance;
198 if (0 != block->put_path_length)
199 {
200 val->put_path
203 * sizeof (struct GNUNET_DHT_PathElement));
204 val->block.put_path = val->put_path;
205 }
207 &val->block.key,
208 val,
211 plugin->heaps[val->distance],
212 val,
214 return val->block.data_size + OVERHEAD;
215}

References GNUNET_TIME_Absolute::abs_value_us, Value::block, PutContext::block, GNUNET_DATACACHE_Block::data, GNUNET_DATACACHE_Block::data_size, Value::distance, GNUNET_DATACACHE_Block::expiration_time, PutContext::found, GNUNET_CONTAINER_heap_insert(), GNUNET_CONTAINER_multihashmap_get_multiple(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_memdup, GNUNET_YES, Value::hn, GNUNET_DATACACHE_Block::key, NUM_HEAPS, OVERHEAD, plugin, put_cb(), GNUNET_DATACACHE_Block::put_path, Value::put_path, and GNUNET_DATACACHE_Block::put_path_length.

Referenced by libgnunet_plugin_datacache_heap_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_cb()

static enum GNUNET_GenericReturnValue get_cb ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Function called during GET to find matching blocks.

Only matches by type.

Parameters
clsthe struct GetContext
keythe key for the value(s)
valuean existing value
Returns
GNUNET_YES to continue to iterate

Definition at line 251 of file plugin_datacache_heap.c.

254{
255 struct GetContext *get_ctx = cls;
256 struct Value *val = value;
257
258 if ( (get_ctx->type != val->block.type) &&
259 (GNUNET_BLOCK_TYPE_ANY != get_ctx->type) )
260 {
262 "Result for key %s does not match block type %d\n",
263 GNUNET_h2s (key),
264 get_ctx->type);
265 return GNUNET_OK;
266 }
268 {
270 "Result for key %s is expired\n",
271 GNUNET_h2s (key));
272 return GNUNET_OK;
273 }
275 "Found result for key %s\n",
276 GNUNET_h2s (key));
277 GNUNET_array_append (get_ctx->values,
278 get_ctx->cnt,
279 val);
280 return GNUNET_OK;
281}

References Value::block, GetContext::cnt, GNUNET_DATACACHE_Block::expiration_time, GNUNET_array_append, GNUNET_BLOCK_TYPE_ANY, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_OK, GNUNET_TIME_absolute_is_past(), key, GNUNET_DATACACHE_Block::type, GetContext::type, value, and GetContext::values.

Referenced by heap_plugin_get().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cmp_expiration()

static int cmp_expiration ( const void *  a,
const void *  b 
)
static

Sort values by expiration time, latest first.

Definition at line 288 of file plugin_datacache_heap.c.

290{
291 const struct Value *va = *(struct Value **) a;
292 const struct Value *vb = *(struct Value **) b;
293
296 return -1;
299 return 1;
300 return 0;
301}

References GNUNET_TIME_Absolute::abs_value_us, Value::block, and GNUNET_DATACACHE_Block::expiration_time.

Referenced by heap_plugin_get().

Here is the caller graph for this function:

◆ heap_plugin_get()

static unsigned int heap_plugin_get ( void *  cls,
const struct GNUNET_HashCode key,
enum GNUNET_BLOCK_Type  type,
GNUNET_DATACACHE_Iterator  iter,
void *  iter_cls 
)
static

Iterate over the results for a particular key in the datastore.

Parameters
clsclosure (our struct Plugin)
key
typeentries of which type are relevant?
itermaybe NULL (to just count)
iter_clsclosure for iter
Returns
the number of results found

Definition at line 316 of file plugin_datacache_heap.c.

321{
322 struct Plugin *plugin = cls;
323 struct GetContext get_ctx = {
324 .type = type
325 };
326 unsigned int ret;
327
329 key,
330 &get_cb,
331 &get_ctx);
332 /* Hand out the freshest block first: a key may hold several
333 versions of the same (mutable) block, and a requester that stops
334 at the first reply must not be given a nearly expired one. */
335 qsort (get_ctx.values,
336 get_ctx.cnt,
337 sizeof (struct Value *),
339 ret = 0;
340 for (unsigned int i = 0; i < get_ctx.cnt; i++)
341 {
342 ret++;
343 if ( (NULL != iter) &&
344 (GNUNET_OK != iter (iter_cls,
345 &get_ctx.values[i]->block)) )
346 break;
347 }
348 GNUNET_array_grow (get_ctx.values,
349 get_ctx.cnt,
350 0);
351 return ret;
352}

References Value::block, cmp_expiration(), GetContext::cnt, get_cb(), GNUNET_array_grow, GNUNET_CONTAINER_multihashmap_get_multiple(), GNUNET_OK, key, plugin, ret, type, GetContext::type, and GetContext::values.

Referenced by libgnunet_plugin_datacache_heap_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ heap_plugin_del()

static enum GNUNET_GenericReturnValue heap_plugin_del ( void *  cls)
static

Delete the entry with the lowest expiration value from the datacache right now.

Parameters
clsclosure (our struct Plugin)
Returns
GNUNET_OK on success, GNUNET_SYSERR on error

Definition at line 363 of file plugin_datacache_heap.c.

364{
365 struct Plugin *plugin = cls;
366 struct Value *val;
367
368 for (unsigned int i = 0; i < NUM_HEAPS; i++)
369 {
371 if (NULL != val)
372 break;
373 }
374 if (NULL == val)
375 return GNUNET_SYSERR;
378 &val->block.key,
379 val));
380 plugin->env->delete_notify (plugin->env->cls,
381 &val->block.key,
382 val->block.data_size + OVERHEAD);
383 GNUNET_free (val->put_path);
384 GNUNET_free (val);
385 return GNUNET_OK;
386}

References Value::block, GNUNET_TESTING_PluginFunctions::cls, GNUNET_DATACACHE_Block::data_size, GNUNET_assert, GNUNET_CONTAINER_heap_remove_root(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_free, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, GNUNET_DATACACHE_Block::key, NUM_HEAPS, OVERHEAD, plugin, and Value::put_path.

Referenced by libgnunet_plugin_datacache_heap_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_closest()

static enum GNUNET_GenericReturnValue find_closest ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 406 of file plugin_datacache_heap.c.

409{
410 struct GetClosestContext *gcc = cls;
411 struct Value *val = value;
412 unsigned int j;
413
414 if (1 != GNUNET_CRYPTO_hash_cmp (key,
415 gcc->key))
416 return GNUNET_OK; /* useless */
417 if ( (val->block.type != gcc->type) &&
418 (GNUNET_BLOCK_TYPE_ANY != gcc->type) )
419 return GNUNET_OK; /* useless */
420 j = gcc->num_results;
421 for (unsigned int i = 0; i < gcc->num_results; i++)
422 {
423 if (NULL == gcc->values[i])
424 {
425 j = i;
426 break;
427 }
428 if (1 ==
430 key))
431 {
432 j = i;
433 break;
434 }
435 }
436 if (j == gcc->num_results)
437 return GNUNET_OK;
438 gcc->values[j] = val;
439 return GNUNET_OK;
440}

References Value::block, GNUNET_BLOCK_TYPE_ANY, GNUNET_CRYPTO_hash_cmp(), GNUNET_OK, key, GNUNET_DATACACHE_Block::key, GetClosestContext::key, GetClosestContext::num_results, GNUNET_DATACACHE_Block::type, GetClosestContext::type, value, and GetClosestContext::values.

Referenced by heap_plugin_get_closest().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ heap_plugin_get_closest()

static unsigned int heap_plugin_get_closest ( void *  cls,
const struct GNUNET_HashCode key,
enum GNUNET_BLOCK_Type  type,
unsigned int  num_results,
GNUNET_DATACACHE_Iterator  iter,
void *  iter_cls 
)
static

Iterate over the results that are "close" to a particular key in the datacache.

"close" is defined as numerically larger than key (when interpreted as a circular address space), with small distance.

Parameters
clsclosure (internal context for the plugin)
keyarea of the keyspace to look into
typedesired block type for the replies
num_resultsnumber of results that should be returned to iter
itermaybe NULL (to just count)
iter_clsclosure for iter
Returns
the number of results found

Definition at line 458 of file plugin_datacache_heap.c.

464{
465 struct Plugin *plugin = cls;
466 struct Value *values[num_results];
467 struct GetClosestContext gcc = {
468 .values = values,
469 .type = type,
470 .num_results = num_results * 2,
471 .key = key
472 };
473
476 &gcc);
477 for (unsigned int i = 0; i < num_results * 2; i++)
478 {
479 if (NULL == values[i])
480 return i;
481 if ( (NULL != iter) &&
482 (GNUNET_SYSERR ==
483 iter (iter_cls,
484 &values[i]->block)) )
485 {
487 "Ending iteration (client error)\n");
488 return i;
489 }
490 }
491 return num_results * 2;
492}

References find_closest(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_SYSERR, key, LOG, GetClosestContext::num_results, plugin, type, values, and GetClosestContext::values.

Referenced by libgnunet_plugin_datacache_heap_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ libgnunet_plugin_datacache_heap_init()

void * libgnunet_plugin_datacache_heap_init ( void *  cls)

Entry point for the plugin.

Parameters
clsclosure (the struct GNUNET_DATACACHE_PluginEnvironmnet)
Returns
the plugin's closure (our struct Plugin)

Definition at line 505 of file plugin_datacache_heap.c.

506{
509 struct Plugin *plugin;
510
511 plugin = GNUNET_new (struct Plugin);
512 plugin->map = GNUNET_CONTAINER_multihashmap_create (1024, /* FIXME: base on quota! */
513 GNUNET_YES);
514 for (unsigned int i = 0; i < NUM_HEAPS; i++)
517 plugin->env = env;
519 api->cls = plugin;
520 api->get = &heap_plugin_get;
521 api->put = &heap_plugin_put;
522 api->del = &heap_plugin_del;
523 api->get_closest = &heap_plugin_get_closest;
525 _ ("Heap datacache running\n"));
526 return api;
527}

References _, Plugin::api, GNUNET_BLOCK_PluginFunctions::cls, GNUNET_DATACACHE_PluginEnvironment::cls, env, GNUNET_CONTAINER_heap_create(), GNUNET_CONTAINER_HEAP_ORDER_MIN, GNUNET_CONTAINER_multihashmap_create(), GNUNET_ERROR_TYPE_INFO, GNUNET_new, GNUNET_YES, heap_plugin_del(), heap_plugin_get(), heap_plugin_get_closest(), heap_plugin_put(), LOG, NUM_HEAPS, and plugin.

Here is the call graph for this function:

◆ libgnunet_plugin_datacache_heap_done()

void * libgnunet_plugin_datacache_heap_done ( void *  cls)

Exit point from the plugin.

Parameters
clsclosure (our "struct Plugin")
Returns
NULL

Definition at line 540 of file plugin_datacache_heap.c.

541{
543 struct Plugin *plugin = api->cls;
544 struct Value *val;
545
546 for (unsigned int i = 0; i < NUM_HEAPS; i++)
547 {
548 while (NULL != (val = GNUNET_CONTAINER_heap_remove_root (plugin->heaps[i])))
549 {
552 &val->block.key,
553 val));
554 GNUNET_free (val->put_path);
555 GNUNET_free (val);
556 }
558 }
561 GNUNET_free (api);
562 return NULL;
563}

References Plugin::api, Value::block, GNUNET_BLOCK_PluginFunctions::cls, GNUNET_DATACACHE_PluginFunctions::cls, GNUNET_assert, GNUNET_CONTAINER_heap_destroy(), GNUNET_CONTAINER_heap_remove_root(), GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_free, GNUNET_YES, GNUNET_DATACACHE_Block::key, NUM_HEAPS, plugin, and Value::put_path.

Here is the call graph for this function: