internal static IntPtr SetupPGConn(PqsqlConnectionStringBuilder connStringBuilder, out ConnStatusType connStatus, out PGTransactionStatusType tranStatus) { #if CODECONTRACTS Contract.Requires <ArgumentNullException>(connStringBuilder != null); #else if (connStringBuilder == null) { throw new ArgumentNullException(nameof(connStringBuilder)); } #endif // setup null-terminated key-value arrays for the connection string[] keys = new string[connStringBuilder.Keys.Count + 1]; string[] vals = new string[connStringBuilder.Values.Count + 1]; // get keys and values from PqsqlConnectionStringBuilder connStringBuilder.Keys.CopyTo(keys, 0); connStringBuilder.Values.CopyTo(vals, 0); // now create connection IntPtr conn = PqsqlWrapper.PQconnectdbParams(keys, vals, 0); if (conn == IntPtr.Zero) { connStatus = ConnStatusType.CONNECTION_BAD; tranStatus = PGTransactionStatusType.PQTRANS_UNKNOWN; return(conn); } // always force client_encoding to utf8 int client_encoding = PqsqlWrapper.PQclientEncoding(conn); if (client_encoding == (int)PgEnc.PG_UTF8) // done { connStatus = PqsqlWrapper.PQstatus(conn); tranStatus = PqsqlWrapper.PQtransactionStatus(conn); } else if (client_encoding == -1) // bail out, but keep connection object { connStatus = ConnStatusType.CONNECTION_BAD; tranStatus = PGTransactionStatusType.PQTRANS_UNKNOWN; } else // try to set client_encoding to utf8 { if (PqsqlWrapper.PQsetClientEncoding(conn, PgEncName.PG_UTF8) == 0) // success { connStatus = PqsqlWrapper.PQstatus(conn); tranStatus = PqsqlWrapper.PQtransactionStatus(conn); } else // bail out, but keep connection object { connStatus = ConnStatusType.CONNECTION_BAD; tranStatus = PGTransactionStatusType.PQTRANS_UNKNOWN; } } return(conn); }
public static IntPtr GetPGConn(PqsqlConnectionStringBuilder connStringBuilder, out ConnStatusType connStatus, out PGTransactionStatusType tranStatus) { #if CODECONTRACTS Contract.Requires <ArgumentNullException>(connStringBuilder != null); #else if (connStringBuilder == null) { throw new ArgumentNullException(nameof(connStringBuilder)); } #endif Queue <ConnectionInfo> queue; IntPtr pgConn = IntPtr.Zero; lock (mPooledConnsLock) { // connStringBuilder guarantees that we only get "compatible" connections from our internal // connection pool, e.g., application_name will be the same if (!mPooledConns.TryGetValue(connStringBuilder, out queue)) { queue = new Queue <ConnectionInfo>(); mPooledConns[connStringBuilder] = queue; } } lock (queue) { int count = queue.Count; if (count > 0) { ConnectionInfo i = queue.Dequeue(); #if CODECONTRACTS Contract.Assume(i != null); #endif pgConn = i.pgconn; if (count > 1) { // head of queue will inherit old visited count ConnectionInfo j = queue.Peek(); #if CODECONTRACTS Contract.Assume(j != null); #endif j.visited = i.visited; } } } if (!CheckOrRelease(pgConn, out connStatus, out tranStatus)) { pgConn = SetupPGConn(connStringBuilder, out connStatus, out tranStatus); } return(pgConn); }
public bool Equals(PqsqlConnectionStringBuilder connectionStringBuilder) { if (ReferenceEquals(null, connectionStringBuilder)) { return(false); } if (ReferenceEquals(this, connectionStringBuilder)) { return(true); } return(connectionStringBuilder.ConnectionString == ConnectionString); }
public PqsqlConnection(PqsqlConnectionStringBuilder builder) { #if CODECONTRACTS Contract.Requires <ArgumentNullException>(builder != null); #else if (builder == null) { throw new ArgumentNullException(nameof(builder)); } #endif Init(); mConnectionStringBuilder = builder; }
public static void ReleasePGConn(PqsqlConnectionStringBuilder connStringBuilder, IntPtr pgConnHandle) { #if CODECONTRACTS Contract.Requires <ArgumentNullException>(connStringBuilder != null); #else if (connStringBuilder == null) { throw new ArgumentNullException(nameof(connStringBuilder)); } #endif if (pgConnHandle == IntPtr.Zero) { return; } Queue <ConnectionInfo> queue; lock (mPooledConnsLock) { mPooledConns.TryGetValue(connStringBuilder, out queue); } bool closeConnection = true; if (queue == null || !DiscardConnection(pgConnHandle)) { goto close; // just cleanup connection and restart timer } lock (queue) { if (queue.Count < MaxQueue) { queue.Enqueue(new ConnectionInfo { pgconn = pgConnHandle, visited = 0 }); closeConnection = false; // keep connection } } close: if (closeConnection) { PqsqlWrapper.PQfinish(pgConnHandle); // close connection and release memory } }
private static void PoolService(object o) { #if CODECONTRACTS Contract.Requires <ArgumentNullException>(o != null); #else if (o == null) { throw new ArgumentNullException(nameof(o)); } #endif List <IntPtr> closeConnections = o as List <IntPtr>; // we assume that we run PoolService in less than IdleTimeout msecs lock (mPooledConnsLock) { #if PQSQL_DEBUG mLogger.Debug("Running PoolService"); #endif using (Dictionary <PqsqlConnectionStringBuilder, Queue <ConnectionInfo> > .Enumerator e = mPooledConns.GetEnumerator()) { while (e.MoveNext()) { KeyValuePair <PqsqlConnectionStringBuilder, Queue <ConnectionInfo> > item = e.Current; #if PQSQL_DEBUG PqsqlConnectionStringBuilder csb = item.Key; #endif Queue <ConnectionInfo> queue = item.Value; lock (queue) { int count = queue.Count; #if PQSQL_DEBUG mLogger.DebugFormat("ConnectionPool {0}: {1} waiting connections", csb.ConnectionString, count); #endif if (count == 0) { continue; } int maxRelease = count / 2 + 1; ConnectionInfo i = queue.Peek(); #if CODECONTRACTS Contract.Assume(i != null); #endif i.visited++; #if PQSQL_DEBUG if (i.visited <= VisitedThreshold) { mLogger.DebugFormat("ConnectionPool {0}: {1} visits", csb.ConnectionString, i.visited); } #endif if (i.visited > VisitedThreshold) { #if PQSQL_DEBUG mLogger.DebugFormat("ConnectionPool {0}: visit threshold {1} reached, releasing {2} connections", csb.ConnectionString, i.visited, maxRelease); #endif while (maxRelease > 0) { // clean maxRelease connections i = queue.Dequeue(); #if CODECONTRACTS Contract.Assume(i != null); #endif closeConnections.Add(i.pgconn); // close connections outside of queue lock maxRelease--; } } } } } } // now close old connections foreach (IntPtr conn in closeConnections) { PqsqlWrapper.PQfinish(conn); // close connection and release memory } closeConnections.Clear(); }