GNUnet  0.11.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 
79 {
85 
89  char *short_name;
90 
94  char *lib_name;
95 
101 };
102 
103 
108 {
113 
118 
122  uint64_t amount;
123 
127  uint64_t entries;
128 
132  int32_t rid;
133 };
134 
135 
139 static struct DatastorePlugin *plugin;
140 
145 
150 
154 static char *plugin_name;
155 
159 static const struct GNUNET_CONFIGURATION_Handle *cfg;
160 
165 
172 static unsigned long long cache_size;
173 
177 static unsigned long long reserved;
178 
183 static unsigned long long payload;
184 
190 
198 
202 static unsigned long long quota;
203 
207 static int do_drop;
208 
212 static int refresh_bf;
213 
219 static unsigned int last_sync;
220 
224 static int stats_worked;
225 
226 
231 static void
233 {
235  GNUNET_STATISTICS_set (stats,
236  "# utilization by current datastore",
237  payload,
238  GNUNET_NO);
239  last_sync = 0;
240 }
241 
242 
247 static int cleaning_done;
248 
253 
258 
267 static void
268 delete_expired (void *cls);
269 
270 
292 static int
293 expired_processor (void *cls,
294  const struct GNUNET_HashCode *key,
295  uint32_t size,
296  const void *data,
297  enum GNUNET_BLOCK_Type type,
298  uint32_t priority,
299  uint32_t anonymity,
300  uint32_t replication,
302  uint64_t uid)
303 {
304  struct GNUNET_TIME_Absolute now;
305 
306  if (NULL == key)
307  {
308  expired_kill_task =
312  NULL);
313  return GNUNET_SYSERR;
314  }
315  now = GNUNET_TIME_absolute_get ();
316  if (expiration.abs_value_us > now.abs_value_us)
317  {
318  /* finished processing */
319  expired_kill_task =
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,
331  GNUNET_TIME_absolute_get_difference (expiration, now),
332  GNUNET_YES));
333  min_expiration = now;
335  gettext_noop ("# bytes expired"),
336  size,
337  GNUNET_YES);
339  expired_kill_task =
343  NULL);
344  return GNUNET_NO;
345 }
346 
347 
356 static void
357 delete_expired (void *cls)
358 {
359  expired_kill_task = NULL;
360  plugin->api->get_expiration (plugin->api->cls, &expired_processor, NULL);
361 }
362 
363 
383 static int
384 quota_processor (void *cls,
385  const struct GNUNET_HashCode *key,
386  uint32_t size,
387  const void *data,
388  enum GNUNET_BLOCK_Type type,
389  uint32_t priority,
390  uint32_t anonymity,
391  uint32_t replication,
393  uint64_t uid)
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);
410  if (size + GNUNET_DATASTORE_ENTRY_OVERHEAD > *need)
411  *need = 0;
412  else
413  *need -= size + GNUNET_DATASTORE_ENTRY_OVERHEAD;
414  if (priority > 0)
416  else
419  gettext_noop ("# bytes purged (low-priority)"),
420  size,
421  GNUNET_YES);
423  return GNUNET_NO;
424 }
425 
426 
439 static void
440 manage_space (unsigned long long need)
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;
451  plugin->api->get_expiration (plugin->api->cls, &quota_processor, &need);
452  }
453 }
454 
455 
463 static void
465  int code,
466  const char *msg)
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 }
484 
485 
504 static int
505 transmit_item (void *cls,
506  const struct GNUNET_HashCode *key,
507  uint32_t size,
508  const void *data,
509  enum GNUNET_BLOCK_Type type,
510  uint32_t priority,
511  uint32_t anonymity,
512  uint32_t replication,
514  uint64_t uid)
515 {
516  struct GNUNET_SERVICE_Client *client = cls;
517  struct GNUNET_MQ_Envelope *env;
518  struct GNUNET_MessageHeader *end;
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  }
529  GNUNET_assert (sizeof(struct DataMessage) + size < GNUNET_MAX_MESSAGE_SIZE);
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);
537  dm->expiration = GNUNET_TIME_absolute_hton (expiration);
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 }
557 
558 
565 static void
566 handle_reserve (void *cls, const struct ReserveMessage *msg)
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 */GNUNET_log (
604  _ (
605  "The requested amount (%llu bytes) is larger than the cache size (%llu bytes)\n"),
606  req,
607  cache_size);
608  transmit_status (client,
609  0,
610  gettext_noop (
611  "Insufficient space to satisfy request and "
612  "requested amount is larger than cache size"));
613  }
614  else
615  {
616  transmit_status (client,
617  0,
618  gettext_noop ("Insufficient space to satisfy request"));
619  }
621  return;
622  }
623  reserved += req;
624  GNUNET_STATISTICS_set (stats,
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;
635  if (reservation_gen < 0)
636  reservation_gen = 0; /* wrap around */
637  transmit_status (client, e->rid, NULL);
639 }
640 
641 
648 static void
650 {
651  struct GNUNET_SERVICE_Client *client = cls;
652  struct ReservationList *pos;
653  struct ReservationList *prev;
654  struct ReservationList *next;
655  int rid = ntohl (msg->rid);
656  unsigned long long rem;
657 
658  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing RELEASE_RESERVE request\n");
659  next = reservations;
660  prev = NULL;
661  while (NULL != (pos = next))
662  {
663  next = pos->next;
664  if (rid == pos->rid)
665  {
666  if (prev == NULL)
667  reservations = next;
668  else
669  prev->next = next;
670  rem =
671  pos->amount
672  + ((unsigned long long) GNUNET_DATASTORE_ENTRY_OVERHEAD) * pos->entries;
673  GNUNET_assert (reserved >= rem);
674  reserved -= rem;
675  GNUNET_STATISTICS_set (stats,
676  gettext_noop ("# reserved"),
677  reserved,
678  GNUNET_NO);
680  "Returning %llu remaining reserved bytes to storage pool\n",
681  rem);
682  GNUNET_free (pos);
683  transmit_status (client, GNUNET_OK, NULL);
685  return;
686  }
687  prev = pos;
688  }
689  GNUNET_break (0);
690  transmit_status (client,
692  gettext_noop ("Could not find matching reservation"));
694 }
695 
696 
703 static int
704 check_data (const struct DataMessage *dm)
705 {
706  uint16_t size;
707  uint32_t dsize;
708 
709  size = ntohs (dm->header.size);
710  dsize = ntohl (dm->size);
711  if (size != dsize + sizeof(struct DataMessage))
712  {
713  GNUNET_break (0);
714  return GNUNET_SYSERR;
715  }
716  return GNUNET_OK;
717 }
718 
719 
730 static void
731 put_continuation (void *cls,
732  const struct GNUNET_HashCode *key,
733  uint32_t size,
734  int status,
735  const char *msg)
736 {
737  struct GNUNET_SERVICE_Client *client = cls;
738 
739  if (GNUNET_OK == status)
740  {
742  gettext_noop ("# bytes stored"),
743  size,
744  GNUNET_YES);
745  GNUNET_CONTAINER_bloomfilter_add (filter, key);
747  "Successfully stored %u bytes under key `%s'\n",
748  size,
749  GNUNET_h2s (key));
750  }
751  transmit_status (client,
752  GNUNET_SYSERR == status ? GNUNET_SYSERR : GNUNET_OK,
753  msg);
754  if (quota - reserved - cache_size < payload)
755  {
757  _ ("Need %llu bytes more space (%llu allowed, using %llu)\n"),
758  (unsigned long long) size + GNUNET_DATASTORE_ENTRY_OVERHEAD,
759  (unsigned long long) (quota - reserved - cache_size),
760  (unsigned long long) payload);
762  }
763 }
764 
765 
773 static int
774 check_put (void *cls, const struct DataMessage *dm)
775 {
776  if (GNUNET_OK != check_data (dm))
777  {
778  GNUNET_break (0);
779  return GNUNET_SYSERR;
780  }
781  return GNUNET_OK;
782 }
783 
784 
791 static void
792 handle_put (void *cls, const struct DataMessage *dm)
793 {
794  struct GNUNET_SERVICE_Client *client = cls;
795  int rid;
796  struct ReservationList *pos;
797  uint32_t size;
798 
800  "Processing PUT request for `%s' of type %u\n",
801  GNUNET_h2s (&dm->key),
802  (uint32_t) ntohl (dm->type));
803  rid = ntohl (dm->rid);
804  size = ntohl (dm->size);
805  if (rid > 0)
806  {
807  pos = reservations;
808  while ((NULL != pos) && (rid != pos->rid))
809  pos = pos->next;
810  GNUNET_break (pos != NULL);
811  if (NULL != pos)
812  {
813  GNUNET_break (pos->entries > 0);
814  GNUNET_break (pos->amount >= size);
815  pos->entries--;
816  pos->amount -= size;
818  GNUNET_STATISTICS_set (stats,
819  gettext_noop ("# reserved"),
820  reserved,
821  GNUNET_NO);
822  }
823  }
824  bool absent =
826  plugin->api->put (plugin->api->cls,
827  &dm->key,
828  absent,
829  ntohl (dm->size),
830  &dm[1],
831  ntohl (dm->type),
832  ntohl (dm->priority),
833  ntohl (dm->anonymity),
834  ntohl (dm->replication),
837  client);
839 }
840 
841 
848 static void
849 handle_get (void *cls, const struct GetMessage *msg)
850 {
851  struct GNUNET_SERVICE_Client *client = cls;
852 
854  "Processing GET request of type %u\n",
855  (uint32_t) ntohl (msg->type));
857  gettext_noop ("# GET requests received"),
858  1,
859  GNUNET_NO);
860  plugin->api->get_key (plugin->api->cls,
861  GNUNET_ntohll (msg->next_uid),
862  msg->random,
863  NULL,
864  ntohl (msg->type),
865  &transmit_item,
866  client);
868 }
869 
870 
877 static void
878 handle_get_key (void *cls, const struct GetKeyMessage *msg)
879 {
880  struct GNUNET_SERVICE_Client *client = cls;
881 
883  "Processing GET request for `%s' of type %u\n",
884  GNUNET_h2s (&msg->key),
885  (uint32_t) ntohl (msg->type));
887  gettext_noop ("# GET KEY requests received"),
888  1,
889  GNUNET_NO);
890  if (GNUNET_YES != GNUNET_CONTAINER_bloomfilter_test (filter, &msg->key))
891  {
892  /* don't bother database... */
894  "Empty result set for GET request for `%s' (bloomfilter).\n",
895  GNUNET_h2s (&msg->key));
897  gettext_noop (
898  "# requests filtered by bloomfilter"),
899  1,
900  GNUNET_NO);
901  transmit_item (client,
902  NULL,
903  0,
904  NULL,
905  0,
906  0,
907  0,
908  0,
910  0);
912  return;
913  }
914  plugin->api->get_key (plugin->api->cls,
915  GNUNET_ntohll (msg->next_uid),
916  msg->random,
917  &msg->key,
918  ntohl (msg->type),
919  &transmit_item,
920  client);
922 }
923 
924 
931 static void
932 handle_get_replication (void *cls, const struct GNUNET_MessageHeader *message)
933 {
934  struct GNUNET_SERVICE_Client *client = cls;
935 
936  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing GET_REPLICATION request\n");
938  gettext_noop (
939  "# GET REPLICATION requests received"),
940  1,
941  GNUNET_NO);
942  plugin->api->get_replication (plugin->api->cls, &transmit_item, client);
944 }
945 
946 
953 static void
955 {
956  struct GNUNET_SERVICE_Client *client = cls;
957  enum GNUNET_BLOCK_Type type;
958 
959  type = (enum GNUNET_BLOCK_Type) ntohl (msg->type);
960  if (type == GNUNET_BLOCK_TYPE_ANY)
961  {
962  GNUNET_break (0);
964  return;
965  }
967  "Processing GET_ZERO_ANONYMITY request\n");
969  gettext_noop (
970  "# GET ZERO ANONYMITY requests received"),
971  1,
972  GNUNET_NO);
973  plugin->api->get_zero_anonymity (plugin->api->cls,
974  GNUNET_ntohll (msg->next_uid),
975  type,
976  &transmit_item,
977  client);
979 }
980 
981 
992 static void
994  const struct GNUNET_HashCode *key,
995  uint32_t size,
996  int status,
997  const char *msg)
998 {
999  struct GNUNET_SERVICE_Client *client = cls;
1000 
1001  if (GNUNET_SYSERR == status)
1002  {
1003  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "REMOVE request failed: %s.\n", msg);
1004  transmit_status (client, GNUNET_NO, msg);
1005  return;
1006  }
1007  if (GNUNET_NO == status)
1008  {
1010  "Content not found for REMOVE request.\n");
1011  transmit_status (client, GNUNET_NO, _ ("Content not found"));
1012  return;
1013  }
1015  "Item matches REMOVE request for key `%s'.\n",
1016  GNUNET_h2s (key));
1017  GNUNET_STATISTICS_update (stats,
1018  gettext_noop ("# bytes removed (explicit request)"),
1019  size,
1020  GNUNET_YES);
1022  transmit_status (client, GNUNET_OK, NULL);
1023 }
1024 
1025 
1033 static int
1034 check_remove (void *cls, const struct DataMessage *dm)
1035 {
1036  if (GNUNET_OK != check_data (dm))
1037  {
1038  GNUNET_break (0);
1039  return GNUNET_SYSERR;
1040  }
1041  return GNUNET_OK;
1042 }
1043 
1044 
1052 static void
1053 handle_remove (void *cls, const struct DataMessage *dm)
1054 {
1055  struct GNUNET_SERVICE_Client *client = cls;
1056 
1057  GNUNET_STATISTICS_update (stats,
1058  gettext_noop ("# REMOVE requests received"),
1059  1,
1060  GNUNET_NO);
1062  "Processing REMOVE request for `%s'\n",
1063  GNUNET_h2s (&dm->key));
1064  plugin->api->remove_key (plugin->api->cls,
1065  &dm->key,
1066  ntohl (dm->size),
1067  &dm[1],
1069  client);
1071 }
1072 
1073 
1080 static void
1081 handle_drop (void *cls, const struct GNUNET_MessageHeader *message)
1082 {
1083  struct GNUNET_SERVICE_Client *client = cls;
1084 
1085  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing DROP request\n");
1086  do_drop = GNUNET_YES;
1088 }
1089 
1090 
1099 static void
1101 {
1102  if ((delta < 0) && (payload < -delta))
1103  {
1104  GNUNET_log (
1106  _ (
1107  "Datastore payload must have been inaccurate (%lld < %lld). Recomputing it.\n"),
1108  (long long) payload,
1109  (long long) -delta);
1110  plugin->api->estimate_size (plugin->api->cls, &payload);
1112  _ ("New payload: %lld\n"),
1113  (long long) payload);
1114  sync_stats ();
1115  return;
1116  }
1117  payload += delta;
1118  last_sync++;
1120  sync_stats ();
1121 }
1122 
1123 
1134 static int
1135 process_stat_in (void *cls,
1136  const char *subsystem,
1137  const char *name,
1138  uint64_t value,
1139  int is_persistent)
1140 {
1143  payload += value;
1144  GNUNET_log (
1146  "Notification from statistics about existing payload (%llu), new payload is %llu\n",
1147  (unsigned long long) value,
1148  (unsigned long long) payload);
1149  return GNUNET_OK;
1150 }
1151 
1152 
1156 static struct DatastorePlugin *
1158 {
1159  struct DatastorePlugin *ret;
1160  char *libname;
1161 
1162  ret = GNUNET_new (struct DatastorePlugin);
1163  ret->env.cfg = cfg;
1165  ret->env.cls = NULL;
1167  _ ("Loading `%s' datastore plugin\n"),
1168  plugin_name);
1169  GNUNET_asprintf (&libname, "libgnunet_plugin_datastore_%s", plugin_name);
1171  ret->lib_name = libname;
1172  ret->api = GNUNET_PLUGIN_load (libname, &ret->env);
1173  if (NULL == ret->api)
1174  {
1176  _ ("Failed to load datastore plugin for `%s'\n"),
1177  plugin_name);
1178  GNUNET_free (ret->short_name);
1179  GNUNET_free (libname);
1180  GNUNET_free (ret);
1181  return NULL;
1182  }
1183  return ret;
1184 }
1185 
1186 
1193 static void
1195 {
1197  "Datastore service is unloading plugin...\n");
1198  GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
1199  GNUNET_free (plug->lib_name);
1200  GNUNET_free (plug->short_name);
1201  GNUNET_free (plug);
1202 }
1203 
1204 
1208 static void
1210 {
1211  GNUNET_SERVICE_resume (service);
1212  expired_kill_task =
1214  &delete_expired,
1215  NULL);
1216 }
1217 
1218 
1226 static void
1228  const struct GNUNET_HashCode *key,
1229  unsigned int count)
1230 {
1231  struct GNUNET_CONTAINER_BloomFilter *bf = cls;
1232 
1233  if (NULL == key)
1234  {
1236  _ ("Bloomfilter construction complete.\n"));
1237  begin_service ();
1238  return;
1239  }
1240 
1241  while (0 < count--)
1243 }
1244 
1245 
1253 static void
1254 process_stat_done (void *cls, int success)
1255 {
1256  stat_get = NULL;
1257  if (NULL != stat_timeout_task)
1258  {
1259  GNUNET_SCHEDULER_cancel (stat_timeout_task);
1260  stat_timeout_task = NULL;
1261  }
1262  plugin = load_plugin ();
1263  if (NULL == plugin)
1264  {
1266  filter = NULL;
1267  if (NULL != stats)
1268  {
1270  stats = NULL;
1271  }
1272  return;
1273  }
1274 
1275  if (GNUNET_NO == stats_worked)
1276  {
1278  "Failed to obtain value from statistics service, recomputing it\n");
1279  plugin->api->estimate_size (plugin->api->cls, &payload);
1281  _ ("New payload: %lld\n"),
1282  (long long) payload);
1283  }
1284 
1285  if (GNUNET_YES == refresh_bf)
1286  {
1288  _ ("Rebuilding bloomfilter. Please be patient.\n"));
1289  if (NULL != plugin->api->get_keys)
1290  {
1291  plugin->api->get_keys (plugin->api->cls, &add_key_to_bloomfilter, filter);
1292  return;
1293  }
1294  else
1295  {
1297  _ (
1298  "Plugin does not support get_keys function. Please fix!\n"));
1299  }
1300  }
1301  begin_service ();
1302 }
1303 
1304 
1310 static void
1311 stat_timeout (void *cls)
1312 {
1313  stat_timeout_task = NULL;
1314  GNUNET_STATISTICS_get_cancel (stat_get);
1315  process_stat_done (NULL, GNUNET_NO);
1316 }
1317 
1318 
1322 static void
1323 cleaning_task (void *cls)
1324 {
1326  if (NULL != expired_kill_task)
1327  {
1328  GNUNET_SCHEDULER_cancel (expired_kill_task);
1329  expired_kill_task = NULL;
1330  }
1331  if (GNUNET_YES == do_drop)
1332  {
1333  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Dropping database!\n");
1334  plugin->api->drop (plugin->api->cls);
1335  payload = 0;
1336  last_sync++;
1337  }
1338  if (NULL != plugin)
1339  {
1340  unload_plugin (plugin);
1341  plugin = NULL;
1342  }
1343  if (NULL != filter)
1344  {
1346  filter = NULL;
1347  }
1348  if (NULL != stat_get)
1349  {
1350  GNUNET_STATISTICS_get_cancel (stat_get);
1351  stat_get = NULL;
1352  }
1353  if (NULL != stat_timeout_task)
1354  {
1355  GNUNET_SCHEDULER_cancel (stat_timeout_task);
1356  stat_timeout_task = NULL;
1357  }
1359  plugin_name = NULL;
1360  if (last_sync > 0)
1361  sync_stats ();
1362  if (NULL != stats)
1363  {
1365  stats = NULL;
1366  }
1368  quota_stat_name = NULL;
1369 }
1370 
1371 
1380 static void *
1382  struct GNUNET_SERVICE_Client *client,
1383  struct GNUNET_MQ_Handle *mq)
1384 {
1385  return client;
1386 }
1387 
1388 
1397 static void
1399  struct GNUNET_SERVICE_Client *client,
1400  void *app_ctx)
1401 {
1402  struct ReservationList *pos;
1403  struct ReservationList *prev;
1404  struct ReservationList *next;
1405 
1406  GNUNET_assert (app_ctx == client);
1407  prev = NULL;
1408  pos = reservations;
1409  while (NULL != pos)
1410  {
1411  next = pos->next;
1412  if (pos->client == client)
1413  {
1414  if (NULL == prev)
1415  reservations = next;
1416  else
1417  prev->next = next;
1419  GNUNET_free (pos);
1420  }
1421  else
1422  {
1423  prev = pos;
1424  }
1425  pos = next;
1426  }
1427  GNUNET_STATISTICS_set (stats,
1428  gettext_noop ("# reserved"),
1429  reserved,
1430  GNUNET_NO);
1431 }
1432 
1433 
1441 static void
1442 run (void *cls,
1443  const struct GNUNET_CONFIGURATION_Handle *c,
1444  struct GNUNET_SERVICE_Handle *serv)
1445 {
1446  char *fn;
1447  char *pfn;
1448  unsigned int bf_size;
1449 
1450  service = serv;
1451  cfg = c;
1453  "DATASTORE",
1454  "DATABASE",
1455  &plugin_name))
1456  {
1458  "DATABASE",
1459  "DATASTORE");
1460  return;
1461  }
1463  _ ("# bytes used in file-sharing datastore `%s'"),
1464  plugin_name);
1465  if (GNUNET_OK !=
1466  GNUNET_CONFIGURATION_get_value_size (cfg, "DATASTORE", "QUOTA", &quota))
1467  {
1468  GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "QUOTA", "DATASTORE");
1469  return;
1470  }
1471  stats = GNUNET_STATISTICS_create ("datastore", cfg);
1472  GNUNET_STATISTICS_set (stats, gettext_noop ("# quota"), quota, GNUNET_NO);
1473  cache_size = quota / 8; /* Or should we make this an option? */
1474  GNUNET_STATISTICS_set (stats,
1475  gettext_noop ("# cache size"),
1476  cache_size,
1477  GNUNET_NO);
1478  if (quota / (32 * 1024LL) > MAX_BF_SIZE)
1479  bf_size = MAX_BF_SIZE;
1480  else
1481  bf_size =
1482  quota / (32 * 1024LL); /* 8 bit per entry, 1 bit per 32 kb in DB */
1483  fn = NULL;
1485  "DATASTORE",
1486  "BLOOMFILTER",
1487  &fn)) ||
1489  {
1491  _ ("Could not use specified filename `%s' for bloomfilter.\n"),
1492  NULL != fn ? fn : "");
1493  GNUNET_free_non_null (fn);
1494  fn = NULL;
1495  }
1496  if (NULL != fn)
1497  {
1498  GNUNET_asprintf (&pfn, "%s.%s", fn, plugin_name);
1499  if (GNUNET_YES == GNUNET_DISK_file_test (pfn))
1500  {
1501  filter =
1503  bf_size,
1504  5); /* approx. 3% false positives at max use */
1505  if (NULL == filter)
1506  {
1507  /* file exists but not valid, remove and try again, but refresh */
1508  if (0 != unlink (pfn))
1509  {
1510  /* failed to remove, run without file */
1512  _ ("Failed to remove bogus bloomfilter file `%s'\n"),
1513  pfn);
1514  GNUNET_free (pfn);
1515  pfn = NULL;
1517  NULL,
1518  bf_size,
1519  5); /* approx. 3% false positives at max use */
1521  }
1522  else
1523  {
1524  /* try again after remove */
1526  pfn,
1527  bf_size,
1528  5); /* approx. 3% false positives at max use */
1530  if (NULL == filter)
1531  {
1532  /* failed yet again, give up on using file */
1534  _ ("Failed to remove bogus bloomfilter file `%s'\n"),
1535  pfn);
1536  GNUNET_free (pfn);
1537  pfn = NULL;
1539  NULL,
1540  bf_size,
1541  5); /* approx. 3% false positives at max use */
1542  }
1543  }
1544  }
1545  else
1546  {
1547  /* normal case: have an existing valid bf file, no need to refresh */
1549  }
1550  }
1551  else
1552  {
1553  filter =
1555  bf_size,
1556  5); /* approx. 3% false positives at max use */
1558  }
1559  GNUNET_free (pfn);
1560  }
1561  else
1562  {
1563  filter =
1565  bf_size,
1566  5); /* approx. 3% false positives at max use */
1568  }
1569  GNUNET_free_non_null (fn);
1570  if (NULL == filter)
1571  {
1573  _ ("Failed to initialize bloomfilter.\n"));
1574  if (NULL != stats)
1575  {
1577  stats = NULL;
1578  }
1579  return;
1580  }
1581  GNUNET_SERVICE_suspend (service);
1582  stat_get = GNUNET_STATISTICS_get (stats,
1583  "datastore",
1586  &process_stat_in,
1587  NULL);
1588  if (NULL == stat_get)
1590  else
1592  &stat_timeout,
1593  NULL);
1595 }
1596 
1597 
1602  "datastore",
1604  &run,
1607  NULL,
1608  GNUNET_MQ_hd_fixed_size (reserve,
1610  struct ReserveMessage,
1611  NULL),
1612  GNUNET_MQ_hd_fixed_size (release_reserve,
1614  struct ReleaseReserveMessage,
1615  NULL),
1616  GNUNET_MQ_hd_var_size (put,
1618  struct DataMessage,
1619  NULL),
1622  struct GetMessage,
1623  NULL),
1624  GNUNET_MQ_hd_fixed_size (get_key,
1626  struct GetKeyMessage,
1627  NULL),
1628  GNUNET_MQ_hd_fixed_size (get_replication,
1630  struct GNUNET_MessageHeader,
1631  NULL),
1632  GNUNET_MQ_hd_fixed_size (get_zero_anonymity,
1634  struct GetZeroAnonymityMessage,
1635  NULL),
1636  GNUNET_MQ_hd_var_size (remove,
1638  struct DataMessage,
1639  NULL),
1642  struct GNUNET_MessageHeader,
1643  NULL),
1645 
1646 
1647 /* 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:544
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:127
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 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:673
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:247
uint32_t type
Desired content type (actually an enum GNUNET_BLOCK_Type)
Definition: datastore.h:178
uint32_t entries
Number of items to reserve.
Definition: datastore.h:49
void GNUNET_SERVICE_resume(struct GNUNET_SERVICE_Handle *sh)
Resume accepting connections from the listen socket.
Definition: service.c:2194
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:116
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:1183
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2437
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:214
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:1300
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:160
#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:89
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.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
#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:684
Message to the datastore service asking about specific content.
Definition: datastore.h:107
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
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:168
#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:155
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.
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:256
Handle to a client that is connected to a service.
Definition: service.c:250
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:1253
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:1207
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:140
uint32_t type
Desired content type.
Definition: datastore.h:117
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:687
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:2324
#define GNUNET_DATASTORE_ENTRY_OVERHEAD
How many bytes of overhead will we assume per entry in any DB (for reservations)? ...
static char * expiration
Credential TTL.
Definition: gnunet-abd.c:96
uint32_t type
Desired content type.
Definition: datastore.h:150
#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:229
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:204
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:191
struct GNUNET_HashCode key
Desired key.
Definition: datastore.h:132
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:67
static int stats_worked
Did we get an answer from statistics?
uint32_t size
Number of bytes in the item (NBO).
Definition: datastore.h:209
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:224
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.
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:99
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:199
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:85
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:183
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
#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:85
const char * name
struct GNUNET_HashCode key
Key under which the item can be found.
Definition: datastore.h:252
uint32_t priority
Priority of the item (NBO), zero for remove.
Definition: datastore.h:219
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:134
Message from datastore service informing client about the success or failure of a requested operation...
Definition: datastore.h:64
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:74
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:354
#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:207
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:353
#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:122
#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:742
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:2182
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:657
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2243
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:966
uint64_t amount
Number of bytes to reserve.
Definition: datastore.h:54