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);
        }
示例#2
0
        /// <summary>
        /// Get a reference to the <see cref="GrainService"/> responsible for actioning the request based on the <paramref name="callingGrainId"/>.
        /// </summary>
        protected TGrainService GetGrainService(GrainId callingGrainId)
        {
            var hashCode    = callingGrainId.GetUniformHashCode();
            var destination = ringProvider.GetPrimaryTargetSilo(hashCode);

            var grainId      = SystemTargetGrainId.CreateGrainServiceGrainId(grainType, destination);
            var grainService = grainFactory.GetSystemTarget <TGrainService>(grainId);

            return(grainService);
        }
示例#3
0
        /// <summary>
        /// Precedence function to resolve races among clusters that are trying to create an activation for a particular grain.
        /// </summary>
        /// <param name="grain">The GrainID under consideration.</param>
        /// <param name="clusterLeft"></param>
        /// <param name="clusterRight"></param>
        /// <returns>
        /// The function returns "true" if clusterLeft has precedence over clusterRight.
        /// </returns>
        internal static bool ActivationPrecedenceFunc(GrainId grain, string clusterLeft, string clusterRight)
        {
            // Make sure that we're not calling this function with default cluster identifiers.
            if (clusterLeft == null || clusterRight == null)
            {
                throw new OrleansException("ActivationPrecedenceFunction must be called with valid cluster identifiers.");
            }

            // use string comparison for cluster precedence, with polarity based on uniform grain hash
            if (grain.GetUniformHashCode() % 2 == 0)
                return string.Compare(clusterLeft, clusterRight, StringComparison.Ordinal) < 0;
            else
                return string.Compare(clusterRight, clusterLeft, StringComparison.Ordinal) < 0;
        }
示例#4
0
        /// <summary>
        /// Precedence function to resolve races among clusters that are trying to create an activation for a particular grain.
        /// </summary>
        /// <param name="grain">The GrainID under consideration.</param>
        /// <param name="clusterLeft"></param>
        /// <param name="clusterRight"></param>
        /// <returns>
        /// The function returns "true" if clusterLeft has precedence over clusterRight.
        /// </returns>
        internal static bool ActivationPrecedenceFunc(GrainId grain, string clusterLeft, string clusterRight)
        {
            // Make sure that we're not calling this function with default cluster identifiers.
            if (clusterLeft == null || clusterRight == null)
            {
                throw new OrleansException("ActivationPrecedenceFunction must be called with valid cluster identifiers.");
            }

            // use string comparison for cluster precedence, with polarity based on uniform grain hash
            if (grain.GetUniformHashCode() % 2 == 0)
            {
                return(string.Compare(clusterLeft, clusterRight, StringComparison.Ordinal) < 0);
            }
            else
            {
                return(string.Compare(clusterRight, clusterLeft, StringComparison.Ordinal) < 0);
            }
        }
示例#5
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));
        }
示例#6
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);
        }
示例#7
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);
        }
示例#8
0
        /// <summary>
        /// Finds the silo that owns the directory information for the given grain ID.
        /// 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="grain"></param>
        /// <param name="excludeThisSiloIfStopping"></param>
        /// <returns></returns>
        public SiloAddress CalculateTargetSilo(GrainId grain, bool excludeThisSiloIfStopping = true)
        {
            // give a special treatment for special grains
            if (grain.IsSystemTarget)
            {
                if (log.IsVerbose2)
                {
                    log.Verbose2("Silo {0} looked for a system target {1}, returned {2}", MyAddress, grain, MyAddress);
                }
                // every silo owns its system targets
                return(MyAddress);
            }

            if (Constants.SystemMembershipTableId.Equals(grain))
            {
                if (Seed == null)
                {
                    string grainName;
                    if (!Constants.TryGetSystemGrainName(grain, out grainName))
                    {
                        grainName = "MembershipTableGrain";
                    }

                    var errorMsg = grainName + " cannot run without Seed node - please check your silo configuration file and make sure it specifies a SeedNode element. " +
                                   " Alternatively, you may want to use AzureTable for LivenessType.";
                    throw new ArgumentException(errorMsg, "grain = " + grain);
                }
                // Directory info for the membership table grain has to be located on the primary (seed) node, for bootstrapping
                if (log.IsVerbose2)
                {
                    log.Verbose2("Silo {0} looked for a special grain {1}, returned {2}", MyAddress, grain, Seed);
                }
                return(Seed);
            }

            SiloAddress siloAddress;
            int         hash = unchecked ((int)grain.GetUniformHashCode());

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

                // 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 = !Running && excludeThisSiloIfStopping;

                // need to implement a binary search, but for now simply traverse the list of silos sorted by their hashes
                siloAddress = membershipRingList.FindLast(siloAddr => (siloAddr.GetConsistentHashCode() <= hash) &&
                                                          (!siloAddr.Equals(MyAddress) || !excludeMySelf));
                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 = membershipRingList[membershipRingList.Count - 1];
                    // Make sure it's not us...
                    if (siloAddress.Equals(MyAddress) && excludeMySelf)
                    {
                        siloAddress = membershipRingList.Count > 1 ? membershipRingList[membershipRingList.Count - 2] : null;
                    }
                }
            }
            if (log.IsVerbose2)
            {
                log.Verbose2("Silo {0} calculated directory partition owner silo {1} for grain {2}: {3} --> {4}", MyAddress, siloAddress, grain, hash, siloAddress.GetConsistentHashCode());
            }
            return(siloAddress);
        }
示例#9
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);
        }
示例#10
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;
        }
示例#11
0
        /// <summary>
        /// Finds the silo that owns the directory information for the given grain ID.
        /// 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="grain"></param>
        /// <param name="excludeThisSiloIfStopping"></param>
        /// <returns></returns>
        public SiloAddress CalculateTargetSilo(GrainId grain, bool excludeThisSiloIfStopping = true)
        {
            // give a special treatment for special grains
            if (grain.IsSystemTarget)
            {
                if (log.IsVerbose2) log.Verbose2("Silo {0} looked for a system target {1}, returned {2}", MyAddress, grain, MyAddress);
                // every silo owns its system targets
                return MyAddress;
            }

            if (Constants.SystemMembershipTableId.Equals(grain))
            {
                if (Seed == null)
                {
                    string grainName;
                    if (!Constants.TryGetSystemGrainName(grain, out grainName))
                        grainName = "MembershipTableGrain";
                    
                    var errorMsg = grainName + " cannot run without Seed node - please check your silo configuration file and make sure it specifies a SeedNode element. " +
                        " Alternatively, you may want to use AzureTable for LivenessType.";
                    throw new ArgumentException(errorMsg, "grain = " + grain);
                }
                // Directory info for the membership table grain has to be located on the primary (seed) node, for bootstrapping
                if (log.IsVerbose2) log.Verbose2("Silo {0} looked for a special grain {1}, returned {2}", MyAddress, grain, Seed);
                return Seed;
            }

            SiloAddress siloAddress;
            int hash = unchecked((int)grain.GetUniformHashCode());

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

                // 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 = !Running && excludeThisSiloIfStopping; 

                // need to implement a binary search, but for now simply traverse the list of silos sorted by their hashes
                siloAddress = membershipRingList.FindLast(siloAddr => (siloAddr.GetConsistentHashCode() <= hash) &&
                                    (!siloAddr.Equals(MyAddress) || !excludeMySelf));
                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 = membershipRingList[membershipRingList.Count - 1];
                    // Make sure it's not us...
                    if (siloAddress.Equals(MyAddress) && excludeMySelf)
                    {
                        siloAddress = membershipRingList.Count > 1 ? membershipRingList[membershipRingList.Count - 2] : null;
                    }
                }
            }
            if (log.IsVerbose2) log.Verbose2("Silo {0} calculated directory partition owner silo {1} for grain {2}: {3} --> {4}", MyAddress, siloAddress, grain, hash, siloAddress.GetConsistentHashCode());
            return siloAddress;
        }
示例#12
0
        public async Task <AddressAndTag> LookupAsync(GrainId grainId, int hopCount = 0)
        {
            (hopCount > 0 ? RemoteLookupsReceived : fullLookups).Increment();

            // see if the owner is somewhere else (returns null if we are owner)
            var forwardAddress = this.CheckIfShouldForward(grainId, hopCount, "LookUpAsync");

            // on all silos other than first, we insert a retry delay and recheck owner before forwarding
            if (hopCount > 0 && forwardAddress != null)
            {
                await Task.Delay(RETRY_DELAY);

                forwardAddress = this.CheckIfShouldForward(grainId, hopCount, "LookUpAsync");
                if (forwardAddress is object)
                {
                    int hash = unchecked ((int)grainId.GetUniformHashCode());
                    this.log.LogWarning($"LookupAsync - It seems we are not the owner of grain {grainId} (hash: {hash:X}), trying to forward it to {forwardAddress} (hopCount={hopCount})");
                }
            }

            if (forwardAddress == null)
            {
                // we are the owner
                LocalDirectoryLookups.Increment();
                var localResult = DirectoryPartition.LookUpActivation(grainId);
                if (localResult.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("FullLookup mine {0}=none", grainId);
                    }
                    localResult.Address    = default;
                    localResult.VersionTag = GrainInfo.NO_ETAG;
                    return(localResult);
                }

                if (log.IsEnabled(LogLevel.Trace))
                {
                    log.Trace("FullLookup mine {0}={1}", grainId, localResult.Address);
                }
                LocalDirectorySuccesses.Increment();
                return(localResult);
            }
            else
            {
                // Just a optimization. Why sending a message to someone we know is not valid.
                if (!IsValidSilo(forwardAddress))
                {
                    throw new OrleansException($"Current directory at {MyAddress} is not stable to perform the lookup for grainId {grainId} (it maps to {forwardAddress}, which is not a valid silo). Retry later.");
                }

                RemoteLookupsSent.Increment();
                var result = await GetDirectoryReference(forwardAddress).LookupAsync(grainId, hopCount + 1);

                // update the cache
                if (result.Address is { } address&& IsValidSilo(address.SiloAddress))
                {
                    DirectoryCache.AddOrUpdate(address, result.VersionTag);
                }

                if (log.IsEnabled(LogLevel.Trace))
                {
                    log.Trace("FullLookup remote {0}={1}", grainId, result.Address);
                }

                return(result);
            }
        }
示例#13
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);
        }
示例#14
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);
        }
        private void CreateGR(int n, int type)
        {
            Guid guid;

            if (type == 1)
            {
                guid = Guid.Parse(string.Format("00000000-0000-0000-0000-{0:X12}", n));
            }
            else
            {
                guid = Guid.Parse(string.Format("{0:X8}-0000-0000-0000-000000000000", n));
            }
            IEchoGrain grain   = GrainClient.GrainFactory.GetGrain <IEchoGrain>(guid);
            GrainId    grainId = ((GrainReference)grain.AsReference <IEchoGrain>()).GrainId;

            output.WriteLine("Guid = {0}, Guid.HashCode = x{1:X8}, GrainId.HashCode = x{2:X8}, GrainId.UniformHashCode = x{3:X8}", guid, guid.GetHashCode(), grainId.GetHashCode(), grainId.GetUniformHashCode());
        }
示例#16
0
 /// <summary>Get a uniform hash code for this grain reference.</summary>
 public uint GetUniformHashCode()
 {
     // GrainId already includes the hashed type code for generic arguments.
     return(GrainId.GetUniformHashCode());
 }
示例#17
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;
        }