fixing mess with search update serialization and parenting
[oweals/gnunet.git] / src / migration / gnunet-daemon-migration.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010 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 2, 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 migration/gnunet-daemon-migration.c
23  * @brief migrating (file-sharing) content through the network; this 
24  *        daemon is only responsible for pushing content out (not for
25  *        processing inbound messages)
26  * @author Christian Grothoff
27  */
28 #include <stdlib.h>
29 #include "platform.h"
30 #include "../fs/fs.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_core_service.h"
33 #include "gnunet_datastore_service.h"
34 #include "gnunet_protocols.h"
35 #include "gnunet_statistics_service.h"
36 #include "gnunet_util_lib.h"
37
38
39 #define DEBUG_MIGRATION GNUNET_YES
40
41 /**
42  * Information we keep per peer.
43  */
44 struct Peer
45 {
46   /**
47    * Last time we migrated data to this peer.
48    */
49   struct GNUNET_TIME_Absolute last_migration;
50
51 };
52
53
54 /**
55  * Our scheduler.
56  */
57 static struct GNUNET_SCHEDULER_Handle *sched;
58
59 /**
60  * Our configuration.
61  */
62 static const struct GNUNET_CONFIGURATION_Handle *cfg;
63
64 /**
65  * Handle to the core API.
66  */
67 static struct GNUNET_CORE_Handle *handle;
68
69 /**
70  * Handle for reporting statistics.
71  */
72 static struct GNUNET_STATISTICS_Handle *stats;
73
74 /**
75  * Handle for the core service.
76 */
77 static struct GNUNET_CORE_Handle *handle;
78
79 /**
80  * Handle to the datastore.
81  */
82 static struct GNUNET_DATASTORE_Handle *datastore;
83
84 /**
85  * Anonymity level for the current block.
86  */
87 static unsigned int current_anonymity;
88
89 /**
90  * Type of the current block.
91  */
92 static enum GNUNET_BLOCK_Type current_type;
93
94 /**
95  * Data of the current block (already encrypted).
96  */
97 static char current_block[GNUNET_SERVER_MAX_MESSAGE_SIZE];
98
99 /**
100  * Size of the current block.
101  */
102 static size_t current_block_size;
103
104 /**
105  * Key of the current block.
106  */
107 static GNUNET_HashCode current_key;
108
109 /**
110  * Task scheduled to receive content from the datastore (with some delay).
111  */
112 static GNUNET_SCHEDULER_TaskIdentifier get_task;
113
114
115 /**
116  * Select a peer for transmitting the current block to.
117  */
118 static void
119 select_peer ()
120 {
121   /* FIXME: select a peer for transmission... */
122 }
123
124
125 /**
126  * Method called whenever a peer connects.
127  *
128  * @param cls closure
129  * @param peer peer identity this notification is about
130  * @param latency reported latency of the connection with 'other'
131  * @param distance reported distance (DV) to 'other' 
132  */
133 static void 
134 connect_notify (void *cls,
135                 const struct
136                 GNUNET_PeerIdentity * peer,
137                 struct GNUNET_TIME_Relative latency,
138                 uint32_t distance)
139 {
140   /* FIXME: track peer */
141 }
142
143
144 /**
145  * Method called whenever a peer disconnects.
146  *
147  * @param cls closure
148  * @param peer peer identity this notification is about
149  */
150 static void 
151 disconnect_notify (void *cls,
152                    const struct
153                    GNUNET_PeerIdentity * peer)
154 {
155   /* FIXME: untrack peer */
156 }
157
158
159 /**
160  * Ask datastore for more content.
161  * @param cls closure
162  * @param tc scheduler context 
163  */
164 static void
165 get_content (void *cls,
166              const struct GNUNET_SCHEDULER_TaskContext *tc);
167
168
169 /**
170  * An iterator over a set of items stored in the datastore.
171  *
172  * @param cls closure
173  * @param key key for the content
174  * @param size number of bytes in data
175  * @param data content stored
176  * @param type type of the content
177  * @param priority priority of the content
178  * @param anonymity anonymity-level for the content
179  * @param expiration expiration time for the content
180  * @param uid unique identifier for the datum;
181  *        maybe 0 if no unique identifier is available
182  */
183 static void 
184 content_processor (void *cls,
185                    const GNUNET_HashCode * key,
186                    uint32_t size,
187                    const void *data,
188                    enum GNUNET_BLOCK_Type type,
189                    uint32_t priority,
190                    uint32_t anonymity,
191                    struct GNUNET_TIME_Absolute
192                    expiration, uint64_t uid)
193 {
194   if (key != NULL)
195     {
196       memcpy (current_block, data, size);
197       current_block_size = size;
198       current_type = type;
199       current_anonymity = anonymity;
200       current_key = *key;
201       return;
202     }
203   if (current_block_size == 0)
204     {
205       get_task = GNUNET_SCHEDULER_add_delayed (sched,
206                                                GNUNET_TIME_UNIT_MINUTES,
207                                                &get_content,
208                                                NULL);
209       return;
210     }
211   if (current_type == GNUNET_BLOCK_TYPE_ONDEMAND)
212     {     
213       /* FIXME: do on-demand encoding... */
214       return;
215     }
216   select_peer ();
217 }
218
219
220 /**
221  * Ask datastore for more content.
222  * @param cls closure
223  * @param tc scheduler context 
224  */
225 static void
226 get_content (void *cls,
227              const struct GNUNET_SCHEDULER_TaskContext *tc)
228 {
229   get_task = GNUNET_SCHEDULER_NO_TASK;
230   GNUNET_DATASTORE_get_random (datastore,
231                                &content_processor,
232                                NULL,
233                                GNUNET_CONSTANTS_SERVICE_TIMEOUT);
234 }
235
236
237 /**
238  * Function called after GNUNET_CORE_connect has succeeded
239  * (or failed for good).
240  *
241  * @param cls closure
242  * @param server handle to the server, NULL if we failed
243  * @param my_id ID of this peer, NULL if we failed
244  * @param publicKey public key of this peer, NULL if we failed
245  */
246 static void
247 core_init (void *cls,
248            struct GNUNET_CORE_Handle * server,
249            const struct GNUNET_PeerIdentity *
250            my_id,
251            const struct
252            GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *
253            publicKey)
254 {
255   handle = server;
256   if (datastore != NULL)
257     get_task = GNUNET_SCHEDULER_add_now (sched,
258                                          &get_content,
259                                          NULL);
260 }
261
262
263 /**
264  * Last task run during shutdown.  Disconnects us from
265  * the core.
266  *
267  * @param cls unused, NULL
268  * @param tc scheduler context
269  */
270 static void
271 cleaning_task (void *cls, 
272                const struct GNUNET_SCHEDULER_TaskContext *tc)
273 {
274   if (get_task != GNUNET_SCHEDULER_NO_TASK)
275     {
276       GNUNET_SCHEDULER_cancel (sched,
277                                get_task);
278       get_task = GNUNET_SCHEDULER_NO_TASK;
279     }
280   if (handle != NULL)
281     {
282       GNUNET_CORE_disconnect (handle);
283       handle = NULL;
284     }
285   if (datastore != NULL)
286     {
287       GNUNET_DATASTORE_disconnect (datastore, GNUNET_NO);
288       datastore = NULL;
289     }
290   if (stats != NULL)
291     {
292       GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
293       stats = NULL;
294     }
295 }
296
297
298 /**
299  * Main function that will be run.
300  *
301  * @param cls closure
302  * @param s the scheduler to use
303  * @param args remaining command-line arguments
304  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
305  * @param c configuration
306  */
307 static void
308 run (void *cls,
309      struct GNUNET_SCHEDULER_Handle * s,
310      char *const *args,
311      const char *cfgfile,
312      const struct GNUNET_CONFIGURATION_Handle * c)
313 {
314   struct GNUNET_CORE_MessageHandler handlers[] =
315     {
316       { NULL, 0, 0 }
317     };
318   sched = s;
319   cfg = c;
320   stats = GNUNET_STATISTICS_create (sched, "topology", cfg);
321   handle = GNUNET_CORE_connect (sched,
322                                 cfg,
323                                 GNUNET_TIME_UNIT_FOREVER_REL,
324                                 NULL,
325                                 &core_init,
326                                 &connect_notify,
327                                 &disconnect_notify,
328                                 NULL, GNUNET_NO,
329                                 NULL, GNUNET_NO,
330                                 handlers);
331   datastore = GNUNET_DATASTORE_connect (cfg, sched);
332   GNUNET_SCHEDULER_add_delayed (sched,
333                                 GNUNET_TIME_UNIT_FOREVER_REL,
334                                 &cleaning_task, NULL);
335   if ( (NULL == handle) ||
336        (NULL == datastore) )
337     {
338       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
339                   _("Failed to connect to `%s' service.\n"),
340                   (NULL == handle) ? "core" : "datastore");
341       GNUNET_SCHEDULER_shutdown (sched);
342       return;
343     }
344 }
345
346
347 /**
348  * gnunet-daemon-topology command line options.
349  */
350 static struct GNUNET_GETOPT_CommandLineOption options[] = {
351   GNUNET_GETOPT_OPTION_END
352 };
353
354
355 /**
356  * The main function for the topology daemon.
357  *
358  * @param argc number of arguments from the command line
359  * @param argv command line arguments
360  * @return 0 ok, 1 on error
361  */
362 int
363 main (int argc, char *const *argv)
364 {
365   int ret;
366
367   ret = (GNUNET_OK ==
368          GNUNET_PROGRAM_run (argc,
369                              argv,
370                              "migration",
371                              _("Content migration for anonymous file-sharing"),
372                              options,
373                              &run, NULL)) ? 0 : 1;
374   return ret;
375 }
376
377 /* end of gnunet-daemon-migration.c */