aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2009-06-15 04:46:35 +0000
committerChristian Grothoff <christian@grothoff.org>2009-06-15 04:46:35 +0000
commitf90483fc8b2a7ee72c0c5f82e714b3de1dd26a71 (patch)
treeefa70facdba2a31f4e5bdfbef5f87b85aa807e10 /src
parent17b95ebf7226cc5ca4ee7d90ff0de874b0dc7576 (diff)
downloadgnunet-f90483fc8b2a7ee72c0c5f82e714b3de1dd26a71.tar.gz
gnunet-f90483fc8b2a7ee72c0c5f82e714b3de1dd26a71.zip
stuff
Diffstat (limited to 'src')
-rw-r--r--src/datastore/datastore.h102
-rw-r--r--src/datastore/datastore_api.c98
-rw-r--r--src/datastore/gnunet-service-datastore.c319
-rw-r--r--src/datastore/plugin_datastore.h8
4 files changed, 519 insertions, 8 deletions
diff --git a/src/datastore/datastore.h b/src/datastore/datastore.h
index e6860efbb..9165c8af8 100644
--- a/src/datastore/datastore.h
+++ b/src/datastore/datastore.h
@@ -29,6 +29,108 @@
29 29
30#include "gnunet_util_lib.h" 30#include "gnunet_util_lib.h"
31 31
32/**
33 * Message from datastore service informing client about
34 * the current size of the datastore.
35 */
36struct SizeMessage
37{
38 /**
39 * Type is GNUNET_MESSAGE_TYPE_DATASTORE_SIZE.
40 */
41 struct GNUNET_MessageHeader header;
42
43 /**
44 * Always zero.
45 */
46 uint32_t reserved GNUNET_PACKED;
47
48 /**
49 * Size of the datastore in bytes.
50 */
51 uint64_t size GNUNET_PACKED;
52};
53
54
55/**
56 * Message to the datastore service asking about specific
57 * content.
58 */
59struct GetMessage
60{
61 /**
62 * Type is GNUNET_MESSAGE_TYPE_DATASTORE_GET. Size
63 * can either be "sizeof(struct GetMessage)" or
64 * "sizeof(struct GetMessage) - sizeof(GNUNET_HashCode)"!
65 */
66 struct GNUNET_MessageHeader header;
67
68 /**
69 * Desired content type.
70 */
71 uint32_t type GNUNET_PACKED;
72
73 /**
74 * Desired key (optional). Check the "size" of the
75 * header to see if the key is actually present.
76 */
77 GNUNET_HashCode key GNUNET_PACKED;
78
79};
80
81
82/**
83 * Message transmitting content from or to the datastore
84 * service.
85 */
86struct DataMessage
87{
88 /**
89 * Type is either GNUNET_MESSAGE_TYPE_DATASTORE_PUT,
90 * GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE or
91 * GNUNET_MESSAGE_TYPE_DATASTORE_DATA. Depending on the message
92 * type, some fields may simply have values of zero.
93 */
94 struct GNUNET_MessageHeader header;
95
96 /**
97 * Always zero.
98 */
99 uint32_t reserved GNUNET_PACKED;
100
101 /**
102 * Number of bytes in the item (NBO).
103 */
104 uint32_t size GNUNET_PACKED;
105
106 /**
107 * Type of the item (NBO), zero for remove.
108 */
109 uint32_t type GNUNET_PACKED;
110
111 /**
112 * Priority of the item (NBO), zero for remove.
113 */
114 uint32_t priority GNUNET_PACKED;
115
116 /**
117 * Desired anonymity level (NBO), zero for remove.
118 */
119 uint32_t anonymity GNUNET_PACKED;
120
121 /**
122 * Expiration time (NBO); zero for remove.
123 */
124 struct GNUNET_TIME_AbsoluteNBO expiration;
125
126 /**
127 * Key under which the item can be found.
128 */
129 GNUNET_HashCode key GNUNET_PACKED;
130
131};
132
133
32 134
33 135
34#endif 136#endif
diff --git a/src/datastore/datastore_api.c b/src/datastore/datastore_api.c
index cc563ba79..95ae25f03 100644
--- a/src/datastore/datastore_api.c
+++ b/src/datastore/datastore_api.c
@@ -22,17 +22,88 @@
22 * @file datastore/datastore_api.c 22 * @file datastore/datastore_api.c
23 * @brief Management for the datastore for files stored on a GNUnet node 23 * @brief Management for the datastore for files stored on a GNUnet node
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 *
26 * TODO:
27 * 1) clarify API (wrt. efficient UPDATE of priority/expiration after GET)
28 * 2) implement INIT
29 * 3) implement SIZE handling (=> API impact?)
30 * 4) implement DROP
31 * 5) implement PUT
32 * 6) implement GET
33 * 7) implement GET_RANDOM
34 * 8) implement REMOVE
25 */ 35 */
26 36
27#include "platform.h" 37#include "platform.h"
28#include "gnunet_datastore_service.h" 38#include "gnunet_datastore_service.h"
29#include "datastore.h" 39#include "datastore.h"
30 40
41
42struct MessageQueue
43{
44 /**
45 * This is a linked list.
46 */
47 struct MessageQueue *next;
48
49 /**
50 * Message we will transmit (allocated at the end
51 * of this struct; do not free!).
52 */
53 struct GNUNET_MessageHeader *msg;
54
55 /**
56 * Function to call on the response.
57 */
58 GNUNET_CLIENT_MessageHandler response_processor;
59
60 /**
61 * Closure for response_processor.
62 */
63 void *response_processor_cls;
64
65};
66
67
31/** 68/**
32 * Handle to the datastore service. 69 * Handle to the datastore service.
33 */ 70 */
34struct GNUNET_DATASTORE_Handle 71struct GNUNET_DATASTORE_Handle
35{ 72{
73
74 /**
75 * Current connection to the datastore service.
76 */
77 struct GNUNET_CLIENT_Connection *client;
78
79 /**
80 * Linked list of messages waiting to be transmitted.
81 */
82 struct MessageQueue *messages;
83
84 /**
85 * Current response processor (NULL if we are not waiting
86 * for a response). Largely used only to know if we have
87 * a 'receive' request pending.
88 */
89 GNUNET_CLIENT_MessageHandler response_proc;
90
91 /**
92 * Closure for response_proc.
93 */
94 void *response_proc_cls;
95
96 /**
97 * Current size of the datastore (cached).
98 */
99 unsigned long long size;
100
101 /**
102 * Set to GNUNET_YES if we have received the size
103 * from the datastore.
104 */
105 int ready;
106
36}; 107};
37 108
38 109
@@ -50,7 +121,16 @@ struct GNUNET_DATASTORE_Handle *GNUNET_DATASTORE_connect (struct
50 GNUNET_SCHEDULER_Handle 121 GNUNET_SCHEDULER_Handle
51 *sched) 122 *sched)
52{ 123{
53 return NULL; 124 struct GNUNET_CLIENT_Connection *c;
125 struct GNUNET_DATASTORE_Handle *h;
126
127 c = GNUNET_CLIENT_connect (sched, "datastore", cfg);
128 if (c == NULL)
129 return NULL; /* oops */
130 h = GNUNET_malloc (sizeof(struct GNUNET_DATASTORE_Handle));
131 h->client = c;
132 /* FIXME: send 'join' request */
133 return h;
54} 134}
55 135
56 136
@@ -64,6 +144,12 @@ struct GNUNET_DATASTORE_Handle *GNUNET_DATASTORE_connect (struct
64void GNUNET_DATASTORE_disconnect (struct GNUNET_DATASTORE_Handle *h, 144void GNUNET_DATASTORE_disconnect (struct GNUNET_DATASTORE_Handle *h,
65 int drop) 145 int drop)
66{ 146{
147 if (GNUNET_YES == drop)
148 {
149 /* FIXME: send 'drop' request */
150 }
151 GNUNET_CLIENT_disconnect (h->client);
152 GNUNET_free (h);
67} 153}
68 154
69 155
@@ -74,7 +160,9 @@ void GNUNET_DATASTORE_disconnect (struct GNUNET_DATASTORE_Handle *h,
74 */ 160 */
75unsigned long long GNUNET_DATASTORE_size (struct GNUNET_DATASTORE_Handle *h) 161unsigned long long GNUNET_DATASTORE_size (struct GNUNET_DATASTORE_Handle *h)
76{ 162{
77 return 0; 163 if (GNUNET_YES != h->ready)
164 return (unsigned long long) -1LL;
165 return h->size;
78} 166}
79 167
80 168
@@ -129,7 +217,7 @@ GNUNET_DATASTORE_get (struct GNUNET_DATASTORE_Handle *h,
129 * Get a random value from the datastore. 217 * Get a random value from the datastore.
130 * 218 *
131 * @param h handle to the datastore 219 * @param h handle to the datastore
132 * @param iter function to call on each matching value; 220 * @param iter function to call on a random value; it
133 * will be called exactly once; if no values 221 * will be called exactly once; if no values
134 * are available, the value will be NULL. 222 * are available, the value will be NULL.
135 * @param iter_cls closure for iter 223 * @param iter_cls closure for iter
@@ -138,6 +226,10 @@ void
138GNUNET_DATASTORE_get_random (struct GNUNET_DATASTORE_Handle *h, 226GNUNET_DATASTORE_get_random (struct GNUNET_DATASTORE_Handle *h,
139 GNUNET_DATASTORE_Iterator iter, void *iter_cls) 227 GNUNET_DATASTORE_Iterator iter, void *iter_cls)
140{ 228{
229 static struct GNUNET_TIME_Absolute zero;
230
231 iter (iter_cls,
232 NULL, 0, NULL, 0, 0, 0, zero, 0);
141} 233}
142 234
143 235
diff --git a/src/datastore/gnunet-service-datastore.c b/src/datastore/gnunet-service-datastore.c
index 8ee153db0..fe7987632 100644
--- a/src/datastore/gnunet-service-datastore.c
+++ b/src/datastore/gnunet-service-datastore.c
@@ -22,6 +22,18 @@
22 * @file datastore/gnunet-service-datastore.c 22 * @file datastore/gnunet-service-datastore.c
23 * @brief Management for the datastore for files stored on a GNUnet node 23 * @brief Management for the datastore for files stored on a GNUnet node
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 *
26 * TODO:
27 * 1) transmit and transmit flow-control (when do we signal client 'success'?
28 * ALSO: async transmit will need to address ref-counting issues on client!
29 * 2) efficient "update" for client to raise priority / expiration
30 * (not possible with current datastore API, but plugin API has support!);
31 * [ maybe integrate desired priority/expiration updates directly
32 * with 'GET' request? ]
33 * 3) semantics of "PUT" (plugin) if entry exists (should likely
34 * be similar to "UPDATE" (need to specify in PLUGIN API!)
35 * 4) quota management code!
36 * 5) add bloomfilter for efficiency!
25 */ 37 */
26 38
27#include "platform.h" 39#include "platform.h"
@@ -41,7 +53,7 @@ struct DatastorePlugin
41 * API of the transport as returned by the plugin's 53 * API of the transport as returned by the plugin's
42 * initialization function. 54 * initialization function.
43 */ 55 */
44 struct GNUNET_DATSTORE_PluginFunctions *api; 56 struct GNUNET_DATASTORE_PluginFunctions *api;
45 57
46 /** 58 /**
47 * Short name for the plugin (i.e. "sqlite"). 59 * Short name for the plugin (i.e. "sqlite").
@@ -69,11 +81,314 @@ static struct DatastorePlugin *plugin;
69 81
70 82
71/** 83/**
84 * Transmit the given message to the client.
85 */
86static void
87transmit (struct GNUNET_SERVER_Client *client,
88 const struct GNUNET_MessageHeader *msg)
89{
90 /* FIXME! */
91}
92
93
94/**
95 * Transmit the size of the current datastore to the client.
96 */
97static void
98transmit_size (struct GNUNET_SERVER_Client *client)
99{
100 struct SizeMessage sm;
101
102 sm.header.size = htons(sizeof(struct SizeMessage));
103 sm.header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_SIZE);
104 sm.reserved = htonl(0);
105 sm.size = GNUNET_htonll(plugin->api->get_size (plugin->api->cls));
106 transmit (client, &sm.header);
107}
108
109
110/**
111 * Function that will transmit the given datastore entry
112 * to the client.
113 *
114 * @param cls closure, pointer to the client (of type GNUNET_SERVER_Client).
115 * @param key key for the content
116 * @param size number of bytes in data
117 * @param data content stored
118 * @param type type of the content
119 * @param priority priority of the content
120 * @param anonymity anonymity-level for the content
121 * @param expiration expiration time for the content
122 * @param uid unique identifier for the datum;
123 * maybe 0 if no unique identifier is available
124 *
125 * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue,
126 * GNUNET_NO to delete the item and continue (if supported)
127 */
128static int
129transmit_item (void *cls,
130 const GNUNET_HashCode * key,
131 uint32_t size,
132 const void *data,
133 uint32_t type,
134 uint32_t priority,
135 uint32_t anonymity,
136 struct GNUNET_TIME_Absolute
137 expiration, unsigned long long uid)
138{
139 struct GNUNET_SERVER_Client *client = cls;
140 struct GNUNET_MessageHeader end;
141 struct DataMessage *dm;
142
143 if (key == NULL)
144 {
145 /* transmit 'DATA_END' */
146 end.size = htons(sizeof(struct GNUNET_MessageHeader));
147 end.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_DATA_END);
148 transmit (client, &end);
149 return GNUNET_OK;
150 }
151 /* FIXME: make use of 'uid' for efficient priority/expiration update! */
152 dm = GNUNET_malloc (sizeof(struct DataMessage) + size);
153 dm->header.size = htons(sizeof(struct DataMessage) + size);
154 dm->header.type = htons(GNUNET_MESSAGE_TYPE_DATASTORE_DATA);
155 dm->reserved = htonl(0);
156 dm->size = htonl(size);
157 dm->type = htonl(type);
158 dm->priority = htonl(priority);
159 dm->anonymity = htonl(anonymity);
160 dm->expiration = GNUNET_TIME_absolute_hton(expiration);
161 dm->key = *key;
162 memcpy (&dm[1], data, size);
163 transmit (client, &dm->header);
164 GNUNET_free (dm);
165 return GNUNET_OK;
166}
167
168
169/**
170 * Handle INIT-message.
171 *
172 * @param cls closure
173 * @param client identification of the client
174 * @param message the actual message
175 */
176static void
177handle_init (void *cls,
178 struct GNUNET_SERVER_Client *client,
179 const struct GNUNET_MessageHeader *message)
180{
181 transmit_size (client);
182 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
183}
184
185
186/**
187 * Check that the given message is a valid data message.
188 *
189 * @return NULL if the message is not well-formed, otherwise the message
190 */
191static const struct DataMessage *
192check_data (const struct GNUNET_MessageHeader *message)
193{
194 uint16_t size;
195 uint32_t dsize;
196 const struct DataMessage *dm;
197
198 size = ntohs(message->size);
199 if (size < sizeof(struct DataMessage))
200 {
201 GNUNET_break (0);
202 return NULL;
203 }
204 dm = (const struct DataMessage *) message;
205 dsize = ntohl(dm->size);
206 if (size != dsize + sizeof(struct DataMessage))
207 {
208 GNUNET_break (0);
209 return NULL;
210 }
211 if ( (ntohl(dm->type) == 0) ||
212 (ntohl(dm->reserved) != 0) )
213 {
214 GNUNET_break (0);
215 return NULL;
216 }
217 return dm;
218}
219
220
221/**
222 * Handle PUT-message.
223 *
224 * @param cls closure
225 * @param client identification of the client
226 * @param message the actual message
227 */
228static void
229handle_put (void *cls,
230 struct GNUNET_SERVER_Client *client,
231 const struct GNUNET_MessageHeader *message)
232{
233 const struct DataMessage *dm = check_data (message);
234 if (dm == NULL)
235 {
236 GNUNET_break (0);
237 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
238 return;
239 }
240 plugin->api->put (plugin->api->cls,
241 &dm->key,
242 ntohl(dm->size),
243 &dm[1],
244 ntohl(dm->type),
245 ntohl(dm->priority),
246 ntohl(dm->anonymity),
247 GNUNET_TIME_absolute_ntoh(dm->expiration));
248 transmit_size (client);
249 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
250}
251
252
253/**
254 * Handle GET-message.
255 *
256 * @param cls closure
257 * @param client identification of the client
258 * @param message the actual message
259 */
260static void
261handle_get (void *cls,
262 struct GNUNET_SERVER_Client *client,
263 const struct GNUNET_MessageHeader *message)
264{
265 const struct GetMessage *msg;
266 uint16_t size;
267
268 size = ntohs(message->size);
269 if ( (size != sizeof(struct GetMessage)) &&
270 (size != sizeof(struct GetMessage) - sizeof(GNUNET_HashCode)) )
271 {
272 GNUNET_break (0);
273 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
274 return;
275 }
276 msg = (const struct GetMessage*) message;
277 plugin->api->get (plugin->api->cls,
278 ((size == sizeof(struct GetMessage)) ? &msg->key : NULL),
279 NULL,
280 ntohl(msg->type),
281 &transmit_item,
282 client);
283 GNUNET_SERVER_receive_done (client, GNUNET_OK);
284}
285
286
287/**
288 * Handle GET_RANDOM-message.
289 *
290 * @param cls closure
291 * @param client identification of the client
292 * @param message the actual message
293 */
294static void
295handle_get_random (void *cls,
296 struct GNUNET_SERVER_Client *client,
297 const struct GNUNET_MessageHeader *message)
298{
299 plugin->api->iter_migration_order (plugin->api->cls,
300 0,
301 &transmit_item,
302 client);
303 GNUNET_SERVER_receive_done (client, GNUNET_OK);
304}
305
306
307/**
308 * Callback function that will cause the item that is passed
309 * in to be deleted (by returning GNUNET_NO).
310 */
311static int
312remove_callback (void *cls,
313 const GNUNET_HashCode * key,
314 uint32_t size,
315 const void *data,
316 uint32_t type,
317 uint32_t priority,
318 uint32_t anonymity,
319 struct GNUNET_TIME_Absolute
320 expiration, unsigned long long uid)
321{
322 return GNUNET_NO;
323}
324
325
326/**
327 * Handle REMOVE-message.
328 *
329 * @param cls closure
330 * @param client identification of the client
331 * @param message the actual message
332 */
333static void
334handle_remove (void *cls,
335 struct GNUNET_SERVER_Client *client,
336 const struct GNUNET_MessageHeader *message)
337{
338 const struct DataMessage *dm = check_data (message);
339 GNUNET_HashCode vhash;
340
341 if (dm == NULL)
342 {
343 GNUNET_break (0);
344 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
345 return;
346 }
347 GNUNET_CRYPTO_hash (&dm[1],
348 ntohl(dm->size),
349 &vhash);
350 plugin->api->get (plugin->api->cls,
351 &dm->key,
352 &vhash,
353 ntohl(dm->type),
354 &remove_callback,
355 NULL);
356 transmit_size (client);
357 GNUNET_SERVER_receive_done (client, GNUNET_OK);
358}
359
360
361/**
362 * Handle DROP-message.
363 *
364 * @param cls closure
365 * @param client identification of the client
366 * @param message the actual message
367 */
368static void
369handle_drop (void *cls,
370 struct GNUNET_SERVER_Client *client,
371 const struct GNUNET_MessageHeader *message)
372{
373 plugin->api->drop (plugin->api->cls);
374 GNUNET_SERVER_receive_done (client, GNUNET_OK);
375}
376
377
378/**
72 * List of handlers for the messages understood by this 379 * List of handlers for the messages understood by this
73 * service. 380 * service.
74 */ 381 */
75static struct GNUNET_SERVER_MessageHandler handlers[] = { 382static struct GNUNET_SERVER_MessageHandler handlers[] = {
76 /* {&handle_xxx, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_XXX, 0}, */ 383 {&handle_init, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_INIT,
384 sizeof(struct GNUNET_MessageHeader) },
385 {&handle_put, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_PUT, 0 },
386 {&handle_get, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_GET, 0 },
387 {&handle_get_random, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_GET_RANDOM,
388 sizeof(struct GNUNET_MessageHeader) },
389 {&handle_remove, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE, 0 },
390 {&handle_drop, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_DROP,
391 sizeof(struct GNUNET_MessageHeader) },
77 {NULL, NULL, 0, 0} 392 {NULL, NULL, 0, 0}
78}; 393};
79 394
diff --git a/src/datastore/plugin_datastore.h b/src/datastore/plugin_datastore.h
index 0f3284b07..1c038bf19 100644
--- a/src/datastore/plugin_datastore.h
+++ b/src/datastore/plugin_datastore.h
@@ -210,14 +210,16 @@ struct GNUNET_DATASTORE_PluginFunctions
210 GNUNET_DATASTORE_Selector iter_zero_anonymity; 210 GNUNET_DATASTORE_Selector iter_zero_anonymity;
211 211
212 /** 212 /**
213 * Iterate over the items in the datastore in ascending 213 * Iterate over the items in the datastore in ascending order of
214 * order of expiration time. 214 * expiration time.
215 */ 215 */
216 GNUNET_DATASTORE_Selector iter_ascending_expiration; 216 GNUNET_DATASTORE_Selector iter_ascending_expiration;
217 217
218 /** 218 /**
219 * Iterate over the items in the datastore in migration 219 * Iterate over the items in the datastore in migration
220 * order. 220 * order. Call the given function on the next item only
221 * (and then signal 'end' with a second call). This is
222 * a significant difference from all the other iterators!
221 */ 223 */
222 GNUNET_DATASTORE_Selector iter_migration_order; 224 GNUNET_DATASTORE_Selector iter_migration_order;
223 225