Example #1
0
        public async Task <AddressAndTag> RegisterAsync(ActivationAddress 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.Grain, 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.Grain, hopCount, "RegisterAsync");
                if (forwardAddress is object)
                {
                    int hash = unchecked ((int)address.Grain.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.Silo))
                {
                    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);
            }
        }
Example #2
0
        /// <summary>
        /// Registers a new activation, in single activation mode, with the directory service.
        /// If there is already an activation registered for this grain, then the new activation will
        /// not be registered and the address of the existing activation will be returned.
        /// Otherwise, the passed-in address will be returned.
        /// <para>This method must be called from a scheduler thread.</para>
        /// </summary>
        /// <param name="address">The address of the potential new activation.</param>
        /// <returns>The address registered for the grain's single activation.</returns>
        public async Task <ActivationAddress> RegisterSingleActivationAsync(ActivationAddress address)
        {
            registrationsSingleActIssued.Increment();
            SiloAddress owner = CalculateTargetSilo(address.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 (owner.Equals(MyAddress))
            {
                RegistrationsSingleActLocal.Increment();
                // if I am the owner, store the new activation locally
                Tuple <ActivationAddress, int> returnedAddress = DirectoryPartition.AddSingleActivation(address.Grain, address.Activation, address.Silo);
                return(returnedAddress == null ? null : returnedAddress.Item1);
            }
            else
            {
                RegistrationsSingleActRemoteSent.Increment();
                // otherwise, notify the owner
                Tuple <ActivationAddress, int> returnedAddress = await GetDirectoryReference(owner).RegisterSingleActivation(address, NUM_RETRIES);

                // 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 (returnedAddress == null || returnedAddress.Item1 == null)
                {
                    return(null);
                }

                if (!address.Equals(returnedAddress.Item1) || !IsValidSilo(address.Silo))
                {
                    return(returnedAddress.Item1);
                }

                var cached = new List <Tuple <SiloAddress, ActivationId> >(1)
                {
                    Tuple.Create(address.Silo, address.Activation)
                };
                // update the cache so next local lookup will find this ActivationAddress in the cache and we will save full lookup.
                DirectoryCache.AddOrUpdate(address.Grain, cached, returnedAddress.Item2);
                return(returnedAddress.Item1);
            }
        }
Example #3
0
        /// <summary>
        /// Registers a new activation, in single activation mode, with the directory service.
        /// If there is already an activation registered for this grain, then the new activation will
        /// not be registered and the address of the existing activation will be returned.
        /// Otherwise, the passed-in address will be returned.
        /// <para>This method must be called from a scheduler thread.</para>
        /// </summary>
        /// <param name="address">The address of the potential new activation.</param>
        /// <returns>The address registered for the grain's single activation.</returns>
        public async Task<ActivationAddress> RegisterSingleActivationAsync(ActivationAddress address)
        {
            registrationsSingleActIssued.Increment();
            SiloAddress owner = CalculateTargetSilo(address.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 (owner.Equals(MyAddress))
            {
                RegistrationsSingleActLocal.Increment();
                // if I am the owner, store the new activation locally
                Tuple<ActivationAddress, int> returnedAddress = DirectoryPartition.AddSingleActivation(address.Grain, address.Activation, address.Silo);
                return returnedAddress == null ? null : returnedAddress.Item1;
            }
            else
            {
                RegistrationsSingleActRemoteSent.Increment();
                // otherwise, notify the owner
                Tuple<ActivationAddress, int> returnedAddress = await GetDirectoryReference(owner).RegisterSingleActivation(address, NUM_RETRIES);

                // 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 (returnedAddress == null || returnedAddress.Item1 == null) return null;

                if (!address.Equals(returnedAddress.Item1) || !IsValidSilo(address.Silo)) return returnedAddress.Item1;

                var cached = new List<Tuple<SiloAddress, ActivationId>>( new [] { Tuple.Create(address.Silo, address.Activation) });
                // update the cache so next local lookup will find this ActivationAddress in the cache and we will save full lookup.
                DirectoryCache.AddOrUpdate(address.Grain, cached, returnedAddress.Item2);
                return returnedAddress.Item1;
            }
        }