dfca2cca32e42b4fa3c8c29e4141c96530853845
[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                           uint64_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->reserved = htonl(0);
411   rm->amount = htonl(amount);
412   rm->entries = htonl(entries);
413   transmit_for_status (h, cont, cont_cls, timeout);
414 }
415
416
417 /**
418  * Signal that all of the data for which a reservation was made has
419  * been stored and that whatever excess space might have been reserved
420  * can now be released.
421  *
422  * @param h handle to the datastore
423  * @param rid reservation ID (value of "success" in original continuation
424  *        from the "reserve" function).
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
428  */
429 void
430 GNUNET_DATASTORE_release_reserve (struct GNUNET_DATASTORE_Handle *h,
431                                   int rid,
432                                   GNUNET_DATASTORE_ContinuationWithStatus cont,
433                                   void *cont_cls,
434                                   struct GNUNET_TIME_Relative timeout)
435 {
436   struct ReleaseReserveMessage *rrm;
437
438   rrm = (struct ReleaseReserveMessage*) &h[1];
439   rrm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_RELEASE_RESERVE);
440   rrm->header.size = htons(sizeof (struct ReleaseReserveMessage));
441   rrm->rid = htonl(rid);
442   transmit_for_status (h, cont, cont_cls, timeout);
443 }
444
445
446 /**
447  * Update a value in the datastore.
448  *
449  * @param h handle to the datastore
450  * @param uid identifier for the value
451  * @param priority how much to increase the priority of the value
452  * @param expiration new expiration value should be MAX of existing and this argument
453  * @param cont continuation to call when done
454  * @param cont_cls closure for cont
455  * @param timeout how long to wait at most for a response
456  */
457 void
458 GNUNET_DATASTORE_update (struct GNUNET_DATASTORE_Handle *h,
459                          unsigned long long uid,
460                          uint32_t priority,
461                          struct GNUNET_TIME_Absolute expiration,
462                          GNUNET_DATASTORE_ContinuationWithStatus cont,
463                          void *cont_cls,
464                          struct GNUNET_TIME_Relative timeout)
465 {
466   struct UpdateMessage *um;
467
468   um = (struct UpdateMessage*) &h[1];
469   um->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_UPDATE);
470   um->header.size = htons(sizeof (struct UpdateMessage));
471   um->priority = htonl(priority);
472   um->expiration = GNUNET_TIME_absolute_hton(expiration);
473   um->uid = GNUNET_htonll(uid);
474   transmit_for_status (h, cont, cont_cls, timeout);
475 }
476
477
478
479
480 /**
481  * Type of a function to call when we receive a message
482  * from the service.  This specific function is used
483  * to handle messages of type "struct DataMessage".
484  *
485  * @param cls closure
486  * @param msg message received, NULL on timeout or fatal error
487  */
488 static void 
489 with_result_response_handler (void *cls,
490                               const struct
491                               GNUNET_MessageHeader * msg)
492 {
493   static struct GNUNET_TIME_Absolute zero;
494   struct GNUNET_DATASTORE_Handle *h = cls;
495   GNUNET_DATASTORE_Iterator cont = h->response_proc;
496   const struct DataMessage *dm;
497   size_t msize;
498
499   if (msg == NULL)
500     {
501       h->response_proc = NULL;
502       GNUNET_CLIENT_disconnect (h->client);
503       h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
504       cont (h->response_proc_cls, 
505             NULL, 0, NULL, 0, 0, 0, zero, 0);
506       return;
507     }
508   if (ntohs(msg->type) == GNUNET_MESSAGE_TYPE_DATASTORE_DATA_END) 
509     {
510       GNUNET_break (ntohs(msg->size) == sizeof(struct GNUNET_MessageHeader));
511       h->response_proc = NULL;
512 #if DEBUG_DATASTORE
513       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
514                   "Received end of result set\n");
515 #endif
516       cont (h->response_proc_cls, 
517             NULL, 0, NULL, 0, 0, 0, zero, 0);
518       return;
519     }
520   if ( (ntohs(msg->size) < sizeof(struct DataMessage)) ||
521        (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_DATASTORE_DATA) ) 
522     {
523       GNUNET_break (0);
524       GNUNET_CLIENT_disconnect (h->client);
525       h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
526       h->response_proc = NULL;
527       cont (h->response_proc_cls, 
528             NULL, 0, NULL, 0, 0, 0, zero, 0);
529       return;
530     }
531   dm = (const struct DataMessage*) msg;
532   msize = ntohl(dm->size);
533   if (ntohs(msg->size) != msize + sizeof(struct DataMessage))
534     {
535       GNUNET_break (0);
536       GNUNET_CLIENT_disconnect (h->client);
537       h->client = GNUNET_CLIENT_connect (h->sched, "datastore", h->cfg);
538       h->response_proc = NULL;
539       cont (h->response_proc_cls, 
540             NULL, 0, NULL, 0, 0, 0, zero, 0);
541       return;
542     }
543 #if DEBUG_DATASTORE
544   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
545               "Received result %llu with type %u and size %u with key %s\n",
546               (unsigned long long) GNUNET_ntohll(dm->uid),
547               ntohl(dm->type),
548               msize,
549               GNUNET_h2s(&dm->key));
550 #endif
551   cont (h->response_proc_cls, 
552         &dm->key,
553         msize,
554         &dm[1],
555         ntohl(dm->type),
556         ntohl(dm->priority),
557         ntohl(dm->anonymity),
558         GNUNET_TIME_absolute_ntoh(dm->expiration),      
559         GNUNET_ntohll(dm->uid));
560   GNUNET_CLIENT_receive (h->client,
561                          &with_result_response_handler,
562                          h,
563                          GNUNET_TIME_absolute_get_remaining (h->timeout));
564 }
565
566
567 /**
568  * Transmit message to datastore service and then
569  * read a result message.
570  *
571  * @param cls closure with handle to datastore
572  * @param size number of bytes we can transmit at most
573  * @param buf where to write transmission, NULL on
574  *        timeout
575  * @return number of bytes copied to buf
576  */
577 static size_t
578 transmit_get_result (void *cls,
579                      size_t size,
580                      void *buf)
581 {
582   struct GNUNET_DATASTORE_Handle *h = cls;
583   GNUNET_DATASTORE_ContinuationWithStatus cont = h->response_proc;
584   uint16_t msize;
585
586   if (buf == NULL)
587     {
588       h->response_proc = NULL;
589       h->message_size = 0;
590       cont (h->response_proc_cls, 
591             GNUNET_SYSERR,
592             gettext_noop ("Error transmitting message to datastore service.\n"));
593       return 0;
594     }
595   msize = h->message_size;
596   GNUNET_assert (msize <= size);
597   memcpy (buf, &h[1], msize);
598 #if DEBUG_DATASTORE
599   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
600               "Transmitted %u byte message to datastore service, now waiting for result.\n",
601               msize);
602 #endif
603   h->message_size = 0;
604   GNUNET_CLIENT_receive (h->client,
605                          &with_result_response_handler,
606                          h,
607                          GNUNET_TIME_absolute_get_remaining (h->timeout));
608   return msize;
609 }
610
611
612 /**
613  * Helper function that will initiate the
614  * transmission of a message to the datastore
615  * service.  The message must already be prepared
616  * and stored in the buffer at the end of the
617  * handle.  The message must be of a type that
618  * expects a "DataMessage" in response.
619  *
620  * @param h handle to the service with prepared message
621  * @param cont function to call with result
622  * @param cont_cls closure
623  * @param timeout timeout for the operation
624  */
625 static void
626 transmit_for_result (struct GNUNET_DATASTORE_Handle *h,
627                      GNUNET_DATASTORE_Iterator cont,
628                      void *cont_cls,
629                      struct GNUNET_TIME_Relative timeout)
630 {
631   static struct GNUNET_TIME_Absolute zero;
632   const struct GNUNET_MessageHeader *hdr;
633   uint16_t msize;
634
635   GNUNET_assert (cont != NULL);
636   hdr = (const struct GNUNET_MessageHeader*) &h[1];
637   msize = ntohs(hdr->size);
638 #if DEBUG_DATASTORE
639   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
640               "Transmitting %u byte message of type %u to datastore service\n",
641               msize,
642               ntohs(hdr->type));
643 #endif
644   GNUNET_assert (h->response_proc == NULL);
645   h->response_proc = cont;
646   h->response_proc_cls = cont_cls;
647   h->timeout = GNUNET_TIME_relative_to_absolute (timeout);
648   h->message_size = msize;
649   if (NULL == GNUNET_CLIENT_notify_transmit_ready (h->client,
650                                                    msize,
651                                                    timeout,
652                                                    &transmit_get_result,
653                                                    h))
654     {
655       GNUNET_break (0);
656       h->response_proc = NULL;
657       h->message_size = 0;
658       cont (h->response_proc_cls, 
659             NULL, 0, NULL, 0, 0, 0, zero, 0);
660     }
661 }
662
663
664 /**
665  * Iterate over the results for a particular key
666  * in the datastore.
667  *
668  * @param h handle to the datastore
669  * @param key maybe NULL (to match all entries)
670  * @param type desired type, 0 for any
671  * @param iter function to call on each matching value;
672  *        will be called once with a NULL value at the end
673  * @param iter_cls closure for iter
674  * @param timeout how long to wait at most for a response
675  */
676 void
677 GNUNET_DATASTORE_get (struct GNUNET_DATASTORE_Handle *h,
678                       const GNUNET_HashCode * key,
679                       uint32_t type,
680                       GNUNET_DATASTORE_Iterator iter, void *iter_cls,
681                       struct GNUNET_TIME_Relative timeout)
682 {
683   struct GetMessage *gm;
684
685   gm = (struct GetMessage*) &h[1];
686   gm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_GET);
687   gm->type = htonl(type);
688   if (key != NULL)
689     {
690       gm->header.size = htons(sizeof (struct GetMessage));
691       gm->key = *key;
692     }
693   else
694     {
695       gm->header.size = htons(sizeof (struct GetMessage) - sizeof(GNUNET_HashCode));
696     }
697   transmit_for_result (h, iter, iter_cls, timeout);
698 }
699
700
701 /**
702  * Get a random value from the datastore.
703  *
704  * @param h handle to the datastore
705  * @param iter function to call on a random value; it
706  *        will be called exactly once; if no values
707  *        are available, the value will be NULL.
708  * @param iter_cls closure for iter
709  * @param timeout how long to wait at most for a response
710  */
711 void
712 GNUNET_DATASTORE_get_random (struct GNUNET_DATASTORE_Handle *h,
713                              GNUNET_DATASTORE_Iterator iter, void *iter_cls,
714                              struct GNUNET_TIME_Relative timeout)
715 {
716   struct GNUNET_MessageHeader *m;
717
718   m = (struct GNUNET_MessageHeader*) &h[1];
719   m->type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_GET_RANDOM);
720   m->size = htons(sizeof (struct GNUNET_MessageHeader));
721   transmit_for_result (h, iter, iter_cls, timeout);
722 }
723
724
725 /**
726  * Explicitly remove some content from the database.
727  *
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
735  */
736 void
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,
741                          void *cont_cls,
742                          struct GNUNET_TIME_Relative timeout)
743 {
744   struct DataMessage *dm;
745   size_t msize;
746
747   msize = sizeof(struct DataMessage) + size;
748   GNUNET_assert (msize <= GNUNET_SERVER_MAX_MESSAGE_SIZE);
749   dm = (struct DataMessage*) &h[1];
750   dm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE);
751   dm->header.size = htons(msize);
752   dm->rid = htonl(0);
753   dm->size = htonl(size);
754   dm->type = htonl(0);
755   dm->priority = htonl(0);
756   dm->anonymity = htonl(0);
757   dm->uid = GNUNET_htonll(0);
758   dm->expiration.value = 0;
759   dm->key = *key;
760   memcpy (&dm[1], data, size);
761   transmit_for_status (h, cont, cont_cls, timeout);
762 }
763
764
765 /* end of datastore_api.c */