/// <summary> /// Checks connection for timeout /// </summary> public void CheckForTimeout(TimeSpan keepAlive) { lock (this) { CachedConnection prev = null; CachedConnection current = _connections; while (current != null) { // see if it's lifetime has expired if (current.InactiveTime > keepAlive) { // close the connection current.Connection.Close(); // remove connection from the list current = current.Next; if (prev == null) { _connections = current; } else { prev.Next = current; } } else { // move to the next prev = current; current = current.Next; } } } }
/// <summary> /// Returns connection back to the cache /// </summary> public void StoreConnection(IConnection connection) { lock (this) { _connections = new CachedConnection(connection, _connections); } }
//------------------------------------------------------ //--Plugin Services //------------------------------------------------------ public IDatabase GetDatabase(string connectionName, int?database = null) { CachedConnection cachedConn = GetConnection(connectionName); int?databaseId = database ?? cachedConn.Configuration.DefaultDatabase; return(databaseId == null ? cachedConn.Connection.GetDatabase() : cachedConn.Connection.GetDatabase(databaseId.Value)); }
public ValueTask <HttpConnection> GetConnectionAsync <TState>(Func <TState, ValueTask <HttpConnection> > createConnection, TState state) { List <CachedConnection> list = _idleConnections; lock (SyncObj) { // Try to return a cached connection. We need to loop in case the connection // we get from the list is unusable. while (list.Count > 0) { CachedConnection cachedConnection = list[list.Count - 1]; list.RemoveAt(list.Count - 1); if (cachedConnection.IsUsable()) { // We found a valid collection. Return it. return(new ValueTask <HttpConnection>(cachedConnection._connection)); } // We got a connection, but it was already closed by the server or the // server sent unexpected data or the connection is too old. In any case, // we can't use the connection, so get rid of it and try again. cachedConnection._connection.Dispose(); } // No valid cached connections, so we need to create a new one. If // there's no limit on the number of connections associated with this // pool, or if we haven't reached such a limit, simply create a new // connection. if (_waiters == null || _associatedConnectionCount < _maxConnections) { IncrementConnectionCountNoLock(); return(WaitForCreatedConnectionAsync(createConnection(state))); } else { // There is a limit, and we've reached it, which means we need to // wait for a connection to be returned to the pool or for a connection // associated with the pool to be dropped before we can create a // new one. Create a waiter object and register it with the pool; it'll // be signaled with the created connection when one is returned or // space is available and the provided creation func has successfully // created the connection to be used. var waiter = new ConnectionWaiter <TState>(this, createConnection, state); _waiters.Enqueue(waiter); return(new ValueTask <HttpConnection>(waiter.Task)); } // Note that we don't check for _disposed. We may end up disposing the // created connection when it's returned, but we don't want to block use // of the pool if it's already been disposed, as there's a race condition // between getting a pool and someone disposing of it, and we don't want // to complicate the logic about trying to get a different pool when the // retrieved one has been disposed of. In the future we could alternatively // try returning such connections to whatever pool is currently considered // current for that endpoint, if there is one. } }
public Task Listen(string channelId) { _logger.LogDebug($"listen {channelId} {Context.User?.Identity.Name} {Context.ConnectionId}"); Groups.AddToGroupAsync(Context.ConnectionId, channelId); var cc = new CachedConnection { Id = Context.ConnectionId, ProfileId = Context.User?.FindFirstValue(JwtRegisteredClaimNames.Sub), ProfileName = Context.User?.FindFirstValue("name"), Room = channelId }; _cache.Connections.TryAdd(cc.Id, cc); return(Clients.OthersInGroup(channelId).PresenceEvent(new BroadcastEvent(Context.User, "PRESENCE.ARRIVED"))); }
/// <summary> /// Returns cached connection /// </summary> public IConnection GetConnection() { lock (this) { if (_connections == null) { // cache is empty so create new connection return(_cache.CreateConnection(_channelUri)); } else { IConnection connection = _connections.Connection; _connections = _connections.Next; return(connection); } } }
public ValueTask <HttpConnection> GetConnectionAsync <TState>( Func <TState, CancellationToken, ValueTask <HttpConnection> > createConnection, TState state, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(new ValueTask <HttpConnection>(Task.FromCanceled <HttpConnection>(cancellationToken))); } List <CachedConnection> list = _idleConnections; lock (SyncObj) { // Try to return a cached connection. We need to loop in case the connection // we get from the list is unusable. while (list.Count > 0) { CachedConnection cachedConnection = list[list.Count - 1]; HttpConnection conn = cachedConnection._connection; list.RemoveAt(list.Count - 1); if (cachedConnection.IsUsable()) { // We found a valid collection. Return it. if (NetEventSource.IsEnabled) { conn.Trace("Found usable connection in pool."); } return(new ValueTask <HttpConnection>(conn)); } // We got a connection, but it was already closed by the server or the // server sent unexpected data or the connection is too old. In any case, // we can't use the connection, so get rid of it and try again. if (NetEventSource.IsEnabled) { conn.Trace("Found invalid connection in pool."); } conn.Dispose(); } // No valid cached connections, so we need to create a new one. If // there's no limit on the number of connections associated with this // pool, or if we haven't reached such a limit, simply create a new // connection. if (_associatedConnectionCount < _maxConnections) { if (NetEventSource.IsEnabled) { Trace("Creating new connection for pool."); } IncrementConnectionCountNoLock(); return(WaitForCreatedConnectionAsync(createConnection(state, cancellationToken))); } else { // There is a limit, and we've reached it, which means we need to // wait for a connection to be returned to the pool or for a connection // associated with the pool to be dropped before we can create a // new one. Create a waiter object and register it with the pool; it'll // be signaled with the created connection when one is returned or // space is available and the provided creation func has successfully // created the connection to be used. if (NetEventSource.IsEnabled) { Trace("Limit reached. Waiting to create new connection."); } var waiter = new ConnectionWaiter <TState>(this, createConnection, state, cancellationToken); EnqueueWaiter(waiter); if (cancellationToken.CanBeCanceled) { // If cancellation could be requested, register a callback for it that'll cancel // the waiter and remove the waiter from the queue. Note that this registration needs // to happen under the reentrant lock and after enqueueing the waiter. waiter._cancellationTokenRegistration = cancellationToken.Register(s => { var innerWaiter = (ConnectionWaiter)s; lock (innerWaiter._pool.SyncObj) { // If it's in the list, remove it and cancel it. if (innerWaiter._pool.RemoveWaiterForCancellation(innerWaiter)) { bool canceled = innerWaiter.TrySetCanceled(innerWaiter._cancellationToken); Debug.Assert(canceled); } } }, waiter); } return(new ValueTask <HttpConnection>(waiter.Task)); } // Note that we don't check for _disposed. We may end up disposing the // created connection when it's returned, but we don't want to block use // of the pool if it's already been disposed, as there's a race condition // between getting a pool and someone disposing of it, and we don't want // to complicate the logic about trying to get a different pool when the // retrieved one has been disposed of. In the future we could alternatively // try returning such connections to whatever pool is currently considered // current for that endpoint, if there is one. } }
public ISubscriber GetSubscriber(string connectionName) { CachedConnection cachedConn = GetConnection(connectionName); return(cachedConn.Connection.GetSubscriber()); }
/// <summary> /// Returns cached connection /// </summary> public IConnection GetConnection() { lock (this) { if (_connections == null) { // cache is empty so create new connection return _cache.CreateConnection(_channelUri); } IConnection connection = _connections.Connection; _connections = _connections.Next; return connection; } }
public CachedConnection(IConnection connection, CachedConnection next) { _connection = connection; _lastUsed = DateTime.Now; Next = next; }
public CachedConnection(IConnection connection, CachedConnection next) { _connection = connection; _lastUsed = DateTime.Now; _next = next; }