Exemplo n.º 1
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);
        }
        private RemoteClusterActivationResponse ProcessRequestLocal(GrainId grain, string requestClusterId)
        {
            RemoteClusterActivationResponse response;

            //This function will be called only on the Owner silo.
            try
            {
                ActivationAddress address;
                int version;
                GrainDirectoryEntryStatus existingActivationStatus = router.DirectoryPartition.TryGetActivation(grain, out address, out version);


                //Return appropriate protocol response, given current mc status
                switch (existingActivationStatus)
                {
                case GrainDirectoryEntryStatus.Invalid:
                    response = RemoteClusterActivationResponse.Pass;
                    break;

                case GrainDirectoryEntryStatus.Owned:
                    response = new RemoteClusterActivationResponse(ActivationResponseStatus.Failed)
                    {
                        ExistingActivationAddress = new AddressAndTag()
                        {
                            Address    = address,
                            VersionTag = version
                        },
                        ClusterId = clusterId,
                        Owned     = true
                    };
                    break;

                case GrainDirectoryEntryStatus.Cached:
                case GrainDirectoryEntryStatus.RaceLoser:
                    response = RemoteClusterActivationResponse.Pass;
                    break;

                case GrainDirectoryEntryStatus.RequestedOwnership:
                case GrainDirectoryEntryStatus.Doubtful:
                    var iWin = MultiClusterUtils.ActivationPrecedenceFunc(grain, clusterId, requestClusterId);
                    if (iWin)
                    {
                        response = new RemoteClusterActivationResponse(ActivationResponseStatus.Failed)
                        {
                            ExistingActivationAddress = new AddressAndTag()
                            {
                                Address    = address,
                                VersionTag = version
                            },
                            ClusterId = clusterId,
                            Owned     = false
                        };
                    }
                    else
                    {
                        response = RemoteClusterActivationResponse.Pass;
                        //update own activation status to race loser.
                        if (existingActivationStatus == GrainDirectoryEntryStatus.RequestedOwnership)
                        {
                            logger.Trace("GSIP:Rsp {0} Origin={1} RaceLoser", grain.ToString(), requestClusterId);
                            var success = router.DirectoryPartition.UpdateClusterRegistrationStatus(grain, address.Activation, GrainDirectoryEntryStatus.RaceLoser, GrainDirectoryEntryStatus.RequestedOwnership);
                            if (!success)
                            {
                                // there was a race. retry.
                                logger.Trace("GSIP:Rsp {0} Origin={1} Retry", grain.ToString(), requestClusterId);
                                return(ProcessRequestLocal(grain, requestClusterId));
                            }
                        }
                    }
                    break;

                default:
                    throw new InvalidOperationException("Invalid MultiClusterStatus value");
                }
            }
            catch (Exception ex)
            {
                //LOG exception
                response = new RemoteClusterActivationResponse(ActivationResponseStatus.Faulted)
                {
                    ResponseException = ex
                };
            }

            if (logger.IsEnabled(LogLevel.Debug))
            {
                logger.Debug("GSIP:Rsp {0} Origin={1} Result={2}", grain.ToString(), requestClusterId, response);
            }

            return(response);
        }