1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using System.Linq;
|
---|
4 | using System.ServiceModel;
|
---|
5 | using DistributedGA.Core.Domain;
|
---|
6 | using DistributedGA.Core.Interface;
|
---|
7 | using System.Timers;
|
---|
8 | using System.Threading.Tasks;
|
---|
9 |
|
---|
10 | namespace DistributedGA.Core.Implementation {
|
---|
11 | public class WcfPeerListManager : IPeerListManager, IDisposable {
|
---|
12 |
|
---|
13 | private string serverString = null;
|
---|
14 |
|
---|
15 | private PeerInfo myself = null;
|
---|
16 |
|
---|
17 | private Timer timer = null; //sends heartbeat to contact-server
|
---|
18 |
|
---|
19 | private Object timerLock = new Object();
|
---|
20 |
|
---|
21 | private List<PeerInfo> cachedPeerList;
|
---|
22 |
|
---|
23 | private double communicationRate;
|
---|
24 |
|
---|
25 | private Random rand;
|
---|
26 |
|
---|
27 | public void Init(PeerInfo source, string contactServerUrl, double communicationRate) {
|
---|
28 | serverString = contactServerUrl;
|
---|
29 | this.communicationRate = communicationRate;
|
---|
30 | myself = source;
|
---|
31 | cachedPeerList = new List<PeerInfo>();
|
---|
32 | rand = new Random();
|
---|
33 | //Init
|
---|
34 | Task.Factory.StartNew(() => RefreshPeerList(this, null), TaskCreationOptions.LongRunning);
|
---|
35 | //Start heartbeat timer
|
---|
36 | timer = new Timer(1000 * 30); //each 30 seconds
|
---|
37 | timer.Elapsed += RefreshPeerList;
|
---|
38 | timer.Start();
|
---|
39 | }
|
---|
40 |
|
---|
41 | public List<PeerInfo> GetPeerList() {
|
---|
42 | return cachedPeerList;
|
---|
43 | }
|
---|
44 |
|
---|
45 | public void Dispose() {
|
---|
46 | timer.Stop();
|
---|
47 | timer.Dispose();
|
---|
48 | }
|
---|
49 |
|
---|
50 | private List<PeerInfo> ChoosePeersForMessaging(List<PeerInfo> allPeers) {
|
---|
51 | Shuffle<PeerInfo>(allPeers);
|
---|
52 | int toTake = Convert.ToInt32(allPeers.Count * communicationRate);
|
---|
53 | if (allPeers.Count > 0 && toTake == 0) {
|
---|
54 | toTake = 1;
|
---|
55 | }
|
---|
56 | return allPeers.Take(toTake).ToList();
|
---|
57 | }
|
---|
58 |
|
---|
59 | private void Shuffle<T>(IList<T> list) {
|
---|
60 | int n = list.Count;
|
---|
61 | while (n > 1) {
|
---|
62 | n--;
|
---|
63 | int k = rand.Next(n + 1);
|
---|
64 | T value = list[k];
|
---|
65 | list[k] = list[n];
|
---|
66 | list[n] = value;
|
---|
67 | }
|
---|
68 | }
|
---|
69 |
|
---|
70 | private void RefreshPeerList(object sender, ElapsedEventArgs e) {
|
---|
71 | lock (timerLock) {
|
---|
72 | try {
|
---|
73 | List<PeerInfo> allPeers = new List<PeerInfo>();
|
---|
74 | var binding = new NetTcpBinding();
|
---|
75 | var endpoint = new EndpointAddress(serverString);
|
---|
76 | using (var myChannelFactory = new ChannelFactory<IContactService>(binding, endpoint)) {
|
---|
77 | using (IClientChannel client = (IClientChannel)myChannelFactory.CreateChannel()) {
|
---|
78 | allPeers = ((IContactService)client).GetPeerList(myself);
|
---|
79 | }
|
---|
80 | }
|
---|
81 | cachedPeerList = ChoosePeersForMessaging(allPeers);
|
---|
82 | }
|
---|
83 | catch { } //nothing to do
|
---|
84 | }
|
---|
85 | }
|
---|
86 |
|
---|
87 | }
|
---|
88 | }
|
---|