예제 #1
0
        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);
        }
예제 #2
0
        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);
 }
예제 #4
0
        public PqsqlConnection(PqsqlConnectionStringBuilder builder)
        {
#if CODECONTRACTS
            Contract.Requires <ArgumentNullException>(builder != null);
#else
            if (builder == null)
            {
                throw new ArgumentNullException(nameof(builder));
            }
#endif

            Init();
            mConnectionStringBuilder = builder;
        }
예제 #5
0
        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
            }
        }
예제 #6
0
        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();
        }