Example #1
0
        protected void AddServer(SiloAddress silo)
        {
            lock (this.writeLock)
            {
                var existing = this.directoryMembership;
                if (existing.MembershipCache.Contains(silo))
                {
                    // we have already cached this silo
                    return;
                }

                // insert new silo in the sorted order
                long hash = silo.GetConsistentHashCode();

                // Find the last silo with hash smaller than the new silo, and insert the latter after (this is why we have +1 here) the former.
                // Notice that FindLastIndex might return -1 if this should be the first silo in the list, but then
                // 'index' will get 0, as needed.
                int index = existing.MembershipRingList.FindLastIndex(siloAddr => siloAddr.GetConsistentHashCode() < hash) + 1;

                this.directoryMembership = new DirectoryMembership(
                    existing.MembershipRingList.Insert(index, silo),
                    existing.MembershipCache.Add(silo));

                HandoffManager.ProcessSiloAddEvent(silo);

                AdjustLocalDirectory(silo, dead: false);
                AdjustLocalCache(silo, dead: false);

                if (log.IsEnabled(LogLevel.Debug))
                {
                    log.Debug("Silo {0} added silo {1}", MyAddress, silo);
                }
            }
        }
Example #2
0
        protected void AddServer(SiloAddress silo)
        {
            lock (membershipCache)
            {
                if (membershipCache.Contains(silo))
                {
                    // we have already cached this silo
                    return;
                }

                membershipCache.Add(silo);

                // insert new silo in the sorted order
                long hash = silo.GetConsistentHashCode();

                // Find the last silo with hash smaller than the new silo, and insert the latter after (this is why we have +1 here) the former.
                // Notice that FindLastIndex might return -1 if this should be the first silo in the list, but then
                // 'index' will get 0, as needed.
                int index = membershipRingList.FindLastIndex(siloAddr => siloAddr.GetConsistentHashCode() < hash) + 1;
                membershipRingList.Insert(index, silo);

                HandoffManager.ProcessSiloAddEvent(silo);

                if (log.IsVerbose)
                {
                    log.Verbose("Silo {0} added silo {1}", MyAddress, silo);
                }
            }
        }
        private static int CompareSiloAddressesForRing(SiloAddress left, SiloAddress right)
        {
            var leftHash  = left.GetConsistentHashCode();
            var rightHash = right.GetConsistentHashCode();

            return(leftHash.CompareTo(rightHash));
        }
        internal SiloAddress CalculateGrainDirectoryPartition(GrainId grainId)
        {
            // give a special treatment for special grains
            if (grainId.IsSystemTarget)
            {
                if (log.IsEnabled(LogLevel.Trace))
                {
                    log.LogTrace(
                        "Silo {LocalSilo} looked for a system target {SystemTarget}, returned {ResultSilo}",
                        this.siloAddress,
                        grainId,
                        this.siloAddress);
                }

                // every silo owns its system targets
                return(this.siloAddress);
            }

            if (this.ring.Count == 0)
            {
                return(null);
            }

            SiloAddress siloAddress = null;
            int         hash        = unchecked ((int)grainId.GetUniformHashCode());

            // need to implement a binary search, but for now simply traverse the list of silos sorted by their hashes
            for (var index = this.ring.Count - 1; index >= 0; --index)
            {
                var item = this.ring[index];
                if (item.GetConsistentHashCode() <= hash)
                {
                    siloAddress = item;
                    break;
                }
            }

            if (siloAddress == null)
            {
                // If not found in the traversal, last silo will do (we are on a ring).
                // We checked above to make sure that the list isn't empty, so this should always be safe.
                siloAddress = this.ring[this.ring.Count - 1];
            }

            if (log.IsEnabled(LogLevel.Trace))
            {
                log.LogTrace(
                    "Silo {LocalSilo} calculated directory partition owner silo {Silo} for grain {Grain}: {GrainHash} --> {SiloHash}",
                    this.siloAddress,
                    siloAddress,
                    grainId,
                    hash,
                    siloAddress?.GetConsistentHashCode());
            }

            return(siloAddress);
        }
Example #5
0
        public ConsistentRingProvider(SiloAddress siloAddr)
        {
            log = TraceLogger.GetLogger(typeof(ConsistentRingProvider).Name);
            membershipRingList = new List <SiloAddress>();
            MyAddress          = siloAddr;
            myKey = MyAddress.GetConsistentHashCode();

            // add myself to the list of members
            AddServer(MyAddress);
            MyRange         = RangeFactory.CreateFullRange(); // i am responsible for the whole range
            statusListeners = new List <IRingRangeListener>();

            Start();
        }
        public ConsistentRingProvider(SiloAddress siloAddr)
        {
            log = LogManager.GetLogger(typeof(ConsistentRingProvider).Name);
            membershipRingList = new List<SiloAddress>();
            MyAddress = siloAddr;
            myKey = MyAddress.GetConsistentHashCode();

            // add myself to the list of members
            AddServer(MyAddress);
            MyRange = RangeFactory.CreateFullRange(); // i am responsible for the whole range
            statusListeners = new List<IRingRangeListener>();
           
            Start();
        }
Example #7
0
        internal void AddServer(SiloAddress silo)
        {
            lock (membershipRingList)
            {
                if (membershipRingList.Contains(silo))
                {
                    return;                                    // we already have this silo
                }
                int myOldIndex = membershipRingList.FindIndex(elem => elem.Equals(MyAddress));

                if (!(membershipRingList.Count == 0 || myOldIndex != -1))
                {
                    throw new OrleansException(string.Format("{0}: Couldn't find my position in the ring {1}.", MyAddress, Utils.EnumerableToString(membershipRingList)));
                }


                // insert new silo in the sorted order
                int hash = silo.GetConsistentHashCode();

                // Find the last silo with hash smaller than the new silo, and insert the latter after (this is why we have +1 here) the former.
                // Notice that FindLastIndex might return -1 if this should be the first silo in the list, but then
                // 'index' will get 0, as needed.
                int index = membershipRingList.FindLastIndex(siloAddr => siloAddr.GetConsistentHashCode() < hash) + 1;
                membershipRingList.Insert(index, silo);

                // relating to triggering handler ... new node took over some of my responsibility
                if (index == myOldIndex ||                                      // new node was inserted in my place
                    (myOldIndex == 0 && index == membershipRingList.Count - 1)) // I am the first node, and the new server is the last node
                {
                    IRingRange oldRange = MyRange;
                    try
                    {
                        MyRange = RangeFactory.CreateRange(unchecked ((uint)hash), unchecked ((uint)myKey));
                    }
                    catch (OverflowException exc)
                    {
                        log.Error(ErrorCode.ConsistentRingProviderBase + 5,
                                  String.Format("OverflowException: hash as int= x{0, 8:X8}, hash as uint= x{1, 8:X8}, myKey as int x{2, 8:X8}, myKey as uint x{3, 8:X8}.",
                                                hash, (uint)hash, myKey, (uint)myKey), exc);
                    }
                    NotifyLocalRangeSubscribers(oldRange, MyRange, false);
                }

                log.Info("Added Server {0}. Current view: {1}", silo.ToStringWithHashCode(), this.ToString());
            }
        }
Example #8
0
        private static long CalcRingDistance(SiloAddress silo1, SiloAddress silo2)
        {
            const long ringSize = int.MaxValue * 2L;
            long       hash1    = silo1.GetConsistentHashCode();
            long       hash2    = silo2.GetConsistentHashCode();

            if (hash2 > hash1)
            {
                return(hash2 - hash1);
            }
            if (hash2 < hash1)
            {
                return(ringSize - (hash1 - hash2));
            }

            return(0);
        }
Example #9
0
        internal void RemoveServer(SiloAddress silo)
        {
            lock (membershipRingList)
            {
                int indexOfFailedSilo = membershipRingList.FindIndex(elem => elem.Equals(silo));
                if (indexOfFailedSilo < 0)
                {
                    return;                        // we have already removed this silo
                }
                membershipRingList.Remove(silo);

                // related to triggering handler
                int myNewIndex = membershipRingList.FindIndex(elem => elem.Equals(MyAddress));

                if (myNewIndex == -1)
                {
                    throw new OrleansException(string.Format("{0}: Couldn't find my position in the ring {1}.", MyAddress, this.ToString()));
                }

                bool wasMyPred = ((myNewIndex == indexOfFailedSilo) || (myNewIndex == 0 && indexOfFailedSilo == membershipRingList.Count)); // no need for '- 1'
                if (wasMyPred)                                                                                                              // failed node was our predecessor
                {
                    if (log.IsVerbose)
                    {
                        log.Verbose("Failed server was my pred? {0}, updated view {1}", wasMyPred, this.ToString());
                    }

                    IRingRange oldRange = MyRange;
                    if (membershipRingList.Count == 1) // i'm the only one left
                    {
                        MyRange = RangeFactory.CreateFullRange();
                        NotifyLocalRangeSubscribers(oldRange, MyRange, true);
                    }
                    else
                    {
                        int myNewPredIndex     = myNewIndex == 0 ? membershipRingList.Count - 1 : myNewIndex - 1;
                        int myPredecessorsHash = membershipRingList[myNewPredIndex].GetConsistentHashCode();

                        MyRange = RangeFactory.CreateRange(unchecked ((uint)myPredecessorsHash), unchecked ((uint)myKey));
                        NotifyLocalRangeSubscribers(oldRange, MyRange, true);
                    }
                }
                log.Info("Removed Server {0} hash {1}. Current view {2}", silo, silo.GetConsistentHashCode(), this.ToString());
            }
        }
Example #10
0
 /// <summary>
 /// Compare SiloAddress-es based on their consistent hash code
 /// </summary>
 /// <param name="x"></param>
 /// <param name="y"></param>
 /// <returns></returns>
 private static int CompareSiloAddressesByHash(SiloAddress x, SiloAddress y)
 {
     if (x == null)
     {
         return(y == null ? 0 : -1);
     }
     else
     {
         if (y == null)
         {
             return(1);
         }
         else
         {
             // real comparison is here
             return(x.GetConsistentHashCode().CompareTo(y.GetConsistentHashCode()));
         }
     }
 }
Example #11
0
        public override string ToString()
        {
            lock (membershipRingList)
            {
                if (membershipRingList.Count == 1)
                {
                    return(Utils.EnumerableToString(membershipRingList, silo => String.Format("{0} -> {1}", silo.ToStringWithHashCode(), RangeFactory.CreateFullRange())));
                }

                var sb = new StringBuilder("[");
                for (int i = 0; i < membershipRingList.Count; i++)
                {
                    SiloAddress curr  = membershipRingList[i];
                    SiloAddress next  = membershipRingList[(i + 1) % membershipRingList.Count];
                    IRingRange  range = RangeFactory.CreateRange(unchecked ((uint)curr.GetConsistentHashCode()), unchecked ((uint)next.GetConsistentHashCode()));
                    sb.Append(String.Format("{0} -> {1},  ", curr.ToStringWithHashCode(), range));
                }
                sb.Append("]");
                return(sb.ToString());
            }
        }
Example #12
0
 private bool IsSiloNextInTheRing(SiloAddress siloAddr, uint hash, bool excludeMySelf)
 {
     return siloAddr.GetConsistentHashCode() >= hash && (!siloAddr.Equals(MyAddress) || !excludeMySelf);
 }
Example #13
0
        /// <summary>
        /// Finds the silo that owns the given hash value.
        /// This routine will always return a non-null silo address unless the excludeThisSiloIfStopping parameter is true,
        /// this is the only silo known, and this silo is stopping.
        /// </summary>
        /// <param name="hash"></param>
        /// <param name="excludeThisSiloIfStopping"></param>
        /// <returns></returns>
        public SiloAddress CalculateTargetSilo(uint hash, bool excludeThisSiloIfStopping = true)
        {
            SiloAddress siloAddress = null;

            lock (membershipRingList)
            {
                // excludeMySelf from being a TargetSilo if we're not running and the excludeThisSIloIfStopping flag is true. see the comment in the Stop method.
                bool excludeMySelf = excludeThisSiloIfStopping && !isRunning;

                if (membershipRingList.Count == 0)
                {
                    // If the membership ring is empty, then we're the owner by default unless we're stopping.
                    return(excludeMySelf ? null : MyAddress);
                }

                // use clockwise ... current code in membershipOracle.CalculateTargetSilo() does counter-clockwise ...
                // if you want to stick to counter-clockwise, change the responsibility definition in 'In()' method & responsibility defs in OrleansReminderMemory
                // need to implement a binary search, but for now simply traverse the list of silos sorted by their hashes

                for (int index = 0; index < membershipRingList.Count; ++index)
                {
                    var siloAddr = membershipRingList[index];
                    if (IsSiloNextInTheRing(siloAddr, hash, excludeMySelf))
                    {
                        siloAddress = siloAddr;
                        break;
                    }
                }

                if (siloAddress == null)
                {
                    // if not found in traversal, then first silo should be returned (we are on a ring)
                    // if you go back to their counter-clockwise policy, then change the 'In()' method in OrleansReminderMemory
                    siloAddress = membershipRingList[0]; // vs [membershipRingList.Count - 1]; for counter-clockwise policy
                    // Make sure it's not us...
                    if (siloAddress.Equals(MyAddress) && excludeMySelf)
                    {
                        // vs [membershipRingList.Count - 2]; for counter-clockwise policy
                        siloAddress = membershipRingList.Count > 1 ? membershipRingList[1] : null;
                    }
                }
            }

            if (log.IsVerbose2)
            {
                log.Verbose2("Silo {0} calculated ring partition owner silo {1} for key {2}: {3} --> {4}", MyAddress, siloAddress, hash, hash, siloAddress.GetConsistentHashCode());
            }
            return(siloAddress);
        }
        internal void AddServer(SiloAddress silo)
        {
            lock (membershipRingList)
            {
                if (membershipRingList.Contains(silo)) return; // we already have this silo

                int myOldIndex = membershipRingList.FindIndex(elem => elem.Equals(MyAddress));

                if (!(membershipRingList.Count == 0 || myOldIndex != -1))
                    throw new OrleansException(string.Format("{0}: Couldn't find my position in the ring {1}.", MyAddress, Utils.EnumerableToString(membershipRingList)));
                

                // insert new silo in the sorted order
                int hash = silo.GetConsistentHashCode();

                // Find the last silo with hash smaller than the new silo, and insert the latter after (this is why we have +1 here) the former.
                // Notice that FindLastIndex might return -1 if this should be the first silo in the list, but then
                // 'index' will get 0, as needed.
                int index = membershipRingList.FindLastIndex(siloAddr => siloAddr.GetConsistentHashCode() < hash) + 1;
                membershipRingList.Insert(index, silo);

                // relating to triggering handler ... new node took over some of my responsibility
                if (index == myOldIndex || // new node was inserted in my place
                    (myOldIndex == 0 && index == membershipRingList.Count - 1)) // I am the first node, and the new server is the last node
                {
                    IRingRange oldRange = MyRange;
                    try
                    {
                        MyRange = RangeFactory.CreateRange(unchecked((uint)hash), unchecked((uint)myKey));
                    }
                    catch (OverflowException exc)
                    {
                        log.Error(ErrorCode.ConsistentRingProviderBase + 5,
                            String.Format("OverflowException: hash as int= x{0, 8:X8}, hash as uint= x{1, 8:X8}, myKey as int x{2, 8:X8}, myKey as uint x{3, 8:X8}.",
                            hash, (uint)hash, myKey, (uint)myKey), exc);
                    }
                    NotifyLocalRangeSubscribers(oldRange, MyRange, false);
                }

                log.Info("Added Server {0}. Current view: {1}", silo.ToStringWithHashCode(), this.ToString());
            }
        }
Example #15
0
        public async Task <List <ActivationAddress> > FullLookup(GrainId grain)
        {
            fullLookups.Increment();

            SiloAddress silo = CalculateTargetSilo(grain, false);

            // No need to check that silo != null since we're passing excludeThisSiloIfStopping = false

            if (log.IsVerbose)
            {
                log.Verbose("Silo {0} fully lookups for {1}-->{2} ({3}-->{4})", MyAddress, grain, silo, grain.GetUniformHashCode(), silo.GetConsistentHashCode());
            }

            // We assyme that getting here means the grain was not found locally (i.e., in TryFullLookup()).
            // We still check if we own the grain locally to avoid races between the time TryFullLookup() and FullLookup() were called.
            if (silo.Equals(MyAddress))
            {
                LocalDirectoryLookups.Increment();
                var localResult = DirectoryPartition.LookUpGrain(grain);
                if (localResult == null)
                {
                    // it can happen that we cannot find the grain in our partition if there were
                    // some recent changes in the membership
                    if (log.IsVerbose2)
                    {
                        log.Verbose2("FullLookup mine {0}=none", grain);
                    }
                    return(new List <ActivationAddress>());
                }
                var a = localResult.Item1.Select(t => ActivationAddress.GetAddress(t.Item1, grain, t.Item2)).Where(addr => IsValidSilo(addr.Silo)).ToList();
                if (log.IsVerbose2)
                {
                    log.Verbose2("FullLookup mine {0}={1}", grain, a.ToStrings());
                }
                LocalDirectorySuccesses.Increment();
                return(a);
            }

            // Just a optimization. Why sending a message to someone we know is not valid.
            if (!IsValidSilo(silo))
            {
                throw new OrleansException(String.Format("Current directory at {0} is not stable to perform the lookup for grain {1} (it maps to {2}, which is not a valid silo). Retry later.", MyAddress, grain, silo));
            }

            RemoteLookupsSent.Increment();
            Tuple <List <Tuple <SiloAddress, ActivationId> >, int> result = await GetDirectoryReference(silo).LookUp(grain, NUM_RETRIES);

            // update the cache
            List <Tuple <SiloAddress, ActivationId> > entries = result.Item1.Where(t => IsValidSilo(t.Item1)).ToList();
            List <ActivationAddress> addresses = entries.Select(t => ActivationAddress.GetAddress(t.Item1, grain, t.Item2)).ToList();

            if (log.IsVerbose2)
            {
                log.Verbose2("FullLookup remote {0}={1}", grain, addresses.ToStrings());
            }

            if (entries.Count > 0)
            {
                DirectoryCache.AddOrUpdate(grain, entries, result.Item2);
            }

            return(addresses);
        }
Example #16
0
        public Task DeleteGrain(GrainId grain)
        {
            SiloAddress silo = CalculateTargetSilo(grain);

            if (silo == null)
            {
                // We don't know about any other silos, and we're stopping, so throw
                throw new InvalidOperationException("Grain directory is stopping");
            }

            if (log.IsVerbose)
            {
                log.Verbose("Silo {0} tries to lookup for {1}-->{2} ({3}-->{4})", MyAddress, grain, silo, grain.GetUniformHashCode(), silo.GetConsistentHashCode());
            }

            if (silo.Equals(MyAddress))
            {
                // remove from our partition
                DirectoryPartition.RemoveGrain(grain);
                return(TaskDone.Done);
            }

            // remove from the cache
            DirectoryCache.Remove(grain);

            // send request to the owner
            return(GetDirectoryReference(silo).DeleteGrain(grain, NUM_RETRIES));
        }
Example #17
0
        private Task UnregisterAsyncImpl(ActivationAddress addr, bool force)
        {
            unregistrationsIssued.Increment();
            SiloAddress owner = CalculateTargetSilo(addr.Grain);

            if (owner == null)
            {
                // We don't know about any other silos, and we're stopping, so throw
                throw new InvalidOperationException("Grain directory is stopping");
            }

            if (log.IsVerbose)
            {
                log.Verbose("Silo {0} is going to unregister grain {1}-->{2} ({3}-->{4})", MyAddress, addr.Grain, owner, addr.Grain.GetUniformHashCode(), owner.GetConsistentHashCode());
            }

            InvalidateCacheEntry(addr);
            if (owner.Equals(MyAddress))
            {
                UnregistrationsLocal.Increment();
                // if I am the owner, remove the old activation locally
                DirectoryPartition.RemoveActivation(addr.Grain, addr.Activation, force);
                return(TaskDone.Done);
            }

            UnregistrationsRemoteSent.Increment();
            // otherwise, notify the owner
            return(GetDirectoryReference(owner).Unregister(addr, force, NUM_RETRIES));
        }
Example #18
0
        public bool LocalLookup(GrainId grain, out List <ActivationAddress> addresses)
        {
            localLookups.Increment();

            SiloAddress silo = CalculateTargetSilo(grain, false);

            // No need to check that silo != null since we're passing excludeThisSiloIfStopping = false

            if (log.IsVerbose)
            {
                log.Verbose("Silo {0} tries to lookup for {1}-->{2} ({3}-->{4})", MyAddress, grain, silo, grain.GetUniformHashCode(), silo.GetConsistentHashCode());
            }

            // check if we own the grain
            if (silo.Equals(MyAddress))
            {
                LocalDirectoryLookups.Increment();
                addresses = GetLocalDirectoryData(grain);
                if (addresses == null)
                {
                    // it can happen that we cannot find the grain in our partition if there were
                    // some recent changes in the membership
                    if (log.IsVerbose2)
                    {
                        log.Verbose2("LocalLookup mine {0}=null", grain);
                    }
                    return(false);
                }
                if (log.IsVerbose2)
                {
                    log.Verbose2("LocalLookup mine {0}={1}", grain, addresses.ToStrings());
                }
                LocalDirectorySuccesses.Increment();
                localSuccesses.Increment();
                return(true);
            }

            // handle cache
            cacheLookups.Increment();
            addresses = GetLocalCacheData(grain);
            if (addresses == null)
            {
                if (log.IsVerbose2)
                {
                    log.Verbose2("TryFullLookup else {0}=null", grain);
                }
                return(false);
            }
            if (log.IsVerbose2)
            {
                log.Verbose2("LocalLookup cache {0}={1}", grain, addresses.ToStrings());
            }
            cacheSuccesses.Increment();
            localSuccesses.Increment();
            return(true);
        }
        internal void RemoveServer(SiloAddress silo)
        {
            lock (membershipRingList)
            {
                int indexOfFailedSilo = membershipRingList.FindIndex(elem => elem.Equals(silo));
                if (indexOfFailedSilo < 0) return; // we have already removed this silo
                
                membershipRingList.Remove(silo);

                // related to triggering handler
                int myNewIndex = membershipRingList.FindIndex(elem => elem.Equals(MyAddress));

                if (myNewIndex == -1)
                    throw new OrleansException(string.Format("{0}: Couldn't find my position in the ring {1}.", MyAddress, this.ToString()));
                
                bool wasMyPred = ((myNewIndex == indexOfFailedSilo) || (myNewIndex == 0 && indexOfFailedSilo == membershipRingList.Count)); // no need for '- 1'
                if (wasMyPred) // failed node was our predecessor
                {
                    if (log.IsVerbose) log.Verbose("Failed server was my pred? {0}, updated view {1}", wasMyPred, this.ToString());

                    IRingRange oldRange = MyRange;
                    if (membershipRingList.Count == 1) // i'm the only one left
                    {
                        MyRange = RangeFactory.CreateFullRange();
                        NotifyLocalRangeSubscribers(oldRange, MyRange, true);
                    }
                    else
                    {
                        int myNewPredIndex = myNewIndex == 0 ? membershipRingList.Count - 1 : myNewIndex - 1;
                        int myPredecessorsHash = membershipRingList[myNewPredIndex].GetConsistentHashCode();

                        MyRange = RangeFactory.CreateRange(unchecked((uint)myPredecessorsHash), unchecked((uint)myKey));
                        NotifyLocalRangeSubscribers(oldRange, MyRange, true);
                    }
                }
                log.Info("Removed Server {0} hash {1}. Current view {2}", silo, silo.GetConsistentHashCode(), this.ToString());
            }
        }
Example #20
0
 private bool IsSiloNextInTheRing(SiloAddress siloAddr, uint hash, bool excludeMySelf)
 {
     return(siloAddr.GetConsistentHashCode() >= hash && (!siloAddr.Equals(MyAddress) || !excludeMySelf));
 }
Example #21
0
 /// <summary>
 /// Compare SiloAddress-es based on their consistent hash code
 /// </summary>
 /// <param name="x"></param>
 /// <param name="y"></param>
 /// <returns></returns>
 private static int CompareSiloAddressesByHash(SiloAddress x, SiloAddress y)
 {
     if (x == null)
     {
         return y == null ? 0 : -1;
     }
     else
     {
         if (y == null)
         {
             return 1;
         }
         else
         {
             // real comparison is here
             return x.GetConsistentHashCode().CompareTo(y.GetConsistentHashCode());
         }
     }
 }
Example #22
0
        /// <summary>
        /// Finds the silo that owns the directory information for the given grain ID.
        /// This method will only be null when I'm the only silo in the cluster and I'm shutting down
        /// </summary>
        /// <param name="grainId"></param>
        /// <returns></returns>
        public SiloAddress CalculateGrainDirectoryPartition(GrainId grainId)
        {
            // give a special treatment for special grains
            if (grainId.IsSystemTarget())
            {
                if (Constants.SystemMembershipTableType.Equals(grainId))
                {
                    if (Seed == null)
                    {
                        var errorMsg =
                            $"Development clustering cannot run without a primary silo. " +
                            $"Please configure {nameof(DevelopmentClusterMembershipOptions)}.{nameof(DevelopmentClusterMembershipOptions.PrimarySiloEndpoint)} " +
                            "or provide a primary silo address to the UseDevelopmentClustering extension. " +
                            "Alternatively, you may want to use reliable membership, such as Azure Table.";
                        throw new ArgumentException(errorMsg, "grainId = " + grainId);
                    }
                }

                if (log.IsEnabled(LogLevel.Trace))
                {
                    log.Trace("Silo {0} looked for a system target {1}, returned {2}", MyAddress, grainId, MyAddress);
                }
                // every silo owns its system targets
                return(MyAddress);
            }

            SiloAddress siloAddress = null;
            int         hash        = unchecked ((int)grainId.GetUniformHashCode());

            // excludeMySelf from being a TargetSilo if we're not running and the excludeThisSIloIfStopping flag is true. see the comment in the Stop method.
            // excludeThisSIloIfStopping flag was removed because we believe that flag complicates things unnecessarily. We can add it back if it turns out that flag
            // is doing something valuable.
            bool excludeMySelf = !Running;

            var existing = this.directoryMembership;

            if (existing.MembershipRingList.Count == 0)
            {
                // If the membership ring is empty, then we're the owner by default unless we're stopping.
                return(!Running ? null : MyAddress);
            }

            // need to implement a binary search, but for now simply traverse the list of silos sorted by their hashes
            for (var index = existing.MembershipRingList.Count - 1; index >= 0; --index)
            {
                var item = existing.MembershipRingList[index];
                if (IsSiloNextInTheRing(item, hash, excludeMySelf))
                {
                    siloAddress = item;
                    break;
                }
            }

            if (siloAddress == null)
            {
                // If not found in the traversal, last silo will do (we are on a ring).
                // We checked above to make sure that the list isn't empty, so this should always be safe.
                siloAddress = existing.MembershipRingList[existing.MembershipRingList.Count - 1];
                // Make sure it's not us...
                if (siloAddress.Equals(MyAddress) && excludeMySelf)
                {
                    siloAddress = existing.MembershipRingList.Count > 1 ? existing.MembershipRingList[existing.MembershipRingList.Count - 2] : null;
                }
            }

            if (log.IsEnabled(LogLevel.Trace))
            {
                log.Trace("Silo {0} calculated directory partition owner silo {1} for grain {2}: {3} --> {4}", MyAddress, siloAddress, grainId, hash, siloAddress?.GetConsistentHashCode());
            }
            return(siloAddress);
        }
Example #23
0
        protected void AddServer(SiloAddress silo)
        {
            lock (membershipCache)
            {
                if (membershipCache.Contains(silo))
                {
                    // we have already cached this silo
                    return;
                }

                membershipCache.Add(silo);

                // insert new silo in the sorted order
                long hash = silo.GetConsistentHashCode();

                // Find the last silo with hash smaller than the new silo, and insert the latter after (this is why we have +1 here) the former.
                // Notice that FindLastIndex might return -1 if this should be the first silo in the list, but then
                // 'index' will get 0, as needed.
                int index = membershipRingList.FindLastIndex(siloAddr => siloAddr.GetConsistentHashCode() < hash) + 1;
                membershipRingList.Insert(index, silo);

                HandoffManager.ProcessSiloAddEvent(silo);

                if (log.IsVerbose) log.Verbose("Silo {0} added silo {1}", MyAddress, silo);
            }
        }
Example #24
0
        private static long CalcRingDistance(SiloAddress silo1, SiloAddress silo2)
        {
            const long ringSize = int.MaxValue * 2L;
            long hash1 = silo1.GetConsistentHashCode();
            long hash2 = silo2.GetConsistentHashCode();

            if (hash2 > hash1) return hash2 - hash1;
            if (hash2 < hash1) return ringSize - (hash1 - hash2);

            return 0;
        }
Example #25
0
        public bool LocalLookup(GrainId grain, out AddressAndTag result)
        {
            localLookups.Increment();

            SiloAddress silo = CalculateGrainDirectoryPartition(grain);


            if (log.IsEnabled(LogLevel.Debug))
            {
                log.Debug("Silo {0} tries to lookup for {1}-->{2} ({3}-->{4})", MyAddress, grain, silo, grain.GetUniformHashCode(), silo?.GetConsistentHashCode());
            }

            //this will only happen if I'm the only silo in the cluster and I'm shutting down
            if (silo == null)
            {
                if (log.IsEnabled(LogLevel.Trace))
                {
                    log.Trace("LocalLookup mine {0}=null", grain);
                }
                result = new AddressAndTag();
                return(false);
            }

            // handle cache
            cacheLookups.Increment();
            var address = GetLocalCacheData(grain);

            if (address != default)
            {
                result = new AddressAndTag
                {
                    Address = address,
                };

                if (log.IsEnabled(LogLevel.Trace))
                {
                    log.Trace("LocalLookup cache {0}={1}", grain, result.Address);
                }
                cacheSuccesses.Increment();
                localSuccesses.Increment();
                return(true);
            }

            // check if we own the grain
            if (silo.Equals(MyAddress))
            {
                LocalDirectoryLookups.Increment();
                result = GetLocalDirectoryData(grain);
                if (result.Address == null)
                {
                    // it can happen that we cannot find the grain in our partition if there were
                    // some recent changes in the membership
                    if (log.IsEnabled(LogLevel.Trace))
                    {
                        log.Trace("LocalLookup mine {0}=null", grain);
                    }
                    return(false);
                }
                if (log.IsEnabled(LogLevel.Trace))
                {
                    log.Trace("LocalLookup mine {0}={1}", grain, result.Address);
                }
                LocalDirectorySuccesses.Increment();
                localSuccesses.Increment();
                return(true);
            }

            if (log.IsEnabled(LogLevel.Trace))
            {
                log.Trace("TryFullLookup else {0}=null", grain);
            }
            result = default;
            return(false);
        }