private void TimerElapsedHandler(object sender, ElapsedEventArgs e) { NpgsqlConnector Connector; var activeConnectionsExist = false; try { lock (locker) { foreach (ConnectorQueue Queue in PooledConnectors.Values) { lock (Queue) { if (Queue.Available.Count > 0) { if (Queue.Available.Count + Queue.Busy.Count > Queue.MinPoolSize) { if (Queue.InactiveTime >= Queue.ConnectionLifeTime) { Int32 diff = Queue.Available.Count + Queue.Busy.Count - Queue.MinPoolSize; Int32 toBeClosed = (diff + 1) / 2; toBeClosed = Math.Min(toBeClosed, Queue.Available.Count); if (diff < 2) { diff = 2; } Queue.InactiveTime -= Queue.ConnectionLifeTime / (int)(Math.Log(diff) / Math.Log(2)); for (Int32 i = 0; i < toBeClosed; ++i) { Connector = Queue.Available.Dequeue(); Connector.Close(); } } else { Queue.InactiveTime++; } } else { Queue.InactiveTime = 0; } if (Queue.Available.Count > 0 || Queue.Busy.Count > 0) { activeConnectionsExist = true; } } else { Queue.InactiveTime = 0; } } } } } finally { if (activeConnectionsExist) { Timer.Start(); } else { Timer = null; } } }
/// <summary> /// Rolls back a transaction from a pending state. /// </summary> public override void Rollback() { CheckReady(); Connector.Rollback(); Connection = null; }
/// <summary> /// Find an available pooled connector in the non-shared pool, or create /// a new one if none found. /// </summary> private NpgsqlConnector GetPooledConnector(NpgsqlConnection Connection) { ConnectorQueue Queue; NpgsqlConnector Connector = null; // We only need to lock all pools when trying to get one pool or create one. lock (locker) { // Try to find a queue. if (!PooledConnectors.TryGetValue(Connection.ConnectionString, out Queue)) { Queue = new ConnectorQueue(); Queue.ConnectionLifeTime = Connection.ConnectionLifeTime; Queue.MinPoolSize = Connection.MinPoolSize; PooledConnectors[Connection.ConnectionString] = Queue; } } // Now we can simply lock on the pool itself. lock (Queue) { if (Queue.Available.Count > 0) { // Found a queue with connectors. Grab the top one. // Check if the connector is still valid. Connector = Queue.Available.Dequeue(); Queue.Busy.Add(Connector, null); } } if (Connector != null) { if (!Connector.IsValid()) { lock (Queue) { Queue.Busy.Remove(Connector); } Connector.Close(); return(GetPooledConnector(Connection)); //Try again } return(Connector); } lock (Queue) { if (Queue.Available.Count + Queue.Busy.Count < Connection.MaxPoolSize) { Connector = new NpgsqlConnector(Connection); Queue.Busy.Add(Connector, null); } } if (Connector != null) { Connector.RemoteCertificateValidationCallback += Connection.RemoteCertificateValidationCallbackDelegate; // Connector.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate; // Connector.CertificateSelectionCallback += Connection.CertificateSelectionCallbackDelegate; // Connector.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate; // Connector.PrivateKeySelectionCallback += Connection.PrivateKeySelectionCallbackDelegate; // Connector.ValidateRemoteCertificateCallback += Connection.ValidateRemoteCertificateCallbackDelegate; try { Connector.Open(); } catch { lock (Queue) { Queue.Busy.Remove(Connector); } Connector.Close(); throw; } // Meet the MinPoolSize requirement if needed. if (Connection.MinPoolSize > 1) { lock (Queue) { while (Queue.Available.Count + Queue.Busy.Count < Connection.MinPoolSize) { NpgsqlConnector Spare = new NpgsqlConnector(Connection); Spare.RemoteCertificateValidationCallback += Connection.RemoteCertificateValidationCallbackDelegate; // Spare.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate; // Spare.CertificateSelectionCallback += Connection.CertificateSelectionCallbackDelegate; // Spare.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate; // Spare.PrivateKeySelectionCallback += Connection.PrivateKeySelectionCallbackDelegate; // Spare.ValidateRemoteCertificateCallback += Connection.ValidateRemoteCertificateCallbackDelegate; Spare.Open(); Spare.RemoteCertificateValidationCallback -= Connection.RemoteCertificateValidationCallbackDelegate; // Spare.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate; // Spare.CertificateSelectionCallback -= Connection.CertificateSelectionCallbackDelegate; // Spare.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate; // Spare.PrivateKeySelectionCallback -= Connection.PrivateKeySelectionCallbackDelegate; // Spare.ValidateRemoteCertificateCallback -= Connection.ValidateRemoteCertificateCallbackDelegate; Queue.Available.Enqueue(Spare); } } } } return(Connector); }
internal override ValueTask <IBackendMessage> ReadMessage(bool async) => Connector.ReadMessage(async, DataRowLoadingMode.Sequential);