diff options
author | Bertrand Marc <beberking@gmail.com> | 2012-06-06 20:47:48 +0200 |
---|---|---|
committer | Bertrand Marc <beberking@gmail.com> | 2012-06-06 20:47:48 +0200 |
commit | 740b30688bd745a527f96f9116c19acb3480971a (patch) | |
tree | 2709a3f4dba11c174aa9e1ba3612e30c578e76a9 /src/fs | |
parent | 2b81464a43485fcc8ce079fafdee7b7a171835f4 (diff) |
Imported Upstream version 0.9.3upstream/0.9.3
Diffstat (limited to 'src/fs')
48 files changed, 1600 insertions, 574 deletions
diff --git a/src/fs/Makefile.am b/src/fs/Makefile.am index 0de739d..b916e4e 100644 --- a/src/fs/Makefile.am +++ b/src/fs/Makefile.am @@ -50,7 +50,7 @@ libgnunetfs_la_LIBADD = \ libgnunetfs_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ - -version-info 2:0:0 + -version-info 2:1:0 libgnunetfstest_a_SOURCES = \ @@ -206,6 +206,7 @@ check_PROGRAMS = \ test_fs_publish \ test_fs_publish_persistence \ test_fs_search \ + test_fs_search_probes \ test_fs_search_persistence \ test_fs_start_stop \ test_fs_test_lib \ @@ -225,6 +226,11 @@ check_SCRIPTS = \ test_gnunet_fs_ns.py endif +if ENABLE_MONKEY + TESTS_ENVIRONMENT = @MONKEYPREFIX@ + AM_LDFLAGS = -no-install +endif + if ENABLE_TEST_RUN TESTS = \ @@ -239,6 +245,7 @@ TESTS = \ test_fs_publish \ test_fs_publish_persistence \ test_fs_search \ + test_fs_search_probes \ test_fs_search_persistence \ test_fs_start_stop \ test_fs_unindex \ @@ -329,6 +336,11 @@ test_fs_search_SOURCES = \ test_fs_search_LDADD = $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la +test_fs_search_probes_SOURCES = \ + test_fs_search_probes.c +test_fs_search_probes_LDADD = $(top_builddir)/src/fs/libgnunetfs.la \ + $(top_builddir)/src/util/libgnunetutil.la + test_fs_search_persistence_SOURCES = \ test_fs_search_persistence.c test_fs_search_persistence_LDADD = $(top_builddir)/src/fs/libgnunetfs.la \ diff --git a/src/fs/Makefile.in b/src/fs/Makefile.in index cbc844e..1dc8dba 100644 --- a/src/fs/Makefile.in +++ b/src/fs/Makefile.in @@ -51,7 +51,8 @@ check_PROGRAMS = test_fs_directory$(EXEEXT) test_fs_download$(EXEEXT) \ test_fs_list_indexed$(EXEEXT) test_fs_namespace$(EXEEXT) \ test_fs_namespace_list_updateable$(EXEEXT) \ test_fs_publish$(EXEEXT) test_fs_publish_persistence$(EXEEXT) \ - test_fs_search$(EXEEXT) test_fs_search_persistence$(EXEEXT) \ + test_fs_search$(EXEEXT) test_fs_search_probes$(EXEEXT) \ + test_fs_search_persistence$(EXEEXT) \ test_fs_start_stop$(EXEEXT) test_fs_test_lib$(EXEEXT) \ test_fs_unindex$(EXEEXT) test_fs_unindex_persistence$(EXEEXT) \ test_fs_uri$(EXEEXT) test_gnunet_service_fs_migration$(EXEEXT) \ @@ -67,6 +68,7 @@ check_PROGRAMS = test_fs_directory$(EXEEXT) test_fs_download$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_publish$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_publish_persistence$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_search$(EXEEXT) \ +@ENABLE_TEST_RUN_TRUE@ test_fs_search_probes$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_search_persistence$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_start_stop$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_unindex$(EXEEXT) \ @@ -310,6 +312,11 @@ test_fs_search_persistence_OBJECTS = \ test_fs_search_persistence_DEPENDENCIES = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la +am_test_fs_search_probes_OBJECTS = test_fs_search_probes.$(OBJEXT) +test_fs_search_probes_OBJECTS = $(am_test_fs_search_probes_OBJECTS) +test_fs_search_probes_DEPENDENCIES = \ + $(top_builddir)/src/fs/libgnunetfs.la \ + $(top_builddir)/src/util/libgnunetutil.la am_test_fs_start_stop_OBJECTS = test_fs_start_stop.$(OBJEXT) test_fs_start_stop_OBJECTS = $(am_test_fs_start_stop_OBJECTS) test_fs_start_stop_DEPENDENCIES = \ @@ -401,8 +408,8 @@ SOURCES = $(libgnunetfstest_a_SOURCES) \ $(test_fs_publish_persistence_SOURCES) \ $(test_fs_search_SOURCES) \ $(test_fs_search_persistence_SOURCES) \ - $(test_fs_start_stop_SOURCES) $(test_fs_test_lib_SOURCES) \ - $(test_fs_unindex_SOURCES) \ + $(test_fs_search_probes_SOURCES) $(test_fs_start_stop_SOURCES) \ + $(test_fs_test_lib_SOURCES) $(test_fs_unindex_SOURCES) \ $(test_fs_unindex_persistence_SOURCES) $(test_fs_uri_SOURCES) \ $(test_gnunet_service_fs_migration_SOURCES) \ $(test_gnunet_service_fs_p2p_SOURCES) @@ -428,8 +435,8 @@ DIST_SOURCES = $(libgnunetfstest_a_SOURCES) \ $(test_fs_publish_persistence_SOURCES) \ $(test_fs_search_SOURCES) \ $(test_fs_search_persistence_SOURCES) \ - $(test_fs_start_stop_SOURCES) $(test_fs_test_lib_SOURCES) \ - $(test_fs_unindex_SOURCES) \ + $(test_fs_search_probes_SOURCES) $(test_fs_start_stop_SOURCES) \ + $(test_fs_test_lib_SOURCES) $(test_fs_unindex_SOURCES) \ $(test_fs_unindex_persistence_SOURCES) $(test_fs_uri_SOURCES) \ $(test_gnunet_service_fs_migration_SOURCES) \ $(test_gnunet_service_fs_p2p_SOURCES) @@ -494,6 +501,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBADD_DL = @LIBADD_DL@ @@ -527,6 +535,7 @@ LT_DLLOADERS = @LT_DLLOADERS@ LT_DLPREOPEN = @LT_DLPREOPEN@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ +MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ @@ -683,7 +692,7 @@ libgnunetfs_la_LIBADD = \ libgnunetfs_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ - -version-info 2:0:0 + -version-info 2:1:0 libgnunetfstest_a_SOURCES = \ fs_test_lib.c fs_test_lib.h @@ -836,6 +845,8 @@ libgnunet_plugin_block_fs_la_DEPENDENCIES = \ @HAVE_PYTHON_PEXPECT_TRUE@ test_gnunet_fs_idx.py \ @HAVE_PYTHON_PEXPECT_TRUE@ test_gnunet_fs_ns.py +@ENABLE_MONKEY_TRUE@TESTS_ENVIRONMENT = @MONKEYPREFIX@ +@ENABLE_MONKEY_TRUE@AM_LDFLAGS = -no-install test_fs_directory_SOURCES = \ test_fs_directory.c @@ -921,6 +932,12 @@ test_fs_search_SOURCES = \ test_fs_search_LDADD = $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la +test_fs_search_probes_SOURCES = \ + test_fs_search_probes.c + +test_fs_search_probes_LDADD = $(top_builddir)/src/fs/libgnunetfs.la \ + $(top_builddir)/src/util/libgnunetutil.la + test_fs_search_persistence_SOURCES = \ test_fs_search_persistence.c @@ -1288,6 +1305,9 @@ test_fs_search$(EXEEXT): $(test_fs_search_OBJECTS) $(test_fs_search_DEPENDENCIES test_fs_search_persistence$(EXEEXT): $(test_fs_search_persistence_OBJECTS) $(test_fs_search_persistence_DEPENDENCIES) @rm -f test_fs_search_persistence$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_search_persistence_OBJECTS) $(test_fs_search_persistence_LDADD) $(LIBS) +test_fs_search_probes$(EXEEXT): $(test_fs_search_probes_OBJECTS) $(test_fs_search_probes_DEPENDENCIES) + @rm -f test_fs_search_probes$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_fs_search_probes_OBJECTS) $(test_fs_search_probes_LDADD) $(LIBS) test_fs_start_stop$(EXEEXT): $(test_fs_start_stop_OBJECTS) $(test_fs_start_stop_DEPENDENCIES) @rm -f test_fs_start_stop$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_start_stop_OBJECTS) $(test_fs_start_stop_LDADD) $(LIBS) @@ -1400,6 +1420,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_publish_persistence.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_search.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_search_persistence.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_search_probes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_start_stop.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_test_lib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_unindex.Po@am__quote@ diff --git a/src/fs/fs.conf.in b/src/fs/fs.conf.in index 48c8b52..a908b1f 100644 --- a/src/fs/fs.conf.in +++ b/src/fs/fs.conf.in @@ -1,10 +1,10 @@ [fs] AUTOSTART = YES -INDEXDB = $SERVICEHOME/idxinfo.lst -TRUST = $SERVICEHOME/data/credit/ -IDENTITY_DIR = $SERVICEHOME/identities/ -STATE_DIR = $SERVICEHOME/persistence/ -UPDATE_DIR = $SERVICEHOME/updates/ +INDEXDB = $SERVICEHOME/fs/idxinfo.lst +TRUST = $SERVICEHOME/fs/credit/ +IDENTITY_DIR = $SERVICEHOME/fs/identities/ +STATE_DIR = $SERVICEHOME/fs/persistence/ +UPDATE_DIR = $SERVICEHOME/fs/updates/ @UNIXONLY@ PORT = 2094 HOSTNAME = localhost HOME = $SERVICEHOME @@ -20,7 +20,6 @@ CONTENT_PUSHING = YES UNIXPATH = /tmp/gnunet-service-fs.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES -# DISABLE_SOCKET_FORWARDING = NO # DEBUG = YES MAX_PENDING_REQUESTS = 65536 # Maximum frequency we're allowed to poll the datastore @@ -29,4 +28,6 @@ MAX_PENDING_REQUESTS = 65536 MIN_MIGRATION_DELAY = 100 ms EXPECTED_NEIGHBOUR_COUNT = 128 +# Enable monkey? +PREFIX = @MONKEYPREFIX@ diff --git a/src/fs/fs_api.c b/src/fs/fs_api.c index 1df9b2e..651c174 100644 --- a/src/fs/fs_api.c +++ b/src/fs/fs_api.c @@ -30,6 +30,15 @@ #include "fs_api.h" #include "fs_tree.h" +/** + * How many block requests can we have outstanding in parallel at a time by default? + */ +#define DEFAULT_MAX_PARALLEL_REQUESTS (1024 * 10) + +/** + * How many downloads can we have outstanding in parallel at a time by default? + */ +#define DEFAULT_MAX_PARALLEL_DOWNLOADS 16 /** * Start the given job (send signal, remove from pending queue, update @@ -99,6 +108,8 @@ process_job_queue (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct GNUNET_TIME_Absolute end_time; h->queue_job = GNUNET_SCHEDULER_NO_TASK; + restart_at = GNUNET_TIME_UNIT_FOREVER_REL; + /* first, see if we can start all the jobs */ next = h->pending_head; while (NULL != (qe = next)) { @@ -109,7 +120,7 @@ process_job_queue (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) continue; } if ((qe->blocks + h->active_blocks <= h->max_parallel_requests) && - (h->active_downloads + 1 <= h->max_parallel_downloads)) + (h->active_downloads < h->max_parallel_downloads)) { start_job (qe); continue; @@ -117,7 +128,7 @@ process_job_queue (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } if (h->pending_head == NULL) return; /* no need to stop anything */ - restart_at = GNUNET_TIME_UNIT_FOREVER_REL; + /* then, check if we should stop some jobs */ next = h->running_head; while (NULL != (qe = next)) { @@ -125,6 +136,22 @@ process_job_queue (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) run_time = GNUNET_TIME_relative_multiply (h->avg_block_latency, qe->blocks * qe->start_times); + switch (qe->priority) + { + case GNUNET_FS_QUEUE_PRIORITY_PROBE: + /* run probes for at most 1s * number-of-restarts; note that + as the total runtime of a probe is limited to 2m, we don't + need to additionally limit the total time of a probe to + strictly limit its lifetime. */ + run_time = GNUNET_TIME_relative_min (run_time, + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, + 1 + qe->start_times)); + break; + case GNUNET_FS_QUEUE_PRIORITY_NORMAL: + break; + default: + GNUNET_break (0); + } end_time = GNUNET_TIME_absolute_add (qe->start_time, run_time); rst = GNUNET_TIME_absolute_get_remaining (end_time); restart_at = GNUNET_TIME_relative_min (rst, restart_at); @@ -132,6 +159,18 @@ process_job_queue (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) continue; stop_job (qe); } + /* finally, start some more tasks if we now have empty slots */ + next = h->pending_head; + while (NULL != (qe = next)) + { + next = qe->next; + if ((qe->blocks + h->active_blocks <= h->max_parallel_requests) && + (h->active_downloads < h->max_parallel_downloads)) + { + start_job (qe); + continue; + } + } h->queue_job = GNUNET_SCHEDULER_add_delayed (restart_at, &process_job_queue, h); } @@ -145,11 +184,13 @@ process_job_queue (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * @param stop function to call to pause the job, or on dequeue (if the job was running) * @param cls closure for start and stop * @param blocks number of blocks this jobs uses + * @param priority how important is this download * @return queue handle */ struct GNUNET_FS_QueueEntry * GNUNET_FS_queue_ (struct GNUNET_FS_Handle *h, GNUNET_FS_QueueStart start, - GNUNET_FS_QueueStop stop, void *cls, unsigned int blocks) + GNUNET_FS_QueueStop stop, void *cls, unsigned int blocks, + enum GNUNET_FS_QueuePriority priority) { struct GNUNET_FS_QueueEntry *qe; @@ -160,6 +201,7 @@ GNUNET_FS_queue_ (struct GNUNET_FS_Handle *h, GNUNET_FS_QueueStart start, qe->cls = cls; qe->queue_time = GNUNET_TIME_absolute_get (); qe->blocks = blocks; + qe->priority = priority; GNUNET_CONTAINER_DLL_insert_after (h->pending_head, h->pending_tail, h->pending_tail, qe); if (h->queue_job != GNUNET_SCHEDULER_NO_TASK) @@ -249,7 +291,11 @@ struct FileInfo * @param cls closure (points to the file information) * @param offset offset to read from; it is possible * that the caller might need to go backwards - * a bit at times + * a bit at times; set to UINT64_MAX to tell + * the reader that we won't be reading for a while + * (used to close the file descriptor but NOT fully + * clean up the reader's state); in this case, + * a value of '0' for max should be ignored * @param max maximum number of bytes that should be * copied to buf; readers are not allowed * to provide less data unless there is an error; @@ -266,20 +312,29 @@ GNUNET_FS_data_reader_file_ (void *cls, uint64_t offset, size_t max, void *buf, struct FileInfo *fi = cls; ssize_t ret; - if (max == 0) + if (UINT64_MAX == offset) { - if (fi->fd != NULL) + if (NULL != fi->fd) + { + GNUNET_DISK_file_close (fi->fd); + fi->fd = NULL; + } + return 0; + } + if (0 == max) + { + if (NULL != fi->fd) GNUNET_DISK_file_close (fi->fd); GNUNET_free (fi->filename); GNUNET_free (fi); return 0; } - if (fi->fd == NULL) + if (NULL == fi->fd) { fi->fd = GNUNET_DISK_file_open (fi->filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); - if (fi->fd == NULL) + if (NULL == fi->fd) { GNUNET_asprintf (emsg, _("Could not open file `%s': %s"), fi->filename, STRERROR (errno)); @@ -288,7 +343,7 @@ GNUNET_FS_data_reader_file_ (void *cls, uint64_t offset, size_t max, void *buf, } GNUNET_DISK_file_seek (fi->fd, offset, GNUNET_DISK_SEEK_SET); ret = GNUNET_DISK_file_read (fi->fd, buf, max); - if (ret == -1) + if (-1 == ret) { GNUNET_asprintf (emsg, _("Could not read file `%s': %s"), fi->filename, STRERROR (errno)); @@ -332,7 +387,11 @@ GNUNET_FS_make_file_reader_context_ (const char *filename) * @param cls closure (points to the buffer) * @param offset offset to read from; it is possible * that the caller might need to go backwards - * a bit at times + * a bit at times; set to UINT64_MAX to tell + * the reader that we won't be reading for a while + * (used to close the file descriptor but NOT fully + * clean up the reader's state); in this case, + * a value of '0' for max should be ignored * @param max maximum number of bytes that should be * copied to buf; readers are not allowed * to provide less data unless there is an error; @@ -348,6 +407,8 @@ GNUNET_FS_data_reader_copy_ (void *cls, uint64_t offset, size_t max, void *buf, { char *data = cls; + if (UINT64_MAX == offset) + return 0; if (max == 0) { GNUNET_free_non_null (data); @@ -1482,6 +1543,7 @@ void GNUNET_FS_unindex_sync_ (struct GNUNET_FS_UnindexContext *uc) { struct GNUNET_BIO_WriteHandle *wh; + char *uris; if (NULL == uc->serialization) uc->serialization = @@ -1496,10 +1558,18 @@ GNUNET_FS_unindex_sync_ (struct GNUNET_FS_UnindexContext *uc) GNUNET_break (0); goto cleanup; } + if (NULL != uc->ksk_uri) + uris = GNUNET_FS_uri_to_string (uc->ksk_uri); + else + uris = NULL; if ((GNUNET_OK != GNUNET_BIO_write_string (wh, uc->filename)) || (GNUNET_OK != GNUNET_BIO_write_int64 (wh, uc->file_size)) || (GNUNET_OK != write_start_time (wh, uc->start_time)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, (uint32_t) uc->state)) || + (GNUNET_OK != + GNUNET_BIO_write (wh, &uc->chk, sizeof (struct ContentHashKey))) || + (GNUNET_OK != GNUNET_BIO_write_string (wh, uris)) || + (GNUNET_OK != GNUNET_BIO_write_int32 (wh, (uint32_t) uc->ksk_offset)) || ((uc->state == UNINDEX_STATE_FS_NOTIFY) && (GNUNET_OK != GNUNET_BIO_write (wh, &uc->file_id, sizeof (GNUNET_HashCode)))) || @@ -1637,9 +1707,8 @@ get_download_sync_filename (struct GNUNET_FS_DownloadContext *dc, if (dc->parent == NULL) return get_serialization_file_name (dc->h, - (dc->search != - NULL) ? - GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD : + (dc->search != NULL) ? + GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD : GNUNET_FS_SYNC_PATH_MASTER_DOWNLOAD, uni); if (dc->parent->serialization == NULL) @@ -1669,6 +1738,8 @@ GNUNET_FS_download_sync_ (struct GNUNET_FS_DownloadContext *dc) char *fn; char *dir; + if (0 != (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE)) + return; /* we don't sync probes */ if (NULL == dc->serialization) { dir = get_download_sync_filename (dc, "", ""); @@ -1920,6 +1991,7 @@ deserialize_unindex_file (void *cls, const char *filename) struct GNUNET_FS_UnindexContext *uc; struct GNUNET_FS_ProgressInfo pi; char *emsg; + char *uris; uint32_t state; uc = GNUNET_malloc (sizeof (struct GNUNET_FS_UnindexContext)); @@ -1931,15 +2003,37 @@ deserialize_unindex_file (void *cls, const char *filename) GNUNET_break (0); goto cleanup; } + uris = NULL; if ((GNUNET_OK != GNUNET_BIO_read_string (rh, "unindex-fn", &uc->filename, 10 * 1024)) || (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &uc->file_size)) || (GNUNET_OK != read_start_time (rh, &uc->start_time)) || - (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &state))) + (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &state)) || + (GNUNET_OK != GNUNET_BIO_read (rh, "uri", &uc->chk, sizeof (struct ContentHashKey))) || + (GNUNET_OK != GNUNET_BIO_read_string (rh, "unindex-kskuri", &uris, 10 * 1024)) || + (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &uc->ksk_offset)) ) { + GNUNET_free_non_null (uris); GNUNET_break (0); goto cleanup; } + if (NULL != uris) + { + uc->ksk_uri = GNUNET_FS_uri_parse (uris, &emsg); + GNUNET_free (uris); + if (NULL == uc->ksk_uri) + { + GNUNET_break (0); + goto cleanup; + } + } + if ( (uc->ksk_offset > 0) && + ( (NULL == uc->ksk_uri) || + (uc->ksk_offset > uc->ksk_uri->data.ksk.keywordCount) ) ) + { + GNUNET_break (0); + goto cleanup; + } uc->state = (enum UnindexState) state; switch (state) { @@ -1955,6 +2049,8 @@ deserialize_unindex_file (void *cls, const char *filename) } break; case UNINDEX_STATE_DS_REMOVE: + case UNINDEX_STATE_EXTRACT_KEYWORDS: + case UNINDEX_STATE_DS_REMOVE_KBLOCKS: break; case UNINDEX_STATE_COMPLETE: break; @@ -1991,6 +2087,12 @@ deserialize_unindex_file (void *cls, const char *filename) case UNINDEX_STATE_DS_REMOVE: GNUNET_FS_unindex_do_remove_ (uc); break; + case UNINDEX_STATE_EXTRACT_KEYWORDS: + GNUNET_FS_unindex_do_extract_keywords_ (uc); + break; + case UNINDEX_STATE_DS_REMOVE_KBLOCKS: + GNUNET_FS_unindex_do_remove_kblocks_ (uc); + break; case UNINDEX_STATE_COMPLETE: case UNINDEX_STATE_ERROR: /* no need to resume any operation, we were done */ @@ -2762,8 +2864,8 @@ GNUNET_FS_start (const struct GNUNET_CONFIGURATION_Handle *cfg, ret->upcb = upcb; ret->upcb_cls = upcb_cls; ret->flags = flags; - ret->max_parallel_downloads = 1; - ret->max_parallel_requests = 1; + ret->max_parallel_downloads = DEFAULT_MAX_PARALLEL_DOWNLOADS; + ret->max_parallel_requests = DEFAULT_MAX_PARALLEL_REQUESTS; ret->avg_block_latency = GNUNET_TIME_UNIT_MINUTES; /* conservative starting point */ va_start (ap, flags); while (GNUNET_FS_OPTIONS_END != (opt = va_arg (ap, enum GNUNET_FS_OPTIONS))) diff --git a/src/fs/fs_api.h b/src/fs/fs_api.h index de66ac6..e75b75f 100644 --- a/src/fs/fs_api.h +++ b/src/fs/fs_api.h @@ -417,6 +417,24 @@ typedef void (*GNUNET_FS_QueueStart) (void *cls, typedef void (*GNUNET_FS_QueueStop) (void *cls); + +/** + * Priorities for the queue. + */ +enum GNUNET_FS_QueuePriority + { + /** + * This is a probe (low priority). + */ + GNUNET_FS_QUEUE_PRIORITY_PROBE, + + /** + * Default priority. + */ + GNUNET_FS_QUEUE_PRIORITY_NORMAL + }; + + /** * Entry in the job queue. */ @@ -479,6 +497,11 @@ struct GNUNET_FS_QueueEntry unsigned int blocks; /** + * How important is this download? + */ + enum GNUNET_FS_QueuePriority priority; + + /** * How often have we (re)started this download? */ unsigned int start_times; @@ -599,11 +622,13 @@ struct GNUNET_FS_SearchResult * @param stop function to call to pause the job, or on dequeue (if the job was running) * @param cls closure for start and stop * @param blocks number of blocks this download has + * @param priority how important is this download * @return queue handle */ struct GNUNET_FS_QueueEntry * GNUNET_FS_queue_ (struct GNUNET_FS_Handle *h, GNUNET_FS_QueueStart start, - GNUNET_FS_QueueStop stop, void *cls, unsigned int blocks); + GNUNET_FS_QueueStop stop, void *cls, unsigned int blocks, + enum GNUNET_FS_QueuePriority priority); /** @@ -709,6 +734,24 @@ GNUNET_FS_unindex_process_hash_ (void *cls, const GNUNET_HashCode * file_id); /** + * Extract the keywords for KBlock removal + * + * @param uc context for the unindex operation. + */ +void +GNUNET_FS_unindex_do_extract_keywords_ (struct GNUNET_FS_UnindexContext *uc); + + +/** + * If necessary, connect to the datastore and remove the KBlocks. + * + * @param uc context for the unindex operation. + */ +void +GNUNET_FS_unindex_do_remove_kblocks_ (struct GNUNET_FS_UnindexContext *uc); + + +/** * Fill in all of the generic fields for a publish event and call the * callback. * @@ -1219,32 +1262,42 @@ struct GNUNET_FS_PublishContext */ enum UnindexState { - /** - * We're currently hashing the file. - */ + /** + * We're currently hashing the file. + */ UNINDEX_STATE_HASHING = 0, - /** - * We're telling the datastore to delete - * the respective entries. - */ + /** + * We're telling the datastore to delete + * the respective DBlocks and IBlocks. + */ UNINDEX_STATE_DS_REMOVE = 1, + + /** + * Find out which keywords apply. + */ + UNINDEX_STATE_EXTRACT_KEYWORDS = 2, - /** - * We're notifying the FS service about - * the unindexing. - */ - UNINDEX_STATE_FS_NOTIFY = 2, - - /** - * We're done. - */ - UNINDEX_STATE_COMPLETE = 3, + /** + * We're telling the datastore to remove KBlocks. + */ + UNINDEX_STATE_DS_REMOVE_KBLOCKS = 3, - /** - * We've encountered a fatal error. - */ - UNINDEX_STATE_ERROR = 4 + /** + * We're notifying the FS service about + * the unindexing. + */ + UNINDEX_STATE_FS_NOTIFY = 4, + + /** + * We're done. + */ + UNINDEX_STATE_COMPLETE = 5, + + /** + * We've encountered a fatal error. + */ + UNINDEX_STATE_ERROR = 6 }; @@ -1255,6 +1308,12 @@ struct GNUNET_FS_UnindexContext { /** + * The content hash key of the last block we processed, will in the + * end be set to the CHK from the URI. Used to remove the KBlocks. + */ + struct ContentHashKey chk; + + /** * Global FS context. */ struct GNUNET_FS_Handle *h; @@ -1265,6 +1324,21 @@ struct GNUNET_FS_UnindexContext struct TopLevelActivity *top; /** + * Directory scanner to find keywords (KBlock removal). + */ + struct GNUNET_FS_DirScanner *dscan; + + /** + * Keywords found (telling us which KBlocks to remove). + */ + struct GNUNET_FS_Uri *ksk_uri; + + /** + * Current offset in KSK removal. + */ + uint32_t ksk_offset; + + /** * Name of the file that we are unindexing. */ char *filename; @@ -1302,6 +1376,27 @@ struct GNUNET_FS_UnindexContext struct GNUNET_DISK_FileHandle *fh; /** + * Handle to datastore 'get_key' operation issued for + * obtaining KBlocks. + */ + struct GNUNET_DATASTORE_QueueEntry *dqe; + + /** + * Current key for decrypting KBLocks from 'get_key' operation. + */ + GNUNET_HashCode key; + + /** + * Current query of 'get_key' operation. + */ + GNUNET_HashCode query; + + /** + * First content UID, 0 for none. + */ + uint64_t first_uid; + + /** * Error message, NULL on success. */ char *emsg; @@ -1317,6 +1412,11 @@ struct GNUNET_FS_UnindexContext uint64_t file_size; /** + * Random offset given to 'GNUNET_DATASTORE_get_key'. + */ + uint64_t roff; + + /** * When did we start? */ struct GNUNET_TIME_Absolute start_time; @@ -1591,6 +1691,11 @@ struct DownloadRequest unsigned int depth; /** + * Offset of the CHK for this block in the parent block + */ + unsigned int chk_idx; + + /** * State in the FSM. */ enum BlockRequestState state; @@ -1821,6 +1926,11 @@ struct GNUNET_FS_DownloadContext */ int in_receive; + /** + * Are we ready to issue requests (reconstructions are finished)? + */ + int issue_requests; + }; diff --git a/src/fs/fs_dirmetascan.c b/src/fs/fs_dirmetascan.c index 4e5354e..6dac690 100644 --- a/src/fs/fs_dirmetascan.c +++ b/src/fs/fs_dirmetascan.c @@ -248,7 +248,7 @@ finish_scan (void *cls, * @param client always NULL * @param msg message from the helper process */ -static void +static int process_helper_msgs (void *cls, void *client, const struct GNUNET_MessageHeader *msg) @@ -257,6 +257,11 @@ process_helper_msgs (void *cls, const char *filename; size_t left; +#if 0 + fprintf (stderr, "DMS parses %u-byte message of type %u\n", + (unsigned int) ntohs (msg->size), + (unsigned int) ntohs (msg->type)); +#endif left = ntohs (msg->size) - sizeof (struct GNUNET_MessageHeader); filename = (const char*) &msg[1]; switch (ntohs (msg->type)) @@ -276,7 +281,7 @@ process_helper_msgs (void *cls, else (void) expand_tree (ds->pos, filename, GNUNET_NO); - return; + return GNUNET_OK; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY: if (filename[left-1] != '\0') { @@ -291,7 +296,7 @@ process_helper_msgs (void *cls, break; } ds->pos = ds->pos->parent; - return; + return GNUNET_OK; } ds->progress_callback (ds->progress_callback_cls, filename, GNUNET_YES, @@ -300,16 +305,16 @@ process_helper_msgs (void *cls, filename, GNUNET_YES); if (NULL == ds->toplevel) ds->toplevel = ds->pos; - return; + return GNUNET_OK; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR: break; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_SKIP_FILE: - if (filename[left-1] != '\0') + if ('\0' != filename[left-1]) break; ds->progress_callback (ds->progress_callback_cls, filename, GNUNET_SYSERR, GNUNET_FS_DIRSCANNER_FILE_IGNORED); - return; + return GNUNET_OK; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_COUNTING_DONE: if (0 != left) { @@ -325,9 +330,9 @@ process_helper_msgs (void *cls, NULL, GNUNET_SYSERR, GNUNET_FS_DIRSCANNER_ALL_COUNTED); ds->pos = ds->toplevel; - if (ds->pos->is_directory == GNUNET_YES) + if (GNUNET_YES == ds->pos->is_directory) ds->pos = advance (ds->pos); - return; + return GNUNET_OK; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_META_DATA: { size_t nlen; @@ -377,7 +382,7 @@ process_helper_msgs (void *cls, } ds->pos->ksk_uri = GNUNET_FS_uri_ksk_create_from_meta_data (ds->pos->meta); ds->pos = advance (ds->pos); - return; + return GNUNET_OK; } case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_FINISHED: if (NULL != ds->pos) @@ -397,7 +402,7 @@ process_helper_msgs (void *cls, } ds->stop_task = GNUNET_SCHEDULER_add_now (&finish_scan, ds); - return; + return GNUNET_OK; default: GNUNET_break (0); break; @@ -405,6 +410,7 @@ process_helper_msgs (void *cls, ds->progress_callback (ds->progress_callback_cls, NULL, GNUNET_SYSERR, GNUNET_FS_DIRSCANNER_INTERNAL_ERROR); + return GNUNET_OK; } diff --git a/src/fs/fs_download.c b/src/fs/fs_download.c index b23d14b..7c4dccb 100644 --- a/src/fs/fs_download.c +++ b/src/fs/fs_download.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2001-2011 Christian Grothoff (and other contributing authors) + (C) 2001-2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -21,9 +21,6 @@ * @file fs/fs_download.c * @brief download methods * @author Christian Grothoff - * - * TODO: - * - different priority for scheduling probe downloads? */ #include "platform.h" #include "gnunet_constants.h" @@ -41,7 +38,7 @@ is_recursive_download (struct GNUNET_FS_DownloadContext *dc) { return (0 != (dc->options & GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE)) && ((GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (dc->meta)) || - ((dc->meta == NULL) && + ((NULL == dc->meta) && ((NULL == dc->filename) || ((strlen (dc->filename) >= strlen (GNUNET_FS_DIRECTORY_EXT)) && (NULL != @@ -75,7 +72,7 @@ compute_disk_offset (uint64_t fsize, uint64_t off, unsigned int depth) uint64_t loff; /* where do IBlocks for depth "i" start? */ unsigned int ioff; /* which IBlock corresponds to "off" at depth "i"? */ - if (depth == 0) + if (0 == depth) return off; /* first IBlocks start at the end of file, rounded up * to full DBLOCK_SIZE */ @@ -111,9 +108,9 @@ GNUNET_FS_download_make_status_ (struct GNUNET_FS_ProgressInfo *pi, pi->value.download.dc = dc; pi->value.download.cctx = dc->client_info; pi->value.download.pctx = - (dc->parent == NULL) ? NULL : dc->parent->client_info; + (NULL == dc->parent) ? NULL : dc->parent->client_info; pi->value.download.sctx = - (dc->search == NULL) ? NULL : dc->search->client_info; + (NULL == dc->search) ? NULL : dc->search->client_info; pi->value.download.uri = dc->uri; pi->value.download.filename = dc->filename; pi->value.download.size = dc->length; @@ -124,7 +121,7 @@ GNUNET_FS_download_make_status_ (struct GNUNET_FS_ProgressInfo *pi, pi->value.download.anonymity = dc->anonymity; pi->value.download.eta = GNUNET_TIME_calculate_eta (dc->start_time, dc->completed, dc->length); - pi->value.download.is_active = (dc->client == NULL) ? GNUNET_NO : GNUNET_YES; + pi->value.download.is_active = (NULL == dc->client) ? GNUNET_NO : GNUNET_YES; if (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE)) dc->client_info = dc->h->upcb (dc->h->upcb_cls, pi); else @@ -183,6 +180,9 @@ struct ProcessResultClosure */ int do_store; + /** + * When did we last transmit the request? + */ struct GNUNET_TIME_Absolute last_transmission; }; @@ -240,7 +240,8 @@ encrypt_existing_match (struct GNUNET_FS_DownloadContext *dc, return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Matching block for `%s' at offset %llu already present, no need for download!\n", + "Matching %u byte block for `%s' at offset %llu already present, no need for download!\n", + (unsigned int) len, dc->filename, (unsigned long long) dr->offset); /* already got it! */ prc.dc = dc; @@ -310,21 +311,21 @@ full_recursive_download (struct GNUNET_FS_DownloadContext *dc) ("Recursive downloads of directories larger than 4 GB are not supported on 32-bit systems\n")); return; } - if (dc->filename != NULL) + if (NULL != dc->filename) { h = GNUNET_DISK_file_open (dc->filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); } else { - GNUNET_assert (dc->temp_filename != NULL); + GNUNET_assert (NULL != dc->temp_filename); h = GNUNET_DISK_file_open (dc->temp_filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); } - if (h == NULL) + if (NULL == h) return; /* oops */ data = GNUNET_DISK_file_map (h, &m, GNUNET_DISK_MAP_TYPE_READ, size); - if (data == NULL) + if (NULL == data) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Directory too large for system address space\n")); @@ -336,7 +337,7 @@ full_recursive_download (struct GNUNET_FS_DownloadContext *dc) GNUNET_DISK_file_unmap (m); } GNUNET_DISK_file_close (h); - if (dc->filename == NULL) + if (NULL == dc->filename) { if (0 != UNLINK (dc->temp_filename)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", @@ -364,25 +365,33 @@ check_completed (struct GNUNET_FS_DownloadContext *dc) struct GNUNET_FS_DownloadContext *pos; /* first, check if we need to download children */ - if ((dc->child_head == NULL) && (is_recursive_download (dc))) + if ((NULL == dc->child_head) && (is_recursive_download (dc))) full_recursive_download (dc); /* then, check if children are done already */ - pos = dc->child_head; - while (pos != NULL) + for (pos = dc->child_head; NULL != pos; pos = pos->next) { if ((pos->emsg == NULL) && (pos->completed < pos->length)) return; /* not done yet */ if ((pos->child_head != NULL) && (pos->has_finished != GNUNET_YES)) return; /* not transitively done yet */ - pos = pos->next; } /* All of our children are done, so mark this download done */ dc->has_finished = GNUNET_YES; - if (dc->job_queue != NULL) + if (NULL != dc->job_queue) { GNUNET_FS_dequeue_ (dc->job_queue); dc->job_queue = NULL; } + if (GNUNET_SCHEDULER_NO_TASK != dc->task) + { + GNUNET_SCHEDULER_cancel (dc->task); + dc->task = GNUNET_SCHEDULER_NO_TASK; + } + if (NULL != dc->rfh) + { + GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (dc->rfh)); + dc->rfh = NULL; + } GNUNET_FS_download_sync_ (dc); /* signal completion */ @@ -390,7 +399,7 @@ check_completed (struct GNUNET_FS_DownloadContext *dc) GNUNET_FS_download_make_status_ (&pi, dc); /* let parent know */ - if (dc->parent != NULL) + if (NULL != dc->parent) check_completed (dc->parent); } @@ -473,7 +482,7 @@ try_match_block (struct GNUNET_FS_DownloadContext *dc, break; } /* write block to disk */ - fn = dc->filename != NULL ? dc->filename : dc->temp_filename; + fn = (NULL != dc->filename) ? dc->filename : dc->temp_filename; fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE | @@ -482,7 +491,7 @@ try_match_block (struct GNUNET_FS_DownloadContext *dc, GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ); - if (fh == NULL) + if (NULL == fh) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn); GNUNET_asprintf (&dc->emsg, _("Failed to open file `%s' for writing"), @@ -517,6 +526,7 @@ try_match_block (struct GNUNET_FS_DownloadContext *dc, pi.value.download.specifics.progress.data_len = dlen; pi.value.download.specifics.progress.depth = 0; pi.value.download.specifics.progress.trust_offered = 0; + pi.value.download.specifics.progress.block_download_duration = GNUNET_TIME_UNIT_ZERO; GNUNET_FS_download_make_status_ (&pi, dc); if ((NULL != dc->filename) && (0 != @@ -559,7 +569,7 @@ match_full_data (void *cls, const char *plugin_name, { struct GNUNET_FS_DownloadContext *dc = cls; - if (type != EXTRACTOR_METATYPE_GNUNET_FULL_DATA) + if (EXTRACTOR_METATYPE_GNUNET_FULL_DATA != type) return 0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u bytes of FD!\n", (unsigned int) data_len); @@ -588,7 +598,7 @@ propagate_up (struct DownloadRequest *dr) { dr->state = BRS_DOWNLOAD_UP; dr = dr->parent; - if (dr == NULL) + if (NULL == dr) break; for (i = 0; i < dr->num_children; i++) if (dr->children[i]->state != BRS_DOWNLOAD_UP) @@ -618,14 +628,13 @@ try_top_down_reconstruction (struct GNUNET_FS_DownloadContext *dc, uint64_t total; size_t len; unsigned int i; - unsigned int chk_off; struct DownloadRequest *drc; uint64_t child_block_size; const struct ContentHashKey *chks; int up_done; - GNUNET_assert (dc->rfh != NULL); - GNUNET_assert (dr->state == BRS_CHK_SET); + GNUNET_assert (NULL != dc->rfh); + GNUNET_assert (BRS_CHK_SET == dr->state); total = GNUNET_FS_uri_chk_get_file_size (dc->uri); GNUNET_assert (dr->depth < dc->treedepth); len = GNUNET_FS_tree_calculate_block_size (total, dr->offset, dr->depth); @@ -652,7 +661,7 @@ try_top_down_reconstruction (struct GNUNET_FS_DownloadContext *dc, /* hash matches but encrypted block does not, really bad */ dr->state = BRS_ERROR; /* propagate up */ - while (dr->parent != NULL) + while (NULL != dr->parent) { dr = dr->parent; dr->state = BRS_ERROR; @@ -670,18 +679,17 @@ try_top_down_reconstruction (struct GNUNET_FS_DownloadContext *dc, drc = dr->children[i]; GNUNET_assert (drc->offset >= dr->offset); child_block_size = GNUNET_FS_tree_compute_tree_size (drc->depth); - GNUNET_assert (0 == (drc->offset - dr->offset) % child_block_size); - chk_off = (drc->offset - dr->offset) / child_block_size; - if (drc->state == BRS_INIT) + GNUNET_assert (0 == (drc->offset - dr->offset) % child_block_size); + if (BRS_INIT == drc->state) { drc->state = BRS_CHK_SET; - drc->chk = chks[chk_off]; + drc->chk = chks[drc->chk_idx]; try_top_down_reconstruction (dc, drc); } - if (drc->state != BRS_DOWNLOAD_UP) + if (BRS_DOWNLOAD_UP != drc->state) up_done = GNUNET_NO; /* children not all done */ } - if (up_done == GNUNET_YES) + if (GNUNET_YES == up_done) propagate_up (dr); /* children all done (or no children...) */ } @@ -736,7 +744,7 @@ schedule_block_download (struct GNUNET_FS_DownloadContext *dc, return; /* already active */ GNUNET_CONTAINER_multihashmap_put (dc->active, &dr->chk.query, dr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - if (dc->client == NULL) + if (NULL == dc->client) return; /* download not active */ GNUNET_CONTAINER_DLL_insert (dc->pending_head, dc->pending_tail, dr); dr->is_pending = GNUNET_YES; @@ -783,26 +791,26 @@ trigger_recursive_download (void *cls, const char *filename, if (NULL == uri) return; /* entry for the directory itself */ cpos = dc->child_head; - while (cpos != NULL) + while (NULL != cpos) { if ((GNUNET_FS_uri_test_equal (uri, cpos->uri)) || - ((filename != NULL) && (0 == strcmp (cpos->filename, filename)))) + ((NULL != filename) && (0 == strcmp (cpos->filename, filename)))) break; cpos = cpos->next; } - if (cpos != NULL) + if (NULL != cpos) return; /* already exists */ fn = NULL; if (NULL == filename) { fn = GNUNET_FS_meta_data_suggest_filename (meta); - if (fn == NULL) + if (NULL == fn) { us = GNUNET_FS_uri_to_string (uri); fn = GNUNET_strdup (&us[strlen (GNUNET_FS_URI_CHK_PREFIX)]); GNUNET_free (us); } - else if (fn[0] == '.') + else if ('.' == fn[0]) { ext = fn; us = GNUNET_FS_uri_to_string (uri); @@ -827,7 +835,7 @@ trigger_recursive_download (void *cls, const char *filename, } filename = fn; } - if (dc->filename == NULL) + if (NULL == dc->filename) { full_name = NULL; } @@ -839,7 +847,7 @@ trigger_recursive_download (void *cls, const char *filename, strstr (dn + strlen (dn) - strlen (GNUNET_FS_DIRECTORY_EXT), GNUNET_FS_DIRECTORY_EXT))); sfn = GNUNET_strdup (filename); - while ((strlen (sfn) > 0) && (filename[strlen (sfn) - 1] == '/')) + while ((strlen (sfn) > 0) && ('/' == filename[strlen (sfn) - 1])) sfn[strlen (sfn) - 1] = '\0'; if ((strlen (dn) >= strlen (GNUNET_FS_DIRECTORY_EXT)) && (NULL != @@ -862,7 +870,7 @@ trigger_recursive_download (void *cls, const char *filename, GNUNET_free (sfn); GNUNET_free (dn); } - if ((full_name != NULL) && + if ((NULL != full_name) && (GNUNET_OK != GNUNET_DISK_directory_create_for_file (full_name))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -899,7 +907,7 @@ GNUNET_FS_free_download_request_ (struct DownloadRequest *dr) { unsigned int i; - if (dr == NULL) + if (NULL == dr) return; for (i = 0; i < dr->num_children; i++) GNUNET_FS_free_download_request_ (dr->children[i]); @@ -937,7 +945,8 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, struct ContentHashKey *chkarr; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received block `%s' matching pending request at depth %u and offset %llu/%llu\n", + "Received %u byte block `%s' matching pending request at depth %u and offset %llu/%llu\n", + (unsigned int) prc->size, GNUNET_h2s (key), dr->depth, (unsigned long long) dr->offset, (unsigned long long) GNUNET_ntohll (dc->uri->data. chk.file_length)); @@ -948,13 +957,13 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, { GNUNET_asprintf (&dc->emsg, _ - ("Internal error or bogus download URI (expected %u bytes at depth %u and offset %llu/%llu, got %u bytes)\n"), + ("Internal error or bogus download URI (expected %u bytes at depth %u and offset %llu/%llu, got %u bytes)"), bs, dr->depth, (unsigned long long) dr->offset, (unsigned long long) GNUNET_ntohll (dc->uri->data. chk.file_length), prc->size); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s", dc->emsg); - while (dr->parent != NULL) + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s\n", dc->emsg); + while (NULL != dr->parent) { dr->state = BRS_ERROR; dr = dr->parent; @@ -982,12 +991,12 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, dr->offset, dr->depth); /* save to disk */ if ((GNUNET_YES == prc->do_store) && - ((dc->filename != NULL) || (is_recursive_download (dc))) && + ((NULL != dc->filename) || (is_recursive_download (dc))) && ((dr->depth == dc->treedepth) || (0 == (dc->options & GNUNET_FS_DOWNLOAD_NO_TEMPORARIES)))) { - fh = GNUNET_DISK_file_open (dc->filename != - NULL ? dc->filename : dc->temp_filename, + fh = GNUNET_DISK_file_open (NULL != dc->filename + ? dc->filename : dc->temp_filename, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_READ | @@ -997,7 +1006,7 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, if (NULL == fh) { GNUNET_asprintf (&dc->emsg, - _("Download failed: could not open file `%s': %s\n"), + _("Download failed: could not open file `%s': %s"), dc->filename, STRERROR (errno)); goto signal_error; } @@ -1007,7 +1016,7 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, if ((off != GNUNET_DISK_file_seek (fh, off, GNUNET_DISK_SEEK_SET))) { GNUNET_asprintf (&dc->emsg, - _("Failed to seek to offset %llu in file `%s': %s\n"), + _("Failed to seek to offset %llu in file `%s': %s"), (unsigned long long) off, dc->filename, STRERROR (errno)); goto signal_error; @@ -1016,7 +1025,7 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, { GNUNET_asprintf (&dc->emsg, _ - ("Failed to write block of %u bytes at offset %llu in file `%s': %s\n"), + ("Failed to write block of %u bytes at offset %llu in file `%s': %s"), (unsigned int) prc->size, (unsigned long long) off, dc->filename, STRERROR (errno)); goto signal_error; @@ -1025,7 +1034,7 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, fh = NULL; } - if (dr->depth == 0) + if (0 == dr->depth) { /* DBLOCK, update progress and try recursion if applicable */ app = prc->size; @@ -1052,7 +1061,6 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, if (is_recursive_download (dc)) GNUNET_FS_directory_list_contents (prc->size, pt, off, &trigger_recursive_download, dc); - } GNUNET_assert (dc->completed <= dc->length); dr->state = BRS_DOWNLOAD_DOWN; @@ -1063,13 +1071,13 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, pi.value.download.specifics.progress.depth = dr->depth; pi.value.download.specifics.progress.trust_offered = 0; if (prc->last_transmission.abs_value != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value) - pi.value.download.specifics.progress.block_download_duration = - GNUNET_TIME_absolute_get_duration (prc->last_transmission); + pi.value.download.specifics.progress.block_download_duration + = GNUNET_TIME_absolute_get_duration (prc->last_transmission); else - pi.value.download.specifics.progress.block_download_duration.rel_value = - GNUNET_TIME_UNIT_FOREVER_REL.rel_value; + pi.value.download.specifics.progress.block_download_duration + = GNUNET_TIME_UNIT_ZERO; /* found locally */ GNUNET_FS_download_make_status_ (&pi, dc); - if (dr->depth == 0) + if (0 == dr->depth) propagate_up (dr); if (dc->completed == dc->length) @@ -1080,7 +1088,7 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, (unsigned long long) GNUNET_ntohll (dc->uri->data. chk.file_length)); /* truncate file to size (since we store IBlocks at the end) */ - if (dc->filename != NULL) + if (NULL != dc->filename) { if (0 != truncate (dc->filename, @@ -1088,10 +1096,10 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "truncate", dc->filename); } - GNUNET_assert (dr->depth == 0); + GNUNET_assert (0 == dr->depth); check_completed (dc); } - if (dr->depth == 0) + if (0 == dr->depth) { /* bottom of the tree, no child downloads possible, just sync */ GNUNET_FS_download_sync_ (dc); @@ -1103,15 +1111,24 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, dr->depth, (unsigned long long) dr->offset); GNUNET_assert (0 == (prc->size % sizeof (struct ContentHashKey))); chkarr = (struct ContentHashKey *) pt; - for (i = (prc->size / sizeof (struct ContentHashKey)) - 1; i >= 0; i--) + for (i = dr->num_children - 1; i >= 0; i--) { drc = dr->children[i]; switch (drc->state) { case BRS_INIT: - drc->chk = chkarr[i]; + if ((drc->chk_idx + 1) * sizeof (struct ContentHashKey) > prc->size) + { + /* 'chkarr' does not have enough space for this chk_idx; + internal error! */ + GNUNET_break (0); + dc->emsg = GNUNET_strdup (_("internal error decoding tree")); + goto signal_error; + } + drc->chk = chkarr[drc->chk_idx]; drc->state = BRS_CHK_SET; - schedule_block_download (dc, drc); + if (GNUNET_YES == dc->issue_requests) + schedule_block_download (dc, drc); break; case BRS_RECONSTRUCT_DOWN: GNUNET_assert (0); @@ -1143,7 +1160,7 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, return GNUNET_YES; signal_error: - if (fh != NULL) + if (NULL != fh) GNUNET_DISK_file_close (fh); pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR; pi.value.download.specifics.error.message = dc->emsg; @@ -1154,7 +1171,7 @@ signal_error: GNUNET_CLIENT_notify_transmit_ready_cancel (dc->th); dc->th = NULL; } - GNUNET_CLIENT_disconnect (dc->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (dc->client); dc->in_receive = GNUNET_NO; dc->client = NULL; GNUNET_FS_free_download_request_ (dc->top_request); @@ -1218,7 +1235,7 @@ receive_results (void *cls, const struct GNUNET_MessageHeader *msg) if ((NULL == msg) || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_FS_PUT) || (sizeof (struct ClientPutMessage) > ntohs (msg->size))) { - GNUNET_break (msg == NULL); + GNUNET_break (NULL == msg); try_reconnect (dc); return; } @@ -1227,7 +1244,7 @@ receive_results (void *cls, const struct GNUNET_MessageHeader *msg) process_result (dc, ntohl (cm->type), GNUNET_TIME_absolute_ntoh (cm->last_transmission), &cm[1], msize - sizeof (struct ClientPutMessage)); - if (dc->client == NULL) + if (NULL == dc->client) return; /* fatal error */ /* continue receiving */ GNUNET_CLIENT_receive (dc->client, &receive_results, dc, @@ -1235,7 +1252,6 @@ receive_results (void *cls, const struct GNUNET_MessageHeader *msg) } - /** * We're ready to transmit a search request to the * file-sharing service. Do it. If there is @@ -1279,7 +1295,7 @@ transmit_download_request (void *cls, size_t size, void *buf) sm->options = htonl (GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY); else sm->options = htonl (GNUNET_FS_SEARCH_OPTION_NONE); - if (dr->depth == 0) + if (0 == dr->depth) sm->type = htonl (GNUNET_BLOCK_TYPE_FS_DBLOCK); else sm->type = htonl (GNUNET_BLOCK_TYPE_FS_IBLOCK); @@ -1291,7 +1307,7 @@ transmit_download_request (void *cls, size_t size, void *buf) msize += sizeof (struct SearchMessage); sm++; } - if (dc->pending_head != NULL) + if (NULL != dc->pending_head) { dc->th = GNUNET_CLIENT_notify_transmit_ready (dc->client, @@ -1299,7 +1315,7 @@ transmit_download_request (void *cls, size_t size, void *buf) GNUNET_CONSTANTS_SERVICE_TIMEOUT, GNUNET_NO, &transmit_download_request, dc); - GNUNET_assert (dc->th != NULL); + GNUNET_assert (NULL != dc->th); } if (GNUNET_NO == dc->in_receive) { @@ -1333,7 +1349,7 @@ do_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) return; } dc->client = client; - if (dc->pending_head != NULL) + if (NULL != dc->pending_head) { dc->th = GNUNET_CLIENT_notify_transmit_ready (client, @@ -1341,7 +1357,7 @@ do_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_CONSTANTS_SERVICE_TIMEOUT, GNUNET_NO, &transmit_download_request, dc); - GNUNET_assert (dc->th != NULL); + GNUNET_assert (NULL != dc->th); } } @@ -1392,7 +1408,7 @@ try_reconnect (struct GNUNET_FS_DownloadContext *dc) dc->pending_head = NULL; dc->pending_tail = NULL; GNUNET_CONTAINER_multihashmap_iterate (dc->active, &retry_entry, dc); - GNUNET_CLIENT_disconnect (dc->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (dc->client); dc->in_receive = GNUNET_NO; dc->client = NULL; } @@ -1417,8 +1433,8 @@ activate_fs_download (void *cls, struct GNUNET_CLIENT_Connection *client) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download activated\n"); GNUNET_assert (NULL != client); - GNUNET_assert (dc->client == NULL); - GNUNET_assert (dc->th == NULL); + GNUNET_assert (NULL == dc->client); + GNUNET_assert (NULL == dc->th); dc->client = client; pi.status = GNUNET_FS_STATUS_DOWNLOAD_ACTIVE; GNUNET_FS_download_make_status_ (&pi, dc); @@ -1427,7 +1443,7 @@ activate_fs_download (void *cls, struct GNUNET_CLIENT_Connection *client) GNUNET_CONTAINER_multihashmap_iterate (dc->active, &retry_entry, dc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking for transmission to FS service\n"); - if (dc->pending_head != NULL) + if (NULL != dc->pending_head) { dc->th = GNUNET_CLIENT_notify_transmit_ready (dc->client, @@ -1435,7 +1451,7 @@ activate_fs_download (void *cls, struct GNUNET_CLIENT_Connection *client) GNUNET_CONSTANTS_SERVICE_TIMEOUT, GNUNET_NO, &transmit_download_request, dc); - GNUNET_assert (dc->th != NULL); + GNUNET_assert (NULL != dc->th); } } @@ -1459,7 +1475,7 @@ deactivate_fs_download (void *cls) } if (NULL != dc->client) { - GNUNET_CLIENT_disconnect (dc->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (dc->client); dc->in_receive = GNUNET_NO; dc->client = NULL; } @@ -1474,6 +1490,7 @@ deactivate_fs_download (void *cls) * (recursively) Create a download request structure. * * @param parent parent of the current entry + * @param chk_idx index of the chk for this block in the parent block * @param depth depth of the current entry, 0 are the DBLOCKs, * top level block is 'dc->treedepth - 1' * @param dr_offset offset in the original file this block maps to @@ -1489,7 +1506,9 @@ deactivate_fs_download (void *cls) * the specified depth */ static struct DownloadRequest * -create_download_request (struct DownloadRequest *parent, unsigned int depth, +create_download_request (struct DownloadRequest *parent, + unsigned int chk_idx, + unsigned int depth, uint64_t dr_offset, uint64_t file_start_offset, uint64_t desired_length) { @@ -1502,40 +1521,45 @@ create_download_request (struct DownloadRequest *parent, unsigned int depth, dr->parent = parent; dr->depth = depth; dr->offset = dr_offset; - if (depth > 0) - { - child_block_size = GNUNET_FS_tree_compute_tree_size (depth - 1); - - /* calculate how many blocks at this level are not interesting - * from the start (rounded down), either because of the requested - * file offset or because this IBlock is further along */ - if (dr_offset < file_start_offset) - head_skip = file_start_offset / child_block_size; - else - head_skip = dr_offset / child_block_size; - - /* calculate index of last block at this level that is interesting (rounded up) */ - dr->num_children = file_start_offset + desired_length / child_block_size; - if (dr->num_children * child_block_size < - file_start_offset + desired_length) - dr->num_children++; /* round up */ - - /* now we can get the total number of children for this block */ - dr->num_children -= head_skip; - if (dr->num_children > CHK_PER_INODE) - dr->num_children = CHK_PER_INODE; /* cap at max */ - - /* why else would we have gotten here to begin with? (that'd be a bad logic error) */ - GNUNET_assert (dr->num_children > 0); - - dr->children = - GNUNET_malloc (dr->num_children * sizeof (struct DownloadRequest *)); - for (i = 0; i < dr->num_children; i++) - dr->children[i] = - create_download_request (dr, depth - 1, - dr_offset + i * child_block_size, - file_start_offset, desired_length); - } + dr->chk_idx = chk_idx; + if (0 == depth) + return dr; + child_block_size = GNUNET_FS_tree_compute_tree_size (depth - 1); + + /* calculate how many blocks at this level are not interesting + * from the start (rounded down), either because of the requested + * file offset or because this IBlock is further along */ + if (dr_offset < file_start_offset) + head_skip = file_start_offset / child_block_size; + else + head_skip = 0; + + /* calculate index of last block at this level that is interesting (rounded up) */ + dr->num_children = (file_start_offset + desired_length - dr_offset) / child_block_size; + if (dr->num_children * child_block_size < + file_start_offset + desired_length - dr_offset) + dr->num_children++; /* round up */ + dr->num_children -= head_skip; + if (dr->num_children > CHK_PER_INODE) + dr->num_children = CHK_PER_INODE; /* cap at max */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Block at offset %llu and depth %u has %u children\n", + (unsigned long long) dr_offset, + depth, + dr->num_children); + + /* now we can get the total number of *interesting* children for this block */ + + /* why else would we have gotten here to begin with? (that'd be a bad logic error) */ + GNUNET_assert (dr->num_children > 0); + + dr->children = + GNUNET_malloc (dr->num_children * sizeof (struct DownloadRequest *)); + for (i = 0; i < dr->num_children; i++) + dr->children[i] = + create_download_request (dr, i + head_skip, depth - 1, + dr_offset + (i + head_skip) * child_block_size, + file_start_offset, desired_length); return dr; } @@ -1552,23 +1576,21 @@ reconstruct_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_DownloadContext *dc = cls; - /* clean up state from tree encoder */ - if (dc->te != NULL) - { - GNUNET_FS_tree_encoder_finish (dc->te, NULL, NULL); - dc->te = NULL; - } + /* clean up state from tree encoder */ if (dc->task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (dc->task); dc->task = GNUNET_SCHEDULER_NO_TASK; } - if (dc->rfh != NULL) + if (NULL != dc->rfh) { GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (dc->rfh)); dc->rfh = NULL; } /* start "normal" download */ + dc->issue_requests = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting normal download\n"); schedule_block_download (dc, dc->top_request); } @@ -1589,7 +1611,6 @@ get_next_block (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } - /** * Function called asking for the current (encoded) * block to be processed. After processing the @@ -1622,11 +1643,34 @@ reconstruct_cb (void *cls, const struct ContentHashKey *chk, uint64_t offset, dr = dc->top_request; while (dr->depth > depth) { - blen = GNUNET_FS_tree_compute_tree_size (dr->depth); + GNUNET_assert (dr->num_children > 0); + blen = GNUNET_FS_tree_compute_tree_size (dr->depth - 1); chld = (offset - dr->offset) / blen; - GNUNET_assert (chld < dr->num_children); - dr = dr->children[chld]; + if (chld < dr->children[0]->chk_idx) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Block %u < %u irrelevant for our range\n", + chld, + dr->children[0]->chk_idx); + dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); + return; /* irrelevant block */ + } + if (chld > dr->children[dr->num_children-1]->chk_idx) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Block %u > %u irrelevant for our range\n", + chld, + dr->children[dr->num_children-1]->chk_idx); + dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); + return; /* irrelevant block */ + } + dr = dr->children[chld - dr->children[0]->chk_idx]; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Matched TE block with request at offset %llu and depth %u in state %d\n", + (unsigned long long) dr->offset, + dr->depth, + dr->state); /* FIXME: this code needs more testing and might need to handle more states... */ switch (dr->state) @@ -1642,11 +1686,14 @@ reconstruct_cb (void *cls, const struct ContentHashKey *chk, uint64_t offset, case BRS_CHK_SET: if (0 == memcmp (chk, &dr->chk, sizeof (struct ContentHashKey))) { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Reconstruction succeeded, can use block at offset %llu, depth %u\n", + (unsigned long long) offset, + depth); /* block matches, hence tree below matches; * this request is done! */ dr->state = BRS_DOWNLOAD_UP; - GNUNET_break (GNUNET_NO == - GNUNET_CONTAINER_multihashmap_remove (dc->active, &dr->chk.query, dr)); + (void) GNUNET_CONTAINER_multihashmap_remove (dc->active, &dr->chk.query, dr); if (GNUNET_YES == dr->is_pending) { GNUNET_break (0); /* how did we get here? */ @@ -1666,6 +1713,7 @@ reconstruct_cb (void *cls, const struct ContentHashKey *chk, uint64_t offset, pi.value.download.specifics.progress.data_len = 0; pi.value.download.specifics.progress.depth = 0; pi.value.download.specifics.progress.trust_offered = 0; + pi.value.download.specifics.progress.block_download_duration = GNUNET_TIME_UNIT_ZERO; GNUNET_FS_download_make_status_ (&pi, dc); /* FIXME: duplicated code from 'process_result_with_request - refactor */ if (dc->completed == dc->length) @@ -1676,7 +1724,7 @@ reconstruct_cb (void *cls, const struct ContentHashKey *chk, uint64_t offset, (unsigned long long) GNUNET_ntohll (dc->uri->data. chk.file_length)); /* truncate file to size (since we store IBlocks at the end) */ - if (dc->filename != NULL) + if (NULL != dc->filename) { if (0 != truncate (dc->filename, @@ -1686,6 +1734,11 @@ reconstruct_cb (void *cls, const struct ContentHashKey *chk, uint64_t offset, } } } + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Reconstruction failed, need to download block at offset %llu, depth %u\n", + (unsigned long long) offset, + depth); break; case BRS_DOWNLOAD_DOWN: break; @@ -1697,12 +1750,9 @@ reconstruct_cb (void *cls, const struct ContentHashKey *chk, uint64_t offset, GNUNET_assert (0); break; } + dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); if ((dr == dc->top_request) && (dr->state == BRS_DOWNLOAD_UP)) - { check_completed (dc); - return; - } - dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); } @@ -1725,16 +1775,19 @@ fh_reader (void *cls, uint64_t offset, size_t max, void *buf, char **emsg) struct GNUNET_DISK_FileHandle *fh = dc->rfh; ssize_t ret; - *emsg = NULL; + if (NULL != emsg) + *emsg = NULL; if (offset != GNUNET_DISK_file_seek (fh, offset, GNUNET_DISK_SEEK_SET)) { - *emsg = GNUNET_strdup (strerror (errno)); + if (NULL != emsg) + *emsg = GNUNET_strdup (strerror (errno)); return 0; } ret = GNUNET_DISK_file_read (fh, buf, max); if (ret < 0) { - *emsg = GNUNET_strdup (strerror (errno)); + if (NULL != emsg) + *emsg = GNUNET_strdup (strerror (errno)); return 0; } return ret; @@ -1758,10 +1811,10 @@ GNUNET_FS_download_start_task_ (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start task running...\n"); dc->task = GNUNET_SCHEDULER_NO_TASK; - if (dc->length == 0) + if (0 == dc->length) { /* no bytes required! */ - if (dc->filename != NULL) + if (NULL != dc->filename) { fh = GNUNET_DISK_file_open (dc->filename, GNUNET_DISK_OPEN_READWRITE | @@ -1782,13 +1835,13 @@ GNUNET_FS_download_start_task_ (void *cls, check_completed (dc); return; } - if (dc->emsg != NULL) + if (NULL != dc->emsg) return; - if (dc->top_request == NULL) + if (NULL == dc->top_request) { dc->top_request = - create_download_request (NULL, dc->treedepth - 1, 0, dc->offset, - dc->length); + create_download_request (NULL, 0, dc->treedepth - 1, 0, dc->offset, + dc->length); dc->top_request->state = BRS_CHK_SET; dc->top_request->chk = (dc->uri->type == @@ -1809,7 +1862,7 @@ GNUNET_FS_download_start_task_ (void *cls, GNUNET_DISK_PERM_NONE); if (dc->top_request->state == BRS_CHK_SET) { - if (dc->rfh != NULL) + if (NULL != dc->rfh) { /* first, try top-down */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -1823,7 +1876,7 @@ GNUNET_FS_download_start_task_ (void *cls, break; /* normal, some blocks already down */ case BRS_DOWNLOAD_UP: /* already done entirely, party! */ - if (dc->rfh != NULL) + if (NULL != dc->rfh) { /* avoid hanging on to file handle longer than * necessary */ @@ -1854,9 +1907,9 @@ GNUNET_FS_download_start_task_ (void *cls, (unsigned int) GNUNET_CONTAINER_meta_data_get_serialized_size (dc->meta)); GNUNET_CONTAINER_meta_data_iterate (dc->meta, &match_full_data, dc); - if (dc->top_request->state == BRS_DOWNLOAD_UP) + if (BRS_DOWNLOAD_UP == dc->top_request->state) { - if (dc->rfh != NULL) + if (NULL != dc->rfh) { /* avoid hanging on to file handle longer than * necessary */ @@ -1866,23 +1919,26 @@ GNUNET_FS_download_start_task_ (void *cls, return; /* finished, status update was already done for us */ } } - if (dc->rfh != NULL) + if (NULL != dc->rfh) { - /* finally, try bottom-up */ + /* finally, actually run bottom-up */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying bottom-up reconstruction of file `%s'\n", dc->filename); dc->te = - GNUNET_FS_tree_encoder_create (dc->h, dc->old_file_size, dc, &fh_reader, - &reconstruct_cb, NULL, - &reconstruct_cont); + GNUNET_FS_tree_encoder_create (dc->h, + GNUNET_FS_uri_chk_get_file_size (dc->uri), + dc, &fh_reader, + &reconstruct_cb, NULL, + &reconstruct_cont); dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); } else { /* simple, top-level download */ + dc->issue_requests = GNUNET_YES; schedule_block_download (dc, dc->top_request); } - if (dc->top_request->state == BRS_DOWNLOAD_UP) + if (BRS_DOWNLOAD_UP == dc->top_request->state) check_completed (dc); } @@ -1899,42 +1955,42 @@ GNUNET_FS_download_signal_suspend_ (void *cls) struct GNUNET_FS_DownloadContext *dc = cls; struct GNUNET_FS_ProgressInfo pi; - if (dc->top != NULL) + if (NULL != dc->top) GNUNET_FS_end_top (dc->h, dc->top); while (NULL != dc->child_head) GNUNET_FS_download_signal_suspend_ (dc->child_head); - if (dc->search != NULL) + if (NULL != dc->search) { dc->search->download = NULL; dc->search = NULL; } - if (dc->job_queue != NULL) + if (NULL != dc->job_queue) { GNUNET_FS_dequeue_ (dc->job_queue); dc->job_queue = NULL; } - if (dc->parent != NULL) + if (NULL != dc->parent) GNUNET_CONTAINER_DLL_remove (dc->parent->child_head, dc->parent->child_tail, dc); - if (dc->task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != dc->task) { GNUNET_SCHEDULER_cancel (dc->task); dc->task = GNUNET_SCHEDULER_NO_TASK; } pi.status = GNUNET_FS_STATUS_DOWNLOAD_SUSPEND; GNUNET_FS_download_make_status_ (&pi, dc); - if (dc->te != NULL) + if (NULL != dc->te) { GNUNET_FS_tree_encoder_finish (dc->te, NULL, NULL); dc->te = NULL; } - if (dc->rfh != NULL) + if (NULL != dc->rfh) { GNUNET_DISK_file_close (dc->rfh); dc->rfh = NULL; } GNUNET_FS_free_download_request_ (dc->top_request); - if (dc->active != NULL) + if (NULL != dc->active) { GNUNET_CONTAINER_multihashmap_destroy (dc->active); dc->active = NULL; @@ -1949,16 +2005,7 @@ GNUNET_FS_download_signal_suspend_ (void *cls) /** - * Download parts of a file. Note that this will store - * the blocks at the respective offset in the given file. Also, the - * download is still using the blocking of the underlying FS - * encoding. As a result, the download may *write* outside of the - * given boundaries (if offset and length do not match the 32k FS - * block boundaries). <p> - * - * This function should be used to focus a download towards a - * particular portion of the file (optimization), not to strictly - * limit the download to exactly those bytes. + * Helper function to setup the download context. * * @param h handle to the file sharing subsystem * @param uri the URI of the file (determines what to download); CHK or LOC URI @@ -1974,38 +2021,27 @@ GNUNET_FS_download_signal_suspend_ (void *cls) * @param anonymity anonymity level to use for the download * @param options various options * @param cctx initial value for the client context for this download - * @param parent parent download to associate this download with (use NULL - * for top-level downloads; useful for manually-triggered recursive downloads) * @return context that can be used to control this download */ struct GNUNET_FS_DownloadContext * -GNUNET_FS_download_start (struct GNUNET_FS_Handle *h, - const struct GNUNET_FS_Uri *uri, - const struct GNUNET_CONTAINER_MetaData *meta, - const char *filename, const char *tempname, - uint64_t offset, uint64_t length, uint32_t anonymity, - enum GNUNET_FS_DownloadOptions options, void *cctx, - struct GNUNET_FS_DownloadContext *parent) +create_download_context (struct GNUNET_FS_Handle *h, + const struct GNUNET_FS_Uri *uri, + const struct GNUNET_CONTAINER_MetaData *meta, + const char *filename, const char *tempname, + uint64_t offset, uint64_t length, uint32_t anonymity, + enum GNUNET_FS_DownloadOptions options, void *cctx) { struct GNUNET_FS_DownloadContext *dc; GNUNET_assert (GNUNET_FS_uri_test_chk (uri) || GNUNET_FS_uri_test_loc (uri)); - if ((offset + length < offset) || (offset + length > GNUNET_FS_uri_chk_get_file_size (uri))) { GNUNET_break (0); return NULL; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting download `%s' of %llu bytes\n", - filename, (unsigned long long) length); dc = GNUNET_malloc (sizeof (struct GNUNET_FS_DownloadContext)); dc->h = h; - dc->parent = parent; - if (parent != NULL) - { - GNUNET_CONTAINER_DLL_insert (parent->child_head, parent->child_tail, dc); - } dc->uri = GNUNET_FS_uri_dup (uri); dc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); dc->client_info = cctx; @@ -2014,7 +2050,7 @@ GNUNET_FS_download_start (struct GNUNET_FS_Handle *h, { dc->filename = GNUNET_strdup (filename); if (GNUNET_YES == GNUNET_DISK_file_test (filename)) - GNUNET_DISK_file_size (filename, &dc->old_file_size, GNUNET_YES); + GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (filename, &dc->old_file_size, GNUNET_YES, GNUNET_YES)); } if (GNUNET_FS_uri_test_loc (dc->uri)) GNUNET_assert (GNUNET_OK == @@ -2027,22 +2063,74 @@ GNUNET_FS_download_start (struct GNUNET_FS_Handle *h, GNUNET_CONTAINER_multihashmap_create (1 + 2 * (length / DBLOCK_SIZE)); dc->treedepth = GNUNET_FS_compute_depth (GNUNET_FS_uri_chk_get_file_size (dc->uri)); - if ((filename == NULL) && (is_recursive_download (dc))) + if ((NULL == filename) && (is_recursive_download (dc))) { - if (tempname != NULL) + if (NULL != tempname) dc->temp_filename = GNUNET_strdup (tempname); else dc->temp_filename = GNUNET_DISK_mktemp ("gnunet-directory-download-tmp"); } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download tree has depth %u\n", + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting download `%s' of %llu bytes with tree depth %u\n", + filename, + (unsigned long long) length, dc->treedepth); - if (parent == NULL) - { + dc->task = GNUNET_SCHEDULER_add_now (&GNUNET_FS_download_start_task_, dc); + return dc; +} + + +/** + * Download parts of a file. Note that this will store + * the blocks at the respective offset in the given file. Also, the + * download is still using the blocking of the underlying FS + * encoding. As a result, the download may *write* outside of the + * given boundaries (if offset and length do not match the 32k FS + * block boundaries). <p> + * + * This function should be used to focus a download towards a + * particular portion of the file (optimization), not to strictly + * limit the download to exactly those bytes. + * + * @param h handle to the file sharing subsystem + * @param uri the URI of the file (determines what to download); CHK or LOC URI + * @param meta known metadata for the file (can be NULL) + * @param filename where to store the file, maybe NULL (then no file is + * created on disk and data must be grabbed from the callbacks) + * @param tempname where to store temporary file data, not used if filename is non-NULL; + * can be NULL (in which case we will pick a name if needed); the temporary file + * may already exist, in which case we will try to use the data that is there and + * if it is not what is desired, will overwrite it + * @param offset at what offset should we start the download (typically 0) + * @param length how many bytes should be downloaded starting at offset + * @param anonymity anonymity level to use for the download + * @param options various options + * @param cctx initial value for the client context for this download + * @param parent parent download to associate this download with (use NULL + * for top-level downloads; useful for manually-triggered recursive downloads) + * @return context that can be used to control this download + */ +struct GNUNET_FS_DownloadContext * +GNUNET_FS_download_start (struct GNUNET_FS_Handle *h, + const struct GNUNET_FS_Uri *uri, + const struct GNUNET_CONTAINER_MetaData *meta, + const char *filename, const char *tempname, + uint64_t offset, uint64_t length, uint32_t anonymity, + enum GNUNET_FS_DownloadOptions options, void *cctx, + struct GNUNET_FS_DownloadContext *parent) +{ + struct GNUNET_FS_DownloadContext *dc; + + dc = create_download_context (h, uri, meta, filename, tempname, + offset, length, anonymity, options, cctx); + if (NULL == dc) + return NULL; + dc->parent = parent; + if (NULL != parent) + GNUNET_CONTAINER_DLL_insert (parent->child_head, parent->child_tail, dc); + else dc->top = GNUNET_FS_make_top (dc->h, &GNUNET_FS_download_signal_suspend_, dc); - } - dc->task = GNUNET_SCHEDULER_add_now (&GNUNET_FS_download_start_task_, dc); return dc; } @@ -2092,62 +2180,22 @@ GNUNET_FS_download_start_from_search (struct GNUNET_FS_Handle *h, { struct GNUNET_FS_DownloadContext *dc; - if ((sr == NULL) || (sr->download != NULL)) + if ((NULL == sr) || (NULL != sr->download)) { GNUNET_break (0); return NULL; } - GNUNET_assert (GNUNET_FS_uri_test_chk (sr->uri) || - GNUNET_FS_uri_test_loc (sr->uri)); - if ((offset + length < offset) || - (offset + length > sr->uri->data.chk.file_length)) - { - GNUNET_break (0); + dc = create_download_context (h, sr->uri, sr->meta, filename, tempname, + offset, length, anonymity, options, cctx); + if (NULL == dc) return NULL; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting download `%s' of %llu bytes\n", - filename, (unsigned long long) length); - dc = GNUNET_malloc (sizeof (struct GNUNET_FS_DownloadContext)); - dc->h = h; dc->search = sr; sr->download = dc; - if (sr->probe_ctx != NULL) + if (NULL != sr->probe_ctx) { GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); sr->probe_ctx = NULL; } - dc->uri = GNUNET_FS_uri_dup (sr->uri); - dc->meta = GNUNET_CONTAINER_meta_data_duplicate (sr->meta); - dc->client_info = cctx; - dc->start_time = GNUNET_TIME_absolute_get (); - if (NULL != filename) - { - dc->filename = GNUNET_strdup (filename); - if (GNUNET_YES == GNUNET_DISK_file_test (filename)) - GNUNET_DISK_file_size (filename, &dc->old_file_size, GNUNET_YES); - } - if (GNUNET_FS_uri_test_loc (dc->uri)) - GNUNET_assert (GNUNET_OK == - GNUNET_FS_uri_loc_get_peer_identity (dc->uri, &dc->target)); - dc->offset = offset; - dc->length = length; - dc->anonymity = anonymity; - dc->options = options; - dc->active = - GNUNET_CONTAINER_multihashmap_create (1 + 2 * (length / DBLOCK_SIZE)); - dc->treedepth = - GNUNET_FS_compute_depth (GNUNET_ntohll (dc->uri->data.chk.file_length)); - if ((filename == NULL) && (is_recursive_download (dc))) - { - if (tempname != NULL) - dc->temp_filename = GNUNET_strdup (tempname); - else - dc->temp_filename = GNUNET_DISK_mktemp ("gnunet-directory-download-tmp"); - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download tree has depth %u\n", - dc->treedepth); - dc->task = GNUNET_SCHEDULER_add_now (&GNUNET_FS_download_start_task_, dc); return dc; } @@ -2162,10 +2210,13 @@ GNUNET_FS_download_start_downloading_ (struct GNUNET_FS_DownloadContext *dc) { if (dc->completed == dc->length) return; - GNUNET_assert (dc->job_queue == NULL); + GNUNET_assert (NULL == dc->job_queue); dc->job_queue = GNUNET_FS_queue_ (dc->h, &activate_fs_download, &deactivate_fs_download, - dc, (dc->length + DBLOCK_SIZE - 1) / DBLOCK_SIZE); + dc, (dc->length + DBLOCK_SIZE - 1) / DBLOCK_SIZE, + (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE)) + ? GNUNET_FS_QUEUE_PRIORITY_NORMAL + : GNUNET_FS_QUEUE_PRIORITY_PROBE); } @@ -2180,28 +2231,28 @@ GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc, int do_delete) { struct GNUNET_FS_ProgressInfo pi; int have_children; + int search_was_null; - if (dc->top != NULL) + if (NULL != dc->top) GNUNET_FS_end_top (dc->h, dc->top); - - - if (dc->task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != dc->task) { GNUNET_SCHEDULER_cancel (dc->task); dc->task = GNUNET_SCHEDULER_NO_TASK; } - if (dc->search != NULL) + search_was_null = (NULL == dc->search); + if (NULL != dc->search) { dc->search->download = NULL; GNUNET_FS_search_result_sync_ (dc->search); dc->search = NULL; } - if (dc->job_queue != NULL) + if (NULL != dc->job_queue) { GNUNET_FS_dequeue_ (dc->job_queue); dc->job_queue = NULL; } - if (dc->te != NULL) + if (NULL != dc->te) { GNUNET_FS_tree_encoder_finish (dc->te, NULL, NULL); dc->te = NULL; @@ -2209,32 +2260,30 @@ GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc, int do_delete) have_children = (NULL != dc->child_head) ? GNUNET_YES : GNUNET_NO; while (NULL != dc->child_head) GNUNET_FS_download_stop (dc->child_head, do_delete); - if (dc->parent != NULL) + if (NULL != dc->parent) GNUNET_CONTAINER_DLL_remove (dc->parent->child_head, dc->parent->child_tail, dc); - if (dc->serialization != NULL) + if (NULL != dc->serialization) GNUNET_FS_remove_sync_file_ (dc->h, - ((dc->parent != NULL) || - (dc->search != - NULL)) ? GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD : + ((NULL != dc->parent) || + (! search_was_null)) ? GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD : GNUNET_FS_SYNC_PATH_MASTER_DOWNLOAD, dc->serialization); - if ((GNUNET_YES == have_children) && (dc->parent == NULL)) + if ((GNUNET_YES == have_children) && (NULL == dc->parent)) GNUNET_FS_remove_sync_dir_ (dc->h, - (dc->search != - NULL) ? GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD : + (! search_was_null) ? GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD : GNUNET_FS_SYNC_PATH_MASTER_DOWNLOAD, dc->serialization); pi.status = GNUNET_FS_STATUS_DOWNLOAD_STOPPED; GNUNET_FS_download_make_status_ (&pi, dc); GNUNET_FS_free_download_request_ (dc->top_request); dc->top_request = NULL; - if (dc->active != NULL) + if (NULL != dc->active) { GNUNET_CONTAINER_multihashmap_destroy (dc->active); dc->active = NULL; } - if (dc->filename != NULL) + if (NULL != dc->filename) { if ((dc->completed != dc->length) && (GNUNET_YES == do_delete)) { diff --git a/src/fs/fs_file_information.c b/src/fs/fs_file_information.c index 85a076f..8065927 100644 --- a/src/fs/fs_file_information.c +++ b/src/fs/fs_file_information.c @@ -107,7 +107,7 @@ GNUNET_FS_file_information_create_from_file (struct GNUNET_FS_Handle *h, *bo) { struct FileInfo *fi; - struct stat sbuf; + uint64_t fsize; struct GNUNET_FS_FileInformation *ret; const char *fn; const char *ss; @@ -116,7 +116,8 @@ GNUNET_FS_file_information_create_from_file (struct GNUNET_FS_Handle *h, char fn_conv[MAX_PATH]; #endif - if (0 != STAT (filename, &sbuf)) + /* FIXME: should includeSymLinks be GNUNET_NO or GNUNET_YES here? */ + if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fsize, GNUNET_NO, GNUNET_YES)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "stat", filename); return NULL; @@ -129,7 +130,7 @@ GNUNET_FS_file_information_create_from_file (struct GNUNET_FS_Handle *h, } ret = GNUNET_FS_file_information_create_from_reader (h, client_info, - sbuf.st_size, + fsize, &GNUNET_FS_data_reader_file_, fi, keywords, meta, do_index, bo); @@ -145,6 +146,9 @@ GNUNET_FS_file_information_create_from_file (struct GNUNET_FS_Handle *h, #endif while (NULL != (ss = strstr (fn, DIR_SEPARATOR_STR))) fn = ss + 1; +/* FIXME: If we assume that on other platforms CRT is UTF-8-aware, then + * this should be changed to EXTRACTOR_METAFORMAT_UTF8 + */ #if !WINDOWS GNUNET_CONTAINER_meta_data_insert (ret->meta, "<gnunet>", EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME, diff --git a/src/fs/fs_list_indexed.c b/src/fs/fs_list_indexed.c index 784c988..ef03dee 100644 --- a/src/fs/fs_list_indexed.c +++ b/src/fs/fs_list_indexed.c @@ -176,7 +176,7 @@ GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h, void GNUNET_FS_get_indexed_files_cancel (struct GNUNET_FS_GetIndexedContext *gic) { - GNUNET_CLIENT_disconnect (gic->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (gic->client); GNUNET_free (gic); } diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c index 1657e29..93c3046 100644 --- a/src/fs/fs_publish.c +++ b/src/fs/fs_publish.c @@ -98,7 +98,7 @@ publish_cleanup (struct GNUNET_FS_PublishContext *pc) } if (pc->client != NULL) { - GNUNET_CLIENT_disconnect (pc->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (pc->client); pc->client = NULL; } GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); @@ -355,6 +355,8 @@ block_reader (void *cls, uint64_t offset, size_t max, void *buf, char **emsg) } else { + if (UINT64_MAX == offset) + return p->data.file.reader (p->data.file.reader_cls, offset, 0, NULL, NULL); pt_size = GNUNET_MIN (max, p->data.file.file_size - offset); if (pt_size == 0) return 0; /* calling reader with pt_size==0 @@ -385,10 +387,10 @@ encode_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) char *emsg; uint64_t flen; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished with tree encoder\n"); p = pc->fi_pos; GNUNET_FS_tree_encoder_finish (p->te, &p->chk_uri, &emsg); p->te = NULL; - GNUNET_FS_file_information_sync_ (p); if (NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error during tree walk: %s\n", emsg); @@ -399,16 +401,19 @@ encode_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) pi.value.publish.specifics.error.message = p->emsg; p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, 0); } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished with tree encoder\n"); + else + { /* final progress event */ - flen = GNUNET_FS_uri_chk_get_file_size (p->chk_uri); - pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS; - pi.value.publish.specifics.progress.data = NULL; - pi.value.publish.specifics.progress.offset = flen; - pi.value.publish.specifics.progress.data_len = 0; - pi.value.publish.specifics.progress.depth = GNUNET_FS_compute_depth (flen); - p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, flen); - + GNUNET_assert (NULL != p->chk_uri); + flen = GNUNET_FS_uri_chk_get_file_size (p->chk_uri); + pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS; + pi.value.publish.specifics.progress.data = NULL; + pi.value.publish.specifics.progress.offset = flen; + pi.value.publish.specifics.progress.data_len = 0; + pi.value.publish.specifics.progress.depth = GNUNET_FS_compute_depth (flen); + p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, flen); + } + GNUNET_FS_file_information_sync_ (p); /* continue with main */ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); pc->upload_task = @@ -606,7 +611,7 @@ process_index_start_response (void *cls, const struct GNUNET_MessageHeader *msg) const char *emsg; uint16_t msize; - GNUNET_CLIENT_disconnect (pc->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (pc->client); pc->client = NULL; p = pc->fi_pos; if (msg == NULL) @@ -942,10 +947,9 @@ fip_signal_start (void *cls, struct GNUNET_FS_FileInformation *fi, pi.status = GNUNET_FS_STATUS_PUBLISH_START; *client_info = GNUNET_FS_publish_make_status_ (&pi, pc, fi, 0); GNUNET_FS_file_information_sync_ (fi); - if (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (meta) - && (fi->dir != NULL)) + if ((fi->is_directory) && (fi->dir != NULL)) { - /* process entries in directory */ + /* We are a directory, and we are not top-level; process entries in directory */ pc->skip_next_fi_callback = GNUNET_YES; GNUNET_FS_file_information_inspect (fi, &fip_signal_start, pc); } diff --git a/src/fs/fs_publish_ksk.c b/src/fs/fs_publish_ksk.c index 5119de4..0b6d407 100644 --- a/src/fs/fs_publish_ksk.c +++ b/src/fs/fs_publish_ksk.c @@ -188,7 +188,7 @@ publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } keyword = pkc->ksk_uri->data.ksk.keywords[pkc->i++]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing under keyword `%s'\n", - keyword); + &keyword[1]); /* first character of keyword indicates if it is * mandatory or not -- ignore for hashing */ GNUNET_CRYPTO_hash (&keyword[1], strlen (&keyword[1]), &key); diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c index a163d97..b280670 100644 --- a/src/fs/fs_search.c +++ b/src/fs/fs_search.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2001-2006, 2008-2011 Christian Grothoff (and other contributing authors) + (C) 2001-2006, 2008-2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -14,10 +14,9 @@ You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Free Software Foundation, Inc., 59 Tem ple Place - Suite 330, Boston, MA 02111-1307, USA. */ - /** * @file fs/fs_search.c * @brief Helper functions for searching. @@ -30,7 +29,6 @@ #include "gnunet_protocols.h" #include "fs_api.h" -#define DEBUG_SEARCH GNUNET_EXTRA_LOGGING /** * Number of availability trials we perform per search result. @@ -54,7 +52,7 @@ GNUNET_FS_search_make_status_ (struct GNUNET_FS_ProgressInfo *pi, pi->value.search.sc = sc; pi->value.search.cctx = sc->client_info; pi->value.search.pctx = - (sc->psearch_result == NULL) ? NULL : sc->psearch_result->client_info; + (NULL == sc->psearch_result) ? NULL : sc->psearch_result->client_info; pi->value.search.query = sc->uri; pi->value.search.duration = GNUNET_TIME_absolute_get_duration (sc->start_time); @@ -121,7 +119,7 @@ notify_client_chk_update (struct GNUNET_FS_SearchContext *sc, struct GNUNET_FS_SearchResult *sr) { struct GNUNET_FS_ProgressInfo pi; - + pi.status = GNUNET_FS_STATUS_SEARCH_UPDATE; pi.value.search.specifics.update.cctx = sr->client_info; pi.value.search.specifics.update.meta = sr->meta; @@ -184,7 +182,7 @@ signal_probe_result (struct GNUNET_FS_SearchResult *sr) { struct GNUNET_FS_ProgressInfo pi; - pi.status = GNUNET_FS_STATUS_SEARCH_START; + pi.status = GNUNET_FS_STATUS_SEARCH_UPDATE; pi.value.search.specifics.update.cctx = sr->client_info; pi.value.search.specifics.update.meta = sr->meta; pi.value.search.specifics.update.uri = sr->uri; @@ -192,7 +190,7 @@ signal_probe_result (struct GNUNET_FS_SearchResult *sr) pi.value.search.specifics.update.availability_certainty = sr->availability_trials; pi.value.search.specifics.update.applicability_rank = sr->optional_support; - sr->sc->client_info = GNUNET_FS_search_make_status_ (&pi, sr->sc); + sr->client_info = GNUNET_FS_search_make_status_ (&pi, sr->sc); GNUNET_FS_search_start_probe_ (sr); } @@ -208,7 +206,10 @@ probe_failure_handler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_SearchResult *sr = cls; + sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; sr->availability_trials++; + GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); + sr->probe_ctx = NULL; GNUNET_FS_search_result_sync_ (sr); signal_probe_result (sr); } @@ -225,8 +226,11 @@ probe_success_handler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_SearchResult *sr = cls; + sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; sr->availability_trials++; sr->availability_success++; + GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); + sr->probe_ctx = NULL; GNUNET_FS_search_result_sync_ (sr); signal_probe_result (sr); } @@ -271,7 +275,7 @@ GNUNET_FS_search_probe_progress_ (void *cls, /* ignore */ break; case GNUNET_FS_STATUS_DOWNLOAD_ERROR: - if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; @@ -281,17 +285,16 @@ GNUNET_FS_search_probe_progress_ (void *cls, &probe_failure_handler, sr); break; case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED: - if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; } sr->probe_cancel_task = - GNUNET_SCHEDULER_add_delayed (sr->remaining_probe_time, - &probe_success_handler, sr); + GNUNET_SCHEDULER_add_now (&probe_success_handler, sr); break; case GNUNET_FS_STATUS_DOWNLOAD_STOPPED: - if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; @@ -299,14 +302,14 @@ GNUNET_FS_search_probe_progress_ (void *cls, sr = NULL; break; case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: - GNUNET_assert (sr->probe_cancel_task == GNUNET_SCHEDULER_NO_TASK); + GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sr->probe_cancel_task); sr->probe_active_time = GNUNET_TIME_absolute_get (); sr->probe_cancel_task = GNUNET_SCHEDULER_add_delayed (sr->remaining_probe_time, &probe_failure_handler, sr); break; case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: - if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; @@ -335,16 +338,18 @@ GNUNET_FS_search_start_probe_ (struct GNUNET_FS_SearchResult *sr) uint64_t off; uint64_t len; - if (sr->probe_ctx != NULL) + if (NULL != sr->probe_ctx) return; - if (sr->download != NULL) + if (NULL != sr->download) return; if (0 == (sr->sc->h->flags & GNUNET_FS_FLAGS_DO_PROBES)) return; if (sr->availability_trials > AVAILABILITY_TRIALS_MAX) return; + if ( (chk != sr->uri->type) && (loc != sr->uri->type)) + return; len = GNUNET_FS_uri_chk_get_file_size (sr->uri); - if (len == 0) + if (0 == len) return; if ((len <= DBLOCK_SIZE) && (sr->availability_success > 0)) return; @@ -497,7 +502,7 @@ process_sks_result (struct GNUNET_FS_SearchContext *sc, const char *id_update, /* notify client */ notify_client_chk_result (sc, sr); /* search for updates */ - if (strlen (id_update) == 0) + if (0 == strlen (id_update)) return; /* no updates */ uu.type = sks; uu.data.sks.namespace = sc->uri->data.sks.namespace; @@ -508,28 +513,32 @@ process_sks_result (struct GNUNET_FS_SearchContext *sc, const char *id_update, /** - * Process a keyword-search result. + * Decrypt a block using a 'keyword' as the passphrase. Given the + * KSK public key derived from the keyword, this function looks up + * the original keyword in the search context and decrypts the + * given ciphertext block. * - * @param sc our search context - * @param kb the kblock - * @param size size of kb + * @param sc search context with the keywords + * @param public_key public key to use to lookup the keyword + * @param edata encrypted data + * @param edata_size number of bytes in 'edata' (and 'data') + * @param data where to store the plaintext + * @return keyword index on success, GNUNET_SYSERR on error (no such + * keyword, internal error) */ -static void -process_kblock (struct GNUNET_FS_SearchContext *sc, const struct KBlock *kb, - size_t size) -{ - unsigned int i; - size_t j; +static int +decrypt_block_with_keyword (const struct GNUNET_FS_SearchContext *sc, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key, + const void *edata, + size_t edata_size, + char *data) +{ GNUNET_HashCode q; - char pt[size - sizeof (struct KBlock)]; struct GNUNET_CRYPTO_AesSessionKey skey; struct GNUNET_CRYPTO_AesInitializationVector iv; - const char *eos; - struct GNUNET_CONTAINER_MetaData *meta; - struct GNUNET_FS_Uri *uri; - char *emsg; + int i; - GNUNET_CRYPTO_hash (&kb->keyspace, + GNUNET_CRYPTO_hash (public_key, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &q); /* find key */ @@ -540,17 +549,46 @@ process_kblock (struct GNUNET_FS_SearchContext *sc, const struct KBlock *kb, { /* oops, does not match any of our keywords!? */ GNUNET_break (0); - return; + return GNUNET_SYSERR; } /* decrypt */ GNUNET_CRYPTO_hash_to_aes_key (&sc->requests[i].key, &skey, &iv); if (-1 == - GNUNET_CRYPTO_aes_decrypt (&kb[1], size - sizeof (struct KBlock), &skey, - &iv, pt)) + GNUNET_CRYPTO_aes_decrypt (edata, edata_size, &skey, + &iv, data)) { GNUNET_break (0); - return; + return GNUNET_SYSERR; } + return i; +} + + +/** + * Process a keyword-search result. + * + * @param sc our search context + * @param kb the kblock + * @param size size of kb + */ +static void +process_kblock (struct GNUNET_FS_SearchContext *sc, const struct KBlock *kb, + size_t size) +{ + size_t j; + char pt[size - sizeof (struct KBlock)]; + const char *eos; + struct GNUNET_CONTAINER_MetaData *meta; + struct GNUNET_FS_Uri *uri; + char *emsg; + int i; + + if (-1 == (i = decrypt_block_with_keyword (sc, + &kb->keyspace, + &kb[1], + size - sizeof (struct KBlock), + pt))) + return; /* parse */ eos = memchr (pt, 0, sizeof (pt)); if (NULL == eos) @@ -563,13 +601,13 @@ process_kblock (struct GNUNET_FS_SearchContext *sc, const struct KBlock *kb, meta = GNUNET_CONTAINER_meta_data_create (); else meta = GNUNET_CONTAINER_meta_data_deserialize (&pt[j], sizeof (pt) - j); - if (meta == NULL) + if (NULL == meta) { GNUNET_break_op (0); /* kblock malformed */ return; } uri = GNUNET_FS_uri_parse (pt, &emsg); - if (uri == NULL) + if (NULL == uri) { GNUNET_break_op (0); /* kblock malformed */ GNUNET_free_non_null (emsg); @@ -596,39 +634,20 @@ static void process_nblock (struct GNUNET_FS_SearchContext *sc, const struct NBlock *nb, size_t size) { - unsigned int i; size_t j; - GNUNET_HashCode q; char pt[size - sizeof (struct NBlock)]; - struct GNUNET_CRYPTO_AesSessionKey skey; - struct GNUNET_CRYPTO_AesInitializationVector iv; const char *eos; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *uri; char *uris; + int i; - GNUNET_CRYPTO_hash (&nb->keyspace, - sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &q); - /* find key */ - for (i = 0; i < sc->uri->data.ksk.keywordCount; i++) - if (0 == memcmp (&q, &sc->requests[i].query, sizeof (GNUNET_HashCode))) - break; - if (i == sc->uri->data.ksk.keywordCount) - { - /* oops, does not match any of our keywords!? */ - GNUNET_break (0); - return; - } - /* decrypt */ - GNUNET_CRYPTO_hash_to_aes_key (&sc->requests[i].key, &skey, &iv); - if (-1 == - GNUNET_CRYPTO_aes_decrypt (&nb[1], size - sizeof (struct NBlock), &skey, - &iv, pt)) - { - GNUNET_break (0); + if (-1 == (i = decrypt_block_with_keyword (sc, + &nb->keyspace, + &nb[1], + size - sizeof (struct NBlock), + pt))) return; - } /* parse */ eos = memchr (pt, 0, sizeof (pt)); if (NULL == eos) @@ -641,7 +660,7 @@ process_nblock (struct GNUNET_FS_SearchContext *sc, const struct NBlock *nb, meta = GNUNET_CONTAINER_meta_data_create (); else meta = GNUNET_CONTAINER_meta_data_deserialize (&pt[j], sizeof (pt) - j); - if (meta == NULL) + if (NULL == meta) { GNUNET_break_op (0); /* nblock malformed */ return; @@ -703,7 +722,7 @@ process_sblock (struct GNUNET_FS_SearchContext *sc, const struct SBlock *sb, } /* parse */ off = GNUNET_STRINGS_buffer_tokenize (pt, len, 2, &id, &uris); - if (off == 0) + if (0 == off) { GNUNET_break_op (0); /* sblock malformed */ return; @@ -715,7 +734,7 @@ process_sblock (struct GNUNET_FS_SearchContext *sc, const struct SBlock *sb, return; } uri = GNUNET_FS_uri_parse (uris, &emsg); - if (uri == NULL) + if (NULL == uri) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to parse URI `%s': %s\n", uris, emsg); @@ -914,7 +933,7 @@ build_result_set (void *cls, const GNUNET_HashCode * key, void *value) struct MessageBuilderContext *mbc = cls; struct GNUNET_FS_SearchResult *sr = value; - if ( (sr->keyword_bitmap != NULL) && + if ( (NULL != sr->keyword_bitmap) && (0 == (sr->keyword_bitmap[mbc->keyword_offset / 8] & (1 << (mbc->keyword_offset % 8)))) ) return GNUNET_OK; /* have no match for this keyword yet */ if (mbc->skip_cnt > 0) @@ -922,7 +941,7 @@ build_result_set (void *cls, const GNUNET_HashCode * key, void *value) mbc->skip_cnt--; return GNUNET_OK; } - if (mbc->put_cnt == 0) + if (0 == mbc->put_cnt) return GNUNET_SYSERR; mbc->sc->search_request_map_offset++; mbc->xoff[--mbc->put_cnt] = *key; @@ -946,7 +965,7 @@ find_result_set (void *cls, const GNUNET_HashCode * key, void *value) struct MessageBuilderContext *mbc = cls; struct GNUNET_FS_SearchResult *sr = value; - if ( (sr->keyword_bitmap != NULL) && + if ( (NULL != sr->keyword_bitmap) && (0 == (sr->keyword_bitmap[mbc->keyword_offset / 8] & (1 << (mbc->keyword_offset % 8)))) ) return GNUNET_OK; /* have no match for this keyword yet */ mbc->put_cnt++; @@ -1133,7 +1152,7 @@ try_reconnect (struct GNUNET_FS_SearchContext *sc) { if (NULL != sc->client) { - GNUNET_CLIENT_disconnect (sc->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (sc->client); sc->client = NULL; } sc->task = @@ -1168,7 +1187,7 @@ search_start (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *uri, sc->uri = GNUNET_FS_uri_dup (uri); sc->anonymity = anonymity; sc->start_time = GNUNET_TIME_absolute_get (); - if (psearch != NULL) + if (NULL != psearch) { sc->psearch_result = psearch; psearch->update_search = sc; @@ -1217,7 +1236,7 @@ GNUNET_FS_search_start_searching_ (struct GNUNET_FS_SearchContext *sc) keyword = &sc->uri->data.ksk.keywords[i][1]; GNUNET_CRYPTO_hash (keyword, strlen (keyword), &hc); pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&hc); - GNUNET_assert (pk != NULL); + GNUNET_assert (NULL != pk); GNUNET_CRYPTO_rsa_key_get_public (pk, &pub); GNUNET_CRYPTO_rsa_key_free (pk); GNUNET_CRYPTO_hash (&pub, @@ -1253,17 +1272,17 @@ search_result_freeze_probes (void *cls, const GNUNET_HashCode * key, { struct GNUNET_FS_SearchResult *sr = value; - if (sr->probe_ctx != NULL) + if (NULL != sr->probe_ctx) { GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); sr->probe_ctx = NULL; } - if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; } - if (sr->update_search != NULL) + if (NULL != sr->update_search) GNUNET_FS_search_pause (sr->update_search); return GNUNET_OK; } @@ -1284,7 +1303,7 @@ search_result_resume_probes (void *cls, const GNUNET_HashCode * key, struct GNUNET_FS_SearchResult *sr = value; GNUNET_FS_search_start_probe_ (sr); - if (sr->update_search != NULL) + if (NULL != sr->update_search) GNUNET_FS_search_continue (sr->update_search); return GNUNET_OK; } @@ -1305,10 +1324,21 @@ search_result_suspend (void *cls, const GNUNET_HashCode * key, void *value) struct GNUNET_FS_SearchResult *sr = value; struct GNUNET_FS_ProgressInfo pi; - if (sr->download != NULL) + if (NULL != sr->download) + { GNUNET_FS_download_signal_suspend_ (sr->download); - if (sr->update_search != NULL) + sr->download = NULL; + } + if (NULL != sr->probe_ctx) + { + GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); + sr->probe_ctx = NULL; + } + if (NULL != sr->update_search) + { GNUNET_FS_search_signal_suspend_ (sr->update_search); + sr->update_search = NULL; + } pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_SUSPEND; pi.value.search.specifics.result_suspend.cctx = sr->client_info; pi.value.search.specifics.result_suspend.meta = sr->meta; @@ -1318,10 +1348,11 @@ search_result_suspend (void *cls, const GNUNET_HashCode * key, void *value) GNUNET_free_non_null (sr->serialization); GNUNET_FS_uri_destroy (sr->uri); GNUNET_CONTAINER_meta_data_destroy (sr->meta); - if (sr->probe_ctx != NULL) - GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); - if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) + { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); + sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; + } GNUNET_free_non_null (sr->keyword_bitmap); GNUNET_free (sr); return GNUNET_OK; @@ -1350,9 +1381,9 @@ GNUNET_FS_search_signal_suspend_ (void *cls) if (sc->task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (sc->task); if (NULL != sc->client) - GNUNET_CLIENT_disconnect (sc->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (sc->client); GNUNET_CONTAINER_multihashmap_destroy (sc->master_result_map); - if (sc->requests != NULL) + if (NULL != sc->requests) { GNUNET_assert (GNUNET_FS_uri_test_ksk (sc->uri)); for (i = 0; i < sc->uri->data.ksk.keywordCount; i++) @@ -1385,7 +1416,7 @@ GNUNET_FS_search_start (struct GNUNET_FS_Handle *h, struct GNUNET_FS_SearchContext *ret; ret = search_start (h, uri, anonymity, options, cctx, NULL); - if (ret == NULL) + if (NULL == ret) return NULL; ret->top = GNUNET_FS_make_top (h, &GNUNET_FS_search_signal_suspend_, ret); return ret; @@ -1402,11 +1433,11 @@ GNUNET_FS_search_pause (struct GNUNET_FS_SearchContext *sc) { struct GNUNET_FS_ProgressInfo pi; - if (sc->task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != sc->task) GNUNET_SCHEDULER_cancel (sc->task); sc->task = GNUNET_SCHEDULER_NO_TASK; if (NULL != sc->client) - GNUNET_CLIENT_disconnect (sc->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (sc->client); sc->client = NULL; GNUNET_FS_search_sync_ (sc); GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, @@ -1426,8 +1457,8 @@ GNUNET_FS_search_continue (struct GNUNET_FS_SearchContext *sc) { struct GNUNET_FS_ProgressInfo pi; - GNUNET_assert (sc->client == NULL); - GNUNET_assert (sc->task == GNUNET_SCHEDULER_NO_TASK); + GNUNET_assert (NULL == sc->client); + GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sc->task); do_reconnect (sc, NULL); GNUNET_FS_search_sync_ (sc); pi.status = GNUNET_FS_STATUS_SEARCH_CONTINUED; @@ -1438,7 +1469,7 @@ GNUNET_FS_search_continue (struct GNUNET_FS_SearchContext *sc) /** - * Free the given search result. + * Signal stop for the given search result. * * @param cls the global FS handle * @param key the key for the search result (unused) @@ -1446,7 +1477,7 @@ GNUNET_FS_search_continue (struct GNUNET_FS_SearchContext *sc) * @return GNUNET_OK */ static int -search_result_free (void *cls, const GNUNET_HashCode * key, void *value) +search_result_stop (void *cls, const GNUNET_HashCode * key, void *value) { struct GNUNET_FS_SearchContext *sc = cls; struct GNUNET_FS_SearchResult *sr = value; @@ -1470,23 +1501,40 @@ search_result_free (void *cls, const GNUNET_HashCode * key, void *value) GNUNET_FS_download_sync_ (sr->download); sr->download = NULL; } - if (NULL != sr->update_search) - { - GNUNET_FS_search_stop (sr->update_search); - GNUNET_assert (sr->update_search == NULL); - } pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED; pi.value.search.specifics.result_stopped.cctx = sr->client_info; pi.value.search.specifics.result_stopped.meta = sr->meta; pi.value.search.specifics.result_stopped.uri = sr->uri; sr->client_info = GNUNET_FS_search_make_status_ (&pi, sc); + return GNUNET_OK; +} + + +/** + * Free the given search result. + * + * @param cls the global FS handle + * @param key the key for the search result (unused) + * @param value the search result to free + * @return GNUNET_OK + */ +static int +search_result_free (void *cls, const GNUNET_HashCode * key, void *value) +{ + struct GNUNET_FS_SearchResult *sr = value; + + if (NULL != sr->update_search) + { + GNUNET_FS_search_stop (sr->update_search); + GNUNET_assert (NULL == sr->update_search); + } GNUNET_break (NULL == sr->client_info); GNUNET_free_non_null (sr->serialization); GNUNET_FS_uri_destroy (sr->uri); GNUNET_CONTAINER_meta_data_destroy (sr->meta); - if (sr->probe_ctx != NULL) + if (NULL != sr->probe_ctx) GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); - if (sr->probe_cancel_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); GNUNET_free_non_null (sr->keyword_bitmap); GNUNET_free (sr); @@ -1505,13 +1553,13 @@ GNUNET_FS_search_stop (struct GNUNET_FS_SearchContext *sc) struct GNUNET_FS_ProgressInfo pi; unsigned int i; - if (sc->top != NULL) + if (NULL != sc->top) GNUNET_FS_end_top (sc->h, sc->top); - if (sc->psearch_result != NULL) - sc->psearch_result->update_search = NULL; GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, - &search_result_free, sc); - if (sc->serialization != NULL) + &search_result_stop, sc); + if (NULL != sc->psearch_result) + sc->psearch_result->update_search = NULL; + if (NULL != sc->serialization) { GNUNET_FS_remove_sync_file_ (sc->h, (sc->psearch_result != @@ -1528,12 +1576,14 @@ GNUNET_FS_search_stop (struct GNUNET_FS_SearchContext *sc) pi.status = GNUNET_FS_STATUS_SEARCH_STOPPED; sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc); GNUNET_break (NULL == sc->client_info); - if (sc->task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != sc->task) GNUNET_SCHEDULER_cancel (sc->task); if (NULL != sc->client) - GNUNET_CLIENT_disconnect (sc->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (sc->client); + GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, + &search_result_free, sc); GNUNET_CONTAINER_multihashmap_destroy (sc->master_result_map); - if (sc->requests != NULL) + if (NULL != sc->requests) { GNUNET_assert (GNUNET_FS_uri_test_ksk (sc->uri)); for (i = 0; i < sc->uri->data.ksk.keywordCount; i++) diff --git a/src/fs/fs_tree.c b/src/fs/fs_tree.c index b3bbdc7..30cdded 100644 --- a/src/fs/fs_tree.c +++ b/src/fs/fs_tree.c @@ -287,6 +287,10 @@ GNUNET_FS_tree_encoder_create (struct GNUNET_FS_Handle *h, uint64_t size, te->chk_tree = GNUNET_malloc (te->chk_tree_depth * CHK_PER_INODE * sizeof (struct ContentHashKey)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Created tree encoder for file with %llu bytes and depth %u\n", + (unsigned long long) size, + te->chk_tree_depth); return te; } @@ -357,8 +361,8 @@ GNUNET_FS_tree_encoder_next (struct GNUNET_FS_TreeEncoder *te) if (pt_size != te->reader (te->cls, te->publish_offset, pt_size, iob, &te->emsg)) { - te->cont (te->cls, NULL); te->in_next = GNUNET_NO; + te->cont (te->cls, NULL); return; } pt_block = iob; @@ -425,6 +429,7 @@ void GNUNET_FS_tree_encoder_finish (struct GNUNET_FS_TreeEncoder *te, struct GNUNET_FS_Uri **uri, char **emsg) { + (void) te->reader (te->cls, UINT64_MAX, 0, 0, NULL); GNUNET_assert (GNUNET_NO == te->in_next); if (uri != NULL) *uri = te->uri; diff --git a/src/fs/fs_unindex.c b/src/fs/fs_unindex.c index ff1996a..6910321 100644 --- a/src/fs/fs_unindex.c +++ b/src/fs/fs_unindex.c @@ -30,6 +30,7 @@ #include "gnunet_protocols.h" #include "fs_api.h" #include "fs_tree.h" +#include "block_fs.h" /** @@ -203,6 +204,7 @@ unindex_process (void *cls, const struct ContentHashKey *chk, uint64_t offset, "Sending REMOVE request to DATASTORE service\n"); GNUNET_DATASTORE_remove (uc->dsh, &chk->query, size, data, -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT, &process_cont, uc); + uc->chk = *chk; } @@ -221,7 +223,7 @@ process_fs_response (void *cls, const struct GNUNET_MessageHeader *msg) if (uc->client != NULL) { - GNUNET_CLIENT_disconnect (uc->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (uc->client); uc->client = NULL; } if (uc->state != UNINDEX_STATE_FS_NOTIFY) @@ -258,16 +260,15 @@ process_fs_response (void *cls, const struct GNUNET_MessageHeader *msg) /** - * Function called when the tree encoder has - * processed all blocks. Clean up. + * Function called when we are done with removing KBlocks. + * Disconnect from datastore and notify FS service about + * the unindex event. * - * @param cls our unindexing context - * @param tc not used + * @param uc our unindexing context */ static void -unindex_finish (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +unindex_finish (struct GNUNET_FS_UnindexContext *uc) { - struct GNUNET_FS_UnindexContext *uc = cls; char *emsg; struct GNUNET_FS_Uri *uri; struct UnindexMessage req; @@ -310,6 +311,297 @@ unindex_finish (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } + +/** + * Function called by the directory scanner as we extract keywords + * that we will need to remove KBlocks. + * + * @param cls the 'struct GNUNET_FS_UnindexContext *' + * @param filename which file we are making progress on + * @param is_directory GNUNET_YES if this is a directory, + * GNUNET_NO if this is a file + * GNUNET_SYSERR if it is neither (or unknown) + * @param reason kind of progress we are making + */ +static void +unindex_directory_scan_cb (void *cls, + const char *filename, + int is_directory, + enum GNUNET_FS_DirScannerProgressUpdateReason reason) +{ + struct GNUNET_FS_UnindexContext *uc = cls; + static struct GNUNET_FS_ShareTreeItem * directory_scan_result; + + switch (reason) + { + case GNUNET_FS_DIRSCANNER_FINISHED: + directory_scan_result = GNUNET_FS_directory_scan_get_result (uc->dscan); + uc->dscan = NULL; + if (NULL != directory_scan_result->ksk_uri) + { + uc->ksk_uri = GNUNET_FS_uri_dup (directory_scan_result->ksk_uri); + uc->state = UNINDEX_STATE_DS_REMOVE_KBLOCKS; + uc->emsg = GNUNET_strdup (_("Failed to get KSKs from directory scan.")); + GNUNET_FS_unindex_sync_ (uc); + GNUNET_FS_unindex_do_remove_kblocks_ (uc); + } + else + { + unindex_finish (uc); + } + GNUNET_FS_share_tree_free (directory_scan_result); + break; + case GNUNET_FS_DIRSCANNER_INTERNAL_ERROR: + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Internal error scanning `%s'.\n"), + uc->filename); + break; + default: + break; + } + +} + + +/** + * If necessary, connect to the datastore and remove the KBlocks. + * + * @param uc context for the unindex operation. + */ +void +GNUNET_FS_unindex_do_extract_keywords_ (struct GNUNET_FS_UnindexContext *uc) +{ + char *ex; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (uc->h->cfg, "FS", "EXTRACTORS", &ex)) + ex = NULL; + uc->dscan = GNUNET_FS_directory_scan_start (uc->filename, + GNUNET_NO, ex, + &unindex_directory_scan_cb, + uc); + GNUNET_free_non_null (ex); +} + + +/** + * Continuation called to notify client about result of the remove + * operation for the KBlock. + * + * @param cls the 'struct GNUNET_FS_UnindexContext *' + * @param success GNUNET_SYSERR on failure (including timeout/queue drop) + * GNUNET_NO if content was already there + * GNUNET_YES (or other positive value) on success + * @param min_expiration minimum expiration time required for 0-priority content to be stored + * by the datacache at this time, zero for unknown, forever if we have no + * space for 0-priority content + * @param msg NULL on success, otherwise an error message + */ +static void +continue_after_remove (void *cls, + int32_t success, + struct GNUNET_TIME_Absolute min_expiration, + const char *msg) +{ + struct GNUNET_FS_UnindexContext *uc = cls; + + uc->dqe = NULL; + if (success != GNUNET_YES) + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Failed to remove KBlock: %s\n"), + msg); + uc->ksk_offset++; + GNUNET_FS_unindex_do_remove_kblocks_ (uc); +} + + +/** + * Function called from datastore with result from us looking for + * a KBlock. There are four cases: + * 1) no result, means we move on to the next keyword + * 2) UID is the same as the first UID, means we move on to next keyword + * 3) KBlock for a different CHK, means we keep looking for more + * 4) KBlock is for our CHK, means we remove the block and then move + * on to the next keyword + * + * @param cls the 'struct GNUNET_FS_UnindexContext *' + * @param key key for the content + * @param size number of bytes in data + * @param data content stored + * @param type type of the content + * @param priority priority of the content + * @param anonymity anonymity-level for the content + * @param expiration expiration time for the content + * @param uid unique identifier for the datum; + * maybe 0 if no unique identifier is available + */ +static void +process_kblock_for_unindex (void *cls, + const GNUNET_HashCode * key, + size_t size, const void *data, + enum GNUNET_BLOCK_Type type, + uint32_t priority, + uint32_t anonymity, + struct GNUNET_TIME_Absolute + expiration, uint64_t uid) +{ + struct GNUNET_FS_UnindexContext *uc = cls; + const struct KBlock *kb; + struct GNUNET_FS_Uri *chk_uri; + + uc->dqe = NULL; + if (NULL == data) + { + /* no result */ + uc->ksk_offset++; + GNUNET_FS_unindex_do_remove_kblocks_ (uc); + return; + } + if (0 == uc->first_uid) + { + /* remember UID of first result to detect cycles */ + uc->first_uid = uid; + } + else if (uid == uc->first_uid) + { + /* no more additional results */ + uc->ksk_offset++; + GNUNET_FS_unindex_do_remove_kblocks_ (uc); + return; + } + GNUNET_assert (GNUNET_BLOCK_TYPE_FS_KBLOCK == type); + if (size < sizeof (struct KBlock)) + { + GNUNET_break (0); + goto get_next; + } + kb = data; + { + char pt[size - sizeof (struct KBlock)]; + struct GNUNET_CRYPTO_AesSessionKey skey; + struct GNUNET_CRYPTO_AesInitializationVector iv; + + GNUNET_CRYPTO_hash_to_aes_key (&uc->key, &skey, &iv); + if (-1 == + GNUNET_CRYPTO_aes_decrypt (&kb[1], size - sizeof (struct KBlock), &skey, + &iv, pt)) + { + GNUNET_break (0); + goto get_next; + } + if (NULL == memchr (pt, 0, sizeof (pt))) + { + GNUNET_break (0); + goto get_next; + } + chk_uri = GNUNET_FS_uri_parse (pt, NULL); + if (NULL == chk_uri) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Failed to parse URI `%s' from KBlock!\n"), + pt); + GNUNET_break (0); + goto get_next; + } + } + if (0 != memcmp (&uc->chk, + &chk_uri->data.chk.chk, + sizeof (struct ContentHashKey))) + { + /* different CHK, ignore */ + GNUNET_FS_uri_destroy (chk_uri); + goto get_next; + } + GNUNET_FS_uri_destroy (chk_uri); + /* matches! */ + uc->dqe = GNUNET_DATASTORE_remove (uc->dsh, + key, size, data, + 0 /* priority */, 1 /* queue size */, + GNUNET_TIME_UNIT_FOREVER_REL, + &continue_after_remove, + uc); + return; + get_next: + uc->dqe = GNUNET_DATASTORE_get_key (uc->dsh, + uc->roff++, + &uc->query, + GNUNET_BLOCK_TYPE_FS_KBLOCK, + 0 /* priority */, 1 /* queue size */, + GNUNET_TIME_UNIT_FOREVER_REL, + &process_kblock_for_unindex, + uc); +} + + +/** + * If necessary, connect to the datastore and remove the KBlocks. + * + * @param uc context for the unindex operation. + */ +void +GNUNET_FS_unindex_do_remove_kblocks_ (struct GNUNET_FS_UnindexContext *uc) +{ + const char *keyword; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub; + struct GNUNET_CRYPTO_RsaPrivateKey *pk; + + if (NULL == uc->dsh) + uc->dsh = GNUNET_DATASTORE_connect (uc->h->cfg); + if (NULL == uc->dsh) + { + uc->state = UNINDEX_STATE_ERROR; + uc->emsg = GNUNET_strdup (_("Failed to connect to `datastore' service.")); + GNUNET_FS_unindex_sync_ (uc); + signal_unindex_error (uc); + return; + } + if ( (NULL == uc->ksk_uri) || + (uc->ksk_offset >= uc->ksk_uri->data.ksk.keywordCount) ) + { + unindex_finish (uc); + return; + } + /* FIXME: code duplication with fs_search.c here... */ + keyword = &uc->ksk_uri->data.ksk.keywords[uc->ksk_offset][1]; + GNUNET_CRYPTO_hash (keyword, strlen (keyword), &uc->key); + pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&uc->key); + GNUNET_assert (pk != NULL); + GNUNET_CRYPTO_rsa_key_get_public (pk, &pub); + GNUNET_CRYPTO_rsa_key_free (pk); + GNUNET_CRYPTO_hash (&pub, + sizeof (struct + GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + &uc->query); + uc->first_uid = 0; + uc->dqe = GNUNET_DATASTORE_get_key (uc->dsh, + uc->roff++, + &uc->query, + GNUNET_BLOCK_TYPE_FS_KBLOCK, + 0 /* priority */, 1 /* queue size */, + GNUNET_TIME_UNIT_FOREVER_REL, + &process_kblock_for_unindex, + uc); +} + + +/** + * Function called when the tree encoder has + * processed all blocks. Clean up. + * + * @param cls our unindexing context + * @param tc not used + */ +static void +unindex_extract_keywords (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_FS_UnindexContext *uc = cls; + + uc->state = UNINDEX_STATE_EXTRACT_KEYWORDS; + GNUNET_FS_unindex_sync_ (uc); + GNUNET_FS_unindex_do_extract_keywords_ (uc); +} + + /** * Connect to the datastore and remove the blocks. * @@ -318,7 +610,8 @@ unindex_finish (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) void GNUNET_FS_unindex_do_remove_ (struct GNUNET_FS_UnindexContext *uc) { - uc->dsh = GNUNET_DATASTORE_connect (uc->h->cfg); + if (NULL == uc->dsh) + uc->dsh = GNUNET_DATASTORE_connect (uc->h->cfg); if (NULL == uc->dsh) { uc->state = UNINDEX_STATE_ERROR; @@ -343,7 +636,7 @@ GNUNET_FS_unindex_do_remove_ (struct GNUNET_FS_UnindexContext *uc) uc->tc = GNUNET_FS_tree_encoder_create (uc->h, uc->file_size, uc, &unindex_reader, &unindex_process, &unindex_progress, - &unindex_finish); + &unindex_extract_keywords); GNUNET_FS_tree_encoder_next (uc->tc); } @@ -393,14 +686,30 @@ GNUNET_FS_unindex_signal_suspend_ (void *cls) struct GNUNET_FS_UnindexContext *uc = cls; struct GNUNET_FS_ProgressInfo pi; + /* FIXME: lots of duplication with unindex_stop here! */ + if (uc->dscan != NULL) + { + GNUNET_FS_directory_scan_abort (uc->dscan); + uc->dscan = NULL; + } + if (NULL != uc->dqe) + { + GNUNET_DATASTORE_cancel (uc->dqe); + uc->dqe = NULL; + } if (uc->fhc != NULL) { GNUNET_CRYPTO_hash_file_cancel (uc->fhc); uc->fhc = NULL; } + if (NULL != uc->ksk_uri) + { + GNUNET_FS_uri_destroy (uc->ksk_uri); + uc->ksk_uri = NULL; + } if (uc->client != NULL) { - GNUNET_CLIENT_disconnect (uc->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (uc->client); uc->client = NULL; } if (NULL != uc->dsh) @@ -447,7 +756,7 @@ GNUNET_FS_unindex_start (struct GNUNET_FS_Handle *h, const char *filename, struct GNUNET_FS_ProgressInfo pi; uint64_t size; - if (GNUNET_OK != GNUNET_DISK_file_size (filename, &size, GNUNET_YES)) + if (GNUNET_OK != GNUNET_DISK_file_size (filename, &size, GNUNET_YES, GNUNET_YES)) return NULL; ret = GNUNET_malloc (sizeof (struct GNUNET_FS_UnindexContext)); ret->h = h; @@ -478,6 +787,16 @@ GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc) { struct GNUNET_FS_ProgressInfo pi; + if (uc->dscan != NULL) + { + GNUNET_FS_directory_scan_abort (uc->dscan); + uc->dscan = NULL; + } + if (NULL != uc->dqe) + { + GNUNET_DATASTORE_cancel (uc->dqe); + uc->dqe = NULL; + } if (uc->fhc != NULL) { GNUNET_CRYPTO_hash_file_cancel (uc->fhc); @@ -485,7 +804,7 @@ GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc) } if (uc->client != NULL) { - GNUNET_CLIENT_disconnect (uc->client, GNUNET_NO); + GNUNET_CLIENT_disconnect (uc->client); uc->client = NULL; } if (NULL != uc->dsh) @@ -493,6 +812,11 @@ GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc) GNUNET_DATASTORE_disconnect (uc->dsh, GNUNET_NO); uc->dsh = NULL; } + if (NULL != uc->ksk_uri) + { + GNUNET_FS_uri_destroy (uc->ksk_uri); + uc->ksk_uri = NULL; + } if (NULL != uc->tc) { GNUNET_FS_tree_encoder_finish (uc->tc, NULL, NULL); @@ -517,6 +841,7 @@ GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc) (uc->state == UNINDEX_STATE_COMPLETE) ? uc->file_size : 0); GNUNET_break (NULL == uc->client_info); + GNUNET_free_non_null (uc->emsg); GNUNET_free (uc->filename); GNUNET_free (uc); } diff --git a/src/fs/fs_uri.c b/src/fs/fs_uri.c index 5dfdcb5..0c2d64c 100644 --- a/src/fs/fs_uri.c +++ b/src/fs/fs_uri.c @@ -214,7 +214,7 @@ percent_decode_keyword (const char *in, char **emsg) { if (out[rpos] == '%') { - if (1 != sscanf (&out[rpos + 1], "%2X", &hx)) + if (1 != SSCANF (&out[rpos + 1], "%2X", &hx)) { GNUNET_free (out); *emsg = GNUNET_strdup (_("`%' must be followed by HEX number")); @@ -1378,14 +1378,16 @@ GNUNET_FS_uri_sks_to_string_fancy (struct GNUNET_CONFIGURATION_Handle *cfg, { char *ret; char *name; + char *unique_name; if (uri->type != sks) return NULL; - name = GNUNET_PSEUDONYM_id_to_name (cfg, &uri->data.sks.namespace); - if (name == NULL) - return GNUNET_FS_uri_to_string (uri); - GNUNET_asprintf (&ret, "%s: %s", name, uri->data.sks.identifier); + (void) GNUNET_PSEUDONYM_get_info (cfg, &uri->data.sks.namespace, + NULL, NULL, &name, NULL); + unique_name = GNUNET_PSEUDONYM_name_uniquify (cfg, &uri->data.sks.namespace, name, NULL); GNUNET_free (name); + GNUNET_asprintf (&ret, "%s: %s", unique_name, uri->data.sks.identifier); + GNUNET_free (unique_name); return ret; } @@ -1499,6 +1501,10 @@ find_duplicate (const char *s, const char **array, int array_length) return GNUNET_NO; } + +/** + * FIXME: comment + */ static char * normalize_metadata (enum EXTRACTOR_MetaFormat format, const char *data, size_t data_len) diff --git a/src/fs/gnunet-directory.c b/src/fs/gnunet-directory.c index 0721ea9..c722f57 100644 --- a/src/fs/gnunet-directory.c +++ b/src/fs/gnunet-directory.c @@ -136,7 +136,7 @@ run (void *cls, char *const *args, const char *cfgfile, i = 0; while (NULL != (filename = args[i++])) { - if ((GNUNET_OK != GNUNET_DISK_file_size (filename, &size, GNUNET_YES)) || + if ((GNUNET_OK != GNUNET_DISK_file_size (filename, &size, GNUNET_YES, GNUNET_YES)) || (NULL == (h = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, diff --git a/src/fs/gnunet-download.c b/src/fs/gnunet-download.c index ff10c39..5a66aea 100644 --- a/src/fs/gnunet-download.c +++ b/src/fs/gnunet-download.c @@ -90,7 +90,8 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) { - char *s, *s2; + char *s; + char *s2; char *t; switch (info->status) diff --git a/src/fs/gnunet-helper-fs-publish.c b/src/fs/gnunet-helper-fs-publish.c index 4f70464..86b0249 100644 --- a/src/fs/gnunet-helper-fs-publish.c +++ b/src/fs/gnunet-helper-fs-publish.c @@ -69,7 +69,8 @@ struct ScanTreeNode char *filename; /** - * Size of the file (if it is a file), in bytes + * Size of the file (if it is a file), in bytes. + * At the moment it is set to 0 for directories. */ uint64_t file_size; @@ -185,6 +186,11 @@ write_message (uint16_t message_type, { struct GNUNET_MessageHeader hdr; +#if 0 + fprintf (stderr, "Helper sends %u-byte message of type %u\n", + (unsigned int) (sizeof (struct GNUNET_MessageHeader) + data_length), + (unsigned int) message_type); +#endif hdr.type = htons (message_type); hdr.size = htons (sizeof (struct GNUNET_MessageHeader) + data_length); if ( (GNUNET_OK != @@ -204,7 +210,8 @@ write_message (uint16_t message_type, * the scan. Does NOT yet add any metadata. * * @param filename file or directory to scan - * @param dst where to store the resulting share tree item + * @param dst where to store the resulting share tree item; + * NULL is stored in 'dst' upon recoverable errors (GNUNET_OK is returned) * @return GNUNET_OK on success, GNUNET_SYSERR on error */ static int @@ -252,6 +259,8 @@ scan_callback (void *cls, rc->stop = GNUNET_YES; return GNUNET_SYSERR; } + if (NULL == chld) + return GNUNET_OK; chld->parent = rc->parent; GNUNET_CONTAINER_DLL_insert (rc->parent->children_head, rc->parent->children_tail, @@ -266,7 +275,8 @@ scan_callback (void *cls, * the scan. Does NOT yet add any metadata. * * @param filename file or directory to scan - * @param dst where to store the resulting share tree item + * @param dst where to store the resulting share tree item; + * NULL is stored in 'dst' upon recoverable errors (GNUNET_OK is returned) * @return GNUNET_OK on success, GNUNET_SYSERR on error */ static int @@ -275,8 +285,11 @@ preprocess_file (const char *filename, { struct ScanTreeNode *item; struct stat sbuf; + uint64_t fsize = 0; - if (0 != STAT (filename, &sbuf)) + if ((0 != STAT (filename, &sbuf)) || + ((!S_ISDIR (sbuf.st_mode)) && (GNUNET_OK != GNUNET_DISK_file_size ( + filename, &fsize, GNUNET_NO, GNUNET_YES)))) { /* If the file doesn't exist (or is not stat-able for any other reason) skip it (but report it), but do continue. */ @@ -284,6 +297,8 @@ preprocess_file (const char *filename, write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_SKIP_FILE, filename, strlen (filename) + 1)) return GNUNET_SYSERR; + /* recoverable error, store 'NULL' in *dst */ + *dst = NULL; return GNUNET_OK; } @@ -297,8 +312,8 @@ preprocess_file (const char *filename, item = GNUNET_malloc (sizeof (struct ScanTreeNode)); item->filename = GNUNET_strdup (filename); item->is_directory = (S_ISDIR (sbuf.st_mode)) ? GNUNET_YES : GNUNET_NO; - item->file_size = (uint64_t) sbuf.st_size; - if (item->is_directory == GNUNET_YES) + item->file_size = fsize; + if (GNUNET_YES == item->is_directory) { struct RecursionContext rc; @@ -307,7 +322,7 @@ preprocess_file (const char *filename, GNUNET_DISK_directory_scan (filename, &scan_callback, &rc); - if ( (rc.stop == GNUNET_YES) || + if ( (GNUNET_YES == rc.stop) || (GNUNET_OK != write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY, "..", 3)) ) @@ -334,7 +349,7 @@ extract_files (struct ScanTreeNode *item) ssize_t size; size_t slen; - if (item->is_directory == GNUNET_YES) + if (GNUNET_YES == item->is_directory) { /* for directories, we simply only descent, no extraction, no progress reporting */ @@ -369,8 +384,13 @@ extract_files (struct ScanTreeNode *item) memcpy (buf, item->filename, slen); size = GNUNET_CONTAINER_meta_data_serialize (meta, - &dst, size - slen, + &dst, size, GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); + if (size < 0) + { + GNUNET_break (0); + size = 0; + } GNUNET_CONTAINER_meta_data_destroy (meta); if (GNUNET_OK != write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_META_DATA, @@ -407,7 +427,7 @@ int main(int argc, #endif /* parse command line */ - if ( (argc != 3) && (argc != 2) ) + if ( (3 != argc) && (2 != argc) ) { FPRINTF (stderr, "%s", @@ -416,7 +436,7 @@ int main(int argc, } filename_expanded = argv[1]; ex = argv[2]; - if ( (ex == NULL) || + if ( (NULL == ex) || (0 != strcmp (ex, "-")) ) { plugins = EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY); @@ -437,14 +457,17 @@ int main(int argc, if (GNUNET_OK != write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_COUNTING_DONE, NULL, 0)) return 3; - if (GNUNET_OK != - extract_files (root)) + if (NULL != root) { - (void) write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR, NULL, 0); + if (GNUNET_OK != + extract_files (root)) + { + (void) write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR, NULL, 0); + free_tree (root); + return 4; + } free_tree (root); - return 4; } - free_tree (root); /* enable "clean" shutdown by telling parent that we are done */ (void) write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_FINISHED, NULL, 0); if (NULL != plugins) diff --git a/src/fs/gnunet-pseudonym.c b/src/fs/gnunet-pseudonym.c index 412ddd2..38826d1 100644 --- a/src/fs/gnunet-pseudonym.c +++ b/src/fs/gnunet-pseudonym.c @@ -106,20 +106,29 @@ ns_printer (void *cls, const char *name, const GNUNET_HashCode * id) static int pseudo_printer (void *cls, const GNUNET_HashCode * pseudonym, + const char *name, const char *unique_name, const struct GNUNET_CONTAINER_MetaData *md, int rating) { char *id; - - id = GNUNET_PSEUDONYM_id_to_name (cfg, pseudonym); - if (id == NULL) + char *unique_id; + int getinfo_result; + + /* While we get a name from the caller, it might be NULL. + * GNUNET_PSEUDONYM_get_info () never returns NULL. + */ + getinfo_result = GNUNET_PSEUDONYM_get_info (cfg, pseudonym, + NULL, NULL, &id, NULL); + if (getinfo_result != GNUNET_OK) { GNUNET_break (0); return GNUNET_OK; } - FPRINTF (stdout, "%s (%d):\n", id, rating); + unique_id = GNUNET_PSEUDONYM_name_uniquify (cfg, pseudonym, id, NULL); + GNUNET_free (id); + FPRINTF (stdout, "%s (%d):\n", unique_id, rating); GNUNET_CONTAINER_meta_data_iterate (md, &EXTRACTOR_meta_data_print, stdout); FPRINTF (stdout, "%s", "\n"); - GNUNET_free (id); + GNUNET_free (unique_id); return GNUNET_OK; } @@ -162,7 +171,8 @@ post_advertising (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg) } else { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namespace `%s' unknown.\n"), + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + ("Namespace `%s' unknown. Make sure you specify its numeric suffix, if any.\n"), rating_change); } } diff --git a/src/fs/gnunet-publish.c b/src/fs/gnunet-publish.c index 50f507d..a1b26db 100644 --- a/src/fs/gnunet-publish.c +++ b/src/fs/gnunet-publish.c @@ -291,6 +291,12 @@ publish_inspector (void *cls, struct GNUNET_FS_FileInformation *fi, } if (!do_disable_creation_time) GNUNET_CONTAINER_meta_data_add_publication_date (m); + if ( (disable_extractor) && + (NULL != *uri) ) + { + GNUNET_FS_uri_destroy (*uri); + *uri = NULL; + } if (extract_only) { fn = GNUNET_CONTAINER_meta_data_get_by_type (m, diff --git a/src/fs/gnunet-service-fs.h b/src/fs/gnunet-service-fs.h index 5ea73ee..0c796bf 100644 --- a/src/fs/gnunet-service-fs.h +++ b/src/fs/gnunet-service-fs.h @@ -129,7 +129,7 @@ struct GetMessage * Hashcodes of the file(s) we're looking for. * Details depend on the query type. */ - GNUNET_HashCode query GNUNET_PACKED; + GNUNET_HashCode query; /* this is followed by hash codes as specified in the "hash_bitmap"; * after that, an optional bloomfilter (with bits set for replies diff --git a/src/fs/gnunet-service-fs_indexing.c b/src/fs/gnunet-service-fs_indexing.c index b563019..e452894 100644 --- a/src/fs/gnunet-service-fs_indexing.c +++ b/src/fs/gnunet-service-fs_indexing.c @@ -368,7 +368,7 @@ GNUNET_FS_handle_index_list_get (void *cls, struct GNUNET_SERVER_Client *client, { struct GNUNET_SERVER_TransmitContext *tc; struct IndexInfoMessage *iim; - char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1]; + char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN; size_t slen; const char *fn; struct IndexInfo *pos; diff --git a/src/fs/gnunet-service-fs_lc.c b/src/fs/gnunet-service-fs_lc.c index 36aafdd..20d430e 100644 --- a/src/fs/gnunet-service-fs_lc.c +++ b/src/fs/gnunet-service-fs_lc.c @@ -140,7 +140,7 @@ struct GSF_LocalClient /** * Context for sending replies. */ - struct GNUNET_CONNECTION_TransmitHandle *th; + struct GNUNET_SERVER_TransmitHandle *th; }; @@ -259,7 +259,7 @@ client_response_handler (void *cls, enum GNUNET_BLOCK_EvaluationResult eval, lc = cr->lc; msize = sizeof (struct ClientPutMessage) + data_len; { - char buf[msize]; + char buf[msize] GNUNET_ALIGN; pm = (struct ClientPutMessage *) buf; pm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_PUT); @@ -498,7 +498,7 @@ GSF_client_disconnect_handler_ (void *cls, struct GNUNET_SERVER_Client *client) } if (pos->th != NULL) { - GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th); + GNUNET_SERVER_notify_transmit_ready_cancel (pos->th); pos->th = NULL; } GSF_handle_local_client_disconnect_ (pos); diff --git a/src/fs/gnunet-service-fs_pr.c b/src/fs/gnunet-service-fs_pr.c index d4b4481..8ca4121 100644 --- a/src/fs/gnunet-service-fs_pr.c +++ b/src/fs/gnunet-service-fs_pr.c @@ -1057,7 +1057,7 @@ GSF_dht_lookup_ (struct GSF_PendingRequest *pr) const void *xquery; size_t xquery_size; struct GNUNET_PeerIdentity pi; - char buf[sizeof (GNUNET_HashCode) * 2]; + char buf[sizeof (GNUNET_HashCode) * 2] GNUNET_ALIGN; if (0 != pr->public_data.anonymity_level) return; @@ -1082,7 +1082,7 @@ GSF_dht_lookup_ (struct GSF_PendingRequest *pr) xquery_size += sizeof (struct GNUNET_PeerIdentity); } pr->gh = - GNUNET_DHT_get_start (GSF_dht, GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_DHT_get_start (GSF_dht, pr->public_data.type, &pr->public_data.query, 5 /* DEFAULT_GET_REPLICATION */ , GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, diff --git a/src/fs/gnunet-service-fs_put.c b/src/fs/gnunet-service-fs_put.c index 3ac6713..463acc0 100644 --- a/src/fs/gnunet-service-fs_put.c +++ b/src/fs/gnunet-service-fs_put.c @@ -33,6 +33,11 @@ */ #define MAX_DHT_PUT_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) +/** + * How many replicas do we try to create per PUT? + */ +#define DEFAULT_PUT_REPLICATION 5 + /** * Context for each zero-anonymity iterator. @@ -51,6 +56,11 @@ struct PutOperator enum GNUNET_BLOCK_Type dht_put_type; /** + * Handle to PUT operation. + */ + struct GNUNET_DHT_PutHandle *dht_put; + + /** * ID of task that collects blocks for DHT PUTs. */ GNUNET_SCHEDULER_TaskIdentifier dht_task; @@ -92,20 +102,15 @@ gather_dht_put_blocks (void *cls, /** - * Task that is run periodically to obtain blocks for DHT PUTs. + * Calculate when to run the next PUT operation and schedule it. * - * @param cls type of blocks to gather - * @param tc scheduler context (unused) + * @param po put operator to schedule */ static void -delay_dht_put_blocks (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +schedule_next_put (struct PutOperator *po) { - struct PutOperator *po = cls; struct GNUNET_TIME_Relative delay; - po->dht_task = GNUNET_SCHEDULER_NO_TASK; - if (tc != NULL && 0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - return; if (po->zero_anonymity_count_estimate > 0) { delay = @@ -125,6 +130,42 @@ delay_dht_put_blocks (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** + * Continuation called after DHT PUT operation has finished. + * + * @param cls type of blocks to gather + * @param success GNUNET_OK if the PUT was transmitted, + * GNUNET_NO on timeout, + * GNUNET_SYSERR on disconnect from service + * after the PUT message was transmitted + * (so we don't know if it was received or not) + */ +static void +delay_dht_put_blocks (void *cls, int success) +{ + struct PutOperator *po = cls; + + po->dht_put = NULL; + schedule_next_put (po); +} + + +/** + * Task that is run periodically to obtain blocks for DHT PUTs. + * + * @param cls type of blocks to gather + * @param tc scheduler context + */ +static void +delay_dht_put_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct PutOperator *po = cls; + + po->dht_task = GNUNET_SCHEDULER_NO_TASK; + schedule_next_put (po); +} + + +/** * Store content in DHT. * * @param cls closure @@ -151,7 +192,7 @@ process_dht_put_content (void *cls, const GNUNET_HashCode * key, size_t size, { po->zero_anonymity_count_estimate = po->current_offset - 1; po->current_offset = 0; - po->dht_task = GNUNET_SCHEDULER_add_now (&delay_dht_put_blocks, po); + po->dht_task = GNUNET_SCHEDULER_add_now (&delay_dht_put_task, po); return; } po->zero_anonymity_count_estimate = @@ -159,10 +200,10 @@ process_dht_put_content (void *cls, const GNUNET_HashCode * key, size_t size, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Retrieved block `%s' of type %u for DHT PUT\n", GNUNET_h2s (key), type); - GNUNET_DHT_put (GSF_dht, key, 5 /* DEFAULT_PUT_REPLICATION */ , - GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, type, size, data, - expiration, GNUNET_TIME_UNIT_FOREVER_REL, - &delay_dht_put_blocks, po); + po->dht_put = GNUNET_DHT_put (GSF_dht, key, DEFAULT_PUT_REPLICATION, + GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, type, size, data, + expiration, GNUNET_TIME_UNIT_FOREVER_REL, + &delay_dht_put_blocks, po); } @@ -187,7 +228,7 @@ gather_dht_put_blocks (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) po->dht_put_type, &process_dht_put_content, po); if (NULL == po->dht_qe) - po->dht_task = GNUNET_SCHEDULER_add_now (&delay_dht_put_blocks, po); + po->dht_task = GNUNET_SCHEDULER_add_now (&delay_dht_put_task, po); } @@ -226,6 +267,11 @@ GSF_put_done_ () GNUNET_SCHEDULER_cancel (po->dht_task); po->dht_task = GNUNET_SCHEDULER_NO_TASK; } + if (NULL != po->dht_put) + { + GNUNET_DHT_put_cancel (po->dht_put); + po->dht_put = NULL; + } if (NULL != po->dht_qe) { GNUNET_DATASTORE_cancel (po->dht_qe); diff --git a/src/fs/perf_gnunet_service_fs_p2p.c b/src/fs/perf_gnunet_service_fs_p2p.c index 32dcffa..7b2c044 100644 --- a/src/fs/perf_gnunet_service_fs_p2p.c +++ b/src/fs/perf_gnunet_service_fs_p2p.c @@ -191,7 +191,7 @@ do_report (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) char *fancy; struct StatMaster *sm; - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) + if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) { del = GNUNET_TIME_absolute_get_duration (start_time); if (del.rel_value == 0) diff --git a/src/fs/test_fs_defaults.conf b/src/fs/test_fs_defaults.conf index 2bc3d26..fcb888c 100644 --- a/src/fs/test_fs_defaults.conf +++ b/src/fs/test_fs_defaults.conf @@ -85,3 +85,6 @@ AUTOSTART = NO [vpn] AUTOSTART = NO + +[namestore] +AUTOSTART = NO diff --git a/src/fs/test_fs_download.c b/src/fs/test_fs_download.c index 570eab9..2781974 100644 --- a/src/fs/test_fs_download.c +++ b/src/fs/test_fs_download.c @@ -118,7 +118,7 @@ abort_download_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_FS_download_stop (download, GNUNET_YES); download = NULL; } - GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_size (fn, &size, GNUNET_YES)); + GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_size (fn, &size, GNUNET_YES, GNUNET_NO)); GNUNET_assert (size == FILESIZE); GNUNET_DISK_directory_remove (fn); GNUNET_free (fn); @@ -268,7 +268,7 @@ stop_arm (struct PeerContext *p) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); - GNUNET_OS_process_close (p->arm_proc); + GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; } #endif diff --git a/src/fs/test_fs_download_indexed.c b/src/fs/test_fs_download_indexed.c index e8504f1..d16aa97 100644 --- a/src/fs/test_fs_download_indexed.c +++ b/src/fs/test_fs_download_indexed.c @@ -42,7 +42,7 @@ /** * How long until we give up on transmitting the message? */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * How long should our test-content live? @@ -75,9 +75,11 @@ static char *fn1; static int err; + static void timeout_kill_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { + fprintf (stderr, "Download not fast enough, timeout!\n"); if (download != NULL) { GNUNET_FS_download_stop (download, GNUNET_YES); @@ -102,6 +104,7 @@ abort_publish_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } } + static void stop_fs_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { @@ -109,6 +112,7 @@ stop_fs_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) fs = NULL; } + static void abort_download_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { @@ -119,7 +123,7 @@ abort_download_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_FS_download_stop (download, GNUNET_YES); download = NULL; } - GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_size (fn, &size, GNUNET_YES)); + GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_size (fn, &size, GNUNET_YES, GNUNET_NO)); GNUNET_assert (size == FILESIZE); GNUNET_DISK_directory_remove (fn); GNUNET_free (fn); @@ -248,9 +252,6 @@ setup_peer (struct PeerContext *p, const char *cfgname) p->arm_proc = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", "gnunet-service-arm", -#if VERBOSE - "-L", "DEBUG", -#endif "-c", cfgname, NULL); #endif GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); @@ -269,7 +270,7 @@ stop_arm (struct PeerContext *p) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); - GNUNET_OS_process_close (p->arm_proc); + GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; } #endif @@ -335,9 +336,6 @@ main (int argc, char *argv[]) "test-fs-download-indexed", "-c", "test_fs_download_data.conf", -#if VERBOSE - "-L", "DEBUG", -#endif NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { @@ -345,11 +343,7 @@ main (int argc, char *argv[]) }; GNUNET_log_setup ("test_fs_download_indexed", -#if VERBOSE - "DEBUG", -#else "WARNING", -#endif NULL); GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, argvx, "test-fs-download-indexed", "nohelp", options, &run, diff --git a/src/fs/test_fs_download_persistence.c b/src/fs/test_fs_download_persistence.c index bcb1c54..ba776dd 100644 --- a/src/fs/test_fs_download_persistence.c +++ b/src/fs/test_fs_download_persistence.c @@ -113,7 +113,7 @@ abort_download_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_FS_download_stop (download, GNUNET_YES); download = NULL; } - GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_size (fn, &size, GNUNET_YES)); + GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_size (fn, &size, GNUNET_YES, GNUNET_NO)); GNUNET_assert (size == FILESIZE); GNUNET_DISK_directory_remove (fn); GNUNET_free (fn); @@ -318,7 +318,7 @@ stop_arm (struct PeerContext *p) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); - GNUNET_OS_process_close (p->arm_proc); + GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; } #endif diff --git a/src/fs/test_fs_list_indexed.c b/src/fs/test_fs_list_indexed.c index 535f8ef..d046a20 100644 --- a/src/fs/test_fs_list_indexed.c +++ b/src/fs/test_fs_list_indexed.c @@ -211,7 +211,7 @@ stop_arm (struct PeerContext *p) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); - GNUNET_OS_process_close (p->arm_proc); + GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; } #endif diff --git a/src/fs/test_fs_namespace.c b/src/fs/test_fs_namespace.c index d25fd6f..78af1f1 100644 --- a/src/fs/test_fs_namespace.c +++ b/src/fs/test_fs_namespace.c @@ -69,9 +69,6 @@ setup_peer (struct PeerContext *p, const char *cfgname) p->arm_proc = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", "gnunet-service-arm", -#if VERBOSE - "-L", "DEBUG", -#endif "-c", cfgname, NULL); #endif GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); @@ -90,7 +87,7 @@ stop_arm (struct PeerContext *p) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); - GNUNET_OS_process_close (p->arm_proc); + GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; } #endif @@ -261,6 +258,13 @@ sks_cont (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg) char *msg; struct GNUNET_FS_BlockOptions bo; + if (NULL == uri) + { + fprintf (stderr, "Error publishing: %s\n", emsg); + err = 1; + GNUNET_FS_stop (fs); + return; + } meta = GNUNET_CONTAINER_meta_data_create (); msg = NULL; ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/ns-search", &msg); @@ -378,9 +382,6 @@ main (int argc, char *argv[]) "test-fs-namespace", "-c", "test_fs_namespace_data.conf", -#if VERBOSE - "-L", "DEBUG", -#endif NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { @@ -388,11 +389,7 @@ main (int argc, char *argv[]) }; GNUNET_log_setup ("test_fs_namespace", -#if VERBOSE - "DEBUG", -#else "WARNING", -#endif NULL); GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, argvx, "test-fs-namespace", "nohelp", options, &run, NULL); diff --git a/src/fs/test_fs_namespace_list_updateable.c b/src/fs/test_fs_namespace_list_updateable.c index 44775ac..2cec67d 100644 --- a/src/fs/test_fs_namespace_list_updateable.c +++ b/src/fs/test_fs_namespace_list_updateable.c @@ -94,7 +94,7 @@ stop_arm (struct PeerContext *p) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); - GNUNET_OS_process_close (p->arm_proc); + GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; } #endif diff --git a/src/fs/test_fs_publish.c b/src/fs/test_fs_publish.c index e527438..1560f4e 100644 --- a/src/fs/test_fs_publish.c +++ b/src/fs/test_fs_publish.c @@ -196,7 +196,7 @@ stop_arm (struct PeerContext *p) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); - GNUNET_OS_process_close (p->arm_proc); + GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; } #endif diff --git a/src/fs/test_fs_publish_persistence.c b/src/fs/test_fs_publish_persistence.c index 7707eac..7d3bc32 100644 --- a/src/fs/test_fs_publish_persistence.c +++ b/src/fs/test_fs_publish_persistence.c @@ -259,7 +259,7 @@ stop_arm (struct PeerContext *p) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); - GNUNET_OS_process_close (p->arm_proc); + GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; } #endif diff --git a/src/fs/test_fs_search.c b/src/fs/test_fs_search.c index f6c8f00..04c5897 100644 --- a/src/fs/test_fs_search.c +++ b/src/fs/test_fs_search.c @@ -176,9 +176,6 @@ setup_peer (struct PeerContext *p, const char *cfgname) p->arm_proc = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", "gnunet-service-arm", -#if VERBOSE - "-L", "DEBUG", -#endif "-c", cfgname, NULL); #endif GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); @@ -197,7 +194,7 @@ stop_arm (struct PeerContext *p) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); - GNUNET_OS_process_close (p->arm_proc); + GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; } #endif @@ -254,9 +251,6 @@ main (int argc, char *argv[]) "test-fs-search", "-c", "test_fs_search_data.conf", -#if VERBOSE - "-L", "DEBUG", -#endif NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { @@ -264,11 +258,7 @@ main (int argc, char *argv[]) }; GNUNET_log_setup ("test_fs_search", -#if VERBOSE - "DEBUG", -#else "WARNING", -#endif NULL); GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, argvx, "test-fs-search", "nohelp", options, &run, NULL); diff --git a/src/fs/test_fs_search_persistence.c b/src/fs/test_fs_search_persistence.c index 38f88a8..d18b50e 100644 --- a/src/fs/test_fs_search_persistence.c +++ b/src/fs/test_fs_search_persistence.c @@ -259,7 +259,7 @@ stop_arm (struct PeerContext *p) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); - GNUNET_OS_process_close (p->arm_proc); + GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; } #endif diff --git a/src/fs/test_fs_search_probes.c b/src/fs/test_fs_search_probes.c new file mode 100644 index 0000000..b816598 --- /dev/null +++ b/src/fs/test_fs_search_probes.c @@ -0,0 +1,268 @@ +/* + This file is part of GNUnet. + (C) 2012 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file fs/test_fs_search_probes.c + * @brief simple testcase for publish + search operation with probes + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_arm_service.h" +#include "gnunet_fs_service.h" + +#define START_ARM GNUNET_YES + +/** + * File-size we use for testing. + */ +#define FILESIZE 1024 + +/** + * How long until we give up on transmitting the message? + */ +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) + +/** + * How long should our test-content live? + */ +#define LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) + +struct PeerContext +{ + struct GNUNET_CONFIGURATION_Handle *cfg; + struct GNUNET_PeerIdentity id; +#if START_ARM + struct GNUNET_OS_Process *arm_proc; +#endif +}; + +static struct PeerContext p1; + +static struct GNUNET_TIME_Absolute start; + +static struct GNUNET_FS_Handle *fs; + +static struct GNUNET_FS_SearchContext *search; + +static struct GNUNET_FS_PublishContext *publish; + + +static void +abort_publish_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_FS_publish_stop (publish); + publish = NULL; +} + + +static void +abort_search_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (search != NULL) + GNUNET_FS_search_stop (search); + search = NULL; +} + + +static void * +progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event) +{ + const char *keywords[] = { + "down_foo" + }; + struct GNUNET_FS_Uri *kuri; + + switch (event->status) + { + case GNUNET_FS_STATUS_PUBLISH_PROGRESS: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Publish is progressing (%llu/%llu at level %u off %llu)...\n", + (unsigned long long) event->value.publish.completed, + (unsigned long long) event->value.publish.size, + event->value.publish.specifics.progress.depth, + (unsigned long long) event->value.publish.specifics. + progress.offset); + break; + case GNUNET_FS_STATUS_PUBLISH_COMPLETED: + kuri = GNUNET_FS_uri_ksk_create_from_args (1, keywords); + start = GNUNET_TIME_absolute_get (); + search = + GNUNET_FS_search_start (fs, kuri, 1, GNUNET_FS_SEARCH_OPTION_NONE, + "search"); + GNUNET_FS_uri_destroy (kuri); + GNUNET_assert (search != NULL); + break; + case GNUNET_FS_STATUS_SEARCH_RESULT: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Search complete.\n"); + break; + case GNUNET_FS_STATUS_PUBLISH_ERROR: + FPRINTF (stderr, "Error publishing file: %s\n", + event->value.publish.specifics.error.message); + GNUNET_break (0); + GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); + break; + case GNUNET_FS_STATUS_SEARCH_ERROR: + FPRINTF (stderr, "Error searching file: %s\n", + event->value.search.specifics.error.message); + GNUNET_SCHEDULER_add_continuation (&abort_search_task, NULL, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); + break; + case GNUNET_FS_STATUS_PUBLISH_START: + GNUNET_assert (0 == strcmp ("publish-context", event->value.publish.cctx)); + GNUNET_assert (NULL == event->value.publish.pctx); + GNUNET_assert (FILESIZE == event->value.publish.size); + GNUNET_assert (0 == event->value.publish.completed); + GNUNET_assert (1 == event->value.publish.anonymity); + break; + case GNUNET_FS_STATUS_PUBLISH_STOPPED: + GNUNET_assert (publish == event->value.publish.pc); + GNUNET_assert (FILESIZE == event->value.publish.size); + GNUNET_assert (1 == event->value.publish.anonymity); + GNUNET_FS_stop (fs); + fs = NULL; + break; + case GNUNET_FS_STATUS_SEARCH_UPDATE: + GNUNET_assert (0 < event->value.search.specifics.update.availability_rank); + GNUNET_assert (0 < event->value.search.specifics.update.availability_certainty); + GNUNET_SCHEDULER_add_now (&abort_search_task, NULL); + break; + case GNUNET_FS_STATUS_SEARCH_START: + GNUNET_assert (search == NULL); + GNUNET_assert (0 == strcmp ("search", event->value.search.cctx)); + GNUNET_assert (1 == event->value.search.anonymity); + break; + case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED: + break; + case GNUNET_FS_STATUS_SEARCH_STOPPED: + GNUNET_assert (search == event->value.search.sc); + GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); + break; + default: + FPRINTF (stderr, "Unexpected event: %d\n", event->status); + break; + } + return NULL; +} + + +static void +setup_peer (struct PeerContext *p, const char *cfgname) +{ + p->cfg = GNUNET_CONFIGURATION_create (); +#if START_ARM + p->arm_proc = + GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", + "gnunet-service-arm", + "-c", cfgname, NULL); +#endif + GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); +} + + +static void +stop_arm (struct PeerContext *p) +{ +#if START_ARM + if (NULL != p->arm_proc) + { + if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + if (GNUNET_OS_process_wait (p->arm_proc) != GNUNET_OK) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", + GNUNET_OS_process_get_pid (p->arm_proc)); + GNUNET_OS_process_destroy (p->arm_proc); + p->arm_proc = NULL; + } +#endif + GNUNET_CONFIGURATION_destroy (p->cfg); +} + + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + const char *keywords[] = { + "down_foo", + "down_bar" + }; + char *buf; + struct GNUNET_CONTAINER_MetaData *meta; + struct GNUNET_FS_Uri *kuri; + struct GNUNET_FS_BlockOptions bo; + struct GNUNET_FS_FileInformation *fi; + size_t i; + + setup_peer (&p1, "test_fs_search_data.conf"); + fs = GNUNET_FS_start (cfg, "test-fs-search", &progress_cb, NULL, + GNUNET_FS_FLAGS_DO_PROBES, + GNUNET_FS_OPTIONS_END); + GNUNET_assert (NULL != fs); + buf = GNUNET_malloc (FILESIZE); + for (i = 0; i < FILESIZE; i++) + buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); + meta = GNUNET_CONTAINER_meta_data_create (); + kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords); + bo.content_priority = 42; + bo.anonymity_level = 1; + bo.replication_level = 0; + bo.expiration_time = GNUNET_TIME_relative_to_absolute (LIFETIME); + fi = GNUNET_FS_file_information_create_from_data (fs, "publish-context", + FILESIZE, buf, kuri, meta, + GNUNET_NO, &bo); + GNUNET_FS_uri_destroy (kuri); + GNUNET_CONTAINER_meta_data_destroy (meta); + GNUNET_assert (NULL != fi); + start = GNUNET_TIME_absolute_get (); + publish = + GNUNET_FS_publish_start (fs, fi, NULL, NULL, NULL, + GNUNET_FS_PUBLISH_OPTION_NONE); + GNUNET_assert (publish != NULL); +} + + +int +main (int argc, char *argv[]) +{ + char *const argvx[] = { + "test-fs-search-probes", + "-c", + "test_fs_search_data.conf", + NULL + }; + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + GNUNET_log_setup ("test_fs_search_probes", + "WARNING", + NULL); + GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, argvx, + "test-fs-search", "nohelp", options, &run, NULL); + stop_arm (&p1); + GNUNET_DISK_directory_remove ("/tmp/gnunet-test-fs-search/"); + return 0; +} + +/* end of test_fs_search_probes.c */ diff --git a/src/fs/test_fs_start_stop.c b/src/fs/test_fs_start_stop.c index 0ef0723..6bd698a 100644 --- a/src/fs/test_fs_start_stop.c +++ b/src/fs/test_fs_start_stop.c @@ -80,7 +80,7 @@ stop_arm (struct PeerContext *p) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); - GNUNET_OS_process_close (p->arm_proc); + GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; } #endif diff --git a/src/fs/test_fs_test_lib.c b/src/fs/test_fs_test_lib.c index 589abb3..29d5fe4 100644 --- a/src/fs/test_fs_test_lib.c +++ b/src/fs/test_fs_test_lib.c @@ -138,9 +138,6 @@ main (int argc, char *argv[]) "test-fs-test-lib", "-c", "fs_test_lib_data.conf", -#if VERBOSE - "-L", "DEBUG", -#endif NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { @@ -149,11 +146,7 @@ main (int argc, char *argv[]) GNUNET_DISK_directory_remove ("/tmp/gnunet-test-fs-lib/"); GNUNET_log_setup ("test_fs_test_lib", -#if VERBOSE - "DEBUG", -#else "WARNING", -#endif NULL); GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, argvx, "test-fs-test-lib", "nohelp", options, &run, NULL); diff --git a/src/fs/test_fs_unindex.c b/src/fs/test_fs_unindex.c index a8b68a3..ee76bf9 100644 --- a/src/fs/test_fs_unindex.c +++ b/src/fs/test_fs_unindex.c @@ -210,7 +210,7 @@ stop_arm (struct PeerContext *p) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); - GNUNET_OS_process_close (p->arm_proc); + GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; } #endif diff --git a/src/fs/test_fs_unindex_persistence.c b/src/fs/test_fs_unindex_persistence.c index 575e171..c6b1062 100644 --- a/src/fs/test_fs_unindex_persistence.c +++ b/src/fs/test_fs_unindex_persistence.c @@ -272,7 +272,7 @@ stop_arm (struct PeerContext *p) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); - GNUNET_OS_process_close (p->arm_proc); + GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; } #endif diff --git a/src/fs/test_gnunet_fs_idx.py.in b/src/fs/test_gnunet_fs_idx.py.in index 6bb7d0d..6bb7d0d 100755..100644 --- a/src/fs/test_gnunet_fs_idx.py.in +++ b/src/fs/test_gnunet_fs_idx.py.in diff --git a/src/fs/test_gnunet_fs_ns.py.in b/src/fs/test_gnunet_fs_ns.py.in index ff892b4..ff892b4 100755..100644 --- a/src/fs/test_gnunet_fs_ns.py.in +++ b/src/fs/test_gnunet_fs_ns.py.in diff --git a/src/fs/test_gnunet_fs_psd.py.in b/src/fs/test_gnunet_fs_psd.py.in index 9790e13..9790e13 100755..100644 --- a/src/fs/test_gnunet_fs_psd.py.in +++ b/src/fs/test_gnunet_fs_psd.py.in diff --git a/src/fs/test_gnunet_fs_rec.py.in b/src/fs/test_gnunet_fs_rec.py.in index e86bb0a..e86bb0a 100755..100644 --- a/src/fs/test_gnunet_fs_rec.py.in +++ b/src/fs/test_gnunet_fs_rec.py.in diff --git a/src/fs/test_gnunet_service_fs_migration.c b/src/fs/test_gnunet_service_fs_migration.c index 8b85e5e..00aab4f 100644 --- a/src/fs/test_gnunet_service_fs_migration.c +++ b/src/fs/test_gnunet_service_fs_migration.c @@ -66,7 +66,7 @@ do_stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) cc = NULL; } GNUNET_FS_TEST_daemons_stop (2, daemons); - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) + if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) { del = GNUNET_TIME_absolute_get_duration (start_time); if (del.rel_value == 0) @@ -146,7 +146,7 @@ static void do_publish (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cc = NULL; - if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) { GNUNET_FS_TEST_daemons_stop (2, daemons); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, diff --git a/src/fs/test_gnunet_service_fs_p2p.c b/src/fs/test_gnunet_service_fs_p2p.c index a853897..7ca786e 100644 --- a/src/fs/test_gnunet_service_fs_p2p.c +++ b/src/fs/test_gnunet_service_fs_p2p.c @@ -62,7 +62,7 @@ do_stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) cc = NULL; } GNUNET_FS_TEST_daemons_stop (NUM_DAEMONS, daemons); - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) + if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) { del = GNUNET_TIME_absolute_get_duration (start_time); if (del.rel_value == 0) |