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;;

Reply via email to