From 539be627c009c2f13da19d6ae847168c1f5d496e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 8 Jan 2012 09:23:47 +0000 Subject: [PATCH] -LRN: my experimental block download time measurer. The results can be found there - [1]. [1] http://lrn.no-ip.info/other/gnunet_download_tie.log --- src/fs/fs.h | 36 ++++++++++++++++++++++++++++++++- src/fs/fs_api.h | 1 - src/fs/fs_download.c | 27 +++++++++++++++++++------ src/fs/fs_search.c | 8 ++++---- src/fs/gnunet-download.c | 13 +++++++++--- src/fs/gnunet-service-fs_cp.c | 1 + src/fs/gnunet-service-fs_lc.c | 9 ++++++--- src/fs/gnunet-service-fs_pe.c | 25 +++++++++++++++++++++++ src/fs/gnunet-service-fs_pe.h | 13 ++++++++++++ src/fs/gnunet-service-fs_pr.c | 14 ++++++++----- src/fs/gnunet-service-fs_pr.h | 3 +++ src/include/gnunet_fs_service.h | 6 ++++++ 12 files changed, 133 insertions(+), 23 deletions(-) diff --git a/src/fs/fs.h b/src/fs/fs.h index cd39522bc..059b8920d 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h @@ -267,7 +267,7 @@ struct SearchMessage * Response from FS service with a result for a previous FS search. * Note that queries for DBLOCKS and IBLOCKS that have received a * single response are considered done. This message is transmitted - * between peers as well as between the service and a client. + * between peers. */ struct PutMessage { @@ -289,6 +289,40 @@ struct PutMessage /* this is followed by the actual encrypted content */ +}; + +/** + * Response from FS service with a result for a previous FS search. + * Note that queries for DBLOCKS and IBLOCKS that have received a + * single response are considered done. This message is transmitted + * between the service and a client. + */ +struct ClientPutMessage +{ + + /** + * Message type will be GNUNET_MESSAGE_TYPE_FS_PUT. + */ + struct GNUNET_MessageHeader header; + + /** + * Type of the block (in big endian). Should never be zero. + */ + uint32_t type GNUNET_PACKED; + + /** + * When does this result expire? + */ + struct GNUNET_TIME_AbsoluteNBO expiration; + + /** + * When was the last time we've tried to download this block? + * (FOREVER if unknown/not relevant) + */ + struct GNUNET_TIME_AbsoluteNBO last_transmission; + + /* this is followed by the actual encrypted content */ + }; GNUNET_NETWORK_STRUCT_END diff --git a/src/fs/fs_api.h b/src/fs/fs_api.h index 66ccda1f2..4f3781d01 100644 --- a/src/fs/fs_api.h +++ b/src/fs/fs_api.h @@ -1906,7 +1906,6 @@ struct GNUNET_FS_Namespace unsigned int nug_gen; }; - #endif /* end of fs_api.h */ diff --git a/src/fs/fs_download.c b/src/fs/fs_download.c index cc36cba1f..85ae3ae34 100644 --- a/src/fs/fs_download.c +++ b/src/fs/fs_download.c @@ -118,6 +118,7 @@ GNUNET_FS_download_make_status_ (struct GNUNET_FS_ProgressInfo *pi, pi->value.download.uri = dc->uri; pi->value.download.filename = dc->filename; pi->value.download.size = dc->length; + /* FIXME: Fix duration calculation to account for pauses */ pi->value.download.duration = GNUNET_TIME_absolute_get_duration (dc->start_time); pi->value.download.completed = dc->completed; @@ -183,6 +184,8 @@ struct ProcessResultClosure */ int do_store; + struct GNUNET_TIME_Absolute last_transmission; + }; @@ -251,6 +254,7 @@ encrypt_existing_match (struct GNUNET_FS_DownloadContext *dc, dr->depth) ? GNUNET_BLOCK_TYPE_FS_DBLOCK : GNUNET_BLOCK_TYPE_FS_IBLOCK; prc.query = chk->query; prc.do_store = do_store; + prc.last_transmission = GNUNET_TIME_UNIT_FOREVER_ABS; process_result_with_request (&prc, &chk->key, dr); return GNUNET_OK; } @@ -1072,6 +1076,12 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, pi.value.download.specifics.progress.data_len = prc->size; 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); + else + pi.value.download.specifics.progress.block_download_duration.rel_value = + GNUNET_TIME_UNIT_FOREVER_REL.rel_value; GNUNET_FS_download_make_status_ (&pi, dc); GNUNET_assert (dc->completed <= dc->length); if (dr->depth == 0) @@ -1182,12 +1192,15 @@ signal_error: * * @param dc our download context * @param type type of the result + * @param last_transmission when was this block requested the last time? (FOREVER if unknown/not applicable) * @param data the (encrypted) response * @param size size of data */ static void process_result (struct GNUNET_FS_DownloadContext *dc, - enum GNUNET_BLOCK_Type type, const void *data, size_t size) + enum GNUNET_BLOCK_Type type, + struct GNUNET_TIME_Absolute last_transmission, + const void *data, size_t size) { struct ProcessResultClosure prc; @@ -1196,6 +1209,7 @@ process_result (struct GNUNET_FS_DownloadContext *dc, prc.size = size; prc.type = type; prc.do_store = GNUNET_YES; + prc.last_transmission = last_transmission; GNUNET_CRYPTO_hash (data, size, &prc.query); #if DEBUG_DOWNLOAD GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -1219,20 +1233,21 @@ static void receive_results (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_FS_DownloadContext *dc = cls; - const struct PutMessage *cm; + const struct ClientPutMessage *cm; uint16_t msize; if ((NULL == msg) || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_FS_PUT) || - (sizeof (struct PutMessage) > ntohs (msg->size))) + (sizeof (struct ClientPutMessage) > ntohs (msg->size))) { GNUNET_break (msg == NULL); try_reconnect (dc); return; } msize = ntohs (msg->size); - cm = (const struct PutMessage *) msg; - process_result (dc, ntohl (cm->type), &cm[1], - msize - sizeof (struct PutMessage)); + cm = (const struct ClientPutMessage *) msg; + process_result (dc, ntohl (cm->type), + GNUNET_TIME_absolute_ntoh (cm->last_transmission), &cm[1], + msize - sizeof (struct ClientPutMessage)); if (dc->client == NULL) return; /* fatal error */ /* continue receiving */ diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c index 55db586b0..03b4a7dfd 100644 --- a/src/fs/fs_search.c +++ b/src/fs/fs_search.c @@ -835,11 +835,11 @@ static void receive_results (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_FS_SearchContext *sc = cls; - const struct PutMessage *cm; + const struct ClientPutMessage *cm; uint16_t msize; if ((NULL == msg) || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_FS_PUT) || - (ntohs (msg->size) <= sizeof (struct PutMessage))) + (ntohs (msg->size) <= sizeof (struct ClientPutMessage))) { try_reconnect (sc); return; @@ -847,10 +847,10 @@ receive_results (void *cls, const struct GNUNET_MessageHeader *msg) msize = ntohs (msg->size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving %u bytes of result from fs service\n", msize); - cm = (const struct PutMessage *) msg; + cm = (const struct ClientPutMessage *) msg; process_result (sc, ntohl (cm->type), GNUNET_TIME_absolute_ntoh (cm->expiration), &cm[1], - msize - sizeof (struct PutMessage)); + msize - sizeof (struct ClientPutMessage)); /* continue receiving */ GNUNET_CLIENT_receive (sc->client, &receive_results, sc, GNUNET_TIME_UNIT_FOREVER_REL); diff --git a/src/fs/gnunet-download.c b/src/fs/gnunet-download.c index b6c67ce27..ff10c39c6 100644 --- a/src/fs/gnunet-download.c +++ b/src/fs/gnunet-download.c @@ -90,7 +90,7 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) { - char *s; + char *s, *s2; char *t; switch (info->status) @@ -104,16 +104,23 @@ progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) if (verbose) { s = GNUNET_STRINGS_relative_time_to_string (info->value.download.eta); + if (info->value.download.specifics.progress.block_download_duration.rel_value + == GNUNET_TIME_UNIT_FOREVER_REL.rel_value) + s2 = GNUNET_strdup (_("")); + else + s2 = GNUNET_STRINGS_relative_time_to_string ( + info->value.download.specifics.progress.block_download_duration); t = GNUNET_STRINGS_byte_size_fancy (info->value.download.completed * 1000LL / (info->value.download. duration.rel_value + 1)); FPRINTF (stdout, - _("Downloading `%s' at %llu/%llu (%s remaining, %s/s)\n"), + _("Downloading `%s' at %llu/%llu (%s remaining, %s/s). Block took %s to download\n"), info->value.download.filename, (unsigned long long) info->value.download.completed, - (unsigned long long) info->value.download.size, s, t); + (unsigned long long) info->value.download.size, s, t, s2); GNUNET_free (s); + GNUNET_free (s2); GNUNET_free (t); } break; diff --git a/src/fs/gnunet-service-fs_cp.c b/src/fs/gnunet-service-fs_cp.c index 4711c09e6..ba6a8ce87 100644 --- a/src/fs/gnunet-service-fs_cp.c +++ b/src/fs/gnunet-service-fs_cp.c @@ -883,6 +883,7 @@ static void handle_p2p_reply (void *cls, enum GNUNET_BLOCK_EvaluationResult eval, struct GSF_PendingRequest *pr, uint32_t reply_anonymity_level, struct GNUNET_TIME_Absolute expiration, + struct GNUNET_TIME_Absolute last_transmission, enum GNUNET_BLOCK_Type type, const void *data, size_t data_len) { diff --git a/src/fs/gnunet-service-fs_lc.c b/src/fs/gnunet-service-fs_lc.c index d8f7d5cb3..6eb054acd 100644 --- a/src/fs/gnunet-service-fs_lc.c +++ b/src/fs/gnunet-service-fs_lc.c @@ -218,6 +218,7 @@ client_request_destroy (void *cls, * @param pr handle to the original pending request * @param reply_anonymity_level anonymity level for the reply, UINT32_MAX for "unknown" * @param expiration when does 'data' expire? + * @param last_transmission when was the last time we've tried to download this block? (FOREVER if unknown) * @param type type of the block * @param data response data, NULL on request expiration * @param data_len number of bytes in data @@ -227,12 +228,13 @@ client_response_handler (void *cls, enum GNUNET_BLOCK_EvaluationResult eval, struct GSF_PendingRequest *pr, uint32_t reply_anonymity_level, struct GNUNET_TIME_Absolute expiration, + struct GNUNET_TIME_Absolute last_transmission, enum GNUNET_BLOCK_Type type, const void *data, size_t data_len) { struct ClientRequest *cr = cls; struct GSF_LocalClient *lc; - struct PutMessage *pm; + struct ClientPutMessage *pm; const struct GSF_PendingRequestData *prd; size_t msize; @@ -255,15 +257,16 @@ client_response_handler (void *cls, enum GNUNET_BLOCK_EvaluationResult eval, GNUNET_NO); GNUNET_assert (pr == cr->pr); lc = cr->lc; - msize = sizeof (struct PutMessage) + data_len; + msize = sizeof (struct ClientPutMessage) + data_len; { char buf[msize]; - pm = (struct PutMessage *) buf; + pm = (struct ClientPutMessage *) buf; pm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_PUT); pm->header.size = htons (msize); pm->type = htonl (type); pm->expiration = GNUNET_TIME_absolute_hton (expiration); + pm->last_transmission = GNUNET_TIME_absolute_hton (last_transmission); memcpy (&pm[1], data, data_len); GSF_local_client_transmit_ (lc, &pm->header); } diff --git a/src/fs/gnunet-service-fs_pe.c b/src/fs/gnunet-service-fs_pe.c index 0a40065cc..78769fa82 100644 --- a/src/fs/gnunet-service-fs_pe.c +++ b/src/fs/gnunet-service-fs_pe.c @@ -699,6 +699,31 @@ GSF_plan_notify_peer_disconnect_ (const struct GSF_ConnectedPeer *cp) GNUNET_free (pp); } +/** + * Get the last transmission attempt time for the request plan list + * referenced by @rpr_head, that was sent to @sender + * + * @param rpr_head request plan reference list to check. + * @param sender the peer that we've sent the request to. + * @param result the timestamp to fill. + * @return GNUNET_YES if @result was changed, GNUNET_NO otherwise. + */ +int +GSF_request_plan_reference_get_last_transmission_ ( + struct GSF_RequestPlanReference *rpr_head, struct GSF_ConnectedPeer *sender, + struct GNUNET_TIME_Absolute *result) +{ + struct GSF_RequestPlanReference *rpr; + for (rpr = rpr_head; rpr; rpr = rpr->next) + { + if (rpr->rp->pp->cp == sender) + { + *result = rpr->rp->last_transmission; + return GNUNET_YES; + } + } + return GNUNET_NO; +} /** * Notify the plan about a request being done; destroy all entries diff --git a/src/fs/gnunet-service-fs_pe.h b/src/fs/gnunet-service-fs_pe.h index 3ae9904a6..da20a7d7b 100644 --- a/src/fs/gnunet-service-fs_pe.h +++ b/src/fs/gnunet-service-fs_pe.h @@ -58,6 +58,19 @@ GSF_plan_notify_peer_disconnect_ (const struct GSF_ConnectedPeer *cp); void GSF_plan_notify_request_done_ (struct GSF_PendingRequest *pr); +/** + * Get the last transmission attempt time for the request plan list + * referenced by @rpr_head, that was sent to @sender + * + * @param rpr_head request plan reference list to check. + * @param sender the peer that we've sent the request to. + * @param result the timestamp to fill. + * @return GNUNET_YES if @result was changed, GNUNET_NO otherwise. + */ +int +GSF_request_plan_reference_get_last_transmission_ ( + struct GSF_RequestPlanReference *rpr_head, struct GSF_ConnectedPeer *sender, + struct GNUNET_TIME_Absolute *result); /** * Initialize plan subsystem. diff --git a/src/fs/gnunet-service-fs_pr.c b/src/fs/gnunet-service-fs_pr.c index 5ba58c4b8..c16f94464 100644 --- a/src/fs/gnunet-service-fs_pr.c +++ b/src/fs/gnunet-service-fs_pr.c @@ -360,8 +360,8 @@ GSF_pending_request_create_ (enum GSF_PendingRequestOptions options, break; /* let the request live briefly... */ if (NULL != dpr->rh) dpr->rh (dpr->rh_cls, GNUNET_BLOCK_EVALUATION_REQUEST_VALID, dpr, - UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_BLOCK_TYPE_ANY, - NULL, 0); + UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, + GNUNET_BLOCK_TYPE_ANY, NULL, 0); GSF_pending_request_cancel_ (dpr, GNUNET_YES); } } @@ -371,7 +371,6 @@ GSF_pending_request_create_ (enum GSF_PendingRequestOptions options, return pr; } - /** * Obtain the public data associated with a pending request * @@ -775,6 +774,7 @@ process_reply (void *cls, const GNUNET_HashCode * key, void *value) struct ProcessReplyClosure *prq = cls; struct GSF_PendingRequest *pr = value; GNUNET_HashCode chash; + struct GNUNET_TIME_Absolute last_transmission; if (NULL == pr->rh) return GNUNET_YES; @@ -804,9 +804,11 @@ process_reply (void *cls, const GNUNET_HashCode * key, void *value) GNUNET_LOAD_update (GSF_rt_entry_lifetime, GNUNET_TIME_absolute_get_duration (pr-> public_data.start_time).rel_value); + if (!GSF_request_plan_reference_get_last_transmission_ (pr->public_data.rpr_head, prq->sender, &last_transmission)) + last_transmission.abs_value = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value; /* pass on to other peers / local clients */ pr->rh (pr->rh_cls, prq->eval, pr, prq->anonymity_level, prq->expiration, - prq->type, prq->data, prq->size); + last_transmission, prq->type, prq->data, prq->size); return GNUNET_YES; case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: GNUNET_STATISTICS_update (GSF_stats, @@ -855,8 +857,10 @@ process_reply (void *cls, const GNUNET_HashCode * key, void *value) pr->public_data.results_found++; prq->request_found = GNUNET_YES; /* finally, pass on to other peer / local client */ + if (!GSF_request_plan_reference_get_last_transmission_ (pr->public_data.rpr_head, prq->sender, &last_transmission)) + last_transmission.abs_value = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value; pr->rh (pr->rh_cls, prq->eval, pr, prq->anonymity_level, prq->expiration, - prq->type, prq->data, prq->size); + last_transmission, prq->type, prq->data, prq->size); return GNUNET_YES; } diff --git a/src/fs/gnunet-service-fs_pr.h b/src/fs/gnunet-service-fs_pr.h index f435cf8d6..92827f76b 100644 --- a/src/fs/gnunet-service-fs_pr.h +++ b/src/fs/gnunet-service-fs_pr.h @@ -174,6 +174,7 @@ struct GSF_PendingRequestData * @param pr handle to the original pending request * @param reply_anonymity_level anonymity level for the reply, UINT32_MAX for "unknown" * @param expiration when does 'data' expire? + * @param last_transmission the last time we've tried to get this block (FOREVER if unknown) * @param type type of the block * @param data response data, NULL on request expiration * @param data_len number of bytes in data @@ -186,6 +187,8 @@ typedef void (*GSF_PendingRequestReplyHandler) (void *cls, uint32_t reply_anonymity_level, struct GNUNET_TIME_Absolute expiration, + struct GNUNET_TIME_Absolute + last_transmission, enum GNUNET_BLOCK_Type type, const void *data, size_t data_len); diff --git a/src/include/gnunet_fs_service.h b/src/include/gnunet_fs_service.h index 4b1b1b199..34925d562 100644 --- a/src/include/gnunet_fs_service.h +++ b/src/include/gnunet_fs_service.h @@ -1027,6 +1027,12 @@ struct GNUNET_FS_ProgressInfo */ unsigned int trust_offered; + /** + * How much time passed between us asking for this block and + * actually getting it? GNUNET_TIME_UNIT_FOREVER_REL if unknown. + */ + struct GNUNET_TIME_Relative block_download_duration; + } progress; /** -- 2.25.1