[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r10462 - gnunet/src/fs
From: |
gnunet |
Subject: |
[GNUnet-SVN] r10462 - gnunet/src/fs |
Date: |
Mon, 1 Mar 2010 17:50:43 +0100 |
Author: grothoff
Date: 2010-03-01 17:50:43 +0100 (Mon, 01 Mar 2010)
New Revision: 10462
Modified:
gnunet/src/fs/fs_download.c
gnunet/src/fs/gnunet-service-fs.c
Log:
avoid tracking requests twice if multiple blocks in the same file are identical
Modified: gnunet/src/fs/fs_download.c
===================================================================
--- gnunet/src/fs/fs_download.c 2010-03-01 15:41:33 UTC (rev 10461)
+++ gnunet/src/fs/fs_download.c 2010-03-01 16:50:43 UTC (rev 10462)
@@ -303,51 +303,70 @@
/**
- * Process a download result.
+ * Closure for iterator processing results.
+ */
+struct ProcessResultClosure
+{
+
+ /**
+ * Hash of data.
+ */
+ GNUNET_HashCode query;
+
+ /**
+ * Data found in P2P network.
+ */
+ const void *data;
+
+ /**
+ * Our download context.
+ */
+ struct GNUNET_FS_DownloadContext *dc;
+
+ /**
+ * Number of bytes in data.
+ */
+ size_t size;
+
+ /**
+ * Type of data.
+ */
+ uint32_t type;
+
+};
+
+
+/**
+ * Iterator over entries in the pending requests in the 'active' map for the
+ * reply that we just got.
*
- * @param dc our download context
- * @param type type of the result
- * @param data the (encrypted) response
- * @param size size of data
+ * @param cls closure (our 'struct ProcessResultClosure')
+ * @param value value in the hash map (a 'struct DownloadRequest')
+ * @return GNUNET_YES (we should continue to iterate); unless serious error
*/
-static void
-process_result (struct GNUNET_FS_DownloadContext *dc,
- uint32_t type,
- const void *data,
- size_t size)
+static int
+process_result_with_request (void *cls,
+ const GNUNET_HashCode * key,
+ void *value)
{
- struct GNUNET_FS_ProgressInfo pi;
- GNUNET_HashCode query;
- struct DownloadRequest *sm;
+ struct ProcessResultClosure *prc = cls;
+ struct DownloadRequest *sm = value;
+ struct GNUNET_FS_DownloadContext *dc = prc->dc;
struct GNUNET_CRYPTO_AesSessionKey skey;
struct GNUNET_CRYPTO_AesInitializationVector iv;
- char pt[size];
+ char pt[prc->size];
+ struct GNUNET_FS_ProgressInfo pi;
uint64_t off;
size_t app;
int i;
struct ContentHashKey *chk;
char *emsg;
-
- GNUNET_CRYPTO_hash (data, size, &query);
-#if DEBUG_DOWNLOAD
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received result for query `%s' from `%s'-service\n",
- GNUNET_h2s (&query),
- "FS");
-#endif
- sm = GNUNET_CONTAINER_multihashmap_get (dc->active,
- &query);
- if (NULL == sm)
+ if (prc->size != calculate_block_size (GNUNET_ntohll
(dc->uri->data.chk.file_length),
+ dc->treedepth,
+ sm->offset,
+ sm->depth))
{
- GNUNET_break (0);
- return;
- }
- if (size != calculate_block_size (GNUNET_ntohll
(dc->uri->data.chk.file_length),
- dc->treedepth,
- sm->offset,
- sm->depth))
- {
#if DEBUG_DOWNLOAD
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Internal error or bogus download URI (expected %u bytes, got
%u)\n",
@@ -355,7 +374,7 @@
dc->treedepth,
sm->offset,
sm->depth),
- size);
+ prc->size);
#endif
dc->emsg = GNUNET_strdup ("Internal error or bogus download URI");
/* signal error */
@@ -372,15 +391,15 @@
}
GNUNET_CLIENT_disconnect (dc->client);
dc->client = NULL;
- return;
+ return GNUNET_NO;
}
GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multihashmap_remove (dc->active,
- &query,
+ &prc->query,
sm));
GNUNET_CRYPTO_hash_to_aes_key (&sm->chk.key, &skey, &iv);
- GNUNET_CRYPTO_aes_decrypt (data,
- size,
+ GNUNET_CRYPTO_aes_decrypt (prc->data,
+ prc->size,
&skey,
&iv,
pt);
@@ -408,13 +427,13 @@
(unsigned long long) off,
dc->filename,
STRERROR (errno));
- else if (size !=
+ else if (prc->size !=
GNUNET_DISK_file_write (dc->handle,
pt,
- size))
+ prc->size))
GNUNET_asprintf (&emsg,
_("Failed to write block of %u bytes at offset %llu in
file `%s': %s\n"),
- (unsigned int) size,
+ (unsigned int) prc->size,
(unsigned long long) off,
dc->filename,
STRERROR (errno));
@@ -439,12 +458,12 @@
GNUNET_CLIENT_disconnect (dc->client);
dc->client = NULL;
GNUNET_free (sm);
- return;
+ return GNUNET_NO;
}
}
if (sm->depth == dc->treedepth)
{
- app = size;
+ app = prc->size;
if (sm->offset < dc->offset)
{
/* starting offset begins in the middle of pt,
@@ -452,12 +471,12 @@
GNUNET_assert (app > (dc->offset - sm->offset));
app -= (dc->offset - sm->offset);
}
- if (sm->offset + size > dc->offset + dc->length)
+ if (sm->offset + prc->size > dc->offset + dc->length)
{
/* end of block is after relevant range,
do not count last bytes as progress */
- GNUNET_assert (app > (sm->offset + size) - (dc->offset + dc->length));
- app -= (sm->offset + size) - (dc->offset + dc->length);
+ GNUNET_assert (app > (sm->offset + prc->size) - (dc->offset +
dc->length));
+ app -= (sm->offset + prc->size) - (dc->offset + dc->length);
}
dc->completed += app;
}
@@ -466,7 +485,7 @@
make_download_status (&pi, dc);
pi.value.download.specifics.progress.data = pt;
pi.value.download.specifics.progress.offset = sm->offset;
- pi.value.download.specifics.progress.data_len = size;
+ pi.value.download.specifics.progress.data_len = prc->size;
pi.value.download.specifics.progress.depth = sm->depth;
dc->client_info = dc->h->upcb (dc->h->upcb_cls,
&pi);
@@ -500,7 +519,7 @@
if (sm->depth == dc->treedepth)
{
GNUNET_free (sm);
- return;
+ return GNUNET_YES;
}
#if DEBUG_DOWNLOAD
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -508,9 +527,9 @@
sm->depth,
(unsigned long long) sm->offset);
#endif
- GNUNET_assert (0 == (size % sizeof(struct ContentHashKey)));
+ GNUNET_assert (0 == (prc->size % sizeof(struct ContentHashKey)));
chk = (struct ContentHashKey*) pt;
- for (i=(size / sizeof(struct ContentHashKey))-1;i>=0;i--)
+ for (i=(prc->size / sizeof(struct ContentHashKey))-1;i>=0;i--)
{
off = compute_dblock_offset (sm->offset,
sm->depth,
@@ -524,10 +543,45 @@
sm->depth + 1);
}
GNUNET_free (sm);
+ return GNUNET_YES;
}
/**
+ * Process a download result.
+ *
+ * @param dc our download context
+ * @param type type of the result
+ * @param data the (encrypted) response
+ * @param size size of data
+ */
+static void
+process_result (struct GNUNET_FS_DownloadContext *dc,
+ uint32_t type,
+ const void *data,
+ size_t size)
+{
+ struct ProcessResultClosure prc;
+
+ prc.dc = dc;
+ prc.data = data;
+ prc.size = size;
+ prc.type = type;
+ GNUNET_CRYPTO_hash (data, size, &prc.query);
+#if DEBUG_DOWNLOAD
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received result for query `%s' from `%s'-service\n",
+ GNUNET_h2s (&prc.query),
+ "FS");
+#endif
+ GNUNET_CONTAINER_multihashmap_get_multiple (dc->active,
+ &prc.query,
+ &process_result_with_request,
+ &prc);
+}
+
+
+/**
* Type of a function to call when we receive a message
* from the service.
*
Modified: gnunet/src/fs/gnunet-service-fs.c
===================================================================
--- gnunet/src/fs/gnunet-service-fs.c 2010-03-01 15:41:33 UTC (rev 10461)
+++ gnunet/src/fs/gnunet-service-fs.c 2010-03-01 16:50:43 UTC (rev 10462)
@@ -658,9 +658,9 @@
{
GNUNET_PEER_resolve (pr->cp->pid,
&pid);
- GNUNET_CONTAINER_multihashmap_remove (peer_request_map,
- &pid.hashPubKey,
- pr);
+ (void) GNUNET_CONTAINER_multihashmap_remove (peer_request_map,
+ &pid.hashPubKey,
+ pr);
pr->cp = NULL;
}
if (pr->bf != NULL)
@@ -1925,6 +1925,56 @@
/**
+ * Closure for 'check_duplicate_request_{peer,client}'.
+ */
+struct CheckDuplicateRequestClosure
+{
+ /**
+ * The new request we should check if it already exists.
+ */
+ const struct PendingRequest *pr;
+
+ /**
+ * Existing request found by the checker, NULL if none.
+ */
+ struct PendingRequest *have;
+};
+
+
+/**
+ * Iterator over entries in the 'query_request_map' that
+ * tries to see if we have the same request pending from
+ * the same client already.
+ *
+ * @param cls closure (our 'struct CheckDuplicateRequestClosure')
+ * @param key current key code (query, ignored, must match)
+ * @param value value in the hash map (a 'struct PendingRequest'
+ * that already exists)
+ * @return GNUNET_YES if we should continue to
+ * iterate (no match yet)
+ * GNUNET_NO if not (match found).
+ */
+static int
+check_duplicate_request_client (void *cls,
+ const GNUNET_HashCode * key,
+ void *value)
+{
+ struct CheckDuplicateRequestClosure *cdc = cls;
+ struct PendingRequest *have = value;
+
+ if (have->client_request_list == NULL)
+ return GNUNET_YES;
+ if ( (cdc->pr->client_request_list->client_list->client ==
have->client_request_list->client_list->client) &&
+ (cdc->pr != have) )
+ {
+ cdc->have = have;
+ return GNUNET_NO;
+ }
+ return GNUNET_YES;
+}
+
+
+/**
* We're processing (local) results for a search request
* from another peer. Pass applicable results to the
* peer and if we are done either clean up (operation
@@ -1955,6 +2005,7 @@
{
struct PendingRequest *pr = cls;
struct ProcessReplyClosure prq;
+ struct CheckDuplicateRequestClosure cdrc;
GNUNET_HashCode dhash;
GNUNET_HashCode mhash;
GNUNET_HashCode query;
@@ -1967,8 +2018,30 @@
#endif
pr->drq = NULL;
if (pr->client_request_list != NULL)
- GNUNET_SERVER_receive_done
(pr->client_request_list->client_list->client,
- GNUNET_YES);
+ {
+ GNUNET_SERVER_receive_done
(pr->client_request_list->client_list->client,
+ GNUNET_YES);
+ /* Figure out if this is a duplicate request and possibly
+ merge 'struct PendingRequest' entries */
+ cdrc.have = NULL;
+ cdrc.pr = pr;
+ GNUNET_CONTAINER_multihashmap_get_multiple (query_request_map,
+ &pr->query,
+
&check_duplicate_request_client,
+ &cdrc);
+ if (cdrc.have != NULL)
+ {
+#if DEBUG_FS
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received request for block `%s' twice from client,
will only request once.\n",
+ GNUNET_h2s (&pr->query));
+#endif
+
+ destroy_pending_request (pr);
+ return;
+ }
+ }
+
/* no more results */
if (pr->task == GNUNET_SCHEDULER_NO_TASK)
pr->task = GNUNET_SCHEDULER_add_now (sched,
@@ -2106,23 +2179,6 @@
/**
- * Closure for 'check_duplicate_request'.
- */
-struct CheckDuplicateRequestClosure
-{
- /**
- * The new request we should check if it already exists.
- */
- const struct PendingRequest *pr;
-
- /**
- * Existing request found by the checker, NULL if none.
- */
- struct PendingRequest *have;
-};
-
-
-/**
* Iterator over entries in the 'query_request_map' that
* tries to see if we have the same request pending from
* the same peer already.
@@ -2136,9 +2192,9 @@
* GNUNET_NO if not (match found).
*/
static int
-check_duplicate_request (void *cls,
- const GNUNET_HashCode * key,
- void *value)
+check_duplicate_request_peer (void *cls,
+ const GNUNET_HashCode * key,
+ void *value)
{
struct CheckDuplicateRequestClosure *cdc = cls;
struct PendingRequest *have = value;
@@ -2327,7 +2383,7 @@
cdc.pr = pr;
GNUNET_CONTAINER_multihashmap_get_multiple (query_request_map,
&gm->query,
- &check_duplicate_request,
+ &check_duplicate_request_peer,
&cdc);
if (cdc.have != NULL)
{
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r10462 - gnunet/src/fs,
gnunet <=