diff options
-rw-r--r-- | src/fs/fs_api.h | 7 | ||||
-rw-r--r-- | src/fs/fs_download.c | 100 | ||||
-rw-r--r-- | src/fs/fs_tree.c | 4 |
3 files changed, 82 insertions, 29 deletions
diff --git a/src/fs/fs_api.h b/src/fs/fs_api.h index 7b44adef8..1d18e20bc 100644 --- a/src/fs/fs_api.h +++ b/src/fs/fs_api.h | |||
@@ -1616,7 +1616,7 @@ struct DownloadRequest | |||
1616 | unsigned int depth; | 1616 | unsigned int depth; |
1617 | 1617 | ||
1618 | /** | 1618 | /** |
1619 | * Offset of the CHK for this block in the parent block. | 1619 | * Offset of the CHK for this block in the parent block |
1620 | */ | 1620 | */ |
1621 | unsigned int chk_idx; | 1621 | unsigned int chk_idx; |
1622 | 1622 | ||
@@ -1851,6 +1851,11 @@ struct GNUNET_FS_DownloadContext | |||
1851 | */ | 1851 | */ |
1852 | int in_receive; | 1852 | int in_receive; |
1853 | 1853 | ||
1854 | /** | ||
1855 | * Are we ready to issue requests (reconstructions are finished)? | ||
1856 | */ | ||
1857 | int issue_requests; | ||
1858 | |||
1854 | }; | 1859 | }; |
1855 | 1860 | ||
1856 | 1861 | ||
diff --git a/src/fs/fs_download.c b/src/fs/fs_download.c index 189afd146..11f5db5b2 100644 --- a/src/fs/fs_download.c +++ b/src/fs/fs_download.c | |||
@@ -243,7 +243,8 @@ encrypt_existing_match (struct GNUNET_FS_DownloadContext *dc, | |||
243 | return GNUNET_SYSERR; | 243 | return GNUNET_SYSERR; |
244 | } | 244 | } |
245 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 245 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
246 | "Matching block for `%s' at offset %llu already present, no need for download!\n", | 246 | "Matching %u byte block for `%s' at offset %llu already present, no need for download!\n", |
247 | (unsigned int) len, | ||
247 | dc->filename, (unsigned long long) dr->offset); | 248 | dc->filename, (unsigned long long) dr->offset); |
248 | /* already got it! */ | 249 | /* already got it! */ |
249 | prc.dc = dc; | 250 | prc.dc = dc; |
@@ -386,6 +387,16 @@ check_completed (struct GNUNET_FS_DownloadContext *dc) | |||
386 | GNUNET_FS_dequeue_ (dc->job_queue); | 387 | GNUNET_FS_dequeue_ (dc->job_queue); |
387 | dc->job_queue = NULL; | 388 | dc->job_queue = NULL; |
388 | } | 389 | } |
390 | if (GNUNET_SCHEDULER_NO_TASK != dc->task) | ||
391 | { | ||
392 | GNUNET_SCHEDULER_cancel (dc->task); | ||
393 | dc->task = GNUNET_SCHEDULER_NO_TASK; | ||
394 | } | ||
395 | if (dc->rfh != NULL) | ||
396 | { | ||
397 | GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (dc->rfh)); | ||
398 | dc->rfh = NULL; | ||
399 | } | ||
389 | GNUNET_FS_download_sync_ (dc); | 400 | GNUNET_FS_download_sync_ (dc); |
390 | 401 | ||
391 | /* signal completion */ | 402 | /* signal completion */ |
@@ -520,6 +531,7 @@ try_match_block (struct GNUNET_FS_DownloadContext *dc, | |||
520 | pi.value.download.specifics.progress.data_len = dlen; | 531 | pi.value.download.specifics.progress.data_len = dlen; |
521 | pi.value.download.specifics.progress.depth = 0; | 532 | pi.value.download.specifics.progress.depth = 0; |
522 | pi.value.download.specifics.progress.trust_offered = 0; | 533 | pi.value.download.specifics.progress.trust_offered = 0; |
534 | pi.value.download.specifics.progress.block_download_duration = GNUNET_TIME_UNIT_ZERO; | ||
523 | GNUNET_FS_download_make_status_ (&pi, dc); | 535 | GNUNET_FS_download_make_status_ (&pi, dc); |
524 | if ((NULL != dc->filename) && | 536 | if ((NULL != dc->filename) && |
525 | (0 != | 537 | (0 != |
@@ -621,7 +633,6 @@ try_top_down_reconstruction (struct GNUNET_FS_DownloadContext *dc, | |||
621 | uint64_t total; | 633 | uint64_t total; |
622 | size_t len; | 634 | size_t len; |
623 | unsigned int i; | 635 | unsigned int i; |
624 | unsigned int chk_off; | ||
625 | struct DownloadRequest *drc; | 636 | struct DownloadRequest *drc; |
626 | uint64_t child_block_size; | 637 | uint64_t child_block_size; |
627 | const struct ContentHashKey *chks; | 638 | const struct ContentHashKey *chks; |
@@ -673,12 +684,11 @@ try_top_down_reconstruction (struct GNUNET_FS_DownloadContext *dc, | |||
673 | drc = dr->children[i]; | 684 | drc = dr->children[i]; |
674 | GNUNET_assert (drc->offset >= dr->offset); | 685 | GNUNET_assert (drc->offset >= dr->offset); |
675 | child_block_size = GNUNET_FS_tree_compute_tree_size (drc->depth); | 686 | child_block_size = GNUNET_FS_tree_compute_tree_size (drc->depth); |
676 | GNUNET_assert (0 == (drc->offset - dr->offset) % child_block_size); | 687 | GNUNET_assert (0 == (drc->offset - dr->offset) % child_block_size); |
677 | chk_off = (drc->offset - dr->offset) / child_block_size; | ||
678 | if (drc->state == BRS_INIT) | 688 | if (drc->state == BRS_INIT) |
679 | { | 689 | { |
680 | drc->state = BRS_CHK_SET; | 690 | drc->state = BRS_CHK_SET; |
681 | drc->chk = chks[chk_off]; | 691 | drc->chk = chks[drc->chk_idx]; |
682 | try_top_down_reconstruction (dc, drc); | 692 | try_top_down_reconstruction (dc, drc); |
683 | } | 693 | } |
684 | if (drc->state != BRS_DOWNLOAD_UP) | 694 | if (drc->state != BRS_DOWNLOAD_UP) |
@@ -1113,9 +1123,10 @@ process_result_with_request (void *cls, const GNUNET_HashCode * key, | |||
1113 | switch (drc->state) | 1123 | switch (drc->state) |
1114 | { | 1124 | { |
1115 | case BRS_INIT: | 1125 | case BRS_INIT: |
1116 | drc->chk = chkarr[dr->chk_idx]; | 1126 | drc->chk = chkarr[drc->chk_idx]; |
1117 | drc->state = BRS_CHK_SET; | 1127 | drc->state = BRS_CHK_SET; |
1118 | schedule_block_download (dc, drc); | 1128 | if (GNUNET_YES == dc->issue_requests) |
1129 | schedule_block_download (dc, drc); | ||
1119 | break; | 1130 | break; |
1120 | case BRS_RECONSTRUCT_DOWN: | 1131 | case BRS_RECONSTRUCT_DOWN: |
1121 | GNUNET_assert (0); | 1132 | GNUNET_assert (0); |
@@ -1527,6 +1538,11 @@ create_download_request (struct DownloadRequest *parent, | |||
1527 | if (dr->num_children * child_block_size < | 1538 | if (dr->num_children * child_block_size < |
1528 | file_start_offset + desired_length) | 1539 | file_start_offset + desired_length) |
1529 | dr->num_children++; /* round up */ | 1540 | dr->num_children++; /* round up */ |
1541 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1542 | "Block at offset %llu and depth %u has %u children\n", | ||
1543 | (unsigned long long) dr_offset, | ||
1544 | depth, | ||
1545 | dr->num_children); | ||
1530 | 1546 | ||
1531 | /* now we can get the total number of children for this block */ | 1547 | /* now we can get the total number of children for this block */ |
1532 | dr->num_children -= head_skip; | 1548 | dr->num_children -= head_skip; |
@@ -1560,12 +1576,7 @@ reconstruct_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1560 | { | 1576 | { |
1561 | struct GNUNET_FS_DownloadContext *dc = cls; | 1577 | struct GNUNET_FS_DownloadContext *dc = cls; |
1562 | 1578 | ||
1563 | /* clean up state from tree encoder */ | 1579 | /* clean up state from tree encoder */ |
1564 | if (dc->te != NULL) | ||
1565 | { | ||
1566 | GNUNET_FS_tree_encoder_finish (dc->te, NULL, NULL); | ||
1567 | dc->te = NULL; | ||
1568 | } | ||
1569 | if (dc->task != GNUNET_SCHEDULER_NO_TASK) | 1580 | if (dc->task != GNUNET_SCHEDULER_NO_TASK) |
1570 | { | 1581 | { |
1571 | GNUNET_SCHEDULER_cancel (dc->task); | 1582 | GNUNET_SCHEDULER_cancel (dc->task); |
@@ -1577,6 +1588,9 @@ reconstruct_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1577 | dc->rfh = NULL; | 1588 | dc->rfh = NULL; |
1578 | } | 1589 | } |
1579 | /* start "normal" download */ | 1590 | /* start "normal" download */ |
1591 | dc->issue_requests = GNUNET_YES; | ||
1592 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1593 | "Starting normal download\n"); | ||
1580 | schedule_block_download (dc, dc->top_request); | 1594 | schedule_block_download (dc, dc->top_request); |
1581 | } | 1595 | } |
1582 | 1596 | ||
@@ -1630,11 +1644,34 @@ reconstruct_cb (void *cls, const struct ContentHashKey *chk, uint64_t offset, | |||
1630 | dr = dc->top_request; | 1644 | dr = dc->top_request; |
1631 | while (dr->depth > depth) | 1645 | while (dr->depth > depth) |
1632 | { | 1646 | { |
1633 | blen = GNUNET_FS_tree_compute_tree_size (dr->depth); | 1647 | GNUNET_assert (dr->num_children > 0); |
1648 | blen = GNUNET_FS_tree_compute_tree_size (dr->depth - 1); | ||
1634 | chld = (offset - dr->offset) / blen; | 1649 | chld = (offset - dr->offset) / blen; |
1635 | GNUNET_assert (chld < dr->num_children); | 1650 | if (chld < dr->children[0]->chk_idx) |
1636 | dr = dr->children[chld]; | 1651 | { |
1652 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1653 | "Block %u < %u irrelevant for our range\n", | ||
1654 | chld, | ||
1655 | dr->children[dr->num_children-1]->chk_idx); | ||
1656 | dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); | ||
1657 | return; /* irrelevant block */ | ||
1658 | } | ||
1659 | if (chld > dr->children[dr->num_children-1]->chk_idx) | ||
1660 | { | ||
1661 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1662 | "Block %u > %u irrelevant for our range\n", | ||
1663 | chld, | ||
1664 | dr->children[dr->num_children-1]->chk_idx); | ||
1665 | dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); | ||
1666 | return; /* irrelevant block */ | ||
1667 | } | ||
1668 | dr = dr->children[chld - dr->children[0]->chk_idx]; | ||
1637 | } | 1669 | } |
1670 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1671 | "Matched TE block with request at offset %llu and depth %u in state %d\n", | ||
1672 | (unsigned long long) dr->offset, | ||
1673 | dr->depth, | ||
1674 | dr->state); | ||
1638 | /* FIXME: this code needs more testing and might | 1675 | /* FIXME: this code needs more testing and might |
1639 | need to handle more states... */ | 1676 | need to handle more states... */ |
1640 | switch (dr->state) | 1677 | switch (dr->state) |
@@ -1650,11 +1687,14 @@ reconstruct_cb (void *cls, const struct ContentHashKey *chk, uint64_t offset, | |||
1650 | case BRS_CHK_SET: | 1687 | case BRS_CHK_SET: |
1651 | if (0 == memcmp (chk, &dr->chk, sizeof (struct ContentHashKey))) | 1688 | if (0 == memcmp (chk, &dr->chk, sizeof (struct ContentHashKey))) |
1652 | { | 1689 | { |
1690 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1691 | "Reconstruction succeeded, can use block at offset %llu, depth %u\n", | ||
1692 | (unsigned long long) offset, | ||
1693 | depth); | ||
1653 | /* block matches, hence tree below matches; | 1694 | /* block matches, hence tree below matches; |
1654 | * this request is done! */ | 1695 | * this request is done! */ |
1655 | dr->state = BRS_DOWNLOAD_UP; | 1696 | dr->state = BRS_DOWNLOAD_UP; |
1656 | GNUNET_break (GNUNET_NO == | 1697 | (void) GNUNET_CONTAINER_multihashmap_remove (dc->active, &dr->chk.query, dr); |
1657 | GNUNET_CONTAINER_multihashmap_remove (dc->active, &dr->chk.query, dr)); | ||
1658 | if (GNUNET_YES == dr->is_pending) | 1698 | if (GNUNET_YES == dr->is_pending) |
1659 | { | 1699 | { |
1660 | GNUNET_break (0); /* how did we get here? */ | 1700 | GNUNET_break (0); /* how did we get here? */ |
@@ -1674,6 +1714,7 @@ reconstruct_cb (void *cls, const struct ContentHashKey *chk, uint64_t offset, | |||
1674 | pi.value.download.specifics.progress.data_len = 0; | 1714 | pi.value.download.specifics.progress.data_len = 0; |
1675 | pi.value.download.specifics.progress.depth = 0; | 1715 | pi.value.download.specifics.progress.depth = 0; |
1676 | pi.value.download.specifics.progress.trust_offered = 0; | 1716 | pi.value.download.specifics.progress.trust_offered = 0; |
1717 | pi.value.download.specifics.progress.block_download_duration = GNUNET_TIME_UNIT_ZERO; | ||
1677 | GNUNET_FS_download_make_status_ (&pi, dc); | 1718 | GNUNET_FS_download_make_status_ (&pi, dc); |
1678 | /* FIXME: duplicated code from 'process_result_with_request - refactor */ | 1719 | /* FIXME: duplicated code from 'process_result_with_request - refactor */ |
1679 | if (dc->completed == dc->length) | 1720 | if (dc->completed == dc->length) |
@@ -1694,6 +1735,11 @@ reconstruct_cb (void *cls, const struct ContentHashKey *chk, uint64_t offset, | |||
1694 | } | 1735 | } |
1695 | } | 1736 | } |
1696 | } | 1737 | } |
1738 | else | ||
1739 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1740 | "Reconstruction failed, need to download block at offset %llu, depth %u\n", | ||
1741 | (unsigned long long) offset, | ||
1742 | depth); | ||
1697 | break; | 1743 | break; |
1698 | case BRS_DOWNLOAD_DOWN: | 1744 | case BRS_DOWNLOAD_DOWN: |
1699 | break; | 1745 | break; |
@@ -1705,12 +1751,9 @@ reconstruct_cb (void *cls, const struct ContentHashKey *chk, uint64_t offset, | |||
1705 | GNUNET_assert (0); | 1751 | GNUNET_assert (0); |
1706 | break; | 1752 | break; |
1707 | } | 1753 | } |
1754 | dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); | ||
1708 | if ((dr == dc->top_request) && (dr->state == BRS_DOWNLOAD_UP)) | 1755 | if ((dr == dc->top_request) && (dr->state == BRS_DOWNLOAD_UP)) |
1709 | { | ||
1710 | check_completed (dc); | 1756 | check_completed (dc); |
1711 | return; | ||
1712 | } | ||
1713 | dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); | ||
1714 | } | 1757 | } |
1715 | 1758 | ||
1716 | 1759 | ||
@@ -1876,18 +1919,21 @@ GNUNET_FS_download_start_task_ (void *cls, | |||
1876 | } | 1919 | } |
1877 | if (dc->rfh != NULL) | 1920 | if (dc->rfh != NULL) |
1878 | { | 1921 | { |
1879 | /* finally, try bottom-up */ | 1922 | /* finally, actually run bottom-up */ |
1880 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1923 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1881 | "Trying bottom-up reconstruction of file `%s'\n", dc->filename); | 1924 | "Trying bottom-up reconstruction of file `%s'\n", dc->filename); |
1882 | dc->te = | 1925 | dc->te = |
1883 | GNUNET_FS_tree_encoder_create (dc->h, dc->old_file_size, dc, &fh_reader, | 1926 | GNUNET_FS_tree_encoder_create (dc->h, |
1884 | &reconstruct_cb, NULL, | 1927 | GNUNET_FS_uri_chk_get_file_size (dc->uri), |
1885 | &reconstruct_cont); | 1928 | dc, &fh_reader, |
1929 | &reconstruct_cb, NULL, | ||
1930 | &reconstruct_cont); | ||
1886 | dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); | 1931 | dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); |
1887 | } | 1932 | } |
1888 | else | 1933 | else |
1889 | { | 1934 | { |
1890 | /* simple, top-level download */ | 1935 | /* simple, top-level download */ |
1936 | dc->issue_requests = GNUNET_YES; | ||
1891 | schedule_block_download (dc, dc->top_request); | 1937 | schedule_block_download (dc, dc->top_request); |
1892 | } | 1938 | } |
1893 | if (dc->top_request->state == BRS_DOWNLOAD_UP) | 1939 | if (dc->top_request->state == BRS_DOWNLOAD_UP) |
@@ -2194,8 +2240,6 @@ GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc, int do_delete) | |||
2194 | 2240 | ||
2195 | if (dc->top != NULL) | 2241 | if (dc->top != NULL) |
2196 | GNUNET_FS_end_top (dc->h, dc->top); | 2242 | GNUNET_FS_end_top (dc->h, dc->top); |
2197 | |||
2198 | |||
2199 | if (dc->task != GNUNET_SCHEDULER_NO_TASK) | 2243 | if (dc->task != GNUNET_SCHEDULER_NO_TASK) |
2200 | { | 2244 | { |
2201 | GNUNET_SCHEDULER_cancel (dc->task); | 2245 | GNUNET_SCHEDULER_cancel (dc->task); |
diff --git a/src/fs/fs_tree.c b/src/fs/fs_tree.c index b3bbdc7b1..a055bcd40 100644 --- a/src/fs/fs_tree.c +++ b/src/fs/fs_tree.c | |||
@@ -287,6 +287,10 @@ GNUNET_FS_tree_encoder_create (struct GNUNET_FS_Handle *h, uint64_t size, | |||
287 | te->chk_tree = | 287 | te->chk_tree = |
288 | GNUNET_malloc (te->chk_tree_depth * CHK_PER_INODE * | 288 | GNUNET_malloc (te->chk_tree_depth * CHK_PER_INODE * |
289 | sizeof (struct ContentHashKey)); | 289 | sizeof (struct ContentHashKey)); |
290 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
291 | "Created tree encoder for file with %llu bytes and depth %u\n", | ||
292 | (unsigned long long) size, | ||
293 | te->chk_tree_depth); | ||
290 | return te; | 294 | return te; |
291 | } | 295 | } |
292 | 296 | ||