3b9e22a3a0953b9639454295a19ac333350da783
[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
27 #include "platform.h"
28 #include "gnunet_datastore_service.h"
29 #include "datastore.h"
30
31
32 struct MessageQueue
33 {
34   /**
35    * This is a linked list.
36    */
37   struct MessageQueue *next;
38
39   /**
40    * Message we will transmit (allocated at the end
41    * of this struct; do not free!).
42    */
43   struct GNUNET_MessageHeader *msg;
44
45   /**
46    * Function to call on the response.
47    */
48   GNUNET_CLIENT_MessageHandler response_processor;
49   
50   /**
51    * Closure for response_processor.
52    */
53   void *response_processor_cls;
54
55 };
56
57
58 /**
59  * Handle to the datastore service.
60  */
61 struct GNUNET_DATASTORE_Handle
62 {
63
64   /**
65    * Current connection to the datastore service.
66    */
67   struct GNUNET_CLIENT_Connection *client;
68   
69   /**
70    * Linked list of messages waiting to be transmitted.
71    */
72   struct MessageQueue *messages;
73
74   /**
75    * Current response processor (NULL if we are not waiting
76    * for a response).  Largely used only to know if we have
77    * a 'receive' request pending.
78    */
79   GNUNET_CLIENT_MessageHandler response_proc;
80   
81   /**
82    * Closure for response_proc.
83    */
84   void *response_proc_cls;
85
86 };
87
88
89 /**
90  * Connect to the datastore service.
91  *
92  * @param cfg configuration to use
93  * @param sched scheduler to use
94  * @return handle to use to access the service
95  */
96 struct GNUNET_DATASTORE_Handle *GNUNET_DATASTORE_connect (struct
97                                                           GNUNET_CONFIGURATION_Handle
98                                                           *cfg,
99                                                           struct
100                                                           GNUNET_SCHEDULER_Handle
101                                                           *sched)
102 {
103   struct GNUNET_CLIENT_Connection *c;
104   struct GNUNET_DATASTORE_Handle *h;
105   
106   c = GNUNET_CLIENT_connect (sched, "datastore", cfg);
107   if (c == NULL)
108     return NULL; /* oops */
109   h = GNUNET_malloc (sizeof(struct GNUNET_DATASTORE_Handle));
110   h->client = c;
111   return h;
112 }
113
114
115 /**
116  * Transmit DROP message to Database service.
117  */
118 static size_t
119 transmit_drop (void *cls,
120                size_t size, void *buf)
121 {
122   struct GNUNET_DATASTORE_Handle *h = cls;
123   struct GNUNET_MessageHeader *hdr;
124
125   if (buf == NULL)
126     {
127       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
128                   _("Failed to transmit request to drop database.\n"));
129       GNUNET_DATASTORE_disconnect (h, GNUNET_NO);
130       return 0;
131     }
132   GNUNET_assert (size >= sizeof(struct GNUNET_MessageHeader));
133   hdr = buf;
134   hdr->size = htons(sizeof(struct GNUNET_MessageHeader));
135   hdr->type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_DROP));
136   GNUNET_DATASTORE_disconnect (h, GNUNET_NO);
137   return sizeof(struct GNUNET_MessageHeader);
138 }
139
140
141 /**
142  * Disconnect from the datastore service (and free
143  * associated resources).
144  *
145  * @param h handle to the datastore
146  * @param drop set to GNUNET_YES to delete all data in datastore (!)
147  */
148 void GNUNET_DATASTORE_disconnect (struct GNUNET_DATASTORE_Handle *h,
149                                   int drop)
150 {
151   if (GNUNET_YES == drop)
152     {
153       if (NULL != 
154           GNUNET_CLIENT_notify_transmit_ready (h->client,
155                                                sizeof(struct GNUNET_MessageHeader),
156                                                GNUNET_TIME_UNIT_MINUTES,
157                                                &transmit_drop,
158                                                h))
159         return;
160       GNUNET_break (0);
161     }
162   GNUNET_CLIENT_disconnect (h->client);
163   GNUNET_free (h);
164 }
165
166
167 /**
168  * The closure is followed by the data message.
169  */
170 struct PutClosure
171 {
172   struct GNUNET_DATASTORE_Handle *h;
173   GNUNET_DATASTORE_ContinuationWithStatus cont;
174   void *cont_cls;
175 };
176
177
178 /**
179  * Transmit PUT message to Database service.
180  */
181 static size_t
182 transmit_put (void *cls,
183               size_t size, void *buf)
184 {
185   struct PutClosure *pc = cls;
186   struct DataMessage *dm;
187   uint16_t msize;
188
189   if (buf == NULL)
190     {
191       pc->cont (pc->cont_cls, GNUNET_SYSERR,
192                 gettext_noop ("Error transmitting `PUT' message to datastore service.\n"));
193       GNUNET_free (pc);
194       return 0;
195     }
196   dm = (struct DataMessage*) &pc[1];
197   msize = ntohs(dm->size);
198   GNUNET_assert (msize <= size);
199   memcpy (buf, dm, msize);
200   /* FIXME: wait for response from datastore, then
201      call our continuation! */
202   return msize;
203 }
204
205
206 /**
207  * Store an item in the datastore.  If the item is already present,
208  * the priorities are summed up and the higher expiration time and
209  * lower anonymity level is used.
210  *
211  * @param h handle to the datastore
212  * @param key key for the value
213  * @param size number of bytes in data
214  * @param data content stored
215  * @param type type of the content
216  * @param priority priority of the content
217  * @param anonymity anonymity-level for the content
218  * @param expiration expiration time for the content
219  * @param timeout timeout for the operation
220  * @param cont continuation to call when done
221  * @param cont_cls closure for cont
222  */
223 void
224 GNUNET_DATASTORE_put (struct GNUNET_DATASTORE_Handle *h,
225                       int rid,
226                       const GNUNET_HashCode * key,
227                       uint32_t size,
228                       const void *data,
229                       uint32_t type,
230                       uint32_t priority,
231                       uint32_t anonymity,
232                       struct GNUNET_TIME_Absolute expiration,
233                       struct GNUNET_TIME_Relative timeout,
234                       GNUNET_DATASTORE_ContinuationWithStatus cont,
235                       void *cont_cls)
236 {
237   struct PutClosure *pc;
238   struct DataMessage *dm;
239
240   pc = GNUNET_malloc (sizeof(struct PutClosure) + 
241                       sizeof(struct DataMessage) + 
242                       size);
243   dm = (struct DataMessage*) &pc[1];
244   pc->h = h;
245   pc->cont = cont;
246   pc->cont_cls = cont_cls;
247   dm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_PUT);
248   dm->header.size = htons(sizeof(struct DataMessage) + size);
249   dm->rid = htonl(rid);
250   dm->size = htonl(size);
251   dm->type = htonl(type);
252   dm->priority = htonl(priority);
253   dm->anonymity = htonl(anonymity);
254   dm->uid = GNUNET_htonll(0);
255   dm->expiration = GNUNET_htonll(expiration);
256   dm->key = *key;
257   memcpy (&dm[1], data, size);
258   if (NULL == GNUNET_CLIENT_notify_transmit_ready (h->client,
259                                                    sizeof(struct DataMessage) + size,
260                                                    timeout,
261                                                    &transmit_put,
262                                                    pc))
263     {
264       GNUNET_break (0);
265       cont (cont_cls, GNUNET_SYSERR,
266             gettext_noop ("Not ready to transmit request to datastore service"));
267     }
268 }
269
270
271 /**
272  * Reserve space in the datastore.  This function should be used
273  * to avoid "out of space" failures during a longer sequence of "put"
274  * operations (for example, when a file is being inserted).
275  *
276  * @param h handle to the datastore
277  * @param amount how much space (in bytes) should be reserved (for content only)
278  * @param entries how many entries will be created (to calculate per-entry overhead)
279  * @param cont continuation to call when done; "success" will be set to
280  *             a positive reservation value if space could be reserved.
281  * @param cont_cls closure for cont
282  */
283 void
284 GNUNET_DATASTORE_reserve (struct GNUNET_DATASTORE_Handle *h,
285                           uint64_t amount,
286                           uint64_t entries,
287                           GNUNET_DATASTORE_ContinuationWithStatus cont,
288                           void *cont_cls)
289 {
290   cont (cont_cls, GNUNET_SYSERR, "not implemented");
291 }
292
293
294 /**
295  * Signal that all of the data for which a reservation was made has
296  * been stored and that whatever excess space might have been reserved
297  * can now be released.
298  *
299  * @param h handle to the datastore
300  * @param rid reservation ID (value of "success" in original continuation
301  *        from the "reserve" function).
302  * @param cont continuation to call when done
303  * @param cont_cls closure for cont
304  */
305 void
306 GNUNET_DATASTORE_release_reserve (struct GNUNET_DATASTORE_Handle *h,
307                                   int rid,
308                                   GNUNET_DATASTORE_ContinuationWithStatus cont,
309                                   void *cont_cls)
310 {
311   cont (cont_cls, GNUNET_OK, NULL);
312 }
313
314
315 /**
316  * Update a value in the datastore.
317  *
318  * @param h handle to the datastore
319  * @param uid identifier for the value
320  * @param priority how much to increase the priority of the value
321  * @param expiration new expiration value should be MAX of existing and this argument
322  * @param cont continuation to call when done
323  * @param cont_cls closure for cont
324  */
325 void
326 GNUNET_DATASTORE_update (struct GNUNET_DATASTORE_Handle *h,
327                          unsigned long long uid,
328                          uint32_t priority,
329                          struct GNUNET_TIME_Absolute expiration,
330                          GNUNET_DATASTORE_ContinuationWithStatus cont,
331                          void *cont_cls)
332 {
333   cont (cont_cls, GNUNET_SYSERR, "not implemented");
334 }
335
336
337 /**
338  * Iterate over the results for a particular key
339  * in the datastore.
340  *
341  * @param h handle to the datastore
342  * @param key maybe NULL (to match all entries)
343  * @param type desired type, 0 for any
344  * @param iter function to call on each matching value;
345  *        will be called once with a NULL value at the end
346  * @param iter_cls closure for iter
347  */
348 void
349 GNUNET_DATASTORE_get (struct GNUNET_DATASTORE_Handle *h,
350                       const GNUNET_HashCode * key,
351                       uint32_t type,
352                       GNUNET_DATASTORE_Iterator iter, void *iter_cls)
353 {
354   static struct GNUNET_TIME_Absolute zero;
355   iter (iter_cls,
356         NULL, 0, NULL, 0, 0, 0, zero, 0);
357 }
358
359
360 /**
361  * Get a random value from the datastore.
362  *
363  * @param h handle to the datastore
364  * @param iter function to call on a random value; it
365  *        will be called exactly once; if no values
366  *        are available, the value will be NULL.
367  * @param iter_cls closure for iter
368  */
369 void
370 GNUNET_DATASTORE_get_random (struct GNUNET_DATASTORE_Handle *h,
371                              GNUNET_DATASTORE_Iterator iter, void *iter_cls)
372 {
373   static struct GNUNET_TIME_Absolute zero;
374   
375   iter (iter_cls,
376         NULL, 0, NULL, 0, 0, 0, zero, 0);
377 }
378
379
380 /**
381  * Explicitly remove some content from the database.
382  *
383  * @param h handle to the datastore
384  * @param key key for the value
385  * @param size number of bytes in data
386  * @param data content stored
387  * @param cont continuation to call when done
388  * @param cont_cls closure for cont
389  */
390 void
391 GNUNET_DATASTORE_remove (struct GNUNET_DATASTORE_Handle *h,
392                          const GNUNET_HashCode * key,
393                          uint32_t size, const void *data,
394                          GNUNET_DATASTORE_ContinuationWithStatus cont,
395                          void *cont_cls)
396 {
397   cont (cont_cls, GNUNET_SYSERR, "not implemented");
398 }
399
400
401 /* end of datastore_api.c */