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