aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-04-30 12:37:39 +0000
committerChristian Grothoff <christian@grothoff.org>2010-04-30 12:37:39 +0000
commit200be29edf8956741de7d03f65a9b3aec407d2ce (patch)
tree0f11e27ee967f18ebdf7f43efbe025f0254f11ab
parent1cc43d608117c035c4986cf6b306b876e84a700e (diff)
downloadgnunet-200be29edf8956741de7d03f65a9b3aec407d2ce.tar.gz
gnunet-200be29edf8956741de7d03f65a9b3aec407d2ce.zip
publish serialization stuff
-rw-r--r--src/fs/fs.c349
-rw-r--r--src/fs/fs.h17
-rw-r--r--src/fs/fs_namespace.c2
-rw-r--r--src/fs/fs_publish.c3
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 */
309static void
310remove_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 */
556static char *
557get_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 */
590static char *
591make_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
525GNUNET_FS_file_information_sync_ (struct GNUNET_FS_FileInformation * fi) 617GNUNET_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 */
940void
941GNUNET_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
624GNUNET_FS_file_information_sync_ (struct GNUNET_FS_FileInformation *f); 624GNUNET_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 */
635void
636GNUNET_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,