aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2009-09-05 21:39:13 +0000
committerChristian Grothoff <christian@grothoff.org>2009-09-05 21:39:13 +0000
commit40b39eeabe0f8301cc7410c9b54f82dd46c48cbb (patch)
treeef59540033927be735b295f8c0f05dd501098e7f /src
parent0dfe519c70ef2c40c8f63499c521c0885af37cc2 (diff)
downloadgnunet-40b39eeabe0f8301cc7410c9b54f82dd46c48cbb.tar.gz
gnunet-40b39eeabe0f8301cc7410c9b54f82dd46c48cbb.zip
towards having download
Diffstat (limited to 'src')
-rw-r--r--src/fs/fs.h8
-rw-r--r--src/fs/fs_download.c210
2 files changed, 157 insertions, 61 deletions
diff --git a/src/fs/fs.h b/src/fs/fs.h
index 529a917a3..50090c6fd 100644
--- a/src/fs/fs.h
+++ b/src/fs/fs.h
@@ -877,6 +877,14 @@ struct GNUNET_FS_DownloadContext
877 GNUNET_SCHEDULER_TaskIdentifier task; 877 GNUNET_SCHEDULER_TaskIdentifier task;
878 878
879 /** 879 /**
880 * What was the size of the file on disk that we're downloading
881 * before we started? Used to detect if there is a point in
882 * checking an existing block on disk for matching the desired
883 * content. 0 if the file did not exist already.
884 */
885 uint64_t old_file_size;
886
887 /**
880 * What is the first offset that we're interested 888 * What is the first offset that we're interested
881 * in? 889 * in?
882 */ 890 */
diff --git a/src/fs/fs_download.c b/src/fs/fs_download.c
index 904244dbb..c5bfec52c 100644
--- a/src/fs/fs_download.c
+++ b/src/fs/fs_download.c
@@ -23,9 +23,9 @@
23 * @author Christian Grothoff 23 * @author Christian Grothoff
24 * 24 *
25 * TODO: 25 * TODO:
26 * - process replies 26 * - offset calculations
27 * - callback signaling 27 * - callback signaling
28 * - check if blocks exist already 28 * - check if blocks exist already (can wait)
29 * - location URI suppport (can wait) 29 * - location URI suppport (can wait)
30 * - persistence (can wait) 30 * - persistence (can wait)
31 */ 31 */
@@ -37,6 +37,65 @@
37 37
38#define DEBUG_DOWNLOAD GNUNET_YES 38#define DEBUG_DOWNLOAD GNUNET_YES
39 39
40/**
41 * We're storing the IBLOCKS after the
42 * DBLOCKS on disk (so that we only have
43 * to truncate the file once we're done).
44 *
45 * Given the offset of a block (with respect
46 * to the DBLOCKS) and its depth, return the
47 * offset where we would store this block
48 * in the file.
49 *
50 * @param fsize overall file size
51 * @param off offset of the block in the file
52 * @param depth depth of the block in the tree
53 * @param treedepth maximum depth of the tree
54 * @return off for DBLOCKS (depth == treedepth),
55 * otherwise an offset past the end
56 * of the file that does not overlap
57 * with the range for any other block
58 */
59static uint64_t
60compute_disk_offset (uint64_t fsize,
61 uint64_t off,
62 unsigned int depth,
63 unsigned int treedepth)
64{
65 if (depth == treedepth)
66 return off;
67 return 42; // FIXME
68}
69
70/**
71 * Given a file of the specified treedepth and
72 * a block at the given offset and depth,
73 * calculate the offset for the CHK at
74 * the given index.
75 *
76 * @param offset the offset of the first
77 * DBLOCK in the subtree of the
78 * identified IBLOCK
79 * @param depth the depth of the IBLOCK in the tree
80 * @param treedepth overall depth of the tree
81 * @param i which CHK in the IBLOCK are we
82 * talking about
83 * @return offset if i=0, otherwise an appropriately
84 * larger value (i.e., if depth = treedepth-1,
85 * the returned value should be offset+DBLOCK_SIZE)
86 */
87static uint64_t
88compute_dblock_offset (uint64_t offset,
89 unsigned int depth,
90 unsigned int treedepth,
91 unsigned int i)
92{
93 GNUNET_assert (depth < treedepth);
94 if (i == 0)
95 return offset;
96 return 42; // FIXME
97}
98
40 99
41/** 100/**
42 * Schedule the download of the specified 101 * Schedule the download of the specified
@@ -57,8 +116,31 @@ schedule_block_download (struct GNUNET_FS_DownloadContext *dc,
57 unsigned int depth) 116 unsigned int depth)
58{ 117{
59 struct DownloadRequest *sm; 118 struct DownloadRequest *sm;
60 119 uint64_t off;
61 // FIXME: check if block exists on disk! 120
121 off = compute_disk_offset (GNUNET_ntohll (dc->uri->data.chk.file_length),
122 offset,
123 depth,
124 dc->treedepth);
125 if ( (dc->old_file_size > off) &&
126 (dc->handle != NULL) &&
127 (off ==
128 GNUNET_DISK_file_seek (dc->handle,
129 off,
130 GNUNET_DISK_SEEK_SET) ) )
131 {
132 // FIXME: check if block exists on disk!
133 // (read block, encode, compare with
134 // query; if matches, simply return)
135 }
136 if (depth < dc->treedepth)
137 {
138 // FIXME: try if we could
139 // reconstitute this IBLOCK
140 // from the existing blocks on disk (can wait)
141 // (read block(s), encode, compare with
142 // query; if matches, simply return)
143 }
62 sm = GNUNET_malloc (sizeof (struct DownloadRequest)); 144 sm = GNUNET_malloc (sizeof (struct DownloadRequest));
63 sm->chk = *chk; 145 sm->chk = *chk;
64 sm->offset = offset; 146 sm->offset = offset;
@@ -103,7 +185,12 @@ process_result (struct GNUNET_FS_DownloadContext *dc,
103 struct GNUNET_CRYPTO_AesSessionKey skey; 185 struct GNUNET_CRYPTO_AesSessionKey skey;
104 struct GNUNET_CRYPTO_AesInitializationVector iv; 186 struct GNUNET_CRYPTO_AesInitializationVector iv;
105 char pt[size]; 187 char pt[size];
188 uint64_t off;
189 size_t app;
190 unsigned int i;
191 struct ContentHashKey *chk;
106 192
193 // FIXME: check that size is as big as expected, otherwise ignore!!!
107 GNUNET_CRYPTO_hash (data, size, &query); 194 GNUNET_CRYPTO_hash (data, size, &query);
108 sm = GNUNET_CONTAINER_multihashmap_get (dc->active, 195 sm = GNUNET_CONTAINER_multihashmap_get (dc->active,
109 &query); 196 &query);
@@ -122,10 +209,62 @@ process_result (struct GNUNET_FS_DownloadContext *dc,
122 &skey, 209 &skey,
123 &iv, 210 &iv,
124 pt); 211 pt);
125 // FIXME: save to disk 212 /* save to disk */
213 if ( (NULL != dc->handle) &&
214 ( (sm->depth == dc->treedepth) ||
215 (0 == (dc->options & GNUNET_FS_DOWNLOAD_NO_TEMPORARIES)) ) )
216 {
217 off = compute_disk_offset (GNUNET_ntohll (dc->uri->data.chk.file_length),
218 sm->offset,
219 sm->depth,
220 dc->treedepth);
221 GNUNET_assert (off !=
222 GNUNET_DISK_file_seek (dc->handle,
223 off,
224 GNUNET_DISK_SEEK_SET) );
225 GNUNET_DISK_file_write (dc->handle,
226 pt,
227 size);
228 }
126 // FIXME: make persistent 229 // FIXME: make persistent
230
231 if (sm->depth == dc->treedepth)
232 {
233 app = size;
234 if (sm->offset < dc->offset)
235 {
236 /* starting offset begins in the middle of pt,
237 do not count first bytes as progress */
238 GNUNET_assert (app > (dc->offset - sm->offset));
239 app -= (dc->offset - sm->offset);
240 }
241 if (sm->offset + size > dc->offset + dc->length)
242 {
243 /* end of block is after relevant range,
244 do not count last bytes as progress */
245 GNUNET_assert (app > (sm->offset + size) - (dc->offset + dc->length));
246 app -= (sm->offset + size) - (dc->offset + dc->length);
247 }
248 dc->completed += app;
249 }
127 // FIXME: call progress callback 250 // FIXME: call progress callback
128 // FIXME: trigger next block (if applicable) 251 if (sm->depth == dc->treedepth)
252 return;
253 GNUNET_assert (0 == (size % sizeof(struct ContentHashKey)));
254 chk = (struct ContentHashKey*) pt;
255 for (i=0;i<(size / sizeof(struct ContentHashKey));i++)
256 {
257 off = compute_dblock_offset (sm->offset,
258 sm->depth,
259 dc->treedepth,
260 i);
261 if ( (off + DBLOCK_SIZE >= dc->offset) &&
262 (off < dc->offset + dc->length) )
263 schedule_block_download (dc,
264 &chk[i],
265 off,
266 sm->depth + 1);
267 }
129} 268}
130 269
131 270
@@ -363,6 +502,10 @@ GNUNET_FS_file_download_start (struct GNUNET_FS_Handle *h,
363 if (NULL != filename) 502 if (NULL != filename)
364 { 503 {
365 dc->filename = GNUNET_strdup (filename); 504 dc->filename = GNUNET_strdup (filename);
505 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
506 GNUNET_DISK_file_size (filename,
507 &dc->old_file_size,
508 GNUNET_YES);
366 dc->handle = GNUNET_DISK_file_open (filename, 509 dc->handle = GNUNET_DISK_file_open (filename,
367 GNUNET_DISK_OPEN_READWRITE | 510 GNUNET_DISK_OPEN_READWRITE |
368 GNUNET_DISK_OPEN_CREATE, 511 GNUNET_DISK_OPEN_CREATE,
@@ -581,61 +724,6 @@ check_node_present (const struct Node *node)
581 return ret; 724 return ret;
582} 725}
583 726
584/**
585 * DOWNLOAD children of this GNUNET_EC_IBlock.
586 *
587 * @param node the node that should be downloaded
588 */
589static void
590iblock_download_children (const struct Node *node,
591 const char *data, unsigned int size)
592{
593 struct GNUNET_GE_Context *ectx = node->ctx->ectx;
594 int i;
595 struct Node *child;
596 unsigned int childcount;
597 const GNUNET_EC_ContentHashKey *chks;
598 unsigned int levelSize;
599 unsigned long long baseOffset;
600
601 GNUNET_GE_ASSERT (ectx, node->level > 0);
602 childcount = size / sizeof (GNUNET_EC_ContentHashKey);
603 if (size != childcount * sizeof (GNUNET_EC_ContentHashKey))
604 {
605 GNUNET_GE_BREAK (ectx, 0);
606 return;
607 }
608 if (node->level == 1)
609 {
610 levelSize = GNUNET_ECRS_DBLOCK_SIZE;
611 baseOffset =
612 node->offset / sizeof (GNUNET_EC_ContentHashKey) *
613 GNUNET_ECRS_DBLOCK_SIZE;
614 }
615 else
616 {
617 levelSize =
618 sizeof (GNUNET_EC_ContentHashKey) * GNUNET_ECRS_CHK_PER_INODE;
619 baseOffset = node->offset * GNUNET_ECRS_CHK_PER_INODE;
620 }
621 chks = (const GNUNET_EC_ContentHashKey *) data;
622 for (i = 0; i < childcount; i++)
623 {
624 child = GNUNET_malloc (sizeof (struct Node));
625 child->ctx = node->ctx;
626 child->chk = chks[i];
627 child->offset = baseOffset + i * levelSize;
628 GNUNET_GE_ASSERT (ectx, child->offset < node->ctx->total);
629 child->level = node->level - 1;
630 GNUNET_GE_ASSERT (ectx, (child->level != 0) ||
631 ((child->offset % GNUNET_ECRS_DBLOCK_SIZE) == 0));
632 if (GNUNET_NO == check_node_present (child))
633 add_request (child);
634 else
635 GNUNET_free (child); /* done already! */
636 }
637}
638
639#endif 727#endif
640 728
641 729