private static bool CheckOrRelease(IntPtr pgConn, out ConnStatusType connStatus, out PGTransactionStatusType tranStatus) { if (pgConn == IntPtr.Zero) { connStatus = ConnStatusType.CONNECTION_BAD; tranStatus = PGTransactionStatusType.PQTRANS_UNKNOWN; return(false); } // is connection reusable? connStatus = PqsqlWrapper.PQstatus(pgConn); if (connStatus != ConnStatusType.CONNECTION_OK) { goto broken; } tranStatus = PqsqlWrapper.PQtransactionStatus(pgConn); if (tranStatus != PGTransactionStatusType.PQTRANS_IDLE) { goto broken; } // // now check the connection: first try to fix the client encoding if it is not utf8 for some reason. // if client_encoding is utf8, we send the empty query to check whether the socket is still usable // for the backend communiction. here, we could make use of tcp_keepalive settings. // int client_encoding = PqsqlWrapper.PQclientEncoding(pgConn); if (client_encoding == -1) { goto broken; } if (client_encoding == (int)PgEnc.PG_UTF8) // client_encoding == utf8 { // send empty query to test whether we are really connected (tcp_keepalive might have closed socket) unsafe { byte[] empty = { 0 }; // empty query string fixed(byte *eq = empty) { if (PqsqlWrapper.PQsendQuery(pgConn, eq) == 0) // could not send query { goto broken; } } } // Reading result: consume and clear remaining results until we reach the NULL result. // PQgetResult will block here IntPtr res; ExecStatusType st = ExecStatusType.PGRES_EMPTY_QUERY; while ((res = PqsqlWrapper.PQgetResult(pgConn)) != IntPtr.Zero) { ExecStatusType st0 = PqsqlWrapper.PQresultStatus(res); if (st0 != ExecStatusType.PGRES_EMPTY_QUERY) { st = st0; } // always free res PqsqlWrapper.PQclear(res); } if (st != ExecStatusType.PGRES_EMPTY_QUERY) // received wrong exec status { goto broken; } } else // set client_encoding to utf8 { // set client_encoding to test whether we are really connected (tcp_keepalive might have closed socket) if (PqsqlWrapper.PQsetClientEncoding(pgConn, PgEncName.PG_UTF8) != 0) { goto broken; } } return(true); // successfully reused connection broken: // reconnect with current connection setting PqsqlWrapper.PQreset(pgConn); connStatus = PqsqlWrapper.PQstatus(pgConn); if (connStatus == ConnStatusType.CONNECTION_OK) { tranStatus = PqsqlWrapper.PQtransactionStatus(pgConn); if (tranStatus == PGTransactionStatusType.PQTRANS_IDLE) { return(true); // successfully reconnected } } else { tranStatus = PGTransactionStatusType.PQTRANS_UNKNOWN; } // could not reconnect: finally give up and clean up memory PqsqlWrapper.PQfinish(pgConn); return(false); }