Example #1
0
        private RavenConnectionStringOptions GetConnectionOptionsSafe(CounterReplicationDestination destination, out string lastError)
        {
            try
            {
                var connectionStringOptions = new RavenConnectionStringOptions
                {
                    Url    = destination.ServerUrl,
                    ApiKey = destination.ApiKey,
                };
                if (string.IsNullOrEmpty(destination.Username) == false)
                {
                    connectionStringOptions.Credentials = string.IsNullOrEmpty(destination.Domain)
                        ? new NetworkCredential(destination.Username, destination.Password)
                        : new NetworkCredential(destination.Username, destination.Password, destination.Domain);
                }
                lastError = string.Empty;

                connectionStringOptions.DefaultDatabase = destination.CounterStorageName;
                return(connectionStringOptions);
            }
            catch (Exception e)
            {
                lastError = e.Message;
                Log.ErrorException($"Ignoring bad replication config!{Environment.NewLine}Could not figure out connection options for [Url: {destination.ServerUrl}]", e);
                return(null);
            }
        }
Example #2
0
        private ReplicationResult TryReplicate(CounterReplicationDestination destination, out long lastEtagSent, out string lastError)
        {
            long etag;

            lastEtagSent = 0;
            var connectionStringOptions = GetConnectionOptionsSafe(destination, out lastError);

            if (connectionStringOptions == null ||
                !GetLastReplicatedEtagFrom(connectionStringOptions, destination.CounterStorageUrl, out etag, out lastError))
            {
                return(ReplicationResult.Failure);
            }

            var replicationData = GetCountersDataSinceEtag(etag, out lastEtagSent);

            storage.MetricsCounters.GetReplicationBatchSizeMetric(destination.CounterStorageUrl).Mark(replicationData.Counters.Count);
            storage.MetricsCounters.GetReplicationBatchSizeHistogram(destination.CounterStorageUrl).Update(replicationData.Counters.Count);

            if (replicationData.Counters.Count > 0)
            {
                return(PerformReplicationToServer(connectionStringOptions, destination.CounterStorageUrl, replicationData, out lastError) ?
                       ReplicationResult.Success : ReplicationResult.Failure);
            }

            return(ReplicationResult.NotReplicated);
        }
Example #3
0
        private bool ReplicateTo(CounterReplicationDestination destination)
        {
            var replicationStopwatch = Stopwatch.StartNew();

            //todo: here, build url according to :destination.Url + '/counters/' + destination.
            try
            {
                string lastError;
                long   lastEtag;
                bool   result = false;

                switch (TryReplicate(destination, out lastEtag, out lastError))
                {
                case ReplicationResult.Success:
                    DateTime replicationTime = SystemTime.UtcNow;
                    RecordSuccess(destination.CounterStorageUrl, lastReplicatedEtag: lastEtag, lastReplicatedLastModified: replicationTime);
                    storage.MetricsCounters.OutgoingReplications.Mark();
                    result = true;
                    break;

                case ReplicationResult.NotReplicated:
                    //TODO: Record not replicated
                    RecordSuccess(destination.CounterStorageUrl, SystemTime.UtcNow);
                    break;

                default:
                    RecordFailure(destination.CounterStorageUrl, lastError);
                    storage.MetricsCounters.OutgoingReplications.Mark();
                    break;
                }

                return(result);
            }
            catch (Exception ex)
            {
                Log.ErrorException("Error occured replicating to: " + destination.CounterStorageUrl, ex);
                RecordFailure(destination.CounterStorageUrl, ex.Message);
                return(false);
            }
            finally
            {
                replicationStopwatch.Stop();
                var elapsedMicroseconds = (long)(replicationStopwatch.Elapsed.TotalMilliseconds * SystemTime.MicroSecPerTick);
                storage.MetricsCounters.GetReplicationDurationHistogram(destination.CounterStorageUrl).Update(elapsedMicroseconds);
                var holder = activeReplicationTasks.GetOrAdd(destination.CounterStorageUrl, s => new SemaphoreSlim(0, 1));
                holder.Release();
            }
        }
Example #4
0
        private void ReplicateToDestination(CounterReplicationDestination destination)
        {
            var dest   = destination.CounterStorageUrl;
            var holder = activeReplicationTasks.GetOrAdd(dest, s => new SemaphoreSlim(1));

            if (holder.Wait(0) == false)
            {
                return;
            }
            var replicationTask = Task.Factory.StartNew(
                () =>
            {
                using (LogContext.WithResource(storage.Name))
                {
                    try
                    {
                        if (ReplicateTo(destination))
                        {
                            SignalCounterUpdate();
                        }
                    }
                    catch (Exception e)
                    {
                        Log.ErrorException("Could not replicate to " + dest, e);
                    }
                }
            });

            activeTasks.Enqueue(replicationTask);
            replicationTask.ContinueWith(
                _ =>
            {
                // here we purge all the completed tasks at the head of the queue
                Task task;
                while (activeTasks.TryPeek(out task))
                {
                    if (!task.IsCompleted && !task.IsCanceled && !task.IsFaulted)
                    {
                        break;
                    }
                    activeTasks.TryDequeue(out task);     // remove it from end
                }
            });
        }
Example #5
0
        private CountersReplicationTopologyDestinationNode HandleDestination(CounterReplicationDestination replicationDestination)
        {
            RavenConnectionStringOptions connectionStringOptions = new RavenConnectionStringOptions
            {
                Credentials = replicationDestination.Credentials,
                ApiKey      = replicationDestination.ApiKey,
                Url         = replicationDestination.ServerUrl
            };

            string error;
            string targetServerUrl;

            // since each server can be addresses using both dns and ips we normalize connection string url by fetching target server url
            // it should give us consistent urls
            if (FetchTargetServerUrl(replicationDestination.ServerUrl, connectionStringOptions, out targetServerUrl, out error) == false)
            {
                var offlineNode = CountersReplicationTopologyDestinationNode.Offline(replicationDestination.CounterStorageUrl, counterStorage.ServerId);

                if (string.IsNullOrEmpty(error) == false)
                {
                    offlineNode.Errors.Add(error);
                }

                return(offlineNode);
            }

            targetServerUrl = targetServerUrl.ForCounter(replicationDestination.CounterStorageName);

            if (replicationDestination.Disabled)
            {
                return(CountersReplicationTopologyDestinationNode.Disabled(targetServerUrl, counterStorage.ServerId));
            }

            if (from.Contains(targetServerUrl))
            {
                var state = CheckConnectionState(replicationDestination.CounterStorageUrl, connectionStringOptions);
                switch (state)
                {
                case ReplicatonNodeState.Online:
                    return(CountersReplicationTopologyDestinationNode.Online(targetServerUrl, counterStorage.ServerId));

                case ReplicatonNodeState.Offline:
                    return(CountersReplicationTopologyDestinationNode.Offline(targetServerUrl, counterStorage.ServerId));

                default:
                    throw new NotSupportedException(state.ToString());
                }
            }


            CountersReplicationTopologyRootNode rootNode;

            if (TryGetSchema(targetServerUrl, connectionStringOptions, out rootNode, out error))
            {
                var node = CountersReplicationTopologyDestinationNode.Online(targetServerUrl, counterStorage.ServerId);
                node.Destinations = rootNode.Destinations;
                node.Sources      = rootNode.Sources;
                node.Errors       = rootNode.Errors;

                return(node);
            }

            var offline = CountersReplicationTopologyDestinationNode.Offline(targetServerUrl, counterStorage.ServerId);

            if (string.IsNullOrEmpty(error) == false)
            {
                offline.Errors.Add(error);
            }

            return(offline);
        }