/// <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); }
/// <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); }
/// <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); }
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); } }
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); }
public GlobalSingleInstanceResponseOutcome(OutcomeState state, AddressAndTag remoteOwnerAddress, string remoteOwnerCluster) { this.State = state; this.RemoteOwnerAddress = remoteOwnerAddress; this.RemoteOwnerCluster = remoteOwnerCluster; }
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); }