aboutsummaryrefslogtreecommitdiff
path: root/src/fs/gnunet-auto-share.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-08-18 17:51:07 +0000
committerChristian Grothoff <christian@grothoff.org>2015-08-18 17:51:07 +0000
commiteb4ebfca26250af0816abf08c5e3364de88c950a (patch)
tree990ea3bfcd78879667ccfa5c8773d3690044d009 /src/fs/gnunet-auto-share.c
parent36731df5428357af5abdae6065e75222d03d49fd (diff)
downloadgnunet-eb4ebfca26250af0816abf08c5e3364de88c950a.tar.gz
gnunet-eb4ebfca26250af0816abf08c5e3364de88c950a.zip
adding some assertions to ensure we only start one gnunet-publish
Diffstat (limited to 'src/fs/gnunet-auto-share.c')
-rw-r--r--src/fs/gnunet-auto-share.c140
1 files changed, 92 insertions, 48 deletions
diff --git a/src/fs/gnunet-auto-share.c b/src/fs/gnunet-auto-share.c
index 7a4cf53be..fc85b29e4 100644
--- a/src/fs/gnunet-auto-share.c
+++ b/src/fs/gnunet-auto-share.c
@@ -97,12 +97,12 @@ static int do_disable_creation_time;
97/** 97/**
98 * Handle for the 'shutdown' task. 98 * Handle for the 'shutdown' task.
99 */ 99 */
100static struct GNUNET_SCHEDULER_Task * kill_task; 100static struct GNUNET_SCHEDULER_Task *kill_task;
101 101
102/** 102/**
103 * Handle for the main task that does scanning and working. 103 * Handle for the main task that does scanning and working.
104 */ 104 */
105static struct GNUNET_SCHEDULER_Task * run_task; 105static struct GNUNET_SCHEDULER_Task *run_task;
106 106
107/** 107/**
108 * Anonymity level option to use for publishing. 108 * Anonymity level option to use for publishing.
@@ -135,13 +135,13 @@ static struct WorkItem *work_head;
135static struct WorkItem *work_tail; 135static struct WorkItem *work_tail;
136 136
137/** 137/**
138 * Map from the hash of the filename (!) to a 'struct WorkItem' 138 * Map from the hash of the filename (!) to a `struct WorkItem`
139 * that was finished. 139 * that was finished.
140 */ 140 */
141static struct GNUNET_CONTAINER_MultiHashMap *work_finished; 141static struct GNUNET_CONTAINER_MultiHashMap *work_finished;
142 142
143/** 143/**
144 * Set to GNUNET_YES if we are shutting down. 144 * Set to #GNUNET_YES if we are shutting down.
145 */ 145 */
146static int do_shutdown; 146static int do_shutdown;
147 147
@@ -180,7 +180,7 @@ get_state_file ()
180 180
181 181
182/** 182/**
183 * Load the set of 'work_finished' items from disk. 183 * Load the set of #work_finished items from disk.
184 */ 184 */
185static void 185static void
186load_state () 186load_state ()
@@ -241,12 +241,12 @@ load_state ()
241 241
242 242
243/** 243/**
244 * Write work item from the work_finished map to the given write handle. 244 * Write work item from the #work_finished map to the given write handle.
245 * 245 *
246 * @param cls the 'struct GNUNET_BIO_WriteHandle*' 246 * @param cls the `struct GNUNET_BIO_WriteHandle *`
247 * @param key key of the item in the map (unused) 247 * @param key key of the item in the map (unused)
248 * @param value the 'struct WorkItem' to write 248 * @param value the `struct WorkItem` to write
249 * @return GNUNET_OK to continue to iterate (if write worked) 249 * @return #GNUNET_OK to continue to iterate (if write worked)
250 */ 250 */
251static int 251static int
252write_item (void *cls, 252write_item (void *cls,
@@ -272,7 +272,7 @@ write_item (void *cls,
272 272
273 273
274/** 274/**
275 * Save the set of 'work_finished' items on disk. 275 * Save the set of #work_finished items on disk.
276 */ 276 */
277static void 277static void
278save_state () 278save_state ()
@@ -320,13 +320,15 @@ save_state ()
320 * @param tc scheduler context, unused 320 * @param tc scheduler context, unused
321 */ 321 */
322static void 322static void
323do_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 323do_stop_task (void *cls,
324 const struct GNUNET_SCHEDULER_TaskContext *tc)
324{ 325{
325 kill_task = NULL; 326 kill_task = NULL;
326 do_shutdown = GNUNET_YES; 327 do_shutdown = GNUNET_YES;
327 if (NULL != publish_proc) 328 if (NULL != publish_proc)
328 { 329 {
329 GNUNET_OS_process_kill (publish_proc, SIGKILL); 330 GNUNET_OS_process_kill (publish_proc,
331 SIGKILL);
330 return; 332 return;
331 } 333 }
332 if (NULL != run_task) 334 if (NULL != run_task)
@@ -348,11 +350,12 @@ schedule_next_task (void);
348 * Task triggered whenever we receive a SIGCHLD (child 350 * Task triggered whenever we receive a SIGCHLD (child
349 * process died). 351 * process died).
350 * 352 *
351 * @param cls the 'struct WorkItem' we were working on 353 * @param cls the `struct WorkItem` we were working on
352 * @param tc context 354 * @param tc context
353 */ 355 */
354static void 356static void
355maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 357maint_child_death (void *cls,
358 const struct GNUNET_SCHEDULER_TaskContext *tc)
356{ 359{
357 struct WorkItem *wi = cls; 360 struct WorkItem *wi = cls;
358 struct GNUNET_HashCode key; 361 struct GNUNET_HashCode key;
@@ -362,15 +365,17 @@ maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
362 char c; 365 char c;
363 const struct GNUNET_DISK_FileHandle *pr; 366 const struct GNUNET_DISK_FileHandle *pr;
364 367
365
366 run_task = NULL; 368 run_task = NULL;
367 pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); 369 pr = GNUNET_DISK_pipe_handle (sigpipe,
370 GNUNET_DISK_PIPE_END_READ);
368 if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) 371 if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
369 { 372 {
370 /* shutdown scheduled us, ignore! */ 373 /* shutdown scheduled us, someone else will kill child,
374 we should just try again */
371 run_task = 375 run_task =
372 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, 376 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
373 pr, &maint_child_death, wi); 377 pr,
378 &maint_child_death, wi);
374 return; 379 return;
375 } 380 }
376 381
@@ -380,10 +385,17 @@ maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
380 GNUNET_assert (GNUNET_SYSERR != ret); 385 GNUNET_assert (GNUNET_SYSERR != ret);
381 if (GNUNET_NO == ret) 386 if (GNUNET_NO == ret)
382 { 387 {
388 /* process still running? Well, how did we get here?
389 Anyway, answer is to kill it! */
383 GNUNET_break (0); 390 GNUNET_break (0);
384 GNUNET_OS_process_kill (publish_proc, SIGKILL); 391 GNUNET_OS_process_kill (publish_proc,
385 type = GNUNET_OS_PROCESS_SIGNALED; 392 SIGKILL);
393 ret = GNUNET_OS_process_status (publish_proc,
394 &type,
395 &code);
386 } 396 }
397 GNUNET_assert (GNUNET_OK == ret);
398
387 GNUNET_OS_process_destroy (publish_proc); 399 GNUNET_OS_process_destroy (publish_proc);
388 publish_proc = NULL; 400 publish_proc = NULL;
389 /* consume the signal */ 401 /* consume the signal */
@@ -433,7 +445,8 @@ sighandler_child_death ()
433 445
434 GNUNET_break (1 == 446 GNUNET_break (1 ==
435 GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle 447 GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle
436 (sigpipe, GNUNET_DISK_PIPE_END_WRITE), 448 (sigpipe,
449 GNUNET_DISK_PIPE_END_WRITE),
437 &c, sizeof (c))); 450 &c, sizeof (c)));
438 errno = old_errno; /* restore errno */ 451 errno = old_errno; /* restore errno */
439} 452}
@@ -489,6 +502,7 @@ work (void *cls,
489 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 502 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
490 _("Publishing `%s'\n"), 503 _("Publishing `%s'\n"),
491 wi->filename); 504 wi->filename);
505 GNUNET_assert (NULL == publish_proc);
492 publish_proc = GNUNET_OS_start_process_vap (GNUNET_YES, 506 publish_proc = GNUNET_OS_start_process_vap (GNUNET_YES,
493 0, NULL, NULL, NULL, 507 0, NULL, NULL, NULL,
494 "gnunet-publish", 508 "gnunet-publish",
@@ -506,10 +520,12 @@ work (void *cls,
506 NULL); 520 NULL);
507 return; 521 return;
508 } 522 }
509 pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); 523 pr = GNUNET_DISK_pipe_handle (sigpipe,
524 GNUNET_DISK_PIPE_END_READ);
510 run_task = 525 run_task =
511 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, 526 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
512 pr, &maint_child_death, wi); 527 pr,
528 &maint_child_death, wi);
513} 529}
514 530
515 531
@@ -519,7 +535,7 @@ work (void *cls,
519 * 535 *
520 * @param cls where to store the unique ID we are computing 536 * @param cls where to store the unique ID we are computing
521 * @param filename file to scan 537 * @param filename file to scan
522 * @return GNUNET_OK (always) 538 * @return #GNUNET_OK (always)
523 */ 539 */
524static int 540static int
525determine_id (void *cls, 541determine_id (void *cls,
@@ -532,10 +548,14 @@ determine_id (void *cls,
532 548
533 if (0 != STAT (filename, &sbuf)) 549 if (0 != STAT (filename, &sbuf))
534 { 550 {
535 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "stat", filename); 551 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
552 "stat",
553 filename);
536 return GNUNET_OK; 554 return GNUNET_OK;
537 } 555 }
538 GNUNET_CRYPTO_hash (filename, strlen (filename), &fx[0]); 556 GNUNET_CRYPTO_hash (filename,
557 strlen (filename),
558 &fx[0]);
539 if (!S_ISDIR (sbuf.st_mode)) 559 if (!S_ISDIR (sbuf.st_mode))
540 { 560 {
541 uint64_t fattr[2]; 561 uint64_t fattr[2];
@@ -543,21 +563,29 @@ determine_id (void *cls,
543 fattr[0] = GNUNET_htonll (sbuf.st_size); 563 fattr[0] = GNUNET_htonll (sbuf.st_size);
544 fattr[0] = GNUNET_htonll (sbuf.st_mtime); 564 fattr[0] = GNUNET_htonll (sbuf.st_mtime);
545 565
546 GNUNET_CRYPTO_hash (fattr, sizeof (fattr), &fx[1]); 566 GNUNET_CRYPTO_hash (fattr,
567 sizeof (fattr),
568 &fx[1]);
547 } 569 }
548 else 570 else
549 { 571 {
550 memset (&fx[1], 1, sizeof (struct GNUNET_HashCode)); 572 memset (&fx[1],
573 1,
574 sizeof (struct GNUNET_HashCode));
551 GNUNET_DISK_directory_scan (filename, 575 GNUNET_DISK_directory_scan (filename,
552 &determine_id, 576 &determine_id,
553 &fx[1]); 577 &fx[1]);
554 } 578 }
555 /* use hash here to make hierarchical structure distinct from 579 /* use hash here to make hierarchical structure distinct from
556 all files on the same level */ 580 all files on the same level */
557 GNUNET_CRYPTO_hash (fx, sizeof (fx), &ft); 581 GNUNET_CRYPTO_hash (fx,
582 sizeof (fx),
583 &ft);
558 /* use XOR here so that order of the files in the directory 584 /* use XOR here so that order of the files in the directory
559 does not matter! */ 585 does not matter! */
560 GNUNET_CRYPTO_hash_xor (&ft, id, id); 586 GNUNET_CRYPTO_hash_xor (&ft,
587 id,
588 id);
561 return GNUNET_OK; 589 return GNUNET_OK;
562} 590}
563 591
@@ -569,7 +597,7 @@ determine_id (void *cls,
569 * 597 *
570 * @param cls closure, NULL 598 * @param cls closure, NULL
571 * @param filename complete filename (absolute path) 599 * @param filename complete filename (absolute path)
572 * @return GNUNET_OK to continue to iterate, GNUNET_SYSERR during shutdown 600 * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR during shutdown
573 */ 601 */
574static int 602static int
575add_file (void *cls, 603add_file (void *cls,
@@ -627,7 +655,8 @@ add_file (void *cls,
627 * @param tc scheduler context, unused 655 * @param tc scheduler context, unused
628 */ 656 */
629static void 657static void
630scan (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 658scan (void *cls,
659 const struct GNUNET_SCHEDULER_TaskContext *tc)
631{ 660{
632 run_task = NULL; 661 run_task = NULL;
633 start_time = GNUNET_TIME_absolute_get (); 662 start_time = GNUNET_TIME_absolute_get ();
@@ -648,6 +677,7 @@ schedule_next_task ()
648 677
649 if (GNUNET_YES == do_shutdown) 678 if (GNUNET_YES == do_shutdown)
650 return; 679 return;
680 GNUNET_assert (NULL == run_task);
651 if (NULL == work_head) 681 if (NULL == work_head)
652 { 682 {
653 /* delay by at most 4h, at least 1s, and otherwise in between depending 683 /* delay by at most 4h, at least 1s, and otherwise in between depending
@@ -664,7 +694,8 @@ schedule_next_task ()
664 } 694 }
665 else 695 else
666 { 696 {
667 run_task = GNUNET_SCHEDULER_add_now (&work, NULL); 697 run_task = GNUNET_SCHEDULER_add_now (&work,
698 NULL);
668 } 699 }
669} 700}
670 701
@@ -678,12 +709,17 @@ schedule_next_task ()
678 * @param c configuration 709 * @param c configuration
679 */ 710 */
680static void 711static void
681run (void *cls, char *const *args, const char *cfgfile, 712run (void *cls,
713 char *const *args,
714 const char *cfgfile,
682 const struct GNUNET_CONFIGURATION_Handle *c) 715 const struct GNUNET_CONFIGURATION_Handle *c)
683{ 716{
684 /* check arguments */ 717 /* check arguments */
685 if ((args[0] == NULL) || (args[1] != NULL) || 718 if ( (NULL == args[0]) ||
686 (GNUNET_YES != GNUNET_DISK_directory_test (args[0], GNUNET_YES))) 719 (NULL != args[1]) ||
720 (GNUNET_YES !=
721 GNUNET_DISK_directory_test (args[0],
722 GNUNET_YES)) )
687 { 723 {
688 printf (_("You must specify one and only one directory name for automatic publication.\n")); 724 printf (_("You must specify one and only one directory name for automatic publication.\n"));
689 ret = -1; 725 ret = -1;
@@ -692,13 +728,15 @@ run (void *cls, char *const *args, const char *cfgfile,
692 cfg_filename = GNUNET_strdup (cfgfile); 728 cfg_filename = GNUNET_strdup (cfgfile);
693 cfg = c; 729 cfg = c;
694 dir_name = args[0]; 730 dir_name = args[0];
695 work_finished = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO); 731 work_finished = GNUNET_CONTAINER_multihashmap_create (1024,
732 GNUNET_NO);
696 load_state (); 733 load_state ();
697 run_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, 734 run_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
698 &scan, NULL); 735 &scan,
699 736 NULL);
700 kill_task = 737 kill_task =
701 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task, 738 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
739 &do_stop_task,
702 NULL); 740 NULL);
703} 741}
704 742
@@ -708,8 +746,8 @@ run (void *cls, char *const *args, const char *cfgfile,
708 * 746 *
709 * @param cls NULL (unused) 747 * @param cls NULL (unused)
710 * @param key key of the item in the map (unused) 748 * @param key key of the item in the map (unused)
711 * @param value the 'struct WorkItem' to free 749 * @param value the `struct WorkItem` to free
712 * @return GNUNET_OK to continue to iterate 750 * @return #GNUNET_OK to continue to iterate
713 */ 751 */
714static int 752static int
715free_item (void *cls, 753free_item (void *cls,
@@ -760,14 +798,18 @@ main (int argc, char *const *argv)
760 int ok; 798 int ok;
761 struct GNUNET_SIGNAL_Context *shc_chld; 799 struct GNUNET_SIGNAL_Context *shc_chld;
762 800
763 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 801 if (GNUNET_OK !=
802 GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
764 return 2; 803 return 2;
765 sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO); 804 sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO,
766 GNUNET_assert (sigpipe != NULL); 805 GNUNET_NO, GNUNET_NO);
806 GNUNET_assert (NULL != sigpipe);
767 shc_chld = 807 shc_chld =
768 GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); 808 GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD,
809 &sighandler_child_death);
769 ok = (GNUNET_OK == 810 ok = (GNUNET_OK ==
770 GNUNET_PROGRAM_run (argc, argv, "gnunet-auto-share [OPTIONS] FILENAME", 811 GNUNET_PROGRAM_run (argc, argv,
812 "gnunet-auto-share [OPTIONS] FILENAME",
771 gettext_noop 813 gettext_noop
772 ("Automatically publish files from a directory on GNUnet"), 814 ("Automatically publish files from a directory on GNUnet"),
773 options, &run, NULL)) ? ret : 1; 815 options, &run, NULL)) ? ret : 1;
@@ -780,7 +822,9 @@ main (int argc, char *const *argv)
780 } 822 }
781 while (NULL != (wi = work_head)) 823 while (NULL != (wi = work_head))
782 { 824 {
783 GNUNET_CONTAINER_DLL_remove (work_head, work_tail, wi); 825 GNUNET_CONTAINER_DLL_remove (work_head,
826 work_tail,
827 wi);
784 GNUNET_free (wi->filename); 828 GNUNET_free (wi->filename);
785 GNUNET_free (wi); 829 GNUNET_free (wi);
786 } 830 }