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:

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.        */
 /*                                                                */
 /*   

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