X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ffs%2Fgnunet-auto-share.c;h=86cab5593ed1c531e62e3b12ebc5d9aaa28253ae;hb=df6facef1ea4d8dd7fe836d78473aa66270d6684;hp=ad3267d9a81591e5cbb35a40e7642146312856a6;hpb=fe4e9927e25d2abee888fe8be318e150b0f0f4a0;p=oweals%2Fgnunet.git diff --git a/src/fs/gnunet-auto-share.c b/src/fs/gnunet-auto-share.c index ad3267d9a..86cab5593 100644 --- a/src/fs/gnunet-auto-share.c +++ b/src/fs/gnunet-auto-share.c @@ -24,10 +24,15 @@ * * TODO: * - support loading meta data / keywords from resource file + * - add stability timer (a la buildbot) */ #include "platform.h" #include "gnunet_util_lib.h" +#define MIN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4) + +#define MAX_FREQUENCY GNUNET_TIME_UNIT_MINUTES + /** * Item in our work queue (or in the set of files/directories @@ -206,6 +211,10 @@ load_state () wi = GNUNET_malloc (sizeof (struct WorkItem)); wi->id = id; wi->filename = fn; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Loaded serialization ID for `%s' is `%s'\n", + wi->filename, + GNUNET_h2s (&id)); fn = NULL; GNUNET_CRYPTO_hash (wi->filename, strlen (wi->filename), @@ -222,7 +231,7 @@ load_state () error: GNUNET_free_non_null (fn); if (NULL != rh) - GNUNET_BIO_read_close (rh, &emsg); + (void) GNUNET_BIO_read_close (rh, &emsg); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to load state: %s\n"), emsg); @@ -246,6 +255,10 @@ write_item (void *cls, struct GNUNET_BIO_WriteHandle *wh = cls; struct WorkItem *wi = value; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Saving serialization ID of file `%s' with value `%s'\n", + wi->filename, + GNUNET_h2s (&wi->id)); if ( (GNUNET_OK != GNUNET_BIO_write_string (wh, wi->filename)) || (GNUNET_OK != @@ -270,6 +283,14 @@ save_state () n = GNUNET_CONTAINER_multihashmap_size (work_finished); fn = get_state_file (); wh = GNUNET_BIO_write_open (fn); + if (NULL == wh) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Failed to save state to file %s\n"), + fn); + GNUNET_free (fn); + return; + } if (GNUNET_OK != GNUNET_BIO_write_int32 (wh, n)) { @@ -334,19 +355,65 @@ maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct WorkItem *wi = cls; struct GNUNET_HashCode key; + enum GNUNET_OS_ProcessStatusType type; + unsigned long code; + int ret; + char c; + const struct GNUNET_DISK_FileHandle *pr; + run_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_break (GNUNET_OK == - GNUNET_OS_process_wait (publish_proc)); + pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); + if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) + { + /* shutdown scheduled us, ignore! */ + run_task = + GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + pr, &maint_child_death, wi); + return; + } + + ret = GNUNET_OS_process_status (publish_proc, + &type, + &code); + GNUNET_assert (GNUNET_SYSERR != ret); + if (GNUNET_NO == ret) + { + GNUNET_break (0); + GNUNET_OS_process_kill (publish_proc, SIGKILL); + type = GNUNET_OS_PROCESS_SIGNALED; + } GNUNET_OS_process_destroy (publish_proc); publish_proc = NULL; - GNUNET_CRYPTO_hash (wi->filename, - strlen (wi->filename), - &key); - GNUNET_CONTAINER_multihashmap_put (work_finished, - &key, - wi, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + /* consume the signal */ + GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c))); + + if (GNUNET_YES == do_shutdown) + { + GNUNET_free (wi->filename); + GNUNET_free (wi); + return; + } + if ( (GNUNET_OS_PROCESS_EXITED == type) && + (0 == code) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Publication of `%s' done\n"), + wi->filename); + GNUNET_CRYPTO_hash (wi->filename, + strlen (wi->filename), + &key); + GNUNET_CONTAINER_multihashmap_put (work_finished, + &key, + wi, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + } + else + { + GNUNET_CONTAINER_DLL_insert_tail (work_head, + work_tail, + wi); + } save_state (); schedule_next_task (); } @@ -417,8 +484,11 @@ work (void *cls, argv[argc++] = repl_level; argv[argc++] = wi->filename; argv[argc] = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Publishing `%s'\n"), + wi->filename); publish_proc = GNUNET_OS_start_process_vap (GNUNET_YES, - NULL, NULL, + 0, NULL, NULL, "gnunet-publish", argv); if (NULL == publish_proc) @@ -458,9 +528,6 @@ determine_id (void *cls, struct GNUNET_HashCode fx[2]; struct GNUNET_HashCode ft; - if (NULL != strstr (filename, - DIR_SEPARATOR_STR ".auto-share")) - return GNUNET_OK; /* skip internal file */ if (0 != STAT (filename, &sbuf)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "stat", filename); @@ -469,9 +536,12 @@ determine_id (void *cls, GNUNET_CRYPTO_hash (filename, strlen (filename), &fx[0]); if (!S_ISDIR (sbuf.st_mode)) { - uint64_t fsize = GNUNET_htonll (sbuf.st_size); + uint64_t fattr[2]; + + fattr[0] = GNUNET_htonll (sbuf.st_size); + fattr[0] = GNUNET_htonll (sbuf.st_mtime); - GNUNET_CRYPTO_hash (&fsize, sizeof (uint64_t), &fx[1]); + GNUNET_CRYPTO_hash (fattr, sizeof (fattr), &fx[1]); } else { @@ -509,6 +579,11 @@ add_file (void *cls, if (GNUNET_YES == do_shutdown) return GNUNET_SYSERR; + if ( (NULL != strstr (filename, + "/.auto-share")) || + (NULL != strstr (filename, + "\\.auto-share")) ) + return GNUNET_OK; /* skip internal file */ GNUNET_CRYPTO_hash (filename, strlen (filename), &key); @@ -523,16 +598,17 @@ add_file (void *cls, sizeof (struct GNUNET_HashCode))) return GNUNET_OK; /* skip: we did this one already */ /* contents changed, need to re-do the directory... */ - GNUNET_CONTAINER_multihashmap_remove (work_finished, - &key, - wi); - wi->id = id; + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multihashmap_remove (work_finished, + &key, + wi)); } else { wi = GNUNET_malloc (sizeof (struct WorkItem)); wi->filename = GNUNET_strdup (filename); } + wi->id = id; GNUNET_CONTAINER_DLL_insert (work_head, work_tail, wi); @@ -575,12 +651,11 @@ schedule_next_task () /* delay by at most 4h, at least 1s, and otherwise in between depending on how long it took to scan */ delay = GNUNET_TIME_absolute_get_duration (start_time); - delay = GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, - 4), + delay = GNUNET_TIME_relative_min (MIN_FREQUENCY, GNUNET_TIME_relative_multiply (delay, 100)); delay = GNUNET_TIME_relative_max (delay, - GNUNET_TIME_UNIT_MINUTES); + MAX_FREQUENCY); run_task = GNUNET_SCHEDULER_add_delayed (delay, &scan, NULL); @@ -606,7 +681,7 @@ run (void *cls, char *const *args, const char *cfgfile, { /* check arguments */ if ((args[0] == NULL) || (args[1] != NULL) || - (GNUNET_YES != GNUNET_DISK_directory_test (args[0]))) + (GNUNET_YES != GNUNET_DISK_directory_test (args[0], GNUNET_YES))) { printf (_("You must specify one and only one directory name for automatic publication.\n")); ret = -1; @@ -615,7 +690,7 @@ run (void *cls, char *const *args, const char *cfgfile, cfg_filename = GNUNET_strdup (cfgfile); cfg = c; dir_name = args[0]; - work_finished = GNUNET_CONTAINER_multihashmap_create (1024); + work_finished = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO); load_state (); run_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, &scan, NULL); @@ -646,6 +721,7 @@ free_item (void *cls, return GNUNET_OK; } + /** * The main function to automatically publish content to GNUnet. * @@ -693,10 +769,13 @@ main (int argc, char *const *argv) gettext_noop ("Automatically publish files from a directory on GNUnet"), options, &run, NULL)) ? ret : 1; - (void) GNUNET_CONTAINER_multihashmap_iterate (work_finished, - &free_item, - NULL); - GNUNET_CONTAINER_multihashmap_destroy (work_finished); + if (NULL != work_finished) + { + (void) GNUNET_CONTAINER_multihashmap_iterate (work_finished, + &free_item, + NULL); + GNUNET_CONTAINER_multihashmap_destroy (work_finished); + } while (NULL != (wi = work_head)) { GNUNET_CONTAINER_DLL_remove (work_head, work_tail, wi); @@ -709,6 +788,7 @@ main (int argc, char *const *argv) sigpipe = NULL; GNUNET_free (cfg_filename); cfg_filename = NULL; + GNUNET_free ((void*) argv); return ok; }