aboutsummaryrefslogtreecommitdiff
path: root/src/fs/gnunet-service-fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/gnunet-service-fs.c')
-rw-r--r--src/fs/gnunet-service-fs.c230
1 files changed, 229 insertions, 1 deletions
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 */
565struct 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 */
565static struct GNUNET_SCHEDULER_Handle *sched; 603static struct GNUNET_SCHEDULER_Handle *sched;
@@ -611,6 +649,37 @@ static struct ClientList *client_list;
611static struct GNUNET_CORE_Handle *core; 649static struct GNUNET_CORE_Handle *core;
612 650
613/** 651/**
652 * Head of linked list of blocks that can be migrated.
653 */
654static struct MigrationReadyBlock *mig_head;
655
656/**
657 * Tail of linked list of blocks that can be migrated.
658 */
659static struct MigrationReadyBlock *mig_tail;
660
661/**
662 * Request to datastore for migration (or NULL).
663 */
664static struct GNUNET_DATASTORE_QueueEntry *mig_qe;
665
666/**
667 * ID of task that collects blocks for migration.
668 */
669static 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 */
675static struct GNUNET_TIME_Relative min_migration_delay;
676
677/**
678 * Size of the doubly-linked list of migration blocks.
679 */
680static 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 */
616static int active_migration; 685static 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 */
695static void
696delete_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 */
714static int
715consider_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 */
737static void
738gather_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 */
756static void
757process_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 */
814static void
815gather_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
974shutdown_task (void *cls, 1181shutdown_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);