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
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 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.
80 * Connect to the datastore service.
82 * @param cfg configuration to use
83 * @param sched scheduler to use
84 * @return handle to use to access the service
86 struct GNUNET_DATASTORE_Handle *GNUNET_DATASTORE_connect (struct
87 GNUNET_CONFIGURATION_Handle
90 GNUNET_SCHEDULER_Handle
93 struct GNUNET_CLIENT_Connection *c;
94 struct GNUNET_DATASTORE_Handle *h;
96 c = GNUNET_CLIENT_connect (sched, "datastore", cfg);
98 return NULL; /* oops */
99 h = GNUNET_malloc (sizeof(struct GNUNET_DATASTORE_Handle) +
100 GNUNET_SERVER_MAX_MESSAGE_SIZE);
109 * Transmit DROP message to datastore service.
112 transmit_drop (void *cls,
113 size_t size, void *buf)
115 struct GNUNET_DATASTORE_Handle *h = cls;
116 struct GNUNET_MessageHeader *hdr;
120 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
121 _("Failed to transmit request to drop database.\n"));
122 GNUNET_DATASTORE_disconnect (h, GNUNET_NO);
125 GNUNET_assert (size >= sizeof(struct GNUNET_MessageHeader));
127 hdr->size = htons(sizeof(struct GNUNET_MessageHeader));
128 hdr->type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_DROP);
129 GNUNET_DATASTORE_disconnect (h, GNUNET_NO);
130 return sizeof(struct GNUNET_MessageHeader);
135 * Disconnect from the datastore service (and free
136 * associated resources).
138 * @param h handle to the datastore
139 * @param drop set to GNUNET_YES to delete all data in datastore (!)
141 void GNUNET_DATASTORE_disconnect (struct GNUNET_DATASTORE_Handle *h,
144 GNUNET_assert (0 == h->message_size);
145 GNUNET_assert (NULL == h->response_proc);
146 if ( (GNUNET_YES == drop) &&
147 (h->client != NULL) )
150 GNUNET_CLIENT_notify_transmit_ready (h->client,
151 sizeof(struct GNUNET_MessageHeader),
152 GNUNET_TIME_UNIT_MINUTES,
158 if (h->client != NULL)
159 GNUNET_CLIENT_disconnect (h->client);
165 * Type of a function to call when we receive a message
166 * from the service. This specific function is used
167 * to handle messages of type "struct StatusMessage".
170 * @param msg message received, NULL on timeout or fatal error
173 with_status_response_handler (void *cls,
175 GNUNET_MessageHeader * msg)
177 struct GNUNET_DATASTORE_Handle *h = cls;
178 GNUNET_DATASTORE_ContinuationWithStatus cont = h->response_proc;
179 const struct StatusMessage *sm;
185 h->response_proc = NULL;
186 GNUNET_CLIENT_disconnect (h->client);
187 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
188 cont (h->response_proc_cls,
190 _("Timeout trying to read response from datastore service\n"));
193 if ( (ntohs(msg->size) < sizeof(struct StatusMessage)) ||
194 (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_DATASTORE_STATUS) )
197 GNUNET_CLIENT_disconnect (h->client);
198 h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
199 cont (h->response_proc_cls,
201 _("Error reading response from datastore service\n"));
204 sm = (const struct StatusMessage*) msg;
205 status = ntohl(sm->status);
207 if (status == GNUNET_SYSERR)
209 emsg = (const char*) &sm[1];
210 if ( (ntohs(msg->size) == sizeof(struct StatusMessage)) ||
211 (emsg[ntohs(msg->size) - sizeof(struct StatusMessage) - 1] != '\0') )
214 emsg = _("Invalid error message received from datastore service");
217 h->response_proc = NULL;
218 cont (h->response_proc_cls,
225 * Transmit message to datastore service and then
226 * read a status message.
228 * @param cls closure with handle to datastore
229 * @param size number of bytes we can transmit at most
230 * @param buf where to write transmission, NULL on
232 * @return number of bytes copied to buf
235 transmit_get_status (void *cls,
239 struct GNUNET_DATASTORE_Handle *h = cls;
240 GNUNET_DATASTORE_ContinuationWithStatus cont = h->response_proc;
243 h->response_proc = NULL;
247 cont (h->response_proc_cls,
249 gettext_noop ("Error transmitting message to datastore service.\n"));
252 GNUNET_assert (h->message_size <= size);
253 memcpy (buf, &h[1], h->message_size);
255 GNUNET_CLIENT_receive (h->client,
256 &with_status_response_handler,
258 GNUNET_TIME_absolute_get_remaining (h->timeout));
264 * Helper function that will initiate the
265 * transmission of a message to the datastore
266 * service. The message must already be prepared
267 * and stored in the buffer at the end of the
268 * handle. The message must be of a type that
269 * expects a "StatusMessage" in response.
271 * @param h handle to the service with prepared message
272 * @param cont function to call with result
273 * @param cont_cls closure
274 * @param timeout timeout for the operation
277 transmit_for_status (struct GNUNET_DATASTORE_Handle *h,
278 GNUNET_DATASTORE_ContinuationWithStatus cont,
280 struct GNUNET_TIME_Relative timeout)
282 const struct GNUNET_MessageHeader *hdr;
285 hdr = (const struct GNUNET_MessageHeader*) &h[1];
286 msize = ntohs(hdr->size);
287 GNUNET_assert (h->response_proc == NULL);
288 h->response_proc = cont;
289 h->response_proc_cls = cont_cls;
290 h->timeout = GNUNET_TIME_relative_to_absolute (timeout);
291 h->message_size = msize;
292 if (NULL == GNUNET_CLIENT_notify_transmit_ready (h->client,
295 &transmit_get_status,
299 h->response_proc = NULL;
303 gettext_noop ("Not ready to transmit request to datastore service"));
309 * Store an item in the datastore. If the item is already present,
310 * the priorities are summed up and the higher expiration time and
311 * lower anonymity level is used.
313 * @param h handle to the datastore
314 * @param key key for the value
315 * @param size number of bytes in data
316 * @param data content stored
317 * @param type type of the content
318 * @param priority priority of the content
319 * @param anonymity anonymity-level for the content
320 * @param expiration expiration time for the content
321 * @param timeout timeout for the operation
322 * @param cont continuation to call when done
323 * @param cont_cls closure for cont
326 GNUNET_DATASTORE_put (struct GNUNET_DATASTORE_Handle *h,
328 const GNUNET_HashCode * key,
334 struct GNUNET_TIME_Absolute expiration,
335 struct GNUNET_TIME_Relative timeout,
336 GNUNET_DATASTORE_ContinuationWithStatus cont,
339 struct DataMessage *dm;
342 msize = sizeof(struct DataMessage) + size;
343 GNUNET_assert (msize <= GNUNET_SERVER_MAX_MESSAGE_SIZE);
344 dm = (struct DataMessage*) &h[1];
345 dm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_PUT);
346 dm->header.size = htons(msize);
347 dm->rid = htonl(rid);
348 dm->size = htonl(size);
349 dm->type = htonl(type);
350 dm->priority = htonl(priority);
351 dm->anonymity = htonl(anonymity);
352 dm->uid = GNUNET_htonll(0);
353 dm->expiration = GNUNET_TIME_absolute_hton(expiration);
355 memcpy (&dm[1], data, size);
356 transmit_for_status (h, cont, cont_cls, timeout);
361 * Reserve space in the datastore. This function should be used
362 * to avoid "out of space" failures during a longer sequence of "put"
363 * operations (for example, when a file is being inserted).
365 * @param h handle to the datastore
366 * @param amount how much space (in bytes) should be reserved (for content only)
367 * @param entries how many entries will be created (to calculate per-entry overhead)
368 * @param cont continuation to call when done; "success" will be set to
369 * a positive reservation value if space could be reserved.
370 * @param cont_cls closure for cont
371 * @param timeout how long to wait at most for a response
374 GNUNET_DATASTORE_reserve (struct GNUNET_DATASTORE_Handle *h,
377 GNUNET_DATASTORE_ContinuationWithStatus cont,
379 struct GNUNET_TIME_Relative timeout)
381 struct ReserveMessage *rm;
383 rm = (struct ReserveMessage*) &h[1];
384 rm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_RESERVE);
385 rm->header.size = htons(sizeof (struct ReserveMessage));
386 rm->reserved = htonl(0);
387 rm->amount = htonl(amount);
388 rm->entries = htonl(entries);
389 transmit_for_status (h, cont, cont_cls, timeout);
394 * Signal that all of the data for which a reservation was made has
395 * been stored and that whatever excess space might have been reserved
396 * can now be released.
398 * @param h handle to the datastore
399 * @param rid reservation ID (value of "success" in original continuation
400 * from the "reserve" function).
401 * @param cont continuation to call when done
402 * @param cont_cls closure for cont
403 * @param timeout how long to wait at most for a response
406 GNUNET_DATASTORE_release_reserve (struct GNUNET_DATASTORE_Handle *h,
408 GNUNET_DATASTORE_ContinuationWithStatus cont,
410 struct GNUNET_TIME_Relative timeout)
412 struct ReleaseReserveMessage *rrm;
414 rrm = (struct ReleaseReserveMessage*) &h[1];
415 rrm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_RELEASE_RESERVE);
416 rrm->header.size = htons(sizeof (struct ReleaseReserveMessage));
417 rrm->rid = htonl(rid);
418 transmit_for_status (h, cont, cont_cls, timeout);
423 * Update a value in the datastore.
425 * @param h handle to the datastore
426 * @param uid identifier for the value
427 * @param priority how much to increase the priority of the value
428 * @param expiration new expiration value should be MAX of existing and this argument
429 * @param cont continuation to call when done
430 * @param cont_cls closure for cont
431 * @param timeout how long to wait at most for a response
434 GNUNET_DATASTORE_update (struct GNUNET_DATASTORE_Handle *h,
435 unsigned long long uid,
437 struct GNUNET_TIME_Absolute expiration,
438 GNUNET_DATASTORE_ContinuationWithStatus cont,
440 struct GNUNET_TIME_Relative timeout)
442 struct UpdateMessage *um;
444 um = (struct UpdateMessage*) &h[1];
445 um->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_UPDATE);
446 um->header.size = htons(sizeof (struct UpdateMessage));
447 um->priority = htonl(priority);
448 um->expiration = GNUNET_TIME_absolute_hton(expiration);
449 um->uid = GNUNET_htonll(uid);
450 transmit_for_status (h, cont, cont_cls, timeout);
455 * Iterate over the results for a particular key
458 * @param h handle to the datastore
459 * @param key maybe NULL (to match all entries)
460 * @param type desired type, 0 for any
461 * @param iter function to call on each matching value;
462 * will be called once with a NULL value at the end
463 * @param iter_cls closure for iter
464 * @param timeout how long to wait at most for a response
467 GNUNET_DATASTORE_get (struct GNUNET_DATASTORE_Handle *h,
468 const GNUNET_HashCode * key,
470 GNUNET_DATASTORE_Iterator iter, void *iter_cls,
471 struct GNUNET_TIME_Relative timeout)
473 static struct GNUNET_TIME_Absolute zero;
475 NULL, 0, NULL, 0, 0, 0, zero, 0);
480 * Get a random value from the datastore.
482 * @param h handle to the datastore
483 * @param iter function to call on a random value; it
484 * will be called exactly once; if no values
485 * are available, the value will be NULL.
486 * @param iter_cls closure for iter
487 * @param timeout how long to wait at most for a response
490 GNUNET_DATASTORE_get_random (struct GNUNET_DATASTORE_Handle *h,
491 GNUNET_DATASTORE_Iterator iter, void *iter_cls,
492 struct GNUNET_TIME_Relative timeout)
494 static struct GNUNET_TIME_Absolute zero;
497 NULL, 0, NULL, 0, 0, 0, zero, 0);
502 * Explicitly remove some content from the database.
504 * @param h handle to the datastore
505 * @param key key for the value
506 * @param size number of bytes in data
507 * @param data content stored
508 * @param cont continuation to call when done
509 * @param cont_cls closure for cont
510 * @param timeout how long to wait at most for a response
513 GNUNET_DATASTORE_remove (struct GNUNET_DATASTORE_Handle *h,
514 const GNUNET_HashCode * key,
515 uint32_t size, const void *data,
516 GNUNET_DATASTORE_ContinuationWithStatus cont,
518 struct GNUNET_TIME_Relative timeout)
520 struct DataMessage *dm;
523 msize = sizeof(struct DataMessage) + size;
524 GNUNET_assert (msize <= GNUNET_SERVER_MAX_MESSAGE_SIZE);
525 dm = (struct DataMessage*) &h[1];
526 dm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE);
527 dm->header.size = htons(msize);
529 dm->size = htonl(size);
531 dm->priority = htonl(0);
532 dm->anonymity = htonl(0);
533 dm->uid = GNUNET_htonll(0);
534 dm->expiration.value = 0;
536 memcpy (&dm[1], data, size);
537 transmit_for_status (h, cont, cont_cls, timeout);
541 /* end of datastore_api.c */