GNUnet  0.17.6
gnunet-service-fs_pr.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009-2013 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 
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_load_lib.h"
29 #include "gnunet-service-fs.h"
30 #include "gnunet-service-fs_cp.h"
32 #include "gnunet-service-fs_pe.h"
33 #include "gnunet-service-fs_pr.h"
35 
36 
40 #define DHT_GET_REPLICATION 5
41 
47 #define MAX_DATASTORE_QUEUE (16 * MAX_QUEUE_PER_PEER)
48 
55 #define CONTENT_BANDWIDTH_VALUE 800
56 
60 #define MAX_RESULTS (100 * 1024)
61 
65 #define INSANE_STATISTICS GNUNET_NO
66 
71 #define CADET_RETRY_MAX 3
72 
73 
78 {
83 
88 
92  void *rh_cls;
93 
98 
103 
108 
113 
118 
123 
129 
134 
139 
145 
151 
156 
161 
166 
170  bool seen_null;
171 
176  uint64_t first_uid;
177 
181  size_t result_count;
182 
187  unsigned int cadet_retry_count;
188 
192  unsigned int replies_seen_count;
193 
197  unsigned int replies_seen_size;
198 };
199 
200 
206 
207 
212 
213 
218 
219 
229 
230 
236 static unsigned long long max_pending_requests = (32 * 1024);
237 
238 
249 static void
251  struct GSF_PendingRequest *pr)
252 {
253  if (NULL != pr->bg)
254  {
256  pr->bg = NULL;
257  }
259  return; /* no need */
260  pr->bg =
262  type,
263  NULL,
264  0,
265  "seen-set-size",
266  pr->replies_seen_count,
267  NULL);
268  if (NULL == pr->bg)
269  return;
272  pr->replies_seen,
273  pr->replies_seen_count));
274 }
275 
276 
277 struct GSF_PendingRequest *
279  enum GNUNET_BLOCK_Type type,
280  const struct GNUNET_HashCode *query,
281  const struct GNUNET_PeerIdentity *target,
282  const char *bf_data,
283  size_t bf_size,
284  uint32_t anonymity_level,
285  uint32_t priority,
286  int32_t ttl,
289  const struct GNUNET_HashCode *replies_seen,
290  unsigned int replies_seen_count,
292  void *rh_cls)
293 {
294  struct GSF_PendingRequest *pr;
295  struct GSF_PendingRequest *dpr;
296  size_t extra;
297  struct GNUNET_HashCode *eptr;
298 
300  "Creating request handle for `%s' of type %d\n",
301  GNUNET_h2s (query),
302  type);
303 #if INSANE_STATISTICS
305  gettext_noop ("# Pending requests created"),
306  1,
307  GNUNET_NO);
308 #endif
309  extra = 0;
310  if (NULL != target)
311  extra += sizeof(struct GNUNET_PeerIdentity);
312  pr = GNUNET_malloc (sizeof(struct GSF_PendingRequest) + extra);
313  pr->public_data.query = *query;
314  eptr = (struct GNUNET_HashCode *) &pr[1];
315  if (NULL != target)
316  {
317  pr->public_data.target = (struct GNUNET_PeerIdentity *) eptr;
318  GNUNET_memcpy (eptr, target, sizeof(struct GNUNET_PeerIdentity));
319  }
321  pr->public_data.priority = priority;
322  pr->public_data.original_priority = priority;
324  pr->public_data.type = type;
326  pr->sender_pid = sender_pid;
327  pr->origin_pid = origin_pid;
328  pr->rh = rh;
329  pr->rh_cls = rh_cls;
330  GNUNET_assert ((sender_pid != 0) || (0 == (options & GSF_PRO_FORWARD_ONLY)));
331  if (ttl >= 0)
334  else
338  (uint32_t) (-ttl)));
339  if (replies_seen_count > 0)
340  {
341  pr->replies_seen_size = replies_seen_count;
342  pr->replies_seen =
345  replies_seen,
346  replies_seen_count * sizeof(struct GNUNET_HashCode));
347  pr->replies_seen_count = replies_seen_count;
348  }
349  if ((NULL != bf_data) &&
351  {
353  pr->public_data.type,
354  bf_data,
355  bf_size,
356  "seen-set-size",
357  0,
358  NULL);
359  }
360  else if ((replies_seen_count > 0) &&
362  {
364  }
366  &pr->public_data.query,
367  pr,
370  {
372  pr,
374  /* make sure we don't track too many requests */
377  {
379  GNUNET_assert (NULL != dpr);
380  if (pr == dpr)
381  break; /* let the request live briefly... */
382  if (NULL != dpr->rh)
383  dpr->rh (dpr->rh_cls,
385  dpr,
386  UINT32_MAX,
390  NULL,
391  0);
393  }
394  }
396  gettext_noop ("# Pending requests active"),
397  1,
398  GNUNET_NO);
399  return pr;
400 }
401 
402 
409 struct GSF_PendingRequestData *
411 {
412  return &pr->public_data;
413 }
414 
415 
425 int
427  struct GSF_PendingRequest *prb)
428 {
429  if ((pra->public_data.type != prb->public_data.type) ||
430  (0 != memcmp (&pra->public_data.query,
431  &prb->public_data.query,
432  sizeof(struct GNUNET_HashCode))))
433  return GNUNET_NO;
434  return GNUNET_OK;
435 }
436 
437 
438 void
440  const struct GNUNET_HashCode *replies_seen,
441  unsigned int replies_seen_count)
442 {
443  if (replies_seen_count + pr->replies_seen_count < pr->replies_seen_count)
444  return; /* integer overflow */
446  {
447  /* we're responsible for the BF, full refresh */
448  if (replies_seen_count + pr->replies_seen_count > pr->replies_seen_size)
450  pr->replies_seen_size,
451  replies_seen_count + pr->replies_seen_count);
453  replies_seen,
454  sizeof(struct GNUNET_HashCode) * replies_seen_count);
455  pr->replies_seen_count += replies_seen_count;
457  }
458  else
459  {
460  if (NULL == pr->bg)
461  {
462  /* we're not the initiator, but the initiator did not give us
463  * any bloom-filter, so we need to create one on-the-fly */
465  }
466  else
467  {
470  replies_seen,
471  pr->replies_seen_count));
472  }
473  }
474  if (NULL != pr->gh)
476  replies_seen_count,
477  replies_seen);
478 }
479 
480 
488 struct GNUNET_MQ_Envelope *
490 {
491  struct GNUNET_MQ_Envelope *env;
492  struct GetMessage *gm;
493  struct GNUNET_PeerIdentity *ext;
494  unsigned int k;
495  uint32_t bm;
496  uint32_t prio;
497  size_t bf_size;
498  struct GNUNET_TIME_Absolute now;
499  int64_t ttl;
500  int do_route;
501  void *bf_data;
502 
504  "Building request message for `%s' of type %d\n",
506  pr->public_data.type);
507  k = 0;
508  bm = 0;
509  do_route = (0 == (pr->public_data.options & GSF_PRO_FORWARD_ONLY));
510  if ((! do_route) && (pr->sender_pid == 0))
511  {
512  GNUNET_break (0);
513  do_route = GNUNET_YES;
514  }
515  if (! do_route)
516  {
518  k++;
519  }
520  if (NULL != pr->public_data.target)
521  {
523  k++;
524  }
525  if (GNUNET_OK !=
527  &bf_data,
528  &bf_size))
529  {
530  bf_size = 0;
531  bf_data = NULL;
532  }
533  env = GNUNET_MQ_msg_extra (gm,
534  bf_size + k * sizeof(struct GNUNET_PeerIdentity),
536  gm->type = htonl (pr->public_data.type);
537  if (do_route)
539  pr->public_data.priority + 1);
540  else
541  prio = 0;
542  pr->public_data.priority -= prio;
544  pr->public_data.respect_offered += prio;
545  gm->priority = htonl (prio);
546  now = GNUNET_TIME_absolute_get ();
547  ttl = (int64_t) (pr->public_data.ttl.abs_value_us - now.abs_value_us);
548  gm->ttl = htonl (ttl / 1000LL / 1000LL);
549  gm->reserved = htonl (0);
550  gm->hash_bitmap = htonl (bm);
551  gm->query = pr->public_data.query;
552  ext = (struct GNUNET_PeerIdentity *) &gm[1];
553  k = 0;
554  if (! do_route)
555  GNUNET_PEER_resolve (pr->sender_pid, &ext[k++]);
556  if (NULL != pr->public_data.target)
557  ext[k++] = *pr->public_data.target;
558  GNUNET_memcpy (&ext[k], bf_data, bf_size);
559  GNUNET_free (bf_data);
560  return env;
561 }
562 
563 
572 static int
573 clean_request (void *cls, const struct GNUNET_HashCode *key, void *value)
574 {
575  struct GSF_PendingRequest *pr = value;
577 
579  "Cleaning up pending request for `%s'.\n",
580  GNUNET_h2s (key));
581  if (NULL != pr->cadet_request)
582  {
585  pr->cadet_request = NULL;
586  }
587  if (NULL != (cont = pr->llc_cont))
588  {
589  pr->llc_cont = NULL;
590  cont (pr->llc_cont_cls,
591  pr,
592  pr->local_result);
593  }
597  pr->bg = NULL;
599  pr->sender_pid = 0;
601  pr->origin_pid = 0;
602  if (NULL != pr->hnode)
603  {
605  pr->hnode = NULL;
606  }
607  if (NULL != pr->qe)
608  {
610  pr->qe = NULL;
611  }
612  if (NULL != pr->gh)
613  {
614  GNUNET_DHT_get_stop (pr->gh);
615  pr->gh = NULL;
616  }
617  if (NULL != pr->warn_task)
618  {
620  pr->warn_task = NULL;
621  }
622  GNUNET_assert (
623  GNUNET_OK ==
626  gettext_noop ("# Pending requests active"),
627  -1,
628  GNUNET_NO);
629  GNUNET_free (pr);
630  return GNUNET_YES;
631 }
632 
633 
640 void
641 GSF_pending_request_cancel_ (struct GSF_PendingRequest *pr, int full_cleanup)
642 {
644 
645  if (NULL == pr_map)
646  return; /* already cleaned up! */
647  if (GNUNET_NO == full_cleanup)
648  {
649  /* make request inactive (we're no longer interested in more results),
650  * but do NOT remove from our data-structures, we still need it there
651  * to prevent the request from looping */
652  pr->rh = NULL;
653  if (NULL != pr->cadet_request)
654  {
657  pr->cadet_request = NULL;
658  }
659  if (NULL != (cont = pr->llc_cont))
660  {
661  pr->llc_cont = NULL;
662  cont (pr->llc_cont_cls,
663  pr,
664  pr->local_result);
665  }
667  if (NULL != pr->qe)
668  {
670  pr->qe = NULL;
671  }
672  if (NULL != pr->gh)
673  {
674  GNUNET_DHT_get_stop (pr->gh);
675  pr->gh = NULL;
676  }
677  if (NULL != pr->warn_task)
678  {
680  pr->warn_task = NULL;
681  }
682  return;
683  }
685  clean_request (NULL, &pr->public_data.query, pr));
686 }
687 
688 
689 void
691 {
693  pr_map,
695  cls);
696 }
697 
698 
703 {
707  const void *data;
708 
713 
718 
722  size_t size;
723 
727  enum GNUNET_BLOCK_Type type;
728 
732  uint32_t priority;
733 
737  uint32_t anonymity_level;
738 
743 
748 };
749 
750 
758 static void
760  struct GSF_PendingRequest *pr)
761 {
762  if (prq->sender == NULL)
763  return;
766  prq->priority);
767 }
768 
769 
778 static enum GNUNET_GenericReturnValue
779 process_reply (void *cls,
780  const struct GNUNET_HashCode *key,
781  void *value)
782 {
783  struct ProcessReplyClosure *prq = cls;
784  struct GSF_PendingRequest *pr = value;
785  struct GNUNET_HashCode chash;
787 
788  if (NULL == pr->rh)
789  return GNUNET_YES;
791  "Matched result (type %u) for query `%s' with pending request\n",
792  (unsigned int) prq->type,
793  GNUNET_h2s (key));
795  gettext_noop ("# replies received and matched"),
796  1,
797  GNUNET_NO);
799  prq->type,
800  pr->bg,
801  key,
802  NULL, 0,
803  prq->data,
804  prq->size);
805  switch (prq->eval)
806  {
809  break;
811  /* short cut: stop processing early, no BF-update, etc. */
816  .rel_value_us);
817  if (GNUNET_YES !=
819  .pr_head,
820  prq->sender,
823  /* pass on to other peers / local clients */
824  pr->rh (pr->rh_cls,
825  prq->eval,
826  pr,
827  prq->anonymity_level,
828  prq->expiration,
830  prq->type,
831  prq->data,
832  prq->size);
833  return GNUNET_YES;
835 #if INSANE_STATISTICS
837  "# duplicate replies discarded (bloomfilter)",
838  1,
839  GNUNET_NO);
840 #endif
842  "Duplicate response, discarding.\n");
843  return GNUNET_YES; /* duplicate */
846  "# irrelevant replies discarded",
847  1,
848  GNUNET_NO);
850  "Irrelevant response, ignoring.\n");
851  return GNUNET_YES;
853  GNUNET_break (0); /* bad installation? */
854  return GNUNET_NO;
855  }
856  /* update bloomfilter */
857  GNUNET_CRYPTO_hash (prq->data,
858  prq->size,
859  &chash);
861  &chash,
862  1);
863  if (NULL == prq->sender)
864  {
866  "Found result for query `%s' in local datastore\n",
867  GNUNET_h2s (key));
869  gettext_noop ("# results found locally"),
870  1,
871  GNUNET_NO);
872  }
873  else
874  {
875  GSF_dht_lookup_ (pr);
876  }
878  pr->public_data.priority = 0;
881  prq->request_found = GNUNET_YES;
882  /* finally, pass on to other peer / local client */
884  .pr_head,
885  prq->sender,
888  pr->rh (pr->rh_cls,
889  prq->eval,
890  pr,
891  prq->anonymity_level,
892  prq->expiration,
894  prq->type,
895  prq->data,
896  prq->size);
897  return GNUNET_YES;
898 }
899 
900 
905 {
910 
915 
921 };
922 
923 
933 static void
935  int success,
937  const char *msg)
938 {
939  struct PutMigrationContext *pmc = cls;
940  struct GSF_ConnectedPeer *cp;
941  struct GNUNET_TIME_Relative mig_pause;
942  struct GSF_PeerPerformanceData *ppd;
943 
944  if (NULL != datastore_put_load)
945  {
946  if (GNUNET_SYSERR != success)
947  {
950  .rel_value_us);
951  }
952  else
953  {
954  /* on queue failure / timeout, increase the put load dramatically */
956  GNUNET_TIME_UNIT_MINUTES.rel_value_us);
957  }
958  }
959  cp = GSF_peer_get_ (&pmc->origin);
960  if (GNUNET_OK == success)
961  {
962  if (NULL != cp)
963  {
965  ppd->migration_delay.rel_value_us /= 2;
966  }
967  GNUNET_free (pmc);
968  return;
969  }
970  if ((GNUNET_NO == success) && (GNUNET_NO == pmc->requested) && (NULL != cp))
971  {
974  {
976  "Asking to stop migration for %s because datastore is full\n",
979  GNUNET_YES));
981  }
982  else
983  {
985  ppd->migration_delay);
986  ppd->migration_delay =
988  mig_pause.rel_value_us =
991  ppd->migration_delay =
993  GNUNET_log (
995  "Replicated content already exists locally, asking to stop migration for %s\n",
999  }
1000  }
1001  GNUNET_free (pmc);
1003  gettext_noop ("# Datastore `PUT' failures"),
1004  1,
1005  GNUNET_NO);
1006 }
1007 
1008 
1018 static int
1019 test_put_load_too_high (uint32_t priority)
1020 {
1021  double ld;
1022 
1023  if (NULL == datastore_put_load)
1024  return GNUNET_NO;
1026  return GNUNET_NO; /* very fast */
1028  if (ld < 2.0 * (1 + priority))
1029  return GNUNET_NO;
1031  gettext_noop (
1032  "# storage requests dropped due to high load"),
1033  1,
1034  GNUNET_NO);
1035  return GNUNET_YES;
1036 }
1037 
1038 
1055 static void
1056 handle_dht_reply (void *cls,
1057  struct GNUNET_TIME_Absolute exp,
1058  const struct GNUNET_HashCode *key,
1059  const struct GNUNET_PeerIdentity *trunc_peer,
1060  const struct GNUNET_DHT_PathElement *get_path,
1061  unsigned int get_path_length,
1062  const struct GNUNET_DHT_PathElement *put_path,
1063  unsigned int put_path_length,
1064  enum GNUNET_BLOCK_Type type,
1065  size_t size,
1066  const void *data)
1067 {
1068  struct GSF_PendingRequest *pr = cls;
1069  struct ProcessReplyClosure prq;
1070  struct PutMigrationContext *pmc;
1071 
1073  gettext_noop ("# Replies received from DHT"),
1074  1,
1075  GNUNET_NO);
1076  memset (&prq, 0, sizeof(prq));
1077  prq.data = data;
1078  prq.expiration = exp;
1079  /* do not allow migrated content to live longer than 1 year */
1082  prq.expiration);
1083  prq.size = size;
1084  prq.type = type;
1085  process_reply (&prq,
1086  key,
1087  pr);
1088  if ((GNUNET_YES == active_to_migration) &&
1090  {
1092  "Replicating result for query `%s' with priority %u\n",
1093  GNUNET_h2s (key),
1094  prq.priority);
1095  pmc = GNUNET_new (struct PutMigrationContext);
1096  pmc->start = GNUNET_TIME_absolute_get ();
1097  pmc->requested = GNUNET_YES;
1098  if (NULL == GNUNET_DATASTORE_put (GSF_dsh,
1099  0,
1100  key,
1101  size,
1102  data,
1103  type,
1104  prq.priority,
1105  1 /* anonymity */,
1106  0 /* replication */,
1107  exp,
1108  1 + prq.priority,
1111  pmc))
1112  {
1114  GNUNET_SYSERR,
1116  NULL);
1117  }
1118  }
1119 }
1120 
1121 
1127 void
1129 {
1130  const void *xquery;
1131  size_t xquery_size;
1132  struct GNUNET_PeerIdentity pi;
1133  char buf[sizeof(struct GNUNET_HashCode) * 2] GNUNET_ALIGN;
1134 
1135  if (0 != pr->public_data.anonymity_level)
1136  return;
1137  if (NULL != pr->gh)
1138  {
1139  GNUNET_DHT_get_stop (pr->gh);
1140  pr->gh = NULL;
1141  }
1142  xquery = NULL;
1143  xquery_size = 0;
1144  if (0 != (pr->public_data.options & GSF_PRO_FORWARD_ONLY))
1145  {
1146  GNUNET_assert (0 != pr->sender_pid);
1148  GNUNET_memcpy (&buf[xquery_size], &pi, sizeof(struct GNUNET_PeerIdentity));
1149  xquery_size += sizeof(struct GNUNET_PeerIdentity);
1150  }
1152  pr->public_data.type,
1153  &pr->public_data.query,
1156  xquery,
1157  xquery_size,
1159  pr);
1160  if ((NULL != pr->gh) && (0 != pr->replies_seen_count))
1162  pr->replies_seen_count,
1163  pr->replies_seen);
1164 }
1165 
1166 
1176 static void
1177 cadet_reply_proc (void *cls,
1178  enum GNUNET_BLOCK_Type type,
1180  size_t data_size,
1181  const void *data)
1182 {
1183  struct GSF_PendingRequest *pr = cls;
1184  struct ProcessReplyClosure prq;
1185  struct GNUNET_HashCode query;
1186 
1187  pr->cadet_request = NULL;
1188  if (GNUNET_OK !=
1190  type,
1191  data,
1192  data_size))
1193  {
1194  GNUNET_break_op (0);
1195  return;
1196  }
1197  if (GNUNET_BLOCK_TYPE_ANY == type)
1198  {
1199  GNUNET_break (NULL == data);
1200  GNUNET_break (0 == data_size);
1201  pr->cadet_retry_count++;
1203  return; /* give up on cadet */
1204  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error retrieiving block via cadet\n");
1205  /* retry -- without delay, as this is non-anonymous
1206  and cadet/cadet connect will take some time anyway */
1208  &pr->public_data.query,
1209  pr->public_data.type,
1211  pr);
1212  return;
1213  }
1214  if (GNUNET_YES !=
1216  type,
1217  data,
1218  data_size,
1219  &query))
1220  {
1222  "Failed to derive key for block of type %d\n",
1223  (int) type);
1224  GNUNET_break_op (0);
1225  return;
1226  }
1228  gettext_noop ("# Replies received from CADET"),
1229  1,
1230  GNUNET_NO);
1231  memset (&prq, 0, sizeof(prq));
1232  prq.data = data;
1233  prq.expiration = expiration;
1234  /* do not allow migrated content to live longer than 1 year */
1237  prq.expiration);
1238  prq.size = data_size;
1239  prq.type = type;
1240  process_reply (&prq,
1241  &query,
1242  pr);
1243 }
1244 
1245 
1251 void
1253 {
1254  if (0 != pr->public_data.anonymity_level)
1255  return;
1256  if (0 == pr->public_data.target)
1257  {
1259  "Cannot do cadet-based download, target peer not known\n");
1260  return;
1261  }
1262  if (NULL != pr->cadet_request)
1263  return;
1265  &pr->public_data.query,
1266  pr->public_data.type,
1268  pr);
1269 }
1270 
1271 
1277 static void
1278 warn_delay_task (void *cls)
1279 {
1280  struct GSF_PendingRequest *pr = cls;
1281 
1283  _ ("Datastore lookup already took %s!\n"),
1286  GNUNET_YES));
1288  &warn_delay_task,
1289  pr);
1290 }
1291 
1292 
1298 static void
1300 {
1301  struct GSF_PendingRequest *pr = cls;
1302 
1304  _ ("On-demand lookup already took %s!\n"),
1307  GNUNET_YES));
1310  pr);
1311 }
1312 
1313 
1314 /* Call our continuation (if we have any) */
1315 static void
1317 {
1319 
1320  GNUNET_assert (NULL == pr->qe);
1321  if (NULL != pr->warn_task)
1322  {
1324  pr->warn_task = NULL;
1325  }
1326  if (NULL == cont)
1327  return; /* no continuation */
1328  pr->llc_cont = NULL;
1329  if (0 != (GSF_PRO_LOCAL_ONLY & pr->public_data.options))
1330  {
1332  {
1333  /* Signal that we are done and that there won't be any
1334  additional results to allow client to clean up state. */
1335  pr->rh (pr->rh_cls,
1337  pr,
1338  UINT32_MAX,
1342  NULL,
1343  0);
1344  }
1345  /* Finally, call our continuation to signal that we are
1346  done with local processing of this request; i.e. to
1347  start reading again from the client. */
1348  cont (pr->llc_cont_cls,
1349  NULL,
1351  return;
1352  }
1353 
1354  cont (pr->llc_cont_cls,
1355  pr,
1356  pr->local_result);
1357 }
1358 
1359 
1360 /* Update stats and call continuation */
1361 static void
1363 {
1365  "No further local responses available.\n");
1366 #if INSANE_STATISTICS
1370  gettext_noop (
1371  "# requested DBLOCK or IBLOCK not found"),
1372  1,
1373  GNUNET_NO);
1374 #endif
1375  call_continuation (pr);
1376 }
1377 
1378 
1379 /* forward declaration */
1380 static void
1381 process_local_reply (void *cls,
1382  const struct GNUNET_HashCode *key,
1383  size_t size,
1384  const void *data,
1385  enum GNUNET_BLOCK_Type type,
1386  uint32_t priority,
1387  uint32_t anonymity,
1388  uint32_t replication,
1390  uint64_t uid);
1391 
1392 
1393 /* Start a local query */
1394 static void
1396  uint64_t next_uid,
1397  bool random)
1398 {
1401  &warn_delay_task,
1402  pr);
1404  next_uid,
1405  random,
1406  &pr->public_data.query,
1407  pr->public_data.type ==
1410  : pr->public_data.type,
1412  & pr->public_data.options))
1413  ? UINT_MAX
1414  : 1
1415  /* queue priority */,
1417  & pr->public_data.options))
1418  ? UINT_MAX
1420  /* max queue size */,
1422  pr);
1423  if (NULL != pr->qe)
1424  return;
1425  GNUNET_log (
1427  "ERROR Requesting `%s' of type %d with next_uid %llu from datastore.\n",
1428  GNUNET_h2s (&pr->public_data.query),
1429  pr->public_data.type,
1430  (unsigned long long) next_uid);
1432  gettext_noop (
1433  "# Datastore lookups concluded (error queueing)"),
1434  1,
1435  GNUNET_NO);
1436  call_continuation (pr);
1437 }
1438 
1439 
1458 static void
1460  const struct GNUNET_HashCode *key,
1461  size_t size,
1462  const void *data,
1463  enum GNUNET_BLOCK_Type type,
1464  uint32_t priority,
1465  uint32_t anonymity,
1466  uint32_t replication,
1468  uint64_t uid)
1469 {
1470  struct GSF_PendingRequest *pr = cls;
1471  struct ProcessReplyClosure prq;
1472  struct GNUNET_HashCode query;
1473  unsigned int old_rf;
1474 
1476  pr->warn_task = NULL;
1477  if (NULL == pr->qe)
1478  goto called_from_on_demand;
1479  pr->qe = NULL;
1480  if (
1481  (NULL == key) && pr->seen_null &&
1482  ! pr->have_first_uid) /* We have hit the end for the 2nd time with no results */
1483  {
1484  /* No results */
1485 #if INSANE_STATISTICS
1487  gettext_noop (
1488  "# Datastore lookups concluded (no results)"),
1489  1,
1490  GNUNET_NO);
1491 #endif
1492  no_more_local_results (pr);
1493  return;
1494  }
1495  if (((NULL == key) &&
1496  pr->seen_null) || /* We have hit the end for the 2nd time OR */
1497  (pr->seen_null && pr->have_first_uid &&
1498  (uid >= pr->first_uid))) /* We have hit the end and past first UID */
1499  {
1500  /* Seen all results */
1502  gettext_noop (
1503  "# Datastore lookups concluded (seen all)"),
1504  1,
1505  GNUNET_NO);
1506  no_more_local_results (pr);
1507  return;
1508  }
1509  if (NULL == key)
1510  {
1511  GNUNET_assert (! pr->seen_null);
1512  pr->seen_null = true;
1513  start_local_query (pr, 0 /* next_uid */, false /* random */);
1514  return;
1515  }
1516  if (! pr->have_first_uid)
1517  {
1518  pr->first_uid = uid;
1519  pr->have_first_uid = true;
1520  }
1521  pr->result_count++;
1522  if (pr->result_count > MAX_RESULTS)
1523  {
1525  GSF_stats,
1526  gettext_noop ("# Datastore lookups aborted (more than MAX_RESULTS)"),
1527  1,
1528  GNUNET_NO);
1529  no_more_local_results (pr);
1530  return;
1531  }
1533  "Received reply for `%s' of type %d with UID %llu from datastore.\n",
1534  GNUNET_h2s (key),
1535  type,
1536  (unsigned long long) uid);
1538  {
1540  "Found ONDEMAND block, performing on-demand encoding\n");
1542  gettext_noop (
1543  "# on-demand blocks matched requests"),
1544  1,
1545  GNUNET_NO);
1549  pr);
1551  size,
1552  data,
1553  type,
1554  priority,
1555  anonymity,
1556  replication,
1557  expiration,
1558  uid,
1560  pr))
1561  {
1563  gettext_noop (
1564  "# on-demand lookups performed successfully"),
1565  1,
1566  GNUNET_NO);
1567  return; /* we're done */
1568  }
1570  gettext_noop ("# on-demand lookups failed"),
1571  1,
1572  GNUNET_NO);
1574  start_local_query (pr, uid + 1 /* next_uid */, false /* random */);
1575  return;
1576  }
1577 called_from_on_demand:
1578  old_rf = pr->public_data.results_found;
1579  memset (&prq, 0, sizeof(prq));
1580  prq.data = data;
1581  prq.expiration = expiration;
1582  prq.size = size;
1583  if (GNUNET_OK !=
1585  type,
1586  data,
1587  size,
1588  &query))
1589  {
1590  GNUNET_break (0);
1592  key,
1593  size,
1594  data,
1595  UINT_MAX,
1596  UINT_MAX,
1597  NULL,
1598  NULL);
1599  start_local_query (pr, uid + 1 /* next_uid */, false /* random */);
1600  return;
1601  }
1602  prq.type = type;
1603  prq.priority = priority;
1604  prq.request_found = GNUNET_NO;
1605  prq.anonymity_level = anonymity;
1606  if ((0 == old_rf) && (0 == pr->public_data.results_found))
1608  process_reply (&prq,
1609  key,
1610  pr);
1611  pr->local_result = prq.eval;
1612  if (GNUNET_BLOCK_REPLY_OK_LAST == prq.eval)
1613  {
1615  GSF_stats,
1616  gettext_noop ("# Datastore lookups concluded (found last result)"),
1617  1,
1618  GNUNET_NO);
1619  call_continuation (pr);
1620  return;
1621  }
1622  if ((0 == (GSF_PRO_PRIORITY_UNLIMITED & pr->public_data.options)) &&
1624  (pr->public_data.results_found > 5 + 2 * pr->public_data.priority)))
1625  {
1626  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Load too high, done with request\n");
1628  gettext_noop (
1629  "# Datastore lookups concluded (load too high)"),
1630  1,
1631  GNUNET_NO);
1632  call_continuation (pr);
1633  return;
1634  }
1635  start_local_query (pr, uid + 1 /* next_uid */, false /* random */);
1636 }
1637 
1638 
1646 int
1648  const struct GNUNET_PeerIdentity *target)
1649 {
1650  struct GNUNET_PeerIdentity pi;
1651 
1652  if (0 == pr->origin_pid)
1653  return GNUNET_YES;
1655  return (0 == memcmp (&pi, target, sizeof(struct GNUNET_PeerIdentity)))
1656  ? GNUNET_NO
1657  : GNUNET_YES;
1658 }
1659 
1660 
1668 void
1671  void *cont_cls)
1672 {
1673  GNUNET_assert (NULL == pr->gh);
1674  GNUNET_assert (NULL == pr->cadet_request);
1675  GNUNET_assert (NULL == pr->llc_cont);
1676  pr->llc_cont = cont;
1677  pr->llc_cont_cls = cont_cls;
1678 #if INSANE_STATISTICS
1680  gettext_noop ("# Datastore lookups initiated"),
1681  1,
1682  GNUNET_NO);
1683 #endif
1684  start_local_query (pr, 0 /* next_uid */, true /* random */);
1685 }
1686 
1687 
1697 void
1698 handle_p2p_put (void *cls,
1699  const struct PutMessage *put)
1700 {
1701  struct GSF_ConnectedPeer *cp = cls;
1702  uint16_t msize;
1703  size_t dsize;
1704  enum GNUNET_BLOCK_Type type;
1706  struct GNUNET_HashCode query;
1707  struct ProcessReplyClosure prq;
1708  struct GNUNET_TIME_Relative block_time;
1709  double putl;
1710  struct PutMigrationContext *pmc;
1711 
1713  "Received P2P PUT from %s\n",
1716  msize = ntohs (put->header.size);
1717  dsize = msize - sizeof(struct PutMessage);
1718  type = ntohl (put->type);
1720  /* do not allow migrated content to live longer than 1 year */
1723  expiration);
1724  if (GNUNET_OK !=
1726  type,
1727  &put[1],
1728  dsize))
1729  {
1730  GNUNET_break_op (0);
1731  return;
1732  }
1733  if (GNUNET_OK !=
1735  type,
1736  &put[1],
1737  dsize,
1738  &query))
1739  {
1740  GNUNET_break_op (0);
1741  return;
1742  }
1744  gettext_noop ("# GAP PUT messages received"),
1745  1,
1746  GNUNET_NO);
1747  /* now, lookup 'query' */
1748  prq.data = (const void *) &put[1];
1749  prq.sender = cp;
1750  prq.size = dsize;
1751  prq.type = type;
1752  prq.expiration = expiration;
1753  prq.priority = 0;
1754  prq.anonymity_level = UINT32_MAX;
1755  prq.request_found = GNUNET_NO;
1757  &query,
1758  &process_reply,
1759  &prq);
1760  if (NULL != cp)
1761  {
1764  + 1000 * prq.priority);
1766  }
1767  if ((GNUNET_YES == active_to_migration) && (NULL != cp) &&
1769  {
1771  "Replicating result for query `%s' with priority %u\n",
1772  GNUNET_h2s (&query),
1773  prq.priority);
1774  pmc = GNUNET_new (struct PutMigrationContext);
1775  pmc->start = GNUNET_TIME_absolute_get ();
1776  pmc->requested = prq.request_found;
1779  &pmc->origin);
1780  if (NULL == GNUNET_DATASTORE_put (GSF_dsh,
1781  0,
1782  &query,
1783  dsize,
1784  &put[1],
1785  type,
1786  prq.priority,
1787  1 /* anonymity */,
1788  0 /* replication */,
1789  expiration,
1790  1 + prq.priority,
1793  pmc))
1794  {
1796  GNUNET_SYSERR,
1798  NULL);
1799  }
1800  }
1801  else if (NULL != cp)
1802  {
1804  "Choosing not to keep content `%s' (%d/%d)\n",
1805  GNUNET_h2s (&query),
1808  }
1810  if ((NULL != cp) && (GNUNET_NO == prq.request_found) &&
1812  (putl > 2.5 * (1 + prq.priority))))
1813  {
1816  block_time = GNUNET_TIME_relative_multiply (
1819  (unsigned int) (60000 * putl * putl)));
1820  GNUNET_log (
1822  "Asking to stop migration for %s because of load %f and events %d/%d\n",
1824  putl,
1826  (GNUNET_NO == prq.request_found));
1828  GNUNET_TIME_relative_to_absolute (block_time));
1829  }
1830 }
1831 
1832 
1839 int
1841 {
1842  return (NULL != pr->rh) ? GNUNET_YES : GNUNET_NO;
1843 }
1844 
1845 
1849 void
1851 {
1852  if (GNUNET_OK !=
1854  "fs",
1855  "MAX_PENDING_REQUESTS",
1857  {
1859  "fs",
1860  "MAX_PENDING_REQUESTS");
1861  }
1863  GNUNET_CONFIGURATION_get_value_yesno (GSF_cfg, "FS", "CONTENT_CACHING");
1868 }
1869 
1870 
1874 void
1876 {
1879  pr_map = NULL;
1883  datastore_put_load = NULL;
1884 }
1885 
1886 
1887 /* end of gnunet-service-fs_pr.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define gettext_noop(String)
Definition: gettext.h:69
static char * expiration
Credential TTL.
Definition: gnunet-abd.c:96
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
static unsigned int anonymity_level
Anonymity level option to use for publishing.
static unsigned int replication
static struct GNUNET_PEERINFO_Handle * pi
Handle to peerinfo service.
struct GNUNET_HashCode key
The key used in the DHT.
static unsigned int anonymity
uint32_t data
The data value.
static char * value
Value of the record to add/remove.
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...
void GSF_update_datastore_delay_(struct GNUNET_TIME_Absolute start)
We've just now completed a datastore request.
struct GNUNET_BLOCK_Context * GSF_block_ctx
Our block context.
struct GNUNET_DHT_Handle * GSF_dht
Handle for DHT operations.
int GSF_test_get_load_too_high_(uint32_t priority)
Test if the DATABASE (GET) load on this peer is too high to even consider processing the query at all...
struct GNUNET_STATISTICS_Handle * GSF_stats
Handle for reporting statistics.
const struct GNUNET_CONFIGURATION_Handle * GSF_cfg
Our configuration.
unsigned int GSF_cover_content_count
How many content messages have we received 'recently' that have not yet been claimed as cover traffic...
struct GNUNET_LOAD_Value * GSF_rt_entry_lifetime
How long do requests typically stay in the routing table?
struct GNUNET_DATASTORE_Handle * GSF_dsh
Our connection to the datastore.
unsigned int GSF_datastore_queue_size
Size of the datastore queue we assume for common requests.
shared data structures of gnunet-service-fs.c
#define GET_MESSAGE_BIT_TRANSMIT_TO
The peer identity of a peer that had claimed to have the content previously is included (can be used ...
#define DATASTORE_LOAD_AUTODECLINE
At what frequency should our datastore load decrease automatically (since if we don't use it,...
#define GET_MESSAGE_BIT_RETURN_TO
The peer identity of a peer waiting for the reply is included (used if the response should be transmi...
non-anonymous file-transfer
void GSF_cadet_query_cancel(struct GSF_CadetRequest *sr)
Cancel an active request; must not be called after 'proc' was called.
struct GSF_CadetRequest * GSF_cadet_query(const struct GNUNET_PeerIdentity *target, const struct GNUNET_HashCode *query, enum GNUNET_BLOCK_Type type, GSF_CadetReplyProcessor proc, void *proc_cls)
Look for a block by directly contacting a particular peer.
struct GSF_ConnectedPeer * GSF_peer_get_(const struct GNUNET_PeerIdentity *peer)
Get a handle for a connected peer.
void GSF_block_peer_migration_(struct GSF_ConnectedPeer *cp, struct GNUNET_TIME_Absolute block_time)
Ask a peer to stop migrating data to us until the given point in time.
void GSF_peer_update_performance_(struct GSF_ConnectedPeer *cp, struct GNUNET_TIME_Absolute request_time, uint32_t request_priority)
Report on receiving a reply; update the performance record of the given peer.
void GSF_connected_peer_change_preference_(struct GSF_ConnectedPeer *cp, uint64_t pref)
Notify core about a preference we have for the given peer (to allocate more resources towards it).
struct GSF_PeerPerformanceData * GSF_get_peer_performance_data_(struct GSF_ConnectedPeer *cp)
Return the performance data record for the given peer.
API to handle 'connected peers'.
int GNUNET_FS_handle_on_demand_block(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, GNUNET_DATASTORE_DatumProcessor cont, void *cont_cls)
We've received an on-demand encoded block from the datastore.
indexing for the file-sharing service
int GSF_request_plan_reference_get_last_transmission_(struct GSF_PendingRequestPlanBijection *pr_head, struct GSF_ConnectedPeer *sender, struct GNUNET_TIME_Absolute *result)
Get the last transmission attempt time for the request plan list referenced by pr_head,...
void GSF_plan_notify_request_done_(struct GSF_PendingRequest *pr)
Notify the plan about a request being done; destroy all entries associated with this request.
API to manage query plan.
int GSF_pending_request_test_target_(struct GSF_PendingRequest *pr, const struct GNUNET_PeerIdentity *target)
Is the given target a legitimate peer for forwarding the given request?
static void update_request_performance_data(struct ProcessReplyClosure *prq, struct GSF_PendingRequest *pr)
Update the performance data for the sender (if any) since the sender successfully answered one of our...
static void put_migration_continuation(void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg)
Continuation called to notify client about result of the operation.
#define MAX_RESULTS
Hard limit on the number of results we may get from the datastore per query.
static void handle_dht_reply(void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *trunc_peer, const struct GNUNET_DHT_PathElement *get_path, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data)
Iterator called on each result obtained for a DHT operation that expects a reply.
#define MAX_DATASTORE_QUEUE
Maximum size of the datastore queue for P2P operations.
static unsigned long long max_pending_requests
Maximum number of requests (from other peers, overall) that we're willing to have pending at any give...
static int active_to_migration
Are we allowed to migrate content to this peer.
#define CONTENT_BANDWIDTH_VALUE
Bandwidth value of a 0-priority content (must be fairly high compared to query since content is typic...
void GSF_cadet_lookup_(struct GSF_PendingRequest *pr)
Consider downloading via cadet (if possible)
#define DHT_GET_REPLICATION
Desired replication level for GETs.
static int test_put_load_too_high(uint32_t priority)
Test if the DATABASE (PUT) load on this peer is too high to even consider processing the query at all...
int GSF_pending_request_is_compatible_(struct GSF_PendingRequest *pra, struct GSF_PendingRequest *prb)
Test if two pending requests are compatible (would generate the same query modulo filters and should ...
static void no_more_local_results(struct GSF_PendingRequest *pr)
void GSF_dht_lookup_(struct GSF_PendingRequest *pr)
Consider looking up the data in the DHT (anonymity-level permitting).
void GSF_iterate_pending_requests_(GSF_PendingRequestIterator it, void *cls)
Iterate over all pending requests.
static void process_local_reply(void *cls, const struct GNUNET_HashCode *key, size_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)
We're processing (local) results for a search request from another peer.
void GSF_local_lookup_(struct GSF_PendingRequest *pr, GSF_LocalLookupContinuation cont, void *cont_cls)
Look up the request in the local datastore.
static void odc_warn_delay_task(void *cls)
Task that issues a warning if the datastore lookup takes too long.
static void call_continuation(struct GSF_PendingRequest *pr)
void GSF_pending_request_init_()
Setup the subsystem.
struct GNUNET_MQ_Envelope * GSF_pending_request_get_message_(struct GSF_PendingRequest *pr)
Generate the message corresponding to the given pending request for transmission to other peers.
void handle_p2p_put(void *cls, const struct PutMessage *put)
Handle P2P "CONTENT" message.
int GSF_pending_request_test_active_(struct GSF_PendingRequest *pr)
Check if the given request is still active.
static void refresh_bloomfilter(enum GNUNET_BLOCK_Type type, struct GSF_PendingRequest *pr)
Recalculate our bloom filter for filtering replies.
static void warn_delay_task(void *cls)
Task that issues a warning if the datastore lookup takes too long.
void GSF_pending_request_done_()
Shutdown the subsystem.
#define CADET_RETRY_MAX
If obtaining a block via cadet fails, how often do we retry it before giving up for good (and stickin...
static enum GNUNET_GenericReturnValue process_reply(void *cls, const struct GNUNET_HashCode *key, void *value)
We have received a reply; handle it!
static struct GNUNET_LOAD_Value * datastore_put_load
Datastore 'PUT' load tracking.
static struct GNUNET_CONTAINER_Heap * requests_by_expiration_heap
Heap with the request that will expire next at the top.
static struct GNUNET_CONTAINER_MultiHashMap * pr_map
All pending requests, ordered by the query.
static int clean_request(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator to free pending requests.
struct GSF_PendingRequestData * GSF_pending_request_get_data_(struct GSF_PendingRequest *pr)
Obtain the public data associated with a pending request.
struct GSF_PendingRequest * GSF_pending_request_create_(enum GSF_PendingRequestOptions options, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *query, const struct GNUNET_PeerIdentity *target, const char *bf_data, size_t bf_size, uint32_t anonymity_level, uint32_t priority, int32_t ttl, GNUNET_PEER_Id sender_pid, GNUNET_PEER_Id origin_pid, const struct GNUNET_HashCode *replies_seen, unsigned int replies_seen_count, GSF_PendingRequestReplyHandler rh, void *rh_cls)
Create a new pending request.
static void cadet_reply_proc(void *cls, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration, size_t data_size, const void *data)
Function called with a reply from the cadet.
static void start_local_query(struct GSF_PendingRequest *pr, uint64_t next_uid, bool random)
void GSF_pending_request_cancel_(struct GSF_PendingRequest *pr, int full_cleanup)
Explicitly cancel a pending request.
void GSF_pending_request_update_(struct GSF_PendingRequest *pr, const struct GNUNET_HashCode *replies_seen, unsigned int replies_seen_count)
Update a given pending request with additional replies that have been seen.
API to handle pending requests.
void(* GSF_PendingRequestReplyHandler)(void *cls, enum GNUNET_BLOCK_ReplyEvaluationResult eval, struct GSF_PendingRequest *pr, uint32_t reply_anonymity_level, struct GNUNET_TIME_Absolute expiration, struct GNUNET_TIME_Absolute last_transmission, enum GNUNET_BLOCK_Type type, const void *data, size_t data_len)
Handle a reply to a pending request.
GSF_PendingRequestOptions
Options for pending requests (bits to be ORed).
@ GSF_PRO_LOCAL_ONLY
Request must only be processed locally.
@ GSF_PRO_PRIORITY_UNLIMITED
Request priority is allowed to be exceeded.
@ GSF_PRO_FORWARD_ONLY
Request must only be forwarded (no routing)
@ GSF_PRO_BLOOMFILTER_FULL_REFRESH
Request is allowed to refresh bloomfilter and change mingle value.
@ GSF_PRO_REQUEST_NEVER_EXPIRES
Request persists indefinitely (no expiration).
void(* GSF_LocalLookupContinuation)(void *cls, struct GSF_PendingRequest *pr, enum GNUNET_BLOCK_ReplyEvaluationResult result)
Function to be called after we're done processing replies from the local lookup.
int(* GSF_PendingRequestIterator)(void *cls, const struct GNUNET_HashCode *key, struct GSF_PendingRequest *pr)
Signature of function called on each request.
static char buf[2048]
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
GNUNET_BLOCK_Type
WARNING: This header is generated! In order to add DHT block types, you must register them in GANA,...
@ GNUNET_BLOCK_TYPE_FS_DBLOCK
Data block (leaf) in the CHK tree.
@ GNUNET_BLOCK_TYPE_FS_ONDEMAND
Type of a block representing a block to be encoded on demand from disk.
@ GNUNET_BLOCK_TYPE_FS_IBLOCK
Inner block in the CHK tree.
@ GNUNET_BLOCK_TYPE_ANY
Identifier for any block.
@ GNUNET_BLOCK_TYPE_FS_UBLOCK
Type of a block representing any type of search result (universal).
enum GNUNET_GenericReturnValue GNUNET_BLOCK_group_set_seen(struct GNUNET_BLOCK_Group *bg, const struct GNUNET_HashCode *seen_results, unsigned int seen_results_count)
Update block group to filter out the given results.
Definition: block.c:360
enum GNUNET_BLOCK_ReplyEvaluationResult GNUNET_BLOCK_check_reply(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, struct GNUNET_BLOCK_Group *group, const struct GNUNET_HashCode *query, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size)
Function called to validate if a reply is good for a particular query.
Definition: block.c:334
enum GNUNET_GenericReturnValue GNUNET_BLOCK_check_block(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size)
Function called to validate a block.
Definition: block.c:316
GNUNET_BLOCK_ReplyEvaluationResult
Possible ways for how a block may relate to a query.
void GNUNET_BLOCK_group_destroy(struct GNUNET_BLOCK_Group *bg)
Destroy resources used by a block group.
Definition: block.c:192
struct GNUNET_BLOCK_Group * GNUNET_BLOCK_group_create(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const void *raw_data, size_t raw_data_size,...)
Create a new block group.
Definition: block.c:247
enum GNUNET_GenericReturnValue GNUNET_BLOCK_group_serialize(struct GNUNET_BLOCK_Group *bg, void **raw_data, size_t *raw_data_size)
Serialize state of a block group.
Definition: block.c:175
enum GNUNET_GenericReturnValue GNUNET_BLOCK_get_key(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, struct GNUNET_HashCode *key)
Function called to obtain the key for a block.
Definition: block.c:276
@ GNUNET_BLOCK_REPLY_OK_MORE
Valid result, and there may be more.
@ GNUNET_BLOCK_REPLY_OK_DUPLICATE
Valid result, but suppressed because it is a duplicate.
@ GNUNET_BLOCK_REPLY_OK_LAST
Last possible valid result.
@ GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED
Specified block type not supported by any plugin.
@ GNUNET_BLOCK_REPLY_IRRELEVANT
Block does not match xquery (valid result, not relevant for the request)
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_get_key(struct GNUNET_DATASTORE_Handle *h, uint64_t next_uid, bool random, const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, unsigned int queue_priority, unsigned int max_queue_size, GNUNET_DATASTORE_DatumProcessor proc, void *proc_cls)
Get a result for a particular key from the datastore.
struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_remove(struct GNUNET_DATASTORE_Handle *h, const struct GNUNET_HashCode *key, size_t size, const void *data, unsigned int queue_priority, unsigned int max_queue_size, GNUNET_DATASTORE_ContinuationWithStatus cont, void *cont_cls)
Explicitly remove some content from the database.
void GNUNET_DATASTORE_cancel(struct GNUNET_DATASTORE_QueueEntry *qe)
Cancel a datastore operation.
struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_put(struct GNUNET_DATASTORE_Handle *h, uint32_t rid, const struct GNUNET_HashCode *key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, unsigned int queue_priority, unsigned int max_queue_size, GNUNET_DATASTORE_ContinuationWithStatus cont, void *cont_cls)
Store an item in the datastore.
void GNUNET_DHT_get_stop(struct GNUNET_DHT_GetHandle *get_handle)
Stop async DHT-get.
Definition: dht_api.c:1237
void GNUNET_DHT_get_filter_known_results(struct GNUNET_DHT_GetHandle *get_handle, unsigned int num_results, const struct GNUNET_HashCode *results)
Tell the DHT not to return any of the following known results to this client.
Definition: dht_api.c:1213
struct GNUNET_DHT_GetHandle * GNUNET_DHT_get_start(struct GNUNET_DHT_Handle *handle, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *key, uint32_t desired_replication_level, enum GNUNET_DHT_RouteOption options, const void *xquery, size_t xquery_size, GNUNET_DHT_GetIterator iter, void *iter_cls)
Perform an asynchronous GET operation on the DHT identified.
Definition: dht_api.c:1164
@ GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
Each peer along the way should process the request (otherwise only peers locally closest to the key w...
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
int GNUNET_CONTAINER_multihashmap_get_multiple(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
enum GNUNET_GenericReturnValue(* GNUNET_CONTAINER_MulitHashMapIteratorCallback)(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over hash map entries.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
void * GNUNET_CONTAINER_heap_peek(const struct GNUNET_CONTAINER_Heap *heap)
Get element stored at the root of heap.
unsigned int GNUNET_CONTAINER_heap_get_size(const struct GNUNET_CONTAINER_Heap *heap)
Get the current size of the heap.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.
#define GNUNET_log(kind,...)
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:96
@ GNUNET_OK
Definition: gnunet_common.h:99
@ GNUNET_YES
@ GNUNET_NO
Definition: gnunet_common.h:98
@ GNUNET_SYSERR
Definition: gnunet_common.h:97
double GNUNET_LOAD_get_average(struct GNUNET_LOAD_Value *load)
Get the average value given to update so far.
Definition: load.c:215
struct GNUNET_LOAD_Value * GNUNET_LOAD_value_init(struct GNUNET_TIME_Relative autodecline)
Create a new load value.
Definition: load.c:124
void GNUNET_LOAD_update(struct GNUNET_LOAD_Value *load, uint64_t data)
Update the current load.
Definition: load.c:236
double GNUNET_LOAD_get_load(struct GNUNET_LOAD_Value *load)
Get the current load.
Definition: load.c:200
#define GNUNET_LOAD_value_free(lv)
Free a load value.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_BULK
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
#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:56
unsigned int GNUNET_PEER_Id
A GNUNET_PEER_Id is simply a shorter version of a "struct GNUNET_PeerIdentifier" that can be used ins...
void GNUNET_PEER_change_rc(GNUNET_PEER_Id id, int delta)
Change the reference counter of an interned PID.
Definition: peer.c:197
void GNUNET_PEER_resolve(GNUNET_PEER_Id id, struct GNUNET_PeerIdentity *pid)
Convert an interned PID to a normal peer identity.
Definition: peer.c:225
#define GNUNET_MESSAGE_TYPE_FS_GET
P2P request for content (one FS to another).
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:957
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:1254
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition: time.c:342
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:435
struct GNUNET_TIME_Relative GNUNET_TIME_relative_saturating_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Saturating multiply relative time by a given factor.
Definition: time.c:530
struct GNUNET_TIME_Relative GNUNET_TIME_relative_max(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the maximum of two relative time values.
Definition: time.c:350
#define GNUNET_TIME_UNIT_HOURS
One hour.
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:404
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:110
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:736
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_subtract(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Subtract a given relative duration from the given start time.
Definition: time.c:468
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:315
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:483
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_min(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the minimum of two absolute time values.
Definition: time.c:358
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
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:570
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define GNUNET_TIME_UNIT_YEARS
One year (365 days).
static unsigned int size
Size of the "table".
Definition: peer.c:67
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
static GNUNET_CronTime last_transmission
Block group data.
Handle to a node in a heap.
Internal representation of the hash map.
Entry in our priority queue.
Handle to a GET request.
Definition: dht_api.c:81
A (signed) path tracking a block's flow through the DHT is represented by an array of path elements,...
A 512-bit hashcode.
Values we track for load calculations.
Definition: load.c:36
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
The identity of the host (wraps the signing key of the peer).
Entry in list of pending tasks.
Definition: scheduler.c:135
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Handle for a request that is going out via cadet API.
A connected peer.
Performance data kept for a peer.
uint32_t respect
Respect rating for this peer.
struct GNUNET_TIME_Relative migration_delay
If we get content we already have from this peer, for how long do we block it? Adjusted based on the ...
Public data (in the sense of not encapsulated within 'gnunet-service-fs_pr', not in the sense of netw...
const struct GNUNET_PeerIdentity * target
Identity of a peer hosting the content, otherwise NULl.
struct GNUNET_TIME_Absolute ttl
Current TTL for the request.
uint32_t respect_offered
How much respect did we (in total) offer for this request so far (estimate, because we might have the...
enum GNUNET_BLOCK_Type type
Type of the requested block.
struct GSF_PendingRequestPlanBijection * pr_head
Fields for the plan module to track a DLL with the request.
uint32_t num_transmissions
Counter for how often this request has been transmitted (estimate, because we might have the same req...
enum GSF_PendingRequestOptions options
Options for the request.
unsigned int results_found
Number of results we have found for this request so far.
uint32_t anonymity_level
Desired anonymity level.
struct GNUNET_HashCode query
Primary query hash for this request.
struct GNUNET_TIME_Absolute start_time
When did we start with the request.
uint32_t priority
Priority that this request (still) has for us.
uint32_t original_priority
Priority that this request (originally) had for us.
An active request.
unsigned int replies_seen_size
Length of the 'replies_seen' array.
enum GNUNET_BLOCK_ReplyEvaluationResult local_result
Last result from the local datastore lookup evaluation.
struct GNUNET_BLOCK_Group * bg
Block group for filtering replies we've already seen.
struct GNUNET_DATASTORE_QueueEntry * qe
Datastore queue entry for this request (or NULL for none).
size_t result_count
Result count.
uint64_t first_uid
Unique ID of the first result from the local datastore; used to terminate the loop.
unsigned int replies_seen_count
Number of valid entries in the 'replies_seen' array.
GNUNET_PEER_Id sender_pid
Identity of the peer that we should use for the 'sender' (recipient of the response) when forwarding ...
void * llc_cont_cls
Closure for llc_cont.
unsigned int cadet_retry_count
How often have we retried this request via 'cadet'? (used to bound overall retries).
GSF_PendingRequestReplyHandler rh
Function to call if we encounter a reply.
struct GSF_CadetRequest * cadet_request
Cadet request handle for this request (or NULL for none).
void * rh_cls
Closure for rh.
bool seen_null
Have we seen a NULL result yet?
struct GSF_PendingRequestData public_data
Public data for the request.
GSF_LocalLookupContinuation llc_cont
Function to call upon completion of the local get request, or NULL for none.
struct GNUNET_CONTAINER_HeapNode * hnode
Entry for this pending request in the expiration heap, or NULL.
struct GNUNET_DHT_GetHandle * gh
DHT request handle for this request (or NULL for none).
GNUNET_PEER_Id origin_pid
Identity of the peer that we should never forward this query to since it originated this query (0 for...
struct GNUNET_HashCode * replies_seen
Array of hash codes of replies we've already seen.
bool have_first_uid
Do we have a first UID yet?
struct GNUNET_SCHEDULER_Task * warn_task
Task that warns us if the local datastore lookup takes too long.
struct GNUNET_TIME_Absolute qe_start
Time we started the last datastore lookup.
Message to the datastore service asking about specific content.
Definition: datastore.h:141
uint32_t type
Desired content type.
Definition: datastore.h:150
uint32_t priority
How important is this request (network byte order)
struct GNUNET_HashCode query
Hashcodes of the file(s) we're looking for.
uint32_t reserved
These days not used.
int32_t ttl
Relative time to live in MILLISECONDS (network byte order)
uint32_t hash_bitmap
Which of the optional hash codes are present at the end of the message? See GET_MESSAGE_BIT_xx consta...
Closure for process_reply() function.
size_t size
Size of data.
struct GNUNET_TIME_Absolute expiration
When the reply expires.
enum GNUNET_BLOCK_ReplyEvaluationResult eval
Evaluation result (returned).
uint32_t priority
How much was this reply worth to us?
const void * data
The data for the reply.
struct GSF_ConnectedPeer * sender
Who gave us this reply? NULL for local host (or DHT)
int request_found
Did we find a matching request?
enum GNUNET_BLOCK_Type type
Type of the block.
uint32_t anonymity_level
Anonymity requirements for this reply.
Response from FS service with a result for a previous FS search.
Definition: fs.h:329
struct GNUNET_MessageHeader header
Message type will be GNUNET_MESSAGE_TYPE_FS_PUT.
Definition: fs.h:333
uint32_t type
Type of the block (in big endian).
Definition: fs.h:338
struct GNUNET_TIME_AbsoluteNBO expiration
When does this result expire?
Definition: fs.h:343
Context for put_migration_continuation().
struct GNUNET_PeerIdentity origin
Request origin.
struct GNUNET_TIME_Absolute start
Start time for the operation.
int requested
GNUNET_YES if we had a matching request for this block, GNUNET_NO if not.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.