diff options
Diffstat (limited to 'src/datastore/gnunet-service-datastore.c')
-rw-r--r-- | src/datastore/gnunet-service-datastore.c | 143 |
1 files changed, 140 insertions, 3 deletions
diff --git a/src/datastore/gnunet-service-datastore.c b/src/datastore/gnunet-service-datastore.c index 40ea153de..01778b1b7 100644 --- a/src/datastore/gnunet-service-datastore.c +++ b/src/datastore/gnunet-service-datastore.c | |||
@@ -42,6 +42,13 @@ | |||
42 | */ | 42 | */ |
43 | #define MAX_EXPIRE_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) | 43 | #define MAX_EXPIRE_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) |
44 | 44 | ||
45 | #define QUOTA_STAT_NAME gettext_noop ("# bytes used in file-sharing datastore") | ||
46 | |||
47 | /** | ||
48 | * After how many payload-changing operations | ||
49 | * do we sync our statistics? | ||
50 | */ | ||
51 | #define MAX_STAT_SYNC_LAG 50 | ||
45 | 52 | ||
46 | 53 | ||
47 | /** | 54 | /** |
@@ -109,6 +116,7 @@ struct ReservationList | |||
109 | }; | 116 | }; |
110 | 117 | ||
111 | 118 | ||
119 | |||
112 | /** | 120 | /** |
113 | * Our datastore plugin (NULL if not available). | 121 | * Our datastore plugin (NULL if not available). |
114 | */ | 122 | */ |
@@ -141,6 +149,24 @@ static unsigned long long cache_size; | |||
141 | * How much space have we currently reserved? | 149 | * How much space have we currently reserved? |
142 | */ | 150 | */ |
143 | static unsigned long long reserved; | 151 | static unsigned long long reserved; |
152 | |||
153 | /** | ||
154 | * How much data are we currently storing | ||
155 | * in the database? | ||
156 | */ | ||
157 | static unsigned long long payload; | ||
158 | |||
159 | /** | ||
160 | * Number of updates that were made to the | ||
161 | * payload value since we last synchronized | ||
162 | * it with the statistics service. | ||
163 | */ | ||
164 | static unsigned int lastSync; | ||
165 | |||
166 | /** | ||
167 | * Did we get an answer from statistics? | ||
168 | */ | ||
169 | static int stats_worked; | ||
144 | 170 | ||
145 | /** | 171 | /** |
146 | * Identity of the task that is used to delete | 172 | * Identity of the task that is used to delete |
@@ -165,6 +191,23 @@ static struct GNUNET_STATISTICS_Handle *stats; | |||
165 | 191 | ||
166 | 192 | ||
167 | /** | 193 | /** |
194 | * Synchronize our utilization statistics with the | ||
195 | * statistics service. | ||
196 | */ | ||
197 | static void | ||
198 | sync_stats () | ||
199 | { | ||
200 | GNUNET_STATISTICS_set (stats, | ||
201 | QUOTA_STAT_NAME, | ||
202 | payload, | ||
203 | GNUNET_YES); | ||
204 | lastSync = 0; | ||
205 | } | ||
206 | |||
207 | |||
208 | |||
209 | |||
210 | /** | ||
168 | * Function called once the transmit operation has | 211 | * Function called once the transmit operation has |
169 | * either failed or succeeded. | 212 | * either failed or succeeded. |
170 | * | 213 | * |
@@ -242,6 +285,12 @@ static struct TransmitCallbackContext *tcc_tail; | |||
242 | static int cleaning_done; | 285 | static int cleaning_done; |
243 | 286 | ||
244 | /** | 287 | /** |
288 | * Handle for pending get request. | ||
289 | */ | ||
290 | static struct GNUNET_STATISTICS_GetHandle *stat_get; | ||
291 | |||
292 | |||
293 | /** | ||
245 | * Task that is used to remove expired entries from | 294 | * Task that is used to remove expired entries from |
246 | * the datastore. This task will schedule itself | 295 | * the datastore. This task will schedule itself |
247 | * again automatically to always delete all expired | 296 | * again automatically to always delete all expired |
@@ -731,7 +780,7 @@ handle_reserve (void *cls, | |||
731 | #endif | 780 | #endif |
732 | amount = GNUNET_ntohll(msg->amount); | 781 | amount = GNUNET_ntohll(msg->amount); |
733 | entries = ntohl(msg->entries); | 782 | entries = ntohl(msg->entries); |
734 | used = plugin->api->get_size (plugin->api->cls) + reserved; | 783 | used = payload + reserved; |
735 | req = amount + ((unsigned long long) GNUNET_DATASTORE_ENTRY_OVERHEAD) * entries; | 784 | req = amount + ((unsigned long long) GNUNET_DATASTORE_ENTRY_OVERHEAD) * entries; |
736 | if (used + req > quota) | 785 | if (used + req > quota) |
737 | { | 786 | { |
@@ -931,13 +980,13 @@ execute_put (struct GNUNET_SERVER_Client *client, | |||
931 | (GNUNET_SYSERR == ret) ? GNUNET_SYSERR : GNUNET_OK, | 980 | (GNUNET_SYSERR == ret) ? GNUNET_SYSERR : GNUNET_OK, |
932 | msg); | 981 | msg); |
933 | GNUNET_free_non_null (msg); | 982 | GNUNET_free_non_null (msg); |
934 | if (quota - reserved - cache_size < plugin->api->get_size (plugin->api->cls)) | 983 | if (quota - reserved - cache_size < payload) |
935 | { | 984 | { |
936 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 985 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
937 | _("Need %llu bytes more space (%llu allowed, using %llu)\n"), | 986 | _("Need %llu bytes more space (%llu allowed, using %llu)\n"), |
938 | (unsigned long long) size + GNUNET_DATASTORE_ENTRY_OVERHEAD, | 987 | (unsigned long long) size + GNUNET_DATASTORE_ENTRY_OVERHEAD, |
939 | (unsigned long long) (quota - reserved - cache_size), | 988 | (unsigned long long) (quota - reserved - cache_size), |
940 | (unsigned long long) plugin->api->get_size (plugin->api->cls)); | 989 | (unsigned long long) payload); |
941 | manage_space (size + GNUNET_DATASTORE_ENTRY_OVERHEAD); | 990 | manage_space (size + GNUNET_DATASTORE_ENTRY_OVERHEAD); |
942 | } | 991 | } |
943 | } | 992 | } |
@@ -1351,6 +1400,78 @@ handle_drop (void *cls, | |||
1351 | 1400 | ||
1352 | 1401 | ||
1353 | /** | 1402 | /** |
1403 | * Function called by plugins to notify us about a | ||
1404 | * change in their disk utilization. | ||
1405 | * | ||
1406 | * @param cls closure (NULL) | ||
1407 | * @param delta change in disk utilization, | ||
1408 | * 0 for "reset to empty" | ||
1409 | */ | ||
1410 | static void | ||
1411 | disk_utilization_change_cb (void *cls, | ||
1412 | int delta) | ||
1413 | { | ||
1414 | if ( (delta < 0) && | ||
1415 | (payload < -delta) ) | ||
1416 | { | ||
1417 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1418 | _("Datastore payload inaccurate (%lld < %lld). Trying to fix.\n"), | ||
1419 | (long long) payload, | ||
1420 | (long long) -delta); | ||
1421 | payload = plugin->api->get_size (plugin->api->cls); | ||
1422 | sync_stats (); | ||
1423 | return; | ||
1424 | } | ||
1425 | payload += delta; | ||
1426 | lastSync++; | ||
1427 | if (lastSync >= MAX_STAT_SYNC_LAG) | ||
1428 | sync_stats (); | ||
1429 | } | ||
1430 | |||
1431 | |||
1432 | /** | ||
1433 | * Callback function to process statistic values. | ||
1434 | * | ||
1435 | * @param cls closure (struct Plugin*) | ||
1436 | * @param subsystem name of subsystem that created the statistic | ||
1437 | * @param name the name of the datum | ||
1438 | * @param value the current value | ||
1439 | * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not | ||
1440 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | ||
1441 | */ | ||
1442 | static int | ||
1443 | process_stat_in (void *cls, | ||
1444 | const char *subsystem, | ||
1445 | const char *name, | ||
1446 | uint64_t value, | ||
1447 | int is_persistent) | ||
1448 | { | ||
1449 | GNUNET_assert (stats_worked == GNUNET_NO); | ||
1450 | stats_worked = GNUNET_YES; | ||
1451 | payload += value; | ||
1452 | #if DEBUG_SQLITE | ||
1453 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1454 | "Notification from statistics about existing payload (%llu), new payload is %llu\n", | ||
1455 | value, | ||
1456 | payload); | ||
1457 | #endif | ||
1458 | return GNUNET_OK; | ||
1459 | } | ||
1460 | |||
1461 | |||
1462 | static void | ||
1463 | process_stat_done (void *cls, | ||
1464 | int success) | ||
1465 | { | ||
1466 | struct DatastorePlugin *plugin = cls; | ||
1467 | |||
1468 | stat_get = NULL; | ||
1469 | if (stats_worked == GNUNET_NO) | ||
1470 | payload = plugin->api->get_size (plugin->api->cls); | ||
1471 | } | ||
1472 | |||
1473 | |||
1474 | /** | ||
1354 | * Load the datastore plugin. | 1475 | * Load the datastore plugin. |
1355 | */ | 1476 | */ |
1356 | static struct DatastorePlugin * | 1477 | static struct DatastorePlugin * |
@@ -1373,6 +1494,8 @@ load_plugin () | |||
1373 | ret = GNUNET_malloc (sizeof(struct DatastorePlugin)); | 1494 | ret = GNUNET_malloc (sizeof(struct DatastorePlugin)); |
1374 | ret->env.cfg = cfg; | 1495 | ret->env.cfg = cfg; |
1375 | ret->env.sched = sched; | 1496 | ret->env.sched = sched; |
1497 | ret->env.duc = &disk_utilization_change_cb; | ||
1498 | ret->env.cls = NULL; | ||
1376 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1499 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
1377 | _("Loading `%s' datastore plugin\n"), name); | 1500 | _("Loading `%s' datastore plugin\n"), name); |
1378 | GNUNET_asprintf (&libname, "libgnunet_plugin_datastore_%s", name); | 1501 | GNUNET_asprintf (&libname, "libgnunet_plugin_datastore_%s", name); |
@@ -1426,6 +1549,13 @@ unload_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1426 | GNUNET_CONTAINER_bloomfilter_free (filter); | 1549 | GNUNET_CONTAINER_bloomfilter_free (filter); |
1427 | filter = NULL; | 1550 | filter = NULL; |
1428 | } | 1551 | } |
1552 | if (lastSync > 0) | ||
1553 | sync_stats (); | ||
1554 | if (stat_get != NULL) | ||
1555 | { | ||
1556 | GNUNET_STATISTICS_get_cancel (stat_get); | ||
1557 | stat_get = NULL; | ||
1558 | } | ||
1429 | if (stats != NULL) | 1559 | if (stats != NULL) |
1430 | { | 1560 | { |
1431 | GNUNET_STATISTICS_destroy (stats, GNUNET_YES); | 1561 | GNUNET_STATISTICS_destroy (stats, GNUNET_YES); |
@@ -1614,6 +1744,13 @@ run (void *cls, | |||
1614 | } | 1744 | } |
1615 | return; | 1745 | return; |
1616 | } | 1746 | } |
1747 | stat_get = GNUNET_STATISTICS_get (stats, | ||
1748 | "datastore", | ||
1749 | QUOTA_STAT_NAME, | ||
1750 | GNUNET_TIME_UNIT_SECONDS, | ||
1751 | &process_stat_done, | ||
1752 | &process_stat_in, | ||
1753 | plugin); | ||
1617 | GNUNET_SERVER_disconnect_notify (server, &cleanup_reservations, NULL); | 1754 | GNUNET_SERVER_disconnect_notify (server, &cleanup_reservations, NULL); |
1618 | GNUNET_SERVER_add_handlers (server, handlers); | 1755 | GNUNET_SERVER_add_handlers (server, handlers); |
1619 | expired_kill_task | 1756 | expired_kill_task |