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