eb7289f1e2ad5c27acb5c0ace0791bf7a1214598
[oweals/gnunet.git] / src / fs / gnunet-service-fs_put.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011 Christian Grothoff (and other contributing authors)
4
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.
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      General Public License for more details.
14
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.
19 */
20
21 /**
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
25  */
26 #include "platform.h"
27 #include "gnunet-service-fs_put.h"
28
29 /* FIXME: below are only old code fragments to use... */
30
31
32 /**
33  * Request to datastore for DHT PUTs (or NULL).
34  */
35 static struct GNUNET_DATASTORE_QueueEntry *dht_qe;
36
37
38 /**
39  * Type we will request for the next DHT PUT round from the datastore.
40  */
41 static enum GNUNET_BLOCK_Type dht_put_type = GNUNET_BLOCK_TYPE_FS_KBLOCK;
42
43 /**
44  * ID of task that collects blocks for DHT PUTs.
45  */
46 static GNUNET_SCHEDULER_TaskIdentifier dht_task;
47
48 /**
49  * How many entires with zero anonymity do we currently estimate
50  * to have in the database?
51  */
52 static unsigned int zero_anonymity_count_estimate;
53
54
55
56
57
58 /**
59  * Task that is run periodically to obtain blocks for DHT PUTs.
60  * 
61  * @param cls type of blocks to gather
62  * @param tc scheduler context (unused)
63  */
64 static void
65 gather_dht_put_blocks (void *cls,
66                        const struct GNUNET_SCHEDULER_TaskContext *tc);
67
68
69
70 /**
71  * If the DHT PUT gathering task is not currently running, consider
72  * (re)scheduling it with the appropriate delay.
73  */
74 static void
75 consider_dht_put_gathering (void *cls)
76 {
77   struct GNUNET_TIME_Relative delay;
78
79   if (dsh == NULL)
80     return;
81   if (dht_qe != NULL)
82     return;
83   if (dht_task != GNUNET_SCHEDULER_NO_TASK)
84     return;
85   if (zero_anonymity_count_estimate > 0)
86     {
87       delay = GNUNET_TIME_relative_divide (GNUNET_DHT_DEFAULT_REPUBLISH_FREQUENCY,
88                                            zero_anonymity_count_estimate);
89       delay = GNUNET_TIME_relative_min (delay,
90                                         MAX_DHT_PUT_FREQ);
91     }
92   else
93     {
94       /* if we have NO zero-anonymity content yet, wait 5 minutes for some to
95          (hopefully) appear */
96       delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5);
97     }
98   dht_task = GNUNET_SCHEDULER_add_delayed (delay,
99                                            &gather_dht_put_blocks,
100                                            cls);
101 }
102
103
104
105 /**
106  * Store content in DHT.
107  *
108  * @param cls closure
109  * @param key key for the content
110  * @param size number of bytes in data
111  * @param data content stored
112  * @param type type of the content
113  * @param priority priority of the content
114  * @param anonymity anonymity-level for the content
115  * @param expiration expiration time for the content
116  * @param uid unique identifier for the datum;
117  *        maybe 0 if no unique identifier is available
118  */
119 static void
120 process_dht_put_content (void *cls,
121                          const GNUNET_HashCode * key,
122                          size_t size,
123                          const void *data,
124                          enum GNUNET_BLOCK_Type type,
125                          uint32_t priority,
126                          uint32_t anonymity,
127                          struct GNUNET_TIME_Absolute
128                          expiration, uint64_t uid)
129
130   static unsigned int counter;
131   static GNUNET_HashCode last_vhash;
132   static GNUNET_HashCode vhash;
133
134   if (key == NULL)
135     {
136       dht_qe = NULL;
137       consider_dht_put_gathering (cls);
138       return;
139     }
140   /* slightly funky code to estimate the total number of values with zero
141      anonymity from the maximum observed length of a monotonically increasing 
142      sequence of hashes over the contents */
143   GNUNET_CRYPTO_hash (data, size, &vhash);
144   if (GNUNET_CRYPTO_hash_cmp (&vhash, &last_vhash) <= 0)
145     {
146       if (zero_anonymity_count_estimate > 0)
147         zero_anonymity_count_estimate /= 2;
148       counter = 0;
149     }
150   last_vhash = vhash;
151   if (counter < 31)
152     counter++;
153   if (zero_anonymity_count_estimate < (1 << counter))
154     zero_anonymity_count_estimate = (1 << counter);
155 #if DEBUG_FS
156   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
157               "Retrieved block `%s' of type %u for DHT PUT\n",
158               GNUNET_h2s (key),
159               type);
160 #endif
161   GNUNET_DHT_put (dht_handle,
162                   key,
163                   DEFAULT_PUT_REPLICATION,
164                   GNUNET_DHT_RO_NONE,
165                   type,
166                   size,
167                   data,
168                   expiration,
169                   GNUNET_TIME_UNIT_FOREVER_REL,
170                   &dht_put_continuation,
171                   cls);
172 }
173
174
175
176 /**
177  * Task that is run periodically to obtain blocks for DHT PUTs.
178  * 
179  * @param cls type of blocks to gather
180  * @param tc scheduler context (unused)
181  */
182 static void
183 gather_dht_put_blocks (void *cls,
184                        const struct GNUNET_SCHEDULER_TaskContext *tc)
185 {
186   dht_task = GNUNET_SCHEDULER_NO_TASK;
187   if (dsh != NULL)
188     {
189       if (dht_put_type == GNUNET_BLOCK_TYPE_FS_ONDEMAND)
190         dht_put_type = GNUNET_BLOCK_TYPE_FS_KBLOCK;
191       dht_qe = GNUNET_DATASTORE_get_zero_anonymity (dsh, 0, UINT_MAX,
192                                                     GNUNET_TIME_UNIT_FOREVER_REL,
193                                                     dht_put_type++,
194                                                     &process_dht_put_content, NULL);
195       GNUNET_assert (dht_qe != NULL);
196     }
197 }