예제 #1
0
        public async Task Publish(MultiClusterData data)
        {
            logger.Verbose("-Publish data:{0}", data);
            // this is (almost) always called with just one item in data to be written back
            // so we are o.k. with doing individual tasks for each storage read and write

            var tasks = new List<Task>();
            if (data.Configuration != null)
            {
                Func<Task> publishconfig = async () => {
                    var configInStorage = await tableManager.ReadConfigurationEntryAsync();
                    await DiffAndWriteBackConfigAsync(data.Configuration, configInStorage);
                };
                tasks.Add(publishconfig());    
            }
            foreach (var gateway in data.Gateways.Values)
            {
                Func<Task> publishgatewayinfo = async () => {
                    var gatewayInfoInStorage = await tableManager.ReadGatewayEntryAsync(gateway);
                    await DiffAndWriteBackGatewayInfoAsync(gateway, gatewayInfoInStorage);
                };
                tasks.Add(publishgatewayinfo());
            }
            await Task.WhenAll(tasks);
        }
        public MultiClusterData ApplyDataAndNotify(MultiClusterData data)
        {
            if (data.IsEmpty)
            {
                return(data);
            }

            MultiClusterData delta;
            MultiClusterData prev = this.localData;

            this.localData = prev.Merge(data, out delta);

            if (logger.IsVerbose2)
            {
                logger.Verbose2("ApplyDataAndNotify: delta {0}", delta);
            }

            if (delta.IsEmpty)
            {
                return(delta);
            }

            if (delta.Configuration != null)
            {
                // notify configuration listeners of change
                // code will be added in separate PR
            }

            return(delta);
        }
예제 #3
0
        public MultiClusterData ApplyDataAndNotify(MultiClusterData data)
        {
            if (data.IsEmpty)
                return data;

            MultiClusterData delta;
            MultiClusterData prev = this.localData;

            this.localData = prev.Merge(data, out delta);

            if (logger.IsVerbose2)
                logger.Verbose2("ApplyDataAndNotify: delta {0}", delta);

            if (delta.IsEmpty)
                return delta;

            if (delta.Gateways.Count > 0)
            {
                // some gateways have changed
                ComputeAvailableGatewaysPerCluster();
            }

            if (delta.Configuration != null)
            {
                // notify configuration listeners of change
                // code will be added in separate PR
            }

            return delta;
        }
예제 #4
0
        private void AssertEffect(MultiClusterData what, MultiClusterData to, MultiClusterData expectedMerge, MultiClusterData expectedDelta = null)
        {
            MultiClusterData delta;
            var merge = to.Merge(what, out delta);

            Assert.True(CheckEquality(expectedMerge, merge));

            if (expectedDelta != null)
            {
                Assert.Equal(expectedDelta, expectedDelta);
            }
        }
예제 #5
0
        public async Task<MultiClusterData> Synchronize(MultiClusterData pushed)
        {
            logger.Verbose("-Synchronize pushed:{0}", pushed);

            try
            {
                // read the entire table from storage
                var entriesFromStorage = await tableManager.ReadAllEntriesAsync();
                var configInStorage = entriesFromStorage.Item1;
                var gatewayInfoInStorage = entriesFromStorage.Item2;

                // diff and write back configuration
                var configDeltaTask = DiffAndWriteBackConfigAsync(pushed.Configuration, configInStorage);

                // diff and write back gateway info for each gateway appearing locally or in storage
                var gatewayDeltaTasks = new List<Task<GatewayEntry>>();
                var allAddresses = gatewayInfoInStorage.Keys.Union(pushed.Gateways.Keys);
                foreach (var address in allAddresses)
                {
                    GatewayEntry pushedInfo = null;
                    pushed.Gateways.TryGetValue(address, out pushedInfo);
                    GossipTableEntry infoInStorage = null;
                    gatewayInfoInStorage.TryGetValue(address, out infoInStorage);

                    gatewayDeltaTasks.Add(DiffAndWriteBackGatewayInfoAsync(pushedInfo, infoInStorage));
                }

                // wait for all the writeback tasks to complete
                // these are not batched because we want them to fail individually on e-tag conflicts, not all
                await configDeltaTask;
                await Task.WhenAll(gatewayDeltaTasks);

                // assemble delta pieces
                var gw = new Dictionary<SiloAddress, GatewayEntry>();
                foreach (var t in gatewayDeltaTasks)
                {
                    var d = t.Result;
                    if (d != null)
                        gw.Add(d.SiloAddress, d);
                }
                var delta = new MultiClusterData(gw, configDeltaTask.Result);

                logger.Verbose("-Synchronize pulled delta:{0}", delta);

                return delta;
            }
            catch (Exception e)
            {
                logger.Info("-Synchronize encountered exception {0}", e);

                throw e;
            }
        }
예제 #6
0
        private void TestAlgebraicProperties(MultiClusterData A, MultiClusterData B)
        {
            MultiClusterData D;
            var BB    = B.Merge(A, out D);
            var empty = new MultiClusterData();

            AssertEffect(D, B, BB, D);
            AssertEffect(D, BB, BB, empty);
            AssertEffect(D, A, A, empty);

            AssertEffect(BB.Minus(D), B, B, empty);
            AssertEffect(BB.Minus(D), A, BB);
            AssertEffect(B, A, BB);
        }
예제 #7
0
        public void MultiClusterData_Configuration()
        {
            var ts1 = new DateTime(year: 2011, month: 1, day: 1);
            var ts2 = new DateTime(year: 2012, month: 2, day: 2);

            var conf1 = new MultiClusterConfiguration(ts1, new string[] { "A" }.ToList());
            var conf2 = new MultiClusterConfiguration(ts2, new string[] { "A", "B", "C" }.ToList());

            var gd1 = new MultiClusterData();
            var gd2 = new MultiClusterData(conf1);
            var gd3 = new MultiClusterData(conf2);

            TestAlgebraicProperties(gd1, gd1);
            TestAlgebraicProperties(gd2, gd2);
            TestAlgebraicProperties(gd1, gd2);
            TestAlgebraicProperties(gd3, gd1);
            TestAlgebraicProperties(gd2, gd3);
            TestAlgebraicProperties(gd3, gd2);
        }
예제 #8
0
        public void MultiClusterData_Configuration()
        {
            var ts1 = new DateTime(year: 2011, month: 1, day: 1);
            var ts2 = new DateTime(year: 2012, month: 2, day: 2);

            var conf1 = new MultiClusterConfiguration(ts1, new string[] { "A" }.ToList());
            var conf2 = new MultiClusterConfiguration(ts2, new string[] { "A", "B", "C" }.ToList());

            var gd1 = new MultiClusterData();
            var gd2 = new MultiClusterData(conf1);
            var gd3 = new MultiClusterData(conf2);

            TestAlgebraicProperties(gd1, gd1);
            TestAlgebraicProperties(gd2, gd2);
            TestAlgebraicProperties(gd1, gd2);
            TestAlgebraicProperties(gd3, gd1);
            TestAlgebraicProperties(gd2, gd3);
            TestAlgebraicProperties(gd3, gd2);
        }
예제 #9
0
        private bool CheckEquality(MultiClusterData one, MultiClusterData other)
        {
            if (one == null)
            {
                return(other == null);
            }
            if (other == null)
            {
                return(false);
            }

            if ((one.Configuration == null) != (other.Configuration == null))
            {
                return(false);
            }

            if (one.Gateways.Count != other.Gateways.Count)
            {
                return(false);
            }

            if ((one.Configuration != null) && !one.Configuration.Equals(other.Configuration))
            {
                return(false);
            }

            foreach (var g in one.Gateways)
            {
                GatewayEntry othergateway;
                if (!other.Gateways.TryGetValue(g.Key, out othergateway))
                {
                    return(false);
                }
                if (!g.Value.Equals(othergateway))
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #10
0
        public MultiClusterData ApplyDataAndNotify(MultiClusterData data)
        {
            if (data.IsEmpty)
                return data;

            MultiClusterData delta;
            MultiClusterData prev = this.localData;

            this.localData = prev.Merge(data, out delta);

            if (logger.IsVerbose2)
                logger.Verbose2("ApplyDataAndNotify: delta {0}", delta);

            if (delta.IsEmpty)
                return delta;

            if (delta.Configuration != null)
            {
                // notify configuration listeners of change
                // code will be added in separate PR
            }

            return delta;
        }
예제 #11
0
 internal MultiClusterOracleData(Logger log)
 {
     logger = log;
     localData = new MultiClusterData();
     activeGatewaysByCluster = new Dictionary<string, List<SiloAddress>>();
 }
예제 #12
0
        private void TestAlgebraicProperties(MultiClusterData A, MultiClusterData B)
        {
            MultiClusterData D;
            var BB = B.Merge(A, out D);
            var empty = new MultiClusterData();

            AssertEffect(D, B, BB, D);
            AssertEffect(D, BB, BB, empty);
            AssertEffect(D, A, A, empty);

            AssertEffect(BB.Minus(D), B, B, empty);
            AssertEffect(BB.Minus(D), A, BB);
            AssertEffect(B, A, BB);
        }
예제 #13
0
 internal MultiClusterOracleData(TraceLogger log)
 {
     logger = log;
     localData = new MultiClusterData();
 }
예제 #14
0
        private void AssertEffect(MultiClusterData what, MultiClusterData to, MultiClusterData expectedMerge, MultiClusterData expectedDelta = null)
        {
            MultiClusterData delta;
            var merge = to.Merge(what, out delta);

            Assert.True(CheckEquality(expectedMerge, merge));

            if (expectedDelta != null)
                Assert.Equal(expectedDelta, expectedDelta);
        }
예제 #15
0
        public void MultiClusterData_Gateways()
        {
            var ts1 = DateTime.UtcNow;
            var ts2 = ts1 + new TimeSpan(hours: 0, minutes: 0, seconds: 1);
            var ts3 = ts1 + new TimeSpan(hours: 0, minutes: 0, seconds: 2);

            IPAddress ip;

            Assert.True(IPAddress.TryParse("127.0.0.1", out ip));
            IPEndPoint ep1          = new IPEndPoint(ip, 21111);
            var        siloAddress1 = SiloAddress.New(ep1, 0);
            IPEndPoint ep2          = new IPEndPoint(ip, 21112);
            var        siloAddress2 = SiloAddress.New(ep2, 0);

            var G1 = new GatewayEntry()
            {
                SiloAddress        = siloAddress1,
                ClusterId          = "1",
                HeartbeatTimestamp = ts1,
                Status             = GatewayStatus.Active
            };
            var G2 = new GatewayEntry()
            {
                SiloAddress        = siloAddress1,
                ClusterId          = "1",
                HeartbeatTimestamp = ts3,
                Status             = GatewayStatus.Inactive
            };
            var H1 = new GatewayEntry()
            {
                SiloAddress        = siloAddress2,
                ClusterId          = "2",
                HeartbeatTimestamp = ts2,
                Status             = GatewayStatus.Active
            };
            var H2 = new GatewayEntry()
            {
                SiloAddress        = siloAddress2,
                ClusterId          = "2",
                HeartbeatTimestamp = ts3,
                Status             = GatewayStatus.Inactive
            };


            var gd1 = new MultiClusterData();
            var gd2 = new MultiClusterData(G1);
            var gd3 = new MultiClusterData(G2);

            TestAlgebraicProperties(gd1, gd1);
            TestAlgebraicProperties(gd2, gd2);
            TestAlgebraicProperties(gd1, gd2);
            TestAlgebraicProperties(gd3, gd1);
            TestAlgebraicProperties(gd2, gd3);
            TestAlgebraicProperties(gd3, gd2);

            gd1 = new MultiClusterData(new GatewayEntry[] { H1, G2 });
            gd2 = new MultiClusterData(new GatewayEntry[] { H2, G1 });

            TestAlgebraicProperties(gd1, gd1);
            TestAlgebraicProperties(gd1, gd2);
            TestAlgebraicProperties(gd2, gd1);

            gd1 = new MultiClusterData(new GatewayEntry[] { H1, G2 });
            gd2 = new MultiClusterData(new GatewayEntry[] { });

            TestAlgebraicProperties(gd1, gd2);
            TestAlgebraicProperties(gd2, gd1);

            gd1 = new MultiClusterData(new GatewayEntry[] { H1, G2 });
            gd2 = new MultiClusterData(new GatewayEntry[] { H1, G1 });

            TestAlgebraicProperties(gd1, gd2);
            TestAlgebraicProperties(gd2, gd1);

            gd1 = new MultiClusterData(new GatewayEntry[] { H1, G2 });
            gd2 = new MultiClusterData(new GatewayEntry[] { G1 });

            TestAlgebraicProperties(gd1, gd2);
            TestAlgebraicProperties(gd2, gd1);

            gd1 = new MultiClusterData(new GatewayEntry[] { H1, G2 });
            gd2 = new MultiClusterData(new GatewayEntry[] { H2 });

            TestAlgebraicProperties(gd1, gd2);
            TestAlgebraicProperties(gd2, gd1);
        }
예제 #16
0
        private bool CheckEquality(MultiClusterData one, MultiClusterData other)
        {
            if (one == null) return (other == null);
            if (other == null) return false;

            if ((one.Configuration == null) != (other.Configuration == null))
                return false;

            if (one.Gateways.Count != other.Gateways.Count)
                return false;

            if ((one.Configuration != null) && !one.Configuration.Equals(other.Configuration))
                return false;

            foreach (var g in one.Gateways)
            {
                GatewayEntry othergateway;
                if (!other.Gateways.TryGetValue(g.Key, out othergateway))
                    return false;
                if (!g.Value.Equals(othergateway))
                    return false;
            }

            return true;
        }
예제 #17
0
        public void MultiClusterData_Gateways()
        {
            var ts1 = DateTime.UtcNow;
            var ts2 = ts1 + new TimeSpan(hours: 0, minutes: 0, seconds: 1);
            var ts3 = ts1 + new TimeSpan(hours: 0, minutes: 0, seconds: 2);

            IPAddress ip;
            Assert.True(IPAddress.TryParse("127.0.0.1", out ip));
            IPEndPoint ep1 = new IPEndPoint(ip, 21111);
            var siloAddress1 = SiloAddress.New(ep1, 0);
            IPEndPoint ep2 = new IPEndPoint(ip, 21112);
            var siloAddress2 = SiloAddress.New(ep2, 0);

            var G1 = new GatewayEntry()
            {
                SiloAddress = siloAddress1,
                ClusterId = "1",
                HeartbeatTimestamp = ts1,
                Status = GatewayStatus.Active
            };
            var G2 = new GatewayEntry()
            {
                SiloAddress = siloAddress1,
                ClusterId = "1",
                HeartbeatTimestamp = ts3,
                Status = GatewayStatus.Inactive
            };
            var H1 = new GatewayEntry()
            {
                SiloAddress = siloAddress2,
                ClusterId = "2",
                HeartbeatTimestamp = ts2,
                Status = GatewayStatus.Active
            };
            var H2 = new GatewayEntry()
            {
                SiloAddress = siloAddress2,
                ClusterId = "2",
                HeartbeatTimestamp = ts3,
                Status = GatewayStatus.Inactive
            };


            var gd1 = new MultiClusterData();
            var gd2 = new MultiClusterData(G1);
            var gd3 = new MultiClusterData(G2);

            TestAlgebraicProperties(gd1, gd1);
            TestAlgebraicProperties(gd2, gd2);
            TestAlgebraicProperties(gd1, gd2);
            TestAlgebraicProperties(gd3, gd1);
            TestAlgebraicProperties(gd2, gd3);
            TestAlgebraicProperties(gd3, gd2);

            gd1 = new MultiClusterData(new GatewayEntry[] { H1, G2 });
            gd2 = new MultiClusterData(new GatewayEntry[] { H2, G1 });

            TestAlgebraicProperties(gd1, gd1);
            TestAlgebraicProperties(gd1, gd2);
            TestAlgebraicProperties(gd2, gd1);

            gd1 = new MultiClusterData(new GatewayEntry[] { H1, G2 });
            gd2 = new MultiClusterData(new GatewayEntry[] { });

            TestAlgebraicProperties(gd1, gd2);
            TestAlgebraicProperties(gd2, gd1);

            gd1 = new MultiClusterData(new GatewayEntry[] { H1, G2 });
            gd2 = new MultiClusterData(new GatewayEntry[] { H1, G1 });

            TestAlgebraicProperties(gd1, gd2);
            TestAlgebraicProperties(gd2, gd1);

            gd1 = new MultiClusterData(new GatewayEntry[] { H1, G2 });
            gd2 = new MultiClusterData(new GatewayEntry[] { G1 });

            TestAlgebraicProperties(gd1, gd2);
            TestAlgebraicProperties(gd2, gd1);

            gd1 = new MultiClusterData(new GatewayEntry[] { H1, G2 });
            gd2 = new MultiClusterData(new GatewayEntry[] { H2 });

            TestAlgebraicProperties(gd1, gd2);
            TestAlgebraicProperties(gd2, gd1);
        }
 internal MultiClusterOracleData(Logger log)
 {
     logger    = log;
     localData = new MultiClusterData();
 }