aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2009-06-16 22:08:40 +0000
committerChristian Grothoff <christian@grothoff.org>2009-06-16 22:08:40 +0000
commit55fe7180de4f26582646418073bd52bf13bb5697 (patch)
tree30296a970be4a650f1f82644ead9f9be305f5a9d /src
parenta69e21076e7a4d6e5b6d66078cae83c0626c94aa (diff)
downloadgnunet-55fe7180de4f26582646418073bd52bf13bb5697.tar.gz
gnunet-55fe7180de4f26582646418073bd52bf13bb5697.zip
further datastore API improvements:
Diffstat (limited to 'src')
-rw-r--r--src/datastore/datastore_api.c9
-rw-r--r--src/datastore/gnunet-service-datastore.c346
-rw-r--r--src/datastore/plugin_datastore.h144
-rw-r--r--src/datastore/plugin_datastore_sqlite.c65
-rw-r--r--src/datastore/plugin_datastore_template.c42
-rw-r--r--src/include/gnunet_datastore_service.h21
6 files changed, 496 insertions, 131 deletions
diff --git a/src/datastore/datastore_api.c b/src/datastore/datastore_api.c
index 960d7d34e..968e09b20 100644
--- a/src/datastore/datastore_api.c
+++ b/src/datastore/datastore_api.c
@@ -22,15 +22,6 @@
22 * @file datastore/datastore_api.c 22 * @file datastore/datastore_api.c
23 * @brief Management for the datastore for files stored on a GNUnet node 23 * @brief Management for the datastore for files stored on a GNUnet node
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 *
26 * TODO:
27 * 1) clarify API (wrt. efficient UPDATE of priority/expiration after GET)
28 * 2) implement INIT
29 * 4) implement DROP
30 * 5) implement PUT
31 * 6) implement GET
32 * 7) implement GET_RANDOM
33 * 8) implement REMOVE
34 */ 25 */
35 26
36#include "platform.h" 27#include "platform.h"
diff --git a/src/datastore/gnunet-service-datastore.c b/src/datastore/gnunet-service-datastore.c
index db3524557..9a24865da 100644
--- a/src/datastore/gnunet-service-datastore.c
+++ b/src/datastore/gnunet-service-datastore.c
@@ -24,14 +24,8 @@
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 * 25 *
26 * TODO: 26 * TODO:
27 * 1) transmit and transmit flow-control (when do we signal client 'success'? 27 * 1) semantics of "PUT" (plugin) if entry exists (should likely
28 * ALSO: async transmit will need to address ref-counting issues on client! 28 * be similar to "UPDATE" (need to specify in PLUGIN API!)
29 * 2) efficient "update" for client to raise priority / expiration
30 * (not possible with current datastore API, but plugin API has support!);
31 * [ maybe integrate desired priority/expiration updates directly
32 * with 'GET' request? ]
33 * 3) semantics of "PUT" (plugin) if entry exists (should likely
34 * be similar to "UPDATE" (need to specify in PLUGIN API!)
35 * 4) quota management code! 29 * 4) quota management code!
36 * 5) add bloomfilter for efficiency! 30 * 5) add bloomfilter for efficiency!
37 */ 31 */
@@ -42,6 +36,11 @@
42#include "plugin_datastore.h" 36#include "plugin_datastore.h"
43#include "datastore.h" 37#include "datastore.h"
44 38
39/**
40 * How many messages do we queue at most per client?
41 */
42#define MAX_PENDING 1024
43
45 44
46/** 45/**
47 * Our datastore plugin. 46 * Our datastore plugin.
@@ -75,19 +74,182 @@ struct DatastorePlugin
75 74
76 75
77/** 76/**
77 * Linked list of active reservations.
78 */
79struct ReservationList
80{
81
82 /**
83 * This is a linked list.
84 */
85 struct ReservationList *next;
86
87 /**
88 * Client that made the reservation.
89 */
90 struct GNUNET_SERVER_Client *client;
91
92 /**
93 * Number of bytes (still) reserved.
94 */
95 uint64_t size;
96
97 /**
98 * Number of items (still) reserved.
99 */
100 uint64_t items;
101
102 /**
103 * Reservation identifier.
104 */
105 int32_t rid;
106
107};
108
109
110/**
78 * Our datastore plugin (NULL if not available). 111 * Our datastore plugin (NULL if not available).
79 */ 112 */
80static struct DatastorePlugin *plugin; 113static struct DatastorePlugin *plugin;
81 114
115/**
116 * Linked list of space reservations made by clients.
117 */
118static struct ReservationList *reservations;
119
120/**
121 * Static counter to produce reservation identifiers.
122 */
123static int reservation_gen;
124
125/**
126 * How much space are we allowed to use?
127 */
128static unsigned long long quota;
129
130
131/**
132 * Function called once the transmit operation has
133 * either failed or succeeded.
134 *
135 * @param cls closure
136 * @param status GNUNET_OK on success, GNUNET_SYSERR on error
137 */
138typedef void (*TransmitContinuation)(void *cls,
139 int status);
140
141struct TransmitCallbackContext
142{
143 /**
144 * The message that we're asked to transmit.
145 */
146 struct GNUNET_MessageHeader *msg;
147
148 /**
149 * Client that we are transmitting to.
150 */
151 struct GNUNET_SERVER_Client *client;
152
153 /**
154 * Function to call once msg has been transmitted
155 * (or at least added to the buffer).
156 */
157 TransmitContinuation tc;
158
159 /**
160 * Closure for tc.
161 */
162 void *tc_cls;
163
164 /**
165 * GNUNET_YES if we are supposed to signal the server
166 * completion of the client's request.
167 */
168 int end;
169};
170
171
172/**
173 * Function called to notify a client about the socket
174 * begin ready to queue more data. "buf" will be
175 * NULL and "size" zero if the socket was closed for
176 * writing in the meantime.
177 *
178 * @param cls closure
179 * @param size number of bytes available in buf
180 * @param buf where the callee should write the message
181 * @return number of bytes written to buf
182 */
183static size_t
184transmit_callback (void *cls,
185 size_t size, void *buf)
186{
187 struct TransmitCallbackContext *tcc = cls;
188 size_t msize;
189
190 msize = ntohs(tcc->msg->size);
191 if (size == 0)
192 {
193 if (tcc->tc != NULL)
194 tcc->tc (tcc->tc_cls, GNUNET_SYSERR);
195 if (GNUNET_YES == tcc->end)
196 GNUNET_SERVER_receive_done (tcc->client, GNUNET_SYSERR);
197 GNUNET_free (tcc->msg);
198 GNUNET_free (tcc);
199 return 0;
200 }
201 GNUNET_assert (size >= msize);
202 memcpy (buf, tcc->msg, msize);
203 if (tcc->tc != NULL)
204 tcc->tc (tcc->tc_cls, GNUNET_OK);
205 if (GNUNET_YES == tcc->end)
206 GNUNET_SERVER_receive_done (tcc->client, GNUNET_OK);
207 GNUNET_free (tcc->msg);
208 GNUNET_free (tcc);
209 return msize;
210}
211
82 212
83/** 213/**
84 * Transmit the given message to the client. 214 * Transmit the given message to the client.
215 *
216 * @param client target of the message
217 * @param msg message to transmit, will be freed!
218 * @param end is this the last response (and we should
219 * signal the server completion accodingly after
220 * transmitting this message)?
85 */ 221 */
86static void 222static void
87transmit (struct GNUNET_SERVER_Client *client, 223transmit (struct GNUNET_SERVER_Client *client,
88 const struct GNUNET_MessageHeader *msg) 224 struct GNUNET_MessageHeader *msg,
225 TransmitContinuation tc,
226 void *tc_cls,
227 int end)
89{ 228{
90 /* FIXME! */ 229 struct TransmitCallbackContext *tcc;
230
231 tcc = GNUNET_malloc (sizeof(struct TransmitCallbackContext));
232 tcc->msg = msg;
233 tcc->client = client;
234 tcc->tc = tc;
235 tcc->tc_cls = tc_cls;
236 tcc->end = end;
237
238 if (NULL ==
239 GNUNET_SERVER_notify_transmit_ready (client,
240 ntohs(msg->size),
241 GNUNET_TIME_UNIT_FOREVER_REL,
242 &transmit_callback,
243 tcc))
244 {
245 GNUNET_break (0);
246 if (GNUNET_YES == end)
247 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
248 if (NULL != tc)
249 tc (tc_cls, GNUNET_SYSERR);
250 GNUNET_free (msg);
251 GNUNET_free (tcc);
252 }
91} 253}
92 254
93 255
@@ -112,8 +274,29 @@ transmit_status (struct GNUNET_SERVER_Client *client,
112 sm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_STATUS); 274 sm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_STATUS);
113 sm->status = htonl(code); 275 sm->status = htonl(code);
114 memcpy (&sm[1], msg, slen); 276 memcpy (&sm[1], msg, slen);
115 transmit (client, &sm->header); 277 transmit (client, &sm->header, NULL, NULL, GNUNET_YES);
116 GNUNET_free (sm); 278}
279
280
281/**
282 * Function called once the transmit operation has
283 * either failed or succeeded.
284 *
285 * @param cls closure
286 * @param status GNUNET_OK on success, GNUNET_SYSERR on error
287 */
288static void
289get_next(void *next_cls,
290 int status)
291{
292 if (status != GNUNET_OK)
293 {
294 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
295 _("Failed to transmit an item to the client; aborting iteration.\n"));
296 plugin->api->next_request (next_cls, GNUNET_YES);
297 return;
298 }
299 plugin->api->next_request (next_cls, GNUNET_NO);
117} 300}
118 301
119 302
@@ -122,6 +305,7 @@ transmit_status (struct GNUNET_SERVER_Client *client,
122 * to the client. 305 * to the client.
123 * 306 *
124 * @param cls closure, pointer to the client (of type GNUNET_SERVER_Client). 307 * @param cls closure, pointer to the client (of type GNUNET_SERVER_Client).
308 * @param next_cls closure to use to ask for the next item
125 * @param key key for the content 309 * @param key key for the content
126 * @param size number of bytes in data 310 * @param size number of bytes in data
127 * @param data content stored 311 * @param data content stored
@@ -137,6 +321,7 @@ transmit_status (struct GNUNET_SERVER_Client *client,
137 */ 321 */
138static int 322static int
139transmit_item (void *cls, 323transmit_item (void *cls,
324 void *next_cls,
140 const GNUNET_HashCode * key, 325 const GNUNET_HashCode * key,
141 uint32_t size, 326 uint32_t size,
142 const void *data, 327 const void *data,
@@ -147,15 +332,17 @@ transmit_item (void *cls,
147 expiration, unsigned long long uid) 332 expiration, unsigned long long uid)
148{ 333{
149 struct GNUNET_SERVER_Client *client = cls; 334 struct GNUNET_SERVER_Client *client = cls;
150 struct GNUNET_MessageHeader end; 335 struct GNUNET_MessageHeader *end;
151 struct DataMessage *dm; 336 struct DataMessage *dm;
152 337
153 if (key == NULL) 338 if (key == NULL)
154 { 339 {
155 /* transmit 'DATA_END' */ 340 /* transmit 'DATA_END' */
156 end.size = htons(sizeof(struct GNUNET_MessageHeader)); 341 end = GNUNET_malloc (sizeof(struct GNUNET_MessageHeader));
157 end.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_DATA_END); 342 end->size = htons(sizeof(struct GNUNET_MessageHeader));
158 transmit (client, &end); 343 end->type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_DATA_END);
344 transmit (client, end, NULL, NULL, GNUNET_YES);
345 GNUNET_SERVER_client_drop (client);
159 return GNUNET_OK; 346 return GNUNET_OK;
160 } 347 }
161 dm = GNUNET_malloc (sizeof(struct DataMessage) + size); 348 dm = GNUNET_malloc (sizeof(struct DataMessage) + size);
@@ -170,8 +357,7 @@ transmit_item (void *cls,
170 dm->uid = GNUNET_htonll(uid); 357 dm->uid = GNUNET_htonll(uid);
171 dm->key = *key; 358 dm->key = *key;
172 memcpy (&dm[1], data, size); 359 memcpy (&dm[1], data, size);
173 transmit (client, &dm->header); 360 transmit (client, &dm->header, &get_next, next_cls, GNUNET_NO);
174 GNUNET_free (dm);
175 return GNUNET_OK; 361 return GNUNET_OK;
176} 362}
177 363
@@ -188,8 +374,20 @@ handle_reserve (void *cls,
188 struct GNUNET_SERVER_Client *client, 374 struct GNUNET_SERVER_Client *client,
189 const struct GNUNET_MessageHeader *message) 375 const struct GNUNET_MessageHeader *message)
190{ 376{
191 transmit_status (client, GNUNET_SYSERR, "not implemented"); 377 const struct ReserveMessage *msg = (const struct ReserveMessage*) message;
192 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 378 struct ReservationList *e;
379
380 /* FIXME: check if we have that much space... */
381 e = GNUNET_malloc (sizeof(struct ReservationList));
382 e->next = reservations;
383 reservations = e;
384 e->client = client;
385 e->size = GNUNET_ntohll(msg->size);
386 e->items = GNUNET_ntohll(msg->items);
387 e->rid = ++reservation_gen;
388 if (reservation_gen < 0)
389 reservation_gen = 0; /* wrap around */
390 transmit_status (client, e->rid, NULL);
193} 391}
194 392
195 393
@@ -205,8 +403,32 @@ handle_release_reserve (void *cls,
205 struct GNUNET_SERVER_Client *client, 403 struct GNUNET_SERVER_Client *client,
206 const struct GNUNET_MessageHeader *message) 404 const struct GNUNET_MessageHeader *message)
207{ 405{
208 transmit_status (client, GNUNET_SYSERR, "not implemented"); 406 const struct ReleaseReserveMessage *msg = (const struct ReleaseReserveMessage*) message;
209 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 407 struct ReservationList *pos;
408 struct ReservationList *prev;
409 struct ReservationList *next;
410
411 int rid = ntohl(msg->rid);
412 next = reservations;
413 prev = NULL;
414 while (NULL != (pos = next))
415 {
416 next = pos->next;
417 if (rid == pos->rid)
418 {
419 if (prev == NULL)
420 reservations = next;
421 else
422 prev->next = next;
423 /* FIXME: released remaining reserved space! */
424 GNUNET_free (pos);
425 transmit_status (client, GNUNET_OK, NULL);
426 return;
427 }
428 prev = pos;
429 pos = next;
430 }
431 transmit_status (client, GNUNET_SYSERR, "Could not find matching reservation");
210} 432}
211 433
212 434
@@ -284,7 +506,6 @@ handle_put (void *cls,
284 &msg); 506 &msg);
285 transmit_status (client, ret, msg); 507 transmit_status (client, ret, msg);
286 GNUNET_free_non_null (msg); 508 GNUNET_free_non_null (msg);
287 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
288} 509}
289 510
290 511
@@ -312,13 +533,13 @@ handle_get (void *cls,
312 return; 533 return;
313 } 534 }
314 msg = (const struct GetMessage*) message; 535 msg = (const struct GetMessage*) message;
536 GNUNET_SERVER_client_drop (client);
315 plugin->api->get (plugin->api->cls, 537 plugin->api->get (plugin->api->cls,
316 ((size == sizeof(struct GetMessage)) ? &msg->key : NULL), 538 ((size == sizeof(struct GetMessage)) ? &msg->key : NULL),
317 NULL, 539 NULL,
318 ntohl(msg->type), 540 ntohl(msg->type),
319 &transmit_item, 541 &transmit_item,
320 client); 542 client);
321 GNUNET_SERVER_receive_done (client, GNUNET_OK);
322} 543}
323 544
324 545
@@ -347,7 +568,6 @@ handle_update (void *cls,
347 &emsg); 568 &emsg);
348 transmit_status (client, ret, emsg); 569 transmit_status (client, ret, emsg);
349 GNUNET_free_non_null (emsg); 570 GNUNET_free_non_null (emsg);
350 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
351} 571}
352 572
353 573
@@ -363,20 +583,38 @@ handle_get_random (void *cls,
363 struct GNUNET_SERVER_Client *client, 583 struct GNUNET_SERVER_Client *client,
364 const struct GNUNET_MessageHeader *message) 584 const struct GNUNET_MessageHeader *message)
365{ 585{
586 GNUNET_SERVER_client_drop (client);
366 plugin->api->iter_migration_order (plugin->api->cls, 587 plugin->api->iter_migration_order (plugin->api->cls,
367 0, 588 0,
368 &transmit_item, 589 &transmit_item,
369 client); 590 client);
370 GNUNET_SERVER_receive_done (client, GNUNET_OK);
371} 591}
372 592
373 593
374/** 594/**
595 * Context for the 'remove_callback'.
596 */
597struct RemoveContext
598{
599 /**
600 * Client for whom we're doing the remvoing.
601 */
602 struct GNUNET_SERVER_Client *client;
603
604 /**
605 * GNUNET_YES if we managed to remove something.
606 */
607 int found;
608};
609
610
611/**
375 * Callback function that will cause the item that is passed 612 * Callback function that will cause the item that is passed
376 * in to be deleted (by returning GNUNET_NO). 613 * in to be deleted (by returning GNUNET_NO).
377 */ 614 */
378static int 615static int
379remove_callback (void *cls, 616remove_callback (void *cls,
617 void *next_cls,
380 const GNUNET_HashCode * key, 618 const GNUNET_HashCode * key,
381 uint32_t size, 619 uint32_t size,
382 const void *data, 620 const void *data,
@@ -386,8 +624,19 @@ remove_callback (void *cls,
386 struct GNUNET_TIME_Absolute 624 struct GNUNET_TIME_Absolute
387 expiration, unsigned long long uid) 625 expiration, unsigned long long uid)
388{ 626{
389 int *found = cls; 627 struct RemoveContext *rc = cls;
390 *found = GNUNET_YES; 628 if (key == NULL)
629 {
630 if (GNUNET_YES == rc->found)
631 transmit_status (rc->client, GNUNET_OK, NULL);
632 else
633 transmit_status (rc->client, GNUNET_SYSERR, _("Content not found"));
634 GNUNET_SERVER_client_drop (rc->client);
635 GNUNET_free (rc);
636 return GNUNET_OK; /* last item */
637 }
638 rc->found = GNUNET_YES;
639 plugin->api->next_request (next_cls, GNUNET_YES);
391 return GNUNET_NO; 640 return GNUNET_NO;
392} 641}
393 642
@@ -406,7 +655,7 @@ handle_remove (void *cls,
406{ 655{
407 const struct DataMessage *dm = check_data (message); 656 const struct DataMessage *dm = check_data (message);
408 GNUNET_HashCode vhash; 657 GNUNET_HashCode vhash;
409 int found; 658 struct RemoveContext *rc;
410 659
411 if (dm == NULL) 660 if (dm == NULL)
412 { 661 {
@@ -414,7 +663,9 @@ handle_remove (void *cls,
414 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 663 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
415 return; 664 return;
416 } 665 }
417 found = GNUNET_NO; 666 rc = GNUNET_malloc (sizeof(struct RemoveContext));
667 GNUNET_SERVER_client_keep (client);
668 rc->client = client;
418 GNUNET_CRYPTO_hash (&dm[1], 669 GNUNET_CRYPTO_hash (&dm[1],
419 ntohl(dm->size), 670 ntohl(dm->size),
420 &vhash); 671 &vhash);
@@ -423,12 +674,7 @@ handle_remove (void *cls,
423 &vhash, 674 &vhash,
424 ntohl(dm->type), 675 ntohl(dm->type),
425 &remove_callback, 676 &remove_callback,
426 &found); 677 rc);
427 if (GNUNET_YES == found)
428 transmit_status (client, GNUNET_OK, NULL);
429 else
430 transmit_status (client, GNUNET_SYSERR, _("Content not found"));
431 GNUNET_SERVER_receive_done (client, GNUNET_OK);
432} 678}
433 679
434 680
@@ -549,6 +795,23 @@ cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
549 795
550 796
551/** 797/**
798 * Function that removes all active reservations made
799 * by the given client and releases the space for other
800 * requests.
801 *
802 * @param cls closure
803 * @param client identification of the client
804 */
805static void
806cleanup_reservations (void *cls,
807 struct GNUNET_SERVER_Client
808 * client)
809{
810 /* FIXME */
811}
812
813
814/**
552 * Process datastore requests. 815 * Process datastore requests.
553 * 816 *
554 * @param cls closure 817 * @param cls closure
@@ -562,9 +825,20 @@ run (void *cls,
562 struct GNUNET_SERVER_Handle *server, 825 struct GNUNET_SERVER_Handle *server,
563 struct GNUNET_CONFIGURATION_Handle *cfg) 826 struct GNUNET_CONFIGURATION_Handle *cfg)
564{ 827{
828 if (GNUNET_OK !=
829 GNUNET_CONFIGURATION_get_value_number (cfg,
830 "DATASTORE", "QUOTA", &quota))
831 {
832 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
833 _("No `%s' specified for `%s' in configuration!\n"),
834 "QUOTA",
835 "DATASTORE");
836 return;
837 }
565 plugin = load_plugin (cfg, sched); 838 plugin = load_plugin (cfg, sched);
566 if (NULL == plugin) 839 if (NULL == plugin)
567 return; 840 return;
841 GNUNET_SERVER_disconnect_notify (server, &cleanup_reservations, NULL);
568 GNUNET_SERVER_add_handlers (server, handlers); 842 GNUNET_SERVER_add_handlers (server, handlers);
569 GNUNET_SCHEDULER_add_delayed (sched, 843 GNUNET_SCHEDULER_add_delayed (sched,
570 GNUNET_YES, 844 GNUNET_YES,
diff --git a/src/datastore/plugin_datastore.h b/src/datastore/plugin_datastore.h
index cc68f3557..1214ae1be 100644
--- a/src/datastore/plugin_datastore.h
+++ b/src/datastore/plugin_datastore.h
@@ -55,15 +55,64 @@ struct GNUNET_DATASTORE_PluginEnvironment
55 55
56 56
57/** 57/**
58 * Function invoked on behalf of a "PluginIterator"
59 * asking the database plugin to call the iterator
60 * with the next item.
61 *
62 * @param next_cls whatever argument was given
63 * to the PluginIterator as "next_cls".
64 * @param end_it set to GNUNET_YES if we
65 * should terminate the iteration early
66 * (iterator should be still called once more
67 * to signal the end of the iteration).
68 */
69typedef void (*PluginNextRequest)(void *next_cls,
70 int end_it);
71
72
73/**
74 * An iterator over a set of items stored in the datastore.
75 *
76 * @param cls closure
77 * @param next_cls closure to pass to the "next" function.
78 * @param key key for the content
79 * @param size number of bytes in data
80 * @param data content stored
81 * @param type type of the content
82 * @param priority priority of the content
83 * @param anonymity anonymity-level for the content
84 * @param expiration expiration time for the content
85 * @param uid unique identifier for the datum;
86 * maybe 0 if no unique identifier is available
87 *
88 * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue
89 * (continue on call to "next", of course),
90 * GNUNET_NO to delete the item and continue (if supported)
91 */
92typedef int (*PluginIterator) (void *cls,
93 void *next_cls,
94 const GNUNET_HashCode * key,
95 uint32_t size,
96 const void *data,
97 uint32_t type,
98 uint32_t priority,
99 uint32_t anonymity,
100 struct GNUNET_TIME_Absolute
101 expiration,
102 uint64_t uid);
103
104/**
58 * Get an estimate of how much space the database is 105 * Get an estimate of how much space the database is
59 * currently using. 106 * currently using.
60 * @return number of bytes used on disk 107 * @return number of bytes used on disk
61 */ 108 */
62typedef unsigned long long (*GNUNET_DATASTORE_GetSize) (void *cls); 109typedef unsigned long long (*PluginGetSize) (void *cls);
63 110
64 111
65/** 112/**
66 * Store an item in the datastore. 113 * Store an item in the datastore. If the item is already present,
114 * the priorities are summed up and the higher expiration time and
115 * lower anonymity level is used.
67 * 116 *
68 * @param cls closure 117 * @param cls closure
69 * @param key key for the item 118 * @param key key for the item
@@ -76,15 +125,14 @@ typedef unsigned long long (*GNUNET_DATASTORE_GetSize) (void *cls);
76 * @param msg set to an error message (on failure) 125 * @param msg set to an error message (on failure)
77 * @return GNUNET_OK on success, GNUNET_SYSERR on failure 126 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
78 */ 127 */
79typedef int 128typedef int (*PluginPut) (void *cls,
80 (*GNUNET_DATASTORE_Put) (void *cls, 129 const GNUNET_HashCode * key,
81 const GNUNET_HashCode * key, 130 uint32_t size,
82 uint32_t size, 131 const void *data,
83 const void *data, 132 uint32_t type,
84 uint32_t type, 133 uint32_t priority,
85 uint32_t priority, 134 uint32_t anonymity,
86 uint32_t anonymity, 135 struct GNUNET_TIME_Absolute expiration,
87 struct GNUNET_TIME_Absolute expiration,
88 char **msg); 136 char **msg);
89 137
90 138
@@ -101,16 +149,19 @@ typedef int
101 * there may be! 149 * there may be!
102 * @param type entries of which type are relevant? 150 * @param type entries of which type are relevant?
103 * Use 0 for any type. 151 * Use 0 for any type.
104 * @param iter function to call on each matching value; 152 * @param iter function to call on each matching value; however,
105 * will be called once with a NULL value at the end 153 * after the first call to "iter", the plugin must wait
154 * until "NextRequest" was called before giving the iterator
155 * the next item; finally, the "iter" should be called once
156 * once with a NULL value at the end ("next_cls" should be NULL
157 * for that last call)
106 * @param iter_cls closure for iter 158 * @param iter_cls closure for iter
107 */ 159 */
108typedef void 160typedef void (*PluginGet) (void *cls,
109 (*GNUNET_DATASTORE_Get) (void *cls, 161 const GNUNET_HashCode * key,
110 const GNUNET_HashCode * key, 162 const GNUNET_HashCode * vhash,
111 const GNUNET_HashCode * vhash, 163 uint32_t type,
112 uint32_t type, 164 PluginIterator iter, void *iter_cls);
113 GNUNET_DATASTORE_Iterator iter, void *iter_cls);
114 165
115 166
116/** 167/**
@@ -135,11 +186,10 @@ typedef void
135 * @param msg set to an error message (on error) 186 * @param msg set to an error message (on error)
136 * @return GNUNET_OK on success 187 * @return GNUNET_OK on success
137 */ 188 */
138typedef int 189typedef int (*PluginUpdate) (void *cls,
139 (*GNUNET_DATASTORE_Update) (void *cls, 190 uint64_t uid,
140 unsigned long long uid, 191 int delta, struct GNUNET_TIME_Absolute expire,
141 int delta, struct GNUNET_TIME_Absolute expire, 192 char **msg);
142 char **msg);
143 193
144 194
145/** 195/**
@@ -148,20 +198,23 @@ typedef int
148 * 198 *
149 * @param type entries of which type should be considered? 199 * @param type entries of which type should be considered?
150 * Use 0 for any type. 200 * Use 0 for any type.
151 * @param iter function to call on each matching value; 201 * @param iter function to call on each matching value; however,
152 * will be called once with a NULL value at the end 202 * after the first call to "iter", the plugin must wait
203 * until "NextRequest" was called before giving the iterator
204 * the next item; finally, the "iter" should be called once
205 * once with a NULL value at the end ("next_cls" should be NULL
206 * for that last call)
153 * @param iter_cls closure for iter 207 * @param iter_cls closure for iter
154 */ 208 */
155typedef void 209typedef void (*PluginSelector) (void *cls,
156 (*GNUNET_DATASTORE_Selector) (void *cls,
157 uint32_t type, 210 uint32_t type,
158 GNUNET_DATASTORE_Iterator iter, 211 PluginIterator iter,
159 void *iter_cls); 212 void *iter_cls);
160 213
161/** 214/**
162 * Drop database. 215 * Drop database.
163 */ 216 */
164typedef void (*GNUNET_DATASTORE_Drop) (void *cls); 217typedef void (*PluginDrop) (void *cls);
165 218
166 219
167 220
@@ -173,7 +226,8 @@ struct GNUNET_DATASTORE_PluginFunctions
173{ 226{
174 227
175 /** 228 /**
176 * Closure to use for all of the following callbacks. 229 * Closure to use for all of the following callbacks
230 * (except "next_request").
177 */ 231 */
178 void *cls; 232 void *cls;
179 233
@@ -181,18 +235,26 @@ struct GNUNET_DATASTORE_PluginFunctions
181 * Get the current on-disk size of the SQ store. Estimates are 235 * Get the current on-disk size of the SQ store. Estimates are
182 * fine, if that's the only thing available. 236 * fine, if that's the only thing available.
183 */ 237 */
184 GNUNET_DATASTORE_GetSize get_size; 238 PluginGetSize get_size;
185 239
186 /** 240 /**
187 * Function to store an item in the datastore. 241 * Function to store an item in the datastore.
188 */ 242 */
189 GNUNET_DATASTORE_Put put; 243 PluginPut put;
244
245 /**
246 * Function called by iterators whenever they want the next value;
247 * note that unlike all of the other callbacks, this one does get a
248 * the "next_cls" closure which is usually different from the "cls"
249 * member of this struct!
250 */
251 PluginNextRequest next_request;
190 252
191 /** 253 /**
192 * Function to iterate over the results for a particular key 254 * Function to iterate over the results for a particular key
193 * in the datastore. 255 * in the datastore.
194 */ 256 */
195 GNUNET_DATASTORE_Get get; 257 PluginGet get;
196 258
197 /** 259 /**
198 * Update the priority for a particular key in the datastore. If 260 * Update the priority for a particular key in the datastore. If
@@ -202,24 +264,24 @@ struct GNUNET_DATASTORE_PluginFunctions
202 * priority should be added to the existing priority, ignoring the 264 * priority should be added to the existing priority, ignoring the
203 * priority in value. 265 * priority in value.
204 */ 266 */
205 GNUNET_DATASTORE_Update update; 267 PluginUpdate update;
206 268
207 /** 269 /**
208 * Iterate over the items in the datastore in ascending 270 * Iterate over the items in the datastore in ascending
209 * order of priority. 271 * order of priority.
210 */ 272 */
211 GNUNET_DATASTORE_Selector iter_low_priority; 273 PluginSelector iter_low_priority;
212 274
213 /** 275 /**
214 * Iterate over content with anonymity zero. 276 * Iterate over content with anonymity zero.
215 */ 277 */
216 GNUNET_DATASTORE_Selector iter_zero_anonymity; 278 PluginSelector iter_zero_anonymity;
217 279
218 /** 280 /**
219 * Iterate over the items in the datastore in ascending order of 281 * Iterate over the items in the datastore in ascending order of
220 * expiration time. 282 * expiration time.
221 */ 283 */
222 GNUNET_DATASTORE_Selector iter_ascending_expiration; 284 PluginSelector iter_ascending_expiration;
223 285
224 /** 286 /**
225 * Iterate over the items in the datastore in migration 287 * Iterate over the items in the datastore in migration
@@ -227,7 +289,7 @@ struct GNUNET_DATASTORE_PluginFunctions
227 * (and then signal 'end' with a second call). This is 289 * (and then signal 'end' with a second call). This is
228 * a significant difference from all the other iterators! 290 * a significant difference from all the other iterators!
229 */ 291 */
230 GNUNET_DATASTORE_Selector iter_migration_order; 292 PluginSelector iter_migration_order;
231 293
232 /** 294 /**
233 * Iterate over all the items in the datastore 295 * Iterate over all the items in the datastore
@@ -235,13 +297,13 @@ struct GNUNET_DATASTORE_PluginFunctions
235 * (can lock datastore while this happens, focus 297 * (can lock datastore while this happens, focus
236 * is on doing it fast). 298 * is on doing it fast).
237 */ 299 */
238 GNUNET_DATASTORE_Selector iter_all_now; 300 PluginSelector iter_all_now;
239 301
240 /** 302 /**
241 * Delete the database. The next operation is 303 * Delete the database. The next operation is
242 * guaranteed to be unloading of the module. 304 * guaranteed to be unloading of the module.
243 */ 305 */
244 GNUNET_DATASTORE_Drop drop; 306 PluginDrop drop;
245 307
246}; 308};
247 309
diff --git a/src/datastore/plugin_datastore_sqlite.c b/src/datastore/plugin_datastore_sqlite.c
index 234519079..6bee1a0c9 100644
--- a/src/datastore/plugin_datastore_sqlite.c
+++ b/src/datastore/plugin_datastore_sqlite.c
@@ -51,6 +51,26 @@ static unsigned long long sqlite_plugin_get_size (void *cls)
51} 51}
52 52
53 53
54
55/**
56 * Function invoked on behalf of a "PluginIterator"
57 * asking the database plugin to call the iterator
58 * with the next item.
59 *
60 * @param next_cls whatever argument was given
61 * to the PluginIterator as "next_cls".
62 * @param end_it set to GNUNET_YES if we
63 * should terminate the iteration early
64 * (iterator should be still called once more
65 * to signal the end of the iteration).
66 */
67static void
68sqlite_next_request (void *next_cls,
69 int end_it)
70{
71}
72
73
54/** 74/**
55 * Store an item in the datastore. 75 * Store an item in the datastore.
56 * 76 *
@@ -103,10 +123,10 @@ sqlite_plugin_get (void *cls,
103 const GNUNET_HashCode * key, 123 const GNUNET_HashCode * key,
104 const GNUNET_HashCode * vhash, 124 const GNUNET_HashCode * vhash,
105 uint32_t type, 125 uint32_t type,
106 GNUNET_DATASTORE_Iterator iter, void *iter_cls) 126 PluginIterator iter, void *iter_cls)
107{ 127{
108 static struct GNUNET_TIME_Absolute zero; 128 static struct GNUNET_TIME_Absolute zero;
109 iter (iter_cls, NULL, 0, NULL, 0, 0, 0, zero, 0); 129 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, zero, 0);
110} 130}
111 131
112 132
@@ -155,12 +175,12 @@ sqlite_plugin_update (void *cls,
155 */ 175 */
156static void 176static void
157sqlite_plugin_iter_low_priority (void *cls, 177sqlite_plugin_iter_low_priority (void *cls,
158 uint32_t type, 178 uint32_t type,
159 GNUNET_DATASTORE_Iterator iter, 179 PluginIterator iter,
160 void *iter_cls) 180 void *iter_cls)
161{ 181{
162 static struct GNUNET_TIME_Absolute zero; 182 static struct GNUNET_TIME_Absolute zero;
163 iter (iter_cls, NULL, 0, NULL, 0, 0, 0, zero, 0); 183 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, zero, 0);
164} 184}
165 185
166 186
@@ -176,12 +196,12 @@ sqlite_plugin_iter_low_priority (void *cls,
176 */ 196 */
177static void 197static void
178sqlite_plugin_iter_zero_anonymity (void *cls, 198sqlite_plugin_iter_zero_anonymity (void *cls,
179 uint32_t type, 199 uint32_t type,
180 GNUNET_DATASTORE_Iterator iter, 200 PluginIterator iter,
181 void *iter_cls) 201 void *iter_cls)
182{ 202{
183 static struct GNUNET_TIME_Absolute zero; 203 static struct GNUNET_TIME_Absolute zero;
184 iter (iter_cls, NULL, 0, NULL, 0, 0, 0, zero, 0); 204 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, zero, 0);
185} 205}
186 206
187 207
@@ -198,12 +218,12 @@ sqlite_plugin_iter_zero_anonymity (void *cls,
198 */ 218 */
199static void 219static void
200sqlite_plugin_iter_ascending_expiration (void *cls, 220sqlite_plugin_iter_ascending_expiration (void *cls,
201 uint32_t type, 221 uint32_t type,
202 GNUNET_DATASTORE_Iterator iter, 222 PluginIterator iter,
203 void *iter_cls) 223 void *iter_cls)
204{ 224{
205 static struct GNUNET_TIME_Absolute zero; 225 static struct GNUNET_TIME_Absolute zero;
206 iter (iter_cls, NULL, 0, NULL, 0, 0, 0, zero, 0); 226 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, zero, 0);
207} 227}
208 228
209 229
@@ -220,12 +240,12 @@ sqlite_plugin_iter_ascending_expiration (void *cls,
220 */ 240 */
221static void 241static void
222sqlite_plugin_iter_migration_order (void *cls, 242sqlite_plugin_iter_migration_order (void *cls,
223 uint32_t type, 243 uint32_t type,
224 GNUNET_DATASTORE_Iterator iter, 244 PluginIterator iter,
225 void *iter_cls) 245 void *iter_cls)
226{ 246{
227 static struct GNUNET_TIME_Absolute zero; 247 static struct GNUNET_TIME_Absolute zero;
228 iter (iter_cls, NULL, 0, NULL, 0, 0, 0, zero, 0); 248 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, zero, 0);
229} 249}
230 250
231 251
@@ -242,12 +262,12 @@ sqlite_plugin_iter_migration_order (void *cls,
242 */ 262 */
243static void 263static void
244sqlite_plugin_iter_all_now (void *cls, 264sqlite_plugin_iter_all_now (void *cls,
245 uint32_t type, 265 uint32_t type,
246 GNUNET_DATASTORE_Iterator iter, 266 PluginIterator iter,
247 void *iter_cls) 267 void *iter_cls)
248{ 268{
249 static struct GNUNET_TIME_Absolute zero; 269 static struct GNUNET_TIME_Absolute zero;
250 iter (iter_cls, NULL, 0, NULL, 0, 0, 0, zero, 0); 270 iter (iter_cls, NULL, NULL, 0, NULL, 0, 0, 0, zero, 0);
251} 271}
252 272
253 273
@@ -276,6 +296,7 @@ libgnunet_plugin_datastore_sqlite_init (void *cls)
276 api->cls = plugin; 296 api->cls = plugin;
277 api->get_size = &sqlite_plugin_get_size; 297 api->get_size = &sqlite_plugin_get_size;
278 api->put = &sqlite_plugin_put; 298 api->put = &sqlite_plugin_put;
299 api->next_request = &sqlite_next_request;
279 api->get = &sqlite_plugin_get; 300 api->get = &sqlite_plugin_get;
280 api->update = &sqlite_plugin_update; 301 api->update = &sqlite_plugin_update;
281 api->iter_low_priority = &sqlite_plugin_iter_low_priority; 302 api->iter_low_priority = &sqlite_plugin_iter_low_priority;
diff --git a/src/datastore/plugin_datastore_template.c b/src/datastore/plugin_datastore_template.c
index 1e3d4343b..4c8f9e1f9 100644
--- a/src/datastore/plugin_datastore_template.c
+++ b/src/datastore/plugin_datastore_template.c
@@ -82,6 +82,25 @@ template_plugin_put (void *cls,
82 82
83 83
84/** 84/**
85 * Function invoked on behalf of a "PluginIterator"
86 * asking the database plugin to call the iterator
87 * with the next item.
88 *
89 * @param next_cls whatever argument was given
90 * to the PluginIterator as "next_cls".
91 * @param end_it set to GNUNET_YES if we
92 * should terminate the iteration early
93 * (iterator should be still called once more
94 * to signal the end of the iteration).
95 */
96static void
97template_next_request (void *next_cls,
98 int end_it)
99{
100}
101
102
103/**
85 * Iterate over the results for a particular key 104 * Iterate over the results for a particular key
86 * in the datastore. 105 * in the datastore.
87 * 106 *
@@ -100,10 +119,10 @@ template_plugin_put (void *cls,
100 */ 119 */
101static void 120static void
102template_plugin_get (void *cls, 121template_plugin_get (void *cls,
103 const GNUNET_HashCode * key, 122 const GNUNET_HashCode * key,
104 const GNUNET_HashCode * vhash, 123 const GNUNET_HashCode * vhash,
105 uint32_t type, 124 uint32_t type,
106 GNUNET_DATASTORE_Iterator iter, void *iter_cls) 125 PluginIterator iter, void *iter_cls)
107{ 126{
108} 127}
109 128
@@ -153,9 +172,9 @@ template_plugin_update (void *cls,
153 */ 172 */
154static void 173static void
155template_plugin_iter_low_priority (void *cls, 174template_plugin_iter_low_priority (void *cls,
156 uint32_t type, 175 uint32_t type,
157 GNUNET_DATASTORE_Iterator iter, 176 PluginIterator iter,
158 void *iter_cls) 177 void *iter_cls)
159{ 178{
160} 179}
161 180
@@ -174,7 +193,7 @@ template_plugin_iter_low_priority (void *cls,
174static void 193static void
175template_plugin_iter_zero_anonymity (void *cls, 194template_plugin_iter_zero_anonymity (void *cls,
176 uint32_t type, 195 uint32_t type,
177 GNUNET_DATASTORE_Iterator iter, 196 PluginIterator iter,
178 void *iter_cls) 197 void *iter_cls)
179{ 198{
180} 199}
@@ -194,7 +213,7 @@ template_plugin_iter_zero_anonymity (void *cls,
194static void 213static void
195template_plugin_iter_ascending_expiration (void *cls, 214template_plugin_iter_ascending_expiration (void *cls,
196 uint32_t type, 215 uint32_t type,
197 GNUNET_DATASTORE_Iterator iter, 216 PluginIterator iter,
198 void *iter_cls) 217 void *iter_cls)
199{ 218{
200} 219}
@@ -214,7 +233,7 @@ template_plugin_iter_ascending_expiration (void *cls,
214static void 233static void
215template_plugin_iter_migration_order (void *cls, 234template_plugin_iter_migration_order (void *cls,
216 uint32_t type, 235 uint32_t type,
217 GNUNET_DATASTORE_Iterator iter, 236 PluginIterator iter,
218 void *iter_cls) 237 void *iter_cls)
219{ 238{
220} 239}
@@ -234,7 +253,7 @@ template_plugin_iter_migration_order (void *cls,
234static void 253static void
235template_plugin_iter_all_now (void *cls, 254template_plugin_iter_all_now (void *cls,
236 uint32_t type, 255 uint32_t type,
237 GNUNET_DATASTORE_Iterator iter, 256 PluginIterator iter,
238 void *iter_cls) 257 void *iter_cls)
239{ 258{
240} 259}
@@ -265,6 +284,7 @@ libgnunet_plugin_datastore_template_init (void *cls)
265 api->cls = plugin; 284 api->cls = plugin;
266 api->get_size = &template_plugin_get_size; 285 api->get_size = &template_plugin_get_size;
267 api->put = &template_plugin_put; 286 api->put = &template_plugin_put;
287 api->next_request = &template_next_request;
268 api->get = &template_plugin_get; 288 api->get = &template_plugin_get;
269 api->update = &template_plugin_update; 289 api->update = &template_plugin_update;
270 api->iter_low_priority = &template_plugin_iter_low_priority; 290 api->iter_low_priority = &template_plugin_iter_low_priority;
diff --git a/src/include/gnunet_datastore_service.h b/src/include/gnunet_datastore_service.h
index 626a5afcc..10b2157d3 100644
--- a/src/include/gnunet_datastore_service.h
+++ b/src/include/gnunet_datastore_service.h
@@ -189,19 +189,16 @@ GNUNET_DATASTORE_update (struct GNUNET_DATASTORE_Handle *h,
189 * @param expiration expiration time for the content 189 * @param expiration expiration time for the content
190 * @param uid unique identifier for the datum; 190 * @param uid unique identifier for the datum;
191 * maybe 0 if no unique identifier is available 191 * maybe 0 if no unique identifier is available
192 *
193 * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue,
194 * GNUNET_NO to delete the item and continue (if supported)
195 */ 192 */
196typedef int (*GNUNET_DATASTORE_Iterator) (void *cls, 193typedef void (*GNUNET_DATASTORE_Iterator) (void *cls,
197 const GNUNET_HashCode * key, 194 const GNUNET_HashCode * key,
198 uint32_t size, 195 uint32_t size,
199 const void *data, 196 const void *data,
200 uint32_t type, 197 uint32_t type,
201 uint32_t priority, 198 uint32_t priority,
202 uint32_t anonymity, 199 uint32_t anonymity,
203 struct GNUNET_TIME_Absolute 200 struct GNUNET_TIME_Absolute
204 expiration, unsigned long long uid); 201 expiration, uint64_t uid);
205 202
206 203
207/** 204/**