aboutsummaryrefslogtreecommitdiff
path: root/src/datastore/gnunet-service-datastore.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2014-12-23 20:37:22 +0000
committerChristian Grothoff <christian@grothoff.org>2014-12-23 20:37:22 +0000
commitaae8cc8afe0bb827dc1b6601b2e5e3a14b25c2ca (patch)
tree3fb1c4132525ed37aa217bf6d61a8ae2f0fc3366 /src/datastore/gnunet-service-datastore.c
parenteb5224e351e70128f6f0afc4b9e7c5fe90c72213 (diff)
downloadgnunet-aae8cc8afe0bb827dc1b6601b2e5e3a14b25c2ca.tar.gz
gnunet-aae8cc8afe0bb827dc1b6601b2e5e3a14b25c2ca.zip
fixing datastore-statistics interaction to ensure stats are properly written to disk on exit
Diffstat (limited to 'src/datastore/gnunet-service-datastore.c')
-rw-r--r--src/datastore/gnunet-service-datastore.c349
1 files changed, 194 insertions, 155 deletions
diff --git a/src/datastore/gnunet-service-datastore.c b/src/datastore/gnunet-service-datastore.c
index 98ef6d797..0aa2273b5 100644
--- a/src/datastore/gnunet-service-datastore.c
+++ b/src/datastore/gnunet-service-datastore.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 (C) 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) 3 (C) 2004-2014 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -142,19 +142,19 @@ static struct ReservationList *reservations;
142static struct GNUNET_CONTAINER_BloomFilter *filter; 142static struct GNUNET_CONTAINER_BloomFilter *filter;
143 143
144/** 144/**
145 * How much space are we allowed to use? 145 * Name of our plugin.
146 */ 146 */
147static unsigned long long quota; 147static char *plugin_name;
148 148
149/** 149/**
150 * Should the database be dropped on exit? 150 * Our configuration.
151 */ 151 */
152static int do_drop; 152static const struct GNUNET_CONFIGURATION_Handle *cfg;
153 153
154/** 154/**
155 * Name of our plugin. 155 * Handle for reporting statistics.
156 */ 156 */
157static char *plugin_name; 157static struct GNUNET_STATISTICS_Handle *stats;
158 158
159/** 159/**
160 * How much space are we using for the cache? (space available for 160 * How much space are we using for the cache? (space available for
@@ -176,40 +176,45 @@ static unsigned long long reserved;
176static unsigned long long payload; 176static unsigned long long payload;
177 177
178/** 178/**
179 * Number of updates that were made to the 179 * Identity of the task that is used to delete
180 * payload value since we last synchronized 180 * expired content.
181 * it with the statistics service.
182 */ 181 */
183static unsigned int lastSync; 182static GNUNET_SCHEDULER_TaskIdentifier expired_kill_task;
184 183
185/** 184/**
186 * Did we get an answer from statistics? 185 * Minimum time that content should have to not be discarded instantly
186 * (time stamp of any content that we've been discarding recently to
187 * stay below the quota). FOREVER if we had to expire content with
188 * non-zero priority.
187 */ 189 */
188static int stats_worked; 190static struct GNUNET_TIME_Absolute min_expiration;
189 191
190/** 192/**
191 * Identity of the task that is used to delete 193 * How much space are we allowed to use?
192 * expired content.
193 */ 194 */
194static GNUNET_SCHEDULER_TaskIdentifier expired_kill_task; 195static unsigned long long quota;
195 196
196/** 197/**
197 * Our configuration. 198 * Should the database be dropped on exit?
198 */ 199 */
199const struct GNUNET_CONFIGURATION_Handle *cfg; 200static int do_drop;
200 201
201/** 202/**
202 * Minimum time that content should have to not be discarded instantly 203 * Should we refresh the BF when the DB is loaded?
203 * (time stamp of any content that we've been discarding recently to
204 * stay below the quota). FOREVER if we had to expire content with
205 * non-zero priority.
206 */ 204 */
207static struct GNUNET_TIME_Absolute min_expiration; 205static int refresh_bf;
208 206
209/** 207/**
210 * Handle for reporting statistics. 208 * Number of updates that were made to the
209 * payload value since we last synchronized
210 * it with the statistics service.
211 */ 211 */
212static struct GNUNET_STATISTICS_Handle *stats; 212static unsigned int last_sync;
213
214/**
215 * Did we get an answer from statistics?
216 */
217static int stats_worked;
213 218
214 219
215/** 220/**
@@ -221,11 +226,10 @@ sync_stats ()
221{ 226{
222 GNUNET_STATISTICS_set (stats, quota_stat_name, payload, GNUNET_YES); 227 GNUNET_STATISTICS_set (stats, quota_stat_name, payload, GNUNET_YES);
223 GNUNET_STATISTICS_set (stats, "# utilization by current datastore", payload, GNUNET_NO); 228 GNUNET_STATISTICS_set (stats, "# utilization by current datastore", payload, GNUNET_NO);
224 lastSync = 0; 229 last_sync = 0;
225} 230}
226 231
227 232
228
229/** 233/**
230 * Context for transmitting replies to clients. 234 * Context for transmitting replies to clients.
231 */ 235 */
@@ -292,7 +296,8 @@ static struct GNUNET_STATISTICS_GetHandle *stat_get;
292 * @param tc task context 296 * @param tc task context
293 */ 297 */
294static void 298static void
295delete_expired (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); 299delete_expired (void *cls,
300 const struct GNUNET_SCHEDULER_TaskContext *tc);
296 301
297 302
298/** 303/**
@@ -311,15 +316,20 @@ delete_expired (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
311 * @param uid unique identifier for the datum; 316 * @param uid unique identifier for the datum;
312 * maybe 0 if no unique identifier is available 317 * maybe 0 if no unique identifier is available
313 * 318 *
314 * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue 319 * @return #GNUNET_SYSERR to abort the iteration, #GNUNET_OK to continue
315 * (continue on call to "next", of course), 320 * (continue on call to "next", of course),
316 * GNUNET_NO to delete the item and continue (if supported) 321 * #GNUNET_NO to delete the item and continue (if supported)
317 */ 322 */
318static int 323static int
319expired_processor (void *cls, const struct GNUNET_HashCode * key, uint32_t size, 324expired_processor (void *cls,
320 const void *data, enum GNUNET_BLOCK_Type type, 325 const struct GNUNET_HashCode *key,
321 uint32_t priority, uint32_t anonymity, 326 uint32_t size,
322 struct GNUNET_TIME_Absolute expiration, uint64_t uid) 327 const void *data,
328 enum GNUNET_BLOCK_Type type,
329 uint32_t priority,
330 uint32_t anonymity,
331 struct GNUNET_TIME_Absolute expiration,
332 uint64_t uid)
323{ 333{
324 struct GNUNET_TIME_Absolute now; 334 struct GNUNET_TIME_Absolute now;
325 335
@@ -564,7 +574,6 @@ transmit_status (struct GNUNET_SERVER_Client *client, int code, const char *msg)
564} 574}
565 575
566 576
567
568/** 577/**
569 * Function that will transmit the given datastore entry 578 * Function that will transmit the given datastore entry
570 * to the client. 579 * to the client.
@@ -719,7 +728,8 @@ handle_reserve (void *cls, struct GNUNET_SERVER_Client *client,
719 * @param message the actual message 728 * @param message the actual message
720 */ 729 */
721static void 730static void
722handle_release_reserve (void *cls, struct GNUNET_SERVER_Client *client, 731handle_release_reserve (void *cls,
732 struct GNUNET_SERVER_Client *client,
723 const struct GNUNET_MessageHeader *message) 733 const struct GNUNET_MessageHeader *message)
724{ 734{
725 const struct ReleaseReserveMessage *msg = 735 const struct ReleaseReserveMessage *msg =
@@ -730,7 +740,8 @@ handle_release_reserve (void *cls, struct GNUNET_SERVER_Client *client,
730 int rid = ntohl (msg->rid); 740 int rid = ntohl (msg->rid);
731 unsigned long long rem; 741 unsigned long long rem;
732 742
733 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' request\n", 743 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
744 "Processing `%s' request\n",
734 "RELEASE_RESERVE"); 745 "RELEASE_RESERVE");
735 next = reservations; 746 next = reservations;
736 prev = NULL; 747 prev = NULL;
@@ -748,7 +759,8 @@ handle_release_reserve (void *cls, struct GNUNET_SERVER_Client *client,
748 ((unsigned long long) GNUNET_DATASTORE_ENTRY_OVERHEAD) * pos->entries; 759 ((unsigned long long) GNUNET_DATASTORE_ENTRY_OVERHEAD) * pos->entries;
749 GNUNET_assert (reserved >= rem); 760 GNUNET_assert (reserved >= rem);
750 reserved -= rem; 761 reserved -= rem;
751 GNUNET_STATISTICS_set (stats, gettext_noop ("# reserved"), reserved, 762 GNUNET_STATISTICS_set (stats,
763 gettext_noop ("# reserved"), reserved,
752 GNUNET_NO); 764 GNUNET_NO);
753 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 765 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
754 "Returning %llu remaining reserved bytes to storage pool\n", 766 "Returning %llu remaining reserved bytes to storage pool\n",
@@ -835,7 +847,8 @@ execute_put (struct GNUNET_SERVER_Client *client, const struct DataMessage *dm)
835 GNUNET_TIME_absolute_ntoh (dm->expiration), &msg); 847 GNUNET_TIME_absolute_ntoh (dm->expiration), &msg);
836 if (GNUNET_OK == ret) 848 if (GNUNET_OK == ret)
837 { 849 {
838 GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes stored"), size, 850 GNUNET_STATISTICS_update (stats,
851 gettext_noop ("# bytes stored"), size,
839 GNUNET_YES); 852 GNUNET_YES);
840 GNUNET_CONTAINER_bloomfilter_add (filter, &dm->key); 853 GNUNET_CONTAINER_bloomfilter_add (filter, &dm->key);
841 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 854 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -961,7 +974,8 @@ handle_put (void *cls, struct GNUNET_SERVER_Client *client,
961 pos->entries--; 974 pos->entries--;
962 pos->amount -= size; 975 pos->amount -= size;
963 reserved -= (size + GNUNET_DATASTORE_ENTRY_OVERHEAD); 976 reserved -= (size + GNUNET_DATASTORE_ENTRY_OVERHEAD);
964 GNUNET_STATISTICS_set (stats, gettext_noop ("# reserved"), reserved, 977 GNUNET_STATISTICS_set (stats,
978 gettext_noop ("# reserved"), reserved,
965 GNUNET_NO); 979 GNUNET_NO);
966 } 980 }
967 } 981 }
@@ -1007,7 +1021,8 @@ handle_get (void *cls, struct GNUNET_SERVER_Client *client,
1007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1021 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1008 "Processing `%s' request for `%s' of type %u\n", "GET", 1022 "Processing `%s' request for `%s' of type %u\n", "GET",
1009 GNUNET_h2s (&msg->key), ntohl (msg->type)); 1023 GNUNET_h2s (&msg->key), ntohl (msg->type));
1010 GNUNET_STATISTICS_update (stats, gettext_noop ("# GET requests received"), 1, 1024 GNUNET_STATISTICS_update (stats,
1025 gettext_noop ("# GET requests received"), 1,
1011 GNUNET_NO); 1026 GNUNET_NO);
1012 GNUNET_SERVER_client_keep (client); 1027 GNUNET_SERVER_client_keep (client);
1013 if ((size == sizeof (struct GetMessage)) && 1028 if ((size == sizeof (struct GetMessage)) &&
@@ -1196,7 +1211,9 @@ static void
1196handle_drop (void *cls, struct GNUNET_SERVER_Client *client, 1211handle_drop (void *cls, struct GNUNET_SERVER_Client *client,
1197 const struct GNUNET_MessageHeader *message) 1212 const struct GNUNET_MessageHeader *message)
1198{ 1213{
1199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' request\n", "DROP"); 1214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1215 "Processing `%s' request\n",
1216 "DROP");
1200 do_drop = GNUNET_YES; 1217 do_drop = GNUNET_YES;
1201 GNUNET_SERVER_receive_done (client, GNUNET_OK); 1218 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1202} 1219}
@@ -1211,21 +1228,25 @@ handle_drop (void *cls, struct GNUNET_SERVER_Client *client,
1211 * 0 for "reset to empty" 1228 * 0 for "reset to empty"
1212 */ 1229 */
1213static void 1230static void
1214disk_utilization_change_cb (void *cls, int delta) 1231disk_utilization_change_cb (void *cls,
1232 int delta)
1215{ 1233{
1216 if ((delta < 0) && (payload < -delta)) 1234 if ((delta < 0) && (payload < -delta))
1217 { 1235 {
1218 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1236 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1219 _ 1237 _("Datastore payload must have been inaccurate (%lld < %lld). Recomputing it.\n"),
1220 ("Datastore payload inaccurate (%lld < %lld). Trying to fix.\n"), 1238 (long long) payload,
1221 (long long) payload, (long long) -delta); 1239 (long long) -delta);
1222 payload = plugin->api->estimate_size (plugin->api->cls); 1240 payload = plugin->api->estimate_size (plugin->api->cls);
1223 sync_stats (); 1241 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1242 _("New payload: %lld\n"),
1243 (long long) payload);
1244 sync_stats ();
1224 return; 1245 return;
1225 } 1246 }
1226 payload += delta; 1247 payload += delta;
1227 lastSync++; 1248 last_sync++;
1228 if (lastSync >= MAX_STAT_SYNC_LAG) 1249 if (last_sync >= MAX_STAT_SYNC_LAG)
1229 sync_stats (); 1250 sync_stats ();
1230} 1251}
1231 1252
@@ -1237,14 +1258,17 @@ disk_utilization_change_cb (void *cls, int delta)
1237 * @param subsystem name of subsystem that created the statistic 1258 * @param subsystem name of subsystem that created the statistic
1238 * @param name the name of the datum 1259 * @param name the name of the datum
1239 * @param value the current value 1260 * @param value the current value
1240 * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not 1261 * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
1241 * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration 1262 * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
1242 */ 1263 */
1243static int 1264static int
1244process_stat_in (void *cls, const char *subsystem, const char *name, 1265process_stat_in (void *cls,
1245 uint64_t value, int is_persistent) 1266 const char *subsystem,
1267 const char *name,
1268 uint64_t value,
1269 int is_persistent)
1246{ 1270{
1247 GNUNET_assert (stats_worked == GNUNET_NO); 1271 GNUNET_assert (GNUNET_NO == stats_worked);
1248 stats_worked = GNUNET_YES; 1272 stats_worked = GNUNET_YES;
1249 payload += value; 1273 payload += value;
1250 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1254,17 +1278,6 @@ process_stat_in (void *cls, const char *subsystem, const char *name,
1254} 1278}
1255 1279
1256 1280
1257static void
1258process_stat_done (void *cls, int success)
1259{
1260 struct DatastorePlugin *plugin = cls;
1261
1262 stat_get = NULL;
1263 if (stats_worked == GNUNET_NO)
1264 payload = plugin->api->estimate_size (plugin->api->cls);
1265}
1266
1267
1268/** 1281/**
1269 * Load the datastore plugin. 1282 * Load the datastore plugin.
1270 */ 1283 */
@@ -1278,16 +1291,20 @@ load_plugin ()
1278 ret->env.cfg = cfg; 1291 ret->env.cfg = cfg;
1279 ret->env.duc = &disk_utilization_change_cb; 1292 ret->env.duc = &disk_utilization_change_cb;
1280 ret->env.cls = NULL; 1293 ret->env.cls = NULL;
1281 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' datastore plugin\n"), 1294 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1295 _("Loading `%s' datastore plugin\n"),
1282 plugin_name); 1296 plugin_name);
1283 GNUNET_asprintf (&libname, "libgnunet_plugin_datastore_%s", plugin_name); 1297 GNUNET_asprintf (&libname,
1298 "libgnunet_plugin_datastore_%s",
1299 plugin_name);
1284 ret->short_name = GNUNET_strdup (plugin_name); 1300 ret->short_name = GNUNET_strdup (plugin_name);
1285 ret->lib_name = libname; 1301 ret->lib_name = libname;
1286 ret->api = GNUNET_PLUGIN_load (libname, &ret->env); 1302 ret->api = GNUNET_PLUGIN_load (libname, &ret->env);
1287 if (ret->api == NULL) 1303 if (NULL == ret->api)
1288 { 1304 {
1289 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1305 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1290 _("Failed to load datastore plugin for `%s'\n"), plugin_name); 1306 _("Failed to load datastore plugin for `%s'\n"),
1307 plugin_name);
1291 GNUNET_free (ret->short_name); 1308 GNUNET_free (ret->short_name);
1292 GNUNET_free (libname); 1309 GNUNET_free (libname);
1293 GNUNET_free (ret); 1310 GNUNET_free (ret);
@@ -1312,50 +1329,85 @@ unload_plugin (struct DatastorePlugin *plug)
1312 GNUNET_free (plug->lib_name); 1329 GNUNET_free (plug->lib_name);
1313 GNUNET_free (plug->short_name); 1330 GNUNET_free (plug->short_name);
1314 GNUNET_free (plug); 1331 GNUNET_free (plug);
1315 GNUNET_free (quota_stat_name);
1316 quota_stat_name = NULL;
1317} 1332}
1318 1333
1319 1334
1320/** 1335/**
1321 * Final task run after shutdown. Unloads plugins and disconnects us from 1336 * Adds a given @a key to the bloomfilter in @a cls @a count times.
1322 * statistics. 1337 *
1338 * @param cls the bloomfilter
1339 * @param key key to add
1340 * @param count number of times to add key
1323 */ 1341 */
1324static void 1342static void
1325unload_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 1343add_key_to_bloomfilter (void *cls,
1344 const struct GNUNET_HashCode *key,
1345 unsigned int count)
1326{ 1346{
1327 if (lastSync > 0) 1347 struct GNUNET_CONTAINER_BloomFilter *bf = cls;
1328 sync_stats (); 1348
1329 if (GNUNET_YES == do_drop) 1349 while (0 < count--)
1330 plugin->api->drop (plugin->api->cls); 1350 GNUNET_CONTAINER_bloomfilter_add (bf, key);
1331 unload_plugin (plugin); 1351}
1332 plugin = NULL; 1352
1333 if (filter != NULL) 1353
1354/**
1355 * We finished receiving the statistic. Initialize the plugin; if
1356 * loading the statistic failed, run the estimator.
1357 *
1358 * @param cls NULL
1359 * @param success #GNUNET_NO if we failed to read the stat
1360 */
1361static void
1362process_stat_done (void *cls, int success)
1363{
1364 stat_get = NULL;
1365 plugin = load_plugin ();
1366 if (NULL == plugin)
1334 { 1367 {
1335 GNUNET_CONTAINER_bloomfilter_free (filter); 1368 GNUNET_CONTAINER_bloomfilter_free (filter);
1336 filter = NULL; 1369 filter = NULL;
1370 if (NULL != stats)
1371 {
1372 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
1373 stats = NULL;
1374 }
1375 return;
1337 } 1376 }
1338 if (stat_get != NULL) 1377 if (GNUNET_NO == stats_worked)
1339 { 1378 {
1340 GNUNET_STATISTICS_get_cancel (stat_get); 1379 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1341 stat_get = NULL; 1380 "Failed to obtain value from statistics service, recomputing it\n");
1381 payload = plugin->api->estimate_size (plugin->api->cls);
1342 } 1382 }
1343 if (stats != NULL) 1383 if (GNUNET_YES == refresh_bf)
1344 { 1384 {
1345 GNUNET_STATISTICS_destroy (stats, GNUNET_YES); 1385 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1346 stats = NULL; 1386 _("Rebuilding bloomfilter. Please be patient.\n"));
1387 if (NULL != plugin->api->get_keys)
1388 plugin->api->get_keys (plugin->api->cls,
1389 &add_key_to_bloomfilter,
1390 filter);
1391 else
1392 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1393 _("Plugin does not support get_keys function. Please fix!\n"));
1394
1395 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1396 _("Bloomfilter construction complete.\n"));
1347 } 1397 }
1348 GNUNET_free_non_null (plugin_name); 1398 expired_kill_task
1349 plugin_name = NULL; 1399 = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
1400 &delete_expired,
1401 NULL);
1350} 1402}
1351 1403
1352 1404
1353/** 1405/**
1354 * Last task run during shutdown. Disconnects us from 1406 * Task run during shutdown.
1355 * the transport and core.
1356 */ 1407 */
1357static void 1408static void
1358cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 1409cleaning_task (void *cls,
1410 const struct GNUNET_SCHEDULER_TaskContext *tc)
1359{ 1411{
1360 struct TransmitCallbackContext *tcc; 1412 struct TransmitCallbackContext *tcc;
1361 1413
@@ -1376,8 +1428,31 @@ cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1376 GNUNET_SCHEDULER_cancel (expired_kill_task); 1428 GNUNET_SCHEDULER_cancel (expired_kill_task);
1377 expired_kill_task = GNUNET_SCHEDULER_NO_TASK; 1429 expired_kill_task = GNUNET_SCHEDULER_NO_TASK;
1378 } 1430 }
1379 GNUNET_SCHEDULER_add_continuation (&unload_task, NULL, 1431 if (GNUNET_YES == do_drop)
1380 GNUNET_SCHEDULER_REASON_PREREQ_DONE); 1432 plugin->api->drop (plugin->api->cls);
1433 unload_plugin (plugin);
1434 plugin = NULL;
1435 if (NULL != filter)
1436 {
1437 GNUNET_CONTAINER_bloomfilter_free (filter);
1438 filter = NULL;
1439 }
1440 if (NULL != stat_get)
1441 {
1442 GNUNET_STATISTICS_get_cancel (stat_get);
1443 stat_get = NULL;
1444 }
1445 GNUNET_free_non_null (plugin_name);
1446 plugin_name = NULL;
1447 if (last_sync > 0)
1448 sync_stats ();
1449 if (NULL != stats)
1450 {
1451 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
1452 stats = NULL;
1453 }
1454 GNUNET_free (quota_stat_name);
1455 quota_stat_name = NULL;
1381} 1456}
1382 1457
1383 1458
@@ -1390,13 +1465,14 @@ cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1390 * @param client identification of the client 1465 * @param client identification of the client
1391 */ 1466 */
1392static void 1467static void
1393cleanup_reservations (void *cls, struct GNUNET_SERVER_Client *client) 1468cleanup_reservations (void *cls,
1469 struct GNUNET_SERVER_Client *client)
1394{ 1470{
1395 struct ReservationList *pos; 1471 struct ReservationList *pos;
1396 struct ReservationList *prev; 1472 struct ReservationList *prev;
1397 struct ReservationList *next; 1473 struct ReservationList *next;
1398 1474
1399 if (client == NULL) 1475 if (NULL == client)
1400 return; 1476 return;
1401 prev = NULL; 1477 prev = NULL;
1402 pos = reservations; 1478 pos = reservations;
@@ -1424,24 +1500,6 @@ cleanup_reservations (void *cls, struct GNUNET_SERVER_Client *client)
1424 1500
1425 1501
1426/** 1502/**
1427 * Adds a given key to the bloomfilter 'count' times.
1428 *
1429 * @param cls the bloomfilter
1430 * @param key key to add
1431 * @param count number of times to add key
1432 */
1433static void
1434add_key_to_bloomfilter (void *cls,
1435 const struct GNUNET_HashCode *key,
1436 unsigned int count)
1437{
1438 struct GNUNET_CONTAINER_BloomFilter *bf = cls;
1439 while (0 < count--)
1440 GNUNET_CONTAINER_bloomfilter_add (bf, key);
1441}
1442
1443
1444/**
1445 * Process datastore requests. 1503 * Process datastore requests.
1446 * 1504 *
1447 * @param cls closure 1505 * @param cls closure
@@ -1449,7 +1507,8 @@ add_key_to_bloomfilter (void *cls,
1449 * @param c configuration to use 1507 * @param c configuration to use
1450 */ 1508 */
1451static void 1509static void
1452run (void *cls, struct GNUNET_SERVER_Handle *server, 1510run (void *cls,
1511 struct GNUNET_SERVER_Handle *server,
1453 const struct GNUNET_CONFIGURATION_Handle *c) 1512 const struct GNUNET_CONFIGURATION_Handle *c)
1454{ 1513{
1455 static const struct GNUNET_SERVER_MessageHandler handlers[] = { 1514 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
@@ -1476,7 +1535,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1476 char *fn; 1535 char *fn;
1477 char *pfn; 1536 char *pfn;
1478 unsigned int bf_size; 1537 unsigned int bf_size;
1479 int refresh_bf;
1480 1538
1481 cfg = c; 1539 cfg = c;
1482 if (GNUNET_OK != 1540 if (GNUNET_OK !=
@@ -1516,11 +1574,11 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1516 { 1574 {
1517 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1575 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1518 _("Could not use specified filename `%s' for bloomfilter.\n"), 1576 _("Could not use specified filename `%s' for bloomfilter.\n"),
1519 fn != NULL ? fn : ""); 1577 NULL != fn ? fn : "");
1520 GNUNET_free_non_null (fn); 1578 GNUNET_free_non_null (fn);
1521 fn = NULL; 1579 fn = NULL;
1522 } 1580 }
1523 if (fn != NULL) 1581 if (NULL != fn)
1524 { 1582 {
1525 GNUNET_asprintf (&pfn, "%s.%s", fn, plugin_name); 1583 GNUNET_asprintf (&pfn, "%s.%s", fn, plugin_name);
1526 if (GNUNET_YES == GNUNET_DISK_file_test (pfn)) 1584 if (GNUNET_YES == GNUNET_DISK_file_test (pfn))
@@ -1576,23 +1634,11 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1576 refresh_bf = GNUNET_YES; 1634 refresh_bf = GNUNET_YES;
1577 } 1635 }
1578 GNUNET_free_non_null (fn); 1636 GNUNET_free_non_null (fn);
1579 if (filter == NULL) 1637 if (NULL == filter)
1580 { 1638 {
1581 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1639 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1582 _("Failed to initialize bloomfilter.\n")); 1640 _("Failed to initialize bloomfilter.\n"));
1583 if (stats != NULL) 1641 if (NULL != stats)
1584 {
1585 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
1586 stats = NULL;
1587 }
1588 return;
1589 }
1590 plugin = load_plugin ();
1591 if (NULL == plugin)
1592 {
1593 GNUNET_CONTAINER_bloomfilter_free (filter);
1594 filter = NULL;
1595 if (stats != NULL)
1596 { 1642 {
1597 GNUNET_STATISTICS_destroy (stats, GNUNET_YES); 1643 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
1598 stats = NULL; 1644 stats = NULL;
@@ -1600,28 +1646,19 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1600 return; 1646 return;
1601 } 1647 }
1602 stat_get = 1648 stat_get =
1603 GNUNET_STATISTICS_get (stats, "datastore", quota_stat_name, 1649 GNUNET_STATISTICS_get (stats,
1604 GNUNET_TIME_UNIT_SECONDS, &process_stat_done, 1650 "datastore",
1605 &process_stat_in, plugin); 1651 quota_stat_name,
1606 GNUNET_SERVER_disconnect_notify (server, &cleanup_reservations, NULL); 1652 GNUNET_TIME_UNIT_SECONDS,
1653 &process_stat_done,
1654 &process_stat_in,
1655 NULL);
1656 GNUNET_SERVER_disconnect_notify (server,
1657 &cleanup_reservations,
1658 NULL);
1607 GNUNET_SERVER_add_handlers (server, handlers); 1659 GNUNET_SERVER_add_handlers (server, handlers);
1608 if (GNUNET_YES == refresh_bf) 1660 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1609 { 1661 &cleaning_task,
1610 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1611 _("Rebuilding bloomfilter. Please be patient.\n"));
1612 if (NULL != plugin->api->get_keys)
1613 plugin->api->get_keys (plugin->api->cls, &add_key_to_bloomfilter, filter);
1614 else
1615 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1616 _("Plugin does not support get_keys function. Please fix!\n"));
1617
1618 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1619 _("Bloomfilter construction complete.\n"));
1620 }
1621 expired_kill_task =
1622 GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
1623 &delete_expired, NULL);
1624 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleaning_task,
1625 NULL); 1662 NULL);
1626} 1663}
1627 1664
@@ -1634,13 +1671,15 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1634 * @return 0 ok, 1 on error 1671 * @return 0 ok, 1 on error
1635 */ 1672 */
1636int 1673int
1637main (int argc, char *const *argv) 1674main (int argc,
1675 char *const *argv)
1638{ 1676{
1639 int ret; 1677 int ret;
1640 1678
1641 ret = 1679 ret =
1642 (GNUNET_OK == 1680 (GNUNET_OK ==
1643 GNUNET_SERVICE_run (argc, argv, "datastore", GNUNET_SERVICE_OPTION_NONE, 1681 GNUNET_SERVICE_run (argc, argv, "datastore",
1682 GNUNET_SERVICE_OPTION_NONE,
1644 &run, NULL)) ? 0 : 1; 1683 &run, NULL)) ? 0 : 1;
1645 return ret; 1684 return ret;
1646} 1685}