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);
171 * Type of a function to call when we receive a message
172 * from the service. This specific function is used
173 * to handle messages of type "struct StatusMessage".
176 * @param msg message received, NULL on timeout or fatal error
179 with_status_response_handler (void *cls,
181 GNUNET_MessageHeader * msg)
183 struct GNUNET_DATASTORE_Handle *h = cls;
184 GNUNET_DATASTORE_ContinuationWithStatus cont = h->response_proc;
185 const struct StatusMessage *sm;
192 h->response_proc = NULL;
193 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
194 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
195 cont (h->response_proc_cls,
197 _("Timeout trying to read response from datastore service"));
200 if ( (ntohs(msg->size) < sizeof(struct StatusMessage)) ||
201 (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_DATASTORE_STATUS) )
204 h->response_proc = NULL;
205 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
206 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
207 cont (h->response_proc_cls,
209 _("Error reading response from datastore service"));
212 sm = (const struct StatusMessage*) msg;
213 status = ntohl(sm->status);
215 if (ntohs(msg->size) > sizeof(struct StatusMessage))
217 emsg = (const char*) &sm[1];
218 if (emsg[ntohs(msg->size) - sizeof(struct StatusMessage) - 1] != '\0')
221 emsg = _("Invalid error message received from datastore service");
224 if ( (status == GNUNET_SYSERR) &&
228 emsg = _("Invalid error message received from datastore service");
230 h->response_proc = NULL;
232 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
233 "Received status %d/%s\n",
237 cont (h->response_proc_cls,
244 * Helper function that will initiate the
245 * transmission of a message to the datastore
246 * service. The message must already be prepared
247 * and stored in the buffer at the end of the
248 * handle. The message must be of a type that
249 * expects a "StatusMessage" in response.
251 * @param h handle to the service with prepared message
252 * @param cont function to call with result
253 * @param cont_cls closure
254 * @param timeout timeout for the operation
257 transmit_for_status (struct GNUNET_DATASTORE_Handle *h,
258 GNUNET_DATASTORE_ContinuationWithStatus cont,
260 struct GNUNET_TIME_Relative timeout)
262 const struct GNUNET_MessageHeader *hdr;
265 GNUNET_assert (cont != NULL);
266 hdr = (const struct GNUNET_MessageHeader*) &h[1];
267 msize = ntohs(hdr->size);
269 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
270 "Transmitting %u byte message of type %u to datastore service\n",
274 GNUNET_assert (h->response_proc == NULL);
275 h->response_proc = cont;
276 h->response_proc_cls = cont_cls;
277 h->timeout = GNUNET_TIME_relative_to_absolute (timeout);
278 h->message_size = msize;
280 GNUNET_CLIENT_transmit_and_get_response (h->client,
284 &with_status_response_handler,
288 h->response_proc = NULL;
292 _("Not ready to transmit request to datastore service"));
298 * Store an item in the datastore. If the item is already present,
299 * the priorities are summed up and the higher expiration time and
300 * lower anonymity level is used.
302 * @param h handle to the datastore
303 * @param rid reservation ID to use (from "reserve"); use 0 if no
304 * prior reservation was made
305 * @param key key for the value
306 * @param size number of bytes in data
307 * @param data content stored
308 * @param type type of the content
309 * @param priority priority of the content
310 * @param anonymity anonymity-level for the content
311 * @param expiration expiration time for the content
312 * @param timeout timeout for the operation
313 * @param cont continuation to call when done
314 * @param cont_cls closure for cont
317 GNUNET_DATASTORE_put (struct GNUNET_DATASTORE_Handle *h,
319 const GNUNET_HashCode * key,
322 enum GNUNET_BLOCK_Type type,
325 struct GNUNET_TIME_Absolute expiration,
326 struct GNUNET_TIME_Relative timeout,
327 GNUNET_DATASTORE_ContinuationWithStatus cont,
330 struct DataMessage *dm;
334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
335 "Asked to put %u bytes of data under key `%s'\n",
339 msize = sizeof(struct DataMessage) + size;
340 GNUNET_assert (msize <= GNUNET_SERVER_MAX_MESSAGE_SIZE);
341 dm = (struct DataMessage*) &h[1];
342 dm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_PUT);
343 dm->header.size = htons(msize);
344 dm->rid = htonl(rid);
345 dm->size = htonl(size);
346 dm->type = htonl(type);
347 dm->priority = htonl(priority);
348 dm->anonymity = htonl(anonymity);
349 dm->uid = GNUNET_htonll(0);
350 dm->expiration = GNUNET_TIME_absolute_hton(expiration);
352 memcpy (&dm[1], data, size);
353 transmit_for_status (h, cont, cont_cls, timeout);
358 * Reserve space in the datastore. This function should be used
359 * to avoid "out of space" failures during a longer sequence of "put"
360 * operations (for example, when a file is being inserted).
362 * @param h handle to the datastore
363 * @param amount how much space (in bytes) should be reserved (for content only)
364 * @param entries how many entries will be created (to calculate per-entry overhead)
365 * @param cont continuation to call when done; "success" will be set to
366 * a positive reservation value if space could be reserved.
367 * @param cont_cls closure for cont
368 * @param timeout how long to wait at most for a response
371 GNUNET_DATASTORE_reserve (struct GNUNET_DATASTORE_Handle *h,
374 GNUNET_DATASTORE_ContinuationWithStatus cont,
376 struct GNUNET_TIME_Relative timeout)
378 struct ReserveMessage *rm;
380 rm = (struct ReserveMessage*) &h[1];
381 rm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_RESERVE);
382 rm->header.size = htons(sizeof (struct ReserveMessage));
383 rm->entries = htonl(entries);
384 rm->amount = GNUNET_htonll(amount);
385 transmit_for_status (h, cont, cont_cls, timeout);
390 * Signal that all of the data for which a reservation was made has
391 * been stored and that whatever excess space might have been reserved
392 * can now be released.
394 * @param h handle to the datastore
395 * @param rid reservation ID (value of "success" in original continuation
396 * from the "reserve" function).
397 * @param cont continuation to call when done
398 * @param cont_cls closure for cont
399 * @param timeout how long to wait at most for a response
402 GNUNET_DATASTORE_release_reserve (struct GNUNET_DATASTORE_Handle *h,
404 GNUNET_DATASTORE_ContinuationWithStatus cont,
406 struct GNUNET_TIME_Relative timeout)
408 struct ReleaseReserveMessage *rrm;
410 rrm = (struct ReleaseReserveMessage*) &h[1];
411 rrm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_RELEASE_RESERVE);
412 rrm->header.size = htons(sizeof (struct ReleaseReserveMessage));
413 rrm->rid = htonl(rid);
414 transmit_for_status (h, cont, cont_cls, timeout);
419 * Update a value in the datastore.
421 * @param h handle to the datastore
422 * @param uid identifier for the value
423 * @param priority how much to increase the priority of the value
424 * @param expiration new expiration value should be MAX of existing and this argument
425 * @param cont continuation to call when done
426 * @param cont_cls closure for cont
427 * @param timeout how long to wait at most for a response
430 GNUNET_DATASTORE_update (struct GNUNET_DATASTORE_Handle *h,
431 unsigned long long uid,
433 struct GNUNET_TIME_Absolute expiration,
434 GNUNET_DATASTORE_ContinuationWithStatus cont,
436 struct GNUNET_TIME_Relative timeout)
438 struct UpdateMessage *um;
440 um = (struct UpdateMessage*) &h[1];
441 um->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_UPDATE);
442 um->header.size = htons(sizeof (struct UpdateMessage));
443 um->priority = htonl(priority);
444 um->expiration = GNUNET_TIME_absolute_hton(expiration);
445 um->uid = GNUNET_htonll(uid);
446 transmit_for_status (h, cont, cont_cls, timeout);
451 * Helper function that will initiate the transmission of a message to
452 * the datastore service. The message must already be prepared and
453 * stored in the buffer at the end of the handle. The message must be
454 * of a type that expects a "DataMessage" in response.
456 * @param h handle to the service with prepared message
457 * @param cont function to call with result
458 * @param cont_cls closure
459 * @param timeout timeout for the operation
462 transmit_for_result (struct GNUNET_DATASTORE_Handle *h,
463 GNUNET_DATASTORE_Iterator cont,
465 struct GNUNET_TIME_Relative timeout);
469 * Type of a function to call when we receive a message
470 * from the service. This specific function is used
471 * to handle messages of type "struct DataMessage".
474 * @param msg message received, NULL on timeout or fatal error
477 with_result_response_handler (void *cls,
479 GNUNET_MessageHeader * msg)
481 struct GNUNET_DATASTORE_Handle *h = cls;
482 GNUNET_DATASTORE_Iterator cont = h->response_proc;
483 const struct DataMessage *dm;
485 struct GNUNET_TIME_Relative remaining;
490 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
491 "Got disconnected from datastore\n");
493 h->response_proc = NULL;
494 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
495 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
496 remaining = GNUNET_TIME_absolute_get_remaining (h->timeout);
497 if (remaining.value > 0)
499 transmit_for_result (h,
501 h->response_proc_cls,
507 cont (h->response_proc_cls,
508 NULL, 0, NULL, 0, 0, 0,
509 GNUNET_TIME_UNIT_ZERO_ABS, 0);
514 if (ntohs(msg->type) == GNUNET_MESSAGE_TYPE_DATASTORE_DATA_END)
516 GNUNET_break (ntohs(msg->size) == sizeof(struct GNUNET_MessageHeader));
517 h->response_proc = NULL;
519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
520 "Received end of result set\n");
522 cont (h->response_proc_cls,
523 NULL, 0, NULL, 0, 0, 0,
524 GNUNET_TIME_UNIT_ZERO_ABS, 0);
527 if ( (ntohs(msg->size) < sizeof(struct DataMessage)) ||
528 (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_DATASTORE_DATA) )
531 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
532 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
533 h->response_proc = NULL;
534 cont (h->response_proc_cls,
535 NULL, 0, NULL, 0, 0, 0,
536 GNUNET_TIME_UNIT_ZERO_ABS, 0);
539 dm = (const struct DataMessage*) msg;
540 msize = ntohl(dm->size);
541 if (ntohs(msg->size) != msize + sizeof(struct DataMessage))
544 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
545 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
546 h->response_proc = NULL;
547 cont (h->response_proc_cls,
548 NULL, 0, NULL, 0, 0, 0,
549 GNUNET_TIME_UNIT_ZERO_ABS, 0);
553 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
554 "Received result %llu with type %u and size %u with key %s\n",
555 (unsigned long long) GNUNET_ntohll(dm->uid),
558 GNUNET_h2s(&dm->key));
560 cont (h->response_proc_cls,
566 ntohl(dm->anonymity),
567 GNUNET_TIME_absolute_ntoh(dm->expiration),
568 GNUNET_ntohll(dm->uid));
573 * Function called to trigger obtaining the next result
574 * from the datastore.
576 * @param h handle to the datastore
577 * @param more GNUNET_YES to get moxre results, GNUNET_NO to abort
578 * iteration (with a final call to "iter" with key/data == NULL).
581 GNUNET_DATASTORE_get_next (struct GNUNET_DATASTORE_Handle *h,
584 GNUNET_DATASTORE_Iterator cont;
586 if (GNUNET_YES == more)
588 GNUNET_CLIENT_receive (h->client,
589 &with_result_response_handler,
591 GNUNET_TIME_absolute_get_remaining (h->timeout));
594 cont = h->response_proc;
595 h->response_proc = NULL;
596 GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
597 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
598 cont (h->response_proc_cls,
599 NULL, 0, NULL, 0, 0, 0,
600 GNUNET_TIME_UNIT_ZERO_ABS, 0);
605 * Helper function that will initiate the transmission of a message to
606 * the datastore service. The message must already be prepared and
607 * stored in the buffer at the end of the handle. The message must be
608 * of a type that expects a "DataMessage" in response.
610 * @param h handle to the service with prepared message
611 * @param cont function to call with result
612 * @param cont_cls closure
613 * @param timeout timeout for the operation
616 transmit_for_result (struct GNUNET_DATASTORE_Handle *h,
617 GNUNET_DATASTORE_Iterator cont,
619 struct GNUNET_TIME_Relative timeout)
621 const struct GNUNET_MessageHeader *hdr;
624 GNUNET_assert (cont != NULL);
625 hdr = (const struct GNUNET_MessageHeader*) &h[1];
626 msize = ntohs(hdr->size);
628 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
629 "Transmitting %u byte message of type %u to datastore service\n",
633 GNUNET_assert (h->response_proc == NULL);
634 h->response_proc = cont;
635 h->response_proc_cls = cont_cls;
636 h->timeout = GNUNET_TIME_relative_to_absolute (timeout);
637 h->message_size = msize;
639 GNUNET_CLIENT_transmit_and_get_response (h->client,
643 &with_result_response_handler,
647 h->response_proc = NULL;
649 cont (h->response_proc_cls,
650 NULL, 0, NULL, 0, 0, 0,
651 GNUNET_TIME_UNIT_ZERO_ABS, 0);
657 * Iterate over the results for a particular key
660 * @param h handle to the datastore
661 * @param key maybe NULL (to match all entries)
662 * @param type desired type, 0 for any
663 * @param iter function to call on each matching value;
664 * will be called once with a NULL value at the end
665 * @param iter_cls closure for iter
666 * @param timeout how long to wait at most for a response
669 GNUNET_DATASTORE_get (struct GNUNET_DATASTORE_Handle *h,
670 const GNUNET_HashCode * key,
671 enum GNUNET_BLOCK_Type type,
672 GNUNET_DATASTORE_Iterator iter, void *iter_cls,
673 struct GNUNET_TIME_Relative timeout)
675 struct GetMessage *gm;
678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
679 "Asked to look for data under key `%s'\n",
682 gm = (struct GetMessage*) &h[1];
683 gm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_GET);
684 gm->type = htonl(type);
687 gm->header.size = htons(sizeof (struct GetMessage));
692 gm->header.size = htons(sizeof (struct GetMessage) - sizeof(GNUNET_HashCode));
694 GNUNET_assert (h->response_proc == NULL);
695 transmit_for_result (h, iter, iter_cls, timeout);
700 * Get a random value from the datastore.
702 * @param h handle to the datastore
703 * @param iter function to call on a random value; it
704 * will be called exactly once; if no values
705 * are available, the value will be NULL.
706 * @param iter_cls closure for iter
707 * @param timeout how long to wait at most for a response
710 GNUNET_DATASTORE_get_random (struct GNUNET_DATASTORE_Handle *h,
711 GNUNET_DATASTORE_Iterator iter, void *iter_cls,
712 struct GNUNET_TIME_Relative timeout)
714 struct GNUNET_MessageHeader *m;
716 m = (struct GNUNET_MessageHeader*) &h[1];
717 m->type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_GET_RANDOM);
718 m->size = htons(sizeof (struct GNUNET_MessageHeader));
719 GNUNET_assert (h->response_proc == NULL);
720 transmit_for_result (h, iter, iter_cls, timeout);
725 * Explicitly remove some content from the database.
727 * @param h handle to the datastore
728 * @param key key for the value
729 * @param size number of bytes in data
730 * @param data content stored
731 * @param cont continuation to call when done
732 * @param cont_cls closure for cont
733 * @param timeout how long to wait at most for a response
736 GNUNET_DATASTORE_remove (struct GNUNET_DATASTORE_Handle *h,
737 const GNUNET_HashCode * key,
738 uint32_t size, const void *data,
739 GNUNET_DATASTORE_ContinuationWithStatus cont,
741 struct GNUNET_TIME_Relative timeout)
743 struct DataMessage *dm;
747 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
748 "Asked to remove %u bytes of data under key `%s'\n",
752 msize = sizeof(struct DataMessage) + size;
753 GNUNET_assert (msize <= GNUNET_SERVER_MAX_MESSAGE_SIZE);
754 dm = (struct DataMessage*) &h[1];
755 dm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE);
756 dm->header.size = htons(msize);
758 dm->size = htonl(size);
760 dm->priority = htonl(0);
761 dm->anonymity = htonl(0);
762 dm->uid = GNUNET_htonll(0);
763 dm->expiration = GNUNET_TIME_absolute_hton(GNUNET_TIME_UNIT_ZERO_ABS);
765 memcpy (&dm[1], data, size);
766 transmit_for_status (h, cont, cont_cls, timeout);
770 /* end of datastore_api.c */