示例#1
0
        public LocalGrainDirectory(Silo silo)
        {
            log = TraceLogger.GetLogger("Orleans.GrainDirectory.LocalGrainDirectory");

            MyAddress          = silo.LocalMessageCenter.MyAddress;
            Scheduler          = silo.LocalScheduler;
            membershipRingList = new List <SiloAddress>();
            membershipCache    = new HashSet <SiloAddress>();

            silo.OrleansConfig.OnConfigChange("Globals/Caching", () =>
            {
                lock (membershipCache)
                {
                    DirectoryCache = GrainDirectoryCacheFactory <List <Tuple <SiloAddress, ActivationId> > > .CreateGrainDirectoryCache(silo.GlobalConfig);
                }
            });
            maintainer = GrainDirectoryCacheFactory <List <Tuple <SiloAddress, ActivationId> > > .CreateGrainDirectoryCacheMaintainer(this, DirectoryCache);

            if (silo.GlobalConfig.SeedNodes.Count > 0)
            {
                seed = silo.GlobalConfig.SeedNodes.Contains(MyAddress.Endpoint) ? MyAddress : SiloAddress.New(silo.GlobalConfig.SeedNodes[0], 0);
            }

            stopPreparationResolver = new TaskCompletionSource <bool>();
            DirectoryPartition      = new GrainDirectoryPartition();
            HandoffManager          = new GrainDirectoryHandoffManager(this, silo.GlobalConfig);

            RemGrainDirectory = new RemoteGrainDirectory(this, Constants.DirectoryServiceId);
            CacheValidator    = new RemoteGrainDirectory(this, Constants.DirectoryCacheValidatorId);

            // add myself to the list of members
            AddServer(MyAddress);

            Func <SiloAddress, string> siloAddressPrint = (SiloAddress addr) =>
                                                          String.Format("{0}/{1:X}", addr.ToLongString(), addr.GetConsistentHashCode());

            localLookups   = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_LOCAL_ISSUED);
            localSuccesses = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_LOCAL_SUCCESSES);
            fullLookups    = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_FULL_ISSUED);

            RemoteLookupsSent     = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_REMOTE_SENT);
            RemoteLookupsReceived = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_REMOTE_RECEIVED);

            LocalDirectoryLookups   = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_LOCALDIRECTORY_ISSUED);
            LocalDirectorySuccesses = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_LOCALDIRECTORY_SUCCESSES);

            cacheLookups   = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_CACHE_ISSUED);
            cacheSuccesses = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_CACHE_SUCCESSES);
            StringValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_CACHE_HITRATIO, () =>
            {
                long delta1, delta2;
                long curr1 = cacheSuccesses.GetCurrentValueAndDelta(out delta1);
                long curr2 = cacheLookups.GetCurrentValueAndDelta(out delta2);
                return(String.Format("{0}, Delta={1}",
                                     (curr2 != 0 ? (float)curr1 / (float)curr2 : 0)
                                     , (delta2 != 0 ? (float)delta1 / (float)delta2 : 0)));
            });

            CacheValidationsSent     = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_VALIDATIONS_CACHE_SENT);
            CacheValidationsReceived = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_VALIDATIONS_CACHE_RECEIVED);

            registrationsIssued                  = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_ISSUED);
            RegistrationsLocal                   = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_LOCAL);
            RegistrationsRemoteSent              = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_REMOTE_SENT);
            RegistrationsRemoteReceived          = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_REMOTE_RECEIVED);
            registrationsSingleActIssued         = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_SINGLE_ACT_ISSUED);
            RegistrationsSingleActLocal          = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_SINGLE_ACT_LOCAL);
            RegistrationsSingleActRemoteSent     = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_SINGLE_ACT_REMOTE_SENT);
            RegistrationsSingleActRemoteReceived = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_SINGLE_ACT_REMOTE_RECEIVED);
            unregistrationsIssued                = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_UNREGISTRATIONS_ISSUED);
            UnregistrationsLocal                 = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_UNREGISTRATIONS_LOCAL);
            UnregistrationsRemoteSent            = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_UNREGISTRATIONS_REMOTE_SENT);
            UnregistrationsRemoteReceived        = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_UNREGISTRATIONS_REMOTE_RECEIVED);
            unregistrationsManyIssued            = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_UNREGISTRATIONS_MANY_ISSUED);
            UnregistrationsManyRemoteSent        = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_UNREGISTRATIONS_MANY_REMOTE_SENT);
            UnregistrationsManyRemoteReceived    = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_UNREGISTRATIONS_MANY_REMOTE_RECEIVED);

            directoryPartitionCount = IntValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_PARTITION_SIZE, () => DirectoryPartition.Count);
            IntValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_RING_MYPORTION_RINGDISTANCE, () => RingDistanceToSuccessor());
            FloatValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_RING_MYPORTION_RINGPERCENTAGE, () => (((float)RingDistanceToSuccessor()) / ((float)(int.MaxValue * 2L))) * 100);
            FloatValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_RING_MYPORTION_AVERAGERINGPERCENTAGE, () => membershipRingList.Count == 0 ? 0 : ((float)100 / (float)membershipRingList.Count));
            IntValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_RING_RINGSIZE, () => membershipRingList.Count);
            StringValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_RING, () =>
            {
                lock (membershipCache)
                {
                    return(Utils.EnumerableToString(membershipRingList, siloAddressPrint));
                }
            });
            StringValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_RING_PREDECESSORS, () => Utils.EnumerableToString(FindPredecessors(MyAddress, 1), siloAddressPrint));
            StringValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_RING_SUCCESSORS, () => Utils.EnumerableToString(FindSuccessors(MyAddress, 1), siloAddressPrint));
        }
 private static SiloAddress NewSiloAddress(int generation) =>
 SiloAddress.New(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 33333), generation);
示例#3
0
        public LocalGrainDirectory(
            IServiceProvider serviceProvider,
            ILocalSiloDetails siloDetails,
            ISiloStatusOracle siloStatusOracle,
            IInternalGrainFactory grainFactory,
            Factory <GrainDirectoryPartition> grainDirectoryPartitionFactory,
            IOptions <DevelopmentClusterMembershipOptions> developmentClusterMembershipOptions,
            IOptions <GrainDirectoryOptions> grainDirectoryOptions,
            ILoggerFactory loggerFactory)
        {
            this.log = loggerFactory.CreateLogger <LocalGrainDirectory>();

            var clusterId = siloDetails.ClusterId;

            MyAddress = siloDetails.SiloAddress;

            this.siloStatusOracle = siloStatusOracle;
            this.grainFactory     = grainFactory;
            ClusterId             = clusterId;

            DirectoryCache = GrainDirectoryCacheFactory.CreateGrainDirectoryCache(serviceProvider, grainDirectoryOptions.Value);
            maintainer     =
                GrainDirectoryCacheFactory.CreateGrainDirectoryCacheMaintainer(
                    this,
                    this.DirectoryCache,
                    grainFactory,
                    loggerFactory);

            var primarySiloEndPoint = developmentClusterMembershipOptions.Value.PrimarySiloEndpoint;

            if (primarySiloEndPoint != null)
            {
                this.seed = this.MyAddress.Endpoint.Equals(primarySiloEndPoint) ? this.MyAddress : SiloAddress.New(primarySiloEndPoint, 0);
            }

            DirectoryPartition = grainDirectoryPartitionFactory();
            HandoffManager     = new GrainDirectoryHandoffManager(this, siloStatusOracle, grainFactory, grainDirectoryPartitionFactory, loggerFactory);

            RemoteGrainDirectory = new RemoteGrainDirectory(this, Constants.DirectoryServiceType, loggerFactory);
            CacheValidator       = new RemoteGrainDirectory(this, Constants.DirectoryCacheValidatorType, loggerFactory);

            // add myself to the list of members
            AddServer(MyAddress);

            Func <SiloAddress, string> siloAddressPrint = (SiloAddress addr) =>
                                                          String.Format("{0}/{1:X}", addr.ToLongString(), addr.GetConsistentHashCode());

            localLookups   = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_LOCAL_ISSUED);
            localSuccesses = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_LOCAL_SUCCESSES);
            fullLookups    = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_FULL_ISSUED);

            RemoteLookupsSent     = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_REMOTE_SENT);
            RemoteLookupsReceived = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_REMOTE_RECEIVED);

            LocalDirectoryLookups   = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_LOCALDIRECTORY_ISSUED);
            LocalDirectorySuccesses = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_LOCALDIRECTORY_SUCCESSES);

            cacheLookups   = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_CACHE_ISSUED);
            cacheSuccesses = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_CACHE_SUCCESSES);
            StringValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_LOOKUPS_CACHE_HITRATIO, () =>
            {
                long delta1, delta2;
                long curr1 = cacheSuccesses.GetCurrentValueAndDelta(out delta1);
                long curr2 = cacheLookups.GetCurrentValueAndDelta(out delta2);
                return(String.Format("{0}, Delta={1}",
                                     (curr2 != 0 ? (float)curr1 / (float)curr2 : 0)
                                     , (delta2 != 0 ? (float)delta1 / (float)delta2 : 0)));
            });

            CacheValidationsSent     = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_VALIDATIONS_CACHE_SENT);
            CacheValidationsReceived = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_VALIDATIONS_CACHE_RECEIVED);

            registrationsIssued                  = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_ISSUED);
            RegistrationsLocal                   = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_LOCAL);
            RegistrationsRemoteSent              = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_REMOTE_SENT);
            RegistrationsRemoteReceived          = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_REMOTE_RECEIVED);
            registrationsSingleActIssued         = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_SINGLE_ACT_ISSUED);
            RegistrationsSingleActLocal          = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_SINGLE_ACT_LOCAL);
            RegistrationsSingleActRemoteSent     = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_SINGLE_ACT_REMOTE_SENT);
            RegistrationsSingleActRemoteReceived = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_REGISTRATIONS_SINGLE_ACT_REMOTE_RECEIVED);
            unregistrationsIssued                = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_UNREGISTRATIONS_ISSUED);
            UnregistrationsLocal                 = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_UNREGISTRATIONS_LOCAL);
            UnregistrationsRemoteSent            = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_UNREGISTRATIONS_REMOTE_SENT);
            UnregistrationsRemoteReceived        = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_UNREGISTRATIONS_REMOTE_RECEIVED);
            unregistrationsManyIssued            = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_UNREGISTRATIONS_MANY_ISSUED);
            UnregistrationsManyRemoteSent        = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_UNREGISTRATIONS_MANY_REMOTE_SENT);
            UnregistrationsManyRemoteReceived    = CounterStatistic.FindOrCreate(StatisticNames.DIRECTORY_UNREGISTRATIONS_MANY_REMOTE_RECEIVED);

            directoryPartitionCount = IntValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_PARTITION_SIZE, () => DirectoryPartition.Count);
            IntValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_RING_MYPORTION_RINGDISTANCE, () => RingDistanceToSuccessor());
            FloatValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_RING_MYPORTION_RINGPERCENTAGE, () => (((float)this.RingDistanceToSuccessor()) / ((float)(int.MaxValue * 2L))) * 100);
            FloatValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_RING_MYPORTION_AVERAGERINGPERCENTAGE, () =>
            {
                var ring = this.directoryMembership.MembershipRingList;
                return(ring.Count == 0 ? 0 : ((float)100 / (float)ring.Count));
            });
            IntValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_RING_RINGSIZE, () => this.directoryMembership.MembershipRingList.Count);
            StringValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_RING, () =>
            {
                var ring = this.directoryMembership.MembershipRingList;
                return(Utils.EnumerableToString(ring, siloAddressPrint));
            });
            StringValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_RING_PREDECESSORS, () => Utils.EnumerableToString(this.FindPredecessors(this.MyAddress, 1), siloAddressPrint));
            StringValueStatistic.FindOrCreate(StatisticNames.DIRECTORY_RING_SUCCESSORS, () => Utils.EnumerableToString(this.FindSuccessors(this.MyAddress, 1), siloAddressPrint));
        }
        private async Task <IMembershipTableSystemTarget> GetMembershipTable()
        {
            var options = this.serviceProvider.GetRequiredService <IOptions <DevelopmentClusterMembershipOptions> >().Value;

            if (options.PrimarySiloEndpoint == null)
            {
                throw new OrleansConfigurationException(
                          $"{nameof(DevelopmentClusterMembershipOptions)}.{nameof(options.PrimarySiloEndpoint)} must be set when using development clustering.");
            }

            var  siloDetails   = this.serviceProvider.GetService <ILocalSiloDetails>();
            bool isPrimarySilo = siloDetails.SiloAddress.Endpoint.Equals(options.PrimarySiloEndpoint);

            if (isPrimarySilo)
            {
                this.logger.Info(ErrorCode.MembershipFactory1, "Creating in-memory membership table");
                var catalog = serviceProvider.GetRequiredService <Catalog>();
                catalog.RegisterSystemTarget(ActivatorUtilities.CreateInstance <MembershipTableSystemTarget>(serviceProvider));
            }

            var grainFactory = this.serviceProvider.GetRequiredService <IInternalGrainFactory>();
            var result       = grainFactory.GetSystemTarget <IMembershipTableSystemTarget>(Constants.SystemMembershipTableType, SiloAddress.New(options.PrimarySiloEndpoint, 0));

            if (isPrimarySilo)
            {
                await this.WaitForTableGrainToInit(result);
            }

            return(result);
        }
示例#5
0
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var stored = (StoredSiloAddress)serializer.Deserialize(reader, typeof(StoredSiloAddress));

            return(SiloAddress.New(stored.Endpoint, stored.Generation));
        }
示例#6
0
        // This function is called asynchronously from gateway refresh timer.
        private void UpdateLiveGatewaysSnapshot(IEnumerable <SiloAddress> refreshedGateways, TimeSpan maxStaleness)
        {
            // this is a short lock, protecting the access to knownDead and cachedLiveGateways.
            lock (lockable)
            {
                // now take whatever listProvider gave us and exclude those we think are dead.

                var live = new List <SiloAddress>();
                var now  = DateTime.UtcNow;

                this.knownGateways = refreshedGateways as List <SiloAddress> ?? refreshedGateways.ToList();
                foreach (SiloAddress trial in knownGateways)
                {
                    var address = trial.Generation == 0 ? trial : SiloAddress.New(trial.Endpoint, 0);

                    // We consider a node to be dead if we recorded it is dead due to socket error
                    // and it was recorded (diedAt) not too long ago (less than maxStaleness ago).
                    // The latter is to cover the case when the Gateway provider returns an outdated list that does not yet reflect the actually recently died Gateway.
                    // If it has passed more than maxStaleness - we assume maxStaleness is the upper bound on Gateway provider freshness.
                    var isDead = false;
                    if (knownDead.TryGetValue(address, out var diedAt))
                    {
                        if (now.Subtract(diedAt) < maxStaleness)
                        {
                            isDead = true;
                        }
                        else
                        {
                            // Remove stale entries.
                            knownDead.Remove(address);
                        }
                    }

                    if (!isDead)
                    {
                        live.Add(address);
                    }
                }

                if (live.Count == 0)
                {
                    logger.Warn(
                        ErrorCode.GatewayManager_AllGatewaysDead,
                        "All gateways have previously been marked as dead. Clearing the list of dead gateways to expedite reconnection.");
                    live.AddRange(knownGateways);
                    knownDead.Clear();
                }

                // swap cachedLiveGateways pointer in one atomic operation
                cachedLiveGateways = live;

                DateTime prevRefresh = lastRefreshTime;
                lastRefreshTime = now;
                if (logger.IsEnabled(LogLevel.Information))
                {
                    logger.Info(ErrorCode.GatewayManager_FoundKnownGateways,
                                "Refreshed the live Gateway list. Found {0} gateways from Gateway listProvider: {1}. Picked only known live out of them. Now has {2} live Gateways: {3}. Previous refresh time was = {4}",
                                knownGateways.Count(),
                                Utils.EnumerableToString(knownGateways),
                                cachedLiveGateways.Count,
                                Utils.EnumerableToString(cachedLiveGateways),
                                prevRefresh);
                }

                this.AbortEvictedGatewayConnections(live);
            }
        }
示例#7
0
        private static Uri ConvertToGatewayUri(SiloEntity gateway)
        {
            SiloAddress address = SiloAddress.New(new IPEndPoint(IPAddress.Parse(gateway.Address), gateway.ProxyPort.Value), gateway.Generation);

            return(address.ToGatewayUri());
        }
 private static SiloAddress NewSiloAddress(string ip, ushort port, int generation) =>
 SiloAddress.New(new IPEndPoint(IPAddress.Parse(ip), port), generation);
        public async Task UnknownSilosAreAccountedForDuringUpdate()
        {
            var now = new[] { DateTime.UtcNow };

            this.unknownSiloMonitor.GetDateTime = () => now[0];

            var listener = new MockStatusListener();

            this.oracle.SubscribeToSiloStatusEvents(listener);
            await this.oracle.Start();

            await this.oracle.BecomeActive();

            var silos = new[]
            {
                CreateSiloInfo(
                    SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 1), 1),
                    SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 2), 1),
                    "HappyNewSilo"),
                CreateSiloInfo(
                    SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 3), 2),
                    SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 4), 2),
                    "OtherNewSilo"),
            };

            this.resolver.Notify(silos);
            listener.WaitForVersion(4);
            Assert.Equal(3, listener.Silos.Count);

            // Query for an unknown silo. Doing so should result in the silo being recorded as unknown.
            var unknownSilo1 = SiloAddress.New(new IPEndPoint(IPAddress.Parse("1.1.1.1"), 3), 3);

            Assert.Equal(SiloStatus.None, this.oracle.GetApproximateSiloStatus(unknownSilo1));
            this.resolver.Notify(silos);

            // The status should not have changed.
            Assert.Equal(SiloStatus.None, this.oracle.GetApproximateSiloStatus(unknownSilo1));

            now[0] += this.fabricClusteringOptions.UnknownSiloRemovalPeriod + TimeSpan.FromMilliseconds(1);
            this.resolver.Notify(silos);
            listener.WaitForVersion(5);

            // After the delay, the silo should be declared dead.
            Assert.Equal(SiloStatus.Dead, this.oracle.GetApproximateSiloStatus(unknownSilo1));

            // Query for another unknown silo using a different mechanism.
            var unknownSilo2 = SiloAddress.New(new IPEndPoint(IPAddress.Parse("2.2.2.2"), 4), 4);

            Assert.False(this.oracle.IsFunctionalDirectory(unknownSilo2));

            // Report a new silo with the same endpoint as the unknown silo but a higher generation.
            silos = new[]
            {
                silos[0],
                silos[1],
                CreateSiloInfo(
                    SiloAddress.New(new IPEndPoint(IPAddress.Parse("2.2.2.2"), 4), 5),
                    SiloAddress.Zero,
                    "TippyTop")
            };

            this.resolver.Notify(silos);
            listener.WaitForVersion(6);
            Assert.True(this.oracle.IsDeadSilo(unknownSilo2));
        }
示例#10
0
        private static Uri ReturnGatewayUri(MongoMembershipDocument record)
        {
            var siloAddress = SiloAddress.FromParsableString(record.SiloAddress);

            return(SiloAddress.New(new IPEndPoint(siloAddress.Endpoint.Address, record.ProxyPort), siloAddress.Generation).ToGatewayUri());
        }
示例#11
0
        private static void RunTest(int numItems)
        {
            InvokeMethodRequest request = new InvokeMethodRequest(0, 0, null);
            Message             resp    = Message.CreateMessage(request, InvokeMethodOptions.None);

            resp.Id           = new CorrelationId();
            resp.SendingSilo  = SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 200), 0);
            resp.TargetSilo   = SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 300), 0);
            resp.SendingGrain = GrainId.NewId();
            resp.TargetGrain  = GrainId.NewId();
            resp.SetHeader(Message.Header.ALWAYS_INTERLEAVE, true);
            resp.SetHeader(Message.Header.CACHE_INVALIDATION_HEADER, "TestBar");
            //resp.SetStringBody("This is test data");

            List <object> requestBody = new List <object>();

            for (int k = 0; k < numItems; k++)
            {
                requestBody.Add(k + ": test line");
            }

            resp.BodyObject = requestBody;

            string s = resp.ToString();

            Console.WriteLine(s);

            var serialized = resp.Serialize();
            int length     = serialized.Sum <ArraySegment <byte> >(x => x.Count);

            byte[] data = new byte[length];
            int    n    = 0;

            foreach (var buffer in serialized)
            {
                Array.Copy(buffer.Array, buffer.Offset, data, n, buffer.Count);
                n += buffer.Count;
            }
            resp.ReleaseBodyAndHeaderBuffers();

            int headerLength = BitConverter.ToInt32(data, 0);
            int bodyLength   = BitConverter.ToInt32(data, 4);

            Assert.AreEqual <int>(length, headerLength + bodyLength + 8, "Serialized lengths are incorrect");
            byte[] header = new byte[headerLength];
            Array.Copy(data, 8, header, 0, headerLength);
            byte[] body = new byte[bodyLength];
            Array.Copy(data, 8 + headerLength, body, 0, bodyLength);
            var headerList = new List <ArraySegment <byte> >();

            headerList.Add(new ArraySegment <byte>(header));
            var bodyList = new List <ArraySegment <byte> >();

            bodyList.Add(new ArraySegment <byte>(body));
            var resp1 = new Message(headerList, bodyList);

            //byte[] serialized = resp.FormatForSending();
            //Message resp1 = new Message(serialized, serialized.Length);
            Assert.AreEqual <Message.Categories>(resp.Category, resp1.Category, "Category is incorrect");
            Assert.AreEqual <Message.Directions>(resp.Direction, resp1.Direction, "Direction is incorrect");
            Assert.AreEqual <CorrelationId>(resp.Id, resp1.Id, "Correlation ID is incorrect");
            Assert.AreEqual <bool>((bool)resp.GetHeader(Message.Header.ALWAYS_INTERLEAVE), (bool)resp1.GetHeader(Message.Header.ALWAYS_INTERLEAVE), "Foo Boolean is incorrect");
            Assert.AreEqual <string>((string)resp.GetHeader(Message.Header.CACHE_INVALIDATION_HEADER), (string)resp1.GetHeader(Message.Header.CACHE_INVALIDATION_HEADER), "Bar string is incorrect");
            Assert.IsTrue(resp.TargetSilo.Equals(resp1.TargetSilo), "TargetSilo is incorrect");
            Assert.IsTrue(resp.SendingSilo.Equals(resp1.SendingSilo), "SendingSilo is incorrect");
            Assert.IsInstanceOfType(resp1.BodyObject, typeof(List <object>), "Body object is wrong type");
            List <object> responseList = resp1.BodyObject as List <object>;

            Assert.AreEqual <int>(numItems, responseList.Count, "Body list has wrong number of entries");
            for (int k = 0; k < numItems; k++)
            {
                Assert.IsInstanceOfType(responseList[k], typeof(string), "Body list item " + k + " has wrong type");
                Assert.AreEqual <string>((string)(requestBody[k]), (string)(responseList[k]), "Body list item " + k + " is incorrect");
            }
        }
示例#12
0
        private ValueTask<Connection> GetGatewayConnection(Message msg)
        {
            // If there's a specific gateway specified, use it
            if (msg.TargetSilo != null && gatewayManager.GetLiveGateways().Contains(msg.TargetSilo))
            {
                var siloAddress = SiloAddress.New(msg.TargetSilo.Endpoint, 0);
                var connectionTask = this.connectionManager.GetConnection(siloAddress);
                if (connectionTask.IsCompletedSuccessfully) return connectionTask;

                return ConnectAsync(msg.TargetSilo, connectionTask, msg, directGatewayMessage: true);
            }

            // For untargeted messages to system targets, and for unordered messages, pick a next connection in round robin fashion.
            if (msg.TargetGrain.IsSystemTarget || msg.IsUnordered)
            {
                // Get the cached list of live gateways.
                // Pick a next gateway name in a round robin fashion.
                // See if we have a live connection to it.
                // If Yes, use it.
                // If not, create a new GatewayConnection and start it.
                // If start fails, we will mark this connection as dead and remove it from the GetCachedLiveGatewayNames.
                int msgNumber = Interlocked.Increment(ref numMessages);
                var gatewayAddresses = gatewayManager.GetLiveGateways();
                int numGateways = gatewayAddresses.Count;
                if (numGateways == 0)
                {
                    RejectMessage(msg, "No gateways available");
                    logger.Warn(ErrorCode.ProxyClient_CannotSend, "Unable to send message {0}; gateway manager state is {1}", msg, gatewayManager);
                    return new ValueTask<Connection>(default(Connection));
                }

                var gatewayAddress = gatewayAddresses[msgNumber % numGateways];

                var connectionTask = this.connectionManager.GetConnection(gatewayAddress);
                if (connectionTask.IsCompletedSuccessfully) return connectionTask;

                return ConnectAsync(gatewayAddress, connectionTask, msg, directGatewayMessage: false);
            }

            // Otherwise, use the buckets to ensure ordering.
            var index = msg.TargetGrain.GetHashCode_Modulo((uint)grainBuckets.Length);

            // Repeated from above, at the declaration of the grainBuckets array:
            // Requests are bucketed by GrainID, so that all requests to a grain get routed through the same bucket.
            // Each bucket holds a (possibly null) weak reference to a GatewayConnection object. That connection instance is used
            // if the WeakReference is non-null, is alive, and points to a live gateway connection. If any of these conditions is
            // false, then a new gateway is selected using the gateway manager, and a new connection established if necessary.
            WeakReference<Connection> weakRef = grainBuckets[index];

            if (weakRef != null && weakRef.TryGetTarget(out var existingConnection) && existingConnection.IsValid)
            {
                return new ValueTask<Connection>(existingConnection);
            }

            var addr = gatewayManager.GetLiveGateway();
            if (addr == null)
            {
                RejectMessage(msg, "No gateways available");
                logger.Warn(ErrorCode.ProxyClient_CannotSend_NoGateway, "Unable to send message {0}; gateway manager state is {1}", msg, gatewayManager);
                return new ValueTask<Connection>(default(Connection));
            }
            if (logger.IsEnabled(LogLevel.Trace)) logger.Trace(ErrorCode.ProxyClient_NewBucketIndex, "Starting new bucket index {0} for ordered messages to grain {1}", index, msg.TargetGrain);

            if (logger.IsEnabled(LogLevel.Debug)) logger.Debug(
                ErrorCode.ProxyClient_CreatedGatewayToGrain,
                "Creating gateway to {0} for message to grain {1}, bucket {2}, grain id hash code {3}X",
                addr,
                msg.TargetGrain,
                index,
                msg.TargetGrain.GetHashCode().ToString("x"));

            var gatewayConnection = this.connectionManager.GetConnection(addr);
            if (gatewayConnection.IsCompletedSuccessfully)
            {
                this.UpdateBucket(index, gatewayConnection.Result);
                return gatewayConnection;
            }

            return AddToBucketAsync(index, gatewayConnection, addr);

            async ValueTask<Connection> AddToBucketAsync(
                uint bucketIndex,
                ValueTask<Connection> connectionTask,
                SiloAddress gatewayAddress)
            {
                try
                {
                    var connection = await connectionTask.ConfigureAwait(false);
                    this.UpdateBucket(bucketIndex, connection);
                    return connection;
                }
                catch
                {
                    this.gatewayManager.MarkAsDead(gatewayAddress);
                    this.UpdateBucket(bucketIndex, null);
                    throw;
                }
            }

            async ValueTask<Connection> ConnectAsync(
                SiloAddress gateway,
                ValueTask<Connection> connectionTask,
                Message message,
                bool directGatewayMessage)
            {
                Connection result = default;
                try
                {
                    return result = await connectionTask;
                }
                catch (Exception exception) when (directGatewayMessage)
                {
                    RejectMessage(message, string.Format("Target silo {0} is unavailable", message.TargetSilo), exception);
                    return null;
                }
                finally
                {
                    if (result is null) this.gatewayManager.MarkAsDead(gateway);
                }
            }
        }
 private SiloAddress GenerateSiloAddress() => SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 5000), ++generation);
 public static SiloAddress NewLocalSiloAddress(int gen)
 {
     return(SiloAddress.New(localEndpoint, gen));
 }
示例#15
0
        private void RunTest(int numItems)
        {
            InvokeMethodRequest request = new InvokeMethodRequest(0, 2, 0, null);
            Message             resp    = this.messageFactory.CreateMessage(request, InvokeMethodOptions.None);

            resp.Id                 = new CorrelationId();
            resp.SendingSilo        = SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 200), 0);
            resp.TargetSilo         = SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 300), 0);
            resp.SendingGrain       = GrainId.NewId();
            resp.TargetGrain        = GrainId.NewId();
            resp.IsAlwaysInterleave = true;
            Assert.True(resp.IsUsingInterfaceVersions);

            List <object> requestBody = new List <object>();

            for (int k = 0; k < numItems; k++)
            {
                requestBody.Add(k + ": test line");
            }

            resp.BodyObject = requestBody;

            string s = resp.ToString();

            output.WriteLine(s);

            int dummy;
            var serialized = resp.Serialize(this.fixture.SerializationManager, out dummy, out dummy);
            int length     = serialized.Sum <ArraySegment <byte> >(x => x.Count);

            byte[] data = new byte[length];
            int    n    = 0;

            foreach (var buffer in serialized)
            {
                Array.Copy(buffer.Array, buffer.Offset, data, n, buffer.Count);
                n += buffer.Count;
            }
            resp.ReleaseBodyAndHeaderBuffers();

            var resp1 = DeserializeMessage(length, data);

            //byte[] serialized = resp.FormatForSending();
            //Message resp1 = new Message(serialized, serialized.Length);
            Assert.Equal(resp.Category, resp1.Category);                               //Category is incorrect"
            Assert.Equal(resp.Direction, resp1.Direction);                             //Direction is incorrect
            Assert.Equal(resp.Id, resp1.Id);                                           //Correlation ID is incorrect
            Assert.Equal(resp.IsAlwaysInterleave, resp1.IsAlwaysInterleave);           //Foo Boolean is incorrect
            Assert.Equal(resp.CacheInvalidationHeader, resp1.CacheInvalidationHeader); //Bar string is incorrect
            Assert.True(resp.TargetSilo.Equals(resp1.TargetSilo));
            Assert.True(resp.TargetGrain.Equals(resp1.TargetGrain));
            Assert.True(resp.SendingGrain.Equals(resp1.SendingGrain));
            Assert.True(resp.SendingSilo.Equals(resp1.SendingSilo)); //SendingSilo is incorrect
            Assert.True(resp1.IsUsingInterfaceVersions);
            List <object> responseList = Assert.IsAssignableFrom <List <object> >(resp1.GetDeserializedBody(this.fixture.SerializationManager));

            Assert.Equal <int>(numItems, responseList.Count); //Body list has wrong number of entries
            for (int k = 0; k < numItems; k++)
            {
                Assert.IsAssignableFrom <string>(responseList[k]);                          //Body list item " + k + " has wrong type
                Assert.Equal <string>((string)(requestBody[k]), (string)(responseList[k])); //Body list item " + k + " is incorrect
            }
        }
示例#16
0
        private static MembershipEntry ConvertFromRow(SqlDataReader results, out string eTag, out int tableVersion, out string versionETag)
        {
            var entry = new MembershipEntry();

            int port = results.GetInt32(PortIdx);
            int gen  = results.GetInt32(GenerationIdx);

            entry.SiloAddress = SiloAddress.New(new IPEndPoint(IPAddress.Parse(results.GetString(AddressIdx)), port), gen);

            entry.HostName = results.GetString(HostNameIdx);
            entry.Status   = (SiloStatus)results.GetInt32(StatusIdx);
            if (!results.GetSqlInt32(ProxyPortIdx).IsNull)
            {
                entry.ProxyPort = results.GetInt32(ProxyPortIdx);
            }
            if (!results.GetSqlBoolean(PrimaryIdx).IsNull)
            {
                entry.IsPrimary = results.GetBoolean(PrimaryIdx);
            }

            entry.RoleName     = results.GetString(RoleNameIdx);
            entry.InstanceName = results.GetString(InstanceNameIdx);
            if (!results.GetSqlInt32(UpdateZoneIdx).IsNull)
            {
                entry.UpdateZone = results.GetInt32(UpdateZoneIdx);
            }
            if (!results.GetSqlInt32(FaultZoneIdx).IsNull)
            {
                entry.FaultZone = results.GetInt32(FaultZoneIdx);
            }

            if (!results.GetSqlDateTime(StartTimeIdx).IsNull)
            {
                entry.StartTime = results.GetDateTime(StartTimeIdx);
            }
            if (!results.GetSqlDateTime(IAmAliveTimeIdx).IsNull)
            {
                entry.IAmAliveTime = results.GetDateTime(IAmAliveTimeIdx);
            }
            eTag         = results.GetString(ETagIdx);
            tableVersion = (int)results.GetInt64(VersionIdx);
            versionETag  = results.GetString(VersionETagIdx);

            var suspectingSilosString = results.GetSqlString(SuspectingSilosIdx);
            var suspectingTimesString = results.GetSqlString(SuspectingTimesIdx);

            List <SiloAddress> suspectingSilos = new List <SiloAddress>();
            List <DateTime>    suspectingTimes = new List <DateTime>();

            if (!suspectingSilosString.IsNull && !string.IsNullOrEmpty(suspectingSilosString.Value))
            {
                string[] silos = suspectingSilosString.Value.Split('|');
                foreach (string silo in silos)
                {
                    suspectingSilos.Add(SiloAddress.FromParsableString(silo));
                }
            }

            if (!suspectingTimesString.IsNull && !string.IsNullOrEmpty(suspectingTimesString.Value))
            {
                string[] times = suspectingTimesString.Value.Split('|');
                foreach (string time in times)
                {
                    suspectingTimes.Add(TraceLogger.ParseDate(time));
                }
            }

            if (suspectingSilos.Count != suspectingTimes.Count)
            {
                throw new OrleansException(String.Format("SuspectingSilos.Length of {0} as read from SQL table is not eqaul to SuspectingTimes.Length of {1}", suspectingSilos.Count, suspectingTimes.Count));
            }

            for (int i = 0; i < suspectingSilos.Count; i++)
            {
                entry.AddSuspector(suspectingSilos[i], suspectingTimes[i]);
            }
            return(entry);
        }
示例#17
0
        private static MembershipEntry Parse(SiloInstanceTableEntry tableEntry)
        {
            var parse = new MembershipEntry
            {
                HostName = tableEntry.HostName,
                Status   = (SiloStatus)Enum.Parse(typeof(SiloStatus), tableEntry.Status)
            };

            if (!string.IsNullOrEmpty(tableEntry.ProxyPort))
            {
                parse.ProxyPort = int.Parse(tableEntry.ProxyPort);
            }

            int port = 0;

            if (!string.IsNullOrEmpty(tableEntry.Port))
            {
                int.TryParse(tableEntry.Port, out port);
            }

            int gen = 0;

            if (!string.IsNullOrEmpty(tableEntry.Generation))
            {
                int.TryParse(tableEntry.Generation, out gen);
            }

            parse.SiloAddress = SiloAddress.New(new IPEndPoint(IPAddress.Parse(tableEntry.Address), port), gen);

            parse.RoleName     = tableEntry.RoleName;
            parse.InstanceName = tableEntry.InstanceName;
            if (!string.IsNullOrEmpty(tableEntry.UpdateZone))
            {
                parse.UpdateZone = int.Parse(tableEntry.UpdateZone);
            }

            if (!string.IsNullOrEmpty(tableEntry.FaultZone))
            {
                parse.FaultZone = int.Parse(tableEntry.FaultZone);
            }

            parse.StartTime = !string.IsNullOrEmpty(tableEntry.StartTime) ?
                              TraceLogger.ParseDate(tableEntry.StartTime) : default(DateTime);

            parse.IAmAliveTime = !string.IsNullOrEmpty(tableEntry.IAmAliveTime) ?
                                 TraceLogger.ParseDate(tableEntry.IAmAliveTime) : default(DateTime);

            var suspectingSilos = new List <SiloAddress>();
            var suspectingTimes = new List <DateTime>();

            if (!string.IsNullOrEmpty(tableEntry.SuspectingSilos))
            {
                string[] silos = tableEntry.SuspectingSilos.Split('|');
                foreach (string silo in silos)
                {
                    suspectingSilos.Add(SiloAddress.FromParsableString(silo));
                }
            }

            if (!string.IsNullOrEmpty(tableEntry.SuspectingTimes))
            {
                string[] times = tableEntry.SuspectingTimes.Split('|');
                foreach (string time in times)
                {
                    suspectingTimes.Add(TraceLogger.ParseDate(time));
                }
            }

            if (suspectingSilos.Count != suspectingTimes.Count)
            {
                throw new OrleansException(String.Format("SuspectingSilos.Length of {0} as read from Azure table is not eqaul to SuspectingTimes.Length of {1}", suspectingSilos.Count, suspectingTimes.Count));
            }

            for (int i = 0; i < suspectingSilos.Count; i++)
            {
                parse.AddSuspector(suspectingSilos[i], suspectingTimes[i]);
            }

            return(parse);
        }
示例#18
0
        public void ID_IsSystem()
        {
            GrainId testGrain = Orleans.Runtime.Constants.DirectoryServiceId;

            output.WriteLine("Testing GrainID " + testGrain);
            Assert.True(testGrain.IsSystemTarget); // System grain ID is not flagged as a system ID

            GrainId sGrain = (GrainId)this.environment.SerializationManager.DeepCopy(testGrain);

            output.WriteLine("Testing GrainID " + sGrain);
            Assert.True(sGrain.IsSystemTarget); // String round-trip grain ID is not flagged as a system ID
            Assert.Equal(testGrain, sGrain);    // Should be equivalent GrainId object
            Assert.Same(testGrain, sGrain);     // Should be same / intern'ed GrainId object

            ActivationId testActivation = ActivationId.GetSystemActivation(testGrain, SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 2456), 0));

            output.WriteLine("Testing ActivationID " + testActivation);
            Assert.True(testActivation.IsSystem); // System activation ID is not flagged as a system ID
        }
示例#19
0
        public void ID_IsSystem()
        {
            GrainId testGrain = Constants.DirectoryServiceId;

            Console.WriteLine("Testing GrainID " + testGrain);
            Assert.IsTrue(testGrain.IsSystemTarget, "System grain ID is not flagged as a system ID");

            GrainId sGrain = (GrainId)SerializationManager.DeepCopy(testGrain);

            Console.WriteLine("Testing GrainID " + sGrain);
            Assert.IsTrue(sGrain.IsSystemTarget, "String round-trip grain ID is not flagged as a system ID");
            Assert.AreEqual(testGrain, sGrain, "Should be equivalent GrainId object");
            Assert.AreSame(testGrain, sGrain, "Should be same / intern'ed GrainId object");

            ActivationId testActivation = ActivationId.GetSystemActivation(testGrain, SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 2456), 0));

            Console.WriteLine("Testing ActivationID " + testActivation);
            Assert.IsTrue(testActivation.IsSystem, "System activation ID is not flagged as a system ID");
        }
示例#20
0
        /// <summary>
        /// Finds dead silos which were previously in an unknown state.
        /// </summary>
        /// <param name="allKnownSilos">The collection of all known silos, including dead silos.</param>
        /// <returns>A collection of dead silos.</returns>
        public IEnumerable <SiloAddress> DetermineDeadSilos(Dictionary <SiloAddress, SiloStatus> allKnownSilos)
        {
            if (this.unknownSilos.Count == 0)
            {
                return(Array.Empty <SiloAddress>());
            }

            // The latest generation for each silo endpoint.
            var latestGenerations = new Dictionary <IPEndPoint, int>();

            // All known silos can be removed from the unknown list as long as their status is valid.
            foreach (var known in allKnownSilos)
            {
                if (known.Value == SiloStatus.None)
                {
                    continue;
                }
                var address  = known.Key;
                var endpoint = address.Endpoint;
                if (!latestGenerations.TryGetValue(endpoint, out var knownGeneration) || knownGeneration < address.Generation)
                {
                    latestGenerations[endpoint] = address.Generation;
                }

                // Unknown silos are not removed from the collection until they have been confirmed in the collection of known silos.
                if (this.unknownSilos.TryRemove(address, out var _))
                {
                    this.log.Info($"Previously unknown silo {address} has transitioned to state {known.Value}.");
                }
            }

            var updates = new List <SiloAddress>();

            foreach (var pair in this.unknownSilos)
            {
                var unknownSilo = pair.Key;

                // If a known silo exists on the endpoint with a higher generation, the old silo must be dead.
                if (latestGenerations.TryGetValue(unknownSilo.Endpoint, out var knownGeneration) && knownGeneration > unknownSilo.Generation)
                {
                    this.log.Info($"Previously unknown silo {unknownSilo} was superseded by later generation on same endpoint {SiloAddress.New(unknownSilo.Endpoint, knownGeneration)}.");
                    updates.Add(unknownSilo);
                }

                // Silos which have been in an unknown state for more than configured maximum allowed time are automatically considered dead.
                if (this.GetDateTime() - pair.Value > this.options.UnknownSiloRemovalPeriod)
                {
                    this.log.Info($"Previously unknown silo {unknownSilo} declared dead after {this.options.UnknownSiloRemovalPeriod.TotalSeconds} seconds.");
                    updates.Add(unknownSilo);
                }
            }

            if (this.unknownSilos.Count == 0 && updates.Count == 0)
            {
                this.log.Info("All unknown silos have been identified.");
            }

            return(updates);
        }
 private static SystemTargetGrainId CreateId(ILocalSiloDetails localSiloDetails)
 {
     return(SystemTargetGrainId.Create(Constants.SystemMembershipTableType, SiloAddress.New(localSiloDetails.SiloAddress.Endpoint, 0)));
 }
        public async Task HandlesSiloAdditionAndRemoval()
        {
            var listener = new MockStatusListener();

            this.oracle.SubscribeToSiloStatusEvents(listener);
            await this.oracle.Start();

            await this.oracle.BecomeActive();

            var multiClusters = this.oracle.GetApproximateMultiClusterGateways();

            Assert.Equal(1, multiClusters.Count);
            Assert.Contains(this.siloDetails.SiloAddress, multiClusters);

            var silos = new[]
            {
                CreateSiloInfo(
                    SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 1), 1),
                    SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 2), 1),
                    "HappyNewSilo"),
                CreateSiloInfo(
                    SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 3), 2),
                    SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 4), 2),
                    "OtherNewSilo"),
            };

            // The local silo transitioned to 'Joining' and then 'Active' and two other silos became 'Active',
            // so the version must be 4
            this.resolver.Notify(silos);
            listener.WaitForVersion(4);
            Assert.Equal(3, listener.Silos.Count);
            Assert.Contains(silos[1].SiloAddress, listener.Silos.Keys);
            Assert.Equal(SiloStatus.Active, listener.Silos[silos[1].SiloAddress]);
            AssertStatus(silos[0].SiloAddress, SiloStatus.Active);
            AssertStatus(silos[1].SiloAddress, SiloStatus.Active);
            multiClusters = this.oracle.GetApproximateMultiClusterGateways();
            Assert.Equal(2, multiClusters.Count);

            // Send the same update again and verify that nothing changed.
            this.resolver.Notify(silos);
            Assert.Equal(3, listener.Silos.Count);
            Assert.Contains(silos[1].SiloAddress, listener.Silos.Keys);
            Assert.Equal(SiloStatus.Active, listener.Silos[silos[1].SiloAddress]);
            multiClusters = this.oracle.GetApproximateMultiClusterGateways();
            Assert.Equal(2, multiClusters.Count);

            // Remove a silo and verify that it's been removed.
            // The single removal will bump the version to 5.
            this.resolver.Notify(new[] { silos[1] });
            listener.WaitForVersion(5);
            Assert.Equal(3, listener.Silos.Count);
            Assert.Contains(silos[1].SiloAddress, listener.Silos.Keys);
            Assert.Equal(SiloStatus.Active, listener.Silos[silos[1].SiloAddress]);
            AssertStatus(silos[1].SiloAddress, SiloStatus.Active);
            Assert.Equal(SiloStatus.Dead, listener.Silos[silos[0].SiloAddress]);
            AssertStatus(silos[0].SiloAddress, SiloStatus.Dead);
            multiClusters = this.oracle.GetApproximateMultiClusterGateways();
            Assert.Equal(2, multiClusters.Count);

            // Remove a silo and verify that it's been removed.
            this.resolver.Notify(new FabricSiloInfo[0]);
            listener.WaitForVersion(6);

            Assert.Equal(3, listener.Silos.Count);
            Assert.Contains(silos[1].SiloAddress, listener.Silos.Keys);
            Assert.Equal(SiloStatus.Dead, listener.Silos[silos[0].SiloAddress]);
            AssertStatus(silos[0].SiloAddress, SiloStatus.Dead);
            Assert.Equal(SiloStatus.Dead, listener.Silos[silos[1].SiloAddress]);
            AssertStatus(silos[1].SiloAddress, SiloStatus.Dead);

            multiClusters = this.oracle.GetApproximateMultiClusterGateways();
            Assert.Equal(1, multiClusters.Count);
            Assert.Contains(this.siloDetails.SiloAddress, multiClusters);
        }
        private void RunTest(int numItems)
        {
            InvokeMethodRequest request = new InvokeMethodRequest(0, 0, null);
            Message             resp    = Message.CreateMessage(request, InvokeMethodOptions.None);

            resp.Id                 = new CorrelationId();
            resp.SendingSilo        = SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 200), 0);
            resp.TargetSilo         = SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 300), 0);
            resp.SendingGrain       = GrainId.NewId();
            resp.TargetGrain        = GrainId.NewId();
            resp.IsAlwaysInterleave = true;

            List <object> requestBody = new List <object>();

            for (int k = 0; k < numItems; k++)
            {
                requestBody.Add(k + ": test line");
            }

            resp.BodyObject = requestBody;

            string s = resp.ToString();

            output.WriteLine(s);

            int dummy      = 0;
            var serialized = resp.Serialize(out dummy);
            int length     = serialized.Sum <ArraySegment <byte> >(x => x.Count);

            byte[] data = new byte[length];
            int    n    = 0;

            foreach (var buffer in serialized)
            {
                Array.Copy(buffer.Array, buffer.Offset, data, n, buffer.Count);
                n += buffer.Count;
            }
            resp.ReleaseBodyAndHeaderBuffers();

            int headerLength = BitConverter.ToInt32(data, 0);
            int bodyLength   = BitConverter.ToInt32(data, 4);

            Assert.Equal <int>(length, headerLength + bodyLength + 8); //Serialized lengths are incorrect
            byte[] header = new byte[headerLength];
            Array.Copy(data, 8, header, 0, headerLength);
            byte[] body = new byte[bodyLength];
            Array.Copy(data, 8 + headerLength, body, 0, bodyLength);
            var headerList = new List <ArraySegment <byte> >();

            headerList.Add(new ArraySegment <byte>(header));
            var bodyList = new List <ArraySegment <byte> >();

            bodyList.Add(new ArraySegment <byte>(body));
            var resp1 = new Message(headerList, bodyList);

            //byte[] serialized = resp.FormatForSending();
            //Message resp1 = new Message(serialized, serialized.Length);
            Assert.Equal(resp.Category, resp1.Category);                               //Category is incorrect"
            Assert.Equal(resp.Direction, resp1.Direction);                             //Direction is incorrect
            Assert.Equal(resp.Id, resp1.Id);                                           //Correlation ID is incorrect
            Assert.Equal(resp.IsAlwaysInterleave, resp1.IsAlwaysInterleave);           //Foo Boolean is incorrect
            Assert.Equal(resp.CacheInvalidationHeader, resp1.CacheInvalidationHeader); //Bar string is incorrect
            Assert.True(resp.TargetSilo.Equals(resp1.TargetSilo));
            Assert.True(resp.TargetGrain.Equals(resp1.TargetGrain));
            Assert.True(resp.SendingGrain.Equals(resp1.SendingGrain));
            Assert.True(resp.SendingSilo.Equals(resp1.SendingSilo)); //SendingSilo is incorrect
            List <object> responseList = Assert.IsAssignableFrom <List <object> >(resp1.BodyObject);

            Assert.Equal <int>(numItems, responseList.Count); //Body list has wrong number of entries
            for (int k = 0; k < numItems; k++)
            {
                Assert.IsAssignableFrom <string>(responseList[k]);                          //Body list item " + k + " has wrong type
                Assert.Equal <string>((string)(requestBody[k]), (string)(responseList[k])); //Body list item " + k + " is incorrect
            }
        }
        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);
        }
示例#25
0
        // This function is called asynchronously from gateway refresh timer.
        private async Task UpdateLiveGatewaysSnapshot(IEnumerable <SiloAddress> refreshedGateways, TimeSpan maxStaleness)
        {
            List <SiloAddress> connectionsToKeepAlive;

            // This is a short lock, protecting the access to knownDead, knownMasked and cachedLiveGateways.
            lock (lockable)
            {
                // now take whatever listProvider gave us and exclude those we think are dead.
                var live = new List <SiloAddress>();
                var now  = DateTime.UtcNow;

                this.knownGateways = refreshedGateways as List <SiloAddress> ?? refreshedGateways.ToList();
                foreach (SiloAddress trial in knownGateways)
                {
                    var address = trial.Generation == 0 ? trial : SiloAddress.New(trial.Endpoint, 0);

                    // We consider a node to be dead if we recorded it is dead due to socket error
                    // and it was recorded (diedAt) not too long ago (less than maxStaleness ago).
                    // The latter is to cover the case when the Gateway provider returns an outdated list that does not yet reflect the actually recently died Gateway.
                    // If it has passed more than maxStaleness - we assume maxStaleness is the upper bound on Gateway provider freshness.
                    var isDead = false;
                    if (knownDead.TryGetValue(address, out var diedAt))
                    {
                        if (now.Subtract(diedAt) < maxStaleness)
                        {
                            isDead = true;
                        }
                        else
                        {
                            // Remove stale entries.
                            knownDead.Remove(address);
                        }
                    }
                    if (knownMasked.TryGetValue(address, out var maskedAt))
                    {
                        if (now.Subtract(maskedAt) < maxStaleness)
                        {
                            isDead = true;
                        }
                        else
                        {
                            // Remove stale entries.
                            knownMasked.Remove(address);
                        }
                    }

                    if (!isDead)
                    {
                        live.Add(address);
                    }
                }

                if (live.Count == 0)
                {
                    logger.LogWarning(
                        (int)ErrorCode.GatewayManager_AllGatewaysDead,
                        "All gateways have previously been marked as dead. Clearing the list of dead gateways to expedite reconnection.");
                    live.AddRange(knownGateways);
                    knownDead.Clear();
                }

                // swap cachedLiveGateways pointer in one atomic operation
                cachedLiveGateways    = live;
                cachedLiveGatewaysSet = new HashSet <SiloAddress>(live);

                DateTime prevRefresh = lastRefreshTime;
                lastRefreshTime = now;
                if (logger.IsEnabled(LogLevel.Debug))
                {
                    logger.LogDebug(
                        (int)ErrorCode.GatewayManager_FoundKnownGateways,
                        "Refreshed the live gateway list. Found {KnownGatewayCount} gateways from gateway list provider: {KnownGateways}. Picked only known live out of them. Now has {LiveGatewayCount} live gateways: {LiveGateways}. Previous refresh time was = {PreviousRefreshTime}",
                        knownGateways.Count,
                        Utils.EnumerableToString(knownGateways),
                        cachedLiveGateways.Count,
                        Utils.EnumerableToString(cachedLiveGateways),
                        prevRefresh);
                }

                // Close connections to known dead connections, but keep the "masked" ones.
                // Client will not send any new request to the "masked" connections, but might still
                // receive responses
                connectionsToKeepAlive = new List <SiloAddress>(live);
                connectionsToKeepAlive.AddRange(knownMasked.Select(e => e.Key));
            }

            await this.CloseEvictedGatewayConnections(connectionsToKeepAlive);
        }
示例#26
0
        public async Task HandlesSiloAdditionAndRemoval()
        {
            var listener = new MockStatusListener();

            this.oracle.SubscribeToSiloStatusEvents(listener);
            await this.oracle.Start();

            await this.oracle.BecomeActive();

            var multiClusters = this.oracle.GetApproximateMultiClusterGateways();

            Assert.Equal(1, multiClusters.Count);
            Assert.Contains(this.siloDetails.SiloAddress, multiClusters);

            var silos = new[]
            {
                CreateSiloInfo(
                    SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 1), 1),
                    SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 2), 1),
                    "HappyNewSilo"),
                CreateSiloInfo(
                    SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 3), 2),
                    SiloAddress.New(new IPEndPoint(IPAddress.Loopback, 4), 2),
                    "OtherNewSilo"),
            };

            listener.VersionReached.Reset();
            listener.WaitForVersion = 4;
            this.resolver.Notify(silos);
            listener.VersionReached.WaitOne(TimeSpan.FromMinutes(1));
            Assert.Equal(3, listener.Silos.Count);
            Assert.Contains(silos[1].SiloAddress, listener.Silos.Keys);
            Assert.Equal(SiloStatus.Active, listener.Silos[silos[1].SiloAddress]);
            AssertStatus(silos[0].SiloAddress, SiloStatus.Active);
            AssertStatus(silos[1].SiloAddress, SiloStatus.Active);
            multiClusters = this.oracle.GetApproximateMultiClusterGateways();
            Assert.Equal(2, multiClusters.Count);

            // Send the same update again and verify that nothing changed.
            this.resolver.Notify(silos);
            Assert.Equal(3, listener.Silos.Count);
            Assert.Contains(silos[1].SiloAddress, listener.Silos.Keys);
            Assert.Equal(SiloStatus.Active, listener.Silos[silos[1].SiloAddress]);
            multiClusters = this.oracle.GetApproximateMultiClusterGateways();
            Assert.Equal(2, multiClusters.Count);

            // Remove a silo and verify that it's been removed.
            listener.WaitForVersion = 5;
            this.resolver.Notify(new[] { silos[1] });
            listener.VersionReached.WaitOne(TimeSpan.FromMinutes(1));
            Assert.Equal(3, listener.Silos.Count);
            Assert.Contains(silos[1].SiloAddress, listener.Silos.Keys);
            Assert.Equal(SiloStatus.Active, listener.Silos[silos[1].SiloAddress]);
            AssertStatus(silos[1].SiloAddress, SiloStatus.Active);
            Assert.Equal(SiloStatus.Dead, listener.Silos[silos[0].SiloAddress]);
            AssertStatus(silos[0].SiloAddress, SiloStatus.Dead);
            multiClusters = this.oracle.GetApproximateMultiClusterGateways();
            Assert.Equal(2, multiClusters.Count);

            // Remove a silo and verify that it's been removed.
            this.resolver.Notify(new FabricSiloInfo[0]);
            listener.VersionReached.WaitOne(TimeSpan.FromMinutes(1));

            Assert.Equal(3, listener.Silos.Count);
            Assert.Contains(silos[1].SiloAddress, listener.Silos.Keys);
            Assert.Equal(SiloStatus.Dead, listener.Silos[silos[0].SiloAddress]);
            AssertStatus(silos[0].SiloAddress, SiloStatus.Dead);
            Assert.Equal(SiloStatus.Dead, listener.Silos[silos[1].SiloAddress]);
            AssertStatus(silos[1].SiloAddress, SiloStatus.Dead);

            multiClusters = this.oracle.GetApproximateMultiClusterGateways();
            Assert.Equal(1, multiClusters.Count);
            Assert.Contains(this.siloDetails.SiloAddress, multiClusters);
        }