aboutsummaryrefslogtreecommitdiff
path: root/src/datastore/plugin_datastore_heap.c
diff options
context:
space:
mode:
authorDavid Barksdale <amatus@amat.us>2017-04-16 12:39:43 -0500
committerDavid Barksdale <amatus@amat.us>2017-04-16 12:42:34 -0500
commit4907330f51ffd48af1f7bac6f43c7c7f78c37818 (patch)
treea2cd65dbb24ea5caeda1fff2521f935dd7ea6256 /src/datastore/plugin_datastore_heap.c
parentcacd64d8635201459e59bf2cd8a2ea8fd0699b84 (diff)
downloadgnunet-4907330f51ffd48af1f7bac6f43c7c7f78c37818.tar.gz
gnunet-4907330f51ffd48af1f7bac6f43c7c7f78c37818.zip
[datastore] Combine put and update plugin APIs
This resolves issue #4965.
Diffstat (limited to 'src/datastore/plugin_datastore_heap.c')
-rw-r--r--src/datastore/plugin_datastore_heap.c170
1 files changed, 109 insertions, 61 deletions
diff --git a/src/datastore/plugin_datastore_heap.c b/src/datastore/plugin_datastore_heap.c
index d04c1cf60..6dbc15ebd 100644
--- a/src/datastore/plugin_datastore_heap.c
+++ b/src/datastore/plugin_datastore_heap.c
@@ -195,10 +195,89 @@ heap_plugin_estimate_size (void *cls, unsigned long long *estimate)
195 195
196 196
197/** 197/**
198 * Closure for iterator for updating.
199 */
200struct UpdateContext
201{
202 /**
203 * Number of bytes in 'data'.
204 */
205 uint32_t size;
206
207 /**
208 * Pointer to the data.
209 */
210 const void *data;
211
212 /**
213 * Priority of the value.
214 */
215 uint32_t priority;
216
217 /**
218 * Replication level for the value.
219 */
220 uint32_t replication;
221
222 /**
223 * Expiration time for this value.
224 */
225 struct GNUNET_TIME_Absolute expiration;
226
227 /**
228 * True if the value was found and updated.
229 */
230 bool updated;
231};
232
233
234/**
235 * Update the matching value.
236 *
237 * @param cls the 'struct UpdateContext'
238 * @param key unused
239 * @param val the 'struct Value'
240 * @return GNUNET_YES (continue iteration), GNUNET_NO if value was found
241 */
242static int
243update_iterator (void *cls,
244 const struct GNUNET_HashCode *key,
245 void *val)
246{
247 struct UpdateContext *uc = cls;
248 struct Value *value = val;
249
250 if (value->size != uc->size)
251 return GNUNET_YES;
252 if (0 != memcmp (value->data, uc->data, uc->size))
253 return GNUNET_YES;
254 uc->expiration = GNUNET_TIME_absolute_max (value->expiration,
255 uc->expiration);
256 if (value->expiration.abs_value_us != uc->expiration.abs_value_us)
257 {
258 value->expiration = uc->expiration;
259 GNUNET_CONTAINER_heap_update_cost (value->expire_heap,
260 value->expiration.abs_value_us);
261 }
262 /* Saturating adds, don't overflow */
263 if (value->priority > UINT32_MAX - uc->priority)
264 value->priority = UINT32_MAX;
265 else
266 value->priority += uc->priority;
267 if (value->replication > UINT32_MAX - uc->replication)
268 value->replication = UINT32_MAX;
269 else
270 value->replication += uc->replication;
271 uc->updated = true;
272 return GNUNET_NO;
273}
274
275/**
198 * Store an item in the datastore. 276 * Store an item in the datastore.
199 * 277 *
200 * @param cls closure 278 * @param cls closure
201 * @param key key for the item 279 * @param key key for the item
280 * @param absent true if the key was not found in the bloom filter
202 * @param size number of bytes in data 281 * @param size number of bytes in data
203 * @param data content stored 282 * @param data content stored
204 * @param type type of the content 283 * @param type type of the content
@@ -211,19 +290,40 @@ heap_plugin_estimate_size (void *cls, unsigned long long *estimate)
211 */ 290 */
212static void 291static void
213heap_plugin_put (void *cls, 292heap_plugin_put (void *cls,
214 const struct GNUNET_HashCode * key, 293 const struct GNUNET_HashCode *key,
215 uint32_t size, 294 bool absent,
216 const void *data, 295 uint32_t size,
217 enum GNUNET_BLOCK_Type type, 296 const void *data,
218 uint32_t priority, uint32_t anonymity, 297 enum GNUNET_BLOCK_Type type,
219 uint32_t replication, 298 uint32_t priority,
220 struct GNUNET_TIME_Absolute expiration, 299 uint32_t anonymity,
221 PluginPutCont cont, 300 uint32_t replication,
222 void *cont_cls) 301 struct GNUNET_TIME_Absolute expiration,
302 PluginPutCont cont,
303 void *cont_cls)
223{ 304{
224 struct Plugin *plugin = cls; 305 struct Plugin *plugin = cls;
225 struct Value *value; 306 struct Value *value;
226 307
308 if (!absent) {
309 struct UpdateContext uc;
310
311 uc.size = size;
312 uc.data = data;
313 uc.priority = priority;
314 uc.replication = replication;
315 uc.expiration = expiration;
316 uc.updated = false;
317 GNUNET_CONTAINER_multihashmap_get_multiple (plugin->keyvalue,
318 key,
319 &update_iterator,
320 &uc);
321 if (uc.updated)
322 {
323 cont (cont_cls, key, size, GNUNET_NO, NULL);
324 return;
325 }
326 }
227 value = GNUNET_malloc (sizeof (struct Value) + size); 327 value = GNUNET_malloc (sizeof (struct Value) + size);
228 value->key = *key; 328 value->key = *key;
229 value->data = &value[1]; 329 value->data = &value[1];
@@ -551,57 +651,6 @@ heap_plugin_get_expiration (void *cls, PluginDatumProcessor proc,
551 651
552 652
553/** 653/**
554 * Update the priority, replication and expiration for a particular
555 * unique ID in the datastore. If the expiration time in value is
556 * different than the time found in the datastore, the higher value
557 * should be kept. The specified priority and replication is added
558 * to the existing value.
559 *
560 * @param cls our `struct Plugin *`
561 * @param uid unique identifier of the datum
562 * @param priority by how much should the priority
563 * change?
564 * @param replication by how much should the replication
565 * change?
566 * @param expire new expiration time should be the
567 * MAX of any existing expiration time and
568 * this value
569 * @param cont continuation called with success or failure status
570 * @param cons_cls continuation closure
571 */
572static void
573heap_plugin_update (void *cls,
574 uint64_t uid,
575 uint32_t priority,
576 uint32_t replication,
577 struct GNUNET_TIME_Absolute expire,
578 PluginUpdateCont cont,
579 void *cont_cls)
580{
581 struct Value *value;
582
583 value = (struct Value*) (intptr_t) uid;
584 GNUNET_assert (NULL != value);
585 if (value->expiration.abs_value_us != expire.abs_value_us)
586 {
587 value->expiration = expire;
588 GNUNET_CONTAINER_heap_update_cost (value->expire_heap,
589 expire.abs_value_us);
590 }
591 /* Saturating adds, don't overflow */
592 if (value->priority > UINT32_MAX - priority)
593 value->priority = UINT32_MAX;
594 else
595 value->priority += priority;
596 if (value->replication > UINT32_MAX - replication)
597 value->replication = UINT32_MAX;
598 else
599 value->replication += replication;
600 cont (cont_cls, GNUNET_OK, NULL);
601}
602
603
604/**
605 * Call the given processor on an item with zero anonymity. 654 * Call the given processor on an item with zero anonymity.
606 * 655 *
607 * @param cls our "struct Plugin*" 656 * @param cls our "struct Plugin*"
@@ -758,7 +807,6 @@ libgnunet_plugin_datastore_heap_init (void *cls)
758 api->cls = plugin; 807 api->cls = plugin;
759 api->estimate_size = &heap_plugin_estimate_size; 808 api->estimate_size = &heap_plugin_estimate_size;
760 api->put = &heap_plugin_put; 809 api->put = &heap_plugin_put;
761 api->update = &heap_plugin_update;
762 api->get_key = &heap_plugin_get_key; 810 api->get_key = &heap_plugin_get_key;
763 api->get_replication = &heap_plugin_get_replication; 811 api->get_replication = &heap_plugin_get_replication;
764 api->get_expiration = &heap_plugin_get_expiration; 812 api->get_expiration = &heap_plugin_get_expiration;