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