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