Thomas,
I believe I have run into another problem that I was hoping you could
help with. I have an application that starts a specified number of
threads that call an empty stored procedure in a tight loop. I started
with 1 thread and when I attempt to start 9 threads, I get the following
error:
[1] sqlstate 08S01 : [SAP AG][LIBSQLOD SO][SAP DB]Communication link
failure;-807 Connection down, session released.
I'll attach the program I used and the stored procedure.
Thanks,
Mark
--
Mark Wong - - [EMAIL PROTECTED]
Open Source Development Lab Inc - A non-profit corporation
15275 SW Koll Parkway - Suite H - Beaverton OR, 97006
(503)-626-2455 x 32 (office)
(503)-626-2436 (fax)
http://www.osdl.org/archive/markw/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <WINDOWS.H>
#include <sqltypes.h>
#include <sql.h>
#include <sqlext.h>
#define LOG_ODBC_ERROR(type, handle) \
log_odbc_error(__FILE__, __LINE__, type, handle)
struct odbc_context_t
{
SQLHDBC hdbc;
SQLHSTMT hstmt;
};
pthread_mutex_t db_source_mutex = PTHREAD_MUTEX_INITIALIZER;
SQLHENV henv = SQL_NULL_HENV;
SQLCHAR servername[32];
SQLCHAR username[32] = "dbt";
SQLCHAR authentication[32] = "dbt";
int thread_count;
int con_only = 0;
int parse_arguments(int argc, char *argv[]);
void *worker(void *data);
double difftimeval(struct timeval rt1, struct timeval rt0);
int log_odbc_error(char *filename, int line, SQLSMALLINT handle_type,
SQLHANDLE handle);
int odbc_connect(struct odbc_context_t *odbcc);
int odbc_disconnect(struct odbc_context_t *odbcc);
int odbc_init(char *sname, char *uname, char *auth);
void test_1(struct odbc_context_t *odbcc);
int main(int argc, char *argv[])
{
int i;
if (!parse_arguments(argc, argv))
{
printf("arguments!\n");
return 0;
}
odbc_init(servername, username, authentication);
for (i = 0; i < thread_count; i++)
{
pthread_t tid;
if (pthread_create(&tid, NULL, &worker, NULL) != 0)
{
printf("pthread_create() error\n");
return 0;
}
if (i == thread_count - 1)
{
pthread_join(tid, NULL);
}
sleep(1);
}
return 0;
}
int parse_arguments(int argc, char *argv[])
{
int i;
char *flag;
if (argc < 3)
{
return 0;
}
for (i = 1; i < argc; i += 2)
{
if (strlen(argv[i]) < 2)
{
printf("invalid flag: %s\n", argv[i]);
exit(1);
}
flag = argv[i] + 1;
if (strcmp(flag, "d") == 0)
{
strcpy(servername, argv[i + 1]);
}
else if (strcmp(flag, "t") == 0)
{
thread_count = atoi(argv[i + 1]);
}
else if (strcmp(flag, "c") == 0)
{
con_only = 1;
}
}
return 1;
}
void *worker(void *data)
{
struct odbc_context_t odbcc;
struct timeval rt0, rt1;
double response_time;
FILE *log;
char filename[128];
odbc_connect(&odbcc);
if (con_only)
{
printf("disconnecting immediately\n");
odbc_disconnect(&odbcc);
return;
}
/*
sprintf(filename, "t%d.log", pthread_self());
log = fopen(filename, "w");
if (log == NULL)
{
printf("canoot open logfile\n");
exit(1);
}
*/
while (1)
{
/*
if (gettimeofday(&rt0, NULL) == -1)
{
perror("gettimeofday");
}
*/
test_1(&odbcc);
/*
if (gettimeofday(&rt1, NULL) == -1)
{
perror("gettimeofday");
}
response_time = difftimeval(rt1, rt0);
fprintf(log, "%d,%f\n");
fflush(log);
*/
}
}
double difftimeval(struct timeval rt1, struct timeval rt0)
{
return (rt1.tv_sec - rt0.tv_sec) +
(double) (rt1.tv_usec - rt0.tv_usec) / 1000000.00;
}
/* Print out all errors messages generated to the error log file. */
int log_odbc_error(char *filename, int line, SQLSMALLINT handle_type,
SQLHANDLE handle)
{
SQLCHAR sqlstate[5];
SQLCHAR message[256];
SQLSMALLINT i;
char msg[1024];
i = 1;
while (SQLGetDiagRec(handle_type, handle, i, sqlstate,
NULL, message, sizeof(message), NULL) == SQL_SUCCESS)
{
sprintf(msg, "[%d] sqlstate %s : %s", i, sqlstate, message);
printf("%s\n", msg);
++i;
}
return 1;
}
/* Open an ODBC connection to the database. */
int odbc_connect(struct odbc_context_t *odbcc)
{
SQLRETURN rc;
/* Allocate connection handles. */
pthread_mutex_lock(&db_source_mutex);
rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &odbcc->hdbc);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
LOG_ODBC_ERROR(SQL_HANDLE_DBC, odbcc->hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, odbcc->hdbc);
return 0;
}
/* Open connection to the database. */
rc = SQLConnect(odbcc->hdbc, servername, SQL_NTS,
username, SQL_NTS, authentication, SQL_NTS);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
LOG_ODBC_ERROR(SQL_HANDLE_DBC, odbcc->hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, odbcc->hdbc);
return 0;
}
rc = SQLSetConnectAttr(odbcc->hdbc, SQL_ATTR_AUTOCOMMIT,
SQL_AUTOCOMMIT_OFF, NULL);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
LOG_ODBC_ERROR(SQL_HANDLE_STMT, odbcc->hstmt);
return 0;
}
rc = SQLSetConnectAttr(odbcc->hdbc, SQL_ATTR_TXN_ISOLATION,
SQL_TXN_REPEATABLE_READ, NULL);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
LOG_ODBC_ERROR(SQL_HANDLE_STMT, odbcc->hstmt);
return 0;
}
/* allocate statement handle */
rc = SQLAllocHandle(SQL_HANDLE_STMT, odbcc->hdbc, &odbcc->hstmt);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
LOG_ODBC_ERROR(SQL_HANDLE_STMT, odbcc->hstmt);
return 0;
}
pthread_mutex_unlock(&db_source_mutex);
return 1;
}
/*
* Disconnect from the database and free the connection handle.
* Note that we create the environment handle in odbc_connect() but
* we don't touch it here.
*/
int odbc_disconnect(struct odbc_context_t *odbcc)
{
SQLRETURN rc;
rc = SQLDisconnect(odbcc->hdbc);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
LOG_ODBC_ERROR(SQL_HANDLE_DBC, odbcc->hdbc);
return 0;
}
rc = SQLFreeHandle(SQL_HANDLE_DBC, odbcc->hdbc);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
LOG_ODBC_ERROR(SQL_HANDLE_DBC, odbcc->hdbc);
return 0;
}
rc = SQLFreeHandle(SQL_HANDLE_STMT, odbcc->hstmt);
if (rc != SQL_SUCCESS)
{
LOG_ODBC_ERROR(SQL_HANDLE_STMT, odbcc->hstmt);
return 0;
}
return 1;
}
/* Initialize ODBC environment handle and the database connect string. */
int odbc_init(char *sname, char *uname, char *auth)
{
SQLRETURN rc;
/* Initialized the environment handle. */
rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
printf("alloc env handle failed");
return 0;
}
/* Set the database connect string, username and password. */
strcpy(servername, sname);
strcpy(username, uname);
strcpy(authentication, auth);
return 1;
}
void test_1(struct odbc_context_t *odbcc)
{
SQLRETURN rc;
rc = SQLPrepare(odbcc->hstmt, "CALL osdl_sapdb_test1", SQL_NTS);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
LOG_ODBC_ERROR(SQL_HANDLE_STMT, odbcc->hstmt);
return;
}
rc = SQLExecute(odbcc->hstmt);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
LOG_ODBC_ERROR(SQL_HANDLE_STMT, odbcc->hstmt);
return;
}
}
/ This file is released under the terms of the Artistic License. Please see
/ the file LICENSE, included in this package, for details.
/
/ Copyright (C) 2002 Mark Wong & Open Source Development Lab, Inc.
CREATE DBPROC osdl_sapdb_test1
AS
SUBTRANS BEGIN;
SUBTRANS END;;