2 This file is part of GNUnet
3 (C) 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file datastore/datastore_api.c
23 * @brief Management for the datastore for files stored on a GNUnet node
24 * @author Christian Grothoff
27 #include "gnunet_arm_service.h"
28 #include "gnunet_datastore_service.h"
29 #include "datastore.h"
32 * Handle to the datastore service. Followed
33 * by 65536 bytes used for storing messages.
35 struct GNUNET_DATASTORE_Handle
41 const struct GNUNET_CONFIGURATION_Handle *cfg;
46 struct GNUNET_SCHEDULER_Handle *sched;
49 * Current connection to the datastore service.
51 struct GNUNET_CLIENT_Connection *client;
54 * Current response processor (NULL if we are not waiting for a
55 * response). The specific type depends on the kind of message we
61 * Closure for response_proc.
63 void *response_proc_cls;
66 * Timeout for the current operation.
68 struct GNUNET_TIME_Absolute timeout;
71 * Number of bytes in the message following
72 * this struct, 0 if we have no request pending.
81 * Connect to the datastore service.
83 * @param cfg configuration to use
84 * @param sched scheduler to use
85 * @return handle to use to access the service
87 struct GNUNET_DATASTORE_Handle *GNUNET_DATASTORE_connect (const struct
88 GNUNET_CONFIGURATION_Handle
91 GNUNET_SCHEDULER_Handle
94 struct GNUNET_CLIENT_Connection *c;
95 struct GNUNET_DATASTORE_Handle *h;
97 c = GNUNET_CLIENT_connect (sched, "datastore", cfg);
99 return NULL; /* oops */
100 GNUNET_ARM_start_services (cfg, sched, "datastore", NULL);
101 h = GNUNET_malloc (sizeof(struct GNUNET_DATASTORE_Handle) +
102 GNUNET_SERVER_MAX_MESSAGE_SIZE);
111 * Transmit DROP message to datastore service.
114 transmit_drop (void *cls,
115 size_t size, void *buf)
117 struct GNUNET_DATASTORE_Handle *h = cls;
118 struct GNUNET_MessageHeader *hdr;
122 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
123 _("Failed to transmit request to drop database.\n"));
124 GNUNET_DATASTORE_disconnect (h, GNUNET_NO);
127 GNUNET_assert (size >= sizeof(struct GNUNET_MessageHeader));
129 hdr->size = htons(sizeof(struct GNUNET_MessageHeader));
130 hdr->type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_DROP);
131 GNUNET_DATASTORE_disconnect (h, GNUNET_NO);
132 return sizeof(struct GNUNET_MessageHeader);
137 * Disconnect from the datastore service (and free
138 * associated resources).
140 * @param h handle to the datastore
141 * @param drop set to GNUNET_YES to delete all data in datastore (!)
143 void GNUNET_DATASTORE_disconnect (struct GNUNET_DATASTORE_Handle *h,
146 if (h->client != NULL)
147 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
149 if (GNUNET_YES == drop)
151 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
152 if (h->client != NULL)
155 GNUNET_CLIENT_notify_transmit_ready (h->client,
156 sizeof(struct GNUNET_MessageHeader),
157 GNUNET_TIME_UNIT_MINUTES,
162 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
166 GNUNET_ARM_stop_services (h->cfg, h->sched, "datastore", NULL);
172 * Type of a function to call when we receive a message
173 * from the service. This specific function is used
174 * to handle messages of type "struct StatusMessage".
177 * @param msg message received, NULL on timeout or fatal error
180 with_status_response_handler (void *cls,
182 GNUNET_MessageHeader * msg)
184 struct GNUNET_DATASTORE_Handle *h = cls;
185 GNUNET_DATASTORE_ContinuationWithStatus cont = h->response_proc;
186 const struct StatusMessage *sm;
193 h->response_proc = NULL;
194 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
195 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
196 cont (h->response_proc_cls,
198 _("Timeout trying to read response from datastore service"));
201 if ( (ntohs(msg->size) < sizeof(struct StatusMessage)) ||
202 (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_DATASTORE_STATUS) )
205 h->response_proc = NULL;
206 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
207 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
208 cont (h->response_proc_cls,
210 _("Error reading response from datastore service"));
213 sm = (const struct StatusMessage*) msg;
214 status = ntohl(sm->status);
216 if (ntohs(msg->size) > sizeof(struct StatusMessage))
218 emsg = (const char*) &sm[1];
219 if (emsg[ntohs(msg->size) - sizeof(struct StatusMessage) - 1] != '\0')
222 emsg = _("Invalid error message received from datastore service");
225 if ( (status == GNUNET_SYSERR) &&
229 emsg = _("Invalid error message received from datastore service");
231 h->response_proc = NULL;
233 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
234 "Received status %d/%s\n",
238 cont (h->response_proc_cls,
245 * Helper function that will initiate the
246 * transmission of a message to the datastore
247 * service. The message must already be prepared
248 * and stored in the buffer at the end of the
249 * handle. The message must be of a type that
250 * expects a "StatusMessage" in response.
252 * @param h handle to the service with prepared message
253 * @param cont function to call with result
254 * @param cont_cls closure
255 * @param timeout timeout for the operation
258 transmit_for_status (struct GNUNET_DATASTORE_Handle *h,
259 GNUNET_DATASTORE_ContinuationWithStatus cont,
261 struct GNUNET_TIME_Relative timeout)
263 const struct GNUNET_MessageHeader *hdr;
266 GNUNET_assert (cont != NULL);
267 hdr = (const struct GNUNET_MessageHeader*) &h[1];
268 msize = ntohs(hdr->size);
270 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
271 "Transmitting %u byte message of type %u to datastore service\n",
275 GNUNET_assert (h->response_proc == NULL);
276 h->response_proc = cont;
277 h->response_proc_cls = cont_cls;
278 h->timeout = GNUNET_TIME_relative_to_absolute (timeout);
279 h->message_size = msize;
281 GNUNET_CLIENT_transmit_and_get_response (h->client,
285 &with_status_response_handler,
289 h->response_proc = NULL;
293 _("Not ready to transmit request to datastore service"));
299 * Store an item in the datastore. If the item is already present,
300 * the priorities are summed up and the higher expiration time and
301 * lower anonymity level is used.
303 * @param h handle to the datastore
304 * @param rid reservation ID to use (from "reserve"); use 0 if no
305 * prior reservation was made
306 * @param key key for the value
307 * @param size number of bytes in data
308 * @param data content stored
309 * @param type type of the content
310 * @param priority priority of the content
311 * @param anonymity anonymity-level for the content
312 * @param expiration expiration time for the content
313 * @param timeout timeout for the operation
314 * @param cont continuation to call when done
315 * @param cont_cls closure for cont
318 GNUNET_DATASTORE_put (struct GNUNET_DATASTORE_Handle *h,
320 const GNUNET_HashCode * key,
326 struct GNUNET_TIME_Absolute expiration,
327 struct GNUNET_TIME_Relative timeout,
328 GNUNET_DATASTORE_ContinuationWithStatus cont,
331 struct DataMessage *dm;
335 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
336 "Asked to put %u bytes of data under key `%s'\n",
340 msize = sizeof(struct DataMessage) + size;
341 GNUNET_assert (msize <= GNUNET_SERVER_MAX_MESSAGE_SIZE);
342 dm = (struct DataMessage*) &h[1];
343 dm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_PUT);
344 dm->header.size = htons(msize);
345 dm->rid = htonl(rid);
346 dm->size = htonl(size);
347 dm->type = htonl(type);
348 dm->priority = htonl(priority);
349 dm->anonymity = htonl(anonymity);
350 dm->uid = GNUNET_htonll(0);
351 dm->expiration = GNUNET_TIME_absolute_hton(expiration);
353 memcpy (&dm[1], data, size);
354 transmit_for_status (h, cont, cont_cls, timeout);
359 * Reserve space in the datastore. This function should be used
360 * to avoid "out of space" failures during a longer sequence of "put"
361 * operations (for example, when a file is being inserted).
363 * @param h handle to the datastore
364 * @param amount how much space (in bytes) should be reserved (for content only)
365 * @param entries how many entries will be created (to calculate per-entry overhead)
366 * @param cont continuation to call when done; "success" will be set to
367 * a positive reservation value if space could be reserved.
368 * @param cont_cls closure for cont
369 * @param timeout how long to wait at most for a response
372 GNUNET_DATASTORE_reserve (struct GNUNET_DATASTORE_Handle *h,
375 GNUNET_DATASTORE_ContinuationWithStatus cont,
377 struct GNUNET_TIME_Relative timeout)
379 struct ReserveMessage *rm;
381 rm = (struct ReserveMessage*) &h[1];
382 rm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_RESERVE);
383 rm->header.size = htons(sizeof (struct ReserveMessage));
384 rm->entries = htonl(entries);
385 rm->amount = GNUNET_htonll(amount);
386 transmit_for_status (h, cont, cont_cls, timeout);
391 * Signal that all of the data for which a reservation was made has
392 * been stored and that whatever excess space might have been reserved
393 * can now be released.
395 * @param h handle to the datastore
396 * @param rid reservation ID (value of "success" in original continuation
397 * from the "reserve" function).
398 * @param cont continuation to call when done
399 * @param cont_cls closure for cont
400 * @param timeout how long to wait at most for a response
403 GNUNET_DATASTORE_release_reserve (struct GNUNET_DATASTORE_Handle *h,
405 GNUNET_DATASTORE_ContinuationWithStatus cont,
407 struct GNUNET_TIME_Relative timeout)
409 struct ReleaseReserveMessage *rrm;
411 rrm = (struct ReleaseReserveMessage*) &h[1];
412 rrm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_RELEASE_RESERVE);
413 rrm->header.size = htons(sizeof (struct ReleaseReserveMessage));
414 rrm->rid = htonl(rid);
415 transmit_for_status (h, cont, cont_cls, timeout);
420 * Update a value in the datastore.
422 * @param h handle to the datastore
423 * @param uid identifier for the value
424 * @param priority how much to increase the priority of the value
425 * @param expiration new expiration value should be MAX of existing and this argument
426 * @param cont continuation to call when done
427 * @param cont_cls closure for cont
428 * @param timeout how long to wait at most for a response
431 GNUNET_DATASTORE_update (struct GNUNET_DATASTORE_Handle *h,
432 unsigned long long uid,
434 struct GNUNET_TIME_Absolute expiration,
435 GNUNET_DATASTORE_ContinuationWithStatus cont,
437 struct GNUNET_TIME_Relative timeout)
439 struct UpdateMessage *um;
441 um = (struct UpdateMessage*) &h[1];
442 um->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_UPDATE);
443 um->header.size = htons(sizeof (struct UpdateMessage));
444 um->priority = htonl(priority);
445 um->expiration = GNUNET_TIME_absolute_hton(expiration);
446 um->uid = GNUNET_htonll(uid);
447 transmit_for_status (h, cont, cont_cls, timeout);
452 * Helper function that will initiate the transmission of a message to
453 * the datastore service. The message must already be prepared and
454 * stored in the buffer at the end of the handle. The message must be
455 * of a type that expects a "DataMessage" in response.
457 * @param h handle to the service with prepared message
458 * @param cont function to call with result
459 * @param cont_cls closure
460 * @param timeout timeout for the operation
463 transmit_for_result (struct GNUNET_DATASTORE_Handle *h,
464 GNUNET_DATASTORE_Iterator cont,
466 struct GNUNET_TIME_Relative timeout);
470 * Type of a function to call when we receive a message
471 * from the service. This specific function is used
472 * to handle messages of type "struct DataMessage".
475 * @param msg message received, NULL on timeout or fatal error
478 with_result_response_handler (void *cls,
480 GNUNET_MessageHeader * msg)
482 struct GNUNET_DATASTORE_Handle *h = cls;
483 GNUNET_DATASTORE_Iterator cont = h->response_proc;
484 const struct DataMessage *dm;
486 struct GNUNET_TIME_Relative remaining;
491 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
492 "Got disconnected from datastore\n");
494 h->response_proc = NULL;
495 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
496 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
497 remaining = GNUNET_TIME_absolute_get_remaining (h->timeout);
498 if (remaining.value > 0)
500 transmit_for_result (h,
502 h->response_proc_cls,
508 cont (h->response_proc_cls,
509 NULL, 0, NULL, 0, 0, 0,
510 GNUNET_TIME_UNIT_ZERO_ABS, 0);
515 if (ntohs(msg->type) == GNUNET_MESSAGE_TYPE_DATASTORE_DATA_END)
517 GNUNET_break (ntohs(msg->size) == sizeof(struct GNUNET_MessageHeader));
518 h->response_proc = NULL;
520 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
521 "Received end of result set\n");
523 cont (h->response_proc_cls,
524 NULL, 0, NULL, 0, 0, 0,
525 GNUNET_TIME_UNIT_ZERO_ABS, 0);
528 if ( (ntohs(msg->size) < sizeof(struct DataMessage)) ||
529 (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_DATASTORE_DATA) )
532 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
533 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
534 h->response_proc = NULL;
535 cont (h->response_proc_cls,
536 NULL, 0, NULL, 0, 0, 0,
537 GNUNET_TIME_UNIT_ZERO_ABS, 0);
540 dm = (const struct DataMessage*) msg;
541 msize = ntohl(dm->size);
542 if (ntohs(msg->size) != msize + sizeof(struct DataMessage))
545 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
546 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
547 h->response_proc = NULL;
548 cont (h->response_proc_cls,
549 NULL, 0, NULL, 0, 0, 0,
550 GNUNET_TIME_UNIT_ZERO_ABS, 0);
554 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
555 "Received result %llu with type %u and size %u with key %s\n",
556 (unsigned long long) GNUNET_ntohll(dm->uid),
559 GNUNET_h2s(&dm->key));
561 cont (h->response_proc_cls,
567 ntohl(dm->anonymity),
568 GNUNET_TIME_absolute_ntoh(dm->expiration),
569 GNUNET_ntohll(dm->uid));
574 * Function called to trigger obtaining the next result
575 * from the datastore.
577 * @param h handle to the datastore
578 * @param more GNUNET_YES to get moxre results, GNUNET_NO to abort
579 * iteration (with a final call to "iter" with key/data == NULL).
582 GNUNET_DATASTORE_get_next (struct GNUNET_DATASTORE_Handle *h,
585 GNUNET_DATASTORE_Iterator cont;
587 if (GNUNET_YES == more)
589 GNUNET_CLIENT_receive (h->client,
590 &with_result_response_handler,
592 GNUNET_TIME_absolute_get_remaining (h->timeout));
595 cont = h->response_proc;
596 h->response_proc = NULL;
597 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
598 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
599 cont (h->response_proc_cls,
600 NULL, 0, NULL, 0, 0, 0,
601 GNUNET_TIME_UNIT_ZERO_ABS, 0);
606 * Helper function that will initiate the transmission of a message to
607 * the datastore service. The message must already be prepared and
608 * stored in the buffer at the end of the handle. The message must be
609 * of a type that expects a "DataMessage" in response.
611 * @param h handle to the service with prepared message
612 * @param cont function to call with result
613 * @param cont_cls closure
614 * @param timeout timeout for the operation
617 transmit_for_result (struct GNUNET_DATASTORE_Handle *h,
618 GNUNET_DATASTORE_Iterator cont,
620 struct GNUNET_TIME_Relative timeout)
622 const struct GNUNET_MessageHeader *hdr;
625 GNUNET_assert (cont != NULL);
626 hdr = (const struct GNUNET_MessageHeader*) &h[1];
627 msize = ntohs(hdr->size);
629 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
630 "Transmitting %u byte message of type %u to datastore service\n",
634 GNUNET_assert (h->response_proc == NULL);
635 h->response_proc = cont;
636 h->response_proc_cls = cont_cls;
637 h->timeout = GNUNET_TIME_relative_to_absolute (timeout);
638 h->message_size = msize;
640 GNUNET_CLIENT_transmit_and_get_response (h->client,
644 &with_result_response_handler,
648 h->response_proc = NULL;
650 cont (h->response_proc_cls,
651 NULL, 0, NULL, 0, 0, 0,
652 GNUNET_TIME_UNIT_ZERO_ABS, 0);
658 * Iterate over the results for a particular key
661 * @param h handle to the datastore
662 * @param key maybe NULL (to match all entries)
663 * @param type desired type, 0 for any
664 * @param iter function to call on each matching value;
665 * will be called once with a NULL value at the end
666 * @param iter_cls closure for iter
667 * @param timeout how long to wait at most for a response
670 GNUNET_DATASTORE_get (struct GNUNET_DATASTORE_Handle *h,
671 const GNUNET_HashCode * key,
673 GNUNET_DATASTORE_Iterator iter, void *iter_cls,
674 struct GNUNET_TIME_Relative timeout)
676 struct GetMessage *gm;
679 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
680 "Asked to look for data under key `%s'\n",
683 gm = (struct GetMessage*) &h[1];
684 gm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_GET);
685 gm->type = htonl(type);
688 gm->header.size = htons(sizeof (struct GetMessage));
693 gm->header.size = htons(sizeof (struct GetMessage) - sizeof(GNUNET_HashCode));
695 GNUNET_assert (h->response_proc == NULL);
696 transmit_for_result (h, iter, iter_cls, timeout);
701 * Get a random value from the datastore.
703 * @param h handle to the datastore
704 * @param iter function to call on a random value; it
705 * will be called exactly once; if no values
706 * are available, the value will be NULL.
707 * @param iter_cls closure for iter
708 * @param timeout how long to wait at most for a response
711 GNUNET_DATASTORE_get_random (struct GNUNET_DATASTORE_Handle *h,
712 GNUNET_DATASTORE_Iterator iter, void *iter_cls,
713 struct GNUNET_TIME_Relative timeout)
715 struct GNUNET_MessageHeader *m;
717 m = (struct GNUNET_MessageHeader*) &h[1];
718 m->type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_GET_RANDOM);
719 m->size = htons(sizeof (struct GNUNET_MessageHeader));
720 GNUNET_assert (h->response_proc == NULL);
721 transmit_for_result (h, iter, iter_cls, timeout);
726 * Explicitly remove some content from the database.
728 * @param h handle to the datastore
729 * @param key key for the value
730 * @param size number of bytes in data
731 * @param data content stored
732 * @param cont continuation to call when done
733 * @param cont_cls closure for cont
734 * @param timeout how long to wait at most for a response
737 GNUNET_DATASTORE_remove (struct GNUNET_DATASTORE_Handle *h,
738 const GNUNET_HashCode * key,
739 uint32_t size, const void *data,
740 GNUNET_DATASTORE_ContinuationWithStatus cont,
742 struct GNUNET_TIME_Relative timeout)
744 struct DataMessage *dm;
748 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
749 "Asked to remove %u bytes of data under key `%s'\n",
753 msize = sizeof(struct DataMessage) + size;
754 GNUNET_assert (msize <= GNUNET_SERVER_MAX_MESSAGE_SIZE);
755 dm = (struct DataMessage*) &h[1];
756 dm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE);
757 dm->header.size = htons(msize);
759 dm->size = htonl(size);
761 dm->priority = htonl(0);
762 dm->anonymity = htonl(0);
763 dm->uid = GNUNET_htonll(0);
764 dm->expiration = GNUNET_TIME_absolute_hton(GNUNET_TIME_UNIT_ZERO_ABS);
766 memcpy (&dm[1], data, size);
767 transmit_for_status (h, cont, cont_cls, timeout);
771 /* end of datastore_api.c */