389 lines
18 KiB
HTML
389 lines
18 KiB
HTML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html
|
|
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html lang="en-us" xml:lang="en-us">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
<meta name="security" content="public" />
|
|
<meta name="Robots" content="index,follow" />
|
|
<meta http-equiv="PICS-Label" content='(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))' />
|
|
<meta name="DC.Type" content="reference" />
|
|
<meta name="DC.Title" content="Example: Delete trigger written in ILE C" />
|
|
<meta name="abstract" content="This example shows the running of the ILE C trigger program when a record is deleted in the ATMTRANS file." />
|
|
<meta name="description" content="This example shows the running of the ILE C trigger program when a record is deleted in the ATMTRANS file." />
|
|
<meta name="DC.Relation" scheme="URI" content="rbaforzahftri.htm" />
|
|
<meta name="copyright" content="(C) Copyright IBM Corporation 1998, 2006" />
|
|
<meta name="DC.Rights.Owner" content="(C) Copyright IBM Corporation 1998, 2006" />
|
|
<meta name="DC.Format" content="XHTML" />
|
|
<meta name="DC.Identifier" content="rbaforzahftrl" />
|
|
<meta name="DC.Language" content="en-us" />
|
|
<!-- All rights reserved. Licensed Materials Property of IBM -->
|
|
<!-- US Government Users Restricted Rights -->
|
|
<!-- Use, duplication or disclosure restricted by -->
|
|
<!-- GSA ADP Schedule Contract with IBM Corp. -->
|
|
<link rel="stylesheet" type="text/css" href="./ibmdita.css" />
|
|
<link rel="stylesheet" type="text/css" href="./ic.css" />
|
|
<title>Example: Delete trigger written in ILE C</title>
|
|
</head>
|
|
<body id="rbaforzahftrl"><a name="rbaforzahftrl"><!-- --></a>
|
|
<!-- Java sync-link --><script language="Javascript" src="../rzahg/synch.js" type="text/javascript"></script>
|
|
<h1 class="topictitle1">Example: Delete trigger written in ILE C</h1>
|
|
<div><p>This example shows the running of the ILE C trigger program when
|
|
a record is deleted in the ATMTRANS file. </p>
|
|
<div class="section"><div class="note"><span class="notetitle">Note:</span> By using the code examples, you agree to the terms of the <a href="codedisclaimer.htm">Code license and disclaimer information</a>.</div>
|
|
</div>
|
|
<div class="section"><div class="p"><pre> /**************************************************************/
|
|
/* 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 */</pre>
|
|
</div>
|
|
</div>
|
|
<div class="section"><p>After the deletion by the application, the ATMTRANS file contains
|
|
the following data: </p>
|
|
</div>
|
|
<div class="section"><div class="p">
|
|
<table cellpadding="4" cellspacing="0" border="1" class="tableborder"><tr><td>
|
|
<table cellpadding="4" cellspacing="0" summary="" width="100%" border="0"><thead align="left"><tr><th align="center" valign="bottom" width="25%" id="d0e36">ATMID</th>
|
|
<th align="center" valign="bottom" width="25%" id="d0e38">ACCTID</th>
|
|
<th align="center" valign="bottom" width="25%" id="d0e40">TCODE</th>
|
|
<th align="center" valign="bottom" width="25%" id="d0e42">AMOUNT</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody><tr><td align="center" valign="top" width="25%" headers="d0e36 ">10001</td>
|
|
<td align="center" valign="top" width="25%" headers="d0e38 ">20001</td>
|
|
<td align="center" valign="top" width="25%" headers="d0e40 ">W</td>
|
|
<td align="center" valign="top" width="25%" headers="d0e42 ">25.00</td>
|
|
</tr>
|
|
<tr><td align="center" valign="top" width="25%" headers="d0e36 ">10002</td>
|
|
<td align="center" valign="top" width="25%" headers="d0e38 ">20002</td>
|
|
<td align="center" valign="top" width="25%" headers="d0e40 ">W</td>
|
|
<td align="center" valign="top" width="25%" headers="d0e42 ">900.00</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td></tr></table>
|
|
After being deleted from the ATMTRANS file by the delete trigger program,
|
|
the ATMS file and the ACCTS file contain the following data:
|
|
<table cellpadding="4" cellspacing="0" border="1" class="tableborder"><tr><td>
|
|
<table cellpadding="4" cellspacing="0" summary="" width="100%" border="0"><thead align="left"><tr><th align="center" valign="bottom" width="33.33333333333333%" id="d0e71">ATMN</th>
|
|
<th align="center" valign="bottom" width="33.33333333333333%" id="d0e73">LOCAT</th>
|
|
<th align="center" valign="bottom" width="33.33333333333333%" id="d0e75">ATMAMT</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody><tr><td align="center" valign="top" width="33.33333333333333%" headers="d0e71 ">10001</td>
|
|
<td align="center" valign="top" width="33.33333333333333%" headers="d0e73 ">MN</td>
|
|
<td align="center" valign="top" width="33.33333333333333%" headers="d0e75 ">275.00</td>
|
|
</tr>
|
|
<tr><td align="center" valign="top" width="33.33333333333333%" headers="d0e71 ">10002</td>
|
|
<td align="center" valign="top" width="33.33333333333333%" headers="d0e73 ">MN</td>
|
|
<td align="center" valign="top" width="33.33333333333333%" headers="d0e75 ">750.00</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td></tr></table>
|
|
|
|
<table cellpadding="4" cellspacing="0" border="1" class="tableborder"><tr><td>
|
|
<table cellpadding="4" cellspacing="0" summary="" width="100%" border="0"><thead align="left"><tr><th align="center" valign="bottom" width="33.33333333333333%" id="d0e100">ACCTN</th>
|
|
<th align="center" valign="bottom" width="33.33333333333333%" id="d0e102">BAL</th>
|
|
<th align="center" valign="bottom" width="33.33333333333333%" id="d0e104">ACTACC</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody><tr><td align="center" valign="top" width="33.33333333333333%" headers="d0e100 ">20001</td>
|
|
<td align="center" valign="top" width="33.33333333333333%" headers="d0e102 ">175.00</td>
|
|
<td align="center" valign="top" width="33.33333333333333%" headers="d0e104 ">A</td>
|
|
</tr>
|
|
<tr><td align="center" valign="top" width="33.33333333333333%" headers="d0e100 ">20002</td>
|
|
<td align="center" valign="top" width="33.33333333333333%" headers="d0e102 ">350.00</td>
|
|
<td align="center" valign="top" width="33.33333333333333%" headers="d0e104 ">A</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td></tr></table>
|
|
<pre> /******************************************************************/
|
|
/* 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);
|
|
}
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
<div class="section"><div class="p"> <pre>/****************************************************************/
|
|
/* 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;</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="familylinks">
|
|
<div class="parentlink"><strong>Parent topic:</strong> <a href="rbaforzahftri.htm" title="This topic provides examples of trigger programs written in C, COBOL, and RPG.">Examples: Trigger programs</a></div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html> |