From: Christian Grothoff Date: Thu, 6 May 2010 19:59:59 +0000 (+0000) Subject: allow file hashing cancellation -- and make use of it X-Git-Tag: initial-import-from-subversion-38251~21838 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=7db4f64461a77f19bb39f1b84d26f96e6acf40ab;p=oweals%2Fgnunet.git allow file hashing cancellation -- and make use of it --- diff --git a/src/fs/fs.c b/src/fs/fs.c index 31c8eee49..1968a8453 100644 --- a/src/fs/fs.c +++ b/src/fs/fs.c @@ -2058,12 +2058,12 @@ deserialize_unindex_file (void *cls, switch (uc->state) { case UNINDEX_STATE_HASHING: - GNUNET_CRYPTO_hash_file (uc->h->sched, - GNUNET_SCHEDULER_PRIORITY_IDLE, - uc->filename, - HASHING_BLOCKSIZE, - &GNUNET_FS_unindex_process_hash_, - uc); + uc->fhc = GNUNET_CRYPTO_hash_file (uc->h->sched, + GNUNET_SCHEDULER_PRIORITY_IDLE, + uc->filename, + HASHING_BLOCKSIZE, + &GNUNET_FS_unindex_process_hash_, + uc); break; case UNINDEX_STATE_FS_NOTIFY: uc->state = UNINDEX_STATE_HASHING; diff --git a/src/fs/fs.h b/src/fs/fs.h index d8e997324..bca8fc691 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h @@ -1407,6 +1407,11 @@ struct GNUNET_FS_UnindexContext */ char *emsg; + /** + * Context for hashing of the file. + */ + struct GNUNET_CRYPTO_FileHashContext *fhc; + /** * Overall size of the file. */ diff --git a/src/fs/fs_unindex.c b/src/fs/fs_unindex.c index 5989fd2c0..db0540607 100644 --- a/src/fs/fs_unindex.c +++ b/src/fs/fs_unindex.c @@ -365,6 +365,7 @@ GNUNET_FS_unindex_process_hash_ (void *cls, struct GNUNET_FS_UnindexContext *uc = cls; struct UnindexMessage req; + uc->fhc = NULL; if (uc->state != UNINDEX_STATE_HASHING) { GNUNET_FS_unindex_stop (uc); @@ -410,6 +411,11 @@ GNUNET_FS_unindex_signal_suspend_ (void *cls) struct GNUNET_FS_UnindexContext *uc = cls; struct GNUNET_FS_ProgressInfo pi; + if (uc->fhc != NULL) + { + GNUNET_CRYPTO_hash_file_cancel (uc->fhc); + uc->fhc = NULL; + } GNUNET_FS_end_top (uc->h, uc->top); pi.status = GNUNET_FS_STATUS_UNINDEX_SUSPEND; GNUNET_FS_unindex_make_status_ (&pi, uc, @@ -454,13 +460,12 @@ GNUNET_FS_unindex_start (struct GNUNET_FS_Handle *h, pi.status = GNUNET_FS_STATUS_UNINDEX_START; pi.value.unindex.eta = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_FS_unindex_make_status_ (&pi, ret, 0); - /* FIXME: must be able to abort hashing here! */ - GNUNET_CRYPTO_hash_file (h->sched, - GNUNET_SCHEDULER_PRIORITY_IDLE, - filename, - HASHING_BLOCKSIZE, - &GNUNET_FS_unindex_process_hash_, - ret); + ret->fhc = GNUNET_CRYPTO_hash_file (h->sched, + GNUNET_SCHEDULER_PRIORITY_IDLE, + filename, + HASHING_BLOCKSIZE, + &GNUNET_FS_unindex_process_hash_, + ret); ret->top = GNUNET_FS_make_top (h, &GNUNET_FS_unindex_signal_suspend_, ret); @@ -478,7 +483,11 @@ GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc) { struct GNUNET_FS_ProgressInfo pi; - /* FIXME: stop hashing (if still ongoing) */ + if (uc->fhc != NULL) + { + GNUNET_CRYPTO_hash_file_cancel (uc->fhc); + uc->fhc = NULL; + } /* FIXME: disconnect uc->client (if still connected) */ /* FIXME: disconnect from datastore (if still connected) */ /* FIXME: other termination operations? */ diff --git a/src/fs/gnunet-service-fs_indexing.c b/src/fs/gnunet-service-fs_indexing.c index a5ac0dda3..f8593ffd4 100644 --- a/src/fs/gnunet-service-fs_indexing.c +++ b/src/fs/gnunet-service-fs_indexing.c @@ -22,6 +22,11 @@ * @file fs/gnunet-service-fs_indexing.c * @brief program that provides indexing functions of the file-sharing service * @author Christian Grothoff + * + * TODO: + * - consider doing GNUNET_CRYPTO_hash_file_cancel on active indexing + * jobs during shutdown (currently, shutdown will only happen after + * all of those are done, not sure if this is good or bad) */ #include "platform.h" #include @@ -60,6 +65,11 @@ struct IndexInfo * NULL if we've done this already. */ struct GNUNET_SERVER_TransmitContext *tc; + + /** + * Context for hashing of the file. + */ + struct GNUNET_CRYPTO_FileHashContext *fhc; /** * Hash of the contents of the file. @@ -282,7 +292,8 @@ hash_for_index_val (void *cls, res) { struct IndexInfo *ii = cls; - + + ii->fhc = NULL; if ( (res == NULL) || (0 != memcmp (res, &ii->file_id, @@ -375,12 +386,14 @@ GNUNET_FS_handle_index_start (void *cls, (unsigned int) mydev); #endif /* slow validation, need to hash full file (again) */ - GNUNET_CRYPTO_hash_file (sched, - GNUNET_SCHEDULER_PRIORITY_IDLE, - fn, - HASHING_BLOCKSIZE, - &hash_for_index_val, - ii); + ii->fhc = GNUNET_CRYPTO_hash_file (sched, + GNUNET_SCHEDULER_PRIORITY_IDLE, + fn, + HASHING_BLOCKSIZE, + &hash_for_index_val, + ii); + if (ii->fhc == NULL) + hash_for_index_val (ii, NULL); GNUNET_free (fn); } diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index 1dc9cb1aa..e1eb0f28d 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h @@ -365,6 +365,11 @@ typedef void (*GNUNET_CRYPTO_HashCompletedCallback) (void *cls, res); +/** + * Handle to file hashing operation. + */ +struct GNUNET_CRYPTO_FileHashContext; + /** * Compute the hash of an entire file. * @@ -374,13 +379,24 @@ typedef void (*GNUNET_CRYPTO_HashCompletedCallback) (void *cls, * @param blocksize number of bytes to process in one task * @param callback function to call upon completion * @param callback_cls closure for callback + * @return NULL on (immediate) errror + */ +struct GNUNET_CRYPTO_FileHashContext * +GNUNET_CRYPTO_hash_file (struct GNUNET_SCHEDULER_Handle *sched, + enum GNUNET_SCHEDULER_Priority priority, + const char *filename, + size_t blocksize, + GNUNET_CRYPTO_HashCompletedCallback callback, + void *callback_cls); + + +/** + * Cancel a file hashing operation. + * + * @param fhc operation to cancel (callback must not yet have been invoked) */ -void GNUNET_CRYPTO_hash_file (struct GNUNET_SCHEDULER_Handle *sched, - enum GNUNET_SCHEDULER_Priority priority, - const char *filename, - size_t blocksize, - GNUNET_CRYPTO_HashCompletedCallback callback, - void *callback_cls); +void +GNUNET_CRYPTO_hash_file_cancel (struct GNUNET_CRYPTO_FileHashContext *fhc); /** diff --git a/src/transport/plugin_transport_http.c b/src/transport/plugin_transport_http.c index da3d03a19..c0de034ac 100644 --- a/src/transport/plugin_transport_http.c +++ b/src/transport/plugin_transport_http.c @@ -181,12 +181,14 @@ static char * get_url( const struct GNUNET_PeerIdentity * target) return strdup("http://localhost:12389"); } +#if 0 static size_t curl_read_function( void *ptr, size_t size, size_t nmemb, void *stream) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"curl read function\n"); // strcpy ("Testmessa") return 0; } +#endif /** * Task that is run when we are ready to receive more data from the hostlist diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c index dcee545f7..60104b604 100644 --- a/src/util/crypto_hash.c +++ b/src/util/crypto_hash.c @@ -372,7 +372,7 @@ GNUNET_CRYPTO_hash (const void *block, size_t size, GNUNET_HashCode * ret) /** * Context used when hashing a file. */ -struct FileHashContext +struct GNUNET_CRYPTO_FileHashContext { /** @@ -396,14 +396,19 @@ struct FileHashContext char *filename; /** - * Cummulated hash. + * File descriptor. */ - struct sha512_ctx hctx; + struct GNUNET_DISK_FileHandle *fh; /** - * Blocksize. + * Our scheduler. */ - size_t bsize; + struct GNUNET_SCHEDULER_Handle *sched; + + /** + * Cummulated hash. + */ + struct sha512_ctx hctx; /** * Size of the file. @@ -416,9 +421,14 @@ struct FileHashContext uint64_t offset; /** - * File descriptor. + * Current task for hashing. */ - struct GNUNET_DISK_FileHandle *fh; + GNUNET_SCHEDULER_TaskIdentifier task; + + /** + * Blocksize. + */ + size_t bsize; }; @@ -428,7 +438,8 @@ struct FileHashContext * and free associated resources. */ static void -file_hash_finish (struct FileHashContext *fhc, const GNUNET_HashCode * res) +file_hash_finish (struct GNUNET_CRYPTO_FileHashContext *fhc, + const GNUNET_HashCode * res) { fhc->callback (fhc->callback_cls, res); GNUNET_free (fhc->filename); @@ -447,10 +458,11 @@ file_hash_finish (struct FileHashContext *fhc, const GNUNET_HashCode * res) static void file_hash_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct FileHashContext *fhc = cls; + struct GNUNET_CRYPTO_FileHashContext *fhc = cls; GNUNET_HashCode res; size_t delta; + fhc->task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (fhc->offset < fhc->fsize); delta = fhc->bsize; if (fhc->fsize - fhc->offset < delta) @@ -470,8 +482,10 @@ file_hash_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) file_hash_finish (fhc, &res); return; } - GNUNET_SCHEDULER_add_after (tc->sched, - GNUNET_SCHEDULER_NO_TASK, &file_hash_task, fhc); + fhc->task + = GNUNET_SCHEDULER_add_after (tc->sched, + GNUNET_SCHEDULER_NO_TASK, + &file_hash_task, fhc); } @@ -484,8 +498,9 @@ file_hash_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * @param blocksize number of bytes to process in one task * @param callback function to call upon completion * @param callback_cls closure for callback + * @return NULL on (immediate) errror */ -void +struct GNUNET_CRYPTO_FileHashContext * GNUNET_CRYPTO_hash_file (struct GNUNET_SCHEDULER_Handle *sched, enum GNUNET_SCHEDULER_Priority priority, const char *filename, @@ -493,12 +508,13 @@ GNUNET_CRYPTO_hash_file (struct GNUNET_SCHEDULER_Handle *sched, GNUNET_CRYPTO_HashCompletedCallback callback, void *callback_cls) { - struct FileHashContext *fhc; + struct GNUNET_CRYPTO_FileHashContext *fhc; GNUNET_assert (blocksize > 0); - fhc = GNUNET_malloc (sizeof (struct FileHashContext) + blocksize); + fhc = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_FileHashContext) + blocksize); fhc->callback = callback; fhc->callback_cls = callback_cls; + fhc->sched = sched; fhc->buffer = (unsigned char *) &fhc[1]; fhc->filename = GNUNET_strdup (filename); fhc->fh = NULL; @@ -506,21 +522,43 @@ GNUNET_CRYPTO_hash_file (struct GNUNET_SCHEDULER_Handle *sched, fhc->bsize = blocksize; if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fhc->fsize, GNUNET_NO)) { - file_hash_finish (fhc, NULL); - return; + GNUNET_free (fhc->filename); + GNUNET_free (fhc); + return NULL; } fhc->fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (!fhc->fh) { - file_hash_finish (fhc, NULL); - return; + GNUNET_free (fhc->filename); + GNUNET_free (fhc); + return NULL; } - GNUNET_SCHEDULER_add_with_priority (sched, priority, &file_hash_task, fhc); + fhc->task + = GNUNET_SCHEDULER_add_with_priority (sched, priority, + &file_hash_task, fhc); + return fhc; +} + + +/** + * Cancel a file hashing operation. + * + * @param fhc operation to cancel (callback must not yet have been invoked) + */ +void +GNUNET_CRYPTO_hash_file_cancel (struct GNUNET_CRYPTO_FileHashContext *fhc) +{ + GNUNET_SCHEDULER_cancel (fhc->sched, + fhc->task); + GNUNET_free (fhc->filename); + GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fhc->fh)); + GNUNET_free (fhc); } + /* ***************** binary-ASCII encoding *************** */ /** diff --git a/src/util/test_crypto_hash.c b/src/util/test_crypto_hash.c index b650355c0..f793e3342 100644 --- a/src/util/test_crypto_hash.c +++ b/src/util/test_crypto_hash.c @@ -122,9 +122,11 @@ finished_task (void *cls, const GNUNET_HashCode * res) static void file_hasher (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - GNUNET_CRYPTO_hash_file (tc->sched, - GNUNET_SCHEDULER_PRIORITY_DEFAULT, - FILENAME, 1024, &finished_task, cls); + GNUNET_assert (NULL != + GNUNET_CRYPTO_hash_file (tc->sched, + GNUNET_SCHEDULER_PRIORITY_DEFAULT, + FILENAME, 1024, + &finished_task, cls)); }