2 This file is part of GNUnet.
3 (C) 2011 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 fs/gnunet-service-fs_put.c
23 * @brief API to PUT zero-anonymity index data from our datastore into the DHT
24 * @author Christian Grothoff
27 #include "gnunet-service-fs.h"
28 #include "gnunet-service-fs_put.h"
32 * How often do we at most PUT content into the DHT?
34 #define MAX_DHT_PUT_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
37 * How many replicas do we try to create per PUT?
39 #define DEFAULT_PUT_REPLICATION 5
43 * Context for each zero-anonymity iterator.
49 * Request to datastore for DHT PUTs (or NULL).
51 struct GNUNET_DATASTORE_QueueEntry *dht_qe;
54 * Type we request from the datastore.
56 enum GNUNET_BLOCK_Type dht_put_type;
59 * Handle to PUT operation.
61 struct GNUNET_DHT_PutHandle *dht_put;
64 * ID of task that collects blocks for DHT PUTs.
66 GNUNET_SCHEDULER_TaskIdentifier dht_task;
69 * How many entires with zero anonymity of our type do we currently
70 * estimate to have in the database?
72 uint64_t zero_anonymity_count_estimate;
75 * Current offset when iterating the database.
77 uint64_t current_offset;
82 * ANY-terminated list of our operators (one per type
83 * of block that we're putting into the DHT).
85 static struct PutOperator operators[] = {
86 {NULL, GNUNET_BLOCK_TYPE_FS_KBLOCK, 0, 0, 0},
87 {NULL, GNUNET_BLOCK_TYPE_FS_SBLOCK, 0, 0, 0},
88 {NULL, GNUNET_BLOCK_TYPE_FS_NBLOCK, 0, 0, 0},
89 {NULL, GNUNET_BLOCK_TYPE_ANY, 0, 0, 0}
94 * Task that is run periodically to obtain blocks for DHT PUTs.
96 * @param cls type of blocks to gather
97 * @param tc scheduler context (unused)
100 gather_dht_put_blocks (void *cls,
101 const struct GNUNET_SCHEDULER_TaskContext *tc);
105 * Calculate when to run the next PUT operation and schedule it.
107 * @param po put operator to schedule
110 schedule_next_put (struct PutOperator *po)
112 struct GNUNET_TIME_Relative delay;
114 if (po->zero_anonymity_count_estimate > 0)
117 GNUNET_TIME_relative_divide (GNUNET_DHT_DEFAULT_REPUBLISH_FREQUENCY,
118 po->zero_anonymity_count_estimate);
119 delay = GNUNET_TIME_relative_min (delay, MAX_DHT_PUT_FREQ);
123 /* if we have NO zero-anonymity content yet, wait 5 minutes for some to
124 * (hopefully) appear */
125 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5);
128 GNUNET_SCHEDULER_add_delayed (delay, &gather_dht_put_blocks, po);
133 * Continuation called after DHT PUT operation has finished.
135 * @param cls type of blocks to gather
136 * @param success GNUNET_OK if the PUT was transmitted,
137 * GNUNET_NO on timeout,
138 * GNUNET_SYSERR on disconnect from service
139 * after the PUT message was transmitted
140 * (so we don't know if it was received or not)
143 delay_dht_put_blocks (void *cls, int success)
145 struct PutOperator *po = cls;
148 schedule_next_put (po);
153 * Task that is run periodically to obtain blocks for DHT PUTs.
155 * @param cls type of blocks to gather
156 * @param tc scheduler context
159 delay_dht_put_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
161 struct PutOperator *po = cls;
163 po->dht_task = GNUNET_SCHEDULER_NO_TASK;
164 schedule_next_put (po);
169 * Store content in DHT.
172 * @param key key for the content
173 * @param size number of bytes in data
174 * @param data content stored
175 * @param type type of the content
176 * @param priority priority of the content
177 * @param anonymity anonymity-level for the content
178 * @param expiration expiration time for the content
179 * @param uid unique identifier for the datum;
180 * maybe 0 if no unique identifier is available
183 process_dht_put_content (void *cls, const struct GNUNET_HashCode * key, size_t size,
184 const void *data, enum GNUNET_BLOCK_Type type,
185 uint32_t priority, uint32_t anonymity,
186 struct GNUNET_TIME_Absolute expiration, uint64_t uid)
188 struct PutOperator *po = cls;
193 po->zero_anonymity_count_estimate = po->current_offset - 1;
194 po->current_offset = 0;
195 po->dht_task = GNUNET_SCHEDULER_add_now (&delay_dht_put_task, po);
198 po->zero_anonymity_count_estimate =
199 GNUNET_MAX (po->current_offset, po->zero_anonymity_count_estimate);
200 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
201 "Retrieved block `%s' of type %u for DHT PUT\n", GNUNET_h2s (key),
203 po->dht_put = GNUNET_DHT_put (GSF_dht, key, DEFAULT_PUT_REPLICATION,
204 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, type, size, data,
205 expiration, GNUNET_TIME_UNIT_FOREVER_REL,
206 &delay_dht_put_blocks, po);
211 * Task that is run periodically to obtain blocks for DHT PUTs.
213 * @param cls type of blocks to gather
214 * @param tc scheduler context (unused)
217 gather_dht_put_blocks (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
219 struct PutOperator *po = cls;
221 po->dht_task = GNUNET_SCHEDULER_NO_TASK;
222 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
225 GNUNET_DATASTORE_get_zero_anonymity (GSF_dsh, po->current_offset++, 0,
227 GNUNET_TIME_UNIT_FOREVER_REL,
229 &process_dht_put_content, po);
230 if (NULL == po->dht_qe)
231 po->dht_task = GNUNET_SCHEDULER_add_now (&delay_dht_put_task, po);
244 while (operators[i].dht_put_type != GNUNET_BLOCK_TYPE_ANY)
246 operators[i].dht_task =
247 GNUNET_SCHEDULER_add_now (&gather_dht_put_blocks, &operators[i]);
254 * Shutdown the module.
259 struct PutOperator *po;
263 while ((po = &operators[i])->dht_put_type != GNUNET_BLOCK_TYPE_ANY)
265 if (GNUNET_SCHEDULER_NO_TASK != po->dht_task)
267 GNUNET_SCHEDULER_cancel (po->dht_task);
268 po->dht_task = GNUNET_SCHEDULER_NO_TASK;
270 if (NULL != po->dht_put)
272 GNUNET_DHT_put_cancel (po->dht_put);
275 if (NULL != po->dht_qe)
277 GNUNET_DATASTORE_cancel (po->dht_qe);
284 /* end of gnunet-service-fs_put.c */