using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; using DistributedGA.Core.Domain; using DistributedGA.Core.Interface; using System.Timers; using System.Threading.Tasks; namespace DistributedGA.Core.Implementation { public class WcfPeerListManager : IPeerListManager, IDisposable { private string serverString = null; private PeerInfo myself = null; private Timer timer = null; //sends heartbeat to contact-server private Object timerLock = new Object(); private List cachedPeerList; private double communicationRate; private Random rand; public void Init(PeerInfo source, string contactServerUrl, double communicationRate) { serverString = contactServerUrl; this.communicationRate = communicationRate; myself = source; cachedPeerList = new List(); rand = new Random(); //Init Task.Factory.StartNew(() => RefreshPeerList(this, null), TaskCreationOptions.LongRunning); //Start heartbeat timer timer = new Timer(1000 * 30); //each 30 seconds timer.Elapsed += RefreshPeerList; timer.Start(); } public List GetPeerList() { return cachedPeerList; } public void Dispose() { timer.Stop(); timer.Dispose(); } private List ChoosePeersForMessaging(List allPeers) { Shuffle(allPeers); int toTake = Convert.ToInt32(allPeers.Count * communicationRate); if (allPeers.Count > 0 && toTake == 0) { toTake = 1; } return allPeers.Take(toTake).ToList(); } private void Shuffle(IList list) { int n = list.Count; while (n > 1) { n--; int k = rand.Next(n + 1); T value = list[k]; list[k] = list[n]; list[n] = value; } } private void RefreshPeerList(object sender, ElapsedEventArgs e) { lock (timerLock) { try { List allPeers = new List(); var binding = new NetTcpBinding(); var endpoint = new EndpointAddress(serverString); using (var myChannelFactory = new ChannelFactory(binding, endpoint)) { using (IClientChannel client = (IClientChannel)myChannelFactory.CreateChannel()) { allPeers = ((IContactService)client).GetPeerList(myself); } } cachedPeerList = ChoosePeersForMessaging(allPeers); } catch { } //nothing to do } } } }