-LRN: my experimental block download time measurer. The results
authorChristian Grothoff <christian@grothoff.org>
Sun, 8 Jan 2012 09:23:47 +0000 (09:23 +0000)
committerChristian Grothoff <christian@grothoff.org>
Sun, 8 Jan 2012 09:23:47 +0000 (09:23 +0000)
can be found there - [1].

[1] http://lrn.no-ip.info/other/gnunet_download_tie.log

12 files changed:
src/fs/fs.h
src/fs/fs_api.h
src/fs/fs_download.c
src/fs/fs_search.c
src/fs/gnunet-download.c
src/fs/gnunet-service-fs_cp.c
src/fs/gnunet-service-fs_lc.c
src/fs/gnunet-service-fs_pe.c
src/fs/gnunet-service-fs_pe.h
src/fs/gnunet-service-fs_pr.c
src/fs/gnunet-service-fs_pr.h
src/include/gnunet_fs_service.h

index cd39522bc8998cad23ae8bba66d206ddcf4fac9c..059b8920d248d01d16eb93a82b0f3c9622c2b2ea 100644 (file)
@@ -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
 
index 66ccda1f2c345e60d101f04398ae927b6ea6601f..4f3781d01049919b52501f70ecd83773d7288fb3 100644 (file)
@@ -1906,7 +1906,6 @@ struct GNUNET_FS_Namespace
   unsigned int nug_gen;
 };
 
-
 #endif
 
 /* end of fs_api.h */
index cc36cba1f29a701903a96b37a7f049e1de0aee06..85ae3ae349583bd4837572dfee9a0e5db72d03e6 100644 (file)
@@ -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 */
index 55db586b0ca6bf432a192308ca465751e211093c..03b4a7dfd181e9ff3b51d887878e953223c6bb37 100644 (file)
@@ -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);
index b6c67ce2709925eec5ee5d5e8f68579d34146977..ff10c39c667ce0a116e6898ad521217b781c6e78 100644 (file)
@@ -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 (_("<unknown time>"));
+      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;
index 4711c09e6137f94414fe8689b146912e33059044..ba6a8ce87054e16bec7ece14615b06120947114e 100644 (file)
@@ -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)
 {
index d8f7d5cb3ef51bbe5b5b251d8abcab5db0b88795..6eb054acd832e3375b6d2979149d78c7dce0617c 100644 (file)
@@ -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);
   }
index 0a40065ccfc6b4802526633b02e7b8b4d04dddb6..78769fa826d16a1f6e2c0036092fb40beea7d966 100644 (file)
@@ -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
index 3ae9904a63e66b2ed7851b1951f5332e146d83ec..da20a7d7b9ba5f977b1851d7cf9cea2425e4eb79 100644 (file)
@@ -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.
index 5ba58c4b8cdeb051ee0d23d25f7b08f97a57209a..c16f94464e5fd9f54d363de1ef005b366cd0a81d 100644 (file)
@@ -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;
 }
 
index f435cf8d677a9a6c2c59d02f04125e628fe8331c..92827f76bb053a9da6eb99e4665c6bf921d9f404 100644 (file)
@@ -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);
index 4b1b1b1993e5fec0190119eb534d2cdd3fff6cd6..34925d562aaceb76de3571efaba3175a1aa29c2d 100644 (file)
@@ -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;
 
         /**