diff options
author | Christian Grothoff <christian@grothoff.org> | 2010-05-15 19:07:15 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2010-05-15 19:07:15 +0000 |
commit | 0e255e78a2f74e70f749431d1ab97198c572e257 (patch) | |
tree | 9e491dbe19e071d67638a93869bd02cd900eef13 | |
parent | 9b913265537544514be1bdfef8770b8c614c759f (diff) | |
download | gnunet-0e255e78a2f74e70f749431d1ab97198c572e257.tar.gz gnunet-0e255e78a2f74e70f749431d1ab97198c572e257.zip |
towards migration
-rw-r--r-- | src/fs/fs.h | 5 | ||||
-rw-r--r-- | src/fs/gnunet-service-fs.c | 230 |
2 files changed, 234 insertions, 1 deletions
diff --git a/src/fs/fs.h b/src/fs/fs.h index 9901cd173..3277ea340 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h | |||
@@ -37,6 +37,11 @@ | |||
37 | #define MAX_DATASTORE_QUEUE 16 | 37 | #define MAX_DATASTORE_QUEUE 16 |
38 | 38 | ||
39 | /** | 39 | /** |
40 | * Maximum number of blocks we keep in memory for migration. | ||
41 | */ | ||
42 | #define MAX_MIGRATION_QUEUE 32 | ||
43 | |||
44 | /** | ||
40 | * Size of the individual blocks used for file-sharing. | 45 | * Size of the individual blocks used for file-sharing. |
41 | */ | 46 | */ |
42 | #define DBLOCK_SIZE (32*1024) | 47 | #define DBLOCK_SIZE (32*1024) |
diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c index 8bec62b08..a08a041da 100644 --- a/src/fs/gnunet-service-fs.c +++ b/src/fs/gnunet-service-fs.c | |||
@@ -560,6 +560,44 @@ struct PendingRequest | |||
560 | 560 | ||
561 | 561 | ||
562 | /** | 562 | /** |
563 | * Block that is ready for migration to other peers. Actual data is at the end of the block. | ||
564 | */ | ||
565 | struct MigrationReadyBlock | ||
566 | { | ||
567 | |||
568 | /** | ||
569 | * This is a doubly-linked list. | ||
570 | */ | ||
571 | struct MigrationReadyBlock *next; | ||
572 | |||
573 | /** | ||
574 | * This is a doubly-linked list. | ||
575 | */ | ||
576 | struct MigrationReadyBlock *prev; | ||
577 | |||
578 | /** | ||
579 | * Query for the block. | ||
580 | */ | ||
581 | GNUNET_HashCode query; | ||
582 | |||
583 | /** | ||
584 | * When does this block expire? | ||
585 | */ | ||
586 | struct GNUNET_TIME_Absolute expiration; | ||
587 | |||
588 | /** | ||
589 | * Size of the block. | ||
590 | */ | ||
591 | size_t size; | ||
592 | |||
593 | /** | ||
594 | * Type of the block. | ||
595 | */ | ||
596 | enum GNUNET_BLOCK_Type type; | ||
597 | }; | ||
598 | |||
599 | |||
600 | /** | ||
563 | * Our scheduler. | 601 | * Our scheduler. |
564 | */ | 602 | */ |
565 | static struct GNUNET_SCHEDULER_Handle *sched; | 603 | static struct GNUNET_SCHEDULER_Handle *sched; |
@@ -611,6 +649,37 @@ static struct ClientList *client_list; | |||
611 | static struct GNUNET_CORE_Handle *core; | 649 | static struct GNUNET_CORE_Handle *core; |
612 | 650 | ||
613 | /** | 651 | /** |
652 | * Head of linked list of blocks that can be migrated. | ||
653 | */ | ||
654 | static struct MigrationReadyBlock *mig_head; | ||
655 | |||
656 | /** | ||
657 | * Tail of linked list of blocks that can be migrated. | ||
658 | */ | ||
659 | static struct MigrationReadyBlock *mig_tail; | ||
660 | |||
661 | /** | ||
662 | * Request to datastore for migration (or NULL). | ||
663 | */ | ||
664 | static struct GNUNET_DATASTORE_QueueEntry *mig_qe; | ||
665 | |||
666 | /** | ||
667 | * ID of task that collects blocks for migration. | ||
668 | */ | ||
669 | static GNUNET_SCHEDULER_TaskIdentifier mig_task; | ||
670 | |||
671 | /** | ||
672 | * What is the maximum frequency at which we are allowed to | ||
673 | * poll the datastore for migration content? | ||
674 | */ | ||
675 | static struct GNUNET_TIME_Relative min_migration_delay; | ||
676 | |||
677 | /** | ||
678 | * Size of the doubly-linked list of migration blocks. | ||
679 | */ | ||
680 | static unsigned int mig_size; | ||
681 | |||
682 | /** | ||
614 | * Are we allowed to migrate content to this peer. | 683 | * Are we allowed to migrate content to this peer. |
615 | */ | 684 | */ |
616 | static int active_migration; | 685 | static int active_migration; |
@@ -619,6 +688,141 @@ static int active_migration; | |||
619 | 688 | ||
620 | 689 | ||
621 | /** | 690 | /** |
691 | * Delete the given migration block. | ||
692 | * | ||
693 | * @param mb block to delete | ||
694 | */ | ||
695 | static void | ||
696 | delete_migration_block (struct MigrationReadyBlock *mb) | ||
697 | { | ||
698 | GNUNET_CONTAINER_DLL_remove (mig_head, | ||
699 | mig_tail, | ||
700 | mb); | ||
701 | mig_size--; | ||
702 | GNUNET_free (mb); | ||
703 | } | ||
704 | |||
705 | |||
706 | /** | ||
707 | * Consider migrating content to a given peer. | ||
708 | * | ||
709 | * @param cls not used | ||
710 | * @param key ID of the peer (not used) | ||
711 | * @param value 'struct ConnectedPeer' of the peer | ||
712 | * @return GNUNET_YES (always continue iteration)2 | ||
713 | */ | ||
714 | static int | ||
715 | consider_migration (void *cls, | ||
716 | const GNUNET_HashCode *key, | ||
717 | void *value) | ||
718 | { | ||
719 | struct ConnectedPeer *cp = value; | ||
720 | |||
721 | if (cp->cth != NULL) | ||
722 | return GNUNET_YES; /* or what? */ | ||
723 | /* FIXME: not implemented! */ | ||
724 | return GNUNET_YES; | ||
725 | } | ||
726 | |||
727 | |||
728 | |||
729 | |||
730 | /** | ||
731 | * Task that is run periodically to obtain blocks for content | ||
732 | * migration | ||
733 | * | ||
734 | * @param cls unused | ||
735 | * @param tc scheduler context (also unused) | ||
736 | */ | ||
737 | static void | ||
738 | gather_migration_blocks (void *cls, | ||
739 | const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
740 | |||
741 | |||
742 | /** | ||
743 | * Process content offered for migration. | ||
744 | * | ||
745 | * @param cls closure | ||
746 | * @param key key for the content | ||
747 | * @param size number of bytes in data | ||
748 | * @param data content stored | ||
749 | * @param type type of the content | ||
750 | * @param priority priority of the content | ||
751 | * @param anonymity anonymity-level for the content | ||
752 | * @param expiration expiration time for the content | ||
753 | * @param uid unique identifier for the datum; | ||
754 | * maybe 0 if no unique identifier is available | ||
755 | */ | ||
756 | static void | ||
757 | process_migration_content (void *cls, | ||
758 | const GNUNET_HashCode * key, | ||
759 | uint32_t size, | ||
760 | const void *data, | ||
761 | enum GNUNET_BLOCK_Type type, | ||
762 | uint32_t priority, | ||
763 | uint32_t anonymity, | ||
764 | struct GNUNET_TIME_Absolute | ||
765 | expiration, uint64_t uid) | ||
766 | { | ||
767 | struct MigrationReadyBlock *mb; | ||
768 | struct GNUNET_TIME_Relative delay; | ||
769 | |||
770 | if (key == NULL) | ||
771 | { | ||
772 | mig_qe = NULL; | ||
773 | if (mig_size < MAX_MIGRATION_QUEUE) | ||
774 | { | ||
775 | delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, | ||
776 | mig_size); | ||
777 | delay = GNUNET_TIME_relative_divide (GNUNET_TIME_UNIT_SECONDS, | ||
778 | MAX_MIGRATION_QUEUE); | ||
779 | delay = GNUNET_TIME_relative_max (delay, | ||
780 | min_migration_delay); | ||
781 | mig_task = GNUNET_SCHEDULER_add_delayed (sched, | ||
782 | delay, | ||
783 | &gather_migration_blocks, | ||
784 | NULL); | ||
785 | } | ||
786 | return; | ||
787 | } | ||
788 | mb = GNUNET_malloc (sizeof (struct MigrationReadyBlock) + size); | ||
789 | mb->query = *key; | ||
790 | mb->expiration = expiration; | ||
791 | mb->size = size; | ||
792 | mb->type = type; | ||
793 | memcpy (&mb[1], data, size); | ||
794 | GNUNET_CONTAINER_DLL_insert_after (mig_head, | ||
795 | mig_tail, | ||
796 | mig_tail, | ||
797 | mb); | ||
798 | mig_size++; | ||
799 | if (mig_size == 1) | ||
800 | GNUNET_CONTAINER_multihashmap_iterate (connected_peers, | ||
801 | &consider_migration, | ||
802 | NULL); | ||
803 | GNUNET_DATASTORE_get_next (dsh, GNUNET_YES); | ||
804 | } | ||
805 | |||
806 | |||
807 | /** | ||
808 | * Task that is run periodically to obtain blocks for content | ||
809 | * migration | ||
810 | * | ||
811 | * @param cls unused | ||
812 | * @param tc scheduler context (also unused) | ||
813 | */ | ||
814 | static void | ||
815 | gather_migration_blocks (void *cls, | ||
816 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
817 | { | ||
818 | mig_task = GNUNET_SCHEDULER_NO_TASK; | ||
819 | mig_qe = GNUNET_DATASTORE_get_random (dsh, 0, -1, | ||
820 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
821 | &process_migration_content, NULL); | ||
822 | } | ||
823 | |||
824 | |||
825 | /** | ||
622 | * We're done with a particular message list entry. | 826 | * We're done with a particular message list entry. |
623 | * Free all associated resources. | 827 | * Free all associated resources. |
624 | * | 828 | * |
@@ -782,9 +986,12 @@ peer_connect_handler (void *cls, | |||
782 | &peer->hashPubKey, | 986 | &peer->hashPubKey, |
783 | cp, | 987 | cp, |
784 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | 988 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); |
989 | if (mig_size > 0) | ||
990 | (void) consider_migration (NULL, &peer->hashPubKey, cp); | ||
785 | } | 991 | } |
786 | 992 | ||
787 | 993 | ||
994 | |||
788 | /** | 995 | /** |
789 | * Free (each) request made by the peer. | 996 | * Free (each) request made by the peer. |
790 | * | 997 | * |
@@ -974,6 +1181,16 @@ static void | |||
974 | shutdown_task (void *cls, | 1181 | shutdown_task (void *cls, |
975 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 1182 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
976 | { | 1183 | { |
1184 | if (mig_qe != NULL) | ||
1185 | { | ||
1186 | GNUNET_DATASTORE_cancel (mig_qe); | ||
1187 | mig_qe = NULL; | ||
1188 | } | ||
1189 | if (GNUNET_SCHEDULER_NO_TASK != mig_task) | ||
1190 | { | ||
1191 | GNUNET_SCHEDULER_cancel (sched, mig_task); | ||
1192 | mig_task = GNUNET_SCHEDULER_NO_TASK; | ||
1193 | } | ||
977 | while (client_list != NULL) | 1194 | while (client_list != NULL) |
978 | handle_client_disconnect (NULL, | 1195 | handle_client_disconnect (NULL, |
979 | client_list->client); | 1196 | client_list->client); |
@@ -1001,6 +1218,9 @@ shutdown_task (void *cls, | |||
1001 | } | 1218 | } |
1002 | GNUNET_DATASTORE_disconnect (dsh, | 1219 | GNUNET_DATASTORE_disconnect (dsh, |
1003 | GNUNET_NO); | 1220 | GNUNET_NO); |
1221 | while (mig_head != NULL) | ||
1222 | delete_migration_block (mig_head); | ||
1223 | GNUNET_assert (0 == mig_size); | ||
1004 | dsh = NULL; | 1224 | dsh = NULL; |
1005 | sched = NULL; | 1225 | sched = NULL; |
1006 | cfg = NULL; | 1226 | cfg = NULL; |
@@ -1065,7 +1285,7 @@ transmit_to_peer (void *cls, | |||
1065 | } | 1285 | } |
1066 | #if DEBUG_FS | 1286 | #if DEBUG_FS |
1067 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1287 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1068 | "Transmitting %u bytes to peer %u.\n", | 1288 | "Transmitting %u bytes to peer %u\n", |
1069 | msize, | 1289 | msize, |
1070 | cp->pid); | 1290 | cp->pid); |
1071 | #endif | 1291 | #endif |
@@ -2930,6 +3150,7 @@ main_init (struct GNUNET_SCHEDULER_Handle *s, | |||
2930 | sched = s; | 3150 | sched = s; |
2931 | cfg = c; | 3151 | cfg = c; |
2932 | stats = GNUNET_STATISTICS_create (sched, "fs", cfg); | 3152 | stats = GNUNET_STATISTICS_create (sched, "fs", cfg); |
3153 | min_migration_delay = GNUNET_TIME_UNIT_SECONDS; // FIXME: get from config | ||
2933 | connected_peers = GNUNET_CONTAINER_multihashmap_create (128); // FIXME: get size from config | 3154 | connected_peers = GNUNET_CONTAINER_multihashmap_create (128); // FIXME: get size from config |
2934 | query_request_map = GNUNET_CONTAINER_multihashmap_create (128); // FIXME: get size from config | 3155 | query_request_map = GNUNET_CONTAINER_multihashmap_create (128); // FIXME: get size from config |
2935 | peer_request_map = GNUNET_CONTAINER_multihashmap_create (128); // FIXME: get size from config | 3156 | peer_request_map = GNUNET_CONTAINER_multihashmap_create (128); // FIXME: get size from config |
@@ -2964,6 +3185,13 @@ main_init (struct GNUNET_SCHEDULER_Handle *s, | |||
2964 | } | 3185 | } |
2965 | return GNUNET_SYSERR; | 3186 | return GNUNET_SYSERR; |
2966 | } | 3187 | } |
3188 | /* FIXME: distinguish between sending and storing in options? */ | ||
3189 | if (active_migration) | ||
3190 | { | ||
3191 | mig_task = GNUNET_SCHEDULER_add_now (sched, | ||
3192 | &gather_migration_blocks, | ||
3193 | NULL); | ||
3194 | } | ||
2967 | GNUNET_SERVER_disconnect_notify (server, | 3195 | GNUNET_SERVER_disconnect_notify (server, |
2968 | &handle_client_disconnect, | 3196 | &handle_client_disconnect, |
2969 | NULL); | 3197 | NULL); |