Oracle Enterprise Manager Oracle Trace User's Guide Go to Product Documentation Library
Library
Go to books for this product
Product
Go to Contents for this book
Contents
Go to Index
Index



Go to previous file in sequence Go to next file in sequence

Sample Instrumented Application



This appendix provides a sample instrumented application.

The application simulates an automated teller machine (ATM). It is instrumented to gather information about the user interface and response time and patterns of ATM use among users. The purpose of instrumenting was to answer such questions as:

You can refer to this sample for examples of instrumenting details.

Events in the Sample Application

Table D-1 describes the events that are instrumented in the ATM sample application.
Table D-1: Events in the ATM Sample Application
Event

Description

Items for Event

Type of Event

BALANCES

Performs an account balance inquiry

resource_items, cross_fac_1

Duration

DEPOSIT

Records deposit and updates balance

resource_items, cross_fac_1, amount

Duration

WITHDRAWAL

Verifies amount is available, records withdrawal, and updates balances

resource_items, cross_fac_1, amount

Duration

TRANSFER

Moves amount from one account to another

resource_items, cross_fac_1, amount, dest_acct

Duration

QUICKWTHDRW

Verifies there is enough in the account, withdraws $50 and updates the balances

resource_items, cross_fac_1, amount

Duration

OVERDRAFT

Records error message if there is not enough in the account to cover the withdrawal

cross_fac_1, acct_num

Point

SESSION

Records duration of ATM session

resource_items

Duration

VALIDOK

User entered valid account number

acct_num

Point

VALIDERR

User entered invalid account number

acct_num

Point

Running the ATM Sample Application

To install and run the ATM sample application provided by Oracle Trace, take the following steps:


1.
Define ORACLE_HOME to point to the Oracle home directory (which contains the Oracle7 Server). For example,
   setenv ORACLE_HOME /oracle/product

2.
Define ORACLE_SID to the SID of the database you will use to store the ATM tables and data. For example,
   setenv ORACLE_SID trace

3.
Locate or create sufficient tablespace for the ATM data you plan to load:
Number of Records

Number of Data Blocks

(2048 Bytes Each)

100

10

2,500

100

10,000

400


4.
Log in as System and create ATM user:
    % sqlplus system\manager
      SQL> create user atm identified by sampleatm
        2> default tablespace is <atm_space> quota
        3> unlimitd on  <atm_space>;   
      SQL> grant create session, create table to atm;

5.
Disconnect, connect as atm, and execute SQL scripts:
   SQL> disconnect
   SQL> connect atm\sampleatm
   SQL> @atmtab
   SQL> @atmdat
   SQL> @atmind
The atmtab.sql script creates tables. The atmdat.sql script loads data for 10,000 accounts. Use either atmdat100.sql or atmdat2500.sql to load fewer accounts. The atmind.sql script creates indexes.


6.
Compile the sample application using the appropriate commands for your operating system's C compiler. The sample application must be linked against libepc.a and libepcpt.a in $ORACLE_HOME/lib.
The atmoci.c version of the sample application uses the Oracle Call Interface. Refer to the OCI documentation set for information on the Oracle Call Interface.

The atmpc.pc version of the sample application uses the Pro*C interface. It should be processed by the Pro*C compiler before compiling. Refer to the Pro*C documentation for further information.


7.
To start collections for the ATM example from the Oracle Trace console, you must first copy the ATM product definition file, atm.fdf, from the server machine to the correct directory as follows:
   % cp $ORACLE_HOME/otrace/demo/atm.fdf $ORACLE_HOME/rdbms/demo

8.
Run the sample application. The ATM program looks for the product definition file in the current directory. If the product definition file is not found, you get an error. Copy the atm.fdf file to the current directory.

9.
Optional step: To pass input through a data file rather than entering it interactively, enter:
   % atmoci atm.inp
   input file is atm.inp
You will not see any output to the terminal when you pass in a data file.

The remainder of this appendix contains the code for the ATM sample application. You can refer to it for examples of how to include calls to Oracle Trace routines within your own application.

/* Copyright (c) Oracle Corporation 1995.  All Rights Reserved.  */
/*
NAME
atmpc.pc -- Trace ATM sample application using PRO*C interface
DESCRIPTION
Simulates an ATM, allowing balance inquiries, deposits and withdrawals
*/
#include <stdio.h>
#include <stdlib.h>
#include <epc.h>
#define S_LONG 4                        /* use instead of sizeof(long) */
#define TRUE 1
#define FALSE 0
#define MAXLINE 80 /* maximum length of input line */
#define API_VERSION 1
#define VENDOR 192216243
#define FACILITY_NUMBER 1
#define MAX_EVENT 9 /* number of events */
#define BALANCES 1 /* event numbers */
#define DEPOSIT 2
#define WITHDRAWAL 3
#define TRANSFER 4
#define QUICK_WITHDRAW 5
#define OVERDRAFT 6
#define USER_SESSION 7
#define VALIDATION_OK 8
#define VALIDATION_ERR 9
/* macros to simplify input/output */
#define DISPLAY(text) if (!FromFile) printf(text)
#define READ(text) if (FromFile) fgets(text, MAXLINE, InFile); else gets(text)
/* Function declarations */
void INIT_ATM(/* int argc, char *argv[] */);
void END_ATM(/* void */);
long LOGIN_USER(/* void */);
void INIT_USER_SESSION(/* void */);
void END_USER_SESSION(/* void */);
long DISPLAY_MAIN_MENU(/* void */);
void GET_BALANCES(/* long acct_num */);
void MAKE_DEPOSIT(/* long acct_num */);
void MAKE_WITHDRAWAL(/* long acct_num */);
void MAKE_TRANSFER(/* long acct_num */);
long MAKE_QUICK_WITHDRAWAL(/* long acct_num */);
long ATM_VALID_ACCT_NUM(/* long acct_num */);
long ATM_VALID_XFER_ACCT(/* long acct_num */);
float ATM_SAV_BALANCE(/* long acct_num */);
float ATM_CHK_BALANCE(/* long acct_num */);
void ATM_SAV_DEPOSIT(/* long acct_num, long amount */);
void ATM_CHK_DEPOSIT(/* long acct_num, long amount */);
void ATM_SAV_WITHDRAWAL(/* long acct_num, long amount */);
void ATM_CHK_WITHDRAWAL(/* long acct_num, long amount */);
void ATM_START_RW(/* void */);
void ATM_START_RO(/* void */);
void ATM_COMMIT(/* void */);
void ATM_ROLLBACK(/* void */);
EXEC SQL INCLUDE sqlca;
long SQLCODE; /* SQL return status code */
EXEC SQL BEGIN DECLARE SECTION; /* declare SQL host variables */
long acct_num; /* passed as parameters in most */
long amount; /* SQL routines */
EXEC SQL END DECLARE SECTION;
EXEC SQL WHENEVER NOT FOUND CONTINUE; /* keep running if record not found */
FILE  *InFile;                          /* input file */
char FromFile; /* true if reading from input file */
char Version[10]; /* Product version string */
char Collection_Name[80]; /* Name of collection file */
char FDF_Name[80]; /* Name of facility definition file */
char Regist_ID[80]; /* reusable registration ID text */
long *Event_Flags; /* Trace event flags set by epc_init */
long Session_Handle; /* event instance handles */
long Txn_Handle;
main (argc, argv)
int argc;
char *argv[];
{
char user = TRUE; /* we're accepting users */
char session; /* we have a valid user */
long acct_num; /* user's account number */
long choice; /* user's menu choice */
char exit_early; /* user finished without picking */
/* exit from menu */
INIT_ATM (argc, argv);
while (user)
{
acct_num = LOGIN_USER(); /* returns valid acct_num or 0 */
if (acct_num == 0)
{
session = FALSE;
user = FALSE;
}
else
{
session = TRUE;
INIT_USER_SESSION(); /* start user_session event */
}
    while (session)
{
choice = DISPLAY_MAIN_MENU();
switch (choice)
{
case 1:
GET_BALANCES(acct_num);
break;
        case 2:
MAKE_DEPOSIT(acct_num);
break;
        case 3:
MAKE_WITHDRAWAL(acct_num);
break;
        case 4:
MAKE_TRANSFER(acct_num);
break;
        case 5:
exit_early = MAKE_QUICK_WITHDRAWAL(acct_num);
if (exit_early)
{
session = FALSE; /* end session after quick withdrawal */
} /* unless it's an overdraft */
break;
        case 0:
session = FALSE;
break;
        default:
DISPLAY("\nInvalid choice.\n");
break;
} /* end of switch */
} /* end of while (session) */
    if (user)
{ END_USER_SESSION(); } /* finish this user */
} /* end of while (user) */
END_ATM();
exit (0);
}
/*-----------------------------------------------------------------------------
INIT_ATM
     Session-wide settings:  input and output, Trace initialization, database
-----------------------------------------------------------------------------*/
void INIT_ATM (argc, argv)
int argc;
char *argv[];
{
long status;
char user_pass[40];
/******************************************************************************
Set up input and output files
******************************************************************************/
if (argc == 1)                           /* no input file; use stdin, stdout */
{ FromFile = FALSE; }
if (argc == 2)
{
if (argv[1] == NULL)
{ printf("Input filename is NULL\n"); }
else
{
printf("Input filename is %s\n", argv[1]);

if ((InFile = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "Can't open file %s\n", argv[1]);
exit(1);
}
else /* we have an input file */
{ FromFile = TRUE; }
}
}
if (argc > 2)
{
fprintf(stderr, "Too many arguments on command line\n");
exit(1);
}
/******************************************************************************
Initialize Trace session and start collection
******************************************************************************/
strcpy(Version, "V1.0");
strcpy(Collection_Name, "sampatm");
strcpy(FDF_Name, "atm.fdf");
status = epc_init(API_VERSION, VENDOR, FACILITY_NUMBER, Version, NULL, NULL,
&Event_Flags, MAX_EVENT, EPC_K_ALLOC, 0, 0, NULL, NULL);
if (status == epc_s_success)
status = epc_collect(API_VERSION, VENDOR, FACILITY_NUMBER, Version, 0,
Collection_Name, FDF_Name, 0, 0);
if (status != epc_s_success)
exit(status); /* problem with Trace */
/******************************************************************************
Connect to database;
******************************************************************************/
strcpy(user_pass, "atm/sampleatm");
EXEC SQL CONNECT :user_pass;
EXEC SQL ROLLBACK; /* rollback any default trans */
return;
}
/*-----------------------------------------------------------------------------
END_ATM
     Clean up session:  close files, end Trace collection, exit database
-----------------------------------------------------------------------------*/
void END_ATM ()
{
long status;
if (FromFile)
{ fclose(InFile); }
EXEC SQL SET TRANSACTION READ ONLY;
EXEC SQL COMMIT RELEASE;
status = epc_cancel(API_VERSION, VENDOR, FACILITY_NUMBER, Version,                                  Collection_Name, 0);
return;
}
/*-----------------------------------------------------------------------------
LOGIN_USER
     Get account number from user and validate against database
-----------------------------------------------------------------------------*/
long LOGIN_USER ()
{
char good_input;
char line[MAXLINE];
long acct_num;
long valid;
long status;
char *record; /* event record */
good_input = FALSE;
record = malloc(S_LONG);
DISPLAY("\n\n  Trace Manhattan Bank\n");
DISPLAY("Automated Teller Machine\n\n\n");
DISPLAY("Please enter your account number\n");
DISPLAY("or enter 0 to exit: ");
do
{
READ(line);
acct_num = atoi(line);
    if (acct_num == 0)                         /* allow user to exit without */
{ good_input = TRUE; } /* logging in */
else
{
valid = ATM_VALID_ACCT_NUM(acct_num); /* valid acct num or -1 */
if (valid == -1) /* no account in database */
{
if (Event_Flags[VALIDATION_ERR])
{
memcpy(record, &acct_num, S_LONG);
status = epc_event(API_VERSION, VENDOR, FACILITY_NUMBER,
VALIDATION_ERR, 0, record, S_LONG, 0, 0, 0);
}
DISPLAY("\nInvalid account number. Enter your account number");
DISPLAY("\nor enter 0 to exit: ");
}
else /* account in database */
{
if (Event_Flags[VALIDATION_OK])
{
memcpy(record, &acct_num, S_LONG);
status = epc_event(API_VERSION, VENDOR, FACILITY_NUMBER,
VALIDATION_OK, 0, record, S_LONG, 0, 0, 0);
}
good_input = TRUE;
}
}
} while (!good_input);
free(record);
return (acct_num);
}
/*-----------------------------------------------------------------------------
INIT_USER_SESSION
     Start user_session event
-----------------------------------------------------------------------------*/
void INIT_USER_SESSION ()
{
long status;
if (Event_Flags[USER_SESSION])
{
status = epc_start_event(API_VERSION, VENDOR, FACILITY_NUMBER,
USER_SESSION, &Session_Handle, 0, NULL,
0, 0, 0, 0);
}
return;
}
/*-----------------------------------------------------------------------------
END_USER_SESSION
     End user_session event
-----------------------------------------------------------------------------*/
void END_USER_SESSION ()
{
long status;
                     /* Make sure cross_fac_1 gets reset now that we're done */
status = epc_cf_value(API_VERSION, 1, 0, NULL, NULL);
if (Event_Flags[USER_SESSION])
{
status = epc_end_event(API_VERSION, VENDOR, FACILITY_NUMBER, USER_SESSION,
&Session_Handle, 0, NULL, 0, 0, 0, 0);
}
return;
}
/*-----------------------------------------------------------------------------
DISPLAY_MAIN_MENU
     Display main menu and get user's choice
-----------------------------------------------------------------------------*/
long DISPLAY_MAIN_MENU ()
{
char line[MAXLINE];
long choice;
char good_input;
good_input = FALSE;
DISPLAY("\n\nTrace Manhattan Bank\n");
DISPLAY(" ATM Main Menu\n");
DISPLAY("1. Balance\n");
DISPLAY("2. Deposit\n");
DISPLAY("3. Withdrawal\n");
DISPLAY("4. Transfer\n");
DISPLAY("5. Quick Withdrawal $50\n\n");
DISPLAY("0. Exit\n\n");
DISPLAY("Enter choice: ");
do
{
READ(line);
choice = atoi(line);
    if ((choice > -1) && (choice < 6))
{
good_input = TRUE;
}
else
DISPLAY("\nInvalid choice. Enter choice: ");
} while (!good_input); /* end of do */
return (choice);
}
/*-----------------------------------------------------------------------------
GET_BALANCES
     Display balances of savings and checkings acct
-----------------------------------------------------------------------------*/
void GET_BALANCES (acct_num)
long acct_num;
{
long status;
float sav_amt;
float chk_amt;
char line[MAXLINE];
strcpy(Regist_ID, "Balances");
status = epc_cf_value(API_VERSION, 1, BALANCES, NULL, NULL);
status = epc_add_reg_id(API_VERSION, VENDOR, FACILITY_NUMBER, Version,
Regist_ID, 1);
if (Event_Flags[BALANCES])
{
status = epc_start_event(API_VERSION, VENDOR, FACILITY_NUMBER, BALANCES,
&Txn_Handle, 0, NULL, 0, 0, 0, 0);
}
ATM_START_RO();
sav_amt = ATM_SAV_BALANCE (acct_num);
chk_amt = ATM_CHK_BALANCE (acct_num);
ATM_COMMIT();
if (Event_Flags[BALANCES])
{
status = epc_end_event(API_VERSION, VENDOR, FACILITY_NUMBER, BALANCES,
&Txn_Handle, 0, NULL, 0, 0, 0, 0);
}
status = epc_remove_reg_id(API_VERSION, VENDOR, FACILITY_NUMBER,
Version, Regist_ID, 1);
DISPLAY("\n\nAccount Balances\n\n");
if (!FromFile)
{
printf("Checking: %-.2f\n", chk_amt);
printf("Savings : %-.2f\n", sav_amt);
}
DISPLAY("\nPress ENTER to return to Main Menu: ");
READ(line);
return;
}
/*-----------------------------------------------------------------------------
MAKE_DEPOSIT
     Deposit money into either savings or checkings.
-----------------------------------------------------------------------------*/
void  MAKE_DEPOSIT (acct_num)
long acct_num;
{
char line[MAXLINE];
long acct_type;
char good_choice;
char good_amount;
long txn_amt = 0;
long status;
char *record;
good_choice = FALSE;
good_amount = FALSE;
record = malloc(S_LONG);
strcpy(Regist_ID, "Deposit");
status = epc_cf_value(API_VERSION, 1, DEPOSIT, NULL, NULL);
status = epc_add_reg_id(API_VERSION, VENDOR, FACILITY_NUMBER, Version,
Regist_ID, 1);
DISPLAY("\n\nAccount Deposit\n\n");
DISPLAY("Deposit into:\n");
DISPLAY("1. Checking\n");
DISPLAY("2. Savings\n");
DISPLAY("\nEnter choice or 0 to cancel: ");
do
{
READ(line);
acct_type = atoi(line);
    if ((acct_type < 0) || (acct_type > 2))    /* bad input */
{ DISPLAY("\nInvalid choice. Enter choice: "); }
else
{ good_choice = TRUE; } /* valid account type */
} while (!good_choice);                        /* end of do */
if (acct_type == 0)                            /* cancel transaction */
{
txn_amt = 0;
good_amount = TRUE;
}
while (!good_amount)
{
DISPLAY("\nEnter dollar amount to deposit or 0 to cancel: ");
READ(line);
txn_amt = atoi(line);
    if (txn_amt < 0)
{ DISPLAY("\nInvalid amount."); }
else
{ good_amount = TRUE; }
}
if (txn_amt > 0)
{
if (Event_Flags[DEPOSIT])
{
memset(record, 0, S_LONG);
status = epc_start_event(API_VERSION, VENDOR, FACILITY_NUMBER, DEPOSIT,
&Txn_Handle, 0, record, S_LONG,
0, 0, 0);
}
    ATM_START_RW();
if (acct_type == 1)
{ ATM_CHK_DEPOSIT(acct_num, txn_amt); }
if (acct_type == 2)
{ ATM_SAV_DEPOSIT(acct_num, txn_amt); }
ATM_COMMIT();
    if (Event_Flags[DEPOSIT])
{
memcpy(record, &txn_amt, S_LONG);
status = epc_end_event(API_VERSION, VENDOR, FACILITY_NUMBER, DEPOSIT,
&Txn_Handle, 0, record, S_LONG, 0, 0, 0);
}
}
status = epc_remove_reg_id(API_VERSION, VENDOR, FACILITY_NUMBER, 
Version, Regist_ID, 1);
free(record);
return;
}
/*-----------------------------------------------------------------------------
MAKE_WITHDRAWAL
     Withdraw money from either savings or checkings.  If withdrawal is more
than balance, record an overdraft event
-----------------------------------------------------------------------------*/
void MAKE_WITHDRAWAL (acct_num)
long acct_num;
{
long status;
char line[MAXLINE];
char txn_complete;
long acct_type;
char good_choice;
long txn_amt = 0;
char good_amount;
float acct_bal;
char *wrecord, *orecord; /* event records for withdrawal, overdraft */
txn_complete = FALSE;
wrecord = malloc(S_LONG);
orecord = malloc(S_LONG);
strcpy(Regist_ID, "Withdrawal");
status = epc_cf_value(API_VERSION, 1, WITHDRAWAL, NULL, NULL);
status = epc_add_reg_id(API_VERSION, VENDOR, FACILITY_NUMBER, Version,
Regist_ID, 1);
do                                                /* get transaction input */
{
good_choice = FALSE;
DISPLAY("\n\nAccount Withdrawal\n\n");
DISPLAY("Withdraw from:\n");
DISPLAY("1. Checking\n");
DISPLAY("2. Savings\n");
DISPLAY("\nEnter choice or 0 to cancel: ");
    do                                             /* get account type */
{
READ(line);
acct_type = atoi(line);
        if ((acct_type < 0) || (acct_type > 2))    /* bad input */
{ DISPLAY("\nInvalid choice. Enter choice: "); }
else
{ good_choice = TRUE; } /* valid account type */
} while (!good_choice);
    if (acct_type == 0)                            /* cancel transaction */
{
txn_amt = 0;
good_amount = TRUE;
}
else
{ good_amount = FALSE; } /* need to get amount */
    while (!good_amount)
{
DISPLAY("\nEnter dollar amount to withdraw or 0 to cancel: ");
READ(line);
txn_amt = atoi(line);
        if (txn_amt < 0)
{ DISPLAY("\nInvalid amount."); }
else
{ good_amount = TRUE; }
} /* have good amount */
    if (txn_amt > 0)                               /* user didn't cancel */
{
if (Event_Flags[WITHDRAWAL])
{
memset(wrecord, 0, S_LONG);
status = epc_start_event(API_VERSION, VENDOR, FACILITY_NUMBER,
WITHDRAWAL, &Txn_Handle, 0, wrecord,
S_LONG, 0, 0, 0);
}
        ATM_START_RW();
if (acct_type == 1)
{ acct_bal = ATM_CHK_BALANCE(acct_num); }
if (acct_type == 2)
{ acct_bal = ATM_SAV_BALANCE(acct_num); }
        if (acct_bal > txn_amt)                    /* sufficient funds */
{
if (acct_type == 1)
{ ATM_CHK_WITHDRAWAL(acct_num, txn_amt, acct_bal); }
if (acct_type == 2)
{ ATM_SAV_WITHDRAWAL(acct_num, txn_amt, acct_bal); }
ATM_COMMIT();
txn_complete = TRUE;
            if (Event_Flags[WITHDRAWAL])
{
memcpy(wrecord, &txn_amt, S_LONG);
status = epc_end_event(API_VERSION, VENDOR, FACILITY_NUMBER,
WITHDRAWAL, &Txn_Handle, 0, wrecord,
S_LONG, 0, 0, 0);
}
}
else
/* Record an overdraft; end the Withdrawal event with a txn_amt of 0 */
/* to show that a transaction really didn't happen */
{
ATM_ROLLBACK; /* cancel transaction */
            if (Event_Flags[OVERDRAFT])
{
memcpy(orecord, &txn_amt, S_LONG);
status = epc_event(API_VERSION, VENDOR, FACILITY_NUMBER,
OVERDRAFT, 0, orecord, S_LONG, 0, 0, 0);
}
            if (Event_Flags[WITHDRAWAL])
{
memset(wrecord, 0, S_LONG);
status = epc_end_event(API_VERSION, VENDOR, FACILITY_NUMBER,
WITHDRAWAL, &Txn_Handle, 0, wrecord,
S_LONG, 0, 0, 0);
}
            DISPLAY("\nBalance insufficient for withdrawal\n");
}
}
else /* txn_amt = 0, cancel */
txn_complete = TRUE;
} while (!txn_complete);                         /* end of do */
status = epc_remove_reg_id(API_VERSION, VENDOR, FACILITY_NUMBER, 
Version, Regist_ID, 1);
free(wrecord);
free(orecord);
return;
}
/*-----------------------------------------------------------------------------
MAKE_TRANSFER
     Transfer money from one account to other.  Destination account might not
be in this bank.
-----------------------------------------------------------------------------*/
void MAKE_TRANSFER (acct_num)
long acct_num;
{
long status;
char line[MAXLINE];
char txn_complete;
char good_source;
long acct_type;
char good_amount;
long txn_amt = 0;
long dest_num;
char good_dest;
long dest_type;
float acct_bal;
char *trecord, *orecord; /* event records for transfer, overdraft */
char *t_ptr; /* pointer to trecord */
txn_complete = FALSE;
trecord = malloc(S_LONG + S_LONG);
orecord = malloc(S_LONG);
strcpy(Regist_ID, "Transfer");
status = epc_cf_value(API_VERSION, 1, TRANSFER, NULL, NULL);
status = epc_add_reg_id(API_VERSION, VENDOR, FACILITY_NUMBER, Version,
Regist_ID, 1);
do
{
DISPLAY("\n\nAccount Transfer\n\n");
DISPLAY("Transfer from:\n");
DISPLAY("1. Checking\n");
DISPLAY("2. Savings\n");
DISPLAY("\nEnter choice or 0 to cancel: ");
    good_source = FALSE;
do /* get account type */
{
READ(line);
acct_type = atoi(line);
        if ((acct_type < 0) || (acct_type > 2))    /* bad input */
{ DISPLAY("\nInvalid choice. Enter choice: "); }
else
{ good_source = TRUE; } /* valid account type */
    } while (!good_source);
    if (acct_type == 0)                            /* cancel transaction */
{ return; }
    good_amount = FALSE;
while (!good_amount)
{
DISPLAY("\nEnter dollar amount to transfer or 0 to cancel: ");
READ(line);
txn_amt = atoi(line);
        if (txn_amt < 0)
{ DISPLAY("\nInvalid amount."); }
if (txn_amt > 0)
{ good_amount = TRUE; }
if (txn_amt == 0) /* cancel transaction */
{ return; }
}
    DISPLAY("\nEnter destination account number or 0 to cancel: ");
READ(line);
dest_num = atoi(line);
    if (dest_num == 0)                    /* cancel transaction */
{ return; }
    DISPLAY("\nTransfer to:\n");
DISPLAY("1. Checking\n");
DISPLAY("2. Savings\n");
DISPLAY("\nEnter choice or 0 to cancel: ");
    good_dest = FALSE;
do /* get account type for */
{ /* destination account */
READ(line);
dest_type = atoi(line);
        if ((dest_type < 0) || (dest_type > 2))    /* bad input */
{ DISPLAY("\nInvalid choice. Enter choice: "); }
else
{ good_dest = TRUE; } /* valid account type */
    } while (!good_dest);
    if (dest_type == 0)                            /* cancel transaction */
{ return; }
/*----------------------------------------------------------------------------
Now we have good source, destination, amount
-----------------------------------------------------------------------------*/
if (Event_Flags[TRANSFER])
{
t_ptr = trecord;
memset(t_ptr, 0, S_LONG);
t_ptr += S_LONG;
memcpy(t_ptr, &dest_num, S_LONG);
status = epc_start_event(API_VERSION, VENDOR, FACILITY_NUMBER,
TRANSFER, &Txn_Handle, 0, trecord,
(S_LONG + S_LONG), 0, 0, 0);
}
    ATM_START_RW();
if (acct_type == 1)
{ acct_bal = ATM_CHK_BALANCE(acct_num); }
if (acct_type == 2)
{ acct_bal = ATM_SAV_BALANCE(acct_num); }
    if (acct_bal > txn_amt)                       /* sufficient funds */
{
if (acct_type == 1)
{ ATM_CHK_WITHDRAWAL(acct_num, txn_amt, acct_bal); }
if (acct_type == 2)
{ ATM_SAV_WITHDRAWAL(acct_num, txn_amt, acct_bal); }
    /* Returns 0 if the account number is not for this branch of the bank */
dest_num = ATM_VALID_XFER_ACCT(dest_num);
if (dest_num)
{
if (dest_type == 1)
{ ATM_CHK_DEPOSIT(dest_num, txn_amt); }
if (dest_type == 2)
{ ATM_SAV_DEPOSIT(dest_num, txn_amt); }
}
        ATM_COMMIT();
        if (Event_Flags[TRANSFER])
{
t_ptr = trecord;
memcpy(t_ptr, &txn_amt, S_LONG);
t_ptr += S_LONG;
memcpy(t_ptr, &dest_num, S_LONG);
status = epc_end_event(API_VERSION, VENDOR, FACILITY_NUMBER,
TRANSFER, &Txn_Handle, 0, trecord,
(S_LONG + S_LONG), 0, 0, 0);
}
txn_complete = TRUE;
}
else /* overdraft */
{
ATM_ROLLBACK; /* cancel transaction */
        if (Event_Flags[OVERDRAFT])
{
memcpy(orecord, &txn_amt, S_LONG);
status = epc_event(API_VERSION, VENDOR, FACILITY_NUMBER, OVERDRAFT,
0, orecord, S_LONG, 0, 0, 0);
}
        if (Event_Flags[TRANSFER])
{
t_ptr = trecord;
memset(t_ptr, 0, S_LONG);
t_ptr += S_LONG;
memcpy(t_ptr, &dest_num, S_LONG);
status = epc_end_event(API_VERSION, VENDOR, FACILITY_NUMBER,
TRANSFER, &Txn_Handle, 0, trecord,
(S_LONG + S_LONG), 0, 0, 0);
}
        DISPLAY("\nInsufficient funds.\n");
}
} while (!txn_complete);
status = epc_remove_reg_id(API_VERSION, VENDOR, FACILITY_NUMBER, 
Version, Regist_ID, 1);
free(trecord);
free(orecord);
return;
}
/*-----------------------------------------------------------------------------
MAKE_QUICK_WITHDRAWAL
     Withdraw $50 from checking.  If withdrawal is more than balance, record 
an overdraft event.
-----------------------------------------------------------------------------*/
long MAKE_QUICK_WITHDRAWAL (acct_num)
long acct_num;
{
long status;
float chk_bal;
long good_txn;
long txn_amt = 50;
char *qrecord, *orecord;
qrecord = malloc(S_LONG);
orecord = malloc(S_LONG);
strcpy(Regist_ID, "Quick Withdrawal");
status = epc_cf_value(API_VERSION, 1, QUICK_WITHDRAW, NULL, NULL);
status = epc_add_reg_id(API_VERSION, VENDOR, FACILITY_NUMBER, Version,
Regist_ID, 1);
if (Event_Flags[QUICK_WITHDRAW])
{
memset(qrecord, 0, S_LONG);
status = epc_start_event(API_VERSION, VENDOR, FACILITY_NUMBER,
QUICK_WITHDRAW, &Txn_Handle, 0, qrecord,
S_LONG, 0, 0, 0);
}
ATM_START_RW();
chk_bal = ATM_CHK_BALANCE(acct_num);
if (chk_bal > 50)                              /* sufficient funds */
{
ATM_CHK_WITHDRAWAL(acct_num, txn_amt, chk_bal);
ATM_COMMIT();
    if (Event_Flags[QUICK_WITHDRAW])
{
memcpy(qrecord, &txn_amt, S_LONG);
status = epc_end_event(API_VERSION, VENDOR, FACILITY_NUMBER,
QUICK_WITHDRAW, &Txn_Handle, 0, qrecord,
S_LONG, 0, 0, 0);
}
good_txn = TRUE;
}
else /* overdraft */
{
ATM_ROLLBACK; /* cancel transaction */
    if (Event_Flags[OVERDRAFT])
{
memcpy(orecord, &txn_amt, S_LONG);
status = epc_event(API_VERSION, VENDOR, FACILITY_NUMBER, OVERDRAFT,
0, orecord, S_LONG, 0, 0, 0);
}
    if (Event_Flags[QUICK_WITHDRAW])
{
memset(qrecord, 0, S_LONG);
status = epc_end_event(API_VERSION, VENDOR, FACILITY_NUMBER,
QUICK_WITHDRAW, &Txn_Handle, 0, qrecord,
S_LONG, 0, 0, 0);
}
DISPLAY("\nInsufficient funds.\n");
good_txn = FALSE;
}
status = epc_remove_reg_id(API_VERSION, VENDOR, FACILITY_NUMBER, 
Version, Regist_ID, 1);
free(qrecord);
free(orecord);
return (good_txn);
}
/*-----------------------------------------------------------------------------
ATM_VALID_ACCT_NUM
     Return acct_num if found in database; otherwise, return -1
-----------------------------------------------------------------------------*/
long ATM_VALID_ACCT_NUM (acct_num)
long acct_num;
{
EXEC SQL BEGIN DECLARE SECTION;
long sav_acct_num = -1;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT account_number INTO :sav_acct_num 
FROM savings WHERE account_number = :acct_num;
return (sav_acct_num);
}
/*-----------------------------------------------------------------------------
ATM_VALID_XFER_ACCT
     Return acct_num if found in database; otherwise, return 0
-----------------------------------------------------------------------------*/
long ATM_VALID_XFER_ACCT (acct_num)
long acct_num;
{
char acct_found = FALSE;
char stop_looking = FALSE;
EXEC SQL BEGIN DECLARE SECTION;
long sav_acct_num;
EXEC SQL END DECLARE SECTION;
EXEC SQL DECLARE xfer_acct_cursor CURSOR FOR
SELECT account_number FROM savings;
EXEC SQL OPEN xfer_acct_cursor;
while (!stop_looking)
{
EXEC SQL FETCH xfer_acct_cursor INTO :sav_acct_num;
if (sav_acct_num == acct_num)
{
acct_found = TRUE;
stop_looking = TRUE;
}
if (SQLCODE > 0) /* end of cursor */
{
stop_looking = TRUE;
}
}
EXEC SQL CLOSE xfer_acct_cursor;
if (acct_found)
{ return(sav_acct_num); }
else
{ return (0); }
}
/*-----------------------------------------------------------------------------
ATM_SAV_BALANCE
     Return savings account balance for account number
-----------------------------------------------------------------------------*/
float ATM_SAV_BALANCE (acct_num)
long acct_num;
{
EXEC SQL BEGIN DECLARE SECTION;
float sav_bal = 0;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT balance INTO :sav_bal
FROM savings WHERE account_number = :acct_num;
return (sav_bal);
}
/*-----------------------------------------------------------------------------
ATM_CHK_BALANCE
     Return checking account balance for account number
-----------------------------------------------------------------------------*/
float ATM_CHK_BALANCE (acct_num)
long acct_num;
{
EXEC SQL BEGIN DECLARE SECTION;
float chk_bal = 0;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT balance INTO :chk_bal
FROM checking WHERE account_number = :acct_num;
return (chk_bal);
}
/*-----------------------------------------------------------------------------
ATM_SAV_DEPOSIT
     Add amount to balance in savings account
-----------------------------------------------------------------------------*/
void  ATM_SAV_DEPOSIT (acct_num, amount)
long acct_num;
long amount;
{
EXEC SQL BEGIN DECLARE SECTION;
float prev_bal;
EXEC SQL END DECLARE SECTION;
prev_bal = ATM_SAV_BALANCE(acct_num);
EXEC SQL UPDATE savings SET balance = (:prev_bal + :amount) 
WHERE account_number = :acct_num;
}
/*-----------------------------------------------------------------------------
ATM_CHK_DEPOSIT
     Add amount to balance in checking account 
-----------------------------------------------------------------------------*/
void  ATM_CHK_DEPOSIT (acct_num, amount)
long acct_num;
long amount;
{
EXEC SQL BEGIN DECLARE SECTION;
float prev_bal;
EXEC SQL END DECLARE SECTION;
prev_bal = ATM_CHK_BALANCE(acct_num);
EXEC SQL UPDATE checking SET balance = (:prev_bal + :amount) 
WHERE account_number = :acct_num;
}
/*-----------------------------------------------------------------------------
ATM_SAV_WITHDRAWAL
     Subtract amount from balance in savings account; assumes amount is less 
than balance (we checked balance before calling)
-----------------------------------------------------------------------------*/
void  ATM_SAV_WITHDRAWAL (acct_num, amount, prev_bal)
long acct_num;
long amount;
float prev_bal;
{
EXEC SQL UPDATE savings SET balance = (:prev_bal - :amount) 
WHERE account_number = :acct_num;
}
/*-----------------------------------------------------------------------------
ATM_CHK_WITHDRAWAL
     Subtract amount from balance in checking account; assumes amount is less 
than balance (we checked balance before calling)
-----------------------------------------------------------------------------*/
void  ATM_CHK_WITHDRAWAL (acct_num, amount, prev_bal)
long acct_num;
long amount;
float prev_bal;
{
EXEC SQL UPDATE checking SET balance = (:prev_bal - :amount) 
WHERE account_number = :acct_num;
}
/*-----------------------------------------------------------------------------
ATM_START_RW
     Start read-write transaction
-----------------------------------------------------------------------------*/
void  ATM_START_RW ()
{
EXEC SQL SET TRANSACTION READ WRITE;
}
/*-----------------------------------------------------------------------------
ATM_START_RO
     Start read-only transaction
-----------------------------------------------------------------------------*/
void  ATM_START_RO ()
{
EXEC SQL SET TRANSACTION READ ONLY;
}
/*-----------------------------------------------------------------------------
ATM_COMMIT
     Commit transaction
-----------------------------------------------------------------------------*/
void  ATM_COMMIT ()
{
EXEC SQL COMMIT;
}
/*-----------------------------------------------------------------------------
ATM_ROLLBACK
     Rollback transaction
-----------------------------------------------------------------------------*/
void  ATM_ROLLBACK ()
{
EXEC SQL ROLLBACK;
}




Go to previous file in sequence Go to next file in sequence
Prev Next
Oracle
Copyright © 1996 Oracle Corporation.
All Rights Reserved.
Go to Product Documentation Library
Library
Go to books for this product
Product
Go to Contents for this book
Contents
Go to Index
Index