GNUnet  0.10.x
gnunet-service-datastore.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2004-2014, 2016 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_protocols.h"
32 #include "datastore.h"
33 
37 #define MAX_PENDING 1024
38 
42 #define MAX_BF_SIZE ((uint32_t)(1LL << 31))
43 
48 #define MAX_EXPIRE_DELAY \
49  GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 15)
50 
55 #define MIN_EXPIRE_DELAY \
56  GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 1)
57 
61 static char *quota_stat_name;
62 
67 
72 #define MAX_STAT_SYNC_LAG 50
73 
74 
84 
88  char *short_name;
89 
93  char *lib_name;
94 
100 };
101 
102 
111 
116 
120  uint64_t amount;
121 
125  uint64_t entries;
126 
130  int32_t rid;
131 };
132 
133 
137 static struct DatastorePlugin *plugin;
138 
143 
148 
152 static char *plugin_name;
153 
157 static const struct GNUNET_CONFIGURATION_Handle *cfg;
158 
163 
170 static unsigned long long cache_size;
171 
175 static unsigned long long reserved;
176 
181 static unsigned long long payload;
182 
188 
196 
200 static unsigned long long quota;
201 
205 static int do_drop;
206 
210 static int refresh_bf;
211 
217 static unsigned int last_sync;
218 
222 static int stats_worked;
223 
224 
229 static void
231 {
233  GNUNET_STATISTICS_set(stats,
234  "# utilization by current datastore",
235  payload,
236  GNUNET_NO);
237  last_sync = 0;
238 }
239 
240 
245 static int cleaning_done;
246 
251 
256 
265 static void
266 delete_expired(void *cls);
267 
268 
290 static int
292  const struct GNUNET_HashCode *key,
293  uint32_t size,
294  const void *data,
295  enum GNUNET_BLOCK_Type type,
296  uint32_t priority,
297  uint32_t anonymity,
298  uint32_t replication,
300  uint64_t uid)
301 {
302  struct GNUNET_TIME_Absolute now;
303 
304  if (NULL == key)
305  {
306  expired_kill_task =
310  NULL);
311  return GNUNET_SYSERR;
312  }
313  now = GNUNET_TIME_absolute_get();
314  if (expiration.abs_value_us > now.abs_value_us)
315  {
316  /* finished processing */
317  expired_kill_task =
321  NULL);
322  return GNUNET_SYSERR;
323  }
325  "Deleting content `%s' of type %u that expired %s ago\n",
326  GNUNET_h2s(key),
327  type,
329  GNUNET_TIME_absolute_get_difference(expiration, now),
330  GNUNET_YES));
331  min_expiration = now;
333  gettext_noop("# bytes expired"),
334  size,
335  GNUNET_YES);
337  expired_kill_task =
341  NULL);
342  return GNUNET_NO;
343 }
344 
345 
354 static void
355 delete_expired(void *cls)
356 {
357  expired_kill_task = NULL;
358  plugin->api->get_expiration(plugin->api->cls, &expired_processor, NULL);
359 }
360 
361 
381 static int
382 quota_processor(void *cls,
383  const struct GNUNET_HashCode *key,
384  uint32_t size,
385  const void *data,
386  enum GNUNET_BLOCK_Type type,
387  uint32_t priority,
388  uint32_t anonymity,
389  uint32_t replication,
391  uint64_t uid)
392 {
393  unsigned long long *need = cls;
394 
395  if (NULL == key)
396  return GNUNET_SYSERR;
397  GNUNET_log(
399  "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",
400  (unsigned long long)(size + GNUNET_DATASTORE_ENTRY_OVERHEAD),
401  (unsigned int)priority,
402  GNUNET_h2s(key),
403  type,
405  expiration),
406  GNUNET_YES),
407  *need);
408  if (size + GNUNET_DATASTORE_ENTRY_OVERHEAD > *need)
409  *need = 0;
410  else
411  *need -= size + GNUNET_DATASTORE_ENTRY_OVERHEAD;
412  if (priority > 0)
414  else
417  gettext_noop("# bytes purged (low-priority)"),
418  size,
419  GNUNET_YES);
421  return GNUNET_NO;
422 }
423 
424 
437 static void
438 manage_space(unsigned long long need)
439 {
440  unsigned long long last;
441 
443  "Asked to free up %llu bytes of cache space\n",
444  need);
445  last = 0;
446  while ((need > 0) && (last != need))
447  {
448  last = need;
449  plugin->api->get_expiration(plugin->api->cls, &quota_processor, &need);
450  }
451 }
452 
453 
461 static void
463  int code,
464  const char *msg)
465 {
466  struct GNUNET_MQ_Envelope *env;
467  struct StatusMessage *sm;
468  size_t slen;
469 
471  "Transmitting `%s' message with value %d and message `%s'\n",
472  "STATUS",
473  code,
474  msg != NULL ? msg : "(none)");
475  slen = (msg == NULL) ? 0 : strlen(msg) + 1;
477  sm->status = htonl(code);
479  GNUNET_memcpy(&sm[1], msg, slen);
481 }
482 
483 
502 static int
503 transmit_item(void *cls,
504  const struct GNUNET_HashCode *key,
505  uint32_t size,
506  const void *data,
507  enum GNUNET_BLOCK_Type type,
508  uint32_t priority,
509  uint32_t anonymity,
510  uint32_t replication,
512  uint64_t uid)
513 {
514  struct GNUNET_SERVICE_Client *client = cls;
515  struct GNUNET_MQ_Envelope *env;
516  struct GNUNET_MessageHeader *end;
517  struct DataMessage *dm;
518 
519  if (NULL == key)
520  {
521  /* transmit 'DATA_END' */
522  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Transmitting DATA_END message\n");
525  return GNUNET_OK;
526  }
527  GNUNET_assert(sizeof(struct DataMessage) + size < GNUNET_MAX_MESSAGE_SIZE);
529  dm->rid = htonl(0);
530  dm->size = htonl(size);
531  dm->type = htonl(type);
532  dm->priority = htonl(priority);
533  dm->anonymity = htonl(anonymity);
534  dm->replication = htonl(replication);
535  dm->expiration = GNUNET_TIME_absolute_hton(expiration);
536  dm->uid = GNUNET_htonll(uid);
537  dm->key = *key;
538  GNUNET_memcpy(&dm[1], data, size);
539  GNUNET_log(
541  "Transmitting DATA message for `%s' of type %u with expiration %s (in: %s)\n",
542  GNUNET_h2s(key),
543  type,
546  expiration),
547  GNUNET_YES));
549  gettext_noop("# results found"),
550  1,
551  GNUNET_NO);
553  return GNUNET_OK;
554 }
555 
556 
563 static void
564 handle_reserve(void *cls, const struct ReserveMessage *msg)
565 {
569  static int reservation_gen;
570  struct GNUNET_SERVICE_Client *client = cls;
571  struct ReservationList *e;
572  unsigned long long used;
573  unsigned long long req;
574  uint64_t amount;
575  uint32_t entries;
576 
577  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Processing RESERVE request\n");
578  amount = GNUNET_ntohll(msg->amount);
579  entries = ntohl(msg->entries);
580  used = payload + reserved;
581  req =
582  amount + ((unsigned long long)GNUNET_DATASTORE_ENTRY_OVERHEAD) * entries;
583  if (used + req > quota)
584  {
585  if (quota < used)
586  used =
587  quota; /* cheat a bit for error message (to avoid negative numbers) */
588  GNUNET_log(
590  _(
591  "Insufficient space (%llu bytes are available) to satisfy RESERVE request for %llu bytes\n"),
592  quota - used,
593  req);
594  if (cache_size < req)
595  {
596  /* TODO: document this in the FAQ; essentially, if this
597  * message happens, the insertion request could be blocked
598  * by less-important content from migration because it is
599  * larger than 1/8th of the overall available space, and
600  * we only reserve 1/8th for "fresh" insertions */
601  GNUNET_log(
603  _(
604  "The requested amount (%llu bytes) is larger than the cache size (%llu bytes)\n"),
605  req,
606  cache_size);
607  transmit_status(client,
608  0,
609  gettext_noop(
610  "Insufficient space to satisfy request and "
611  "requested amount is larger than cache size"));
612  }
613  else
614  {
615  transmit_status(client,
616  0,
617  gettext_noop("Insufficient space to satisfy request"));
618  }
620  return;
621  }
622  reserved += req;
623  GNUNET_STATISTICS_set(stats,
624  gettext_noop("# reserved"),
625  reserved,
626  GNUNET_NO);
627  e = GNUNET_new(struct ReservationList);
628  e->next = reservations;
629  reservations = e;
630  e->client = client;
631  e->amount = amount;
632  e->entries = entries;
633  e->rid = ++reservation_gen;
634  if (reservation_gen < 0)
635  reservation_gen = 0; /* wrap around */
636  transmit_status(client, e->rid, NULL);
638 }
639 
640 
647 static void
649 {
650  struct GNUNET_SERVICE_Client *client = cls;
651  struct ReservationList *pos;
652  struct ReservationList *prev;
653  struct ReservationList *next;
654  int rid = ntohl(msg->rid);
655  unsigned long long rem;
656 
657  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Processing RELEASE_RESERVE request\n");
658  next = reservations;
659  prev = NULL;
660  while (NULL != (pos = next))
661  {
662  next = pos->next;
663  if (rid == pos->rid)
664  {
665  if (prev == NULL)
666  reservations = next;
667  else
668  prev->next = next;
669  rem =
670  pos->amount +
671  ((unsigned long long)GNUNET_DATASTORE_ENTRY_OVERHEAD) * pos->entries;
672  GNUNET_assert(reserved >= rem);
673  reserved -= rem;
674  GNUNET_STATISTICS_set(stats,
675  gettext_noop("# reserved"),
676  reserved,
677  GNUNET_NO);
679  "Returning %llu remaining reserved bytes to storage pool\n",
680  rem);
681  GNUNET_free(pos);
682  transmit_status(client, GNUNET_OK, NULL);
684  return;
685  }
686  prev = pos;
687  }
688  GNUNET_break(0);
689  transmit_status(client,
691  gettext_noop("Could not find matching reservation"));
693 }
694 
695 
702 static int
703 check_data(const struct DataMessage *dm)
704 {
705  uint16_t size;
706  uint32_t dsize;
707 
708  size = ntohs(dm->header.size);
709  dsize = ntohl(dm->size);
710  if (size != dsize + sizeof(struct DataMessage))
711  {
712  GNUNET_break(0);
713  return GNUNET_SYSERR;
714  }
715  return GNUNET_OK;
716 }
717 
718 
729 static void
731  const struct GNUNET_HashCode *key,
732  uint32_t size,
733  int status,
734  const char *msg)
735 {
736  struct GNUNET_SERVICE_Client *client = cls;
737 
738  if (GNUNET_OK == status)
739  {
741  gettext_noop("# bytes stored"),
742  size,
743  GNUNET_YES);
746  "Successfully stored %u bytes under key `%s'\n",
747  size,
748  GNUNET_h2s(key));
749  }
750  transmit_status(client,
751  GNUNET_SYSERR == status ? GNUNET_SYSERR : GNUNET_OK,
752  msg);
753  if (quota - reserved - cache_size < payload)
754  {
756  _("Need %llu bytes more space (%llu allowed, using %llu)\n"),
757  (unsigned long long)size + GNUNET_DATASTORE_ENTRY_OVERHEAD,
758  (unsigned long long)(quota - reserved - cache_size),
759  (unsigned long long)payload);
761  }
762 }
763 
764 
772 static int
773 check_put(void *cls, const struct DataMessage *dm)
774 {
775  if (GNUNET_OK != check_data(dm))
776  {
777  GNUNET_break(0);
778  return GNUNET_SYSERR;
779  }
780  return GNUNET_OK;
781 }
782 
783 
790 static void
791 handle_put(void *cls, const struct DataMessage *dm)
792 {
793  struct GNUNET_SERVICE_Client *client = cls;
794  int rid;
795  struct ReservationList *pos;
796  uint32_t size;
797 
799  "Processing PUT request for `%s' of type %u\n",
800  GNUNET_h2s(&dm->key),
801  (uint32_t)ntohl(dm->type));
802  rid = ntohl(dm->rid);
803  size = ntohl(dm->size);
804  if (rid > 0)
805  {
806  pos = reservations;
807  while ((NULL != pos) && (rid != pos->rid))
808  pos = pos->next;
809  GNUNET_break(pos != NULL);
810  if (NULL != pos)
811  {
812  GNUNET_break(pos->entries > 0);
813  GNUNET_break(pos->amount >= size);
814  pos->entries--;
815  pos->amount -= size;
817  GNUNET_STATISTICS_set(stats,
818  gettext_noop("# reserved"),
819  reserved,
820  GNUNET_NO);
821  }
822  }
823  bool absent =
825  plugin->api->put(plugin->api->cls,
826  &dm->key,
827  absent,
828  ntohl(dm->size),
829  &dm[1],
830  ntohl(dm->type),
831  ntohl(dm->priority),
832  ntohl(dm->anonymity),
833  ntohl(dm->replication),
836  client);
838 }
839 
840 
847 static void
848 handle_get(void *cls, const struct GetMessage *msg)
849 {
850  struct GNUNET_SERVICE_Client *client = cls;
851 
853  "Processing GET request of type %u\n",
854  (uint32_t)ntohl(msg->type));
856  gettext_noop("# GET requests received"),
857  1,
858  GNUNET_NO);
859  plugin->api->get_key(plugin->api->cls,
860  GNUNET_ntohll(msg->next_uid),
861  msg->random,
862  NULL,
863  ntohl(msg->type),
864  &transmit_item,
865  client);
867 }
868 
869 
876 static void
877 handle_get_key(void *cls, const struct GetKeyMessage *msg)
878 {
879  struct GNUNET_SERVICE_Client *client = cls;
880 
882  "Processing GET request for `%s' of type %u\n",
883  GNUNET_h2s(&msg->key),
884  (uint32_t)ntohl(msg->type));
886  gettext_noop("# GET KEY requests received"),
887  1,
888  GNUNET_NO);
889  if (GNUNET_YES != GNUNET_CONTAINER_bloomfilter_test(filter, &msg->key))
890  {
891  /* don't bother database... */
893  "Empty result set for GET request for `%s' (bloomfilter).\n",
894  GNUNET_h2s(&msg->key));
896  gettext_noop(
897  "# requests filtered by bloomfilter"),
898  1,
899  GNUNET_NO);
900  transmit_item(client,
901  NULL,
902  0,
903  NULL,
904  0,
905  0,
906  0,
907  0,
909  0);
911  return;
912  }
913  plugin->api->get_key(plugin->api->cls,
914  GNUNET_ntohll(msg->next_uid),
915  msg->random,
916  &msg->key,
917  ntohl(msg->type),
918  &transmit_item,
919  client);
921 }
922 
923 
930 static void
931 handle_get_replication(void *cls, const struct GNUNET_MessageHeader *message)
932 {
933  struct GNUNET_SERVICE_Client *client = cls;
934 
935  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Processing GET_REPLICATION request\n");
937  gettext_noop(
938  "# GET REPLICATION requests received"),
939  1,
940  GNUNET_NO);
941  plugin->api->get_replication(plugin->api->cls, &transmit_item, client);
943 }
944 
945 
952 static void
954 {
955  struct GNUNET_SERVICE_Client *client = cls;
956  enum GNUNET_BLOCK_Type type;
957 
958  type = (enum GNUNET_BLOCK_Type)ntohl(msg->type);
959  if (type == GNUNET_BLOCK_TYPE_ANY)
960  {
961  GNUNET_break(0);
963  return;
964  }
966  "Processing GET_ZERO_ANONYMITY request\n");
968  gettext_noop(
969  "# GET ZERO ANONYMITY requests received"),
970  1,
971  GNUNET_NO);
972  plugin->api->get_zero_anonymity(plugin->api->cls,
973  GNUNET_ntohll(msg->next_uid),
974  type,
975  &transmit_item,
976  client);
978 }
979 
980 
991 static void
993  const struct GNUNET_HashCode *key,
994  uint32_t size,
995  int status,
996  const char *msg)
997 {
998  struct GNUNET_SERVICE_Client *client = cls;
999 
1000  if (GNUNET_SYSERR == status)
1001  {
1002  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "REMOVE request failed: %s.\n", msg);
1003  transmit_status(client, GNUNET_NO, msg);
1004  return;
1005  }
1006  if (GNUNET_NO == status)
1007  {
1009  "Content not found for REMOVE request.\n");
1010  transmit_status(client, GNUNET_NO, _("Content not found"));
1011  return;
1012  }
1014  "Item matches REMOVE request for key `%s'.\n",
1015  GNUNET_h2s(key));
1017  gettext_noop("# bytes removed (explicit request)"),
1018  size,
1019  GNUNET_YES);
1021  transmit_status(client, GNUNET_OK, NULL);
1022 }
1023 
1024 
1032 static int
1033 check_remove(void *cls, const struct DataMessage *dm)
1034 {
1035  if (GNUNET_OK != check_data(dm))
1036  {
1037  GNUNET_break(0);
1038  return GNUNET_SYSERR;
1039  }
1040  return GNUNET_OK;
1041 }
1042 
1043 
1051 static void
1052 handle_remove(void *cls, const struct DataMessage *dm)
1053 {
1054  struct GNUNET_SERVICE_Client *client = cls;
1055 
1057  gettext_noop("# REMOVE requests received"),
1058  1,
1059  GNUNET_NO);
1061  "Processing REMOVE request for `%s'\n",
1062  GNUNET_h2s(&dm->key));
1063  plugin->api->remove_key(plugin->api->cls,
1064  &dm->key,
1065  ntohl(dm->size),
1066  &dm[1],
1068  client);
1070 }
1071 
1072 
1079 static void
1080 handle_drop(void *cls, const struct GNUNET_MessageHeader *message)
1081 {
1082  struct GNUNET_SERVICE_Client *client = cls;
1083 
1084  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Processing DROP request\n");
1085  do_drop = GNUNET_YES;
1087 }
1088 
1089 
1098 static void
1100 {
1101  if ((delta < 0) && (payload < -delta))
1102  {
1103  GNUNET_log(
1105  _(
1106  "Datastore payload must have been inaccurate (%lld < %lld). Recomputing it.\n"),
1107  (long long)payload,
1108  (long long)-delta);
1109  plugin->api->estimate_size(plugin->api->cls, &payload);
1111  _("New payload: %lld\n"),
1112  (long long)payload);
1113  sync_stats();
1114  return;
1115  }
1116  payload += delta;
1117  last_sync++;
1119  sync_stats();
1120 }
1121 
1122 
1133 static int
1135  const char *subsystem,
1136  const char *name,
1137  uint64_t value,
1138  int is_persistent)
1139 {
1142  payload += value;
1143  GNUNET_log(
1145  "Notification from statistics about existing payload (%llu), new payload is %llu\n",
1146  (unsigned long long)value,
1147  (unsigned long long)payload);
1148  return GNUNET_OK;
1149 }
1150 
1151 
1155 static struct DatastorePlugin *
1157 {
1158  struct DatastorePlugin *ret;
1159  char *libname;
1160 
1161  ret = GNUNET_new(struct DatastorePlugin);
1162  ret->env.cfg = cfg;
1164  ret->env.cls = NULL;
1166  _("Loading `%s' datastore plugin\n"),
1167  plugin_name);
1168  GNUNET_asprintf(&libname, "libgnunet_plugin_datastore_%s", plugin_name);
1170  ret->lib_name = libname;
1171  ret->api = GNUNET_PLUGIN_load(libname, &ret->env);
1172  if (NULL == ret->api)
1173  {
1175  _("Failed to load datastore plugin for `%s'\n"),
1176  plugin_name);
1177  GNUNET_free(ret->short_name);
1178  GNUNET_free(libname);
1179  GNUNET_free(ret);
1180  return NULL;
1181  }
1182  return ret;
1183 }
1184 
1185 
1192 static void
1194 {
1196  "Datastore service is unloading plugin...\n");
1197  GNUNET_break(NULL == GNUNET_PLUGIN_unload(plug->lib_name, plug->api));
1198  GNUNET_free(plug->lib_name);
1199  GNUNET_free(plug->short_name);
1200  GNUNET_free(plug);
1201 }
1202 
1203 
1207 static void
1209 {
1210  GNUNET_SERVICE_resume(service);
1211  expired_kill_task =
1213  &delete_expired,
1214  NULL);
1215 }
1216 
1217 
1225 static void
1227  const struct GNUNET_HashCode *key,
1228  unsigned int count)
1229 {
1230  struct GNUNET_CONTAINER_BloomFilter *bf = cls;
1231 
1232  if (NULL == key)
1233  {
1235  _("Bloomfilter construction complete.\n"));
1236  begin_service();
1237  return;
1238  }
1239 
1240  while (0 < count--)
1242 }
1243 
1244 
1252 static void
1253 process_stat_done(void *cls, int success)
1254 {
1255  stat_get = NULL;
1256  if (NULL != stat_timeout_task)
1257  {
1258  GNUNET_SCHEDULER_cancel(stat_timeout_task);
1259  stat_timeout_task = NULL;
1260  }
1261  plugin = load_plugin();
1262  if (NULL == plugin)
1263  {
1265  filter = NULL;
1266  if (NULL != stats)
1267  {
1269  stats = NULL;
1270  }
1271  return;
1272  }
1273 
1274  if (GNUNET_NO == stats_worked)
1275  {
1277  "Failed to obtain value from statistics service, recomputing it\n");
1278  plugin->api->estimate_size(plugin->api->cls, &payload);
1280  _("New payload: %lld\n"),
1281  (long long)payload);
1282  }
1283 
1284  if (GNUNET_YES == refresh_bf)
1285  {
1287  _("Rebuilding bloomfilter. Please be patient.\n"));
1288  if (NULL != plugin->api->get_keys)
1289  {
1290  plugin->api->get_keys(plugin->api->cls, &add_key_to_bloomfilter, filter);
1291  return;
1292  }
1293  else
1294  {
1296  _(
1297  "Plugin does not support get_keys function. Please fix!\n"));
1298  }
1299  }
1300  begin_service();
1301 }
1302 
1303 
1309 static void
1310 stat_timeout(void *cls)
1311 {
1312  stat_timeout_task = NULL;
1313  GNUNET_STATISTICS_get_cancel(stat_get);
1315 }
1316 
1317 
1321 static void
1322 cleaning_task(void *cls)
1323 {
1325  if (NULL != expired_kill_task)
1326  {
1327  GNUNET_SCHEDULER_cancel(expired_kill_task);
1328  expired_kill_task = NULL;
1329  }
1330  if (GNUNET_YES == do_drop)
1331  {
1332  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Dropping database!\n");
1333  plugin->api->drop(plugin->api->cls);
1334  payload = 0;
1335  last_sync++;
1336  }
1337  if (NULL != plugin)
1338  {
1339  unload_plugin(plugin);
1340  plugin = NULL;
1341  }
1342  if (NULL != filter)
1343  {
1345  filter = NULL;
1346  }
1347  if (NULL != stat_get)
1348  {
1349  GNUNET_STATISTICS_get_cancel(stat_get);
1350  stat_get = NULL;
1351  }
1352  if (NULL != stat_timeout_task)
1353  {
1354  GNUNET_SCHEDULER_cancel(stat_timeout_task);
1355  stat_timeout_task = NULL;
1356  }
1358  plugin_name = NULL;
1359  if (last_sync > 0)
1360  sync_stats();
1361  if (NULL != stats)
1362  {
1364  stats = NULL;
1365  }
1367  quota_stat_name = NULL;
1368 }
1369 
1370 
1379 static void *
1381  struct GNUNET_SERVICE_Client *client,
1382  struct GNUNET_MQ_Handle *mq)
1383 {
1384  return client;
1385 }
1386 
1387 
1396 static void
1398  struct GNUNET_SERVICE_Client *client,
1399  void *app_ctx)
1400 {
1401  struct ReservationList *pos;
1402  struct ReservationList *prev;
1403  struct ReservationList *next;
1404 
1405  GNUNET_assert(app_ctx == client);
1406  prev = NULL;
1407  pos = reservations;
1408  while (NULL != pos)
1409  {
1410  next = pos->next;
1411  if (pos->client == client)
1412  {
1413  if (NULL == prev)
1414  reservations = next;
1415  else
1416  prev->next = next;
1418  GNUNET_free(pos);
1419  }
1420  else
1421  {
1422  prev = pos;
1423  }
1424  pos = next;
1425  }
1426  GNUNET_STATISTICS_set(stats,
1427  gettext_noop("# reserved"),
1428  reserved,
1429  GNUNET_NO);
1430 }
1431 
1432 
1440 static void
1441 run(void *cls,
1442  const struct GNUNET_CONFIGURATION_Handle *c,
1443  struct GNUNET_SERVICE_Handle *serv)
1444 {
1445  char *fn;
1446  char *pfn;
1447  unsigned int bf_size;
1448 
1449  service = serv;
1450  cfg = c;
1452  "DATASTORE",
1453  "DATABASE",
1454  &plugin_name))
1455  {
1457  "DATABASE",
1458  "DATASTORE");
1459  return;
1460  }
1462  _("# bytes used in file-sharing datastore `%s'"),
1463  plugin_name);
1464  if (GNUNET_OK !=
1465  GNUNET_CONFIGURATION_get_value_size(cfg, "DATASTORE", "QUOTA", &quota))
1466  {
1467  GNUNET_log_config_missing(GNUNET_ERROR_TYPE_ERROR, "QUOTA", "DATASTORE");
1468  return;
1469  }
1470  stats = GNUNET_STATISTICS_create("datastore", cfg);
1471  GNUNET_STATISTICS_set(stats, gettext_noop("# quota"), quota, GNUNET_NO);
1472  cache_size = quota / 8; /* Or should we make this an option? */
1473  GNUNET_STATISTICS_set(stats,
1474  gettext_noop("# cache size"),
1475  cache_size,
1476  GNUNET_NO);
1477  if (quota / (32 * 1024LL) > MAX_BF_SIZE)
1478  bf_size = MAX_BF_SIZE;
1479  else
1480  bf_size =
1481  quota / (32 * 1024LL); /* 8 bit per entry, 1 bit per 32 kb in DB */
1482  fn = NULL;
1484  "DATASTORE",
1485  "BLOOMFILTER",
1486  &fn)) ||
1488  {
1490  _("Could not use specified filename `%s' for bloomfilter.\n"),
1491  NULL != fn ? fn : "");
1493  fn = NULL;
1494  }
1495  if (NULL != fn)
1496  {
1497  GNUNET_asprintf(&pfn, "%s.%s", fn, plugin_name);
1498  if (GNUNET_YES == GNUNET_DISK_file_test(pfn))
1499  {
1500  filter =
1502  bf_size,
1503  5); /* approx. 3% false positives at max use */
1504  if (NULL == filter)
1505  {
1506  /* file exists but not valid, remove and try again, but refresh */
1507  if (0 != unlink(pfn))
1508  {
1509  /* failed to remove, run without file */
1511  _("Failed to remove bogus bloomfilter file `%s'\n"),
1512  pfn);
1513  GNUNET_free(pfn);
1514  pfn = NULL;
1516  NULL,
1517  bf_size,
1518  5); /* approx. 3% false positives at max use */
1520  }
1521  else
1522  {
1523  /* try again after remove */
1525  pfn,
1526  bf_size,
1527  5); /* approx. 3% false positives at max use */
1529  if (NULL == filter)
1530  {
1531  /* failed yet again, give up on using file */
1533  _("Failed to remove bogus bloomfilter file `%s'\n"),
1534  pfn);
1535  GNUNET_free(pfn);
1536  pfn = NULL;
1538  NULL,
1539  bf_size,
1540  5); /* approx. 3% false positives at max use */
1541  }
1542  }
1543  }
1544  else
1545  {
1546  /* normal case: have an existing valid bf file, no need to refresh */
1548  }
1549  }
1550  else
1551  {
1552  filter =
1554  bf_size,
1555  5); /* approx. 3% false positives at max use */
1557  }
1558  GNUNET_free(pfn);
1559  }
1560  else
1561  {
1562  filter =
1564  bf_size,
1565  5); /* approx. 3% false positives at max use */
1567  }
1569  if (NULL == filter)
1570  {
1572  _("Failed to initialize bloomfilter.\n"));
1573  if (NULL != stats)
1574  {
1576  stats = NULL;
1577  }
1578  return;
1579  }
1580  GNUNET_SERVICE_suspend(service);
1581  stat_get = GNUNET_STATISTICS_get(stats,
1582  "datastore",
1585  &process_stat_in,
1586  NULL);
1587  if (NULL == stat_get)
1589  else
1591  &stat_timeout,
1592  NULL);
1594 }
1595 
1596 
1601  "datastore",
1603  &run,
1606  NULL,
1607  GNUNET_MQ_hd_fixed_size(reserve,
1609  struct ReserveMessage,
1610  NULL),
1611  GNUNET_MQ_hd_fixed_size(release_reserve,
1613  struct ReleaseReserveMessage,
1614  NULL),
1617  struct DataMessage,
1618  NULL),
1621  struct GetMessage,
1622  NULL),
1623  GNUNET_MQ_hd_fixed_size(get_key,
1625  struct GetKeyMessage,
1626  NULL),
1627  GNUNET_MQ_hd_fixed_size(get_replication,
1629  struct GNUNET_MessageHeader,
1630  NULL),
1631  GNUNET_MQ_hd_fixed_size(get_zero_anonymity,
1633  struct GetZeroAnonymityMessage,
1634  NULL),
1635  GNUNET_MQ_hd_var_size(remove,
1637  struct DataMessage,
1638  NULL),
1641  struct GNUNET_MessageHeader,
1642  NULL),
1644 
1645 
1646 /* end of gnunet-service-datastore.c */
static void handle_drop(void *cls, const struct GNUNET_MessageHeader *message)
Handle DROP-message.
int 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:541
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.
#define GNUNET_MESSAGE_TYPE_DATASTORE_STATUS
Message sent by datastore to client informing about status processing a request (in response to RESER...
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_get(void *cls, const struct GetMessage *msg)
Handle GNUNET_MESSAGE_TYPE_DATASTORE_GET-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.
static void handle_put(void *cls, const struct DataMessage *dm)
Handle PUT-message.
GNUNET_DATASTORE_DiskUtilizationChange duc
Function to call on disk utilization change.
PluginGetKeys get_keys
Iterate over all keys in the database.
PluginPut put
Function to store an item in the datastore.
static int cleaning_done
Have we already cleaned up the TCCs and are hence no longer willing (or able) to transmit anything to...
uint32_t random
If true return a random result.
Definition: datastore.h:123
PluginGetType get_zero_anonymity
Get datum (of the specified type) with anonymity level zero.
static char * subsystem
Set to subsystem that we&#39;re going to get stats for (or NULL for all).
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static char * expiration
Credential TTL.
static void disk_utilization_change_cb(void *cls, int delta)
Function called by plugins to notify us about a change in their disk utilization. ...
GNUNET_SERVICE_MAIN("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.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:671
void GNUNET_CONTAINER_bloomfilter_add(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Add an element to the filter.
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
static void manage_space(unsigned long long need)
Manage available disk space by running tasks that will discard content if necessary.
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:35
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
struct GNUNET_TIME_AbsoluteNBO expiration
Expiration time (NBO); zero for remove.
Definition: datastore.h:240
uint32_t type
Desired content type (actually an enum GNUNET_BLOCK_Type)
Definition: datastore.h:172
uint32_t entries
Number of items to reserve.
Definition: datastore.h:48
void GNUNET_SERVICE_resume(struct GNUNET_SERVICE_Handle *sh)
Resume accepting connections from the listen socket.
Definition: service.c:2185
Any type of block, used as a wildcard when searching.
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.
Message from datastore service informing client about the current size of the datastore.
Definition: datastore.h:39
static struct GNUNET_SERVICE_Handle * service
Handle to our server.
Handle to a service.
Definition: service.c:114
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
GNUNET_BLOCK_Type
Blocks in the datastore and the datacache must have a unique type.
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:1169
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2424
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&#39;re happy with respect t...
uint32_t type
Type of the item (NBO), zero for remove, (actually an enum GNUNET_BLOCK_Type)
Definition: datastore.h:207
Our datastore plugin.
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, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1284
char * lib_name
Name of the library (i.e.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
static int check_put(void *cls, const struct DataMessage *dm)
Verify PUT-message.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
uint32_t random
If true return a random result.
Definition: datastore.h:155
#define GNUNET_TIME_UNIT_SECONDS
One second.
#define MAX_STAT_SYNC_LAG
After how many payload-changing operations do we sync our statistics?
uint64_t amount
Number of bytes (still) reserved.
PluginRemoveKey remove_key
Function to remove an item from the database.
void GNUNET_STATISTICS_get_cancel(struct GNUNET_STATISTICS_GetHandle *gh)
Cancel a GNUNET_STATISTICS_get request.
Message from datastore client informing service that the remainder of the reserved bytes can now be r...
Definition: datastore.h:87
static unsigned int replication
static void remove_continuation(void *cls, const struct GNUNET_HashCode *key, uint32_t size, int status, const char *msg)
Remove continuation.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
PluginEstimateSize estimate_size
Calculate the current on-disk size of the SQ store.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
#define GNUNET_MESSAGE_TYPE_DATASTORE_GET_REPLICATION
Message sent by datastore client to get random data.
static struct Experiment * e
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:681
Message to the datastore service asking about specific content.
Definition: datastore.h:104
struct GNUNET_TIME_AbsoluteNBO min_expiration
Minimum expiration time required for content to be stored by the datacache at this time...
Definition: datastore.h:78
Linked list of things we still need to do.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
Message to the datastore service asking about zero anonymity content.
Definition: datastore.h:163
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_MESSAGE_TYPE_DATASTORE_RESERVE
Message sent by datastore client on join.
uint64_t next_uid
UID at which to start the search.
Definition: datastore.h:150
static int do_drop
Should the database be dropped on exit?
#define GNUNET_MESSAGE_TYPE_DATASTORE_PUT
Message sent by datastore client to store data.
static char * quota_stat_name
Name under which we store current space consumption.
static int check_remove(void *cls, const struct DataMessage *dm)
Verify REMOVE-message.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
static int ret
Final status code.
Definition: gnunet-arm.c:89
Handle for the service.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
static void sync_stats()
Synchronize our utilization statistics with the statistics service.
uint64_t abs_value_us
The actual value.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static int check_data(const struct DataMessage *dm)
Check that the given message is a valid data message.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
void * GNUNET_PLUGIN_unload(const char *library_name, void *arg)
Unload plugin (runs the "done" callback and returns whatever "done" returned).
Definition: plugin.c:255
Handle to a client that is connected to a service.
Definition: service.c:246
PluginGetRandom get_replication
Function to get a random item with high replication score from the database, lowering the item&#39;s repl...
#define GNUNET_MESSAGE_TYPE_DATASTORE_RELEASE_RESERVE
Message sent by datastore client on join.
#define MAX_EXPIRE_DELAY
How long are we at most keeping "expired" content past the expiration date in the database...
PluginDrop drop
Delete the database.
structs for communication between datastore service and API
static struct DatastorePlugin * load_plugin()
Load the datastore plugin.
static void unload_plugin(struct DatastorePlugin *plug)
Function called when the service shuts down.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
int32_t rid
Reservation identifier.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
static struct GNUNET_STATISTICS_GetHandle * stat_get
Handle for pending get request.
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.
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:1237
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:1191
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.
#define GNUNET_MESSAGE_TYPE_DATASTORE_DROP
Message sent by datastore client to drop the database.
static void handle_get_replication(void *cls, const struct GNUNET_MessageHeader *message)
Handle GET_REPLICATION-message.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
static char * value
Value of the record to add/remove.
void GNUNET_CONTAINER_bloomfilter_remove(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Remove an element from the filter.
int GNUNET_CONTAINER_bloomfilter_test(const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Test if an element is in the filter.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
static char * fn
Filename of the unique file.
Message to the datastore service asking about specific content.
Definition: datastore.h:136
uint32_t type
Desired content type.
Definition: datastore.h:113
static struct ReservationList * reservations
Linked list of space reservations made by clients.
PluginGetRandom get_expiration
Function to get a random expired item or, if none are expired, either the oldest entry or one with a ...
struct ListEntry * entries
List of peers in the list.
static void process_stat_done(void *cls, int success)
We finished receiving the statistic.
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
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:686
uint16_t status
See PRISM_STATUS_*-constants.
char * short_name
Short name for the plugin (i.e.
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_load(const char *filename, size_t size, unsigned int k)
Load a Bloom filter from a file.
static struct GNUNET_CONTAINER_BloomFilter * filter
Bloomfilter to quickly tell if we don&#39;t have the content.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Called whenever a client is disconnected.
The datastore service will pass a pointer to a struct of this type as the first and only argument to ...
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
A 512-bit hashcode.
static struct GNUNET_SCHEDULER_Task * expired_kill_task
Identity of the task that is used to delete expired content.
int 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.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2315
#define GNUNET_DATASTORE_ENTRY_OVERHEAD
How many bytes of overhead will we assume per entry in any DB (for reservations)? ...
uint32_t type
Desired content type.
Definition: datastore.h:145
#define GNUNET_MESSAGE_TYPE_DATASTORE_DATA_END
Message sent by datastore to client signaling end of matching data.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
uint32_t replication
Desired replication level.
Definition: datastore.h:222
Run when otherwise idle.
int 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.
uint32_t rid
Reservation ID to use; use zero for none.
Definition: datastore.h:197
struct GNUNET_DATASTORE_PluginFunctions * api
API of the transport as returned by the plugin&#39;s initialization function.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:35
static void stat_timeout(void *cls)
Fetching stats took to long, run without.
struct ReservationList * next
This is a linked list.
struct GNUNET_DATASTORE_PluginEnvironment env
Environment this transport service is using for this plugin.
Message transmitting content from or to the datastore service.
Definition: datastore.h:185
struct GNUNET_HashCode key
Desired key.
Definition: datastore.h:128
static void handle_reserve(void *cls, const struct ReserveMessage *msg)
Handle RESERVE-message.
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static unsigned int size
Size of the "table".
Definition: peer.c:66
static int stats_worked
Did we get an answer from statistics?
uint32_t size
Number of bytes in the item (NBO).
Definition: datastore.h:202
static unsigned int last_sync
Number of updates that were made to the payload value since we last synchronized it with the statisti...
uint32_t anonymity
Desired anonymity level (NBO), zero for remove.
Definition: datastore.h:217
static int refresh_bf
Should we refresh the BF when the DB is loaded?
static void handle_get_key(void *cls, const struct GetKeyMessage *msg)
Handle GNUNET_MESSAGE_TYPE_DATASTORE_GET_KEY-message.
const char * name
static void handle_release_reserve(void *cls, const struct ReleaseReserveMessage *msg)
Handle RELEASE_RESERVE-message.
uint64_t entries
Number of items (still) reserved.
static unsigned long long payload
How much data are we currently storing in the database?
int32_t rid
Reservation id.
Definition: datastore.h:96
static struct GNUNET_STATISTICS_Handle * stats
Handle for reporting statistics.
void * cls
Closure to use for all of the following callbacks (except "next_request").
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.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
struct GNUNET_MessageHeader header
Type is either GNUNET_MESSAGE_TYPE_DATASTORE_PUT, GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE or GNUNET_MESS...
Definition: datastore.h:192
static unsigned long long quota
How much space are we allowed to use?
static struct DatastorePlugin * plugin
Our datastore plugin (NULL if not available).
static void cleaning_task(void *cls)
Task run during shutdown.
Handle to a message queue.
Definition: mq.c:84
static unsigned long long cache_size
How much space are we using for the cache? (space available for insertions that will be instantly rec...
uint64_t next_uid
UID at which to start the search.
Definition: datastore.h:177
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:235
#define GNUNET_MESSAGE_TYPE_DATASTORE_GET_ZERO_ANONYMITY
Message sent by datastore client to get random data.
#define GNUNET_MESSAGE_TYPE_DATASTORE_GET_KEY
Message sent by datastore client to get data by key.
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.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *serv)
Process datastore requests.
configuration data
Definition: configuration.c:83
struct GNUNET_HashCode key
Key under which the item can be found.
Definition: datastore.h:245
uint32_t priority
Priority of the item (NBO), zero for remove.
Definition: datastore.h:212
static void put_continuation(void *cls, const struct GNUNET_HashCode *key, uint32_t size, int status, const char *msg)
Put continuation.
static void begin_service()
Initialization complete, start operating the service.
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:131
Message from datastore service informing client about the success or failure of a requested operation...
Definition: datastore.h:63
int 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.
#define MAX_BF_SIZE
Limit size of bloom filter to 2 GB.
static void handle_remove(void *cls, const struct DataMessage *dm)
Handle REMOVE-message.
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:331
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
static unsigned int anonymity
int32_t status
Status code, -1 for errors.
Definition: datastore.h:72
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:353
#define MIN_EXPIRE_DELAY
How fast are we allowed to query the database for deleting expired content? (1 item per second)...
void * GNUNET_PLUGIN_load(const char *library_name, void *arg)
Setup plugin (runs the "init" callback and returns whatever "init" returned).
Definition: plugin.c:206
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:351
#define GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE
Message sent by datastore client to remove data.
static void transmit_status(struct GNUNET_SERVICE_Client *client, int code, const char *msg)
Transmit a status code to the client.
uint64_t next_uid
UID at which to start the search.
Definition: datastore.h:118
#define GNUNET_MESSAGE_TYPE_DATASTORE_GET
Message sent by datastore client to get data.
static unsigned long long reserved
How much space have we currently reserved?
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:741
struct GNUNET_SERVICE_Client * client
Client that made the reservation.
void GNUNET_SERVICE_suspend(struct GNUNET_SERVICE_Handle *sh)
Suspend accepting connections from the listen socket temporarily.
Definition: service.c:2173
PluginGetKey get_key
Get a particular datum matching a given hash from the datastore.
static void delete_expired(void *cls)
Task that is used to remove expired entries from the datastore.
uint32_t data
The data value.
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:655
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2234
void GNUNET_CONTAINER_bloomfilter_free(struct GNUNET_CONTAINER_BloomFilter *bf)
Free the space associcated with a filter in memory, flush to drive if needed (do not free the space o...
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
static char * plugin_name
Name of our plugin.
#define GNUNET_MESSAGE_TYPE_DATASTORE_DATA
Message sent by datastore to client providing requested data (in response to GET or GET_RANDOM reques...
Linked list of active reservations.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
#define GNUNET_free(ptr)
Wrapper around free.
static struct GNUNET_SCHEDULER_Task * stat_timeout_task
Task to timeout stat GET.
static void handle_get_zero_anonymity(void *cls, const struct GetZeroAnonymityMessage *msg)
Handle GET_ZERO_ANONYMITY-message.
#define gettext_noop(String)
Definition: gettext.h:69
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
uint64_t amount
Number of bytes to reserve.
Definition: datastore.h:53