Enabling a Connection Pool
Prerequisite: The data source has been configured successfully. For Linux OS, see Configuring a Data Source in the Linux OS. For Windows OS, see Configuring a Data Source in the Windows OS.
Enabling a connection pool in a Linux or Windows OS can significantly improve the performance of middle-layer applications that need to establish and close connections frequently. For details about the reference configuration, see Connection Pool Scenario. The sample code is as follows:
#ifdef WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>
#include <string.h>
#include <sys/time.h>
#include <pthread.h>
#include <sqltypes.h>
#include <time.h>
SQLHENV env;
SQLHDBC conn;
struct timeval start, end;
#define CONN_COUNT 15000
#define CHECK_ERROR(retcode, str, handle, htype) \
({ \
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { \
fprintf(stderr, "FAILED:\t"); \
extract_error(str, handle, htype); \
exit(-1); \
} else { \
printf("OK:\t%s\n", str); \
} \
})
void print_diag(char *msg, SQLSMALLINT htype, SQLHANDLE handle)
{
char sqlstate[32];
char message[1000];
SQLINTEGER nativeerror;
SQLSMALLINT textlen;
SQLRETURN ret;
if (msg) {
printf("%s\n", msg);
}
ret = SQLGetDiagRec(htype, handle, 1, sqlstate, &nativeerror, message, 256, &textlen);
if (ret != SQL_ERROR) {
printf("%s=%s\n", (CHAR *)sqlstate, (CHAR *)message);
}
}
void extract_error(char *fn, SQLHANDLE handle, SQLSMALLINT type)
{
SQLINTEGER i = 0;
SQLINTEGER NativeError;
SQLCHAR SQLState[7];
SQLCHAR MessageText[256];
SQLSMALLINT TextLength;
SQLRETURN ret;
fprintf(stderr, "The driver reported the following error %s\n", fn);
if (NULL == handle)
return;
do {
ret = SQLGetDiagRec(type, handle, ++i, SQLState, &NativeError, MessageText, sizeof(MessageText), &TextLength);
if (SQL_SUCCEEDED(ret)) {
printf("[SQLState:%s]:[%ldth error]:[NativeError:%ld]: %s\n",
SQLState,
(long)i,
(long)NativeError,
MessageText);
}
} while (ret == SQL_SUCCESS);
}
void InitializeEnvironment()
{
/* Enable the connection pool. Configure connection pool parameters in the Windows OS before allocating an environment handle. */
SQLSetEnvAttr(env, SQL_ATTR_CONNECTION_POOLING, (SQLINTEGER *)SQL_CP_ONE_PER_DRIVER, 0);
/* Close the connection pool in the Windows OS. */
// SQLSetEnvAttr(env, SQL_ATTR_CONNECTION_POOLING, (SQLINTEGER*)SQL_CP_OFF, 0);
// Allocate an environment handle.
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
// Configure the ODBC version.
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
// Configure the timeout interval for establishing a connection.
SQLSetConnectAttr(conn, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)5, 0);
}
void test_connect()
{
SQLRETURN ret;
SQLCHAR str[1024];
SQLSMALLINT strl;
SQLCHAR dsn[1024];
SQLUINTEGER uIntVal;
SQLAllocHandle(SQL_HANDLE_DBC, env, &conn);
/* Adjust the connection string based on the scenario. */
char *config = "Driver=GaussMPP;DSN=gaussdb;";
ret = SQLSetConnectAttr(conn, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)(1), 0);
ret = SQLDriverConnect(conn, 0, (SQLCHAR *)config, SQL_NTS, (SQLCHAR *)NULL, SQL_NTS, 0, SQL_DRIVER_NOPROMPT);
if (SQL_SUCCEEDED(ret)) {
// printf("Connected\n");
} else {
print_diag("SQLDriverConnect failed.", SQL_HANDLE_DBC, conn);
SQLFreeHandle(SQL_HANDLE_DBC, conn);
SQLFreeHandle(SQL_HANDLE_ENV, env);
exit(1);
}
/* Put the connection into the connection pool to reuse the connection. */
if (conn != SQL_NULL_HDBC) {
SQLDisconnect(conn);
SQLFreeHandle(SQL_HANDLE_DBC, conn);
conn = SQL_NULL_HDBC;
}
}
int main()
{
int count = 0;
int timeuser;
gettimeofday(&start, NULL);
InitializeEnvironment();
for (int i = 0; i < CONN_COUNT; i++) {
test_connect();
count++;
}
// Release an environment handle.
SQLFreeHandle(SQL_HANDLE_ENV, env);
printf("Connection count: %d\n", count);
gettimeofday(&end, NULL);
timeuser = 1000000 * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec;
printf("Connection time: %.3f s \n", (double)timeuser / 1000000);
return 0;
} The result varies with the environment. When the connection pool is enabled, the running result of this example is as follows:
Connection count: 15000 Connection time: 14.175 s
When the connection pool is disabled, the running result of this example is as follows:
Connection count: 15000 Connection time: 691.768 s
The application code in the Windows OS is the same as that in the Linux OS. The connection string needs to be configured based on the scenario.