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