private static List<OperationMetadata> GetNodes(OperationMetadata node, ReplicationDocumentWithClusterInformation replicationDocument)
        {
            var nodes = replicationDocument.Destinations
                .Select(x => ConvertReplicationDestinationToOperationMetadata(x, x.ClusterInformation))
                .Where(x => x != null)
                .ToList();

            nodes.Add(new OperationMetadata(node.Url, node.Credentials, replicationDocument.ClusterInformation));

            return nodes;
        }
        internal static List <OperationMetadata> GetNodes(OperationMetadata node, ReplicationDocumentWithClusterInformation replicationDocument)
        {
            if (node == null || replicationDocument == null)
            {
                return(null);
            }

            var nodes = replicationDocument.Destinations
                        .Select(x => ConvertReplicationDestinationToOperationMetadata(x, x.ClusterInformation))
                        .Where(x => x != null)
                        .ToList();

            if (nodes.Exists(x => x.Url.Equals(node.Url, StringComparison.OrdinalIgnoreCase)) == false)
            {
                nodes.Add(new OperationMetadata(node.Url, node.Credentials, replicationDocument.ClusterInformation));
            }

            return(nodes);
        }
        internal bool UpdateTopology(AsyncServerClient serverClient, OperationMetadata node, ReplicationDocumentWithClusterInformation replicationDocument, string serverHash, OperationMetadata prevLeader)
        {
            Nodes = GetNodes(node, replicationDocument);
            var newLeader = Nodes.SingleOrDefault(x => x.ClusterInformation.IsLeader);
            var document  = new JsonDocument
            {
                DataAsJson = RavenJObject.FromObject(replicationDocument)
            };

            ReplicationInformerLocalCache.TrySavingReplicationInformationToLocalCache(serverHash, document);

            if (replicationDocument.ClientConfiguration != null)
            {
                if (replicationDocument.ClientConfiguration.FailoverBehavior == null)
                {
                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"Server side failoever configuration is set to let client decide, client decided on {serverClient.convention.FailoverBehavior}. ");
                    }
                    replicationDocument.ClientConfiguration.FailoverBehavior = serverClient.convention.FailoverBehavior;
                }
                else if (Log.IsDebugEnabled)
                {
                    Log.Debug($"Server enforced failoever behavior {replicationDocument.ClientConfiguration.FailoverBehavior}. ");
                }
                serverClient.convention.UpdateFrom(replicationDocument.ClientConfiguration);
            }
            if (newLeader != null)
            {
                SetLeaderNodeToKnownLeader(newLeader);
                return(true);
            }
            //here we try to set leader node to null but we might fail since it was changed.
            //We just need to make sure that the leader node is not null and we can stop searching.
            if (SetLeaderNodeToNullIfPrevIsTheSame(prevLeader) == false && LeaderNode != null)
            {
                return(true);
            }
            return(false);
        }
        public HttpResponseMessage TopologyGet()
        {
            if (Database == null)
            {
                return(GetEmptyMessage(HttpStatusCode.NotFound));
            }

            var configurationDocument = Database.ConfigurationRetriever.GetConfigurationDocument <ReplicationDocument <ReplicationDestination.ReplicationDestinationWithConfigurationOrigin> >(Constants.RavenReplicationDestinations);

            if (configurationDocument == null)
            {
                return(GetEmptyMessage(HttpStatusCode.NotFound));
            }

            var mergedDocument = configurationDocument.MergedDocument;

            var isInCluster     = ClusterManager.IsActive() && Database.IsClusterDatabase();
            var commitIndex     = isInCluster ? ClusterManager.Engine.CommitIndex : -1;
            var term            = isInCluster ? ClusterManager.Engine.PersistentState.CurrentTerm : -1;
            var currentTopology = isInCluster ? ClusterManager.Engine.CurrentTopology : null;
            var currentLeader   = ClusterManager.Engine.CurrentLeader;
            var isLeader        = currentLeader == ClusterManager.Engine.Options.SelfConnection.Name;

            var configurationDocumentWithClusterInformation = new ReplicationDocumentWithClusterInformation
            {
                ClientConfiguration = mergedDocument.ClientConfiguration,
                Id                 = mergedDocument.Id,
                Source             = mergedDocument.Source,
                ClusterCommitIndex = commitIndex,
                Term               = term
            };

            if (isInCluster)
            {
                configurationDocumentWithClusterInformation.ClusterInformation = new ClusterInformation(true, isLeader);
            }

            foreach (var destination in mergedDocument.Destinations)
            {
                var destinationIsLeader = isInCluster && isLeader == false && currentTopology != null && currentLeader != null;
                if (destinationIsLeader)
                {
                    var destinationUrl = RaftHelper.GetNormalizedNodeUrl(destination.Url);
                    var node           = currentTopology.AllVotingNodes.FirstOrDefault(x => x.Uri.AbsoluteUri.ToLowerInvariant() == destinationUrl);
                    if (node != null)
                    {
                        destinationIsLeader = node.Name == currentLeader;
                    }
                    else
                    {
                        destinationIsLeader = false;
                    }
                }

                configurationDocumentWithClusterInformation
                .Destinations
                .Add(ReplicationDestination.ReplicationDestinationWithClusterInformation.Create(destination, isInCluster, destinationIsLeader));
            }

            return(GetMessageWithObject(configurationDocumentWithClusterInformation));
        }