Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
Home -> Community -> Usenet -> c.d.o.server -> multiple threads with 7.3.2
Hi,
Has anyone developed a multi-threaded application with Oracle 7.3.2/Pro*C/solaris 2.5 ?
I have been playing around with the multi-threaded example given in the Oracle book (online CD version). These are are the problems I have :
1.The example is incomplete - does not have logon and logoff function
details, for instance.
2.Even with each thread having its own runtime context, I need to use
mutexes. This is the opposite of what is stated against Figure 3-4 under
the section Runtime Context Usage Models.
3.The logoff function I have coded is incorrect - it logs the application
out - with threads still running. Apparently, the run time context is not
used.
4.The statement
EXEC SQL CONTEXT USE :ctx;
generates no sql code
There is no reference to ctx in the sql code generated for UPDATE or
COMMIT statements that follow. Am I actually using a different context
each time - how do I verify ?
My modified version of the program is given below. Would appreciate any help.
Thanks,
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
#include <thread.h>
#include <sqlca.h>
EXEC SQL BEGIN DECLARE SECTION;
struct record_log { char action; unsigned int from_account; unsigned int to_account; float amount; }; typedef struct record_log record_log ; struct record_log *trx;
// Function prototypes
void err_report(struct sqlca);
void* do_transaction(void *);
void get_transaction(record_log **);
void logon(sql_context, char*);
void logoff(sql_context);
#define MAX_THREADS 3
record_log records[]= { { 'M', 10001, 10002, 12.50 }, { 'M', 10001, 10003, 25.00 }, { 'M', 10001, 10007, 123.00 }, { 'M', 10001, 10003, 125.00 }, { 'M', 10002, 10006, 12.23 }, { 'M', 10007, 10008, 225.23 }, { 'M', 10002, 10008, 0.70 }, { 'M', 10001, 10003, 11.30 }, { 'M', 10003, 10002, 47.50 }, { 'M', 10002, 10006, 125.00 }, { 'M', 10007, 10008, 225.00 }, { 'M', 10002, 10008, 0.70 }, { 'M', 10001, 10003, 11.00 }, { 'M', 10003, 10002, 47.50 }, { 'M', 10002, 10006, 125.00 }, { 'M', 10007, 10008, 225.00 }, { 'M', 10002, 10008, 0.70 }, { 'M', 10001, 10003, 11.00 }, { 'M', 10003, 10002, 47.50 }, { 'M', 10008, 10001, 1034.54}};
static unsigned int trx_nr=0;
mutex_t mutex;
////////////////////////////////////////////////////////////////////////// Main
////////////////////////////////////////////////////////////////////////
main()
{
thread_t thread_id[3];
parameters params[3];
int status,i;
EXEC SQL BEGIN DECLARE SECTION;
char connection_name[30]; sql_context ctx[3];
// Create MAX_THREADS sessions by connecting MAX_THREADS times
for(i=0;i<MAX_THREADS;i++)
{
cout << "Starting Session ..." << i << endl;
EXEC SQL CONTEXT ALLOCATE :ctx[i];
logon(ctx[i],connection_name);
}
// Create mutex for transaction retrieval if (mutex_init(&mutex, USYNC_THREAD, NULL)) {
cerr << "Can't initialize mutex" << endl; exit(1);
// Create threads
for(i=0;i<MAX_THREADS;i++)
{
params[i].ctx=&ctx[i];
if (thr_create(NULL, 0, &do_transaction, ¶ms[i], 0, &thread_id[i]))
cerr << "Can't create thread:" << i << endl; else
cout << "Created thread:ThrId:" << thread_id[i] << endl;
params[i].thread_id=thread_id[i];
}
// Logoff sessions
for(i=0;i<MAX_THREADS;i++)
{
// wait for thread to end cout << "Waiting for Thread ...." << thread_id[i] << endl; while (thr_join(thread_id[i], NULL, NULL)) cerr << "Error waiting for thread to terminate" << endl; cout << "Stop Session ...." << thread_id[i] << endl; logoff(ctx[i]);
for(i=0;i<MAX_THREADS;i++)
{
EXEC SQL CONTEXT FREE :ctx[i]; cout << "Freed context ...." << thread_id[i] << endl;}
// Destroys mutex
if (mutex_destroy(&mutex))
{
cerr << "Can't destroy mutex" << endl;
exit(1);
}
}
////////////////////////////////////////////// // Function : do_transaction // Description: This functions executes one transaction out of the // records array. //////////////////////////////////////////////
void *do_transaction(void* x )
{
parameters *params = (parameters *) x;
EXEC SQL BEGIN DECLARE SECTION;
typedef struct record_log record_log; record_log *trx; sql_context ctx;
struct sqlca sqlca;
/* Done all transactions ? */
/*
while (trx_nr < (sizeof(records)))
{
*/
get_transaction(&trx);
if (mutex_lock(&mutex))
cerr << "Can't lock mutex" << endl;
EXEC SQL WHENEVER SQLERROR DO err_report(sqlca); EXEC SQL CONTEXT USE :ctx;
cout << "Thread " << params->thread_id << " executing transaction" << endl;
switch(trx->action)
{
/*
case 'M': EXEC SQL UPDATE ACCOUNTS SET BALANCE=BALANCE+:trx->amount WHERE ACCOUNT=:trx->to_account; EXEC SQL UPDATE ACCOUNTS SET BALANCE=BALANCE-:trx->amount WHERE ACCOUNT=:trx->from_account; cout << "Update done:" << trx->to_account << ":" << trx->amount << endl;
case 'M': EXEC SQL SELECT balance INTO :trx->amount FROM ACCOUNTS WHERE ACCOUNT=:trx->to_account; cout << "Select done:" << trx->to_account << ":" << trx->amount << endl; break; default: break;
if (mutex_unlock(&mutex))
cerr << "Can't unlock mutex" << endl;
/*
}
*/
cout << "Done with do_transaction" << endl;
return (0);
}
/***************************************************************** * Function: err_report * * Description: This routine prints out the most recent error*
****************************************************************/ void err_report(struct sqlca sqlca){
cout << endl << sqlca.sqlerrm.sqlerrml << sqlca.sqlerrm.sqlerrmc;
exit(1);
}
////////////////////////////////////////////////////////////////// // Function: logon //
////////////////////////////////////////////////////////////////// void logon(sql_context ctx,char *connect_info){
EXEC SQL BEGIN DECLARE SECTION;
char conn_info[30];
EXEC SQL END DECLARE SECTION;
strcpy(conn_info,connect_info);
EXEC SQL WHENEVER SQLERROR DO err_report(sqlca);
EXEC SQL CONTEXT USE :ctx;
EXEC SQL CONNECT :conn_info;
cout << "Connected!" << endl;
}
/****************************************************************** * Function: logoff * * Description: This routine logs off the database*
******************************************************************/ void logoff(sql_context ctx)
EXEC SQL WHENEVER SQLERROR DO err_report(sqlca);
EXEC SQL CONTEXT USE :ctx;
EXEC SQL COMMIT WORK RELEASE;
cout << "Logged off!" << endl;
}
/****************************************************************** * Function: get_transaction * * Description: This routine returns the next transaction to process*
******************************************************************/void
cerr << "Can't lock mutex" << endl;
*trx=&records[trx_nr];
trx_nr++;
if (mutex_unlock(&mutex))
cerr << "Can't unlock mutex" << endl;
}
Received on Thu Nov 21 1996 - 00:00:00 CST