Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.server -> multiple threads with 7.3.2

multiple threads with 7.3.2

From: <psriram_at_dnt.dialog.com>
Date: 1996/11/21
Message-ID: <5706t6$rt5@mimas.dnt.dialog.com>

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;

EXEC SQL END DECLARE SECTION; struct parameters
{
  sql_context * ctx;
  int thread_id;
};
typedef struct parameters parameters;

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

  EXEC SQL END DECLARE SECTION;     EXEC SQL WHENEVER SQLERROR DO err_report(sqlca);   EXEC SQL ENABLE THREADS;   strcpy(connection_name,"psriram/psriram_at_devsrc");

  // 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, &params[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;

  EXEC SQL END DECLARE SECTION;   ctx=params->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; 

    }
    EXEC SQL COMMIT;
    cout << "Commit done" << endl;

  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) 
{
  if (sqlca.sqlcode < 0)

        cout << endl << sqlca.sqlerrm.sqlerrml << sqlca.sqlerrm.sqlerrmc;   exit(1);
}  

////////////////////////////////////////////////////////////////// 
// Function: logon 
// 

// Description: This routine logs on onto the database as USERNAME/PASSWORD
////////////////////////////////////////////////////////////////// 
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
get_transaction(record_log **trx)
{
  if (mutex_lock(&mutex))

       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

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US