/// <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; // 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.AvailableCount > 0) { // Found a queue with connectors. Grab the top one. // Check if the connector is still valid. Connector = Queue.TakeAvailable(); Queue.AddBusy(Connector); } } if (Connector != null) { if (!Connector.IsValid()) { Queue.RemoveBusy(Connector); Connector.Close(); return(GetPooledConnector(Connection)); //Try again } return(Connector); } lock (Queue) { if (Queue.AvailableCount + Queue.BusyCount < Connection.MaxPoolSize) { Connector = new NpgsqlConnector(Connection); Queue.AddBusy(Connector); } } if (Connector != null) { Connector.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate; Connector.CertificateSelectionCallback += Connection.CertificateSelectionCallbackDelegate; Connector.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate; Connector.PrivateKeySelectionCallback += Connection.PrivateKeySelectionCallbackDelegate; try { Connector.Open(); } catch { Queue.RemoveBusy(Connector); Connector.Close(); throw; } // Meet the MinPoolSize requirement if needed. if (Connection.MinPoolSize > 1) { lock (Queue) { while (Queue.AvailableCount + Queue.BusyCount < Connection.MinPoolSize) { NpgsqlConnector Spare = new NpgsqlConnector(Connection); Spare.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate; Spare.CertificateSelectionCallback += Connection.CertificateSelectionCallbackDelegate; Spare.CertificateValidationCallback += Connection.CertificateValidationCallbackDelegate; Spare.PrivateKeySelectionCallback += Connection.PrivateKeySelectionCallbackDelegate; Spare.Open(); Spare.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate; Spare.CertificateSelectionCallback -= Connection.CertificateSelectionCallbackDelegate; Spare.CertificateValidationCallback -= Connection.CertificateValidationCallbackDelegate; Spare.PrivateKeySelectionCallback -= Connection.PrivateKeySelectionCallbackDelegate; Queue.EnqueueAvailable(Spare); } } } } return(Connector); }