aboutsummaryrefslogtreecommitdiff
path: root/src/fs/gnunet-auto-share.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/gnunet-auto-share.c')
-rw-r--r--src/fs/gnunet-auto-share.c306
1 files changed, 298 insertions, 8 deletions
diff --git a/src/fs/gnunet-auto-share.c b/src/fs/gnunet-auto-share.c
index e076d8b31..01c48aab0 100644
--- a/src/fs/gnunet-auto-share.c
+++ b/src/fs/gnunet-auto-share.c
@@ -26,35 +26,316 @@
26#include "gnunet_util_lib.h" 26#include "gnunet_util_lib.h"
27 27
28 28
29/**
30 * Item in our work queue (or in the set of files/directories
31 * we have successfully published).
32 */
33struct WorkItem
34{
35
36 /**
37 * PENDING Work is kept in a linked list.
38 */
39 struct WorkItem *prev;
40
41 /**
42 * PENDING Work is kept in a linked list.
43 */
44 struct WorkItem *next;
45
46 /**
47 * Filename of the work item.
48 */
49 const char *filename;
50
51 /**
52 * Unique identity for this work item (used to detect
53 * if we need to do the work again).
54 */
55 struct GNUNET_HashCode id;
56};
57
58
59/**
60 * Global return value from 'main'.
61 */
29static int ret; 62static int ret;
30 63
64/**
65 * Are we running 'verbosely'?
66 */
31static int verbose; 67static int verbose;
32 68
69/**
70 * Configuration to use.
71 */
33static const struct GNUNET_CONFIGURATION_Handle *cfg; 72static const struct GNUNET_CONFIGURATION_Handle *cfg;
34 73
74/**
75 * Disable extractor option to use for publishing.
76 */
35static int disable_extractor; 77static int disable_extractor;
36 78
79/**
80 * Disable creation time option to use for publishing.
81 */
37static int do_disable_creation_time; 82static int do_disable_creation_time;
38 83
84/**
85 * Handle for the 'shutdown' task.
86 */
39static GNUNET_SCHEDULER_TaskIdentifier kill_task; 87static GNUNET_SCHEDULER_TaskIdentifier kill_task;
40 88
89/**
90 * Handle for the main task that does scanning and working.
91 */
92static GNUNET_SCHEDULER_TaskIdentifier run_task;
93
94/**
95 * Anonymity level option to use for publishing.
96 */
41static unsigned int anonymity_level = 1; 97static unsigned int anonymity_level = 1;
42 98
99/**
100 * Content priority option to use for publishing.
101 */
43static unsigned int content_priority = 365; 102static unsigned int content_priority = 365;
44 103
104/**
105 * Replication level option to use for publishing.
106 */
45static unsigned int replication_level = 1; 107static unsigned int replication_level = 1;
46 108
109/**
110 * Top-level directory we monitor to auto-publish.
111 */
112static const char *dir_name;
113
114/**
115 * Head of linked list of files still to publish.
116 */
117static struct WorkItem *work_head;
118
119/**
120 * Tail of linked list of files still to publish.
121 */
122static struct WorkItem *work_tail;
123
124/**
125 * Map from the hash of the filename (!) to a 'struct WorkItem'
126 * that was finished.
127 */
128static struct GNUNET_CONTAINER_MultiHashMap *work_finished;
129
130/**
131 * Set to GNUNET_YES if we are shutting down.
132 */
133static int do_shutdown;
134
135/**
136 * Start time of the current round; used to determine how long
137 * one iteration takes (which influences how fast we schedule
138 * the next one).
139 */
140static struct GNUNET_TIME_Absolute start_time;
141
142
143/**
144 * Load the set of 'work_finished' items from disk.
145 */
146static void
147load_state ()
148{
149 GNUNET_break (0);
150 // FIXME: implement!
151}
152
153
154/**
155 * Save the set of 'work_finished' items on disk.
156 */
157static void
158save_state ()
159{
160 GNUNET_break (0);
161 // FIXME: implement!
162}
163
47 164
48/** 165/**
49 * FIXME: docu 166 * Task run on shutdown. Serializes our current state to disk.
167 *
168 * @param cls closure, unused
169 * @param tc scheduler context, unused
50 */ 170 */
51static void 171static void
52do_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 172do_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
53{ 173{
54 kill_task = GNUNET_SCHEDULER_NO_TASK; 174 kill_task = GNUNET_SCHEDULER_NO_TASK;
175 do_shutdown = GNUNET_YES;
176 if (GNUNET_SCHEDULER_NO_TASK != run_task)
177 {
178 GNUNET_SCHEDULER_cancel (run_task);
179 run_task = GNUNET_SCHEDULER_NO_TASK;
180 }
181}
182
183
184/**
185 * Decide what the next task is (working or scanning) and schedule it.
186 */
187static void
188schedule_next_task (void);
189
190
191/**
192 * Function called to process work items.
193 *
194 * @param cls closure, NULL
195 * @param tc scheduler context (unused)
196 */
197static void
198work (void *cls,
199 const struct GNUNET_SCHEDULER_TaskContext *tc)
200{
201 struct WorkItem *wi;
202 struct GNUNET_HashCode key;
203
204 run_task = GNUNET_SCHEDULER_NO_TASK;
205 wi = work_head;
206 GNUNET_CONTAINER_DLL_remove (work_head,
207 work_tail,
208 wi);
209 // FIXME: actually run 'publish' here!
210
211 GNUNET_CRYPTO_hash (wi->filename,
212 strlen (wi->filename),
213 &key);
214 GNUNET_CONTAINER_multihashmap_put (work_finished,
215 &key,
216 wi,
217 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
218 save_state ();
219 schedule_next_task ();
220}
221
222
223/**
224 * Recursively scan the given file/directory structure to determine
225 * a unique ID that represents the current state of the hierarchy.
226 *
227 * @param filename file to scan
228 * @param id where to store the unique ID we computed
229 */
230static void
231determine_id (const char *filename,
232 struct GNUNET_HashCode *id)
233{
234 // FIXME: implement!
235 GNUNET_break (0);
236}
237
238
239/**
240 * Function called with a filename (or directory name) to publish
241 * (if it has changed since the last time we published it). This function
242 * is called for the top-level files only.
243 *
244 * @param cls closure, NULL
245 * @param filename complete filename (absolute path)
246 * @return GNUNET_OK to continue to iterate, GNUNET_SYSERR during shutdown
247 */
248static int
249add_file (void *cls,
250 const char *filename)
251{
252 struct WorkItem *wi;
253 struct GNUNET_HashCode key;
254 struct GNUNET_HashCode id;
255
256 if (GNUNET_YES == do_shutdown)
257 return GNUNET_SYSERR;
258 GNUNET_CRYPTO_hash (filename,
259 strlen (filename),
260 &key);
261 wi = GNUNET_CONTAINER_multihashmap_get (work_finished,
262 &key);
263 memset (&id, 0, sizeof (struct GNUNET_HashCode));
264 determine_id (filename, &id);
265 if (NULL != wi)
266 {
267 if (0 == memcmp (&id,
268 &wi->id,
269 sizeof (struct GNUNET_HashCode)))
270 return GNUNET_OK; /* skip: we did this one already */
271 /* contents changed, need to re-do the directory... */
272 GNUNET_CONTAINER_multihashmap_remove (work_finished,
273 &key,
274 wi);
275 wi->id = id;
276 }
277 else
278 {
279 wi = GNUNET_malloc (sizeof (struct WorkItem));
280 wi->filename = GNUNET_strdup (filename);
281 }
282 GNUNET_CONTAINER_DLL_insert (work_head,
283 work_tail,
284 wi);
285 if (GNUNET_YES == do_shutdown)
286 return GNUNET_SYSERR;
287 return GNUNET_OK;
288}
289
290
291/**
292 * Periodically run task to update our view of the directory to share.
293 *
294 * @param cls NULL
295 * @param tc scheduler context, unused
296 */
297static void
298scan (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
299{
300 run_task = GNUNET_SCHEDULER_NO_TASK;
301 start_time = GNUNET_TIME_absolute_get ();
302 (void) GNUNET_DISK_directory_scan (dir_name,
303 &add_file,
304 NULL);
305 schedule_next_task ();
55} 306}
56 307
57 308
309/**
310 * Decide what the next task is (working or scanning) and schedule it.
311 */
312static void
313schedule_next_task ()
314{
315 struct GNUNET_TIME_Relative delay;
316
317 if (GNUNET_YES == do_shutdown)
318 return;
319 if (NULL == work_head)
320 {
321 /* delay by at most 4h, at least 1s, and otherwise in between depending
322 on how long it took to scan */
323 delay = GNUNET_TIME_absolute_get_duration (start_time);
324 delay = GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS,
325 4),
326 GNUNET_TIME_relative_multiply (delay,
327 100));
328 delay = GNUNET_TIME_relative_max (delay,
329 GNUNET_TIME_UNIT_MINUTES);
330 run_task = GNUNET_SCHEDULER_add_delayed (delay,
331 &scan,
332 NULL);
333 }
334 else
335 {
336 run_task = GNUNET_SCHEDULER_add_now (&work, NULL);
337 }
338}
58 339
59 340
60/** 341/**
@@ -78,7 +359,12 @@ run (void *cls, char *const *args, const char *cfgfile,
78 return; 359 return;
79 } 360 }
80 cfg = c; 361 cfg = c;
81 // FIXME... 362 dir_name = args[0];
363 work_finished = GNUNET_CONTAINER_multihashmap_create (1024);
364 load_state ();
365 run_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
366 &scan, NULL);
367
82 kill_task = 368 kill_task =
83 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task, 369 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task,
84 NULL); 370 NULL);
@@ -94,7 +380,7 @@ run (void *cls, char *const *args, const char *cfgfile,
94 */ 380 */
95int 381int
96main (int argc, char *const *argv) 382main (int argc, char *const *argv)
97{ 383{
98 static const struct GNUNET_GETOPT_CommandLineOption options[] = { 384 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
99 {'a', "anonymity", "LEVEL", 385 {'a', "anonymity", "LEVEL",
100 gettext_noop ("set the desired LEVEL of sender-anonymity"), 386 gettext_noop ("set the desired LEVEL of sender-anonymity"),
@@ -117,13 +403,17 @@ main (int argc, char *const *argv)
117 0, &GNUNET_GETOPT_set_one, &verbose}, 403 0, &GNUNET_GETOPT_set_one, &verbose},
118 GNUNET_GETOPT_OPTION_END 404 GNUNET_GETOPT_OPTION_END
119 }; 405 };
406 int ok;
407
120 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 408 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
121 return 2; 409 return 2;
122 return (GNUNET_OK == 410 ok = (GNUNET_OK ==
123 GNUNET_PROGRAM_run (argc, argv, "gnunet-auto-share [OPTIONS] FILENAME", 411 GNUNET_PROGRAM_run (argc, argv, "gnunet-auto-share [OPTIONS] FILENAME",
124 gettext_noop 412 gettext_noop
125 ("Automatically publish files from a directory on GNUnet"), 413 ("Automatically publish files from a directory on GNUnet"),
126 options, &run, NULL)) ? ret : 1; 414 options, &run, NULL)) ? ret : 1;
415 // FIXME: free memory in work lists and hash map...
416 return ok;
127} 417}
128 418
129/* end of gnunet-auto-share.c */ 419/* end of gnunet-auto-share.c */