gnunet-service-xdht_datacache.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file dht/gnunet-service-dht_datacache.c
  19. * @brief GNUnet DHT service's datacache integration
  20. * @author Christian Grothoff
  21. * @author Nathan Evans
  22. */
  23. #include "platform.h"
  24. #include "gnunet_datacache_lib.h"
  25. #include "gnunet-service-xdht_clients.h"
  26. #include "gnunet-service-xdht_datacache.h"
  27. #include "gnunet-service-xdht_routing.h"
  28. #include "gnunet-service-xdht_neighbours.h"
  29. #include "gnunet-service-dht.h"
  30. #define LOG(kind,...) GNUNET_log_from (kind, "dht-dtcache",__VA_ARGS__)
  31. #define DEBUG(...) \
  32. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
  33. /**
  34. * Handle to the datacache service (for inserting/retrieving data)
  35. */
  36. static struct GNUNET_DATACACHE_Handle *datacache;
  37. /**
  38. * Handle a datum we've received from another peer. Cache if
  39. * possible.
  40. *
  41. * @param expiration when will the reply expire
  42. * @param key the query this reply is for
  43. * @param put_path_length number of peers in 'put_path'
  44. * @param put_path path the reply took on put
  45. * @param type type of the reply
  46. * @param data_size number of bytes in 'data'
  47. * @param data application payload data
  48. */
  49. void
  50. GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration,
  51. const struct GNUNET_HashCode * key,
  52. unsigned int put_path_length,
  53. const struct GNUNET_PeerIdentity *put_path,
  54. enum GNUNET_BLOCK_Type type, size_t data_size,
  55. const void *data)
  56. {
  57. int r;
  58. if (NULL == datacache)
  59. {
  60. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  61. _("%s request received, but have no datacache!\n"), "PUT");
  62. return;
  63. }
  64. if (data_size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
  65. {
  66. GNUNET_break (0);
  67. return;
  68. }
  69. /* Put size is actual data size plus struct overhead plus path length (if any) */
  70. GNUNET_STATISTICS_update (GDS_stats,
  71. gettext_noop ("# ITEMS stored in datacache"), 1,
  72. GNUNET_NO);
  73. struct GNUNET_PeerIdentity peer = GDS_NEIGHBOURS_get_my_id();
  74. DEBUG("DATACACHE_PUT KEY = %s, peer = %s\n",GNUNET_h2s(key),GNUNET_i2s(&peer));
  75. r = GNUNET_DATACACHE_put (datacache, key, data_size, data, type, expiration,
  76. put_path_length, put_path);
  77. LOG (GNUNET_ERROR_TYPE_DEBUG,
  78. "DATACACHE PUT for key %s [%u] completed (%d) after %u hops\n",
  79. GNUNET_h2s (key), data_size, r, put_path_length);
  80. }
  81. /**
  82. * List of peers in the get path.
  83. */
  84. struct GetPath
  85. {
  86. /**
  87. * Pointer to next item in the list
  88. */
  89. struct GetPath *next;
  90. /**
  91. * Pointer to previous item in the list
  92. */
  93. struct GetPath *prev;
  94. /**
  95. * An element in the get path.
  96. */
  97. struct GNUNET_PeerIdentity peer;
  98. };
  99. /**
  100. * Context containing information about a GET request.
  101. */
  102. struct GetRequestContext
  103. {
  104. /**
  105. * extended query (see gnunet_block_lib.h).
  106. */
  107. const void *xquery;
  108. /**
  109. * Bloomfilter to filter out duplicate replies (updated)
  110. */
  111. struct GNUNET_CONTAINER_BloomFilter **reply_bf;
  112. /**
  113. * The key this request was about
  114. */
  115. struct GNUNET_HashCode key;
  116. /**
  117. * Number of bytes in xquery.
  118. */
  119. size_t xquery_size;
  120. /**
  121. * Mutator value for the reply_bf, see gnunet_block_lib.h
  122. */
  123. uint32_t reply_bf_mutator;
  124. /**
  125. * Total number of peers in get path.
  126. */
  127. unsigned int get_path_length;
  128. /**
  129. * Return value to give back.
  130. */
  131. enum GNUNET_BLOCK_EvaluationResult eval;
  132. /**
  133. * Peeer which has the data for the key.
  134. */
  135. struct GNUNET_PeerIdentity source_peer;
  136. /**
  137. * Next hop to forward the get result to.
  138. */
  139. struct GNUNET_PeerIdentity next_hop;
  140. /**
  141. * Head of get path.
  142. */
  143. struct GetPath *head;
  144. /**
  145. * Tail of get path.
  146. */
  147. struct GetPath *tail;
  148. /* get_path */
  149. };
  150. /**
  151. * Iterator for local get request results,
  152. *
  153. * @param cls closure for iterator, a DatacacheGetContext
  154. * @param exp when does this value expire?
  155. * @param key the key this data is stored under
  156. * @param size the size of the data identified by key
  157. * @param data the actual data
  158. * @param type the type of the data
  159. * @param put_path_length number of peers in 'put_path'
  160. * @param put_path path the reply took on put
  161. * @return GNUNET_OK to continue iteration, anything else
  162. * to stop iteration.
  163. */
  164. static int
  165. datacache_get_iterator (void *cls,
  166. const struct GNUNET_HashCode * key, size_t size,
  167. const char *data, enum GNUNET_BLOCK_Type type,
  168. struct GNUNET_TIME_Absolute exp,
  169. unsigned int put_path_length,
  170. const struct GNUNET_PeerIdentity *put_path)
  171. {
  172. struct GetRequestContext *ctx = cls;
  173. enum GNUNET_BLOCK_EvaluationResult eval;
  174. eval =
  175. GNUNET_BLOCK_evaluate (GDS_block_context, type, key, ctx->reply_bf,
  176. ctx->reply_bf_mutator, ctx->xquery,
  177. ctx->xquery_size, data, size);
  178. LOG (GNUNET_ERROR_TYPE_DEBUG,
  179. "Found reply for query %s in datacache, evaluation result is %d\n",
  180. GNUNET_h2s (key), (int) eval);
  181. ctx->eval = eval;
  182. switch (eval)
  183. {
  184. case GNUNET_BLOCK_EVALUATION_OK_MORE:
  185. case GNUNET_BLOCK_EVALUATION_OK_LAST:
  186. /* forward to local clients */
  187. GNUNET_STATISTICS_update (GDS_stats,
  188. gettext_noop
  189. ("# Good RESULTS found in datacache"), 1,
  190. GNUNET_NO);
  191. struct GNUNET_PeerIdentity *get_path;
  192. get_path = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) *
  193. ctx->get_path_length);
  194. struct GetPath *iterator;
  195. iterator = ctx->head;
  196. int i = 0;
  197. while (i < ctx->get_path_length)
  198. {
  199. get_path[i] = iterator->peer;
  200. i++;
  201. iterator = iterator->next;
  202. }
  203. GDS_NEIGHBOURS_send_get_result (key,type, &(ctx->next_hop),&(ctx->source_peer),
  204. put_path_length, put_path, ctx->get_path_length,
  205. get_path, exp, data, size );
  206. GNUNET_free_non_null (get_path);
  207. break;
  208. case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
  209. GNUNET_STATISTICS_update (GDS_stats,
  210. gettext_noop
  211. ("# Duplicate RESULTS found in datacache"), 1,
  212. GNUNET_NO);
  213. break;
  214. case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
  215. GNUNET_STATISTICS_update (GDS_stats,
  216. gettext_noop
  217. ("# Invalid RESULTS found in datacache"), 1,
  218. GNUNET_NO);
  219. break;
  220. case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
  221. GNUNET_STATISTICS_update (GDS_stats,
  222. gettext_noop
  223. ("# Irrelevant RESULTS found in datacache"), 1,
  224. GNUNET_NO);
  225. break;
  226. case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
  227. GNUNET_break (0);
  228. break;
  229. case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
  230. GNUNET_break_op (0);
  231. return GNUNET_SYSERR;
  232. case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
  233. GNUNET_STATISTICS_update (GDS_stats,
  234. gettext_noop
  235. ("# Unsupported RESULTS found in datacache"), 1,
  236. GNUNET_NO);
  237. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  238. _("Unsupported block type (%u) in local response!\n"), type);
  239. break;
  240. }
  241. return (eval == GNUNET_BLOCK_EVALUATION_OK_LAST) ? GNUNET_NO : GNUNET_OK;
  242. }
  243. /**
  244. * Handle a GET request we've received from another peer.
  245. *
  246. * @param key the query
  247. * @param type requested data type
  248. * @param xquery extended query
  249. * @param xquery_size number of bytes in xquery
  250. * @param reply_bf where the reply bf is (to be) stored, possibly updated, can be NULL
  251. * @param reply_bf_mutator mutation value for reply_bf
  252. * @return evaluation result for the local replies
  253. * @get_path_length Total number of peers in get path
  254. * @get_path Peers in get path.
  255. */
  256. enum GNUNET_BLOCK_EvaluationResult
  257. GDS_DATACACHE_handle_get (const struct GNUNET_HashCode * key,
  258. enum GNUNET_BLOCK_Type type, const void *xquery,
  259. size_t xquery_size,
  260. struct GNUNET_CONTAINER_BloomFilter **reply_bf,
  261. uint32_t reply_bf_mutator,
  262. uint32_t get_path_length,
  263. struct GNUNET_PeerIdentity *get_path,
  264. struct GNUNET_PeerIdentity *next_hop,
  265. struct GNUNET_PeerIdentity *source_peer)
  266. {
  267. struct GetRequestContext ctx;
  268. unsigned int r;
  269. if (datacache == NULL)
  270. return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
  271. GNUNET_STATISTICS_update (GDS_stats,
  272. gettext_noop ("# GET requests given to datacache"),
  273. 1, GNUNET_NO);
  274. ctx.eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
  275. ctx.key = *key;
  276. ctx.xquery = xquery;
  277. ctx.xquery_size = xquery_size;
  278. ctx.reply_bf = reply_bf;
  279. ctx.reply_bf_mutator = reply_bf_mutator;
  280. ctx.get_path_length = get_path_length;
  281. if (next_hop != NULL)
  282. {
  283. memcpy (&(ctx.next_hop), next_hop, sizeof (struct GNUNET_PeerIdentity));
  284. }
  285. unsigned int i = 0;
  286. ctx.head = NULL;
  287. ctx.tail = NULL;
  288. if (get_path != NULL)
  289. {
  290. while (i < get_path_length)
  291. {
  292. struct GetPath *element;
  293. element = GNUNET_new (struct GetPath);
  294. element->next = NULL;
  295. element->prev = NULL;
  296. element->peer = get_path[i];
  297. GNUNET_CONTAINER_DLL_insert_tail (ctx.head, ctx.tail, element);
  298. i++;
  299. }
  300. }
  301. r = GNUNET_DATACACHE_get (datacache, key, type, &datacache_get_iterator,
  302. &ctx);
  303. DEBUG ("DATACACHE_GET for key %s completed (%d). %u results found.\n",GNUNET_h2s (key), ctx.eval, r);
  304. return ctx.eval;
  305. }
  306. /**
  307. * Initialize datacache subsystem.
  308. */
  309. void
  310. GDS_DATACACHE_init ()
  311. {
  312. datacache = GNUNET_DATACACHE_create (GDS_cfg, "dhtcache");
  313. }
  314. /**
  315. * Shutdown datacache subsystem.
  316. */
  317. void
  318. GDS_DATACACHE_done ()
  319. {
  320. if (datacache != NULL)
  321. {
  322. GNUNET_DATACACHE_destroy (datacache);
  323. datacache = NULL;
  324. }
  325. }
  326. /* end of gnunet-service-dht_datacache.c */