reservations
[oweals/gnunet.git] / src / datastore / datastore_api.c
1 /*
2      This file is part of GNUnet
3      (C) 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19 */
20
21 /**
22  * @file datastore/datastore_api.c
23  * @brief Management for the datastore for files stored on a GNUnet node
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_datastore_service.h"
28 #include "datastore.h"
29
30 /**
31  * Handle to the datastore service.  Followed
32  * by 65536 bytes used for storing messages.
33  */
34 struct GNUNET_DATASTORE_Handle
35 {
36
37   /**
38    * Our configuration.
39    */
40   struct GNUNET_CONFIGURATION_Handle *cfg;
41
42   /**
43    * Our scheduler.
44    */
45   struct GNUNET_SCHEDULER_Handle *sched;
46
47   /**
48    * Current connection to the datastore service.
49    */
50   struct GNUNET_CLIENT_Connection *client;
51
52   /**
53    * Current response processor (NULL if we are not waiting for a
54    * response).  The specific type depends on the kind of message we
55    * just transmitted.
56    */
57   void *response_proc;
58   
59   /**
60    * Closure for response_proc.
61    */
62   void *response_proc_cls;
63
64   /**
65    * Timeout for the current operation.
66    */
67   struct GNUNET_TIME_Absolute timeout;
68
69   /**
70    * Number of bytes in the message following
71    * this struct, 0 if we have no request pending.
72    */
73   size_t message_size;
74
75 };
76
77
78 /**
79  * Connect to the datastore service.
80  *
81  * @param cfg configuration to use
82  * @param sched scheduler to use
83  * @return handle to use to access the service
84  */
85 struct GNUNET_DATASTORE_Handle *GNUNET_DATASTORE_connect (struct
86                                                           GNUNET_CONFIGURATION_Handle
87                                                           *cfg,
88                                                           struct
89                                                           GNUNET_SCHEDULER_Handle
90                                                           *sched)
91 {
92   struct GNUNET_CLIENT_Connection *c;
93   struct GNUNET_DATASTORE_Handle *h;
94   
95   c = GNUNET_CLIENT_connect (sched, "datastore", cfg);
96   if (c == NULL)
97     return NULL; /* oops */
98   h = GNUNET_malloc (sizeof(struct GNUNET_DATASTORE_Handle) + 
99                      GNUNET_SERVER_MAX_MESSAGE_SIZE);
100   h->client = c;
101   h->cfg = cfg;
102   h->sched = sched;
103   return h;
104 }
105
106
107 /**
108  * Transmit DROP message to datastore service.
109  */
110 static size_t
111 transmit_drop (void *cls,
112                size_t size, void *buf)
113 {
114   struct GNUNET_DATASTORE_Handle *h = cls;
115   struct GNUNET_MessageHeader *hdr;
116   
117   if (buf == NULL)
118     {
119       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
120                   _("Failed to transmit request to drop database.\n"));
121       GNUNET_DATASTORE_disconnect (h, GNUNET_NO);
122       return 0;
123     }
124   GNUNET_assert (size >= sizeof(struct GNUNET_MessageHeader));
125   hdr = buf;
126   hdr->size = htons(sizeof(struct GNUNET_MessageHeader));
127   hdr->type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_DROP);
128   GNUNET_DATASTORE_disconnect (h, GNUNET_NO);
129   return sizeof(struct GNUNET_MessageHeader);
130 }
131
132
133 /**
134  * Disconnect from the datastore service (and free
135  * associated resources).
136  *
137  * @param h handle to the datastore
138  * @param drop set to GNUNET_YES to delete all data in datastore (!)
139  */
140 void GNUNET_DATASTORE_disconnect (struct GNUNET_DATASTORE_Handle *h,
141                                   int drop)
142 {
143   GNUNET_assert (0 == h->message_size);
144   GNUNET_assert (NULL == h->response_proc);
145   if ( (GNUNET_YES == drop) &&
146        (h->client != NULL) )
147     {
148       if (NULL != 
149           GNUNET_CLIENT_notify_transmit_ready (h->client,
150                                                sizeof(struct GNUNET_MessageHeader),
151                                                GNUNET_TIME_UNIT_MINUTES,
152                                                &transmit_drop,
153                                                h))
154         return;
155       GNUNET_break (0);
156     }
157   if (h->client != NULL)
158     GNUNET_CLIENT_disconnect (h->client);
159   GNUNET_free (h);
160 }
161
162
163 /**
164  * Type of a function to call when we receive a message
165  * from the service.  This specific function is used
166  * to handle messages of type "struct StatusMessage".
167  *
168  * @param cls closure
169  * @param msg message received, NULL on timeout or fatal error
170  */
171 static void 
172 with_status_response_handler (void *cls,
173                               const struct
174                               GNUNET_MessageHeader * msg)
175 {
176   struct GNUNET_DATASTORE_Handle *h = cls;
177   GNUNET_DATASTORE_ContinuationWithStatus cont = h->response_proc;
178   const struct StatusMessage *sm;
179   const char *emsg;
180   int status;
181
182   if (msg == NULL)
183     {
184       h->response_proc = NULL;
185       GNUNET_CLIENT_disconnect (h->client);
186       h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
187       cont (h->response_proc_cls, 
188             GNUNET_SYSERR,
189             _("Timeout trying to read response from datastore service\n"));       
190       return;
191     }
192   if ( (ntohs(msg->size) < sizeof(struct StatusMessage)) ||
193        (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_DATASTORE_STATUS) ) 
194     {
195       GNUNET_break (0);
196       h->response_proc = NULL;
197       GNUNET_CLIENT_disconnect (h->client);
198       h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
199       cont (h->response_proc_cls, 
200             GNUNET_SYSERR,
201             _("Error reading response from datastore service\n"));
202       return;
203     }
204   sm = (const struct StatusMessage*) msg;
205   status = ntohl(sm->status);
206   emsg = NULL;
207   if (status == GNUNET_SYSERR)
208     {
209       emsg = (const char*) &sm[1];
210       if ( (ntohs(msg->size) == sizeof(struct StatusMessage)) ||
211            (emsg[ntohs(msg->size) - sizeof(struct StatusMessage) - 1] != '\0') )
212         {
213           GNUNET_break (0);
214           emsg = _("Invalid error message received from datastore service");
215         }
216     }  
217   h->response_proc = NULL;
218 #if DEBUG_DATASTORE
219   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
220               "Received status %d/%s\n",
221               status,
222               emsg);
223 #endif
224   cont (h->response_proc_cls, 
225         status,
226         emsg);
227 }
228
229
230 /**
231  * Transmit message to datastore service and then
232  * read a status message.
233  *
234  * @param cls closure with handle to datastore
235  * @param size number of bytes we can transmit at most
236  * @param buf where to write transmission, NULL on
237  *        timeout
238  * @return number of bytes copied to buf
239  */
240 static size_t
241 transmit_get_status (void *cls,
242                      size_t size,
243                      void *buf)
244 {
245   struct GNUNET_DATASTORE_Handle *h = cls;
246   GNUNET_DATASTORE_ContinuationWithStatus cont = h->response_proc;
247   uint16_t msize;
248
249   if (buf == NULL)
250     {
251       h->message_size = 0;
252       h->response_proc = NULL;
253       cont (h->response_proc_cls, 
254             GNUNET_SYSERR,
255             gettext_noop ("Error transmitting message to datastore service.\n"));
256       return 0;
257     }
258   msize = h->message_size;
259   GNUNET_assert (msize <= size);
260   memcpy (buf, &h[1], msize);
261 #if DEBUG_DATASTORE
262   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
263               "Transmitted %u byte message to datastore service, now waiting for status.\n",
264               msize);
265 #endif
266   h->message_size = 0;
267   GNUNET_CLIENT_receive (h->client,
268                          &with_status_response_handler,
269                          h,
270                          GNUNET_TIME_absolute_get_remaining (h->timeout));
271   return msize;
272 }
273
274
275 /**
276  * Helper function that will initiate the
277  * transmission of a message to the datastore
278  * service.  The message must already be prepared
279  * and stored in the buffer at the end of the
280  * handle.  The message must be of a type that
281  * expects a "StatusMessage" in response.
282  *
283  * @param h handle to the service with prepared message
284  * @param cont function to call with result
285  * @param cont_cls closure
286  * @param timeout timeout for the operation
287  */
288 static void
289 transmit_for_status (struct GNUNET_DATASTORE_Handle *h,
290                      GNUNET_DATASTORE_ContinuationWithStatus cont,
291                      void *cont_cls,
292                      struct GNUNET_TIME_Relative timeout)
293 {
294   const struct GNUNET_MessageHeader *hdr;
295   uint16_t msize;
296
297   GNUNET_assert (cont != NULL);
298   hdr = (const struct GNUNET_MessageHeader*) &h[1];
299   msize = ntohs(hdr->size);
300 #if DEBUG_DATASTORE
301   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
302               "Transmitting %u byte message of type %u to datastore service\n",
303               msize,
304               ntohs(hdr->type));
305 #endif
306   GNUNET_assert (h->response_proc == NULL);
307   h->response_proc = cont;
308   h->response_proc_cls = cont_cls;
309   h->timeout = GNUNET_TIME_relative_to_absolute (timeout);
310   h->message_size = msize;
311   if (NULL == GNUNET_CLIENT_notify_transmit_ready (h->client,
312                                                    msize,
313                                                    timeout,
314                                                    &transmit_get_status,
315                                                    h))
316     {
317       GNUNET_break (0);
318       h->response_proc = NULL;
319       h->message_size = 0;
320       cont (cont_cls,
321             GNUNET_SYSERR,
322             gettext_noop ("Not ready to transmit request to datastore service"));
323     }
324 }
325
326
327 /**
328  * Store an item in the datastore.  If the item is already present,
329  * the priorities are summed up and the higher expiration time and
330  * lower anonymity level is used.
331  *
332  * @param h handle to the datastore
333  * @param key key for the value
334  * @param size number of bytes in data
335  * @param data content stored
336  * @param type type of the content
337  * @param priority priority of the content
338  * @param anonymity anonymity-level for the content
339  * @param expiration expiration time for the content
340  * @param timeout timeout for the operation
341  * @param cont continuation to call when done
342  * @param cont_cls closure for cont
343  */
344 void
345 GNUNET_DATASTORE_put (struct GNUNET_DATASTORE_Handle *h,
346                       int rid,
347                       const GNUNET_HashCode * key,
348                       uint32_t size,
349                       const void *data,
350                       uint32_t type,
351                       uint32_t priority,
352                       uint32_t anonymity,
353                       struct GNUNET_TIME_Absolute expiration,
354                       struct GNUNET_TIME_Relative timeout,
355                       GNUNET_DATASTORE_ContinuationWithStatus cont,
356                       void *cont_cls)
357 {
358   struct DataMessage *dm;
359   size_t msize;
360
361 #if DEBUG_DATASTORE
362   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
363               "Asked to put %u bytes of data\n",
364               size);
365 #endif
366   msize = sizeof(struct DataMessage) + size;
367   GNUNET_assert (msize <= GNUNET_SERVER_MAX_MESSAGE_SIZE);
368   dm = (struct DataMessage*) &h[1];
369   dm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_PUT);
370   dm->header.size = htons(msize);
371   dm->rid = htonl(rid);
372   dm->size = htonl(size);
373   dm->type = htonl(type);
374   dm->priority = htonl(priority);
375   dm->anonymity = htonl(anonymity);
376   dm->uid = GNUNET_htonll(0);
377   dm->expiration = GNUNET_TIME_absolute_hton(expiration);
378   dm->key = *key;
379   memcpy (&dm[1], data, size);
380   transmit_for_status (h, cont, cont_cls, timeout);
381 }
382
383
384 /**
385  * Reserve space in the datastore.  This function should be used
386  * to avoid "out of space" failures during a longer sequence of "put"
387  * operations (for example, when a file is being inserted).
388  *
389  * @param h handle to the datastore
390  * @param amount how much space (in bytes) should be reserved (for content only)
391  * @param entries how many entries will be created (to calculate per-entry overhead)
392  * @param cont continuation to call when done; "success" will be set to
393  *             a positive reservation value if space could be reserved.
394  * @param cont_cls closure for cont
395  * @param timeout how long to wait at most for a response
396  */
397 void
398 GNUNET_DATASTORE_reserve (struct GNUNET_DATASTORE_Handle *h,
399                           uint64_t amount,
400                           uint32_t entries,
401                           GNUNET_DATASTORE_ContinuationWithStatus cont,
402                           void *cont_cls,
403                           struct GNUNET_TIME_Relative timeout)
404 {
405   struct ReserveMessage *rm;
406
407   rm = (struct ReserveMessage*) &h[1];
408   rm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_RESERVE);
409   rm->header.size = htons(sizeof (struct ReserveMessage));
410   rm->entries = htonl(entries);
411   rm->amount = htonl(amount);
412   transmit_for_status (h, cont, cont_cls, timeout);
413 }
414
415
416 /**
417  * Signal that all of the data for which a reservation was made has
418  * been stored and that whatever excess space might have been reserved
419  * can now be released.
420  *
421  * @param h handle to the datastore
422  * @param rid reservation ID (value of "success" in original continuation
423  *        from the "reserve" function).
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
427  */
428 void
429 GNUNET_DATASTORE_release_reserve (struct GNUNET_DATASTORE_Handle *h,
430                                   int rid,
431                                   GNUNET_DATASTORE_ContinuationWithStatus cont,
432                                   void *cont_cls,
433                                   struct GNUNET_TIME_Relative timeout)
434 {
435   struct ReleaseReserveMessage *rrm;
436
437   rrm = (struct ReleaseReserveMessage*) &h[1];
438   rrm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_RELEASE_RESERVE);
439   rrm->header.size = htons(sizeof (struct ReleaseReserveMessage));
440   rrm->rid = htonl(rid);
441   transmit_for_status (h, cont, cont_cls, timeout);
442 }
443
444
445 /**
446  * Update a value in the datastore.
447  *
448  * @param h handle to the datastore
449  * @param uid identifier for the value
450  * @param priority how much to increase the priority of the value
451  * @param expiration new expiration value should be MAX of existing and this argument
452  * @param cont continuation to call when done
453  * @param cont_cls closure for cont
454  * @param timeout how long to wait at most for a response
455  */
456 void
457 GNUNET_DATASTORE_update (struct GNUNET_DATASTORE_Handle *h,
458                          unsigned long long uid,
459                          uint32_t priority,
460                          struct GNUNET_TIME_Absolute expiration,
461                          GNUNET_DATASTORE_ContinuationWithStatus cont,
462                          void *cont_cls,
463                          struct GNUNET_TIME_Relative timeout)
464 {
465   struct UpdateMessage *um;
466
467   um = (struct UpdateMessage*) &h[1];
468   um->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_UPDATE);
469   um->header.size = htons(sizeof (struct UpdateMessage));
470   um->priority = htonl(priority);
471   um->expiration = GNUNET_TIME_absolute_hton(expiration);
472   um->uid = GNUNET_htonll(uid);
473   transmit_for_status (h, cont, cont_cls, timeout);
474 }
475
476
477
478
479 /**
480  * Type of a function to call when we receive a message
481  * from the service.  This specific function is used
482  * to handle messages of type "struct DataMessage".
483  *
484  * @param cls closure
485  * @param msg message received, NULL on timeout or fatal error
486  */
487 static void 
488 with_result_response_handler (void *cls,
489                               const struct
490                               GNUNET_MessageHeader * msg)
491 {
492   static struct GNUNET_TIME_Absolute zero;
493   struct GNUNET_DATASTORE_Handle *h = cls;
494   GNUNET_DATASTORE_Iterator cont = h->response_proc;
495   const struct DataMessage *dm;
496   size_t msize;
497
498   if (msg == NULL)
499     {
500       h->response_proc = NULL;
501       GNUNET_CLIENT_disconnect (h->client);
502       h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
503       cont (h->response_proc_cls, 
504             NULL, 0, NULL, 0, 0, 0, zero, 0);
505       return;
506     }
507   if (ntohs(msg->type) == GNUNET_MESSAGE_TYPE_DATASTORE_DATA_END) 
508     {
509       GNUNET_break (ntohs(msg->size) == sizeof(struct GNUNET_MessageHeader));
510       h->response_proc = NULL;
511 #if DEBUG_DATASTORE
512       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
513                   "Received end of result set\n");
514 #endif
515       cont (h->response_proc_cls, 
516             NULL, 0, NULL, 0, 0, 0, zero, 0);
517       return;
518     }
519   if ( (ntohs(msg->size) < sizeof(struct DataMessage)) ||
520        (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_DATASTORE_DATA) ) 
521     {
522       GNUNET_break (0);
523       GNUNET_CLIENT_disconnect (h->client);
524       h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
525       h->response_proc = NULL;
526       cont (h->response_proc_cls, 
527             NULL, 0, NULL, 0, 0, 0, zero, 0);
528       return;
529     }
530   dm = (const struct DataMessage*) msg;
531   msize = ntohl(dm->size);
532   if (ntohs(msg->size) != msize + sizeof(struct DataMessage))
533     {
534       GNUNET_break (0);
535       GNUNET_CLIENT_disconnect (h->client);
536       h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
537       h->response_proc = NULL;
538       cont (h->response_proc_cls, 
539             NULL, 0, NULL, 0, 0, 0, zero, 0);
540       return;
541     }
542 #if DEBUG_DATASTORE
543   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
544               "Received result %llu with type %u and size %u with key %s\n",
545               (unsigned long long) GNUNET_ntohll(dm->uid),
546               ntohl(dm->type),
547               msize,
548               GNUNET_h2s(&dm->key));
549 #endif
550   cont (h->response_proc_cls, 
551         &dm->key,
552         msize,
553         &dm[1],
554         ntohl(dm->type),
555         ntohl(dm->priority),
556         ntohl(dm->anonymity),
557         GNUNET_TIME_absolute_ntoh(dm->expiration),      
558         GNUNET_ntohll(dm->uid));
559   GNUNET_CLIENT_receive (h->client,
560                          &with_result_response_handler,
561                          h,
562                          GNUNET_TIME_absolute_get_remaining (h->timeout));
563 }
564
565
566 /**
567  * Transmit message to datastore service and then
568  * read a result message.
569  *
570  * @param cls closure with handle to datastore
571  * @param size number of bytes we can transmit at most
572  * @param buf where to write transmission, NULL on
573  *        timeout
574  * @return number of bytes copied to buf
575  */
576 static size_t
577 transmit_get_result (void *cls,
578                      size_t size,
579                      void *buf)
580 {
581   struct GNUNET_DATASTORE_Handle *h = cls;
582   GNUNET_DATASTORE_ContinuationWithStatus cont = h->response_proc;
583   uint16_t msize;
584
585   if (buf == NULL)
586     {
587       h->response_proc = NULL;
588       h->message_size = 0;
589       cont (h->response_proc_cls, 
590             GNUNET_SYSERR,
591             gettext_noop ("Error transmitting message to datastore service.\n"));
592       return 0;
593     }
594   msize = h->message_size;
595   GNUNET_assert (msize <= size);
596   memcpy (buf, &h[1], msize);
597 #if DEBUG_DATASTORE
598   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
599               "Transmitted %u byte message to datastore service, now waiting for result.\n",
600               msize);
601 #endif
602   h->message_size = 0;
603   GNUNET_CLIENT_receive (h->client,
604                          &with_result_response_handler,
605                          h,
606                          GNUNET_TIME_absolute_get_remaining (h->timeout));
607   return msize;
608 }
609
610
611 /**
612  * Helper function that will initiate the
613  * transmission of a message to the datastore
614  * service.  The message must already be prepared
615  * and stored in the buffer at the end of the
616  * handle.  The message must be of a type that
617  * expects a "DataMessage" in response.
618  *
619  * @param h handle to the service with prepared message
620  * @param cont function to call with result
621  * @param cont_cls closure
622  * @param timeout timeout for the operation
623  */
624 static void
625 transmit_for_result (struct GNUNET_DATASTORE_Handle *h,
626                      GNUNET_DATASTORE_Iterator cont,
627                      void *cont_cls,
628                      struct GNUNET_TIME_Relative timeout)
629 {
630   static struct GNUNET_TIME_Absolute zero;
631   const struct GNUNET_MessageHeader *hdr;
632   uint16_t msize;
633
634   GNUNET_assert (cont != NULL);
635   hdr = (const struct GNUNET_MessageHeader*) &h[1];
636   msize = ntohs(hdr->size);
637 #if DEBUG_DATASTORE
638   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
639               "Transmitting %u byte message of type %u to datastore service\n",
640               msize,
641               ntohs(hdr->type));
642 #endif
643   GNUNET_assert (h->response_proc == NULL);
644   h->response_proc = cont;
645   h->response_proc_cls = cont_cls;
646   h->timeout = GNUNET_TIME_relative_to_absolute (timeout);
647   h->message_size = msize;
648   if (NULL == GNUNET_CLIENT_notify_transmit_ready (h->client,
649                                                    msize,
650                                                    timeout,
651                                                    &transmit_get_result,
652                                                    h))
653     {
654       GNUNET_break (0);
655       h->response_proc = NULL;
656       h->message_size = 0;
657       cont (h->response_proc_cls, 
658             NULL, 0, NULL, 0, 0, 0, zero, 0);
659     }
660 }
661
662
663 /**
664  * Iterate over the results for a particular key
665  * in the datastore.
666  *
667  * @param h handle to the datastore
668  * @param key maybe NULL (to match all entries)
669  * @param type desired type, 0 for any
670  * @param iter function to call on each matching value;
671  *        will be called once with a NULL value at the end
672  * @param iter_cls closure for iter
673  * @param timeout how long to wait at most for a response
674  */
675 void
676 GNUNET_DATASTORE_get (struct GNUNET_DATASTORE_Handle *h,
677                       const GNUNET_HashCode * key,
678                       uint32_t type,
679                       GNUNET_DATASTORE_Iterator iter, void *iter_cls,
680                       struct GNUNET_TIME_Relative timeout)
681 {
682   struct GetMessage *gm;
683
684   gm = (struct GetMessage*) &h[1];
685   gm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_GET);
686   gm->type = htonl(type);
687   if (key != NULL)
688     {
689       gm->header.size = htons(sizeof (struct GetMessage));
690       gm->key = *key;
691     }
692   else
693     {
694       gm->header.size = htons(sizeof (struct GetMessage) - sizeof(GNUNET_HashCode));
695     }
696   transmit_for_result (h, iter, iter_cls, timeout);
697 }
698
699
700 /**
701  * Get a random value from the datastore.
702  *
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
709  */
710 void
711 GNUNET_DATASTORE_get_random (struct GNUNET_DATASTORE_Handle *h,
712                              GNUNET_DATASTORE_Iterator iter, void *iter_cls,
713                              struct GNUNET_TIME_Relative timeout)
714 {
715   struct GNUNET_MessageHeader *m;
716
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   transmit_for_result (h, iter, iter_cls, timeout);
721 }
722
723
724 /**
725  * Explicitly remove some content from the database.
726  *
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
734  */
735 void
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,
740                          void *cont_cls,
741                          struct GNUNET_TIME_Relative timeout)
742 {
743   struct DataMessage *dm;
744   size_t msize;
745
746   msize = sizeof(struct DataMessage) + size;
747   GNUNET_assert (msize <= GNUNET_SERVER_MAX_MESSAGE_SIZE);
748   dm = (struct DataMessage*) &h[1];
749   dm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE);
750   dm->header.size = htons(msize);
751   dm->rid = htonl(0);
752   dm->size = htonl(size);
753   dm->type = htonl(0);
754   dm->priority = htonl(0);
755   dm->anonymity = htonl(0);
756   dm->uid = GNUNET_htonll(0);
757   dm->expiration.value = 0;
758   dm->key = *key;
759   memcpy (&dm[1], data, size);
760   transmit_for_status (h, cont, cont_cls, timeout);
761 }
762
763
764 /* end of datastore_api.c */