diff options
Diffstat (limited to 'src/fs/fs_tree.c')
-rw-r--r-- | src/fs/fs_tree.c | 247 |
1 files changed, 110 insertions, 137 deletions
diff --git a/src/fs/fs_tree.c b/src/fs/fs_tree.c index e22ce8221..5584ad868 100644 --- a/src/fs/fs_tree.c +++ b/src/fs/fs_tree.c | |||
@@ -40,7 +40,7 @@ struct GNUNET_FS_TreeEncoder | |||
40 | * Global FS context. | 40 | * Global FS context. |
41 | */ | 41 | */ |
42 | struct GNUNET_FS_Handle *h; | 42 | struct GNUNET_FS_Handle *h; |
43 | 43 | ||
44 | /** | 44 | /** |
45 | * Closure for all callbacks. | 45 | * Closure for all callbacks. |
46 | */ | 46 | */ |
@@ -65,7 +65,7 @@ struct GNUNET_FS_TreeEncoder | |||
65 | * Function to call once we're done with processing. | 65 | * Function to call once we're done with processing. |
66 | */ | 66 | */ |
67 | GNUNET_SCHEDULER_Task cont; | 67 | GNUNET_SCHEDULER_Task cont; |
68 | 68 | ||
69 | /** | 69 | /** |
70 | * Set to an error message (if we had an error). | 70 | * Set to an error message (if we had an error). |
71 | */ | 71 | */ |
@@ -132,15 +132,15 @@ GNUNET_FS_compute_depth (uint64_t flen) | |||
132 | treeDepth = 1; | 132 | treeDepth = 1; |
133 | fl = DBLOCK_SIZE; | 133 | fl = DBLOCK_SIZE; |
134 | while (fl < flen) | 134 | while (fl < flen) |
135 | { | ||
136 | treeDepth++; | ||
137 | if (fl * CHK_PER_INODE < fl) | ||
135 | { | 138 | { |
136 | treeDepth++; | 139 | /* integer overflow, this is a HUGE file... */ |
137 | if (fl * CHK_PER_INODE < fl) | 140 | return treeDepth; |
138 | { | ||
139 | /* integer overflow, this is a HUGE file... */ | ||
140 | return treeDepth; | ||
141 | } | ||
142 | fl = fl * CHK_PER_INODE; | ||
143 | } | 141 | } |
142 | fl = fl * CHK_PER_INODE; | ||
143 | } | ||
144 | return treeDepth; | 144 | return treeDepth; |
145 | } | 145 | } |
146 | 146 | ||
@@ -161,7 +161,7 @@ GNUNET_FS_tree_compute_tree_size (unsigned int depth) | |||
161 | unsigned int i; | 161 | unsigned int i; |
162 | 162 | ||
163 | rsize = DBLOCK_SIZE; | 163 | rsize = DBLOCK_SIZE; |
164 | for (i = 0; i<depth; i++) | 164 | for (i = 0; i < depth; i++) |
165 | rsize *= CHK_PER_INODE; | 165 | rsize *= CHK_PER_INODE; |
166 | return rsize; | 166 | return rsize; |
167 | } | 167 | } |
@@ -181,9 +181,8 @@ GNUNET_FS_tree_compute_tree_size (unsigned int depth) | |||
181 | * end of a block). | 181 | * end of a block). |
182 | * @return size of the corresponding IBlock | 182 | * @return size of the corresponding IBlock |
183 | */ | 183 | */ |
184 | static uint16_t | 184 | static uint16_t |
185 | GNUNET_FS_tree_compute_iblock_size (unsigned int depth, | 185 | GNUNET_FS_tree_compute_iblock_size (unsigned int depth, uint64_t end_offset) |
186 | uint64_t end_offset) | ||
187 | { | 186 | { |
188 | unsigned int ret; | 187 | unsigned int ret; |
189 | uint64_t mod; | 188 | uint64_t mod; |
@@ -194,19 +193,19 @@ GNUNET_FS_tree_compute_iblock_size (unsigned int depth, | |||
194 | bds = GNUNET_FS_tree_compute_tree_size (depth); | 193 | bds = GNUNET_FS_tree_compute_tree_size (depth); |
195 | mod = end_offset % bds; | 194 | mod = end_offset % bds; |
196 | if (0 == mod) | 195 | if (0 == mod) |
197 | { | 196 | { |
198 | /* we were triggered at the end of a full block */ | 197 | /* we were triggered at the end of a full block */ |
199 | ret = CHK_PER_INODE; | 198 | ret = CHK_PER_INODE; |
200 | } | 199 | } |
201 | else | 200 | else |
202 | { | 201 | { |
203 | /* we were triggered at the end of the file */ | 202 | /* we were triggered at the end of the file */ |
204 | bds /= CHK_PER_INODE; | 203 | bds /= CHK_PER_INODE; |
205 | ret = mod / bds; | 204 | ret = mod / bds; |
206 | if (0 != mod % bds) | 205 | if (0 != mod % bds) |
207 | ret++; | 206 | ret++; |
208 | } | 207 | } |
209 | return (uint16_t) (ret * sizeof(struct ContentHashKey)); | 208 | return (uint16_t) (ret * sizeof (struct ContentHashKey)); |
210 | } | 209 | } |
211 | 210 | ||
212 | 211 | ||
@@ -223,8 +222,7 @@ GNUNET_FS_tree_compute_iblock_size (unsigned int depth, | |||
223 | */ | 222 | */ |
224 | size_t | 223 | size_t |
225 | GNUNET_FS_tree_calculate_block_size (uint64_t fsize, | 224 | GNUNET_FS_tree_calculate_block_size (uint64_t fsize, |
226 | uint64_t offset, | 225 | uint64_t offset, unsigned int depth) |
227 | unsigned int depth) | ||
228 | { | 226 | { |
229 | size_t ret; | 227 | size_t ret; |
230 | uint64_t rsize; | 228 | uint64_t rsize; |
@@ -234,18 +232,16 @@ GNUNET_FS_tree_calculate_block_size (uint64_t fsize, | |||
234 | GNUNET_assert (fsize > 0); | 232 | GNUNET_assert (fsize > 0); |
235 | GNUNET_assert (offset <= fsize); | 233 | GNUNET_assert (offset <= fsize); |
236 | if (depth == 0) | 234 | if (depth == 0) |
237 | { | 235 | { |
238 | ret = DBLOCK_SIZE; | 236 | ret = DBLOCK_SIZE; |
239 | if ( (offset + ret > fsize) || | 237 | if ((offset + ret > fsize) || (offset + ret < offset)) |
240 | (offset + ret < offset) ) | 238 | ret = (size_t) (fsize - offset); |
241 | ret = (size_t) (fsize - offset); | 239 | return ret; |
242 | return ret; | 240 | } |
243 | } | ||
244 | 241 | ||
245 | rsize = GNUNET_FS_tree_compute_tree_size (depth - 1); | 242 | rsize = GNUNET_FS_tree_compute_tree_size (depth - 1); |
246 | epos = offset + rsize * CHK_PER_INODE; | 243 | epos = offset + rsize * CHK_PER_INODE; |
247 | if ( (epos < offset) || | 244 | if ((epos < offset) || (epos > fsize)) |
248 | (epos > fsize) ) | ||
249 | epos = fsize; | 245 | epos = fsize; |
250 | /* round up when computing #CHKs in our IBlock */ | 246 | /* round up when computing #CHKs in our IBlock */ |
251 | chks = (epos - offset + rsize - 1) / rsize; | 247 | chks = (epos - offset + rsize - 1) / rsize; |
@@ -273,16 +269,16 @@ GNUNET_FS_tree_calculate_block_size (uint64_t fsize, | |||
273 | */ | 269 | */ |
274 | struct GNUNET_FS_TreeEncoder * | 270 | struct GNUNET_FS_TreeEncoder * |
275 | GNUNET_FS_tree_encoder_create (struct GNUNET_FS_Handle *h, | 271 | GNUNET_FS_tree_encoder_create (struct GNUNET_FS_Handle *h, |
276 | uint64_t size, | 272 | uint64_t size, |
277 | void *cls, | 273 | void *cls, |
278 | GNUNET_FS_DataReader reader, | 274 | GNUNET_FS_DataReader reader, |
279 | GNUNET_FS_TreeBlockProcessor proc, | 275 | GNUNET_FS_TreeBlockProcessor proc, |
280 | GNUNET_FS_TreeProgressCallback progress, | 276 | GNUNET_FS_TreeProgressCallback progress, |
281 | GNUNET_SCHEDULER_Task cont) | 277 | GNUNET_SCHEDULER_Task cont) |
282 | { | 278 | { |
283 | struct GNUNET_FS_TreeEncoder *te; | 279 | struct GNUNET_FS_TreeEncoder *te; |
284 | 280 | ||
285 | te = GNUNET_malloc (sizeof (struct GNUNET_FS_TreeEncoder)); | 281 | te = GNUNET_malloc (sizeof (struct GNUNET_FS_TreeEncoder)); |
286 | te->h = h; | 282 | te->h = h; |
287 | te->size = size; | 283 | te->size = size; |
288 | te->cls = cls; | 284 | te->cls = cls; |
@@ -292,8 +288,7 @@ GNUNET_FS_tree_encoder_create (struct GNUNET_FS_Handle *h, | |||
292 | te->cont = cont; | 288 | te->cont = cont; |
293 | te->chk_tree_depth = GNUNET_FS_compute_depth (size); | 289 | te->chk_tree_depth = GNUNET_FS_compute_depth (size); |
294 | te->chk_tree = GNUNET_malloc (te->chk_tree_depth * | 290 | te->chk_tree = GNUNET_malloc (te->chk_tree_depth * |
295 | CHK_PER_INODE * | 291 | CHK_PER_INODE * sizeof (struct ContentHashKey)); |
296 | sizeof (struct ContentHashKey)); | ||
297 | return te; | 292 | return te; |
298 | } | 293 | } |
299 | 294 | ||
@@ -310,17 +305,16 @@ GNUNET_FS_tree_encoder_create (struct GNUNET_FS_Handle *h, | |||
310 | * @return (array of CHKs') offset in the above IBlock | 305 | * @return (array of CHKs') offset in the above IBlock |
311 | */ | 306 | */ |
312 | static unsigned int | 307 | static unsigned int |
313 | compute_chk_offset (unsigned int depth, | 308 | compute_chk_offset (unsigned int depth, uint64_t end_offset) |
314 | uint64_t end_offset) | ||
315 | { | 309 | { |
316 | uint64_t bds; | 310 | uint64_t bds; |
317 | unsigned int ret; | 311 | unsigned int ret; |
318 | 312 | ||
319 | bds = GNUNET_FS_tree_compute_tree_size (depth); | 313 | bds = GNUNET_FS_tree_compute_tree_size (depth); |
320 | if (depth > 0) | 314 | if (depth > 0) |
321 | end_offset--; /* round down since for depth > 0 offset is at the END of the block */ | 315 | end_offset--; /* round down since for depth > 0 offset is at the END of the block */ |
322 | ret = end_offset / bds; | 316 | ret = end_offset / bds; |
323 | return ret % CHK_PER_INODE; | 317 | return ret % CHK_PER_INODE; |
324 | } | 318 | } |
325 | 319 | ||
326 | 320 | ||
@@ -331,8 +325,8 @@ compute_chk_offset (unsigned int depth, | |||
331 | * | 325 | * |
332 | * @param te tree encoder to use | 326 | * @param te tree encoder to use |
333 | */ | 327 | */ |
334 | void | 328 | void |
335 | GNUNET_FS_tree_encoder_next (struct GNUNET_FS_TreeEncoder * te) | 329 | GNUNET_FS_tree_encoder_next (struct GNUNET_FS_TreeEncoder *te) |
336 | { | 330 | { |
337 | struct ContentHashKey *mychk; | 331 | struct ContentHashKey *mychk; |
338 | const void *pt_block; | 332 | const void *pt_block; |
@@ -346,105 +340,85 @@ GNUNET_FS_tree_encoder_next (struct GNUNET_FS_TreeEncoder * te) | |||
346 | GNUNET_assert (GNUNET_NO == te->in_next); | 340 | GNUNET_assert (GNUNET_NO == te->in_next); |
347 | te->in_next = GNUNET_YES; | 341 | te->in_next = GNUNET_YES; |
348 | if (te->chk_tree_depth == te->current_depth) | 342 | if (te->chk_tree_depth == te->current_depth) |
349 | { | 343 | { |
350 | off = CHK_PER_INODE * (te->chk_tree_depth - 1); | 344 | off = CHK_PER_INODE * (te->chk_tree_depth - 1); |
351 | #if DEBUG_TREE | 345 | #if DEBUG_TREE |
352 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 346 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
353 | "TE done, reading CHK `%s' from %u\n", | 347 | "TE done, reading CHK `%s' from %u\n", |
354 | GNUNET_h2s (&te->chk_tree[off].query), | 348 | GNUNET_h2s (&te->chk_tree[off].query), off); |
355 | off); | ||
356 | #endif | 349 | #endif |
357 | te->uri = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri)); | 350 | te->uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); |
358 | te->uri->type = chk; | 351 | te->uri->type = chk; |
359 | te->uri->data.chk.chk = te->chk_tree[off]; | 352 | te->uri->data.chk.chk = te->chk_tree[off]; |
360 | te->uri->data.chk.file_length = GNUNET_htonll (te->size); | 353 | te->uri->data.chk.file_length = GNUNET_htonll (te->size); |
361 | te->in_next = GNUNET_NO; | 354 | te->in_next = GNUNET_NO; |
362 | te->cont (te->cls, NULL); | 355 | te->cont (te->cls, NULL); |
363 | return; | 356 | return; |
364 | } | 357 | } |
365 | if (0 == te->current_depth) | 358 | if (0 == te->current_depth) |
359 | { | ||
360 | /* read DBLOCK */ | ||
361 | pt_size = GNUNET_MIN (DBLOCK_SIZE, te->size - te->publish_offset); | ||
362 | if (pt_size != | ||
363 | te->reader (te->cls, te->publish_offset, pt_size, iob, &te->emsg)) | ||
366 | { | 364 | { |
367 | /* read DBLOCK */ | 365 | GNUNET_SCHEDULER_add_continuation (te->cont, |
368 | pt_size = GNUNET_MIN(DBLOCK_SIZE, | 366 | te->cls, |
369 | te->size - te->publish_offset); | 367 | GNUNET_SCHEDULER_REASON_TIMEOUT); |
370 | if (pt_size != | 368 | te->in_next = GNUNET_NO; |
371 | te->reader (te->cls, | 369 | return; |
372 | te->publish_offset, | ||
373 | pt_size, | ||
374 | iob, | ||
375 | &te->emsg)) | ||
376 | { | ||
377 | GNUNET_SCHEDULER_add_continuation (te->cont, | ||
378 | te->cls, | ||
379 | GNUNET_SCHEDULER_REASON_TIMEOUT); | ||
380 | te->in_next = GNUNET_NO; | ||
381 | return; | ||
382 | } | ||
383 | pt_block = iob; | ||
384 | } | 370 | } |
371 | pt_block = iob; | ||
372 | } | ||
385 | else | 373 | else |
386 | { | 374 | { |
387 | pt_size = GNUNET_FS_tree_compute_iblock_size (te->current_depth, | 375 | pt_size = GNUNET_FS_tree_compute_iblock_size (te->current_depth, |
388 | te->publish_offset); | 376 | te->publish_offset); |
389 | pt_block = &te->chk_tree[(te->current_depth - 1) * | 377 | pt_block = &te->chk_tree[(te->current_depth - 1) * CHK_PER_INODE]; |
390 | CHK_PER_INODE]; | 378 | } |
391 | } | 379 | off = compute_chk_offset (te->current_depth, te->publish_offset); |
392 | off = compute_chk_offset (te->current_depth, | ||
393 | te->publish_offset); | ||
394 | #if DEBUG_TREE | 380 | #if DEBUG_TREE |
395 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 381 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
396 | "TE is at offset %llu and depth %u with block size %u and target-CHK-offset %u\n", | 382 | "TE is at offset %llu and depth %u with block size %u and target-CHK-offset %u\n", |
397 | (unsigned long long) te->publish_offset, | 383 | (unsigned long long) te->publish_offset, |
398 | te->current_depth, | 384 | te->current_depth, (unsigned int) pt_size, (unsigned int) off); |
399 | (unsigned int) pt_size, | ||
400 | (unsigned int) off); | ||
401 | #endif | 385 | #endif |
402 | mychk = &te->chk_tree[te->current_depth*CHK_PER_INODE+off]; | 386 | mychk = &te->chk_tree[te->current_depth * CHK_PER_INODE + off]; |
403 | GNUNET_CRYPTO_hash (pt_block, pt_size, &mychk->key); | 387 | GNUNET_CRYPTO_hash (pt_block, pt_size, &mychk->key); |
404 | GNUNET_CRYPTO_hash_to_aes_key (&mychk->key, &sk, &iv); | 388 | GNUNET_CRYPTO_hash_to_aes_key (&mychk->key, &sk, &iv); |
405 | GNUNET_CRYPTO_aes_encrypt (pt_block, | 389 | GNUNET_CRYPTO_aes_encrypt (pt_block, pt_size, &sk, &iv, enc); |
406 | pt_size, | ||
407 | &sk, | ||
408 | &iv, | ||
409 | enc); | ||
410 | GNUNET_CRYPTO_hash (enc, pt_size, &mychk->query); | 390 | GNUNET_CRYPTO_hash (enc, pt_size, &mychk->query); |
411 | #if DEBUG_TREE | 391 | #if DEBUG_TREE |
412 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 392 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
413 | "TE calculates query to be `%s', stored at %u\n", | 393 | "TE calculates query to be `%s', stored at %u\n", |
414 | GNUNET_h2s (&mychk->query), | 394 | GNUNET_h2s (&mychk->query), |
415 | te->current_depth * CHK_PER_INODE + off); | 395 | te->current_depth * CHK_PER_INODE + off); |
416 | #endif | 396 | #endif |
417 | if (NULL != te->proc) | 397 | if (NULL != te->proc) |
418 | te->proc (te->cls, | 398 | te->proc (te->cls, |
419 | mychk, | 399 | mychk, |
420 | te->publish_offset, | 400 | te->publish_offset, |
421 | te->current_depth, | 401 | te->current_depth, |
422 | (0 == te->current_depth) | 402 | (0 == te->current_depth) |
423 | ? GNUNET_BLOCK_TYPE_FS_DBLOCK | 403 | ? GNUNET_BLOCK_TYPE_FS_DBLOCK |
424 | : GNUNET_BLOCK_TYPE_FS_IBLOCK, | 404 | : GNUNET_BLOCK_TYPE_FS_IBLOCK, enc, pt_size); |
425 | enc, | ||
426 | pt_size); | ||
427 | if (NULL != te->progress) | 405 | if (NULL != te->progress) |
428 | te->progress (te->cls, | 406 | te->progress (te->cls, |
429 | te->publish_offset, | 407 | te->publish_offset, pt_block, pt_size, te->current_depth); |
430 | pt_block, | 408 | if (0 == te->current_depth) |
431 | pt_size, | 409 | { |
432 | te->current_depth); | 410 | te->publish_offset += pt_size; |
433 | if (0 == te->current_depth) | 411 | if ((te->publish_offset == te->size) || |
434 | { | 412 | (0 == te->publish_offset % (CHK_PER_INODE * DBLOCK_SIZE))) |
435 | te->publish_offset += pt_size; | 413 | te->current_depth++; |
436 | if ( (te->publish_offset == te->size) || | 414 | } |
437 | (0 == te->publish_offset % (CHK_PER_INODE * DBLOCK_SIZE) ) ) | ||
438 | te->current_depth++; | ||
439 | } | ||
440 | else | 415 | else |
441 | { | 416 | { |
442 | if ( (off == CHK_PER_INODE) || | 417 | if ((off == CHK_PER_INODE) || (te->publish_offset == te->size)) |
443 | (te->publish_offset == te->size) ) | 418 | te->current_depth++; |
444 | te->current_depth++; | 419 | else |
445 | else | 420 | te->current_depth = 0; |
446 | te->current_depth = 0; | 421 | } |
447 | } | ||
448 | te->in_next = GNUNET_NO; | 422 | te->in_next = GNUNET_NO; |
449 | } | 423 | } |
450 | 424 | ||
@@ -460,16 +434,15 @@ GNUNET_FS_tree_encoder_next (struct GNUNET_FS_TreeEncoder * te) | |||
460 | * prior to completion and prior to an internal error, | 434 | * prior to completion and prior to an internal error, |
461 | * both "*uri" and "*emsg" will be set to NULL). | 435 | * both "*uri" and "*emsg" will be set to NULL). |
462 | */ | 436 | */ |
463 | void GNUNET_FS_tree_encoder_finish (struct GNUNET_FS_TreeEncoder *te, | 437 | void |
464 | struct GNUNET_FS_Uri **uri, | 438 | GNUNET_FS_tree_encoder_finish (struct GNUNET_FS_TreeEncoder *te, |
465 | char **emsg) | 439 | struct GNUNET_FS_Uri **uri, char **emsg) |
466 | { | 440 | { |
467 | GNUNET_assert (GNUNET_NO == te->in_next); | 441 | GNUNET_assert (GNUNET_NO == te->in_next); |
468 | if (uri != NULL) | 442 | if (uri != NULL) |
469 | *uri = te->uri; | 443 | *uri = te->uri; |
470 | else | 444 | else if (NULL != te->uri) |
471 | if (NULL != te->uri) | 445 | GNUNET_FS_uri_destroy (te->uri); |
472 | GNUNET_FS_uri_destroy (te->uri); | ||
473 | if (emsg != NULL) | 446 | if (emsg != NULL) |
474 | *emsg = te->emsg; | 447 | *emsg = te->emsg; |
475 | else | 448 | else |