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); } }
/// <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); } }
/// <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; } }