diff options
author | Christian Grothoff <christian@grothoff.org> | 2010-04-30 12:37:39 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2010-04-30 12:37:39 +0000 |
commit | 200be29edf8956741de7d03f65a9b3aec407d2ce (patch) | |
tree | 0f11e27ee967f18ebdf7f43efbe025f0254f11ab | |
parent | 1cc43d608117c035c4986cf6b306b876e84a700e (diff) | |
download | gnunet-200be29edf8956741de7d03f65a9b3aec407d2ce.tar.gz gnunet-200be29edf8956741de7d03f65a9b3aec407d2ce.zip |
publish serialization stuff
-rw-r--r-- | src/fs/fs.c | 349 | ||||
-rw-r--r-- | src/fs/fs.h | 17 | ||||
-rw-r--r-- | src/fs/fs_namespace.c | 2 | ||||
-rw-r--r-- | src/fs/fs_publish.c | 3 |
4 files changed, 254 insertions, 117 deletions
diff --git a/src/fs/fs.c b/src/fs/fs.c index 44a35dbf7..837f59a10 100644 --- a/src/fs/fs.c +++ b/src/fs/fs.c | |||
@@ -300,6 +300,36 @@ get_write_handle (struct GNUNET_FS_Handle *h, | |||
300 | 300 | ||
301 | 301 | ||
302 | /** | 302 | /** |
303 | * Remove serialization/deserialization file from disk. | ||
304 | * | ||
305 | * @param h master context | ||
306 | * @param ext component of the path | ||
307 | * @param ent entity identifier | ||
308 | */ | ||
309 | static void | ||
310 | remove_sync_file (struct GNUNET_FS_Handle *h, | ||
311 | const char *ext, | ||
312 | const char *ent) | ||
313 | { | ||
314 | char *filename; | ||
315 | |||
316 | if ( (NULL == ent) || | ||
317 | (0 == strlen (ent)) ) | ||
318 | { | ||
319 | GNUNET_break (0); | ||
320 | return; | ||
321 | } | ||
322 | filename = get_serialization_file_name (h, ext, ent); | ||
323 | if (0 != UNLINK (filename)) | ||
324 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | ||
325 | "unlink", | ||
326 | filename); | ||
327 | GNUNET_free (filename); | ||
328 | } | ||
329 | |||
330 | |||
331 | |||
332 | /** | ||
303 | * Using the given serialization filename, try to deserialize | 333 | * Using the given serialization filename, try to deserialize |
304 | * the file-information tree associated with it. | 334 | * the file-information tree associated with it. |
305 | * | 335 | * |
@@ -516,6 +546,68 @@ deserialize_file_information (struct GNUNET_FS_Handle *h, | |||
516 | 546 | ||
517 | 547 | ||
518 | /** | 548 | /** |
549 | * Given a serialization name (full absolute path), return the | ||
550 | * basename of the file (without the path), which must only | ||
551 | * consist of the 6 random characters. | ||
552 | * | ||
553 | * @param fullname name to extract the basename from | ||
554 | * @return copy of the basename, NULL on error | ||
555 | */ | ||
556 | static char * | ||
557 | get_serialization_short_name (const char *fullname) | ||
558 | { | ||
559 | const char *end; | ||
560 | const char *nxt; | ||
561 | |||
562 | end = NULL; | ||
563 | nxt = fullname; | ||
564 | /* FIXME: we could do this faster since we know | ||
565 | the length of 'end'... */ | ||
566 | while ('\0' != nxt) | ||
567 | { | ||
568 | if (DIR_SEPARATOR == *nxt) | ||
569 | end = nxt + 1; | ||
570 | nxt++; | ||
571 | } | ||
572 | if ( (end == NULL) || | ||
573 | (strlen (end) == 0) ) | ||
574 | { | ||
575 | GNUNET_break (0); | ||
576 | return NULL; | ||
577 | } | ||
578 | GNUNET_break (6 == strlen (end)); | ||
579 | return GNUNET_strdup (end); | ||
580 | } | ||
581 | |||
582 | |||
583 | /** | ||
584 | * Create a new random name for serialization. | ||
585 | * | ||
586 | * @param h master context | ||
587 | * @param ext component of the path | ||
588 | * @return NULL on errror | ||
589 | */ | ||
590 | static char * | ||
591 | make_serialization_file_name (struct GNUNET_FS_Handle *h, | ||
592 | const char *ext) | ||
593 | { | ||
594 | char *fn; | ||
595 | char *dn; | ||
596 | char *ret; | ||
597 | |||
598 | /* FIXME: check if persistence option was set! */ | ||
599 | dn = get_serialization_file_name (h, ext, ""); | ||
600 | fn = GNUNET_DISK_mktemp (dn); | ||
601 | GNUNET_free (dn); | ||
602 | if (fn == NULL) | ||
603 | return NULL; /* epic fail */ | ||
604 | ret = get_serialization_short_name (fn); | ||
605 | GNUNET_free (fn); | ||
606 | return ret; | ||
607 | } | ||
608 | |||
609 | |||
610 | /** | ||
519 | * Create a temporary file on disk to store the current | 611 | * Create a temporary file on disk to store the current |
520 | * state of "fi" in. | 612 | * state of "fi" in. |
521 | * | 613 | * |
@@ -525,40 +617,16 @@ void | |||
525 | GNUNET_FS_file_information_sync_ (struct GNUNET_FS_FileInformation * fi) | 617 | GNUNET_FS_file_information_sync_ (struct GNUNET_FS_FileInformation * fi) |
526 | { | 618 | { |
527 | char *fn; | 619 | char *fn; |
528 | char *dn; | ||
529 | const char *end; | ||
530 | const char *nxt; | ||
531 | struct GNUNET_BIO_WriteHandle *wh; | 620 | struct GNUNET_BIO_WriteHandle *wh; |
532 | char b; | 621 | char b; |
533 | char *ksks; | 622 | char *ksks; |
534 | char *chks; | 623 | char *chks; |
535 | 624 | ||
625 | /* FIXME: check if persistence option was set! */ | ||
626 | if (NULL == fi->serialization) | ||
627 | fi->serialization = make_serialization_file_name (fi->h, "publish-fi"); | ||
536 | if (NULL == fi->serialization) | 628 | if (NULL == fi->serialization) |
537 | { | 629 | return; |
538 | dn = get_serialization_file_name (fi->h, "publish-fi", ""); | ||
539 | fn = GNUNET_DISK_mktemp (dn); | ||
540 | GNUNET_free (dn); | ||
541 | if (fn == NULL) | ||
542 | return; /* epic fail */ | ||
543 | end = NULL; | ||
544 | nxt = fn; | ||
545 | while ('\0' != nxt) | ||
546 | { | ||
547 | if (DIR_SEPARATOR == *nxt) | ||
548 | end = nxt + 1; | ||
549 | nxt++; | ||
550 | } | ||
551 | if ( (end == NULL) || | ||
552 | (strlen (end) == 0) ) | ||
553 | { | ||
554 | GNUNET_break (0); | ||
555 | GNUNET_free (fn); | ||
556 | return; | ||
557 | } | ||
558 | GNUNET_break (6 == strlen (end)); | ||
559 | fi->serialization = GNUNET_strdup (end); | ||
560 | GNUNET_free (fn); | ||
561 | } | ||
562 | wh = get_write_handle (fi->h, "publish-fi", fi->serialization); | 630 | wh = get_write_handle (fi->h, "publish-fi", fi->serialization); |
563 | if (wh == NULL) | 631 | if (wh == NULL) |
564 | { | 632 | { |
@@ -658,7 +726,7 @@ GNUNET_FS_file_information_sync_ (struct GNUNET_FS_FileInformation * fi) | |||
658 | GNUNET_BIO_write_close (wh)) | 726 | GNUNET_BIO_write_close (wh)) |
659 | return; /* done! */ | 727 | return; /* done! */ |
660 | cleanup: | 728 | cleanup: |
661 | GNUNET_BIO_write_close (wh); | 729 | (void) GNUNET_BIO_write_close (wh); |
662 | GNUNET_free_non_null (chks); | 730 | GNUNET_free_non_null (chks); |
663 | GNUNET_free_non_null (ksks); | 731 | GNUNET_free_non_null (ksks); |
664 | fn = get_serialization_file_name (fi->h, "publish-fi", fi->serialization); | 732 | fn = get_serialization_file_name (fi->h, "publish-fi", fi->serialization); |
@@ -762,99 +830,71 @@ deserialize_publish_file (void *cls, | |||
762 | char *fi_pos; | 830 | char *fi_pos; |
763 | char *emsg; | 831 | char *emsg; |
764 | 832 | ||
833 | pc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishContext)); | ||
834 | pc->h = h; | ||
835 | fi_root = NULL; | ||
836 | fi_pos = NULL; | ||
837 | ns = NULL; | ||
765 | rh = GNUNET_BIO_read_open (filename); | 838 | rh = GNUNET_BIO_read_open (filename); |
766 | if (rh == NULL) | 839 | if (rh == NULL) |
840 | goto cleanup; | ||
841 | if ( (GNUNET_OK != | ||
842 | GNUNET_BIO_read_string (rh, "publish-nid", &pc->nid, 1024)) || | ||
843 | (GNUNET_OK != | ||
844 | GNUNET_BIO_read_string (rh, "publish-nuid", &pc->nuid, 1024)) || | ||
845 | (GNUNET_OK != | ||
846 | GNUNET_BIO_read_int32 (rh, &options)) || | ||
847 | (GNUNET_OK != | ||
848 | GNUNET_BIO_read_int32 (rh, &all_done)) || | ||
849 | (GNUNET_OK != | ||
850 | GNUNET_BIO_read_string (rh, "publish-firoot", &fi_root, 128)) || | ||
851 | (GNUNET_OK != | ||
852 | GNUNET_BIO_read_string (rh, "publish-fipos", &fi_pos, 128)) || | ||
853 | (GNUNET_OK != | ||
854 | GNUNET_BIO_read_string (rh, "publish-ns", &ns, 1024)) ) | ||
855 | goto cleanup; | ||
856 | pc->options = options; | ||
857 | pc->all_done = all_done; | ||
858 | pc->fi = deserialize_file_information (h, fi_root); | ||
859 | if (pc->fi == NULL) | ||
860 | goto cleanup; | ||
861 | if (ns != NULL) | ||
767 | { | 862 | { |
768 | if (0 != UNLINK (filename)) | 863 | pc->namespace = GNUNET_FS_namespace_create (h, ns); |
769 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | 864 | if (pc->namespace == NULL) |
770 | "unlink", | 865 | { |
771 | filename); | 866 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
772 | return GNUNET_OK; | 867 | _("Failed to recover namespace `%s', cannot resume publishing operation.\n"), |
868 | ns); | ||
869 | goto cleanup; | ||
870 | } | ||
773 | } | 871 | } |
774 | while (1) | 872 | if (fi_pos != NULL) |
775 | { | 873 | { |
776 | fi_root = NULL; | 874 | pc->fi_pos = find_file_position (pc->fi, |
777 | fi_pos = NULL; | 875 | fi_pos); |
778 | ns = NULL; | 876 | GNUNET_free (fi_pos); |
779 | pc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishContext)); | 877 | if (pc->fi_pos == NULL) |
780 | pc->h = h; | ||
781 | if ( (GNUNET_OK != | ||
782 | GNUNET_BIO_read_string (rh, "publish-nid", &pc->nid, 1024)) || | ||
783 | (GNUNET_OK != | ||
784 | GNUNET_BIO_read_string (rh, "publish-nuid", &pc->nuid, 1024)) || | ||
785 | (GNUNET_OK != | ||
786 | GNUNET_BIO_read_int32 (rh, &options)) || | ||
787 | (GNUNET_OK != | ||
788 | GNUNET_BIO_read_int32 (rh, &all_done)) || | ||
789 | (GNUNET_OK != | ||
790 | GNUNET_BIO_read_string (rh, "publish-firoot", &fi_root, 128)) || | ||
791 | (GNUNET_OK != | ||
792 | GNUNET_BIO_read_string (rh, "publish-fipos", &fi_pos, 128)) || | ||
793 | (GNUNET_OK != | ||
794 | GNUNET_BIO_read_string (rh, "publish-ns", &ns, 1024)) ) | ||
795 | { | 878 | { |
796 | GNUNET_free_non_null (pc->nid); | 879 | /* failed to find position for resuming, outch! Will start from root! */ |
797 | GNUNET_free_non_null (pc->nuid); | 880 | GNUNET_break (0); |
798 | GNUNET_free_non_null (fi_root); | 881 | if (pc->all_done != GNUNET_YES) |
799 | GNUNET_free_non_null (ns); | 882 | pc->fi_pos = pc->fi; |
800 | GNUNET_free (pc); | 883 | } |
801 | break; | ||
802 | } | ||
803 | pc->options = options; | ||
804 | pc->all_done = all_done; | ||
805 | pc->fi = deserialize_file_information (h, fi_root); | ||
806 | if (pc->fi == NULL) | ||
807 | { | ||
808 | GNUNET_free_non_null (pc->nid); | ||
809 | GNUNET_free_non_null (pc->nuid); | ||
810 | GNUNET_free_non_null (fi_root); | ||
811 | GNUNET_free_non_null (ns); | ||
812 | GNUNET_free (pc); | ||
813 | continue; | ||
814 | } | ||
815 | if (ns != NULL) | ||
816 | { | ||
817 | pc->namespace = GNUNET_FS_namespace_create (h, ns); | ||
818 | if (pc->namespace == NULL) | ||
819 | { | ||
820 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
821 | _("Failed to recover namespace `%s', cannot resume publishing operation.\n"), | ||
822 | ns); | ||
823 | GNUNET_free_non_null (pc->nid); | ||
824 | GNUNET_free_non_null (pc->nuid); | ||
825 | GNUNET_free_non_null (fi_root); | ||
826 | GNUNET_free_non_null (ns); | ||
827 | GNUNET_free (pc); | ||
828 | continue; | ||
829 | } | ||
830 | } | ||
831 | if (fi_pos != NULL) | ||
832 | { | ||
833 | pc->fi_pos = find_file_position (pc->fi, | ||
834 | fi_pos); | ||
835 | GNUNET_free (fi_pos); | ||
836 | if (pc->fi_pos == NULL) | ||
837 | { | ||
838 | /* failed to find position for resuming, outch! Will start from root! */ | ||
839 | GNUNET_break (0); | ||
840 | if (pc->all_done != GNUNET_YES) | ||
841 | pc->fi_pos = pc->fi; | ||
842 | } | ||
843 | } | ||
844 | pc->serialization = GNUNET_strdup (filename); | ||
845 | /* generate RESUME event(s) */ | ||
846 | GNUNET_FS_file_information_inspect (pc->fi, | ||
847 | &fip_signal_resume, | ||
848 | pc); | ||
849 | |||
850 | /* re-start publishing (if needed)... */ | ||
851 | if (pc->all_done != GNUNET_YES) | ||
852 | pc->upload_task | ||
853 | = GNUNET_SCHEDULER_add_with_priority (h->sched, | ||
854 | GNUNET_SCHEDULER_PRIORITY_BACKGROUND, | ||
855 | &GNUNET_FS_publish_main_, | ||
856 | pc); | ||
857 | } | 884 | } |
885 | pc->serialization = get_serialization_short_name (filename); | ||
886 | /* generate RESUME event(s) */ | ||
887 | GNUNET_FS_file_information_inspect (pc->fi, | ||
888 | &fip_signal_resume, | ||
889 | pc); | ||
890 | |||
891 | /* re-start publishing (if needed)... */ | ||
892 | if (pc->all_done != GNUNET_YES) | ||
893 | pc->upload_task | ||
894 | = GNUNET_SCHEDULER_add_with_priority (h->sched, | ||
895 | GNUNET_SCHEDULER_PRIORITY_BACKGROUND, | ||
896 | &GNUNET_FS_publish_main_, | ||
897 | pc); | ||
858 | if (GNUNET_OK != | 898 | if (GNUNET_OK != |
859 | GNUNET_BIO_read_close (rh, &emsg)) | 899 | GNUNET_BIO_read_close (rh, &emsg)) |
860 | { | 900 | { |
@@ -865,6 +905,85 @@ deserialize_publish_file (void *cls, | |||
865 | GNUNET_free (emsg); | 905 | GNUNET_free (emsg); |
866 | } | 906 | } |
867 | return GNUNET_OK; | 907 | return GNUNET_OK; |
908 | cleanup: | ||
909 | GNUNET_free_non_null (pc->nid); | ||
910 | GNUNET_free_non_null (pc->nuid); | ||
911 | GNUNET_free_non_null (fi_root); | ||
912 | GNUNET_free_non_null (ns); | ||
913 | if ( (rh != NULL) && | ||
914 | (GNUNET_OK != | ||
915 | GNUNET_BIO_read_close (rh, &emsg)) ) | ||
916 | { | ||
917 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
918 | _("Failed to resume publishing operation `%s': %s\n"), | ||
919 | filename, | ||
920 | emsg); | ||
921 | GNUNET_free (emsg); | ||
922 | } | ||
923 | if (pc->fi != NULL) | ||
924 | GNUNET_FS_file_information_destroy (pc->fi, NULL, NULL); | ||
925 | remove_sync_file (h, "publish", pc->serialization); | ||
926 | GNUNET_free_non_null (pc->serialization); | ||
927 | GNUNET_free (pc); | ||
928 | return GNUNET_OK; | ||
929 | } | ||
930 | |||
931 | |||
932 | /** | ||
933 | * Synchronize this publishing struct with its mirror | ||
934 | * on disk. Note that all internal FS-operations that change | ||
935 | * publishing structs should already call "sync" internally, | ||
936 | * so this function is likely not useful for clients. | ||
937 | * | ||
938 | * @param pc the struct to sync | ||
939 | */ | ||
940 | void | ||
941 | GNUNET_FS_publish_sync_ (struct GNUNET_FS_PublishContext *pc) | ||
942 | { | ||
943 | struct GNUNET_BIO_WriteHandle *wh; | ||
944 | |||
945 | if (NULL == pc->serialization) | ||
946 | pc->serialization = make_serialization_file_name (pc->h, | ||
947 | "publish"); | ||
948 | if (NULL == pc->serialization) | ||
949 | return; | ||
950 | if (NULL == pc->fi) | ||
951 | return; | ||
952 | if (NULL == pc->fi->serialization) | ||
953 | { | ||
954 | GNUNET_break (0); | ||
955 | return; | ||
956 | } | ||
957 | wh = get_write_handle (pc->h, "publish", pc->serialization); | ||
958 | if ( (GNUNET_OK != | ||
959 | GNUNET_BIO_write_string (wh, pc->nid)) || | ||
960 | (GNUNET_OK != | ||
961 | GNUNET_BIO_write_string (wh, pc->nuid)) || | ||
962 | (GNUNET_OK != | ||
963 | GNUNET_BIO_write_int32 (wh, pc->options)) || | ||
964 | (GNUNET_OK != | ||
965 | GNUNET_BIO_write_int32 (wh, pc->all_done)) || | ||
966 | (GNUNET_OK != | ||
967 | GNUNET_BIO_write_string (wh, pc->fi->serialization)) || | ||
968 | (GNUNET_OK != | ||
969 | GNUNET_BIO_write_string (wh, (pc->fi_pos == NULL) ? NULL : pc->fi_pos->serialization)) || | ||
970 | (GNUNET_OK != | ||
971 | GNUNET_BIO_write_string (wh, (pc->namespace == NULL) ? NULL : pc->namespace->name)) ) | ||
972 | { | ||
973 | (void) GNUNET_BIO_write_close (wh); | ||
974 | remove_sync_file (pc->h, "publish", pc->serialization); | ||
975 | GNUNET_free (pc->serialization); | ||
976 | pc->serialization = NULL; | ||
977 | return; | ||
978 | } | ||
979 | if (GNUNET_OK != | ||
980 | GNUNET_BIO_write_close (wh)) | ||
981 | { | ||
982 | remove_sync_file (pc->h, "publish", pc->serialization); | ||
983 | GNUNET_free (pc->serialization); | ||
984 | pc->serialization = NULL; | ||
985 | return; | ||
986 | } | ||
868 | } | 987 | } |
869 | 988 | ||
870 | 989 | ||
diff --git a/src/fs/fs.h b/src/fs/fs.h index 50306851e..fa36b8f02 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h | |||
@@ -624,6 +624,18 @@ void | |||
624 | GNUNET_FS_file_information_sync_ (struct GNUNET_FS_FileInformation *f); | 624 | GNUNET_FS_file_information_sync_ (struct GNUNET_FS_FileInformation *f); |
625 | 625 | ||
626 | 626 | ||
627 | /** | ||
628 | * Synchronize this publishing struct with its mirror | ||
629 | * on disk. Note that all internal FS-operations that change | ||
630 | * publishing structs should already call "sync" internally, | ||
631 | * so this function is likely not useful for clients. | ||
632 | * | ||
633 | * @param pc the struct to sync | ||
634 | */ | ||
635 | void | ||
636 | GNUNET_FS_publish_sync_ (struct GNUNET_FS_PublishContext *pc); | ||
637 | |||
638 | |||
627 | 639 | ||
628 | /** | 640 | /** |
629 | * Master context for most FS operations. | 641 | * Master context for most FS operations. |
@@ -1352,6 +1364,11 @@ struct GNUNET_FS_Namespace | |||
1352 | char *filename; | 1364 | char *filename; |
1353 | 1365 | ||
1354 | /** | 1366 | /** |
1367 | * Name of the namespace. | ||
1368 | */ | ||
1369 | char *name; | ||
1370 | |||
1371 | /** | ||
1355 | * Reference counter. | 1372 | * Reference counter. |
1356 | */ | 1373 | */ |
1357 | unsigned int rc; | 1374 | unsigned int rc; |
diff --git a/src/fs/fs_namespace.c b/src/fs/fs_namespace.c index 267a90228..e853ce813 100644 --- a/src/fs/fs_namespace.c +++ b/src/fs/fs_namespace.c | |||
@@ -343,6 +343,7 @@ GNUNET_FS_namespace_create (struct GNUNET_FS_Handle *h, | |||
343 | GNUNET_free (fn); | 343 | GNUNET_free (fn); |
344 | return NULL; | 344 | return NULL; |
345 | } | 345 | } |
346 | ret->name = GNUNET_strdup (name); | ||
346 | ret->filename = fn; | 347 | ret->filename = fn; |
347 | return ret; | 348 | return ret; |
348 | } | 349 | } |
@@ -375,6 +376,7 @@ GNUNET_FS_namespace_delete (struct GNUNET_FS_Namespace *namespace, | |||
375 | { | 376 | { |
376 | GNUNET_CRYPTO_rsa_key_free (namespace->key); | 377 | GNUNET_CRYPTO_rsa_key_free (namespace->key); |
377 | GNUNET_free (namespace->filename); | 378 | GNUNET_free (namespace->filename); |
379 | GNUNET_free (namespace->name); | ||
378 | GNUNET_free (namespace); | 380 | GNUNET_free (namespace); |
379 | } | 381 | } |
380 | return GNUNET_OK; | 382 | return GNUNET_OK; |
diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c index 16bab3ba1..ab50d4bea 100644 --- a/src/fs/fs_publish.c +++ b/src/fs/fs_publish.c | |||
@@ -977,8 +977,7 @@ GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h, | |||
977 | if (NULL != nuid) | 977 | if (NULL != nuid) |
978 | ret->nuid = GNUNET_strdup (nuid); | 978 | ret->nuid = GNUNET_strdup (nuid); |
979 | } | 979 | } |
980 | // FIXME: make upload persistent! | 980 | GNUNET_FS_publish_sync_ (ret); |
981 | |||
982 | /* signal start */ | 981 | /* signal start */ |
983 | GNUNET_FS_file_information_inspect (ret->fi, | 982 | GNUNET_FS_file_information_inspect (ret->fi, |
984 | &fip_signal_start, | 983 | &fip_signal_start, |