コード例 #1
0
        /// <summary>
        /// Adds a new activation to the directory partition
        /// </summary>
        /// <param name="grain"></param>
        /// <param name="activation"></param>
        /// <param name="silo"></param>
        /// <param name="registrationStatus"></param>
        /// <returns>The registered ActivationAddress and version associated with this directory mapping</returns>
        internal virtual AddressAndTag AddSingleActivation(GrainId grain, ActivationId activation, SiloAddress silo, GrainDirectoryEntryStatus registrationStatus)
        {
            if (log.IsEnabled(LogLevel.Trace))
            {
                log.Trace("Adding single activation for grain {0}{1}{2}", silo, grain, activation);
            }

            AddressAndTag result = new AddressAndTag();

            if (!IsValidSilo(silo))
            {
                return(result);
            }

            IGrainInfo grainInfo;

            lock (lockable)
            {
                if (!partitionData.TryGetValue(grain, out grainInfo))
                {
                    partitionData[grain] = grainInfo = new GrainInfo();
                }

                result.Address    = grainInfo.AddSingleActivation(grain, activation, silo, registrationStatus);
                result.VersionTag = grainInfo.VersionTag;
            }

            return(result);
        }
コード例 #2
0
        /// <summary>
        /// Adds a new activation to the directory partition
        /// </summary>
        /// <param name="grain"></param>
        /// <param name="activation"></param>
        /// <param name="silo"></param>
        /// <param name="registrationStatus"></param>
        /// <returns>The registered ActivationAddress and version associated with this directory mapping</returns>
        internal virtual AddressAndTag AddSingleActivation(GrainId grain, ActivationId activation, SiloAddress silo, MultiClusterStatus registrationStatus = MultiClusterStatus.Owned)
        {
            if (log.IsVerbose3)
            {
                log.Verbose3("Adding single activation for grain {0}{1}{2}", silo, grain, activation);
            }

            AddressAndTag result = new AddressAndTag();

            if (!IsValidSilo(silo))
            {
                return(result);
            }

            lock (lockable)
            {
                if (!partitionData.ContainsKey(grain))
                {
                    partitionData[grain] = new GrainInfo();
                }
                var grainInfo = partitionData[grain];
                result.Address    = grainInfo.AddSingleActivation(grain, activation, silo, registrationStatus);
                result.VersionTag = grainInfo.VersionTag;
            }
            return(result);
        }
コード例 #3
0
        /// <summary>
        /// Adds a new activation to the directory partition
        /// </summary>
        /// <param name="grain"></param>
        /// <param name="activation"></param>
        /// <param name="silo"></param>
        /// <returns>The registered ActivationAddress and version associated with this directory mapping</returns>
        internal virtual AddressAndTag AddSingleActivation(GrainId grain, ActivationId activation, SiloAddress silo)
        {
            if (log.IsEnabled(LogLevel.Trace))
            {
                log.Trace("Adding single activation for grain {0}{1}{2}", silo, grain, activation);
            }

            AddressAndTag result = new AddressAndTag();

            if (!IsValidSilo(silo))
            {
                var siloStatus = this.siloStatusOracle.GetApproximateSiloStatus(silo);
                throw new OrleansException($"Trying to register {grain} on invalid silo: {silo}. Known status: {siloStatus}");
            }

            IGrainInfo grainInfo;

            lock (lockable)
            {
                if (!partitionData.TryGetValue(grain, out grainInfo))
                {
                    partitionData[grain] = grainInfo = new GrainInfo();
                }

                result.Address    = grainInfo.AddSingleActivation(grain, activation, silo);
                result.VersionTag = grainInfo.VersionTag;
            }

            return(result);
        }
コード例 #4
0
        public async Task <AddressAndTag> RegisterAsync(GrainAddress address, int hopCount)
        {
            var counterStatistic = hopCount > 0 ? this.RegistrationsSingleActRemoteReceived : this.registrationsSingleActIssued;

            counterStatistic.Increment();

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

            // 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(address.GrainId, hopCount, "RegisterAsync");
                if (forwardAddress is object)
                {
                    int hash = unchecked ((int)address.GrainId.GetUniformHashCode());
                    this.log.LogWarning($"RegisterAsync - It seems we are not the owner of activation {address} (hash: {hash:X}), trying to forward it to {forwardAddress} (hopCount={hopCount})");
                }
            }

            if (forwardAddress == null)
            {
                RegistrationsSingleActLocal.Increment();

                var result = DirectoryPartition.AddSingleActivation(address);
                return(result);
            }
            else
            {
                RegistrationsSingleActRemoteSent.Increment();

                // otherwise, notify the owner
                AddressAndTag result = await GetDirectoryReference(forwardAddress).RegisterAsync(address, hopCount + 1);

                // Caching optimization:
                // cache the result of a successfull RegisterSingleActivation call, only if it is not a duplicate activation.
                // this way next local lookup will find this ActivationAddress in the cache and we will save a full lookup!
                if (result.Address == null)
                {
                    return(result);
                }

                if (!address.Equals(result.Address) || !IsValidSilo(address.SiloAddress))
                {
                    return(result);
                }

                // update the cache so next local lookup will find this ActivationAddress in the cache and we will save full lookup.
                DirectoryCache.AddOrUpdate(address, result.VersionTag);

                return(result);
            }
        }
コード例 #5
0
        private static GlobalSingleInstanceResponseOutcome?GetOutcome(ICollection <RemoteClusterActivationResponse> responses, GrainId grainId, ILogger logger, bool hasPendingResponses)
        {
            if (!hasPendingResponses && responses.All(res => res.ResponseStatus == ActivationResponseStatus.Pass))
            {
                // All passed, or no other clusters exist
                return(GlobalSingleInstanceResponseOutcome.Succeed);
            }

            var ownerResponses = responses
                                 .Where(res => res.ResponseStatus == ActivationResponseStatus.Failed && res.Owned == true).ToList();

            if (ownerResponses.Count > 0)
            {
                if (ownerResponses.Count > 1)
                {
                    logger.Warn((int)ErrorCode.GlobalSingleInstance_MultipleOwners, "GSIP:Req {0} Unexpected error occurred. Multiple Owner Replies.", grainId);
                }

                return(new GlobalSingleInstanceResponseOutcome(OutcomeState.RemoteOwner, ownerResponses[0].ExistingActivationAddress, ownerResponses[0].ClusterId));
            }

            // are all responses here or have failed?
            if (!hasPendingResponses)
            {
                // determine best candidate
                var candidates = responses
                                 .Where(res => res.ResponseStatus == ActivationResponseStatus.Failed && res.ExistingActivationAddress.Address != null)
                                 .ToList();

                AddressAndTag remoteOwner        = new AddressAndTag();
                string        remoteOwnerCluster = null;
                foreach (var res in candidates)
                {
                    if (remoteOwner.Address == null ||
                        MultiClusterUtils.ActivationPrecedenceFunc(grainId, res.ClusterId, remoteOwnerCluster))
                    {
                        remoteOwner        = res.ExistingActivationAddress;
                        remoteOwnerCluster = res.ClusterId;
                    }
                }

                var outcome = remoteOwner.Address != null ? OutcomeState.RemoteOwnerLikely : OutcomeState.Inconclusive;
                return(new GlobalSingleInstanceResponseOutcome(outcome, remoteOwner, remoteOwnerCluster));
            }

            return(null);
        }
コード例 #6
0
 public GlobalSingleInstanceResponseOutcome(OutcomeState state, AddressAndTag remoteOwnerAddress, string remoteOwnerCluster)
 {
     this.State = state;
     this.RemoteOwnerAddress = remoteOwnerAddress;
     this.RemoteOwnerCluster = remoteOwnerCluster;
 }
コード例 #7
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);
        }