GNUnet 0.26.2-114-g7c6b613e3
 
Loading...
Searching...
No Matches
gnunet-service-datastore.c File Reference

Management for the datastore for files stored on a GNUnet node. More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_protocols.h"
#include "gnunet_statistics_service.h"
#include "gnunet_datastore_plugin.h"
#include "datastore.h"
Include dependency graph for gnunet-service-datastore.c:

Go to the source code of this file.

Data Structures

struct  DatastorePlugin
 Our datastore plugin. More...
 
struct  ReservationList
 Linked list of active reservations. More...
 

Macros

#define MAX_PENDING   1024
 How many messages do we queue at most per client?
 
#define MAX_BF_SIZE   ((uint32_t) (1LL << 31))
 Limit size of bloom filter to 2 GB.
 
#define MAX_EXPIRE_DELAY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
 How long are we at most keeping "expired" content past the expiration date in the database?
 
#define MIN_EXPIRE_DELAY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
 How fast are we allowed to query the database for deleting expired content? (1 item per second).
 
#define MAX_STAT_SYNC_LAG   50
 After how many payload-changing operations do we sync our statistics?
 

Functions

static void sync_stats ()
 Synchronize our utilization statistics with the statistics service.
 
static void delete_expired (void *cls)
 Task that is used to remove expired entries from the datastore.
 
static int expired_processor (void *cls, const struct GNUNET_HashCode *key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, uint64_t uid)
 Iterate over the expired items stored in the datastore.
 
static int quota_processor (void *cls, const struct GNUNET_HashCode *key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, uint64_t uid)
 An iterator over a set of items stored in the datastore that deletes until we're happy with respect to our quota.
 
static void manage_space (unsigned long long need)
 Manage available disk space by running tasks that will discard content if necessary.
 
static void transmit_status (struct GNUNET_SERVICE_Client *client, int code, const char *msg)
 Transmit a status code to the client.
 
static int transmit_item (void *cls, const struct GNUNET_HashCode *key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, uint64_t uid)
 Function that will transmit the given datastore entry to the client.
 
static void handle_reserve (void *cls, const struct ReserveMessage *msg)
 Handle RESERVE-message.
 
static void handle_release_reserve (void *cls, const struct ReleaseReserveMessage *msg)
 Handle RELEASE_RESERVE-message.
 
static int check_data (const struct DataMessage *dm)
 Check that the given message is a valid data message.
 
static void put_continuation (void *cls, const struct GNUNET_HashCode *key, uint32_t size, int status, const char *msg)
 Put continuation.
 
static int check_put (void *cls, const struct DataMessage *dm)
 Verify PUT-message.
 
static void handle_put (void *cls, const struct DataMessage *dm)
 Handle PUT-message.
 
static void handle_get (void *cls, const struct GetMessage *msg)
 Handle GNUNET_MESSAGE_TYPE_DATASTORE_GET-message.
 
static void handle_get_key (void *cls, const struct GetKeyMessage *msg)
 Handle GNUNET_MESSAGE_TYPE_DATASTORE_GET_KEY-message.
 
static void handle_get_replication (void *cls, const struct GNUNET_MessageHeader *message)
 Handle GET_REPLICATION-message.
 
static void handle_get_zero_anonymity (void *cls, const struct GetZeroAnonymityMessage *msg)
 Handle GET_ZERO_ANONYMITY-message.
 
static void remove_continuation (void *cls, const struct GNUNET_HashCode *key, uint32_t size, int status, const char *msg)
 Remove continuation.
 
static int check_remove (void *cls, const struct DataMessage *dm)
 Verify REMOVE-message.
 
static void handle_remove (void *cls, const struct DataMessage *dm)
 Handle REMOVE-message.
 
static void handle_drop (void *cls, const struct GNUNET_MessageHeader *message)
 Handle DROP-message.
 
static void disk_utilization_change_cb (void *cls, int delta)
 Function called by plugins to notify us about a change in their disk utilization.
 
static int process_stat_in (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent)
 Callback function to process statistic values.
 
static struct DatastorePluginload_plugin ()
 Load the datastore plugin.
 
static void unload_plugin (struct DatastorePlugin *plug)
 Function called when the service shuts down.
 
static void begin_service ()
 Initialization complete, start operating the service.
 
static void add_key_to_bloomfilter (void *cls, const struct GNUNET_HashCode *key, unsigned int count)
 Adds a given key to the bloomfilter in cls count times.
 
static void process_stat_done (void *cls, int success)
 We finished receiving the statistic.
 
static void stat_timeout (void *cls)
 Fetching stats took to long, run without.
 
static void cleaning_task (void *cls)
 Task run during shutdown.
 
static void * client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
 Add a client to our list of active clients.
 
static void client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
 Called whenever a client is disconnected.
 
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *serv)
 Process datastore requests.
 
 GNUNET_SERVICE_MAIN (GNUNET_OS_project_data_gnunet(), "datastore", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_fixed_size(reserve, GNUNET_MESSAGE_TYPE_DATASTORE_RESERVE, struct ReserveMessage, NULL), GNUNET_MQ_hd_fixed_size(release_reserve, GNUNET_MESSAGE_TYPE_DATASTORE_RELEASE_RESERVE, struct ReleaseReserveMessage, NULL), GNUNET_MQ_hd_var_size(put, GNUNET_MESSAGE_TYPE_DATASTORE_PUT, struct DataMessage, NULL), GNUNET_MQ_hd_fixed_size(get, GNUNET_MESSAGE_TYPE_DATASTORE_GET, struct GetMessage, NULL), GNUNET_MQ_hd_fixed_size(get_key, GNUNET_MESSAGE_TYPE_DATASTORE_GET_KEY, struct GetKeyMessage, NULL), GNUNET_MQ_hd_fixed_size(get_replication, GNUNET_MESSAGE_TYPE_DATASTORE_GET_REPLICATION, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_hd_fixed_size(get_zero_anonymity, GNUNET_MESSAGE_TYPE_DATASTORE_GET_ZERO_ANONYMITY, struct GetZeroAnonymityMessage, NULL), GNUNET_MQ_hd_var_size(remove, GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE, struct DataMessage, NULL), GNUNET_MQ_hd_fixed_size(drop, GNUNET_MESSAGE_TYPE_DATASTORE_DROP, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_handler_end())
 Define "main" method using service macro.
 

Variables

static char * quota_stat_name
 Name under which we store current space consumption.
 
static struct GNUNET_SCHEDULER_Taskstat_timeout_task
 Task to timeout stat GET.
 
static struct DatastorePluginplugin
 Our datastore plugin (NULL if not available).
 
static struct ReservationListreservations
 Linked list of space reservations made by clients.
 
static struct GNUNET_CONTAINER_BloomFilterfilter
 Bloomfilter to quickly tell if we don't have the content.
 
static char * plugin_name
 Name of our plugin.
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 Our configuration.
 
static struct GNUNET_STATISTICS_Handlestats
 Handle for reporting statistics.
 
static unsigned long long cache_size
 How much space are we using for the cache? (space available for insertions that will be instantly reclaimed by discarding less important content — or possibly whatever we just inserted into the "cache").
 
static unsigned long long reserved
 How much space have we currently reserved?
 
static unsigned long long payload
 How much data are we currently storing in the database?
 
static struct GNUNET_SCHEDULER_Taskexpired_kill_task
 Identity of the task that is used to delete expired content.
 
static struct GNUNET_TIME_Absolute min_expiration
 Minimum time that content should have to not be discarded instantly (time stamp of any content that we've been discarding recently to stay below the quota).
 
static unsigned long long quota
 How much space are we allowed to use?
 
static int do_drop
 Should the database be dropped on exit?
 
static int refresh_bf
 Should we refresh the BF when the DB is loaded?
 
static unsigned int last_sync
 Number of updates that were made to the payload value since we last synchronized it with the statistics service.
 
static int stats_worked
 Did we get an answer from statistics?
 
static int cleaning_done
 Have we already cleaned up the TCCs and are hence no longer willing (or able) to transmit anything to anyone?
 
static struct GNUNET_STATISTICS_GetHandlestat_get
 Handle for pending get request.
 
static struct GNUNET_SERVICE_Handleservice
 Handle to our server.
 

Detailed Description

Management for the datastore for files stored on a GNUnet node.

Author
Christian Grothoff

Definition in file gnunet-service-datastore.c.

Macro Definition Documentation

◆ MAX_PENDING

#define MAX_PENDING   1024

How many messages do we queue at most per client?

Definition at line 37 of file gnunet-service-datastore.c.

◆ MAX_BF_SIZE

#define MAX_BF_SIZE   ((uint32_t) (1LL << 31))

Limit size of bloom filter to 2 GB.

Definition at line 42 of file gnunet-service-datastore.c.

◆ MAX_EXPIRE_DELAY

#define MAX_EXPIRE_DELAY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)

How long are we at most keeping "expired" content past the expiration date in the database?

Definition at line 48 of file gnunet-service-datastore.c.

78{
84
88 char *short_name;
89
93 char *lib_name;
94
100};
101
102
106struct ReservationList
107{
111 struct ReservationList *next;
112
117
121 uint64_t amount;
122
126 uint64_t entries;
127
131 int32_t rid;
132};
133
134
138static struct DatastorePlugin *plugin;
139
143static struct ReservationList *reservations;
144
149
153static char *plugin_name;
154
158static const struct GNUNET_CONFIGURATION_Handle *cfg;
159
163static struct GNUNET_STATISTICS_Handle *stats;
164
171static unsigned long long cache_size;
172
176static unsigned long long reserved;
177
182static unsigned long long payload;
183
189
197
201static unsigned long long quota;
202
206static int do_drop;
207
211static int refresh_bf;
212
218static unsigned int last_sync;
219
223static int stats_worked;
224
225
230static void
231sync_stats ()
232{
235 "# utilization by current datastore",
236 payload,
237 GNUNET_NO);
238 last_sync = 0;
239}
240
241
246static int cleaning_done;
247
252
256static struct GNUNET_SERVICE_Handle *service;
257
266static void
267delete_expired (void *cls);
268
269
291static int
292expired_processor (void *cls,
293 const struct GNUNET_HashCode *key,
294 uint32_t size,
295 const void *data,
297 uint32_t priority,
298 uint32_t anonymity,
299 uint32_t replication,
301 uint64_t uid)
302{
303 struct GNUNET_TIME_Absolute now;
304
305 if (NULL == key)
306 {
311 NULL);
312 return GNUNET_SYSERR;
313 }
315 if (expiration.abs_value_us > now.abs_value_us)
316 {
317 /* finished processing */
322 NULL);
323 return GNUNET_SYSERR;
324 }
326 "Deleting content `%s' of type %u that expired %s ago\n",
327 GNUNET_h2s (key),
328 type,
331 GNUNET_YES));
332 min_expiration = now;
334 gettext_noop ("# bytes expired"),
335 size,
336 GNUNET_YES);
342 NULL);
343 return GNUNET_NO;
344}
345
346
355static void
356delete_expired (void *cls)
357{
358 expired_kill_task = NULL;
360}
361
362
382static int
383quota_processor (void *cls,
384 const struct GNUNET_HashCode *key,
385 uint32_t size,
386 const void *data,
388 uint32_t priority,
389 uint32_t anonymity,
390 uint32_t replication,
392 uint64_t uid)
393{
394 unsigned long long *need = cls;
395
396 if (NULL == key)
397 return GNUNET_SYSERR;
398 GNUNET_log (
400 "Deleting %llu bytes of low-priority (%u) content `%s' of type %u at %s prior to expiration (still trying to free another %llu bytes)\n",
401 (unsigned long long) (size + GNUNET_DATASTORE_ENTRY_OVERHEAD),
402 (unsigned int) priority,
403 GNUNET_h2s (key),
404 type,
406 expiration),
407 GNUNET_YES),
408 *need);
410 *need = 0;
411 else
413 if (priority > 0)
415 else
418 gettext_noop ("# bytes purged (low-priority)"),
419 size,
420 GNUNET_YES);
422 return GNUNET_NO;
423}
424
425
438static void
439manage_space (unsigned long long need)
440{
441 unsigned long long last;
442
444 "Asked to free up %llu bytes of cache space\n",
445 need);
446 last = 0;
447 while ((need > 0) && (last != need))
448 {
449 last = need;
451 }
452}
453
454
462static void
464 int code,
465 const char *msg)
466{
467 struct GNUNET_MQ_Envelope *env;
468 struct StatusMessage *sm;
469 size_t slen;
470
472 "Transmitting `%s' message with value %d and message `%s'\n",
473 "STATUS",
474 code,
475 msg != NULL ? msg : "(none)");
476 slen = (msg == NULL) ? 0 : strlen (msg) + 1;
478 sm->status = htonl (code);
480 GNUNET_memcpy (&sm[1], msg, slen);
482}
483
484
503static int
504transmit_item (void *cls,
505 const struct GNUNET_HashCode *key,
506 uint32_t size,
507 const void *data,
509 uint32_t priority,
510 uint32_t anonymity,
511 uint32_t replication,
513 uint64_t uid)
514{
515 struct GNUNET_SERVICE_Client *client = cls;
516 struct GNUNET_MQ_Envelope *env;
518 struct DataMessage *dm;
519
520 if (NULL == key)
521 {
522 /* transmit 'DATA_END' */
523 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting DATA_END message\n");
526 return GNUNET_OK;
527 }
530 dm->rid = htonl (0);
531 dm->size = htonl (size);
532 dm->type = htonl (type);
533 dm->priority = htonl (priority);
534 dm->anonymity = htonl (anonymity);
535 dm->replication = htonl (replication);
537 dm->uid = GNUNET_htonll (uid);
538 dm->key = *key;
539 GNUNET_memcpy (&dm[1], data, size);
540 GNUNET_log (
542 "Transmitting DATA message for `%s' of type %u with expiration %s (in: %s)\n",
543 GNUNET_h2s (key),
544 type,
547 expiration),
548 GNUNET_YES));
550 gettext_noop ("# results found"),
551 1,
552 GNUNET_NO);
554 return GNUNET_OK;
555}
556
557
564static void
565handle_reserve (void *cls, const struct ReserveMessage *msg)
566{
570 static int reservation_gen;
571 struct GNUNET_SERVICE_Client *client = cls;
572 struct ReservationList *e;
573 unsigned long long used;
574 unsigned long long req;
575 uint64_t amount;
576 uint32_t entries;
577
578 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing RESERVE request\n");
579 amount = GNUNET_ntohll (msg->amount);
580 entries = ntohl (msg->entries);
581 used = payload + reserved;
582 req =
583 amount + ((unsigned long long) GNUNET_DATASTORE_ENTRY_OVERHEAD) * entries;
584 if (used + req > quota)
585 {
586 if (quota < used)
587 used =
588 quota; /* cheat a bit for error message (to avoid negative numbers) */
589 GNUNET_log (
591 _ (
592 "Insufficient space (%llu bytes are available) to satisfy RESERVE request for %llu bytes\n"),
593 quota - used,
594 req);
595 if (cache_size < req)
596 {
597 /* TODO: document this in the FAQ; essentially, if this
598 * message happens, the insertion request could be blocked
599 * by less-important content from migration because it is
600 * larger than 1/8th of the overall available space, and
601 * we only reserve 1/8th for "fresh" insertions */
602 GNUNET_log (
604 _ (
605 "The requested amount (%llu bytes) is larger than the cache size (%llu bytes)\n"),
606 req,
607 cache_size);
609 0,
611 "Insufficient space to satisfy request and "
612 "requested amount is larger than cache size"));
613 }
614 else
615 {
617 0,
618 gettext_noop ("Insufficient space to satisfy request"));
619 }
621 return;
622 }
623 reserved += req;
625 gettext_noop ("# reserved"),
626 reserved,
627 GNUNET_NO);
628 e = GNUNET_new (struct ReservationList);
629 e->next = reservations;
630 reservations = e;
631 e->client = client;
632 e->amount = amount;
633 e->entries = entries;
634 e->rid = ++reservation_gen;
636 "Reserve space for %u entries with up to %lu bytes under rid %u\n",
637 entries,
638 amount,
639 e->rid);
640 if (reservation_gen < 0)
641 reservation_gen = 0; /* wrap around */
642 transmit_status (client, e->rid, NULL);
644}
645
646
653static void
654handle_release_reserve (void *cls, const struct ReleaseReserveMessage *msg)
655{
656 struct GNUNET_SERVICE_Client *client = cls;
657 struct ReservationList *pos;
658 struct ReservationList *prev;
659 struct ReservationList *next;
660 int rid = ntohl (msg->rid);
661 unsigned long long rem;
662
663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing RELEASE_RESERVE request\n");
665 prev = NULL;
666 while (NULL != (pos = next))
667 {
668 next = pos->next;
669 if (rid == pos->rid)
670 {
671 if (prev == NULL)
673 else
674 prev->next = next;
675 rem =
676 pos->amount
677 + ((unsigned long long) GNUNET_DATASTORE_ENTRY_OVERHEAD) * pos->entries;
678 GNUNET_assert (reserved >= rem);
679 reserved -= rem;
681 gettext_noop ("# reserved"),
682 reserved,
683 GNUNET_NO);
685 "Returning %llu remaining reserved bytes to storage pool\n",
686 rem);
687 GNUNET_free (pos);
690 return;
691 }
692 prev = pos;
693 }
694 GNUNET_break (0);
697 gettext_noop ("Could not find matching reservation"));
699}
700
701
708static int
709check_data (const struct DataMessage *dm)
710{
711 uint16_t size;
712 uint32_t dsize;
713
714 size = ntohs (dm->header.size);
715 dsize = ntohl (dm->size);
716 if (size != dsize + sizeof(struct DataMessage))
717 {
718 GNUNET_break (0);
719 return GNUNET_SYSERR;
720 }
721 return GNUNET_OK;
722}
723
724
735static void
736put_continuation (void *cls,
737 const struct GNUNET_HashCode *key,
738 uint32_t size,
739 int status,
740 const char *msg)
741{
742 struct GNUNET_SERVICE_Client *client = cls;
743
744 if (GNUNET_OK == status)
745 {
747 gettext_noop ("# bytes stored"),
748 size,
749 GNUNET_YES);
752 "Successfully stored %u bytes under key `%s'\n",
753 size,
754 GNUNET_h2s (key));
755 }
756 transmit_status (client,
758 msg);
760 {
762 _ ("Need %llu bytes more space (%llu allowed, using %llu)\n"),
763 (unsigned long long) size + GNUNET_DATASTORE_ENTRY_OVERHEAD,
764 (unsigned long long) (quota - reserved - cache_size),
765 (unsigned long long) payload);
767 }
768}
769
770
778static int
779check_put (void *cls, const struct DataMessage *dm)
780{
781 if (GNUNET_OK != check_data (dm))
782 {
783 GNUNET_break (0);
784 return GNUNET_SYSERR;
785 }
786 return GNUNET_OK;
787}
788
789
796static void
797handle_put (void *cls, const struct DataMessage *dm)
798{
799 struct GNUNET_SERVICE_Client *client = cls;
800 int rid;
801 struct ReservationList *pos;
802 uint32_t size;
803
805 "Processing PUT request for `%s' of type %u\n",
806 GNUNET_h2s (&dm->key),
807 (uint32_t) ntohl (dm->type));
808 rid = ntohl (dm->rid);
809 size = ntohl (dm->size);
811 "Put entry into space with %u bytes under rid %u\n",
812 size,
813 rid);
814 if (rid > 0)
815 {
816 pos = reservations;
817 while ((NULL != pos) && (rid != pos->rid))
818 pos = pos->next;
819 GNUNET_break (pos != NULL);
820 if (NULL != pos)
821 {
822 GNUNET_break (pos->entries > 0);
823 GNUNET_break (pos->amount >= size);
824 pos->entries--;
825 pos->amount -= size;
828 gettext_noop ("# reserved"),
829 reserved,
830 GNUNET_NO);
831 }
832 }
833 {
834 bool absent =
836 plugin->api->put (plugin->api->cls,
837 &dm->key,
838 absent,
839 size,
840 &dm[1],
841 ntohl (dm->type),
842 ntohl (dm->priority),
843 ntohl (dm->anonymity),
844 ntohl (dm->replication),
847 client);
848 }
850}
851
852
859static void
860handle_get (void *cls, const struct GetMessage *msg)
861{
862 struct GNUNET_SERVICE_Client *client = cls;
863
865 "Processing GET request of type %u\n",
866 (uint32_t) ntohl (msg->type));
868 gettext_noop ("# GET requests received"),
869 1,
870 GNUNET_NO);
872 GNUNET_ntohll (msg->next_uid),
873 msg->random,
874 NULL,
875 ntohl (msg->type),
877 client);
879}
880
881
888static void
889handle_get_key (void *cls, const struct GetKeyMessage *msg)
890{
891 struct GNUNET_SERVICE_Client *client = cls;
892
894 "Processing GET request for `%s' of type %u\n",
895 GNUNET_h2s (&msg->key),
896 (uint32_t) ntohl (msg->type));
898 gettext_noop ("# GET KEY requests received"),
899 1,
900 GNUNET_NO);
902 {
903 /* don't bother database... */
905 "Empty result set for GET request for `%s' (bloomfilter).\n",
906 GNUNET_h2s (&msg->key));
909 "# requests filtered by bloomfilter"),
910 1,
911 GNUNET_NO);
912 transmit_item (client,
913 NULL,
914 0,
915 NULL,
916 0,
917 0,
918 0,
919 0,
921 0);
923 return;
924 }
926 GNUNET_ntohll (msg->next_uid),
927 msg->random,
928 &msg->key,
929 ntohl (msg->type),
931 client);
933}
934
935
942static void
943handle_get_replication (void *cls, const struct GNUNET_MessageHeader *message)
944{
945 struct GNUNET_SERVICE_Client *client = cls;
946
947 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing GET_REPLICATION request\n");
950 "# GET REPLICATION requests received"),
951 1,
952 GNUNET_NO);
955}
956
957
964static void
966{
967 struct GNUNET_SERVICE_Client *client = cls;
969
970 type = ntohl (msg->type);
972 {
973 GNUNET_break (0);
975 return;
976 }
978 "Processing GET_ZERO_ANONYMITY request\n");
981 "# GET ZERO ANONYMITY requests received"),
982 1,
983 GNUNET_NO);
985 GNUNET_ntohll (msg->next_uid),
986 type,
988 client);
990}
991
992
1003static void
1004remove_continuation (void *cls,
1005 const struct GNUNET_HashCode *key,
1006 uint32_t size,
1007 int status,
1008 const char *msg)
1009{
1010 struct GNUNET_SERVICE_Client *client = cls;
1011
1012 if (GNUNET_SYSERR == status)
1013 {
1014 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "REMOVE request failed: %s.\n", msg);
1015 transmit_status (client, GNUNET_NO, msg);
1016 return;
1017 }
1018 if (GNUNET_NO == status)
1019 {
1021 "Content not found for REMOVE request.\n");
1022 transmit_status (client, GNUNET_NO, _ ("Content not found"));
1023 return;
1024 }
1026 "Item matches REMOVE request for key `%s'.\n",
1027 GNUNET_h2s (key));
1029 gettext_noop ("# bytes removed (explicit request)"),
1030 size,
1031 GNUNET_YES);
1033 transmit_status (client, GNUNET_OK, NULL);
1034}
1035
1036
1044static int
1045check_remove (void *cls, const struct DataMessage *dm)
1046{
1047 if (GNUNET_OK != check_data (dm))
1048 {
1049 GNUNET_break (0);
1050 return GNUNET_SYSERR;
1051 }
1052 return GNUNET_OK;
1053}
1054
1055
1062static void
1063handle_remove (void *cls, const struct DataMessage *dm)
1064{
1065 struct GNUNET_SERVICE_Client *client = cls;
1066
1068 gettext_noop ("# REMOVE requests received"),
1069 1,
1070 GNUNET_NO);
1072 "Processing REMOVE request for `%s'\n",
1073 GNUNET_h2s (&dm->key));
1075 &dm->key,
1076 ntohl (dm->size),
1077 &dm[1],
1079 client);
1081}
1082
1083
1090static void
1091handle_drop (void *cls,
1092 const struct GNUNET_MessageHeader *message)
1093{
1094 struct GNUNET_SERVICE_Client *client = cls;
1095
1097 "Processing DROP request\n");
1100}
1101
1102
1111static void
1112disk_utilization_change_cb (void *cls, int delta)
1113{
1114 if ((delta < 0) && (payload < -delta))
1115 {
1116 GNUNET_log (
1118 _ (
1119 "Datastore payload must have been inaccurate (%lld < %lld). Recomputing it.\n"),
1120 (long long) payload,
1121 (long long) -delta);
1124 _ ("New payload: %lld\n"),
1125 (long long) payload);
1126 sync_stats ();
1127 return;
1128 }
1129 payload += delta;
1130 last_sync++;
1132 sync_stats ();
1133}
1134
1135
1146static int
1147process_stat_in (void *cls,
1148 const char *subsystem,
1149 const char *name,
1150 uint64_t value,
1151 int is_persistent)
1152{
1155 payload += value;
1156 GNUNET_log (
1158 "Notification from statistics about existing payload (%llu), new payload is %llu\n",
1159 (unsigned long long) value,
1160 (unsigned long long) payload);
1161 return GNUNET_OK;
1162}
1163
1164
1168static struct DatastorePlugin *
1169load_plugin ()
1170{
1171 struct DatastorePlugin *ret;
1172 char *libname;
1173
1174 ret = GNUNET_new (struct DatastorePlugin);
1175 ret->env.cfg = cfg;
1176 ret->env.duc = &disk_utilization_change_cb;
1177 ret->env.cls = NULL;
1179 _ ("Loading `%s' datastore plugin\n"),
1180 plugin_name);
1181 GNUNET_asprintf (&libname,
1182 "libgnunet_plugin_datastore_%s",
1183 plugin_name);
1184 ret->short_name = GNUNET_strdup (plugin_name);
1185 ret->lib_name = libname;
1187 libname,
1188 &ret->env);
1189 if (NULL == ret->api)
1190 {
1192 _ ("Failed to load datastore plugin for `%s'\n"),
1193 plugin_name);
1194 GNUNET_free (ret->short_name);
1195 GNUNET_free (libname);
1196 GNUNET_free (ret);
1197 return NULL;
1198 }
1199 return ret;
1200}
1201
1202
1209static void
1210unload_plugin (struct DatastorePlugin *plug)
1211{
1213 "Datastore service is unloading plugin...\n");
1214 GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
1215 GNUNET_free (plug->lib_name);
1216 GNUNET_free (plug->short_name);
1217 GNUNET_free (plug);
1218}
1219
1220
1224static void
1226{
1231 NULL);
1232}
1233
1234
1242static void
1243add_key_to_bloomfilter (void *cls,
1244 const struct GNUNET_HashCode *key,
1245 unsigned int count)
1246{
1247 struct GNUNET_CONTAINER_BloomFilter *bf = cls;
1248
1249 if (NULL == key)
1250 {
1252 _ ("Bloomfilter construction complete.\n"));
1253 begin_service ();
1254 return;
1255 }
1256
1257 while (0 < count--)
1259}
1260
1261
1269static void
1270process_stat_done (void *cls, int success)
1271{
1272 stat_get = NULL;
1273 if (NULL != stat_timeout_task)
1274 {
1276 stat_timeout_task = NULL;
1277 }
1278 plugin = load_plugin ();
1279 if (NULL == plugin)
1280 {
1282 filter = NULL;
1283 if (NULL != stats)
1284 {
1286 stats = NULL;
1287 }
1288 return;
1289 }
1290
1291 if (GNUNET_NO == stats_worked)
1292 {
1294 "Failed to obtain value from statistics service, recomputing it\n");
1297 _ ("New payload: %lld\n"),
1298 (long long) payload);
1299 }
1300
1301 if (GNUNET_YES == refresh_bf)
1302 {
1304 _ ("Rebuilding bloomfilter. Please be patient.\n"));
1305 if (NULL != plugin->api->get_keys)
1306 {
1308 return;
1309 }
1310 else
1311 {
1313 _ (
1314 "Plugin does not support get_keys function. Please fix!\n"))
1315 ;
1316 }
1317 }
1318 begin_service ();
1319}
1320
1321
1327static void
1328stat_timeout (void *cls)
1329{
1330 stat_timeout_task = NULL;
1333}
1334
1335
1339static void
1340cleaning_task (void *cls)
1341{
1343 if (NULL != expired_kill_task)
1344 {
1346 expired_kill_task = NULL;
1347 }
1348 if (GNUNET_YES == do_drop)
1349 {
1351 "Dropping database!\n");
1352 plugin->api->drop (plugin->api->cls);
1353 payload = 0;
1354 last_sync++;
1355 }
1356 if (NULL != plugin)
1357 {
1359 plugin = NULL;
1360 }
1361 if (NULL != filter)
1362 {
1364 filter = NULL;
1365 }
1366 if (NULL != stat_get)
1367 {
1369 stat_get = NULL;
1370 }
1371 if (NULL != stat_timeout_task)
1372 {
1374 stat_timeout_task = NULL;
1375 }
1377 plugin_name = NULL;
1378 if (last_sync > 0)
1379 sync_stats ();
1380 if (NULL != stats)
1381 {
1383 stats = NULL;
1384 }
1386 quota_stat_name = NULL;
1387}
1388
1389
1398static void *
1399client_connect_cb (void *cls,
1400 struct GNUNET_SERVICE_Client *client,
1401 struct GNUNET_MQ_Handle *mq)
1402{
1403 return client;
1404}
1405
1406
1415static void
1416client_disconnect_cb (void *cls,
1417 struct GNUNET_SERVICE_Client *client,
1418 void *app_ctx)
1419{
1420 struct ReservationList *pos;
1421 struct ReservationList *prev;
1422 struct ReservationList *next;
1423
1424 GNUNET_assert (app_ctx == client);
1425 prev = NULL;
1426 pos = reservations;
1427 while (NULL != pos)
1428 {
1429 next = pos->next;
1430 if (pos->client == client)
1431 {
1432 if (NULL == prev)
1434 else
1435 prev->next = next;
1437 GNUNET_free (pos);
1438 }
1439 else
1440 {
1441 prev = pos;
1442 }
1443 pos = next;
1444 }
1446 gettext_noop ("# reserved"),
1447 reserved,
1448 GNUNET_NO);
1449}
1450
1451
1459static void
1460run (void *cls,
1461 const struct GNUNET_CONFIGURATION_Handle *c,
1462 struct GNUNET_SERVICE_Handle *serv)
1463{
1464 char *fn;
1465 char *pfn;
1466 unsigned int bf_size;
1467
1468 service = serv;
1469 cfg = c;
1471 "DATASTORE",
1472 "DATABASE",
1473 &plugin_name))
1474 {
1476 "DATABASE",
1477 "DATASTORE");
1478 return;
1479 }
1481 _ ("# bytes used in file-sharing datastore `%s'"),
1482 plugin_name);
1483 if (GNUNET_OK !=
1484 GNUNET_CONFIGURATION_get_value_size (cfg, "DATASTORE", "QUOTA", &quota))
1485 {
1486 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "QUOTA", "DATASTORE");
1487 return;
1488 }
1489 stats = GNUNET_STATISTICS_create ("datastore", cfg);
1491 cache_size = quota / 8; /* Or should we make this an option? */
1493 gettext_noop ("# cache size"),
1494 cache_size,
1495 GNUNET_NO);
1496 if (quota / (32 * 1024LL) > MAX_BF_SIZE)
1497 bf_size = MAX_BF_SIZE;
1498 else
1499 bf_size =
1500 quota / (32 * 1024LL); /* 8 bit per entry, 1 bit per 32 kb in DB */
1501 fn = NULL;
1503 "DATASTORE",
1504 "BLOOMFILTER",
1505 &fn)) ||
1507 {
1509 _ ("Could not use specified filename `%s' for bloomfilter.\n"),
1510 NULL != fn ? fn : "");
1511 GNUNET_free (fn);
1512 fn = NULL;
1513 }
1514 if (NULL != fn)
1515 {
1516 GNUNET_asprintf (&pfn, "%s.%s", fn, plugin_name);
1517 if (GNUNET_YES == GNUNET_DISK_file_test (pfn))
1518 {
1519 filter =
1521 bf_size,
1522 5); /* approx. 3% false positives at max use */
1523 if (NULL == filter)
1524 {
1525 /* file exists but not valid, remove and try again, but refresh */
1526 if (0 != unlink (pfn))
1527 {
1528 /* failed to remove, run without file */
1530 _ ("Failed to remove bogus bloomfilter file `%s'\n"),
1531 pfn);
1532 GNUNET_free (pfn);
1533 pfn = NULL;
1535 NULL,
1536 bf_size,
1537 5); /* approx. 3% false positives at max use */
1539 }
1540 else
1541 {
1542 /* try again after remove */
1544 pfn,
1545 bf_size,
1546 5); /* approx. 3% false positives at max use */
1548 if (NULL == filter)
1549 {
1550 /* failed yet again, give up on using file */
1552 _ ("Failed to remove bogus bloomfilter file `%s'\n"),
1553 pfn);
1554 GNUNET_free (pfn);
1555 pfn = NULL;
1557 NULL,
1558 bf_size,
1559 5); /* approx. 3% false positives at max use */
1560 }
1561 }
1562 }
1563 else
1564 {
1565 /* normal case: have an existing valid bf file, no need to refresh */
1567 }
1568 }
1569 else
1570 {
1571 filter =
1573 bf_size,
1574 5); /* approx. 3% false positives at max use */
1576 }
1577 GNUNET_free (pfn);
1578 }
1579 else
1580 {
1581 filter =
1583 bf_size,
1584 5); /* approx. 3% false positives at max use */
1586 }
1587 GNUNET_free (fn);
1588 if (NULL == filter)
1589 {
1591 _ ("Failed to initialize bloomfilter.\n"));
1592 if (NULL != stats)
1593 {
1595 stats = NULL;
1596 }
1597 return;
1598 }
1601 "datastore",
1605 NULL);
1606 if (NULL == stat_get)
1608 else
1610 &stat_timeout,
1611 NULL);
1613}
1614
1615
1621 "datastore",
1623 &run,
1626 NULL,
1627 GNUNET_MQ_hd_fixed_size (reserve,
1629 struct ReserveMessage,
1630 NULL),
1631 GNUNET_MQ_hd_fixed_size (release_reserve,
1633 struct ReleaseReserveMessage,
1634 NULL),
1637 struct DataMessage,
1638 NULL),
1641 struct GetMessage,
1642 NULL),
1643 GNUNET_MQ_hd_fixed_size (get_key,
1645 struct GetKeyMessage,
1646 NULL),
1647 GNUNET_MQ_hd_fixed_size (get_replication,
1649 struct GNUNET_MessageHeader,
1650 NULL),
1651 GNUNET_MQ_hd_fixed_size (get_zero_anonymity,
1654 NULL),
1655 GNUNET_MQ_hd_var_size (remove,
1657 struct DataMessage,
1658 NULL),
1661 struct GNUNET_MessageHeader,
1662 NULL),
1664
1665
1666/* end of gnunet-service-datastore.c */
struct GNUNET_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
#define gettext_noop(String)
Definition gettext.h:74
static int ret
Final status code.
Definition gnunet-arm.c:93
static int end
Set if we are to shutdown all services (including ARM).
Definition gnunet-arm.c:33
static unsigned int replication
Desired replication level.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_TIME_Relative expiration
User supplied expiration value.
static unsigned int anonymity
static char * name
Name (label) of the records to list.
static char * value
Value of the record to add/remove.
static uint32_t type
Type string converted to DNS type value.
static int status
The program status; 0 for success.
Definition gnunet-nse.c:39
static int check_put(void *cls, const struct DataMessage *dm)
Verify PUT-message.
static struct GNUNET_STATISTICS_GetHandle * stat_get
Handle for pending get request.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *serv)
Process datastore requests.
static void stat_timeout(void *cls)
Fetching stats took to long, run without.
static void handle_drop(void *cls, const struct GNUNET_MessageHeader *message)
Handle DROP-message.
static void cleaning_task(void *cls)
Task run during shutdown.
static int expired_processor(void *cls, const struct GNUNET_HashCode *key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, uint64_t uid)
Iterate over the expired items stored in the datastore.
static char * plugin_name
Name of our plugin.
static void add_key_to_bloomfilter(void *cls, const struct GNUNET_HashCode *key, unsigned int count)
Adds a given key to the bloomfilter in cls count times.
static struct DatastorePlugin * plugin
Our datastore plugin (NULL if not available).
static int stats_worked
Did we get an answer from statistics?
static struct GNUNET_STATISTICS_Handle * stats
Handle for reporting statistics.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static struct GNUNET_SCHEDULER_Task * stat_timeout_task
Task to timeout stat GET.
static struct GNUNET_CONTAINER_BloomFilter * filter
Bloomfilter to quickly tell if we don't have the content.
static void delete_expired(void *cls)
Task that is used to remove expired entries from the datastore.
static struct GNUNET_TIME_Absolute min_expiration
Minimum time that content should have to not be discarded instantly (time stamp of any content that w...
static void handle_remove(void *cls, const struct DataMessage *dm)
Handle REMOVE-message.
static unsigned long long payload
How much data are we currently storing in the database?
static int check_remove(void *cls, const struct DataMessage *dm)
Verify REMOVE-message.
static void handle_reserve(void *cls, const struct ReserveMessage *msg)
Handle RESERVE-message.
#define MAX_BF_SIZE
Limit size of bloom filter to 2 GB.
static void put_continuation(void *cls, const struct GNUNET_HashCode *key, uint32_t size, int status, const char *msg)
Put continuation.
static char * quota_stat_name
Name under which we store current space consumption.
static void handle_get_key(void *cls, const struct GetKeyMessage *msg)
Handle GNUNET_MESSAGE_TYPE_DATASTORE_GET_KEY-message.
static int quota_processor(void *cls, const struct GNUNET_HashCode *key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, uint64_t uid)
An iterator over a set of items stored in the datastore that deletes until we're happy with respect t...
static void process_stat_done(void *cls, int success)
We finished receiving the statistic.
static void remove_continuation(void *cls, const struct GNUNET_HashCode *key, uint32_t size, int status, const char *msg)
Remove continuation.
#define MIN_EXPIRE_DELAY
How fast are we allowed to query the database for deleting expired content? (1 item per second).
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
Add a client to our list of active clients.
static void transmit_status(struct GNUNET_SERVICE_Client *client, int code, const char *msg)
Transmit a status code to the client.
static int check_data(const struct DataMessage *dm)
Check that the given message is a valid data message.
static int process_stat_in(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent)
Callback function to process statistic values.
static int do_drop
Should the database be dropped on exit?
static int cleaning_done
Have we already cleaned up the TCCs and are hence no longer willing (or able) to transmit anything to...
static void handle_release_reserve(void *cls, const struct ReleaseReserveMessage *msg)
Handle RELEASE_RESERVE-message.
#define MAX_STAT_SYNC_LAG
After how many payload-changing operations do we sync our statistics?
static void manage_space(unsigned long long need)
Manage available disk space by running tasks that will discard content if necessary.
static struct GNUNET_SCHEDULER_Task * expired_kill_task
Identity of the task that is used to delete expired content.
static void begin_service()
Initialization complete, start operating the service.
static unsigned long long quota
How much space are we allowed to use?
static struct ReservationList * reservations
Linked list of space reservations made by clients.
static unsigned int last_sync
Number of updates that were made to the payload value since we last synchronized it with the statisti...
static void handle_get_replication(void *cls, const struct GNUNET_MessageHeader *message)
Handle GET_REPLICATION-message.
static void handle_get(void *cls, const struct GetMessage *msg)
Handle GNUNET_MESSAGE_TYPE_DATASTORE_GET-message.
static unsigned long long reserved
How much space have we currently reserved?
static void sync_stats()
Synchronize our utilization statistics with the statistics service.
static int transmit_item(void *cls, const struct GNUNET_HashCode *key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, uint64_t uid)
Function that will transmit the given datastore entry to the client.
static void handle_put(void *cls, const struct DataMessage *dm)
Handle PUT-message.
static void unload_plugin(struct DatastorePlugin *plug)
Function called when the service shuts down.
#define MAX_EXPIRE_DELAY
How long are we at most keeping "expired" content past the expiration date in the database?
static void disk_utilization_change_cb(void *cls, int delta)
Function called by plugins to notify us about a change in their disk utilization.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Called whenever a client is disconnected.
static struct GNUNET_SERVICE_Handle * service
Handle to our server.
static int refresh_bf
Should we refresh the BF when the DB is loaded?
static struct DatastorePlugin * load_plugin()
Load the datastore plugin.
static unsigned long long cache_size
How much space are we using for the cache? (space available for insertions that will be instantly rec...
static void handle_get_zero_anonymity(void *cls, const struct GetZeroAnonymityMessage *msg)
Handle GET_ZERO_ANONYMITY-message.
static char * subsystem
Set to subsystem that we're going to get stats for (or NULL for all).
GNUNET_BLOCK_Type
WARNING: This header is generated! In order to add DHT block types, you must register them in GANA,...
@ GNUNET_BLOCK_TYPE_ANY
Identifier for any block.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_init(const char *data, size_t size, unsigned int k)
Create a Bloom filter from raw bits.
void GNUNET_CONTAINER_bloomfilter_add(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Add an element to the filter.
bool GNUNET_CONTAINER_bloomfilter_test(const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Test if an element is in the filter.
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_load(const char *filename, size_t size, unsigned int k)
Load a Bloom filter from a file.
void GNUNET_CONTAINER_bloomfilter_remove(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Remove an element from the filter.
void GNUNET_CONTAINER_bloomfilter_free(struct GNUNET_CONTAINER_BloomFilter *bf)
Free the space associated with a filter in memory, flush to drive if needed (do not free the space on...
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_size(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *size)
Get a configuration value that should be a size in bytes.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define GNUNET_DATASTORE_ENTRY_OVERHEAD
How many bytes of overhead will we assume per entry in any DB (for reservations)?
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory).
Definition disk.c:557
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition disk.c:664
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_SCHEDULER_PRIORITY_IDLE
Run when otherwise idle.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition mq.c:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
void * GNUNET_PLUGIN_load(const struct GNUNET_OS_ProjectData *pd, const char *library_name, void *arg)
Setup plugin (runs the "init" callback and returns whatever "init" returned).
Definition plugin.c:221
void * GNUNET_PLUGIN_unload(const char *library_name, void *arg)
Unload plugin (runs the "done" callback and returns whatever "done" returned).
Definition plugin.c:277
#define GNUNET_MESSAGE_TYPE_DATASTORE_DROP
Message sent by datastore client to drop the database.
#define GNUNET_MESSAGE_TYPE_DATASTORE_RELEASE_RESERVE
Message sent by datastore client on join.
#define GNUNET_MESSAGE_TYPE_DATASTORE_DATA_END
Message sent by datastore to client signaling end of matching data.
#define GNUNET_MESSAGE_TYPE_DATASTORE_GET_KEY
Message sent by datastore client to get data by key.
#define GNUNET_MESSAGE_TYPE_DATASTORE_RESERVE
Message sent by datastore client on join.
#define GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE
Message sent by datastore client to remove data.
#define GNUNET_MESSAGE_TYPE_DATASTORE_GET
Message sent by datastore client to get data.
#define GNUNET_MESSAGE_TYPE_DATASTORE_DATA
Message sent by datastore to client providing requested data (in response to GET or GET_RANDOM reques...
#define GNUNET_MESSAGE_TYPE_DATASTORE_PUT
Message sent by datastore client to store data.
#define GNUNET_MESSAGE_TYPE_DATASTORE_GET_REPLICATION
Message sent by datastore client to get random data.
#define GNUNET_MESSAGE_TYPE_DATASTORE_STATUS
Message sent by datastore to client informing about status processing a request (in response to RESER...
#define GNUNET_MESSAGE_TYPE_DATASTORE_GET_ZERO_ANONYMITY
Message sent by datastore client to get random data.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1345
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1283
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1213
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_with_priority(enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority.
Definition scheduler.c:1237
#define GNUNET_SERVICE_MAIN(pd, service_name, service_options, init_cb, connect_cb, disconnect_cb, cls,...)
Creates the "main" function for a GNUnet service.
void GNUNET_SERVICE_suspend(struct GNUNET_SERVICE_Handle *sh)
Suspend accepting connections from the listen socket temporarily.
Definition service.c:2381
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition service.c:2463
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition service.c:2545
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition service.c:2434
void GNUNET_SERVICE_resume(struct GNUNET_SERVICE_Handle *sh)
Resume accepting connections from the listen socket.
Definition service.c:2389
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_get_cancel(struct GNUNET_STATISTICS_GetHandle *gh)
Cancel a GNUNET_STATISTICS_get request.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
struct GNUNET_STATISTICS_GetHandle * GNUNET_STATISTICS_get(struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, GNUNET_STATISTICS_Callback cont, GNUNET_STATISTICS_Iterator proc, void *cls)
Get statistic from the peer.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition time.c:406
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition strings.c:604
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:737
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end)
Compute the time difference between the given start and end times.
Definition time.c:423
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition time.c:636
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition strings.c:665
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
static unsigned int size
Size of the "table".
Definition peer.c:68
#define _(String)
GNU gettext support macro.
Definition platform.h:179
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
static struct GNUNET_TIME_Relative delta
Definition speedup.c:36
Message transmitting content from or to the datastore service.
Definition datastore.h:192
uint32_t priority
Priority of the item (NBO), zero for remove.
Definition datastore.h:219
struct GNUNET_HashCode key
Key under which the item can be found.
Definition datastore.h:252
uint64_t uid
Unique ID for the content (can be used for UPDATE); can be zero for remove (which indicates that the ...
Definition datastore.h:242
struct GNUNET_TIME_AbsoluteNBO expiration
Expiration time (NBO); zero for remove.
Definition datastore.h:247
struct GNUNET_MessageHeader header
Type is either GNUNET_MESSAGE_TYPE_DATASTORE_PUT, GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE or GNUNET_MESS...
Definition datastore.h:199
uint32_t type
Type of the item (NBO), zero for remove, (actually an enum GNUNET_BLOCK_Type)
Definition datastore.h:214
uint32_t size
Number of bytes in the item (NBO).
Definition datastore.h:209
uint32_t replication
Desired replication level.
Definition datastore.h:229
uint32_t anonymity
Desired anonymity level (NBO), zero for remove.
Definition datastore.h:224
uint32_t rid
Reservation ID to use; use zero for none.
Definition datastore.h:204
Our datastore plugin.
char * lib_name
Name of the library (e.g.
struct GNUNET_DATASTORE_PluginFunctions * api
API of the transport as returned by the plugin's initialization function.
char * short_name
Short name for the plugin (e.g.
The datastore service will pass a pointer to a struct of this type as the first and only argument to ...
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
PluginGetKey get_key
Get a particular datum matching a given hash from the datastore.
PluginGetRandom get_expiration
Function to get a random expired item or, if none are expired, either the oldest entry or one with a ...
PluginEstimateSize estimate_size
Calculate the current on-disk size of the SQ store.
PluginGetKeys get_keys
Iterate over all keys in the database.
PluginGetRandom get_replication
Function to get a random item with high replication score from the database, lowering the item's repl...
PluginPut put
Function to store an item in the datastore.
void * cls
Closure to use for all of the following callbacks (except "next_request").
PluginGetType get_zero_anonymity
Get datum (of the specified type) with anonymity level zero.
PluginDrop drop
Delete the database.
PluginRemoveKey remove_key
Function to remove an item from the database.
A 512-bit hashcode.
Handle to a message queue.
Definition mq.c:87
Header for all communications.
Entry in list of pending tasks.
Definition scheduler.c:141
Handle to a client that is connected to a service.
Definition service.c:249
Handle to a service.
Definition service.c:116
Linked list of things we still need to do.
Handle for the service.
Time for absolute times used by GNUnet, in microseconds.
Message to the datastore service asking about specific content.
Definition datastore.h:108
Message to the datastore service asking about specific content.
Definition datastore.h:141
Message to the datastore service asking about zero anonymity content.
Definition datastore.h:169
Message from datastore client informing service that the remainder of the reserved bytes can now be r...
Definition datastore.h:90
Linked list of active reservations.
uint64_t amount
Number of bytes (still) reserved.
struct GNUNET_SERVICE_Client * client
Client that made the reservation.
int32_t rid
Reservation identifier.
uint64_t entries
Number of items (still) reserved.
struct ReservationList * next
This is a linked list.
Message from datastore service informing client about the current size of the datastore.
Definition datastore.h:40
Message from datastore service informing client about the success or failure of a requested operation...
Definition datastore.h:65
struct GNUNET_TIME_AbsoluteNBO min_expiration
Minimum expiration time required for content to be stored by the datacache at this time,...
Definition datastore.h:80
int32_t status
Status code, -1 for errors.
Definition datastore.h:74

◆ MIN_EXPIRE_DELAY

#define MIN_EXPIRE_DELAY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)

How fast are we allowed to query the database for deleting expired content? (1 item per second).

Definition at line 55 of file gnunet-service-datastore.c.

◆ MAX_STAT_SYNC_LAG

#define MAX_STAT_SYNC_LAG   50

After how many payload-changing operations do we sync our statistics?

Definition at line 72 of file gnunet-service-datastore.c.

Function Documentation

◆ sync_stats()

static void sync_stats ( )
static

Synchronize our utilization statistics with the statistics service.

Definition at line 232 of file gnunet-service-datastore.c.

233{
236 "# utilization by current datastore",
237 payload,
238 GNUNET_NO);
239 last_sync = 0;
240}

References GNUNET_NO, GNUNET_STATISTICS_set(), GNUNET_YES, last_sync, payload, quota_stat_name, and stats.

Referenced by cleaning_task(), and disk_utilization_change_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ delete_expired()

static void delete_expired ( void *  cls)
static

Task that is used to remove expired entries from the datastore.

This task will schedule itself again automatically to always delete all expired content quickly.

Parameters
clsnot used

Definition at line 357 of file gnunet-service-datastore.c.

358{
359 expired_kill_task = NULL;
361}

References DatastorePlugin::api, GNUNET_DATASTORE_PluginFunctions::cls, expired_kill_task, expired_processor(), GNUNET_DATASTORE_PluginFunctions::get_expiration, and plugin.

Referenced by begin_service(), and expired_processor().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ expired_processor()

static int expired_processor ( void *  cls,
const struct GNUNET_HashCode key,
uint32_t  size,
const void *  data,
enum GNUNET_BLOCK_Type  type,
uint32_t  priority,
uint32_t  anonymity,
uint32_t  replication,
struct GNUNET_TIME_Absolute  expiration,
uint64_t  uid 
)
static

Iterate over the expired items stored in the datastore.

Delete all expired items; once we have processed all expired items, re-schedule the "delete_expired" task.

Parameters
clsnot used
keykey for the content
sizenumber of bytes in data
datacontent stored
typetype of the content
prioritypriority of the content
anonymityanonymity-level for the content
replicationreplication-level for the content
expirationexpiration time for the content
uidunique identifier for the datum; maybe 0 if no unique identifier is available
Returns
GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue (continue on call to "next", of course), GNUNET_NO to delete the item and continue (if supported)

Definition at line 293 of file gnunet-service-datastore.c.

303{
304 struct GNUNET_TIME_Absolute now;
305
306 if (NULL == key)
307 {
312 NULL);
313 return GNUNET_SYSERR;
314 }
316 if (expiration.abs_value_us > now.abs_value_us)
317 {
318 /* finished processing */
323 NULL);
324 return GNUNET_SYSERR;
325 }
327 "Deleting content `%s' of type %u that expired %s ago\n",
328 GNUNET_h2s (key),
329 type,
332 GNUNET_YES));
333 min_expiration = now;
335 gettext_noop ("# bytes expired"),
336 size,
337 GNUNET_YES);
343 NULL);
344 return GNUNET_NO;
345}

References GNUNET_TIME_Absolute::abs_value_us, delete_expired(), expiration, expired_kill_task, filter, gettext_noop, GNUNET_CONTAINER_bloomfilter_remove(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_NO, GNUNET_SCHEDULER_add_delayed_with_priority(), GNUNET_SCHEDULER_PRIORITY_IDLE, GNUNET_STATISTICS_update(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_SYSERR, GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_get_difference(), GNUNET_YES, key, MAX_EXPIRE_DELAY, min_expiration, MIN_EXPIRE_DELAY, size, stats, and type.

Referenced by delete_expired().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ quota_processor()

static int quota_processor ( void *  cls,
const struct GNUNET_HashCode key,
uint32_t  size,
const void *  data,
enum GNUNET_BLOCK_Type  type,
uint32_t  priority,
uint32_t  anonymity,
uint32_t  replication,
struct GNUNET_TIME_Absolute  expiration,
uint64_t  uid 
)
static

An iterator over a set of items stored in the datastore that deletes until we're happy with respect to our quota.

Parameters
clsclosure
keykey for the content
sizenumber of bytes in data
datacontent stored
typetype of the content
prioritypriority of the content
anonymityanonymity-level for the content
replicationreplication-level for the content
expirationexpiration time for the content
uidunique identifier for the datum; maybe 0 if no unique identifier is available
Returns
GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue (continue on call to "next", of course), GNUNET_NO to delete the item and continue (if supported)

Definition at line 384 of file gnunet-service-datastore.c.

394{
395 unsigned long long *need = cls;
396
397 if (NULL == key)
398 return GNUNET_SYSERR;
399 GNUNET_log (
401 "Deleting %llu bytes of low-priority (%u) content `%s' of type %u at %s prior to expiration (still trying to free another %llu bytes)\n",
402 (unsigned long long) (size + GNUNET_DATASTORE_ENTRY_OVERHEAD),
403 (unsigned int) priority,
404 GNUNET_h2s (key),
405 type,
407 expiration),
408 GNUNET_YES),
409 *need);
411 *need = 0;
412 else
414 if (priority > 0)
416 else
419 gettext_noop ("# bytes purged (low-priority)"),
420 size,
421 GNUNET_YES);
423 return GNUNET_NO;
424}

References expiration, filter, gettext_noop, GNUNET_CONTAINER_bloomfilter_remove(), GNUNET_DATASTORE_ENTRY_OVERHEAD, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_SYSERR, GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_YES, key, min_expiration, size, stats, and type.

Referenced by manage_space().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ manage_space()

static void manage_space ( unsigned long long  need)
static

Manage available disk space by running tasks that will discard content if necessary.

This function will be run whenever a request for "need" bytes of storage could only be satisfied by eating into the "cache" (and we want our cache space back).

Parameters
neednumber of bytes of content that were placed into the "cache" (and hence the number of bytes that should be removed).

Definition at line 440 of file gnunet-service-datastore.c.

441{
442 unsigned long long last;
443
445 "Asked to free up %llu bytes of cache space\n",
446 need);
447 last = 0;
448 while ((need > 0) && (last != need))
449 {
450 last = need;
452 }
453}

References DatastorePlugin::api, GNUNET_DATASTORE_PluginFunctions::cls, GNUNET_DATASTORE_PluginFunctions::get_expiration, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, plugin, and quota_processor().

Referenced by put_continuation().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ transmit_status()

static void transmit_status ( struct GNUNET_SERVICE_Client client,
int  code,
const char *  msg 
)
static

Transmit a status code to the client.

Parameters
clientreceiver of the response
codestatus code
msgoptional error message (can be NULL)

Definition at line 464 of file gnunet-service-datastore.c.

467{
468 struct GNUNET_MQ_Envelope *env;
469 struct StatusMessage *sm;
470 size_t slen;
471
473 "Transmitting `%s' message with value %d and message `%s'\n",
474 "STATUS",
475 code,
476 msg != NULL ? msg : "(none)");
477 slen = (msg == NULL) ? 0 : strlen (msg) + 1;
479 sm->status = htonl (code);
481 GNUNET_memcpy (&sm[1], msg, slen);
483}

References env, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_DATASTORE_STATUS, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_SERVICE_client_get_mq(), GNUNET_TIME_absolute_hton(), StatusMessage::min_expiration, min_expiration, msg, and StatusMessage::status.

Referenced by handle_release_reserve(), handle_reserve(), put_continuation(), and remove_continuation().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ transmit_item()

static int transmit_item ( void *  cls,
const struct GNUNET_HashCode key,
uint32_t  size,
const void *  data,
enum GNUNET_BLOCK_Type  type,
uint32_t  priority,
uint32_t  anonymity,
uint32_t  replication,
struct GNUNET_TIME_Absolute  expiration,
uint64_t  uid 
)
static

Function that will transmit the given datastore entry to the client.

Parameters
clsclosure, pointer to the client (of type struct GNUNET_SERVICE_Client).
keykey for the content
sizenumber of bytes in data
datacontent stored
typetype of the content
prioritypriority of the content
anonymityanonymity-level for the content
replicationreplication-level for the content
expirationexpiration time for the content
uidunique identifier for the datum; maybe 0 if no unique identifier is available
Returns
GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue, GNUNET_NO to delete the item and continue (if supported)

Definition at line 505 of file gnunet-service-datastore.c.

515{
516 struct GNUNET_SERVICE_Client *client = cls;
517 struct GNUNET_MQ_Envelope *env;
519 struct DataMessage *dm;
520
521 if (NULL == key)
522 {
523 /* transmit 'DATA_END' */
524 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting DATA_END message\n");
527 return GNUNET_OK;
528 }
531 dm->rid = htonl (0);
532 dm->size = htonl (size);
533 dm->type = htonl (type);
534 dm->priority = htonl (priority);
535 dm->anonymity = htonl (anonymity);
536 dm->replication = htonl (replication);
538 dm->uid = GNUNET_htonll (uid);
539 dm->key = *key;
540 GNUNET_memcpy (&dm[1], data, size);
541 GNUNET_log (
543 "Transmitting DATA message for `%s' of type %u with expiration %s (in: %s)\n",
544 GNUNET_h2s (key),
545 type,
548 expiration),
549 GNUNET_YES));
551 gettext_noop ("# results found"),
552 1,
553 GNUNET_NO);
555 return GNUNET_OK;
556}

References anonymity, DataMessage::anonymity, data, end, env, expiration, DataMessage::expiration, gettext_noop, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_htonll(), GNUNET_log, GNUNET_MAX_MESSAGE_SIZE, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_DATASTORE_DATA, GNUNET_MESSAGE_TYPE_DATASTORE_DATA_END, GNUNET_MQ_msg, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_OK, GNUNET_SERVICE_client_get_mq(), GNUNET_STATISTICS_update(), GNUNET_STRINGS_absolute_time_to_string(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_hton(), GNUNET_YES, key, DataMessage::key, DataMessage::priority, replication, DataMessage::replication, DataMessage::rid, size, DataMessage::size, stats, type, DataMessage::type, and DataMessage::uid.

Referenced by handle_get(), handle_get_key(), handle_get_replication(), and handle_get_zero_anonymity().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_reserve()

static void handle_reserve ( void *  cls,
const struct ReserveMessage msg 
)
static

Handle RESERVE-message.

Parameters
clsidentification of the client
msgthe actual message

Static counter to produce reservation identifiers.

Definition at line 566 of file gnunet-service-datastore.c.

567{
571 static int reservation_gen;
572 struct GNUNET_SERVICE_Client *client = cls;
573 struct ReservationList *e;
574 unsigned long long used;
575 unsigned long long req;
576 uint64_t amount;
577 uint32_t entries;
578
579 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing RESERVE request\n");
580 amount = GNUNET_ntohll (msg->amount);
581 entries = ntohl (msg->entries);
582 used = payload + reserved;
583 req =
584 amount + ((unsigned long long) GNUNET_DATASTORE_ENTRY_OVERHEAD) * entries;
585 if (used + req > quota)
586 {
587 if (quota < used)
588 used =
589 quota; /* cheat a bit for error message (to avoid negative numbers) */
590 GNUNET_log (
592 _ (
593 "Insufficient space (%llu bytes are available) to satisfy RESERVE request for %llu bytes\n"),
594 quota - used,
595 req);
596 if (cache_size < req)
597 {
598 /* TODO: document this in the FAQ; essentially, if this
599 * message happens, the insertion request could be blocked
600 * by less-important content from migration because it is
601 * larger than 1/8th of the overall available space, and
602 * we only reserve 1/8th for "fresh" insertions */
603 GNUNET_log (
605 _ (
606 "The requested amount (%llu bytes) is larger than the cache size (%llu bytes)\n"),
607 req,
608 cache_size);
610 0,
612 "Insufficient space to satisfy request and "
613 "requested amount is larger than cache size"));
614 }
615 else
616 {
618 0,
619 gettext_noop ("Insufficient space to satisfy request"));
620 }
622 return;
623 }
624 reserved += req;
626 gettext_noop ("# reserved"),
627 reserved,
628 GNUNET_NO);
629 e = GNUNET_new (struct ReservationList);
630 e->next = reservations;
631 reservations = e;
632 e->client = client;
633 e->amount = amount;
634 e->entries = entries;
635 e->rid = ++reservation_gen;
637 "Reserve space for %u entries with up to %lu bytes under rid %u\n",
638 entries,
639 amount,
640 e->rid);
641 if (reservation_gen < 0)
642 reservation_gen = 0; /* wrap around */
643 transmit_status (client, e->rid, NULL);
645}

References _, ReservationList::amount, cache_size, ReservationList::client, ReservationList::entries, gettext_noop, GNUNET_DATASTORE_ENTRY_OVERHEAD, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_new, GNUNET_NO, GNUNET_ntohll(), GNUNET_SERVICE_client_continue(), GNUNET_STATISTICS_set(), msg, ReservationList::next, payload, quota, reservations, reserved, ReservationList::rid, stats, and transmit_status().

Here is the call graph for this function:

◆ handle_release_reserve()

static void handle_release_reserve ( void *  cls,
const struct ReleaseReserveMessage msg 
)
static

Handle RELEASE_RESERVE-message.

Parameters
clsidentification of the client
msgthe actual message

Definition at line 655 of file gnunet-service-datastore.c.

656{
657 struct GNUNET_SERVICE_Client *client = cls;
658 struct ReservationList *pos;
659 struct ReservationList *prev;
660 struct ReservationList *next;
661 int rid = ntohl (msg->rid);
662 unsigned long long rem;
663
664 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing RELEASE_RESERVE request\n");
666 prev = NULL;
667 while (NULL != (pos = next))
668 {
669 next = pos->next;
670 if (rid == pos->rid)
671 {
672 if (prev == NULL)
674 else
675 prev->next = next;
676 rem =
677 pos->amount
678 + ((unsigned long long) GNUNET_DATASTORE_ENTRY_OVERHEAD) * pos->entries;
679 GNUNET_assert (reserved >= rem);
680 reserved -= rem;
682 gettext_noop ("# reserved"),
683 reserved,
684 GNUNET_NO);
686 "Returning %llu remaining reserved bytes to storage pool\n",
687 rem);
688 GNUNET_free (pos);
691 return;
692 }
693 prev = pos;
694 }
695 GNUNET_break (0);
698 gettext_noop ("Could not find matching reservation"));
700}

References ReservationList::amount, ReservationList::client, ReservationList::entries, gettext_noop, GNUNET_assert, GNUNET_break, GNUNET_DATASTORE_ENTRY_OVERHEAD, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_SERVICE_client_continue(), GNUNET_STATISTICS_set(), GNUNET_SYSERR, msg, ReservationList::next, reservations, reserved, ReservationList::rid, stats, and transmit_status().

Here is the call graph for this function:

◆ check_data()

static int check_data ( const struct DataMessage dm)
static

Check that the given message is a valid data message.

Parameters
dmmessage to check
Returns
GNUNET_SYSERR is not well-formed, otherwise GNUNET_OK

Definition at line 710 of file gnunet-service-datastore.c.

711{
712 uint16_t size;
713 uint32_t dsize;
714
715 size = ntohs (dm->header.size);
716 dsize = ntohl (dm->size);
717 if (size != dsize + sizeof(struct DataMessage))
718 {
719 GNUNET_break (0);
720 return GNUNET_SYSERR;
721 }
722 return GNUNET_OK;
723}

References GNUNET_break, GNUNET_OK, GNUNET_SYSERR, DataMessage::header, GNUNET_MessageHeader::size, size, and DataMessage::size.

Referenced by check_put(), and check_remove().

Here is the caller graph for this function:

◆ put_continuation()

static void put_continuation ( void *  cls,
const struct GNUNET_HashCode key,
uint32_t  size,
int  status,
const char *  msg 
)
static

Put continuation.

Parameters
clsclosure
keykey for the item stored
sizesize of the item stored
statusGNUNET_OK if inserted, GNUNET_NO if updated, or #GNUNET_SYSERROR if error
msgerror message on error

Definition at line 737 of file gnunet-service-datastore.c.

742{
743 struct GNUNET_SERVICE_Client *client = cls;
744
745 if (GNUNET_OK == status)
746 {
748 gettext_noop ("# bytes stored"),
749 size,
750 GNUNET_YES);
753 "Successfully stored %u bytes under key `%s'\n",
754 size,
755 GNUNET_h2s (key));
756 }
757 transmit_status (client,
759 msg);
761 {
763 _ ("Need %llu bytes more space (%llu allowed, using %llu)\n"),
764 (unsigned long long) size + GNUNET_DATASTORE_ENTRY_OVERHEAD,
765 (unsigned long long) (quota - reserved - cache_size),
766 (unsigned long long) payload);
768 }
769}

References _, cache_size, filter, gettext_noop, GNUNET_CONTAINER_bloomfilter_add(), GNUNET_DATASTORE_ENTRY_OVERHEAD, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_h2s(), GNUNET_log, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_YES, key, manage_space(), msg, payload, quota, reserved, size, stats, status, and transmit_status().

Referenced by handle_put().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_put()

static int check_put ( void *  cls,
const struct DataMessage dm 
)
static

Verify PUT-message.

Parameters
clsidentification of the client
dmthe actual message
Returns
GNUNET_OK if dm is well-formed

Definition at line 780 of file gnunet-service-datastore.c.

781{
782 if (GNUNET_OK != check_data (dm))
783 {
784 GNUNET_break (0);
785 return GNUNET_SYSERR;
786 }
787 return GNUNET_OK;
788}

References check_data(), GNUNET_break, GNUNET_OK, and GNUNET_SYSERR.

Here is the call graph for this function:

◆ handle_put()

static void handle_put ( void *  cls,
const struct DataMessage dm 
)
static

Handle PUT-message.

Parameters
clsidentification of the client
dmthe actual message

Definition at line 798 of file gnunet-service-datastore.c.

799{
800 struct GNUNET_SERVICE_Client *client = cls;
801 int rid;
802 struct ReservationList *pos;
803 uint32_t size;
804
806 "Processing PUT request for `%s' of type %u\n",
807 GNUNET_h2s (&dm->key),
808 (uint32_t) ntohl (dm->type));
809 rid = ntohl (dm->rid);
810 size = ntohl (dm->size);
812 "Put entry into space with %u bytes under rid %u\n",
813 size,
814 rid);
815 if (rid > 0)
816 {
817 pos = reservations;
818 while ((NULL != pos) && (rid != pos->rid))
819 pos = pos->next;
820 GNUNET_break (pos != NULL);
821 if (NULL != pos)
822 {
823 GNUNET_break (pos->entries > 0);
824 GNUNET_break (pos->amount >= size);
825 pos->entries--;
826 pos->amount -= size;
829 gettext_noop ("# reserved"),
830 reserved,
831 GNUNET_NO);
832 }
833 }
834 {
835 bool absent =
837 plugin->api->put (plugin->api->cls,
838 &dm->key,
839 absent,
840 size,
841 &dm[1],
842 ntohl (dm->type),
843 ntohl (dm->priority),
844 ntohl (dm->anonymity),
845 ntohl (dm->replication),
848 client);
849 }
851}

References ReservationList::amount, DataMessage::anonymity, DatastorePlugin::api, ReservationList::client, GNUNET_DATASTORE_PluginFunctions::cls, ReservationList::entries, DataMessage::expiration, filter, gettext_noop, GNUNET_break, GNUNET_CONTAINER_bloomfilter_test(), GNUNET_DATASTORE_ENTRY_OVERHEAD, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_STATISTICS_set(), GNUNET_TIME_absolute_ntoh(), DataMessage::key, ReservationList::next, plugin, DataMessage::priority, GNUNET_DATASTORE_PluginFunctions::put, put_continuation(), DataMessage::replication, reservations, reserved, DataMessage::rid, ReservationList::rid, size, DataMessage::size, stats, and DataMessage::type.

Here is the call graph for this function:

◆ handle_get()

static void handle_get ( void *  cls,
const struct GetMessage msg 
)
static

Handle GNUNET_MESSAGE_TYPE_DATASTORE_GET-message.

Parameters
clsidentification of the client
msgthe actual message

Definition at line 861 of file gnunet-service-datastore.c.

862{
863 struct GNUNET_SERVICE_Client *client = cls;
864
866 "Processing GET request of type %u\n",
867 (uint32_t) ntohl (msg->type));
869 gettext_noop ("# GET requests received"),
870 1,
871 GNUNET_NO);
873 GNUNET_ntohll (msg->next_uid),
874 msg->random,
875 NULL,
876 ntohl (msg->type),
878 client);
880}

References DatastorePlugin::api, GNUNET_DATASTORE_PluginFunctions::cls, GNUNET_DATASTORE_PluginFunctions::get_key, gettext_noop, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_ntohll(), GNUNET_SERVICE_client_continue(), GNUNET_STATISTICS_update(), msg, plugin, stats, transmit_item(), and GNUNET_MessageHeader::type.

Here is the call graph for this function:

◆ handle_get_key()

static void handle_get_key ( void *  cls,
const struct GetKeyMessage msg 
)
static

Handle GNUNET_MESSAGE_TYPE_DATASTORE_GET_KEY-message.

Parameters
clsclosure
msgthe actual message

Definition at line 890 of file gnunet-service-datastore.c.

891{
892 struct GNUNET_SERVICE_Client *client = cls;
893
895 "Processing GET request for `%s' of type %u\n",
896 GNUNET_h2s (&msg->key),
897 (uint32_t) ntohl (msg->type));
899 gettext_noop ("# GET KEY requests received"),
900 1,
901 GNUNET_NO);
903 {
904 /* don't bother database... */
906 "Empty result set for GET request for `%s' (bloomfilter).\n",
907 GNUNET_h2s (&msg->key));
910 "# requests filtered by bloomfilter"),
911 1,
912 GNUNET_NO);
913 transmit_item (client,
914 NULL,
915 0,
916 NULL,
917 0,
918 0,
919 0,
920 0,
922 0);
924 return;
925 }
927 GNUNET_ntohll (msg->next_uid),
928 msg->random,
929 &msg->key,
930 ntohl (msg->type),
932 client);
934}

References DatastorePlugin::api, GNUNET_DATASTORE_PluginFunctions::cls, filter, GNUNET_DATASTORE_PluginFunctions::get_key, gettext_noop, GNUNET_CONTAINER_bloomfilter_test(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_NO, GNUNET_ntohll(), GNUNET_SERVICE_client_continue(), GNUNET_STATISTICS_update(), GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_YES, msg, plugin, stats, transmit_item(), and GNUNET_MessageHeader::type.

Here is the call graph for this function:

◆ handle_get_replication()

static void handle_get_replication ( void *  cls,
const struct GNUNET_MessageHeader message 
)
static

Handle GET_REPLICATION-message.

Parameters
clsidentification of the client
messagethe actual message

Definition at line 944 of file gnunet-service-datastore.c.

945{
946 struct GNUNET_SERVICE_Client *client = cls;
947
948 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing GET_REPLICATION request\n");
951 "# GET REPLICATION requests received"),
952 1,
953 GNUNET_NO);
956}

References DatastorePlugin::api, GNUNET_DATASTORE_PluginFunctions::cls, GNUNET_DATASTORE_PluginFunctions::get_replication, gettext_noop, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_STATISTICS_update(), plugin, stats, and transmit_item().

Here is the call graph for this function:

◆ handle_get_zero_anonymity()

static void handle_get_zero_anonymity ( void *  cls,
const struct GetZeroAnonymityMessage msg 
)
static

Handle GET_ZERO_ANONYMITY-message.

Parameters
clsclient identification of the client
msgthe actual message

Definition at line 966 of file gnunet-service-datastore.c.

967{
968 struct GNUNET_SERVICE_Client *client = cls;
970
971 type = ntohl (msg->type);
973 {
974 GNUNET_break (0);
976 return;
977 }
979 "Processing GET_ZERO_ANONYMITY request\n");
982 "# GET ZERO ANONYMITY requests received"),
983 1,
984 GNUNET_NO);
986 GNUNET_ntohll (msg->next_uid),
987 type,
989 client);
991}

References DatastorePlugin::api, GNUNET_DATASTORE_PluginFunctions::cls, GNUNET_DATASTORE_PluginFunctions::get_zero_anonymity, gettext_noop, GNUNET_BLOCK_TYPE_ANY, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_ntohll(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_STATISTICS_update(), msg, plugin, stats, transmit_item(), type, and GNUNET_MessageHeader::type.

Here is the call graph for this function:

◆ remove_continuation()

static void remove_continuation ( void *  cls,
const struct GNUNET_HashCode key,
uint32_t  size,
int  status,
const char *  msg 
)
static

Remove continuation.

Parameters
clsclosure
keykey for the content
sizenumber of bytes in data
statusGNUNET_OK if removed, GNUNET_NO if not found, or #GNUNET_SYSERROR if error
msgerror message on error

Definition at line 1005 of file gnunet-service-datastore.c.

1010{
1011 struct GNUNET_SERVICE_Client *client = cls;
1012
1013 if (GNUNET_SYSERR == status)
1014 {
1015 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "REMOVE request failed: %s.\n", msg);
1016 transmit_status (client, GNUNET_NO, msg);
1017 return;
1018 }
1019 if (GNUNET_NO == status)
1020 {
1022 "Content not found for REMOVE request.\n");
1023 transmit_status (client, GNUNET_NO, _ ("Content not found"));
1024 return;
1025 }
1027 "Item matches REMOVE request for key `%s'.\n",
1028 GNUNET_h2s (key));
1030 gettext_noop ("# bytes removed (explicit request)"),
1031 size,
1032 GNUNET_YES);
1034 transmit_status (client, GNUNET_OK, NULL);
1035}

References _, filter, gettext_noop, GNUNET_CONTAINER_bloomfilter_remove(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_h2s(), GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_YES, key, msg, size, stats, status, and transmit_status().

Referenced by handle_remove().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_remove()

static int check_remove ( void *  cls,
const struct DataMessage dm 
)
static

Verify REMOVE-message.

Parameters
clsidentification of the client
dmthe actual message
Returns
GNUNET_OK if dm is well-formed

Definition at line 1046 of file gnunet-service-datastore.c.

1047{
1048 if (GNUNET_OK != check_data (dm))
1049 {
1050 GNUNET_break (0);
1051 return GNUNET_SYSERR;
1052 }
1053 return GNUNET_OK;
1054}

References check_data(), GNUNET_break, GNUNET_OK, and GNUNET_SYSERR.

Here is the call graph for this function:

◆ handle_remove()

static void handle_remove ( void *  cls,
const struct DataMessage dm 
)
static

Handle REMOVE-message.

Parameters
clsclosure
dmthe actual message

Definition at line 1064 of file gnunet-service-datastore.c.

1065{
1066 struct GNUNET_SERVICE_Client *client = cls;
1067
1069 gettext_noop ("# REMOVE requests received"),
1070 1,
1071 GNUNET_NO);
1073 "Processing REMOVE request for `%s'\n",
1074 GNUNET_h2s (&dm->key));
1076 &dm->key,
1077 ntohl (dm->size),
1078 &dm[1],
1080 client);
1082}

References DatastorePlugin::api, GNUNET_DATASTORE_PluginFunctions::cls, gettext_noop, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_STATISTICS_update(), DataMessage::key, plugin, remove_continuation(), GNUNET_DATASTORE_PluginFunctions::remove_key, DataMessage::size, and stats.

Here is the call graph for this function:

◆ handle_drop()

static void handle_drop ( void *  cls,
const struct GNUNET_MessageHeader message 
)
static

Handle DROP-message.

Parameters
clsidentification of the client
messagethe actual message

Definition at line 1092 of file gnunet-service-datastore.c.

1094{
1095 struct GNUNET_SERVICE_Client *client = cls;
1096
1098 "Processing DROP request\n");
1101}

References do_drop, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_SERVICE_client_continue(), and GNUNET_YES.

Here is the call graph for this function:

◆ disk_utilization_change_cb()

static void disk_utilization_change_cb ( void *  cls,
int  delta 
)
static

Function called by plugins to notify us about a change in their disk utilization.

Parameters
clsclosure (NULL)
deltachange in disk utilization, 0 for "reset to empty"

Definition at line 1113 of file gnunet-service-datastore.c.

1114{
1115 if ((delta < 0) && (payload < -delta))
1116 {
1117 GNUNET_log (
1119 _ (
1120 "Datastore payload must have been inaccurate (%lld < %lld). Recomputing it.\n"),
1121 (long long) payload,
1122 (long long) -delta);
1125 _ ("New payload: %lld\n"),
1126 (long long) payload);
1127 sync_stats ();
1128 return;
1129 }
1130 payload += delta;
1131 last_sync++;
1133 sync_stats ();
1134}

References _, DatastorePlugin::api, GNUNET_DATASTORE_PluginFunctions::cls, delta, GNUNET_DATASTORE_PluginFunctions::estimate_size, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, last_sync, MAX_STAT_SYNC_LAG, payload, plugin, and sync_stats().

Referenced by load_plugin().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_stat_in()

static int process_stat_in ( void *  cls,
const char *  subsystem,
const char *  name,
uint64_t  value,
int  is_persistent 
)
static

Callback function to process statistic values.

Parameters
clsclosure (struct Plugin*)
subsystemname of subsystem that created the statistic
namethe name of the datum
valuethe current value
is_persistentGNUNET_YES if the value is persistent, GNUNET_NO if not
Returns
GNUNET_OK to continue, GNUNET_SYSERR to abort iteration

Definition at line 1148 of file gnunet-service-datastore.c.

1153{
1156 payload += value;
1157 GNUNET_log (
1159 "Notification from statistics about existing payload (%llu), new payload is %llu\n",
1160 (unsigned long long) value,
1161 (unsigned long long) payload);
1162 return GNUNET_OK;
1163}

References GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_YES, payload, stats_worked, and value.

Referenced by run().

Here is the caller graph for this function:

◆ load_plugin()

static struct DatastorePlugin * load_plugin ( )
static

Load the datastore plugin.

Definition at line 1170 of file gnunet-service-datastore.c.

1171{
1172 struct DatastorePlugin *ret;
1173 char *libname;
1174
1175 ret = GNUNET_new (struct DatastorePlugin);
1176 ret->env.cfg = cfg;
1177 ret->env.duc = &disk_utilization_change_cb;
1178 ret->env.cls = NULL;
1180 _ ("Loading `%s' datastore plugin\n"),
1181 plugin_name);
1182 GNUNET_asprintf (&libname,
1183 "libgnunet_plugin_datastore_%s",
1184 plugin_name);
1185 ret->short_name = GNUNET_strdup (plugin_name);
1186 ret->lib_name = libname;
1188 libname,
1189 &ret->env);
1190 if (NULL == ret->api)
1191 {
1193 _ ("Failed to load datastore plugin for `%s'\n"),
1194 plugin_name);
1195 GNUNET_free (ret->short_name);
1196 GNUNET_free (libname);
1197 GNUNET_free (ret);
1198 return NULL;
1199 }
1200 return ret;
1201}

References _, cfg, disk_utilization_change_cb(), GNUNET_asprintf(), GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_log, GNUNET_new, GNUNET_OS_project_data_gnunet(), GNUNET_PLUGIN_load(), GNUNET_strdup, plugin_name, and ret.

Referenced by process_stat_done().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ unload_plugin()

static void unload_plugin ( struct DatastorePlugin plug)
static

Function called when the service shuts down.

Unloads our datastore plugin.

Parameters
plugplugin to unload

Definition at line 1211 of file gnunet-service-datastore.c.

1212{
1214 "Datastore service is unloading plugin...\n");
1215 GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
1216 GNUNET_free (plug->lib_name);
1217 GNUNET_free (plug->short_name);
1218 GNUNET_free (plug);
1219}

References DatastorePlugin::api, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_PLUGIN_unload(), DatastorePlugin::lib_name, and DatastorePlugin::short_name.

Referenced by cleaning_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ begin_service()

static void begin_service ( )
static

Initialization complete, start operating the service.

Definition at line 1226 of file gnunet-service-datastore.c.

References delete_expired(), expired_kill_task, GNUNET_SCHEDULER_add_with_priority(), GNUNET_SCHEDULER_PRIORITY_IDLE, GNUNET_SERVICE_resume(), and service.

Referenced by add_key_to_bloomfilter(), and process_stat_done().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_key_to_bloomfilter()

static void add_key_to_bloomfilter ( void *  cls,
const struct GNUNET_HashCode key,
unsigned int  count 
)
static

Adds a given key to the bloomfilter in cls count times.

Parameters
clsthe bloomfilter
keykey to add
countnumber of times to add key

Definition at line 1244 of file gnunet-service-datastore.c.

1247{
1248 struct GNUNET_CONTAINER_BloomFilter *bf = cls;
1249
1250 if (NULL == key)
1251 {
1253 _ ("Bloomfilter construction complete.\n"));
1254 begin_service ();
1255 return;
1256 }
1257
1258 while (0 < count--)
1260}

References _, begin_service(), GNUNET_CONTAINER_bloomfilter_add(), GNUNET_ERROR_TYPE_INFO, GNUNET_log, and key.

Referenced by process_stat_done().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_stat_done()

static void process_stat_done ( void *  cls,
int  success 
)
static

We finished receiving the statistic.

Initialize the plugin; if loading the statistic failed, run the estimator.

Parameters
clsNULL
successGNUNET_NO if we failed to read the stat

Definition at line 1271 of file gnunet-service-datastore.c.

1272{
1273 stat_get = NULL;
1274 if (NULL != stat_timeout_task)
1275 {
1277 stat_timeout_task = NULL;
1278 }
1279 plugin = load_plugin ();
1280 if (NULL == plugin)
1281 {
1283 filter = NULL;
1284 if (NULL != stats)
1285 {
1287 stats = NULL;
1288 }
1289 return;
1290 }
1291
1292 if (GNUNET_NO == stats_worked)
1293 {
1295 "Failed to obtain value from statistics service, recomputing it\n");
1298 _ ("New payload: %lld\n"),
1299 (long long) payload);
1300 }
1301
1302 if (GNUNET_YES == refresh_bf)
1303 {
1305 _ ("Rebuilding bloomfilter. Please be patient.\n"));
1306 if (NULL != plugin->api->get_keys)
1307 {
1309 return;
1310 }
1311 else
1312 {
1314 _ (
1315 "Plugin does not support get_keys function. Please fix!\n"))
1316 ;
1317 }
1318 }
1319 begin_service ();
1320}

References _, add_key_to_bloomfilter(), DatastorePlugin::api, begin_service(), GNUNET_DATASTORE_PluginFunctions::cls, GNUNET_DATASTORE_PluginFunctions::estimate_size, filter, GNUNET_DATASTORE_PluginFunctions::get_keys, GNUNET_CONTAINER_bloomfilter_free(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_NO, GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_destroy(), GNUNET_YES, load_plugin(), payload, plugin, refresh_bf, stat_get, stat_timeout_task, stats, and stats_worked.

Referenced by run(), and stat_timeout().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ stat_timeout()

static void stat_timeout ( void *  cls)
static

Fetching stats took to long, run without.

Parameters
clsNULL

Definition at line 1329 of file gnunet-service-datastore.c.

1330{
1331 stat_timeout_task = NULL;
1334}

References GNUNET_NO, GNUNET_STATISTICS_get_cancel(), process_stat_done(), stat_get, and stat_timeout_task.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cleaning_task()

static void cleaning_task ( void *  cls)
static

Task run during shutdown.

Definition at line 1341 of file gnunet-service-datastore.c.

1342{
1344 if (NULL != expired_kill_task)
1345 {
1347 expired_kill_task = NULL;
1348 }
1349 if (GNUNET_YES == do_drop)
1350 {
1352 "Dropping database!\n");
1353 plugin->api->drop (plugin->api->cls);
1354 payload = 0;
1355 last_sync++;
1356 }
1357 if (NULL != plugin)
1358 {
1360 plugin = NULL;
1361 }
1362 if (NULL != filter)
1363 {
1365 filter = NULL;
1366 }
1367 if (NULL != stat_get)
1368 {
1370 stat_get = NULL;
1371 }
1372 if (NULL != stat_timeout_task)
1373 {
1375 stat_timeout_task = NULL;
1376 }
1378 plugin_name = NULL;
1379 if (last_sync > 0)
1380 sync_stats ();
1381 if (NULL != stats)
1382 {
1384 stats = NULL;
1385 }
1387 quota_stat_name = NULL;
1388}

References DatastorePlugin::api, cleaning_done, GNUNET_DATASTORE_PluginFunctions::cls, do_drop, GNUNET_DATASTORE_PluginFunctions::drop, expired_kill_task, filter, GNUNET_CONTAINER_bloomfilter_free(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_destroy(), GNUNET_STATISTICS_get_cancel(), GNUNET_YES, last_sync, payload, plugin, plugin_name, quota_stat_name, stat_get, stat_timeout_task, stats, sync_stats(), and unload_plugin().

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ client_connect_cb()

static void * client_connect_cb ( void *  cls,
struct GNUNET_SERVICE_Client client,
struct GNUNET_MQ_Handle mq 
)
static

Add a client to our list of active clients.

Parameters
clsNULL
clientclient to add
mqmessage queue for client
Returns
client

Definition at line 1400 of file gnunet-service-datastore.c.

1403{
1404 return client;
1405}

◆ client_disconnect_cb()

static void client_disconnect_cb ( void *  cls,
struct GNUNET_SERVICE_Client client,
void *  app_ctx 
)
static

Called whenever a client is disconnected.

Frees our resources associated with that client.

Parameters
clsclosure
clientidentification of the client
app_ctxmust match client

Definition at line 1417 of file gnunet-service-datastore.c.

1420{
1421 struct ReservationList *pos;
1422 struct ReservationList *prev;
1423 struct ReservationList *next;
1424
1425 GNUNET_assert (app_ctx == client);
1426 prev = NULL;
1427 pos = reservations;
1428 while (NULL != pos)
1429 {
1430 next = pos->next;
1431 if (pos->client == client)
1432 {
1433 if (NULL == prev)
1435 else
1436 prev->next = next;
1438 GNUNET_free (pos);
1439 }
1440 else
1441 {
1442 prev = pos;
1443 }
1444 pos = next;
1445 }
1447 gettext_noop ("# reserved"),
1448 reserved,
1449 GNUNET_NO);
1450}

References ReservationList::amount, ReservationList::client, ReservationList::entries, gettext_noop, GNUNET_assert, GNUNET_DATASTORE_ENTRY_OVERHEAD, GNUNET_free, GNUNET_NO, GNUNET_STATISTICS_set(), ReservationList::next, reservations, reserved, and stats.

Here is the call graph for this function:

◆ run()

static void run ( void *  cls,
const struct GNUNET_CONFIGURATION_Handle c,
struct GNUNET_SERVICE_Handle serv 
)
static

Process datastore requests.

Parameters
clsclosure
servthe initialized service
cconfiguration to use

Definition at line 1461 of file gnunet-service-datastore.c.

1464{
1465 char *fn;
1466 char *pfn;
1467 unsigned int bf_size;
1468
1469 service = serv;
1470 cfg = c;
1472 "DATASTORE",
1473 "DATABASE",
1474 &plugin_name))
1475 {
1477 "DATABASE",
1478 "DATASTORE");
1479 return;
1480 }
1482 _ ("# bytes used in file-sharing datastore `%s'"),
1483 plugin_name);
1484 if (GNUNET_OK !=
1485 GNUNET_CONFIGURATION_get_value_size (cfg, "DATASTORE", "QUOTA", &quota))
1486 {
1487 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "QUOTA", "DATASTORE");
1488 return;
1489 }
1490 stats = GNUNET_STATISTICS_create ("datastore", cfg);
1492 cache_size = quota / 8; /* Or should we make this an option? */
1494 gettext_noop ("# cache size"),
1495 cache_size,
1496 GNUNET_NO);
1497 if (quota / (32 * 1024LL) > MAX_BF_SIZE)
1498 bf_size = MAX_BF_SIZE;
1499 else
1500 bf_size =
1501 quota / (32 * 1024LL); /* 8 bit per entry, 1 bit per 32 kb in DB */
1502 fn = NULL;
1504 "DATASTORE",
1505 "BLOOMFILTER",
1506 &fn)) ||
1508 {
1510 _ ("Could not use specified filename `%s' for bloomfilter.\n"),
1511 NULL != fn ? fn : "");
1512 GNUNET_free (fn);
1513 fn = NULL;
1514 }
1515 if (NULL != fn)
1516 {
1517 GNUNET_asprintf (&pfn, "%s.%s", fn, plugin_name);
1518 if (GNUNET_YES == GNUNET_DISK_file_test (pfn))
1519 {
1520 filter =
1522 bf_size,
1523 5); /* approx. 3% false positives at max use */
1524 if (NULL == filter)
1525 {
1526 /* file exists but not valid, remove and try again, but refresh */
1527 if (0 != unlink (pfn))
1528 {
1529 /* failed to remove, run without file */
1531 _ ("Failed to remove bogus bloomfilter file `%s'\n"),
1532 pfn);
1533 GNUNET_free (pfn);
1534 pfn = NULL;
1536 NULL,
1537 bf_size,
1538 5); /* approx. 3% false positives at max use */
1540 }
1541 else
1542 {
1543 /* try again after remove */
1545 pfn,
1546 bf_size,
1547 5); /* approx. 3% false positives at max use */
1549 if (NULL == filter)
1550 {
1551 /* failed yet again, give up on using file */
1553 _ ("Failed to remove bogus bloomfilter file `%s'\n"),
1554 pfn);
1555 GNUNET_free (pfn);
1556 pfn = NULL;
1558 NULL,
1559 bf_size,
1560 5); /* approx. 3% false positives at max use */
1561 }
1562 }
1563 }
1564 else
1565 {
1566 /* normal case: have an existing valid bf file, no need to refresh */
1568 }
1569 }
1570 else
1571 {
1572 filter =
1574 bf_size,
1575 5); /* approx. 3% false positives at max use */
1577 }
1578 GNUNET_free (pfn);
1579 }
1580 else
1581 {
1582 filter =
1584 bf_size,
1585 5); /* approx. 3% false positives at max use */
1587 }
1588 GNUNET_free (fn);
1589 if (NULL == filter)
1590 {
1592 _ ("Failed to initialize bloomfilter.\n"));
1593 if (NULL != stats)
1594 {
1596 stats = NULL;
1597 }
1598 return;
1599 }
1602 "datastore",
1606 NULL);
1607 if (NULL == stat_get)
1609 else
1611 &stat_timeout,
1612 NULL);
1614}

References _, cache_size, cfg, cleaning_task(), filter, gettext_noop, GNUNET_asprintf(), GNUNET_CONFIGURATION_get_value_filename(), GNUNET_CONFIGURATION_get_value_size(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONTAINER_bloomfilter_init(), GNUNET_CONTAINER_bloomfilter_load(), GNUNET_DISK_directory_create_for_file(), GNUNET_DISK_file_test(), GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_log_config_missing(), GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_add_shutdown(), GNUNET_SERVICE_suspend(), GNUNET_STATISTICS_create(), GNUNET_STATISTICS_destroy(), GNUNET_STATISTICS_get(), GNUNET_STATISTICS_set(), GNUNET_SYSERR, GNUNET_TIME_UNIT_SECONDS, GNUNET_YES, MAX_BF_SIZE, plugin_name, process_stat_done(), process_stat_in(), quota, quota_stat_name, refresh_bf, service, stat_get, stat_timeout(), stat_timeout_task, and stats.

Here is the call graph for this function:

◆ GNUNET_SERVICE_MAIN()

Variable Documentation

◆ quota_stat_name

char* quota_stat_name
static

Name under which we store current space consumption.

Definition at line 61 of file gnunet-service-datastore.c.

Referenced by cleaning_task(), run(), and sync_stats().

◆ stat_timeout_task

struct GNUNET_SCHEDULER_Task* stat_timeout_task
static

Task to timeout stat GET.

Definition at line 66 of file gnunet-service-datastore.c.

Referenced by cleaning_task(), GNUNET_HOSTLIST_client_start(), process_stat_done(), run(), and stat_timeout().

◆ plugin

◆ reservations

struct ReservationList* reservations
static

Linked list of space reservations made by clients.

Definition at line 144 of file gnunet-service-datastore.c.

Referenced by client_disconnect_cb(), handle_put(), handle_release_reserve(), and handle_reserve().

◆ filter

◆ plugin_name

char* plugin_name
static

Name of our plugin.

Definition at line 154 of file gnunet-service-datastore.c.

Referenced by cleaning_task(), load_plugin(), and run().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Our configuration.

Definition at line 159 of file gnunet-service-datastore.c.

Referenced by load_plugin(), and run().

◆ stats

◆ cache_size

unsigned long long cache_size
static

How much space are we using for the cache? (space available for insertions that will be instantly reclaimed by discarding less important content — or possibly whatever we just inserted into the "cache").

Definition at line 172 of file gnunet-service-datastore.c.

Referenced by handle_reserve(), put_continuation(), and run().

◆ reserved

unsigned long long reserved
static

How much space have we currently reserved?

Definition at line 177 of file gnunet-service-datastore.c.

Referenced by client_disconnect_cb(), handle_put(), handle_release_reserve(), handle_reserve(), and put_continuation().

◆ payload

◆ expired_kill_task

struct GNUNET_SCHEDULER_Task* expired_kill_task
static

Identity of the task that is used to delete expired content.

Definition at line 189 of file gnunet-service-datastore.c.

Referenced by begin_service(), cleaning_task(), delete_expired(), and expired_processor().

◆ min_expiration

struct GNUNET_TIME_Absolute min_expiration
static

Minimum time that content should have to not be discarded instantly (time stamp of any content that we've been discarding recently to stay below the quota).

FOREVER if we had to expire content with non-zero priority.

Definition at line 197 of file gnunet-service-datastore.c.

Referenced by expired_processor(), put_migration_continuation(), quota_processor(), and transmit_status().

◆ quota

unsigned long long quota
static

How much space are we allowed to use?

Definition at line 202 of file gnunet-service-datastore.c.

Referenced by GNUNET_DATACACHE_create(), handle_reserve(), put_continuation(), and run().

◆ do_drop

int do_drop
static

Should the database be dropped on exit?

Definition at line 207 of file gnunet-service-datastore.c.

Referenced by cleaning_task(), and handle_drop().

◆ refresh_bf

int refresh_bf
static

Should we refresh the BF when the DB is loaded?

Definition at line 212 of file gnunet-service-datastore.c.

Referenced by process_stat_done(), and run().

◆ last_sync

unsigned int last_sync
static

Number of updates that were made to the payload value since we last synchronized it with the statistics service.

Definition at line 219 of file gnunet-service-datastore.c.

Referenced by cleaning_task(), disk_utilization_change_cb(), and sync_stats().

◆ stats_worked

int stats_worked
static

Did we get an answer from statistics?

Definition at line 224 of file gnunet-service-datastore.c.

Referenced by process_stat_done(), and process_stat_in().

◆ cleaning_done

int cleaning_done
static

Have we already cleaned up the TCCs and are hence no longer willing (or able) to transmit anything to anyone?

Definition at line 247 of file gnunet-service-datastore.c.

Referenced by cleaning_task().

◆ stat_get

struct GNUNET_STATISTICS_GetHandle* stat_get
static

Handle for pending get request.

Definition at line 252 of file gnunet-service-datastore.c.

Referenced by cleaning_task(), process_stat_done(), run(), and stat_timeout().

◆ service

struct GNUNET_SERVICE_Handle* service
static

Handle to our server.

Definition at line 257 of file gnunet-service-datastore.c.

Referenced by begin_service(), and run().