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