/// <summary> /// Handles the reconnection attempts. /// If it succeeds, it marks the host as UP. /// If not, it marks the host as DOWN /// </summary> internal void AttemptReconnection() { _poolModificationSemaphore.Wait(); var toRemove = _connections.Where(c => c.IsClosed).ToArray(); foreach (var c in toRemove) { _connections.Remove(c); } if (_connections.Count > 0) { //there is already an open connection _poolModificationSemaphore.Release(); return; } Logger.Info("Attempting reconnection to host {0}", _host.Address); CreateConnection().ContinueWith(t => { if (t.Status == TaskStatus.RanToCompletion) { _connections.Add(t.Result); //Release as soon as possible _poolModificationSemaphore.Release(); Logger.Info("Reconnection attempt to host {0} succeeded", _host.Address); _host.BringUpIfDown(); } else { _poolModificationSemaphore.Release(); Logger.Info("Reconnection attempt to host {0} failed", _host.Address); _host.SetDown(); } }, TaskContinuationOptions.ExecuteSynchronously); }
public void CopyOnWriteList_Should_Add_And_Remove() { var list = new CopyOnWriteList<string> {"one", "two", "three", "four", "five"}; Assert.AreEqual(5, list.Count); list.Remove("three"); CollectionAssert.AreEqual(new[] { "one", "two", "four", "five" }, list); list.Remove("one"); CollectionAssert.AreEqual(new[] { "two", "four", "five" }, list); list.Remove("five"); CollectionAssert.AreEqual(new[] { "two", "four" }, list); list.Remove("four"); CollectionAssert.AreEqual(new[] { "two" }, list); CollectionAssert.AreEqual(new[] { "two" }, list.ToArray()); list.Remove("two"); CollectionAssert.AreEqual(new string[0], list); }
public void RemoveListener(ContextPartitionStateListener listener) { if (listenersLazy == null) { return; } listenersLazy.Remove(listener); }
public void CheckHealth(Connection c) { if (c.TimedOutOperations < _config.SocketOptions.DefunctReadTimeoutThreshold) { return; } //We are in the default thread-pool (non-io thread) //Defunct: close it and remove it from the pool _connections.Remove(c); c.Dispose(); }
public IDisposable Subscribe <T>(string path, Action <T> consumeAction) { Action <string, object> consumer = (pattern, message) => { if (path == pattern && message is T) { consumeAction((T)message); } }; _list.Add(consumer); return(new AnonymousDisposer(() => _list.Remove(consumer))); }
public IDisposable Subscribe(string topicPattern, Action <string, object> messageConsumer) { var topicExpression = new Regex(topicPattern); Action <string, object> conditionalConsume = (path, message) => { if (topicExpression.IsMatch(path)) { messageConsumer(path, message); } }; _subscribtions.Add(conditionalConsume); return(new AnonymousDisposer(() => _subscribtions.Remove(conditionalConsume))); }
public void CopyOnWriteList_Should_Allow_Parallel_Calls_To_Remove() { var actions = new List<Action>(); var list = new CopyOnWriteList<int>(); for (var i = 0; i < 100; i++) { list.Add(i); } Assert.AreEqual(100, list.Count); for (var i = 0; i < 100; i++) { var item = i; actions.Add(() => { list.Remove(item); }); } TestHelper.ParallelInvoke(actions); Assert.AreEqual(0, list.Count); }
/// <summary> /// Opens one connection. /// If a connection is being opened it yields the same task, preventing creation in parallel. /// </summary> /// <exception cref="SocketException">Throws a SocketException when the connection could not be established with the host</exception> /// <exception cref="AuthenticationException" /> /// <exception cref="UnsupportedProtocolVersionException" /> private async Task <Connection> CreateOpenConnection(bool foreground) { var concurrentOpenTcs = Volatile.Read(ref _connectionOpenTcs); // Try to exit early (cheap) as there could be another thread creating / finishing creating if (concurrentOpenTcs != null) { // There is another thread opening a new connection return(await concurrentOpenTcs.Task.ConfigureAwait(false)); } var tcs = new TaskCompletionSource <Connection>(); // Try to set the creation task source concurrentOpenTcs = Interlocked.CompareExchange(ref _connectionOpenTcs, tcs, null); if (concurrentOpenTcs != null) { // There is another thread opening a new connection return(await concurrentOpenTcs.Task.ConfigureAwait(false)); } if (IsClosing) { return(await FinishOpen(tcs, false, GetNotConnectedException()).ConfigureAwait(false)); } // Before creating, make sure that its still needed // This method is the only one that adds new connections // But we don't control the removal, use snapshot var connectionsSnapshot = _connections.GetSnapshot(); if (connectionsSnapshot.Length >= _expectedConnectionLength) { if (connectionsSnapshot.Length == 0) { // Avoid race condition while removing return(await FinishOpen(tcs, false, GetNotConnectedException()).ConfigureAwait(false)); } return(await FinishOpen(tcs, true, null, connectionsSnapshot[0]).ConfigureAwait(false)); } if (foreground && !_canCreateForeground) { // Foreground creation only cares about one connection // If its already there, yield it connectionsSnapshot = _connections.GetSnapshot(); if (connectionsSnapshot.Length == 0) { // When creating in foreground, it failed return(await FinishOpen(tcs, false, GetNotConnectedException()).ConfigureAwait(false)); } return(await FinishOpen(tcs, false, null, connectionsSnapshot[0]).ConfigureAwait(false)); } Logger.Info("Creating a new connection to {0}", _host.Address); Connection c = null; Exception creationEx = null; try { c = await DoCreateAndOpen().ConfigureAwait(false); } catch (Exception ex) { Logger.Info("Connection to {0} could not be created: {1}", _host.Address, ex); // Can not be awaited on catch on C# 5... creationEx = ex; } if (creationEx != null) { return(await FinishOpen(tcs, true, creationEx).ConfigureAwait(false)); } if (IsClosing) { Logger.Info("Connection to {0} opened successfully but pool #{1} was being closed", _host.Address, GetHashCode()); c.Dispose(); return(await FinishOpen(tcs, false, GetNotConnectedException()).ConfigureAwait(false)); } var newLength = _connections.AddNew(c); Logger.Info("Connection to {0} opened successfully, pool #{1} length: {2}", _host.Address, GetHashCode(), newLength); if (IsClosing) { // We haven't use a CAS operation, so it's possible that the pool is being closed while adding a new // connection, we should remove it. Logger.Info("Connection to {0} opened successfully and added to the pool #{1} but it was being closed", _host.Address, GetHashCode()); _connections.Remove(c); c.Dispose(); return(await FinishOpen(tcs, false, GetNotConnectedException()).ConfigureAwait(false)); } return(await FinishOpen(tcs, true, null, c).ConfigureAwait(false)); }
public void RemoveListener(ContextPartitionStateListener listener) { listenersLazy?.Remove(listener); }
public IDisposable Subscribe(Action <object> consumer) { _subscribers.Add(consumer); EnsureWatching(); return(new AnonymousDisposer(() => _subscribers.Remove(consumer))); }