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 h = GNUNET_malloc (sizeof(struct GNUNET_DATASTORE_Handle) +
101 GNUNET_SERVER_MAX_MESSAGE_SIZE);
110 * Transmit DROP message to datastore service.
113 transmit_drop (void *cls,
114 size_t size, void *buf)
116 struct GNUNET_DATASTORE_Handle *h = cls;
117 struct GNUNET_MessageHeader *hdr;
121 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
122 _("Failed to transmit request to drop database.\n"));
123 GNUNET_DATASTORE_disconnect (h, GNUNET_NO);
126 GNUNET_assert (size >= sizeof(struct GNUNET_MessageHeader));
128 hdr->size = htons(sizeof(struct GNUNET_MessageHeader));
129 hdr->type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_DROP);
130 GNUNET_DATASTORE_disconnect (h, GNUNET_NO);
131 return sizeof(struct GNUNET_MessageHeader);
136 * Disconnect from the datastore service (and free
137 * associated resources).
139 * @param h handle to the datastore
140 * @param drop set to GNUNET_YES to delete all data in datastore (!)
142 void GNUNET_DATASTORE_disconnect (struct GNUNET_DATASTORE_Handle *h,
145 if (h->client != NULL)
146 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
148 if (GNUNET_YES == drop)
150 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
151 if (h->client != NULL)
154 GNUNET_CLIENT_notify_transmit_ready (h->client,
155 sizeof(struct GNUNET_MessageHeader),
156 GNUNET_TIME_UNIT_MINUTES,
161 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
170 * Type of a function to call when we receive a message
171 * from the service. This specific function is used
172 * to handle messages of type "struct StatusMessage".
175 * @param msg message received, NULL on timeout or fatal error
178 with_status_response_handler (void *cls,
180 GNUNET_MessageHeader * msg)
182 struct GNUNET_DATASTORE_Handle *h = cls;
183 GNUNET_DATASTORE_ContinuationWithStatus cont = h->response_proc;
184 const struct StatusMessage *sm;
191 h->response_proc = NULL;
192 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
193 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
194 cont (h->response_proc_cls,
196 _("Timeout trying to read response from datastore service"));
199 if ( (ntohs(msg->size) < sizeof(struct StatusMessage)) ||
200 (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_DATASTORE_STATUS) )
203 h->response_proc = NULL;
204 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
205 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
206 cont (h->response_proc_cls,
208 _("Error reading response from datastore service"));
211 sm = (const struct StatusMessage*) msg;
212 status = ntohl(sm->status);
214 if (ntohs(msg->size) > sizeof(struct StatusMessage))
216 emsg = (const char*) &sm[1];
217 if (emsg[ntohs(msg->size) - sizeof(struct StatusMessage) - 1] != '\0')
220 emsg = _("Invalid error message received from datastore service");
223 if ( (status == GNUNET_SYSERR) &&
227 emsg = _("Invalid error message received from datastore service");
229 h->response_proc = NULL;
231 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
232 "Received status %d/%s\n",
236 cont (h->response_proc_cls,
243 * Helper function that will initiate the
244 * transmission of a message to the datastore
245 * service. The message must already be prepared
246 * and stored in the buffer at the end of the
247 * handle. The message must be of a type that
248 * expects a "StatusMessage" in response.
250 * @param h handle to the service with prepared message
251 * @param cont function to call with result
252 * @param cont_cls closure
253 * @param timeout timeout for the operation
256 transmit_for_status (struct GNUNET_DATASTORE_Handle *h,
257 GNUNET_DATASTORE_ContinuationWithStatus cont,
259 struct GNUNET_TIME_Relative timeout)
261 const struct GNUNET_MessageHeader *hdr;
264 GNUNET_assert (cont != NULL);
265 hdr = (const struct GNUNET_MessageHeader*) &h[1];
266 msize = ntohs(hdr->size);
268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
269 "Transmitting %u byte message of type %u to datastore service\n",
273 GNUNET_assert (h->response_proc == NULL);
274 h->response_proc = cont;
275 h->response_proc_cls = cont_cls;
276 h->timeout = GNUNET_TIME_relative_to_absolute (timeout);
277 h->message_size = msize;
279 GNUNET_CLIENT_transmit_and_get_response (h->client,
283 &with_status_response_handler,
287 h->response_proc = NULL;
291 _("Not ready to transmit request to datastore service"));
297 * Store an item in the datastore. If the item is already present,
298 * the priorities are summed up and the higher expiration time and
299 * lower anonymity level is used.
301 * @param h handle to the datastore
302 * @param rid reservation ID to use (from "reserve"); use 0 if no
303 * prior reservation was made
304 * @param key key for the value
305 * @param size number of bytes in data
306 * @param data content stored
307 * @param type type of the content
308 * @param priority priority of the content
309 * @param anonymity anonymity-level for the content
310 * @param expiration expiration time for the content
311 * @param timeout timeout for the operation
312 * @param cont continuation to call when done
313 * @param cont_cls closure for cont
316 GNUNET_DATASTORE_put (struct GNUNET_DATASTORE_Handle *h,
318 const GNUNET_HashCode * key,
321 enum GNUNET_BLOCK_Type type,
324 struct GNUNET_TIME_Absolute expiration,
325 struct GNUNET_TIME_Relative timeout,
326 GNUNET_DATASTORE_ContinuationWithStatus cont,
329 struct DataMessage *dm;
333 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
334 "Asked to put %u bytes of data under key `%s'\n",
338 msize = sizeof(struct DataMessage) + size;
339 GNUNET_assert (msize <= GNUNET_SERVER_MAX_MESSAGE_SIZE);
340 dm = (struct DataMessage*) &h[1];
341 dm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_PUT);
342 dm->header.size = htons(msize);
343 dm->rid = htonl(rid);
344 dm->size = htonl(size);
345 dm->type = htonl(type);
346 dm->priority = htonl(priority);
347 dm->anonymity = htonl(anonymity);
348 dm->uid = GNUNET_htonll(0);
349 dm->expiration = GNUNET_TIME_absolute_hton(expiration);
351 memcpy (&dm[1], data, size);
352 transmit_for_status (h, cont, cont_cls, timeout);
357 * Reserve space in the datastore. This function should be used
358 * to avoid "out of space" failures during a longer sequence of "put"
359 * operations (for example, when a file is being inserted).
361 * @param h handle to the datastore
362 * @param amount how much space (in bytes) should be reserved (for content only)
363 * @param entries how many entries will be created (to calculate per-entry overhead)
364 * @param cont continuation to call when done; "success" will be set to
365 * a positive reservation value if space could be reserved.
366 * @param cont_cls closure for cont
367 * @param timeout how long to wait at most for a response
370 GNUNET_DATASTORE_reserve (struct GNUNET_DATASTORE_Handle *h,
373 GNUNET_DATASTORE_ContinuationWithStatus cont,
375 struct GNUNET_TIME_Relative timeout)
377 struct ReserveMessage *rm;
379 rm = (struct ReserveMessage*) &h[1];
380 rm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_RESERVE);
381 rm->header.size = htons(sizeof (struct ReserveMessage));
382 rm->entries = htonl(entries);
383 rm->amount = GNUNET_htonll(amount);
384 transmit_for_status (h, cont, cont_cls, timeout);
389 * Signal that all of the data for which a reservation was made has
390 * been stored and that whatever excess space might have been reserved
391 * can now be released.
393 * @param h handle to the datastore
394 * @param rid reservation ID (value of "success" in original continuation
395 * from the "reserve" function).
396 * @param cont continuation to call when done
397 * @param cont_cls closure for cont
398 * @param timeout how long to wait at most for a response
401 GNUNET_DATASTORE_release_reserve (struct GNUNET_DATASTORE_Handle *h,
403 GNUNET_DATASTORE_ContinuationWithStatus cont,
405 struct GNUNET_TIME_Relative timeout)
407 struct ReleaseReserveMessage *rrm;
409 rrm = (struct ReleaseReserveMessage*) &h[1];
410 rrm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_RELEASE_RESERVE);
411 rrm->header.size = htons(sizeof (struct ReleaseReserveMessage));
412 rrm->rid = htonl(rid);
413 transmit_for_status (h, cont, cont_cls, timeout);
418 * Update a value in the datastore.
420 * @param h handle to the datastore
421 * @param uid identifier for the value
422 * @param priority how much to increase the priority of the value
423 * @param expiration new expiration value should be MAX of existing and this argument
424 * @param cont continuation to call when done
425 * @param cont_cls closure for cont
426 * @param timeout how long to wait at most for a response
429 GNUNET_DATASTORE_update (struct GNUNET_DATASTORE_Handle *h,
430 unsigned long long uid,
432 struct GNUNET_TIME_Absolute expiration,
433 GNUNET_DATASTORE_ContinuationWithStatus cont,
435 struct GNUNET_TIME_Relative timeout)
437 struct UpdateMessage *um;
439 um = (struct UpdateMessage*) &h[1];
440 um->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_UPDATE);
441 um->header.size = htons(sizeof (struct UpdateMessage));
442 um->priority = htonl(priority);
443 um->expiration = GNUNET_TIME_absolute_hton(expiration);
444 um->uid = GNUNET_htonll(uid);
445 transmit_for_status (h, cont, cont_cls, timeout);
450 * Helper function that will initiate the transmission of a message to
451 * the datastore service. The message must already be prepared and
452 * stored in the buffer at the end of the handle. The message must be
453 * of a type that expects a "DataMessage" in response.
455 * @param h handle to the service with prepared message
456 * @param cont function to call with result
457 * @param cont_cls closure
458 * @param timeout timeout for the operation
461 transmit_for_result (struct GNUNET_DATASTORE_Handle *h,
462 GNUNET_DATASTORE_Iterator cont,
464 struct GNUNET_TIME_Relative timeout);
468 * Type of a function to call when we receive a message
469 * from the service. This specific function is used
470 * to handle messages of type "struct DataMessage".
473 * @param msg message received, NULL on timeout or fatal error
476 with_result_response_handler (void *cls,
478 GNUNET_MessageHeader * msg)
480 struct GNUNET_DATASTORE_Handle *h = cls;
481 GNUNET_DATASTORE_Iterator cont = h->response_proc;
482 const struct DataMessage *dm;
484 struct GNUNET_TIME_Relative remaining;
489 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
490 "Got disconnected from datastore\n");
492 h->response_proc = NULL;
493 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
494 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
495 remaining = GNUNET_TIME_absolute_get_remaining (h->timeout);
496 if (remaining.value > 0)
498 transmit_for_result (h,
500 h->response_proc_cls,
506 cont (h->response_proc_cls,
507 NULL, 0, NULL, 0, 0, 0,
508 GNUNET_TIME_UNIT_ZERO_ABS, 0);
513 if (ntohs(msg->type) == GNUNET_MESSAGE_TYPE_DATASTORE_DATA_END)
515 GNUNET_break (ntohs(msg->size) == sizeof(struct GNUNET_MessageHeader));
516 h->response_proc = NULL;
518 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
519 "Received end of result set\n");
521 cont (h->response_proc_cls,
522 NULL, 0, NULL, 0, 0, 0,
523 GNUNET_TIME_UNIT_ZERO_ABS, 0);
526 if ( (ntohs(msg->size) < sizeof(struct DataMessage)) ||
527 (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_DATASTORE_DATA) )
530 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
531 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
532 h->response_proc = NULL;
533 cont (h->response_proc_cls,
534 NULL, 0, NULL, 0, 0, 0,
535 GNUNET_TIME_UNIT_ZERO_ABS, 0);
538 dm = (const struct DataMessage*) msg;
539 msize = ntohl(dm->size);
540 if (ntohs(msg->size) != msize + sizeof(struct DataMessage))
543 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
544 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
545 h->response_proc = NULL;
546 cont (h->response_proc_cls,
547 NULL, 0, NULL, 0, 0, 0,
548 GNUNET_TIME_UNIT_ZERO_ABS, 0);
552 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
553 "Received result %llu with type %u and size %u with key %s\n",
554 (unsigned long long) GNUNET_ntohll(dm->uid),
557 GNUNET_h2s(&dm->key));
559 cont (h->response_proc_cls,
565 ntohl(dm->anonymity),
566 GNUNET_TIME_absolute_ntoh(dm->expiration),
567 GNUNET_ntohll(dm->uid));
572 * Function called to trigger obtaining the next result
573 * from the datastore.
575 * @param h handle to the datastore
576 * @param more GNUNET_YES to get moxre results, GNUNET_NO to abort
577 * iteration (with a final call to "iter" with key/data == NULL).
580 GNUNET_DATASTORE_get_next (struct GNUNET_DATASTORE_Handle *h,
583 GNUNET_DATASTORE_Iterator cont;
585 if (GNUNET_YES == more)
587 GNUNET_CLIENT_receive (h->client,
588 &with_result_response_handler,
590 GNUNET_TIME_absolute_get_remaining (h->timeout));
593 cont = h->response_proc;
594 h->response_proc = NULL;
595 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
596 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
597 cont (h->response_proc_cls,
598 NULL, 0, NULL, 0, 0, 0,
599 GNUNET_TIME_UNIT_ZERO_ABS, 0);
604 * Helper function that will initiate the transmission of a message to
605 * the datastore service. The message must already be prepared and
606 * stored in the buffer at the end of the handle. The message must be
607 * of a type that expects a "DataMessage" in response.
609 * @param h handle to the service with prepared message
610 * @param cont function to call with result
611 * @param cont_cls closure
612 * @param timeout timeout for the operation
615 transmit_for_result (struct GNUNET_DATASTORE_Handle *h,
616 GNUNET_DATASTORE_Iterator cont,
618 struct GNUNET_TIME_Relative timeout)
620 const struct GNUNET_MessageHeader *hdr;
623 GNUNET_assert (cont != NULL);
624 hdr = (const struct GNUNET_MessageHeader*) &h[1];
625 msize = ntohs(hdr->size);
627 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
628 "Transmitting %u byte message of type %u to datastore service\n",
632 GNUNET_assert (h->response_proc == NULL);
633 h->response_proc = cont;
634 h->response_proc_cls = cont_cls;
635 h->timeout = GNUNET_TIME_relative_to_absolute (timeout);
636 h->message_size = msize;
638 GNUNET_CLIENT_transmit_and_get_response (h->client,
642 &with_result_response_handler,
646 h->response_proc = NULL;
648 cont (h->response_proc_cls,
649 NULL, 0, NULL, 0, 0, 0,
650 GNUNET_TIME_UNIT_ZERO_ABS, 0);
656 * Iterate over the results for a particular key
659 * @param h handle to the datastore
660 * @param key maybe NULL (to match all entries)
661 * @param type desired type, 0 for any
662 * @param iter function to call on each matching value;
663 * will be called once with a NULL value at the end
664 * @param iter_cls closure for iter
665 * @param timeout how long to wait at most for a response
668 GNUNET_DATASTORE_get (struct GNUNET_DATASTORE_Handle *h,
669 const GNUNET_HashCode * key,
670 enum GNUNET_BLOCK_Type type,
671 GNUNET_DATASTORE_Iterator iter, void *iter_cls,
672 struct GNUNET_TIME_Relative timeout)
674 struct GetMessage *gm;
677 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
678 "Asked to look for data under key `%s'\n",
681 gm = (struct GetMessage*) &h[1];
682 gm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_GET);
683 gm->type = htonl(type);
686 gm->header.size = htons(sizeof (struct GetMessage));
691 gm->header.size = htons(sizeof (struct GetMessage) - sizeof(GNUNET_HashCode));
693 GNUNET_assert (h->response_proc == NULL);
694 transmit_for_result (h, iter, iter_cls, timeout);
699 * Get a random value from the datastore.
701 * @param h handle to the datastore
702 * @param iter function to call on a random value; it
703 * will be called exactly once; if no values
704 * are available, the value will be NULL.
705 * @param iter_cls closure for iter
706 * @param timeout how long to wait at most for a response
709 GNUNET_DATASTORE_get_random (struct GNUNET_DATASTORE_Handle *h,
710 GNUNET_DATASTORE_Iterator iter, void *iter_cls,
711 struct GNUNET_TIME_Relative timeout)
713 struct GNUNET_MessageHeader *m;
715 m = (struct GNUNET_MessageHeader*) &h[1];
716 m->type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_GET_RANDOM);
717 m->size = htons(sizeof (struct GNUNET_MessageHeader));
718 GNUNET_assert (h->response_proc == NULL);
719 transmit_for_result (h, iter, iter_cls, timeout);
724 * Explicitly remove some content from the database.
726 * @param h handle to the datastore
727 * @param key key for the value
728 * @param size number of bytes in data
729 * @param data content stored
730 * @param cont continuation to call when done
731 * @param cont_cls closure for cont
732 * @param timeout how long to wait at most for a response
735 GNUNET_DATASTORE_remove (struct GNUNET_DATASTORE_Handle *h,
736 const GNUNET_HashCode * key,
737 uint32_t size, const void *data,
738 GNUNET_DATASTORE_ContinuationWithStatus cont,
740 struct GNUNET_TIME_Relative timeout)
742 struct DataMessage *dm;
746 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
747 "Asked to remove %u bytes of data under key `%s'\n",
751 msize = sizeof(struct DataMessage) + size;
752 GNUNET_assert (msize <= GNUNET_SERVER_MAX_MESSAGE_SIZE);
753 dm = (struct DataMessage*) &h[1];
754 dm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE);
755 dm->header.size = htons(msize);
757 dm->size = htonl(size);
759 dm->priority = htonl(0);
760 dm->anonymity = htonl(0);
761 dm->uid = GNUNET_htonll(0);
762 dm->expiration = GNUNET_TIME_absolute_hton(GNUNET_TIME_UNIT_ZERO_ABS);
764 memcpy (&dm[1], data, size);
765 transmit_for_status (h, cont, cont_cls, timeout);
769 /* end of datastore_api.c */