/* Copyright © Oracle Corporation 1995. All Rights Reserved. */ /***************************************************************************** * * SQL$DIST_TRANS.C * * This program demonstrates how to use the two-phase commit (2PC) * features from a distributed application in DEC C. * * This program uses three databases: two copies of the PERSONNEL database * named EAST and WEST, and an Oracle CODASYL DBMS database used as the central * database. * The Oracle Rdb routines are written in DEC C with embedded SQL. The SQLMOD * routines are included in the module SQL$DIST_TRANS_C.SQLMOD and are called * from different subroutines. The Oracle CODASYL DBMS routines are written in * Fortan DML; DBMS_INSERT adds an employee to the central database and * DBMS_DELETE removes an employee record from the central database. * * The Oracle Rdb procedures in SQLMOD perform the following functions: * * START_EAST starts a transaction on the EAST database * START_WEST starts a transaction on the WEST database * START_2DB starts a transaction on both EAST and WEST databases * SELECT_WEST selects a record from the WEST database * DELETE_WEST deletes a record from the WEST database * INSERT_EAST inserts a record in a EAST database * * The Oracle Rdb procedures in embedded SQL perform the following functions: * * RDB_ADD_WEST adds an employee to the WEST database * RDB_DEL_EAST terminates an employee from the EAST database * TRANSFER_WEST transfers an employee to the WEST * TRANSFER_EAST transfers an employee to the EAST * SQL$DIST_TRANS_ERROR (called by various routines) * aborts an unsuccessful transaction. **************************************************************************/ #include #include #include #include #include #include #include #include #include /* Typedefs */ typedef void (*ASTADR)(); typedef short IOSB[4]; typedef long DATETIME[2]; typedef long TID[4]; typedef struct { long version; long type; long length; TID distributed_tid; long end; } Context; typedef struct { char emp_id[6]; char emp_last_name[15]; char emp_first_name[11]; char emp_middle_initial[2]; char emp_address1[26]; char emp_city[21]; char emp_state[3]; char emp_zip[6]; char emp_sex[2]; char emp_birth[8]; } Employee; /* File level variables */ static Context context = {1, 1, 16, {0, 0, 0, 0}, 0}; static Employee employee; static long sqlcode; extern char emp_id[6]; extern void start_west(long *sqlcode, Context *context); extern void rdb_add_west(Context *context, Employee *employee); extern void rdb_add_east(Context *context, Employee *employee); extern void rdb_del_east(Context *context, char *emp_id); extern void rdb_del_west(Context *context, char *emp_id); extern void transfer_west(Context *context, char *emp_id); extern void transfer_east(Context *context, char *emp_id); extern void dbms_insert(TID tid, int *id); extern void dbms_delete(TID tid, int *id); extern void sql$dist_trans_error(Context *context); main() { IOSB iosb; TID tid; long message_id = 1; int status, numeric_id; char release_screen, ch, answer, string_inp[23]; char last_name[15], first_name[11], middle_initial[2]; char address1[26], city[21], state[3], zip[6], sex[2]; char emp_birth[8]; struct dsc$descriptor_s ascii_birthday; char xyz1[15]; char xyz2[10]; printf ("Main Menu for a 2PC Application in DEC C\n"); printf ("Enter 1 to add an employee\n"); printf ("Enter 2 to transfer from EAST to WEST\n"); printf ("Enter 3 to transfer from WEST to EAST\n"); printf ("Enter 4 to terminate an employee\n"); while (message_id >= 1 && message_id <= 4) { printf ("\nEnter selection [1,2,3,4, (5 to exit)] ") ; scanf("%d", &message_id); iosb[0] = 0; status = sys$start_transw( 0, /*efn */ 0, /*flags */ iosb, /*IO status block */ NULL, /*astadr */ NULL, /*astprm */ context.distributed_tid, /* return TID */ NULL, /*timeout */ 0 /*accmode */ ); if (status != SS$_SYNCH) status = iosb[0]; if ((status & 1) == 0) lib$signal(status); switch (message_id) { case 1: repeat_1: printf("\nAdd employee to [E]ast or [W]est :"); scanf("\n%c", &ch); ch = tolower(ch); if (ch != 'e' && ch != 'w') goto repeat_1; printf("Enter employee id: "); scanf("\n%s", &employee.emp_id); printf("Enter emp_last_name: "); scanf("\n%s", &employee.emp_last_name); printf("Enter employee first_name: "); scanf("\n%s", &employee.emp_first_name ); printf("Enter employee middle_initial: "); scanf("\n%s", &employee.emp_middle_initial); printf("Enter employee sex :"); scanf("\n%s", &employee.emp_sex); release_screen = getchar(); printf("Enter employee address :"); gets(employee.emp_address1); printf("\nEnter employee city :"); scanf("\n%s", &employee.emp_city); printf("Enter employee state :"); scanf("\n%s", &employee.emp_state); printf("Enter employee zip code :"); scanf("\n%s", &employee.emp_zip); printf("Enter employee birthday dd-MMM-yyyy : "); scanf("\n%s", &string_inp); strcpy(&string_inp[11], " 00:00:00.00"); ascii_birthday.dsc$w_length = strlen(string_inp); ascii_birthday.dsc$a_pointer = string_inp; ascii_birthday.dsc$b_class= DSC$K_CLASS_S; ascii_birthday.dsc$b_dtype= DSC$K_DTYPE_T; status=sys$bintim(&ascii_birthday, &employee.emp_birth); printf("\nDo you need to make changes ? "); scanf("\n%c", &answer); answer = tolower(answer); if (answer == 'y') goto repeat_1; if (ch == 'e') { printf("\nStart Transaction East \n "); rdb_add_east(&context, &employee); if (sqlcode != 0) { printf("\nTransaction failed at insert_east \n"); sql$dist_trans_error(&context); } } else { printf("\nAdding Employee West\n"); rdb_add_west(&context, &employee); if (sqlcode != 0) { printf("\nTransaction failed at rdb_add_west\n"); sql$dist_trans_error(&context); } } numeric_id = atoi(employee.emp_id); strncpy (xyz1, employee.emp_last_name, sizeof xyz1); strncpy (xyz2, employee.emp_first_name, sizeof xyz2); if (sqlcode == 0) { printf("\nAdding Employee to Oracle CODASYL DBMS Database\n "); dbms_insert(context.distributed_tid, &numeric_id); } break; case 2: printf("\nTransfer employees to the WEST database\n"); printf("\nEmployee_id to transfer West :"); scanf("\n%s", &emp_id); transfer_west(&context, emp_id); if (sqlcode != 0) { printf("\nTransaction failed at transfer_west\n"); sql$dist_trans_error(&context); } break; case 3: printf("\nTransfer employees to the EAST database\n"); printf("\nEmployee_id to transfer East :"); scanf("\n%s", &emp_id); transfer_east(&context, emp_id); if (sqlcode != 0) { printf("\nTransaction failed to transfer EAST\n"); sql$dist_trans_error(&context); } break; case 4: repeat_2: printf("\nTerminate employee in [E]ast or [W]est :"); scanf("\n%c", &ch); ch = tolower(ch); if (ch != 'e' && ch != 'w') goto repeat_2; printf("\nEmployee_id to terminate: "); scanf("\n%s", &emp_id); if (ch == 'e') { printf("\nDeleting Record from EAST database\n"); rdb_del_east(&context, emp_id); if (sqlcode != 0) { printf("\nTransaction failed at rdb_del_east\n"); sql$dist_trans_error(&context); } } else { start_west(&sqlcode, &context); if (sqlcode != 0) { printf("\nTransaction failed at start_west \n"); sql$dist_trans_error(&context); } printf("\nDeleting Record from WEST database \n"); rdb_del_west(&context, emp_id); } numeric_id = atoi(emp_id); printf("\nDeleting Record from Oracle CODASYL DBMS database \n"); dbms_delete(context.distributed_tid, &numeric_id); break; } /* end switch block */ iosb[0] = 0; status = sys$end_transw( 0, /*efn */ 0, /*flags */ iosb, /*IO status block */ NULL, /*astadr */ NULL, /*astprm */ context.distributed_tid /* TID */ ); if (status != SS$_SYNCH) status = sys$synch(0, iosb); if ((status & 1) == 0) lib$signal(status); printf ("Enter 1 to add an employee\n"); printf ("Enter 2 to transfer from EAST to WEST\n"); printf ("Enter 3 to transfer from WEST to EAST\n"); printf ("Enter 4 to terminate an employee\n"); }/* end while */ } /* end main program */