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