2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011, 2015 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file dht/gnunet-service-wdht_datacache.c
23 * @brief GNUnet DHT service's datacache integration
24 * @author Christian Grothoff
25 * @author Nathan Evans
28 #include "gnunet_datacache_lib.h"
29 #include "gnunet-service-wdht_clients.h"
30 #include "gnunet-service-wdht_datacache.h"
31 #include "gnunet-service-wdht_neighbours.h"
32 #include "gnunet-service-dht.h"
34 #define LOG(kind,...) GNUNET_log_from (kind, "dht-dtcache",__VA_ARGS__)
37 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
40 * How many "closest" results to we return for migration when
43 #define NUM_CLOSEST 42
46 * Handle to the datacache service (for inserting/retrieving data)
48 static struct GNUNET_DATACACHE_Handle *datacache;
52 * Handle a datum we've received from another peer. Cache if
55 * @param expiration when will the reply expire
56 * @param key the query this reply is for
57 * @param put_path_length number of peers in @a put_path
58 * @param put_path path the reply took on put
59 * @param get_path_length number of peers in @a get_path
60 * @param get_path path the reply took on get
61 * @param type type of the reply
62 * @param data_size number of bytes in @a data
63 * @param data application payload data
66 GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration,
67 const struct GNUNET_HashCode *key,
68 unsigned int put_path_length,
69 const struct GNUNET_PeerIdentity *put_path,
70 unsigned int get_path_length,
71 const struct GNUNET_PeerIdentity *get_path,
72 enum GNUNET_BLOCK_Type type,
77 struct GNUNET_PeerIdentity path[get_path_length + put_path_length];
79 if (NULL == datacache)
81 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
82 _("PUT request received, but have no datacache!\n"));
85 if (data_size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
92 put_path_length * sizeof (struct GNUNET_PeerIdentity));
93 memcpy (&path[put_path_length],
95 get_path_length * sizeof (struct GNUNET_PeerIdentity));
96 /* Put size is actual data size plus struct overhead plus path length (if any) */
97 r = GNUNET_DATACACHE_put (datacache,
103 get_path_length + put_path_length,
106 GNUNET_STATISTICS_update (GDS_stats,
107 gettext_noop ("# ITEMS stored in datacache"), 1,
109 LOG (GNUNET_ERROR_TYPE_DEBUG,
110 "DATACACHE PUT for key %s [%u] completed (%d) after %u hops\n",
114 put_path_length + get_path_length);
119 * Context containing information about a GET request.
121 struct GetRequestContext
124 * extended query (see gnunet_block_lib.h).
129 * Bloomfilter to filter out duplicate replies (updated)
131 struct GNUNET_CONTAINER_BloomFilter **reply_bf;
134 * The key this request was about
136 struct GNUNET_HashCode key;
139 * The trail this request was for
141 const struct GNUNET_HashCode *trail_id;
144 * Number of bytes in @e xquery.
149 * Mutator value for the @e reply_bf, see gnunet_block_lib.h
151 uint32_t reply_bf_mutator;
154 * Return value to give back.
156 enum GNUNET_BLOCK_EvaluationResult eval;
162 * Iterator for local get request results,
164 * @param cls closure for iterator, a `struct GetRequestContext`
165 * @param key the key this data is stored under
166 * @param size the size of the data identified by key
167 * @param data the actual data
168 * @param type the type of the data
169 * @param exp when does this value expire?
170 * @param put_path_length number of peers in @a put_path
171 * @param put_path path the reply took on put
172 * @return #GNUNET_OK to continue iteration, anything else
176 datacache_get_iterator (void *cls,
177 const struct GNUNET_HashCode *key,
180 enum GNUNET_BLOCK_Type type,
181 struct GNUNET_TIME_Absolute exp,
182 unsigned int put_path_length,
183 const struct GNUNET_PeerIdentity *put_path)
185 struct GetRequestContext *ctx = cls;
186 enum GNUNET_BLOCK_EvaluationResult eval;
189 GNUNET_BLOCK_evaluate (GDS_block_context,
191 GNUNET_BLOCK_EO_NONE,
194 ctx->reply_bf_mutator,
199 LOG (GNUNET_ERROR_TYPE_DEBUG,
200 "Found reply for query %s in datacache, evaluation result is %d\n",
201 GNUNET_h2s (key), (int) eval);
206 case GNUNET_BLOCK_EVALUATION_OK_MORE:
207 case GNUNET_BLOCK_EVALUATION_OK_LAST:
208 /* forward to local clients */
209 GNUNET_STATISTICS_update (GDS_stats,
211 ("# Good RESULTS found in datacache"), 1,
213 GDS_NEIGHBOURS_send_get_result (ctx->trail_id,
222 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
223 GNUNET_STATISTICS_update (GDS_stats,
225 ("# Duplicate RESULTS found in datacache"), 1,
228 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
229 GNUNET_STATISTICS_update (GDS_stats,
231 ("# Invalid RESULTS found in datacache"), 1,
234 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
235 GNUNET_STATISTICS_update (GDS_stats,
237 ("# Irrelevant RESULTS found in datacache"), 1,
240 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
243 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
245 return GNUNET_SYSERR;
246 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
247 GNUNET_STATISTICS_update (GDS_stats,
249 ("# Unsupported RESULTS found in datacache"), 1,
251 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
252 _("Unsupported block type (%u) in local response!\n"), type);
256 return (eval == GNUNET_BLOCK_EVALUATION_OK_LAST) ? GNUNET_NO : GNUNET_OK;
261 * Handle a GET request we've received from another peer.
263 * @param trail_id trail identifying where to send the result to, NULL for us
264 * @param key the query
265 * @param type requested data type
266 * @param xquery extended query
267 * @param xquery_size number of bytes in @a xquery
268 * @param reply_bf where the reply bf is (to be) stored, possibly updated, can be NULL
269 * @param reply_bf_mutator mutation value for @a reply_bf
270 * @return evaluation result for the local replies
272 enum GNUNET_BLOCK_EvaluationResult
273 GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *trail_id,
274 const struct GNUNET_HashCode *key,
275 enum GNUNET_BLOCK_Type type,
278 struct GNUNET_CONTAINER_BloomFilter **reply_bf,
279 uint32_t reply_bf_mutator)
281 struct GetRequestContext ctx;
284 if (NULL == datacache)
285 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
286 GNUNET_STATISTICS_update (GDS_stats,
287 gettext_noop ("# GET requests given to datacache"),
289 ctx.eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
290 ctx.trail_id = trail_id;
293 ctx.xquery_size = xquery_size;
294 ctx.reply_bf = reply_bf;
295 ctx.reply_bf_mutator = reply_bf_mutator;
296 r = GNUNET_DATACACHE_get (datacache,
299 &datacache_get_iterator,
301 DEBUG ("DATACACHE_GET for key %s completed (%d). %u results found.\n",
310 * Function called with a random element from the datacache.
311 * Stores the key in the closure.
313 * @param cls a `struct GNUNET_HashCode *`, where to store the @a key
314 * @param key key for the content
315 * @param data_size number of bytes in @a data
316 * @param data content stored
317 * @param type type of the content
318 * @param exp when will the content expire?
319 * @param path_info_len number of entries in @a path_info
320 * @param path_info a path through the network
321 * @return #GNUNET_OK to continue iterating, #GNUNET_SYSERR to abort
324 datacache_random_iterator (void *cls,
325 const struct GNUNET_HashCode *key,
328 enum GNUNET_BLOCK_Type type,
329 struct GNUNET_TIME_Absolute exp,
330 unsigned int path_info_len,
331 const struct GNUNET_PeerIdentity *path_info)
333 struct GNUNET_HashCode *dest = cls;
336 return GNUNET_OK; /* should actually not matter which we return */
341 * Obtain a random key from the datacache.
342 * Used by Whanau for load-balancing.
344 * @param[out] key where to store the key of a random element,
345 * randomized by PRNG if datacache is empty
346 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the datacache is empty
349 GDS_DATACACHE_get_random_key (struct GNUNET_HashCode *key)
352 GNUNET_DATACACHE_get_random (datacache,
353 &datacache_random_iterator,
356 /* randomize key in this case */
357 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
359 return GNUNET_SYSERR;
365 * Iterator for local get request results,
367 * @param cls closure with the `struct GNUNET_HashCode *` with the trail ID
368 * @param key the key this data is stored under
369 * @param size the size of the data identified by key
370 * @param data the actual data
371 * @param type the type of the data
372 * @param exp when does this value expire?
373 * @param put_path_length number of peers in @a put_path
374 * @param put_path path the reply took on put
375 * @return #GNUNET_OK to continue iteration, anything else
379 datacache_get_successors_iterator (void *cls,
380 const struct GNUNET_HashCode *key,
383 enum GNUNET_BLOCK_Type type,
384 struct GNUNET_TIME_Absolute exp,
385 unsigned int put_path_length,
386 const struct GNUNET_PeerIdentity *put_path)
388 const struct GNUNET_HashCode *trail_id = cls;
390 GDS_NEIGHBOURS_send_get_result (trail_id,
393 put_path_length, put_path,
402 * Handle a request for data close to a key that we have received from
405 * @param trail_id trail where the reply needs to be send to
406 * @param key the location at which the peer is looking for data that is close
409 GDS_DATACACHE_get_successors (const struct GNUNET_HashCode *trail_id,
410 const struct GNUNET_HashCode *key)
412 (void) GNUNET_DATACACHE_get_closest (datacache,
415 &datacache_get_successors_iterator,
421 * Initialize datacache subsystem.
424 GDS_DATACACHE_init ()
426 datacache = GNUNET_DATACACHE_create (GDS_cfg, "dhtcache");
431 * Shutdown datacache subsystem.
434 GDS_DATACACHE_done ()
436 if (NULL != datacache)
438 GNUNET_DATACACHE_destroy (datacache);
444 /* end of gnunet-service-wdht_datacache.c */