aboutsummaryrefslogtreecommitdiff
path: root/src/peerstore/gnunet-service-peerstore.c
diff options
context:
space:
mode:
authorOmar Tarabai <tarabai@devegypt.com>2014-05-31 21:48:01 +0000
committerOmar Tarabai <tarabai@devegypt.com>2014-05-31 21:48:01 +0000
commit805d4a3556dee6d13ad5a9439b7a4a9ef3f9ab46 (patch)
tree63473a907807a2aadb7780353b4ad34ee6a041fa /src/peerstore/gnunet-service-peerstore.c
parent95cdeb5c0bb1f14f3959863e6bf4675db48ea177 (diff)
downloadgnunet-805d4a3556dee6d13ad5a9439b7a4a9ef3f9ab46.tar.gz
gnunet-805d4a3556dee6d13ad5a9439b7a4a9ef3f9ab46.zip
peerstore: watch functionality
Diffstat (limited to 'src/peerstore/gnunet-service-peerstore.c')
-rw-r--r--src/peerstore/gnunet-service-peerstore.c94
1 files changed, 72 insertions, 22 deletions
diff --git a/src/peerstore/gnunet-service-peerstore.c b/src/peerstore/gnunet-service-peerstore.c
index 70d79ea5e..706fcaaae 100644
--- a/src/peerstore/gnunet-service-peerstore.c
+++ b/src/peerstore/gnunet-service-peerstore.c
@@ -73,6 +73,11 @@ static struct GNUNET_PEERSTORE_PluginFunctions *db;
73static struct GNUNET_CONTAINER_MultiHashMap *watchers; 73static struct GNUNET_CONTAINER_MultiHashMap *watchers;
74 74
75/** 75/**
76 * Our notification context.
77 */
78static struct GNUNET_SERVER_NotificationContext *nc;
79
80/**
76 * Task run during shutdown. 81 * Task run during shutdown.
77 * 82 *
78 * @param cls unused 83 * @param cls unused
@@ -88,8 +93,8 @@ shutdown_task (void *cls,
88 GNUNET_free (db_lib_name); 93 GNUNET_free (db_lib_name);
89 db_lib_name = NULL; 94 db_lib_name = NULL;
90 } 95 }
91 if(NULL != watchers) 96 GNUNET_SERVER_notification_context_destroy(nc);
92 GNUNET_CONTAINER_multihashmap_destroy(watchers); 97 GNUNET_CONTAINER_multihashmap_destroy(watchers);
93 GNUNET_SCHEDULER_shutdown(); 98 GNUNET_SCHEDULER_shutdown();
94} 99}
95 100
@@ -154,6 +159,60 @@ int record_iterator(void *cls,
154} 159}
155 160
156/** 161/**
162 * Iterator over all watcher clients
163 * to notify them of a new record
164 *
165 * @param cls closuer, a 'struct GNUNET_PEERSTORE_Record *'
166 * @param key hash of record key
167 * @param value the watcher client, a 'struct GNUNET_SERVER_Client *'
168 * @return #GNUNET_YES to continue iterating
169 */
170int watch_notifier_it(void *cls,
171 const struct GNUNET_HashCode *key,
172 void *value)
173{
174 struct GNUNET_PEERSTORE_Record *record = cls;
175 struct GNUNET_SERVER_Client *client = value;
176 struct StoreRecordMessage *srm;
177
178 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found a watcher to update.\n");
179 if(NULL == value)
180 {
181 GNUNET_CONTAINER_multihashmap_remove(watchers, key, value);
182 return GNUNET_YES;
183 }
184 srm = PEERSTORE_create_record_message(record->sub_system,
185 record->peer,
186 record->key,
187 record->value,
188 record->value_size,
189 record->expiry,
190 GNUNET_MESSAGE_TYPE_PEERSTORE_WATCH_RECORD);
191 GNUNET_SERVER_notification_context_unicast(nc, client,
192 (const struct GNUNET_MessageHeader *)srm, GNUNET_YES);
193 return GNUNET_YES;
194}
195
196/**
197 * Given a new record, notifies watchers
198 *
199 * @cls closure, a 'struct GNUNET_PEERSTORE_Record *'
200 * @tc unused
201 */
202void watch_notifier (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
203{
204 struct GNUNET_PEERSTORE_Record *record = cls;
205 struct GNUNET_HashCode keyhash;
206
207 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Sending update to any watchers.\n");
208 PEERSTORE_hash_key(record->sub_system,
209 record->peer,
210 record->key,
211 &keyhash);
212 GNUNET_CONTAINER_multihashmap_get_multiple(watchers, &keyhash, &watch_notifier_it, record);
213}
214
215/**
157 * Handle a watch cancel request from client 216 * Handle a watch cancel request from client
158 * 217 *
159 * @param cls unused 218 * @param cls unused
@@ -167,13 +226,6 @@ void handle_watch_cancel (void *cls,
167 struct StoreKeyHashMessage *hm; 226 struct StoreKeyHashMessage *hm;
168 227
169 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a watch cancel request from client.\n"); 228 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a watch cancel request from client.\n");
170 if(NULL == watchers)
171 {
172 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
173 "Received a watch cancel request when we don't have any watchers.\n");
174 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
175 return;
176 }
177 hm = (struct StoreKeyHashMessage *) message; 229 hm = (struct StoreKeyHashMessage *) message;
178 GNUNET_CONTAINER_multihashmap_remove(watchers, &hm->keyhash, client); 230 GNUNET_CONTAINER_multihashmap_remove(watchers, &hm->keyhash, client);
179 GNUNET_SERVER_receive_done(client, GNUNET_OK); 231 GNUNET_SERVER_receive_done(client, GNUNET_OK);
@@ -195,8 +247,7 @@ void handle_watch (void *cls,
195 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a watch request from client.\n"); 247 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a watch request from client.\n");
196 hm = (struct StoreKeyHashMessage *) message; 248 hm = (struct StoreKeyHashMessage *) message;
197 GNUNET_SERVER_client_mark_monitor(client); 249 GNUNET_SERVER_client_mark_monitor(client);
198 if(NULL == watchers) 250 GNUNET_SERVER_notification_context_add(nc, client);
199 watchers = GNUNET_CONTAINER_multihashmap_create(10, GNUNET_NO);
200 GNUNET_CONTAINER_multihashmap_put(watchers, &hm->keyhash, 251 GNUNET_CONTAINER_multihashmap_put(watchers, &hm->keyhash,
201 client, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 252 client, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
202 GNUNET_SERVER_receive_done(client, GNUNET_OK); 253 GNUNET_SERVER_receive_done(client, GNUNET_OK);
@@ -246,7 +297,7 @@ void handle_iterate (void *cls,
246 GNUNET_free(tc); 297 GNUNET_free(tc);
247 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR); 298 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
248 } 299 }
249 GNUNET_free(record); 300 GNUNET_free(record); /* FIXME: destroy record */
250} 301}
251 302
252/** 303/**
@@ -261,7 +312,6 @@ void handle_store (void *cls,
261 const struct GNUNET_MessageHeader *message) 312 const struct GNUNET_MessageHeader *message)
262{ 313{
263 struct GNUNET_PEERSTORE_Record *record; 314 struct GNUNET_PEERSTORE_Record *record;
264 uint16_t response_type;
265 struct GNUNET_SERVER_TransmitContext *tc; 315 struct GNUNET_SERVER_TransmitContext *tc;
266 316
267 record = PEERSTORE_parse_record_message(message); 317 record = PEERSTORE_parse_record_message(message);
@@ -275,6 +325,7 @@ void handle_store (void *cls,
275 || NULL == record->peer 325 || NULL == record->peer
276 || NULL == record->key) 326 || NULL == record->key)
277 { 327 {
328 /* FIXME: Destroy record */
278 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Full key not supplied in client store request\n"); 329 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Full key not supplied in client store request\n");
279 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR); 330 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
280 return; 331 return;
@@ -284,7 +335,7 @@ void handle_store (void *cls,
284 record->sub_system, 335 record->sub_system,
285 GNUNET_i2s (record->peer), 336 GNUNET_i2s (record->peer),
286 record->key); 337 record->key);
287 if(GNUNET_OK == db->store_record(db->cls, 338 if(GNUNET_OK != db->store_record(db->cls,
288 record->sub_system, 339 record->sub_system,
289 record->peer, 340 record->peer,
290 record->key, 341 record->key,
@@ -292,18 +343,15 @@ void handle_store (void *cls,
292 record->value_size, 343 record->value_size,
293 *record->expiry)) 344 *record->expiry))
294 { 345 {
295 response_type = GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_OK; 346 /* FIXME: Destroy record */
296 }
297 else
298 {
299 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to store requested value, sqlite database error."); 347 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to store requested value, sqlite database error.");
300 response_type = GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_FAIL; 348 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
349 return;
301 } 350 }
302
303 tc = GNUNET_SERVER_transmit_context_create (client); 351 tc = GNUNET_SERVER_transmit_context_create (client);
304 GNUNET_SERVER_transmit_context_append_data(tc, NULL, 0, response_type); 352 GNUNET_SERVER_transmit_context_append_data(tc, NULL, 0, GNUNET_MESSAGE_TYPE_PEERSTORE_STORE_RESULT_OK);
305 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); 353 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
306 //TODO: notify watchers, if a client is disconnected, remove its watch entry 354 GNUNET_SCHEDULER_add_continuation(&watch_notifier, record, -1);
307} 355}
308 356
309/** 357/**
@@ -343,6 +391,8 @@ run (void *cls,
343 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n", db_lib_name); 391 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n", db_lib_name);
344 else 392 else
345 { 393 {
394 nc = GNUNET_SERVER_notification_context_create (server, 16);
395 watchers = GNUNET_CONTAINER_multihashmap_create(10, GNUNET_NO);
346 GNUNET_SCHEDULER_add_now(&cleanup_expired_records, NULL); 396 GNUNET_SCHEDULER_add_now(&cleanup_expired_records, NULL);
347 GNUNET_SERVER_add_handlers (server, handlers); 397 GNUNET_SERVER_add_handlers (server, handlers);
348 GNUNET_SERVER_disconnect_notify (server, 398 GNUNET_SERVER_disconnect_notify (server,