Example: Delete trigger written in ILE C
This trigger program runs after a record is deleted from the ATMTRANS file.
By using the code examples, you agree to the terms of the Code license and disclaimer information.
/**************************************************************/ /* Program Name - DELTRG */ /* This program is called when a delete operation occurs in */ /* the ATMTRANS file. */ /* */ /* This program will delete the records from ATMS and ACCTS */ /* based on the ATM ID and ACCT ID that are passed in from */ /* the trigger buffer. */ /* */ /* The application will delete ATMID 10003 from the ATMTRANS */ /* file. */ /* */ /**************************************************************/ #include <stdio.h> #include <stdlib.h> #include <recio.h> #include "applib/csrc/msghandler" /* message handler include */ #include "qsysinc/h/trgbuf" /* trigger buffer include without*/ /* old and new records */ Qdb_Trigger_Buffer_t *hstruct; /* pointer to the trigger buffer */ char *datapt; #define KEYLEN 5 /**************************************************************/ /* Need to define file structures here since there are non- */ /* character fields in each file. For each non-character */ /* field, C requires boundary alignment. Therefore, a _PACKED */ /* struct should be used in order to access the data that */ /* is passed to the trigger program. */ /* */ /**************************************************************/ /** record area for ATMTRANS **/ _Packed struct rec { char atmid[5]; char acctid[5]; char tcode[1]; char amount[5]; } oldbuf, newbuf; /** record area for ATMS **/ _Packed struct rec1{ char atmn[5]; char locat[2]; char atmamt[9]; } atmfile; /** record area for ACCTS **/ _Packed struct rec2{ char acctn[5]; char bal[9]; char actacc[1]; } accfile; /********************************************************************/ /********************************************************************/ /* Start of the Main Line Code. ************************************/ /********************************************************************/ /********************************************************************/ main(int argc, char **argv) { _RFILE *out1; /* file pointer for ATMS */ _RFILE *out2; /* file pointer for ACCTS */ _RIOFB_T *fb; /* file feedback pointer */ char record[16]; /* record buffer */ _FEEDBACK fc; /* feedback for message handler */ _HDLR_ENTRY hdlr = main_handler; /********************************/ /* active exception handler */ /********************************/ CEEHDLR(&hdlr, NULL, &fc);; /********************************/ /* ensure exception handler OK */ /********************************/ if (fc.MsgNo != CEE0000) { printf("Failed to register exception handler.\n"); exit(99); } /* set pointer to the input parameter */ hstruct = (Qdb_Trigger_Buffer_t *)argv[1]; datapt = (char *) hstruct; /* Copy old and new record from the input parameter */ if ((strncmp(hstruct ->trigger_event,"2",1)== 0)|| /* delete event */ (strncmp(hstruct -> trigger_event,"3",1)== 0)) /* update event */ { obufoff = hstruct ->old_record_offset; memcpy(&oldbuf,datapt+obufoff,; hstruct->old_record_len); } if ((strncmp(hstruct -> trigger_event,"1",1)== 0) || /* insert event */ (strncmp(hstruct -> trigger_event,"3",1)== 0)) /* update event */ { nbufoff = hstruct ->new_record_offset; memcpy(&newbuf,datapt+nbufoff,; hstruct->new_record_len); } /*****************************************************/ /* Open ATM and ACCTS files */ /* */ /* Check the application's commit lock level. If it */ /* runs under commitment control, then open both */ /* files with commitment control. Otherwise, open */ /* both files without commitment control. */ /*****************************************************/ if(strcmp(hstruct->commit_lock_level,"0") == 0) /* no commit */ { if ((out1=_Ropen("APPLIB/ATMS","rr+")) == NULL) { printf("Error opening ATM file"); exit(1); } if ((out2=_Ropen("APPLIB/ACCTS","rr+")) == NULL) { printf("Error opening ACCTS file"); exit(1); } } else /* with commitment control */ { if ((out1=_Ropen("APPLIB/ATMS","rr+,commit=Y")) == NULL) { printf("Error opening ATMS file"); exit(1); } if ((out2=_Ropen("APPLIB/ACCTS","rr+,commit=Y")) == NULL) { printf("Error opening ACCTS file"); exit(1); } } /* Delete the record based on the input parameter */ fb =_Rlocate(out1,&oldbuf.atmid,KEYLEN,__DFT); if (fb->num_bytes != 1) { printf("record not found in ATMS\n"); _Rclose(out1); exit(1); } _Rdelete(out1); /* delete record from ATMS */ _Rclose(out1); fb =_Rlocate(out2,&oldbuf.acctid,KEYLEN,__DFT); if (fb->num_bytes != 1) { printf("record not found in ACCOUNTS\n"); _Rclose(out2); exit(1); } _Rdelete(out2); /* delete record from ACCOUNTS */ _Rclose(out2); } /* end of main */After the deletion by the application, the ATMTRANS file contains the following data:
After being deleted from the ATMTRANS file by the delete trigger program, the ATMS file and the ACCTS file contain the following data:
ATMID ACCTID TCODE AMOUNT 10001 20001 W 25.00 10002 20002 W 900.00
ATMN LOCAT ATMAMT 10001 MN 275.00 10002 MN 750.00
ACCTN BAL ACTACC 20001 175.00 A 20002 350.00 A /******************************************************************/ /* INCLUDE NAME : MSGHANDLER */ /* */ /* DESCRIPTION : Message handler to signal an exception message*/ /* to the caller of this trigger program. */ /* */ /*This message handler is a user defined routine. */ /* */ /******************************************************************/ #include <stdio.h> #include <stdlib.h> #include <recio.h> #include <leawi.h> #pragma linkage (QMHSNDPM, OS) void QMHSNDPM(char *, /* Message identifier */ void *, /* Qualified message file name */ void *, /* Message data or text */ int, /* Length of message data or text */ char *, /* Message type */ char *, /* Call message queue */ int, /* Call stack counter */ void *, /* Message key */ void *, /* Error code */ ...); /* Optionals: length of call message queue name Call stack entry qualification display external messages screen wait time */ /*********************************************************************/ /******** This is the start of the exception handler function. */ /*********************************************************************/ void main_handler(_FEEDBACK *cond, _POINTER *token, _INT4 *rc, _FEEDBACK *new) { /****************************************/ /* Initialize variables for call to */ /* QMHSNDPM. */ /* User defines any message ID and */ /* message file for the following data */ /****************************************/ char message_id[7] = "TRG9999"; char message_file[20] = "MSGF LIB1 "; char message_data[50] = "Trigger error "; int message_len = 30; char message_type[10] = "*ESCAPE "; char message_q[10] = "_C_pep "; int pgm_stack_cnt = 1; char message_key[4]; /****************************************/ /* Declare error code structure for */ /* QMHSNDPM. */ /****************************************/ struct error_code { int bytes_provided; int bytes_available; char message_id[7]; } error_code; error_code.bytes_provided = 15; /****************************************/ /* Set the error handler to resume and */ /* mark the last escape message as */ /* handled. */ /****************************************/ *rc = CEE_HDLR_RESUME; /****************************************/ /* Send my own *ESCAPE message. */ /****************************************/ QMHSNDPM(message_id, &message_file, &message_data, message_len, message_type, message_q, pgm_stack_cnt, &message_key, &error_code ); /****************************************/ /* Check that the call to QMHSNDPM */ /* finished correctly. */ /****************************************/ if (error_code.bytes_available != 0) { printf("Error in QMHOVPM : %s\n", error_code.message_id); } }
/****************************************************************/ /* INCLUDE NAME : TRGBUF */ /* */ /* DESCRIPTION : The input trigger buffer structure for the */ /* user's trigger program. */ /* */ /* LANGUAGE : ILE C */ /* */ /****************************************************************/ /****************************************************************/ /*The following type definition only defines the fixed */ /* portion of the format. The data area of the original */ /* record, null byte map of the original record, the */ /* new record, and the null byte map of the new record */ /* is varying length and immediately follows what is */ /* defined here. */ /****************************************************************/ typedef _Packed struct Qdb_Trigger_Buffer { char file_name[10]; char library_name[10]; char member_name[10]; char trigger_event[1]; char trigger_time[1]; char commit_lock_level[1]; char reserved_1[3]; int data_area_ccsid; char reserved_2]8]; int old_record_offset; int old_record_len; int old_record_null_byte_map; int old_record_null_byte_map_len; int new_record_offset; int new_record_len; int new_record_null_byte_map; int new_record_null_byte_map_len; } Qdb_Trigger_Buffer_t;
Parent topic:
Examples: Trigger programs