Example: Delete trigger written in ILE C

This example shows the running of the ILE C trigger program when a record is deleted in the ATMTRANS file.

Note: 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:

ATMID ACCTID TCODE AMOUNT
10001 20001 W 25.00
10002 20002 W 900.00
After being deleted from the ATMTRANS file by the delete trigger program, the ATMS file and the ACCTS file contain the following data:
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.        */
 /*                                                                */
 /*   Note: 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                                       */
/*                                                              */
/****************************************************************/
/****************************************************************/
/*   Note: 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;