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