From 70e446850e82317805db0a2f1508e3edc81b6a7f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 29 Aug 2009 20:58:34 +0000 Subject: [PATCH] more --- src/fs/fs.h | 11 +++ src/fs/fs_file_information.c | 1 + src/fs/fs_publish.c | 136 +++++++++++++++++++++++++++++++- src/include/gnunet_fs_service.h | 24 +++++- src/util/time.c | 2 +- 5 files changed, 166 insertions(+), 8 deletions(-) diff --git a/src/fs/fs.h b/src/fs/fs.h index 3c92b42ae..3f1ffad30 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h @@ -219,6 +219,11 @@ struct GNUNET_FS_FileInformation */ struct GNUNET_TIME_Absolute expirationTime; + /** + * At what time did we start this upload? + */ + struct GNUNET_TIME_Absolute start_time; + /** * Under what filename is this struct serialized * (for operational persistence). @@ -237,6 +242,12 @@ struct GNUNET_FS_FileInformation * finally freed once the upload is complete. */ struct ContentHashKey *chk_tree; + + /** + * Error message (non-NULL if this operation + * failed). + */ + char *emsg; /** * Number of entries in "chk_tree". diff --git a/src/fs/fs_file_information.c b/src/fs/fs_file_information.c index 60bcc2529..e72f42f9a 100644 --- a/src/fs/fs_file_information.c +++ b/src/fs/fs_file_information.c @@ -822,6 +822,7 @@ GNUNET_FS_file_information_destroy (struct GNUNET_FS_FileInformation *fi, &fi->expirationTime, &fi->client_info); } + GNUNET_free_non_null (fi->emsg); GNUNET_free_non_null (fi->chk_tree); /* clean up serialization */ if (0 != UNLINK (fi->serialization)) diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c index f5c2b4cdc..eae97b1d8 100644 --- a/src/fs/fs_publish.c +++ b/src/fs/fs_publish.c @@ -76,6 +76,38 @@ struct PutContCtx GNUNET_SCHEDULER_Task cont; }; + +/** + * Fill in all of the generic fields for + * a publish event. + * + * @param pc structure to fill in + * @param sc overall publishing context + * @param p file information for the file being published + */ +static void +make_publish_status (struct GNUNET_FS_ProgressInfo *pi, + struct GNUNET_FS_PublishContext *sc, + const struct GNUNET_FS_FileInformation *p) +{ + pi->value.publish.sc = sc; + pi->value.publish.fi = p; + pi->value.publish.cctx + = p->client_info; + pi->value.publish.pctx + = (NULL == p->dir) ? NULL : p->dir->client_info; + pi->value.publish.size + = (p->is_directory) ? p->data.dir.dir_size : p->data.file.file_size; + pi->value.publish.eta + = GNUNET_TIME_calculate_eta (p->start_time, + p->publish_offset, + pi->value.publish.size); + pi->value.publish.duration = GNUNET_TIME_absolute_get_duration (p->start_time); + pi->value.publish.completed = p->publish_offset; + pi->value.publish.anonymity = p->anonymity; +} + + /** * Function called by the datastore API with * the result from the PUT request. @@ -90,12 +122,20 @@ ds_put_cont (void *cls, const char *msg) { struct PutContCtx *pcc = cls; + struct GNUNET_FS_ProgressInfo pi; if (GNUNET_OK != success) { - // FIXME: call progress CB with error - // FIXME: update pcc->p to indicate abort + GNUNET_asprintf (&pcc->p->emsg, + _("Upload failed: %s"), + msg); GNUNET_FS_file_information_sync (pcc->p); + pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR; + make_publish_status (&pi, pcc->sc, pcc->p); + pi.value.publish.eta = GNUNET_TIME_UNIT_FOREVER_REL; + pi.value.publish.specifics.error.message = pcc->p->emsg; + pcc->sc->h->upcb (pcc->sc->h->upcb_cls, + &pi); return; } GNUNET_FS_file_information_sync (pcc->p); @@ -158,6 +198,29 @@ publish_block (struct GNUNET_FS_PublishContext *sc, } +/** + * Generate the callback that signals clients + * that a file (or directory) has been completely + * published. + * + * @param p the completed upload + * @param sc context of the publication + */ +static void +signal_publish_completion (struct GNUNET_FS_FileInformation *p, + struct GNUNET_FS_PublishContext *sc) +{ + struct GNUNET_FS_ProgressInfo pi; + + pi.status = GNUNET_FS_STATUS_PUBLISH_COMPLETED; + make_publish_status (&pi, sc, p); + pi.value.publish.eta = GNUNET_TIME_UNIT_ZERO; + pi.value.publish.specifics.completed.chk_uri = p->chk_uri; + sc->h->upcb (sc->h->upcb_cls, + &pi); +} + + /** * We are almost done publishing the structure, * add SBlocks (if needed). @@ -175,6 +238,8 @@ publish_sblock (struct GNUNET_FS_PublishContext *sc) // FIXME: continuation should // be releasing the datastore reserve // (once implemented) + // FIXME: finally, signal overall completion + signal_publish_completion (p, sc); } @@ -194,6 +259,12 @@ publish_kblocks (struct GNUNET_FS_PublishContext *sc, { // FIXME: build all kblocks // call publish_kblock on each + + + GNUNET_FS_file_information_sync (p); + if (NULL != p->dir) + signal_publish_completion (p, sc); + // last continuation should then call the main continuation again } @@ -306,6 +377,7 @@ static void publish_content (struct GNUNET_FS_PublishContext *sc, struct GNUNET_FS_FileInformation *p) { + struct GNUNET_FS_ProgressInfo pi; struct ContentHashKey *mychk; const void *pt_block; uint16_t pt_size; @@ -397,8 +469,27 @@ publish_content (struct GNUNET_FS_PublishContext *sc, iob, &emsg)) { - // FIXME: abort with error "emsg" + GNUNET_asprintf (&p->emsg, + _("Upload failed: %s"), + emsg); GNUNET_free (emsg); + GNUNET_FS_file_information_sync (p); + pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR; + make_publish_status (&pi, sc, p); + pi.value.publish.eta = GNUNET_TIME_UNIT_FOREVER_REL; + pi.value.publish.specifics.error.message = p->emsg; + sc->h->upcb (sc->h->upcb_cls, + &pi); + /* continue with main (to propagate error up) */ + sc->upload_task + = GNUNET_SCHEDULER_add_delayed (sc->h->sched, + GNUNET_NO, + GNUNET_SCHEDULER_PRIORITY_BACKGROUND, + GNUNET_SCHEDULER_NO_TASK, + GNUNET_TIME_UNIT_ZERO, + &do_upload, + sc); + return; } pt_block = iob; } @@ -432,7 +523,16 @@ publish_content (struct GNUNET_FS_PublishContext *sc, ? GNUNET_DATASTORE_BLOCKTYPE_DBLOCK : GNUNET_DATASTORE_BLOCKTYPE_IBLOCK, &do_upload); - // FIXME: should call progress function somewhere here! + if (p->current_depth == p->chk_tree_depth) + { + pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS; + make_publish_status (&pi, sc, p); + pi.value.publish.specifics.progress.data = pt_block; + pi.value.publish.specifics.progress.offset = p->publish_offset; + pi.value.publish.specifics.progress.data_len = pt_size; + sc->h->upcb (sc->h->upcb_cls, + &pi); + } GNUNET_CRYPTO_hash (enc, pt_size, &mychk->query); if (p->current_depth == p->chk_tree_depth) { @@ -471,7 +571,9 @@ do_upload (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_PublishContext *sc = cls; + struct GNUNET_FS_ProgressInfo pi; struct GNUNET_FS_FileInformation *p; + char *fn; sc->upload_task = GNUNET_SCHEDULER_NO_TASK; p = sc->fi_pos; @@ -482,6 +584,29 @@ do_upload (void *cls, publish_sblock (sc); return; } + if (NULL != p->emsg) + { + /* error with current file, abort all + related files as well! */ + while (NULL != p->dir) + { + fn = GNUNET_CONTAINER_meta_data_get_by_type (p->meta, + EXTRACTOR_FILENAME); + p = p->dir; + GNUNET_asprintf (&p->emsg, + _("Recursive upload failed at `%s'"), + fn); + GNUNET_free (fn); + GNUNET_FS_file_information_sync (p); + pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR; + make_publish_status (&pi, sc, p); + pi.value.publish.eta = GNUNET_TIME_UNIT_FOREVER_REL; + pi.value.publish.specifics.error.message = p->emsg; + sc->h->upcb (sc->h->upcb_cls, + &pi); + } + return; + } if (NULL != p->chk_uri) { /* move on to next file */ @@ -551,6 +676,9 @@ GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h, } // FIXME: make upload persistent! + /* signal start */ + + /* find first leaf, DFS */ p = ret->fi; while ( (p->is_directory) && diff --git a/src/include/gnunet_fs_service.h b/src/include/gnunet_fs_service.h index f78ed51e5..6e18e67c8 100644 --- a/src/include/gnunet_fs_service.h +++ b/src/include/gnunet_fs_service.h @@ -726,7 +726,7 @@ struct GNUNET_FS_ProgressInfo * (will be a value in the past for completed * uploads). */ - struct GNUNET_TIME_Absolute eta; + struct GNUNET_TIME_Relative eta; /** * How long has this upload been actively running @@ -782,9 +782,27 @@ struct GNUNET_FS_ProgressInfo * Error message, NULL if no error was encountered so far. */ const char *message; + + /** + * URI of the file (if the download had been completed) + */ + const struct GNUNET_FS_Uri *chk_uri; } resume; + /** + * These values are only valid for + * GNUNET_FS_STATUS_PUBLISH_COMPLETED events. + */ + struct { + + /** + * URI of the file. + */ + const struct GNUNET_FS_Uri *chk_uri; + + } completed; + /** * These values are only valid for * GNUNET_FS_STATUS_PUBLISH_ERROR events. @@ -844,7 +862,7 @@ struct GNUNET_FS_ProgressInfo * (will be a value in the past for completed * uploads). */ - struct GNUNET_TIME_Absolute eta; + struct GNUNET_TIME_Relative eta; /** * How long has this download been active? @@ -1256,7 +1274,7 @@ struct GNUNET_FS_ProgressInfo * (will be a value in the past for completed * unindexing opeations). */ - struct GNUNET_TIME_Absolute eta; + struct GNUNET_TIME_Relative eta; /** * How long has this upload been actively running diff --git a/src/util/time.c b/src/util/time.c index 6b6be7917..f818fc9a1 100644 --- a/src/util/time.c +++ b/src/util/time.c @@ -261,7 +261,7 @@ struct GNUNET_TIME_Relative GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolu if (finished >= total) return GNUNET_TIME_UNIT_ZERO; if (finished == 0) - return GNUNET_TIME_UNIT_FOREVER; + return GNUNET_TIME_UNIT_FOREVER_REL; dur = GNUNET_TIME_absolute_get_duration (start); exp = ((double)dur.value) * ((double) total) / ((double)finished); ret.value = ((uint64_t) exp) - dur.value; -- 2.25.1