diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-02-18 19:03:26 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-02-18 19:03:26 +0000 |
commit | c456c5bb7f9b95d1800ad6e2892a77f40a08493e (patch) | |
tree | 8b04e75f8a65225848816d8e588b28413ff9d758 /src/fs/fs_publish.c | |
parent | 6d0a62078edfa5c0001acb93d517c674c5124f4e (diff) | |
download | gnunet-c456c5bb7f9b95d1800ad6e2892a77f40a08493e.tar.gz gnunet-c456c5bb7f9b95d1800ad6e2892a77f40a08493e.zip |
make all (?) asynchronously operating FS operations actually cancel-able
Diffstat (limited to 'src/fs/fs_publish.c')
-rw-r--r-- | src/fs/fs_publish.c | 397 |
1 files changed, 34 insertions, 363 deletions
diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c index 444128016..134dd21e4 100644 --- a/src/fs/fs_publish.c +++ b/src/fs/fs_publish.c | |||
@@ -34,13 +34,6 @@ | |||
34 | #include "fs_api.h" | 34 | #include "fs_api.h" |
35 | #include "fs_tree.h" | 35 | #include "fs_tree.h" |
36 | 36 | ||
37 | #define DEBUG_PUBLISH GNUNET_EXTRA_LOGGING | ||
38 | |||
39 | /** | ||
40 | * Maximum legal size for a kblock. | ||
41 | */ | ||
42 | #define MAX_KBLOCK_SIZE (60 * 1024) | ||
43 | |||
44 | 37 | ||
45 | /** | 38 | /** |
46 | * Fill in all of the generic fields for | 39 | * Fill in all of the generic fields for |
@@ -78,17 +71,12 @@ GNUNET_FS_publish_make_status_ (struct GNUNET_FS_ProgressInfo *pi, | |||
78 | /** | 71 | /** |
79 | * Cleanup the publish context, we're done with it. | 72 | * Cleanup the publish context, we're done with it. |
80 | * | 73 | * |
81 | * @param cls struct to clean up after | 74 | * @param pc struct to clean up |
82 | * @param tc scheduler context | ||
83 | */ | 75 | */ |
84 | static void | 76 | static void |
85 | publish_cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 77 | publish_cleanup (struct GNUNET_FS_PublishContext *pc) |
86 | { | 78 | { |
87 | struct GNUNET_FS_PublishContext *pc = cls; | ||
88 | |||
89 | #if DEBUG_PUBLISH | ||
90 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up publish context (done!)\n"); | 79 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up publish context (done!)\n"); |
91 | #endif | ||
92 | if (pc->fhc != NULL) | 80 | if (pc->fhc != NULL) |
93 | { | 81 | { |
94 | GNUNET_CRYPTO_hash_file_cancel (pc->fhc); | 82 | GNUNET_CRYPTO_hash_file_cancel (pc->fhc); |
@@ -136,15 +124,6 @@ ds_put_cont (void *cls, int success, | |||
136 | struct GNUNET_FS_ProgressInfo pi; | 124 | struct GNUNET_FS_ProgressInfo pi; |
137 | 125 | ||
138 | pc->qre = NULL; | 126 | pc->qre = NULL; |
139 | if (GNUNET_SYSERR == pc->in_network_wait) | ||
140 | { | ||
141 | /* we were aborted in the meantime, finish shutdown! */ | ||
142 | GNUNET_SCHEDULER_add_continuation (&publish_cleanup, pc, | ||
143 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
144 | return; | ||
145 | } | ||
146 | GNUNET_assert (GNUNET_YES == pc->in_network_wait); | ||
147 | pc->in_network_wait = GNUNET_NO; | ||
148 | if (GNUNET_SYSERR == success) | 127 | if (GNUNET_SYSERR == success) |
149 | { | 128 | { |
150 | GNUNET_asprintf (&pc->fi_pos->emsg, _("Publishing failed: %s"), msg); | 129 | GNUNET_asprintf (&pc->fi_pos->emsg, _("Publishing failed: %s"), msg); |
@@ -238,9 +217,7 @@ finish_release_reserve (void *cls, int success, | |||
238 | struct GNUNET_FS_PublishContext *pc = cls; | 217 | struct GNUNET_FS_PublishContext *pc = cls; |
239 | 218 | ||
240 | pc->qre = NULL; | 219 | pc->qre = NULL; |
241 | #if DEBUG_PUBLISH | ||
242 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Releasing reserve done!\n"); | 220 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Releasing reserve done!\n"); |
243 | #endif | ||
244 | signal_publish_completion (pc->fi, pc); | 221 | signal_publish_completion (pc->fi, pc); |
245 | pc->all_done = GNUNET_YES; | 222 | pc->all_done = GNUNET_YES; |
246 | GNUNET_FS_publish_sync_ (pc); | 223 | GNUNET_FS_publish_sync_ (pc); |
@@ -261,6 +238,7 @@ publish_sblocks_cont (void *cls, const struct GNUNET_FS_Uri *uri, | |||
261 | { | 238 | { |
262 | struct GNUNET_FS_PublishContext *pc = cls; | 239 | struct GNUNET_FS_PublishContext *pc = cls; |
263 | 240 | ||
241 | pc->sks_pc = NULL; | ||
264 | if (NULL != emsg) | 242 | if (NULL != emsg) |
265 | { | 243 | { |
266 | signal_publish_error (pc->fi, pc, emsg); | 244 | signal_publish_error (pc->fi, pc, emsg); |
@@ -292,9 +270,9 @@ static void | |||
292 | publish_sblock (struct GNUNET_FS_PublishContext *pc) | 270 | publish_sblock (struct GNUNET_FS_PublishContext *pc) |
293 | { | 271 | { |
294 | if (NULL != pc->namespace) | 272 | if (NULL != pc->namespace) |
295 | GNUNET_FS_publish_sks (pc->h, pc->namespace, pc->nid, pc->nuid, | 273 | pc->sks_pc = GNUNET_FS_publish_sks (pc->h, pc->namespace, pc->nid, pc->nuid, |
296 | pc->fi->meta, pc->fi->chk_uri, &pc->fi->bo, | 274 | pc->fi->meta, pc->fi->chk_uri, &pc->fi->bo, |
297 | pc->options, &publish_sblocks_cont, pc); | 275 | pc->options, &publish_sblocks_cont, pc); |
298 | else | 276 | else |
299 | publish_sblocks_cont (pc, NULL, NULL); | 277 | publish_sblocks_cont (pc, NULL, NULL); |
300 | } | 278 | } |
@@ -316,25 +294,22 @@ publish_kblocks_cont (void *cls, const struct GNUNET_FS_Uri *uri, | |||
316 | struct GNUNET_FS_PublishContext *pc = cls; | 294 | struct GNUNET_FS_PublishContext *pc = cls; |
317 | struct GNUNET_FS_FileInformation *p = pc->fi_pos; | 295 | struct GNUNET_FS_FileInformation *p = pc->fi_pos; |
318 | 296 | ||
297 | pc->ksk_pc = NULL; | ||
319 | if (NULL != emsg) | 298 | if (NULL != emsg) |
320 | { | 299 | { |
321 | #if DEBUG_PUBLISH | ||
322 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading KSK blocks: %s\n", | 300 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading KSK blocks: %s\n", |
323 | emsg); | 301 | emsg); |
324 | #endif | ||
325 | signal_publish_error (p, pc, emsg); | 302 | signal_publish_error (p, pc, emsg); |
326 | GNUNET_FS_file_information_sync_ (p); | 303 | GNUNET_FS_file_information_sync_ (p); |
327 | GNUNET_FS_publish_sync_ (pc); | 304 | GNUNET_FS_publish_sync_ (pc); |
328 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); | 305 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); |
329 | pc->upload_task = | 306 | pc->upload_task = |
330 | GNUNET_SCHEDULER_add_with_priority | 307 | GNUNET_SCHEDULER_add_with_priority |
331 | (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc); | 308 | (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc); |
332 | return; | 309 | return; |
333 | } | 310 | } |
334 | #if DEBUG_PUBLISH | ||
335 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 311 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
336 | "KSK blocks published, moving on to next file\n"); | 312 | "KSK blocks published, moving on to next file\n"); |
337 | #endif | ||
338 | if (NULL != p->dir) | 313 | if (NULL != p->dir) |
339 | signal_publish_completion (p, pc); | 314 | signal_publish_completion (p, pc); |
340 | /* move on to next file */ | 315 | /* move on to next file */ |
@@ -415,9 +390,7 @@ encode_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
415 | p->te = NULL; | 390 | p->te = NULL; |
416 | if (NULL != emsg) | 391 | if (NULL != emsg) |
417 | { | 392 | { |
418 | #if DEBUG_PUBLISH | ||
419 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error during tree walk: %s\n", emsg); | 393 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error during tree walk: %s\n", emsg); |
420 | #endif | ||
421 | GNUNET_asprintf (&p->emsg, _("Publishing failed: %s"), emsg); | 394 | GNUNET_asprintf (&p->emsg, _("Publishing failed: %s"), emsg); |
422 | GNUNET_free (emsg); | 395 | GNUNET_free (emsg); |
423 | pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR; | 396 | pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR; |
@@ -425,9 +398,7 @@ encode_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
425 | pi.value.publish.specifics.error.message = p->emsg; | 398 | pi.value.publish.specifics.error.message = p->emsg; |
426 | p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, 0); | 399 | p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, 0); |
427 | } | 400 | } |
428 | #if DEBUG_PUBLISH | ||
429 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished with tree encoder\n"); | 401 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished with tree encoder\n"); |
430 | #endif | ||
431 | /* final progress event */ | 402 | /* final progress event */ |
432 | flen = GNUNET_FS_uri_chk_get_file_size (p->chk_uri); | 403 | flen = GNUNET_FS_uri_chk_get_file_size (p->chk_uri); |
433 | pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS; | 404 | pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS; |
@@ -471,9 +442,7 @@ block_proc (void *cls, const struct ContentHashKey *chk, uint64_t offset, | |||
471 | p = pc->fi_pos; | 442 | p = pc->fi_pos; |
472 | if (NULL == pc->dsh) | 443 | if (NULL == pc->dsh) |
473 | { | 444 | { |
474 | #if DEBUG_PUBLISH | ||
475 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for datastore connection\n"); | 445 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for datastore connection\n"); |
476 | #endif | ||
477 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); | 446 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); |
478 | pc->upload_task = | 447 | pc->upload_task = |
479 | GNUNET_SCHEDULER_add_with_priority | 448 | GNUNET_SCHEDULER_add_with_priority |
@@ -481,17 +450,13 @@ block_proc (void *cls, const struct ContentHashKey *chk, uint64_t offset, | |||
481 | return; | 450 | return; |
482 | } | 451 | } |
483 | 452 | ||
484 | GNUNET_assert (GNUNET_NO == pc->in_network_wait); | ||
485 | pc->in_network_wait = GNUNET_YES; | ||
486 | if ((!p->is_directory) && (GNUNET_YES == p->data.file.do_index) && | 453 | if ((!p->is_directory) && (GNUNET_YES == p->data.file.do_index) && |
487 | (type == GNUNET_BLOCK_TYPE_FS_DBLOCK)) | 454 | (type == GNUNET_BLOCK_TYPE_FS_DBLOCK)) |
488 | { | 455 | { |
489 | #if DEBUG_PUBLISH | ||
490 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 456 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
491 | "Indexing block `%s' for offset %llu with index size %u\n", | 457 | "Indexing block `%s' for offset %llu with index size %u\n", |
492 | GNUNET_h2s (&chk->query), (unsigned long long) offset, | 458 | GNUNET_h2s (&chk->query), (unsigned long long) offset, |
493 | sizeof (struct OnDemandBlock)); | 459 | sizeof (struct OnDemandBlock)); |
494 | #endif | ||
495 | odb.offset = GNUNET_htonll (offset); | 460 | odb.offset = GNUNET_htonll (offset); |
496 | odb.file_id = p->data.file.file_id; | 461 | odb.file_id = p->data.file.file_id; |
497 | GNUNET_assert (pc->qre == NULL); | 462 | GNUNET_assert (pc->qre == NULL); |
@@ -505,12 +470,10 @@ block_proc (void *cls, const struct ContentHashKey *chk, uint64_t offset, | |||
505 | &ds_put_cont, pc); | 470 | &ds_put_cont, pc); |
506 | return; | 471 | return; |
507 | } | 472 | } |
508 | #if DEBUG_PUBLISH | ||
509 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 473 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
510 | "Publishing block `%s' for offset %llu with size %u\n", | 474 | "Publishing block `%s' for offset %llu with size %u\n", |
511 | GNUNET_h2s (&chk->query), (unsigned long long) offset, | 475 | GNUNET_h2s (&chk->query), (unsigned long long) offset, |
512 | (unsigned int) block_size); | 476 | (unsigned int) block_size); |
513 | #endif | ||
514 | GNUNET_assert (pc->qre == NULL); | 477 | GNUNET_assert (pc->qre == NULL); |
515 | pc->qre = | 478 | pc->qre = |
516 | GNUNET_DATASTORE_put (pc->dsh, (p->is_directory) ? 0 : pc->rid, | 479 | GNUNET_DATASTORE_put (pc->dsh, (p->is_directory) ? 0 : pc->rid, |
@@ -573,9 +536,7 @@ publish_content (struct GNUNET_FS_PublishContext *pc) | |||
573 | { | 536 | { |
574 | if (p->is_directory) | 537 | if (p->is_directory) |
575 | { | 538 | { |
576 | #if DEBUG_PUBLISH | ||
577 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating directory\n"); | 539 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating directory\n"); |
578 | #endif | ||
579 | db = GNUNET_FS_directory_builder_create (p->meta); | 540 | db = GNUNET_FS_directory_builder_create (p->meta); |
580 | dirpos = p->data.dir.entries; | 541 | dirpos = p->data.dir.entries; |
581 | while (NULL != dirpos) | 542 | while (NULL != dirpos) |
@@ -617,18 +578,14 @@ publish_content (struct GNUNET_FS_PublishContext *pc) | |||
617 | GNUNET_FS_file_information_sync_ (p); | 578 | GNUNET_FS_file_information_sync_ (p); |
618 | } | 579 | } |
619 | size = (p->is_directory) ? p->data.dir.dir_size : p->data.file.file_size; | 580 | size = (p->is_directory) ? p->data.dir.dir_size : p->data.file.file_size; |
620 | #if DEBUG_PUBLISH | ||
621 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating tree encoder\n"); | 581 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating tree encoder\n"); |
622 | #endif | ||
623 | p->te = | 582 | p->te = |
624 | GNUNET_FS_tree_encoder_create (pc->h, size, pc, &block_reader, | 583 | GNUNET_FS_tree_encoder_create (pc->h, size, pc, &block_reader, |
625 | &block_proc, &progress_proc, | 584 | &block_proc, &progress_proc, |
626 | &encode_cont); | 585 | &encode_cont); |
627 | 586 | ||
628 | } | 587 | } |
629 | #if DEBUG_PUBLISH | ||
630 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing next block from tree\n"); | 588 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing next block from tree\n"); |
631 | #endif | ||
632 | GNUNET_FS_tree_encoder_next (p->te); | 589 | GNUNET_FS_tree_encoder_next (p->te); |
633 | } | 590 | } |
634 | 591 | ||
@@ -739,10 +696,8 @@ hash_for_index_cb (void *cls, const GNUNET_HashCode * res) | |||
739 | publish_content (pc); | 696 | publish_content (pc); |
740 | return; | 697 | return; |
741 | } | 698 | } |
742 | #if DEBUG_PUBLISH | ||
743 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hash of indexed file `%s' is `%s'\n", | 699 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hash of indexed file `%s' is `%s'\n", |
744 | p->filename, GNUNET_h2s (res)); | 700 | p->filename, GNUNET_h2s (res)); |
745 | #endif | ||
746 | if (0 != (pc->options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) | 701 | if (0 != (pc->options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) |
747 | { | 702 | { |
748 | p->data.file.file_id = *res; | 703 | p->data.file.file_id = *res; |
@@ -779,13 +734,11 @@ hash_for_index_cb (void *cls, const GNUNET_HashCode * res) | |||
779 | ism->device = GNUNET_htonll (dev); | 734 | ism->device = GNUNET_htonll (dev); |
780 | ism->inode = GNUNET_htonll (ino); | 735 | ism->inode = GNUNET_htonll (ino); |
781 | } | 736 | } |
782 | #if DEBUG_PUBLISH | ||
783 | else | 737 | else |
784 | { | 738 | { |
785 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 739 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
786 | _("Failed to get file identifiers for `%s'\n"), p->filename); | 740 | _("Failed to get file identifiers for `%s'\n"), p->filename); |
787 | } | 741 | } |
788 | #endif | ||
789 | ism->file_id = *res; | 742 | ism->file_id = *res; |
790 | memcpy (&ism[1], fn, slen); | 743 | memcpy (&ism[1], fn, slen); |
791 | GNUNET_free (fn); | 744 | GNUNET_free (fn); |
@@ -820,10 +773,8 @@ GNUNET_FS_publish_main_ (void *cls, | |||
820 | p = pc->fi_pos; | 773 | p = pc->fi_pos; |
821 | if (NULL == p) | 774 | if (NULL == p) |
822 | { | 775 | { |
823 | #if DEBUG_PUBLISH | ||
824 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 776 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
825 | "Publishing complete, now publishing SKS and KSK blocks.\n"); | 777 | "Publishing complete, now publishing SKS and KSK blocks.\n"); |
826 | #endif | ||
827 | /* upload of entire hierarchy complete, | 778 | /* upload of entire hierarchy complete, |
828 | * publish namespace entries */ | 779 | * publish namespace entries */ |
829 | GNUNET_FS_publish_sync_ (pc); | 780 | GNUNET_FS_publish_sync_ (pc); |
@@ -841,9 +792,7 @@ GNUNET_FS_publish_main_ (void *cls, | |||
841 | /* abort on error */ | 792 | /* abort on error */ |
842 | if (NULL != p->emsg) | 793 | if (NULL != p->emsg) |
843 | { | 794 | { |
844 | #if DEBUG_PUBLISH | ||
845 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading: %s\n", p->emsg); | 795 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading: %s\n", p->emsg); |
846 | #endif | ||
847 | /* error with current file, abort all | 796 | /* error with current file, abort all |
848 | * related files as well! */ | 797 | * related files as well! */ |
849 | while (NULL != p->dir) | 798 | while (NULL != p->dir) |
@@ -873,10 +822,8 @@ GNUNET_FS_publish_main_ (void *cls, | |||
873 | /* handle completion */ | 822 | /* handle completion */ |
874 | if (NULL != p->chk_uri) | 823 | if (NULL != p->chk_uri) |
875 | { | 824 | { |
876 | #if DEBUG_PUBLISH | ||
877 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 825 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
878 | "File upload complete, now publishing KSK blocks.\n"); | 826 | "File upload complete, now publishing KSK blocks.\n"); |
879 | #endif | ||
880 | if (0 == p->bo.anonymity_level) | 827 | if (0 == p->bo.anonymity_level) |
881 | { | 828 | { |
882 | /* zero anonymity, box CHK URI in LOC URI */ | 829 | /* zero anonymity, box CHK URI in LOC URI */ |
@@ -890,8 +837,8 @@ GNUNET_FS_publish_main_ (void *cls, | |||
890 | /* upload of "p" complete, publish KBlocks! */ | 837 | /* upload of "p" complete, publish KBlocks! */ |
891 | if (p->keywords != NULL) | 838 | if (p->keywords != NULL) |
892 | { | 839 | { |
893 | GNUNET_FS_publish_ksk (pc->h, p->keywords, p->meta, p->chk_uri, &p->bo, | 840 | pc->ksk_pc = GNUNET_FS_publish_ksk (pc->h, p->keywords, p->meta, p->chk_uri, &p->bo, |
894 | pc->options, &publish_kblocks_cont, pc); | 841 | pc->options, &publish_kblocks_cont, pc); |
895 | } | 842 | } |
896 | else | 843 | else |
897 | { | 844 | { |
@@ -959,9 +906,7 @@ fip_signal_start (void *cls, struct GNUNET_FS_FileInformation *fi, | |||
959 | pc->skip_next_fi_callback = GNUNET_NO; | 906 | pc->skip_next_fi_callback = GNUNET_NO; |
960 | return GNUNET_OK; | 907 | return GNUNET_OK; |
961 | } | 908 | } |
962 | #if DEBUG_PUBLISH | ||
963 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting publish operation\n"); | 909 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting publish operation\n"); |
964 | #endif | ||
965 | if (*do_index) | 910 | if (*do_index) |
966 | { | 911 | { |
967 | /* space for on-demand blocks */ | 912 | /* space for on-demand blocks */ |
@@ -1043,9 +988,17 @@ fip_signal_suspend (void *cls, struct GNUNET_FS_FileInformation *fi, | |||
1043 | pc->skip_next_fi_callback = GNUNET_YES; | 988 | pc->skip_next_fi_callback = GNUNET_YES; |
1044 | GNUNET_FS_file_information_inspect (fi, &fip_signal_suspend, pc); | 989 | GNUNET_FS_file_information_inspect (fi, &fip_signal_suspend, pc); |
1045 | } | 990 | } |
1046 | #if DEBUG_PUBLISH | 991 | if (NULL != pc->ksk_pc) |
992 | { | ||
993 | GNUNET_FS_publish_ksk_cancel (pc->ksk_pc); | ||
994 | pc->ksk_pc = NULL; | ||
995 | } | ||
996 | if (NULL != pc->sks_pc) | ||
997 | { | ||
998 | GNUNET_FS_publish_sks_cancel (pc->sks_pc); | ||
999 | pc->sks_pc = NULL; | ||
1000 | } | ||
1047 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suspending publish operation\n"); | 1001 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suspending publish operation\n"); |
1048 | #endif | ||
1049 | GNUNET_free_non_null (fi->serialization); | 1002 | GNUNET_free_non_null (fi->serialization); |
1050 | fi->serialization = NULL; | 1003 | fi->serialization = NULL; |
1051 | off = (fi->chk_uri == NULL) ? 0 : length; | 1004 | off = (fi->chk_uri == NULL) ? 0 : length; |
@@ -1086,7 +1039,7 @@ GNUNET_FS_publish_signal_suspend_ (void *cls) | |||
1086 | GNUNET_FS_file_information_inspect (pc->fi, &fip_signal_suspend, pc); | 1039 | GNUNET_FS_file_information_inspect (pc->fi, &fip_signal_suspend, pc); |
1087 | GNUNET_FS_end_top (pc->h, pc->top); | 1040 | GNUNET_FS_end_top (pc->h, pc->top); |
1088 | pc->top = NULL; | 1041 | pc->top = NULL; |
1089 | publish_cleanup (pc, NULL); | 1042 | publish_cleanup (pc); |
1090 | } | 1043 | } |
1091 | 1044 | ||
1092 | 1045 | ||
@@ -1107,9 +1060,7 @@ finish_reserve (void *cls, int success, | |||
1107 | struct GNUNET_FS_PublishContext *pc = cls; | 1060 | struct GNUNET_FS_PublishContext *pc = cls; |
1108 | 1061 | ||
1109 | pc->qre = NULL; | 1062 | pc->qre = NULL; |
1110 | #if DEBUG_PUBLISH | ||
1111 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reservation complete (%d)!\n", success); | 1063 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reservation complete (%d)!\n", success); |
1112 | #endif | ||
1113 | if ((msg != NULL) || (success <= 0)) | 1064 | if ((msg != NULL) || (success <= 0)) |
1114 | { | 1065 | { |
1115 | GNUNET_asprintf (&pc->fi->emsg, _("Insufficient space for publishing: %s"), | 1066 | GNUNET_asprintf (&pc->fi->emsg, _("Insufficient space for publishing: %s"), |
@@ -1267,14 +1218,17 @@ GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc) | |||
1267 | struct GNUNET_FS_ProgressInfo pi; | 1218 | struct GNUNET_FS_ProgressInfo pi; |
1268 | uint64_t off; | 1219 | uint64_t off; |
1269 | 1220 | ||
1270 | #if DEBUG_PUBLISH | ||
1271 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish stop called\n"); | 1221 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish stop called\n"); |
1272 | #endif | ||
1273 | GNUNET_FS_end_top (pc->h, pc->top); | 1222 | GNUNET_FS_end_top (pc->h, pc->top); |
1274 | if (NULL != pc->qre) | 1223 | if (NULL != pc->ksk_pc) |
1275 | { | 1224 | { |
1276 | GNUNET_DATASTORE_cancel (pc->qre); | 1225 | GNUNET_FS_publish_ksk_cancel (pc->ksk_pc); |
1277 | pc->qre = NULL; | 1226 | pc->ksk_pc = NULL; |
1227 | } | ||
1228 | if (NULL != pc->sks_pc) | ||
1229 | { | ||
1230 | GNUNET_FS_publish_sks_cancel (pc->sks_pc); | ||
1231 | pc->sks_pc = NULL; | ||
1278 | } | 1232 | } |
1279 | if (GNUNET_SCHEDULER_NO_TASK != pc->upload_task) | 1233 | if (GNUNET_SCHEDULER_NO_TASK != pc->upload_task) |
1280 | { | 1234 | { |
@@ -1300,299 +1254,16 @@ GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc) | |||
1300 | GNUNET_free (pc->serialization); | 1254 | GNUNET_free (pc->serialization); |
1301 | pc->serialization = NULL; | 1255 | pc->serialization = NULL; |
1302 | } | 1256 | } |
1303 | if (GNUNET_YES == pc->in_network_wait) | 1257 | if (NULL != pc->qre) |
1304 | { | 1258 | { |
1305 | pc->in_network_wait = GNUNET_SYSERR; | 1259 | GNUNET_DATASTORE_cancel (pc->qre); |
1306 | return; | 1260 | pc->qre = NULL; |
1307 | } | 1261 | } |
1308 | pi.status = GNUNET_FS_STATUS_PUBLISH_STOPPED; | 1262 | pi.status = GNUNET_FS_STATUS_PUBLISH_STOPPED; |
1309 | GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, pc, pc->fi, off)); | 1263 | GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, pc, pc->fi, off)); |
1310 | publish_cleanup (pc, NULL); | 1264 | publish_cleanup (pc); |
1311 | } | 1265 | } |
1312 | 1266 | ||
1313 | 1267 | ||
1314 | /** | ||
1315 | * Context for the KSK publication. | ||
1316 | */ | ||
1317 | struct PublishKskContext | ||
1318 | { | ||
1319 | |||
1320 | /** | ||
1321 | * Keywords to use. | ||
1322 | */ | ||
1323 | struct GNUNET_FS_Uri *ksk_uri; | ||
1324 | |||
1325 | /** | ||
1326 | * Global FS context. | ||
1327 | */ | ||
1328 | struct GNUNET_FS_Handle *h; | ||
1329 | |||
1330 | /** | ||
1331 | * The master block that we are sending | ||
1332 | * (in plaintext), has "mdsize+slen" more | ||
1333 | * bytes than the struct would suggest. | ||
1334 | */ | ||
1335 | struct KBlock *kb; | ||
1336 | |||
1337 | /** | ||
1338 | * Buffer of the same size as "kb" for | ||
1339 | * the encrypted version. | ||
1340 | */ | ||
1341 | struct KBlock *cpy; | ||
1342 | |||
1343 | /** | ||
1344 | * Handle to the datastore, NULL if we are just | ||
1345 | * simulating. | ||
1346 | */ | ||
1347 | struct GNUNET_DATASTORE_Handle *dsh; | ||
1348 | |||
1349 | /** | ||
1350 | * Handle to datastore PUT request. | ||
1351 | */ | ||
1352 | struct GNUNET_DATASTORE_QueueEntry *qre; | ||
1353 | |||
1354 | /** | ||
1355 | * Function to call once we're done. | ||
1356 | */ | ||
1357 | GNUNET_FS_PublishContinuation cont; | ||
1358 | |||
1359 | /** | ||
1360 | * Closure for cont. | ||
1361 | */ | ||
1362 | void *cont_cls; | ||
1363 | |||
1364 | /** | ||
1365 | * When should the KBlocks expire? | ||
1366 | */ | ||
1367 | struct GNUNET_FS_BlockOptions bo; | ||
1368 | |||
1369 | /** | ||
1370 | * Size of the serialized metadata. | ||
1371 | */ | ||
1372 | ssize_t mdsize; | ||
1373 | |||
1374 | /** | ||
1375 | * Size of the (CHK) URI as a string. | ||
1376 | */ | ||
1377 | size_t slen; | ||
1378 | |||
1379 | /** | ||
1380 | * Keyword that we are currently processing. | ||
1381 | */ | ||
1382 | unsigned int i; | ||
1383 | |||
1384 | }; | ||
1385 | |||
1386 | |||
1387 | /** | ||
1388 | * Continuation of "GNUNET_FS_publish_ksk" that performs | ||
1389 | * the actual publishing operation (iterating over all | ||
1390 | * of the keywords). | ||
1391 | * | ||
1392 | * @param cls closure of type "struct PublishKskContext*" | ||
1393 | * @param tc unused | ||
1394 | */ | ||
1395 | static void | ||
1396 | publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
1397 | |||
1398 | |||
1399 | /** | ||
1400 | * Function called by the datastore API with | ||
1401 | * the result from the PUT request. | ||
1402 | * | ||
1403 | * @param cls closure of type "struct PublishKskContext*" | ||
1404 | * @param success GNUNET_OK on success | ||
1405 | * @param min_expiration minimum expiration time required for content to be stored | ||
1406 | * @param msg error message (or NULL) | ||
1407 | */ | ||
1408 | static void | ||
1409 | kb_put_cont (void *cls, int success, | ||
1410 | struct GNUNET_TIME_Absolute min_expiration, | ||
1411 | const char *msg) | ||
1412 | { | ||
1413 | struct PublishKskContext *pkc = cls; | ||
1414 | |||
1415 | pkc->qre = NULL; | ||
1416 | if (GNUNET_OK != success) | ||
1417 | { | ||
1418 | #if DEBUG_PUBLISH | ||
1419 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KB PUT operation complete\n"); | ||
1420 | #endif | ||
1421 | if (NULL != pkc->dsh) | ||
1422 | { | ||
1423 | GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO); | ||
1424 | pkc->dsh = NULL; | ||
1425 | } | ||
1426 | GNUNET_free (pkc->cpy); | ||
1427 | GNUNET_free (pkc->kb); | ||
1428 | pkc->cont (pkc->cont_cls, NULL, msg); | ||
1429 | GNUNET_FS_uri_destroy (pkc->ksk_uri); | ||
1430 | GNUNET_free (pkc); | ||
1431 | return; | ||
1432 | } | ||
1433 | GNUNET_SCHEDULER_add_continuation (&publish_ksk_cont, pkc, | ||
1434 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
1435 | } | ||
1436 | |||
1437 | |||
1438 | /** | ||
1439 | * Continuation of "GNUNET_FS_publish_ksk" that performs the actual | ||
1440 | * publishing operation (iterating over all of the keywords). | ||
1441 | * | ||
1442 | * @param cls closure of type "struct PublishKskContext*" | ||
1443 | * @param tc unused | ||
1444 | */ | ||
1445 | static void | ||
1446 | publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1447 | { | ||
1448 | struct PublishKskContext *pkc = cls; | ||
1449 | const char *keyword; | ||
1450 | GNUNET_HashCode key; | ||
1451 | GNUNET_HashCode query; | ||
1452 | struct GNUNET_CRYPTO_AesSessionKey skey; | ||
1453 | struct GNUNET_CRYPTO_AesInitializationVector iv; | ||
1454 | struct GNUNET_CRYPTO_RsaPrivateKey *pk; | ||
1455 | |||
1456 | |||
1457 | if ((pkc->i == pkc->ksk_uri->data.ksk.keywordCount) || (NULL == pkc->dsh)) | ||
1458 | { | ||
1459 | #if DEBUG_PUBLISH | ||
1460 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KSK PUT operation complete\n"); | ||
1461 | #endif | ||
1462 | if (NULL != pkc->dsh) | ||
1463 | { | ||
1464 | GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO); | ||
1465 | pkc->dsh = NULL; | ||
1466 | } | ||
1467 | GNUNET_free (pkc->cpy); | ||
1468 | GNUNET_free (pkc->kb); | ||
1469 | pkc->cont (pkc->cont_cls, pkc->ksk_uri, NULL); | ||
1470 | GNUNET_FS_uri_destroy (pkc->ksk_uri); | ||
1471 | GNUNET_free (pkc); | ||
1472 | return; | ||
1473 | } | ||
1474 | keyword = pkc->ksk_uri->data.ksk.keywords[pkc->i++]; | ||
1475 | #if DEBUG_PUBLISH | ||
1476 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing under keyword `%s'\n", | ||
1477 | keyword); | ||
1478 | #endif | ||
1479 | /* first character of keyword indicates if it is | ||
1480 | * mandatory or not -- ignore for hashing */ | ||
1481 | GNUNET_CRYPTO_hash (&keyword[1], strlen (&keyword[1]), &key); | ||
1482 | GNUNET_CRYPTO_hash_to_aes_key (&key, &skey, &iv); | ||
1483 | GNUNET_CRYPTO_aes_encrypt (&pkc->kb[1], pkc->slen + pkc->mdsize, &skey, &iv, | ||
1484 | &pkc->cpy[1]); | ||
1485 | pk = GNUNET_CRYPTO_rsa_key_create_from_hash (&key); | ||
1486 | GNUNET_assert (NULL != pk); | ||
1487 | GNUNET_CRYPTO_rsa_key_get_public (pk, &pkc->cpy->keyspace); | ||
1488 | GNUNET_CRYPTO_hash (&pkc->cpy->keyspace, | ||
1489 | sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), | ||
1490 | &query); | ||
1491 | GNUNET_assert (GNUNET_OK == | ||
1492 | GNUNET_CRYPTO_rsa_sign (pk, &pkc->cpy->purpose, | ||
1493 | &pkc->cpy->signature)); | ||
1494 | GNUNET_CRYPTO_rsa_key_free (pk); | ||
1495 | pkc->qre = | ||
1496 | GNUNET_DATASTORE_put (pkc->dsh, 0, &query, | ||
1497 | pkc->mdsize + sizeof (struct KBlock) + pkc->slen, | ||
1498 | pkc->cpy, GNUNET_BLOCK_TYPE_FS_KBLOCK, | ||
1499 | pkc->bo.content_priority, pkc->bo.anonymity_level, | ||
1500 | pkc->bo.replication_level, pkc->bo.expiration_time, | ||
1501 | -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT, | ||
1502 | &kb_put_cont, pkc); | ||
1503 | } | ||
1504 | |||
1505 | |||
1506 | /** | ||
1507 | * Publish a CHK under various keywords on GNUnet. | ||
1508 | * | ||
1509 | * @param h handle to the file sharing subsystem | ||
1510 | * @param ksk_uri keywords to use | ||
1511 | * @param meta metadata to use | ||
1512 | * @param uri URI to refer to in the KBlock | ||
1513 | * @param bo per-block options | ||
1514 | * @param options publication options | ||
1515 | * @param cont continuation | ||
1516 | * @param cont_cls closure for cont | ||
1517 | */ | ||
1518 | void | ||
1519 | GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h, | ||
1520 | const struct GNUNET_FS_Uri *ksk_uri, | ||
1521 | const struct GNUNET_CONTAINER_MetaData *meta, | ||
1522 | const struct GNUNET_FS_Uri *uri, | ||
1523 | const struct GNUNET_FS_BlockOptions *bo, | ||
1524 | enum GNUNET_FS_PublishOptions options, | ||
1525 | GNUNET_FS_PublishContinuation cont, void *cont_cls) | ||
1526 | { | ||
1527 | struct PublishKskContext *pkc; | ||
1528 | char *uris; | ||
1529 | size_t size; | ||
1530 | char *kbe; | ||
1531 | char *sptr; | ||
1532 | |||
1533 | GNUNET_assert (NULL != uri); | ||
1534 | pkc = GNUNET_malloc (sizeof (struct PublishKskContext)); | ||
1535 | pkc->h = h; | ||
1536 | pkc->bo = *bo; | ||
1537 | pkc->cont = cont; | ||
1538 | pkc->cont_cls = cont_cls; | ||
1539 | if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) | ||
1540 | { | ||
1541 | pkc->dsh = GNUNET_DATASTORE_connect (h->cfg); | ||
1542 | if (pkc->dsh == NULL) | ||
1543 | { | ||
1544 | cont (cont_cls, NULL, _("Could not connect to datastore.")); | ||
1545 | GNUNET_free (pkc); | ||
1546 | return; | ||
1547 | } | ||
1548 | } | ||
1549 | if (meta == NULL) | ||
1550 | pkc->mdsize = 0; | ||
1551 | else | ||
1552 | pkc->mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta); | ||
1553 | GNUNET_assert (pkc->mdsize >= 0); | ||
1554 | uris = GNUNET_FS_uri_to_string (uri); | ||
1555 | pkc->slen = strlen (uris) + 1; | ||
1556 | size = pkc->mdsize + sizeof (struct KBlock) + pkc->slen; | ||
1557 | if (size > MAX_KBLOCK_SIZE) | ||
1558 | { | ||
1559 | size = MAX_KBLOCK_SIZE; | ||
1560 | pkc->mdsize = size - sizeof (struct KBlock) - pkc->slen; | ||
1561 | } | ||
1562 | pkc->kb = GNUNET_malloc (size); | ||
1563 | kbe = (char *) &pkc->kb[1]; | ||
1564 | memcpy (kbe, uris, pkc->slen); | ||
1565 | GNUNET_free (uris); | ||
1566 | sptr = &kbe[pkc->slen]; | ||
1567 | if (meta != NULL) | ||
1568 | pkc->mdsize = | ||
1569 | GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, pkc->mdsize, | ||
1570 | GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); | ||
1571 | if (pkc->mdsize == -1) | ||
1572 | { | ||
1573 | GNUNET_break (0); | ||
1574 | GNUNET_free (pkc->kb); | ||
1575 | if (pkc->dsh != NULL) | ||
1576 | { | ||
1577 | GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO); | ||
1578 | pkc->dsh = NULL; | ||
1579 | } | ||
1580 | cont (cont_cls, NULL, _("Internal error.")); | ||
1581 | GNUNET_free (pkc); | ||
1582 | return; | ||
1583 | } | ||
1584 | size = sizeof (struct KBlock) + pkc->slen + pkc->mdsize; | ||
1585 | |||
1586 | pkc->cpy = GNUNET_malloc (size); | ||
1587 | pkc->cpy->purpose.size = | ||
1588 | htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + | ||
1589 | sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + | ||
1590 | pkc->mdsize + pkc->slen); | ||
1591 | pkc->cpy->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK); | ||
1592 | pkc->ksk_uri = GNUNET_FS_uri_dup (ksk_uri); | ||
1593 | GNUNET_SCHEDULER_add_continuation (&publish_ksk_cont, pkc, | ||
1594 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
1595 | } | ||
1596 | |||
1597 | 1268 | ||
1598 | /* end of fs_publish.c */ | 1269 | /* end of fs_publish.c */ |