You've got a dilemma. The accounts payable manager tells you she needs to know immediately when a client's credit balance exceeds $5,000, but she's not hooked up to the company AS/400, only to the PC LAN. She doesn't want a report, because she needs to know quickly. It certainly wouldn't be efficient for someone to call her when a credit balance goes too high because that would take two peoples' time and a high credit balance may get mistakenly overlooked. What's the solution? Well, the Messaging Application Program Interface (MAPI), of course. E-mail is a good way to deliver the notification, and MAPI can make it easier for you.
In "Get Wired with MAPI" (MC, September 1995), I described MAPI and discussed some of the things that you can do with it. This month, you'll use MAPI with other AS/400 facilities to create an application that could serve as the framework for a customized system for your company. You will create examples that are generic enough to run on any AS/400 with V3R1. In the example, I used the QCUSTCDT file in the QIWS library because that file is on every AS/400 that has PC Support or Client Access, but, of course, you can change the example to work with any file.
You will use three enabling technologies to accomplish your goal. There are many ways to achieve what you want to do?the methods chosen are just examples. The technologies you will use are triggers (provided in V3R1 of DB2/400), Client Access data queue transfer, and MAPI calls from Visual Basic (VB).
You create the trigger so that you receive notification when a record is added to or changed in the QCUSTCDT file. The trigger is simply an RPG program that puts the updated customer record into a data queue. For more information on triggers, see "Referential Integrity & Triggers in DB2/400" (MC, November 1994).
On the client (PC) side, you create a program using VB to retrieve the record from the data queue and to automatically create and send an E-mail message notifying the AP manager of the high credit amount. I used VB for example purposes only. MAPI can be utilized from any language capable of calling a Windows Dynamic Link Library (DLL), which includes most mainstream Windows languages. 1 shows the relationships between the different technology components that we will use.
On the client (PC) side, you create a program using VB to retrieve the record from the data queue and to automatically create and send an E-mail message notifying the AP manager of the high credit amount. I used VB for example purposes only. MAPI can be utilized from any language capable of calling a Windows Dynamic Link Library (DLL), which includes most mainstream Windows languages. Figure 1 shows the relationships between the different technology components that we will use.
The Visual Basics
The VB program is actually fairly simple. There are two main modules to this program?MAPILIB.BAS and MAPIDEMO.FRM. 2 shows the MAPILIB.BAS module. MAPILIB.BAS is provided by Microsoft in the Microsoft Mail Software Development Kit (SDK) to help VB programmers declare the appropriate functions, variables, and constants for implementing MAPI. I've modified the file to eliminate code unnecessary for this example.
The VB program is actually fairly simple. There are two main modules to this program?MAPILIB.BAS and MAPIDEMO.FRM. Figure 2 shows the MAPILIB.BAS module. MAPILIB.BAS is provided by Microsoft in the Microsoft Mail Software Development Kit (SDK) to help VB programmers declare the appropriate functions, variables, and constants for implementing MAPI. I've modified the file to eliminate code unnecessary for this example.
3 shows the functional portion of the MAPIDEMO.FRM VB program. I put the main logic behind a VB timer control. You can set the timer control's Interval property to run the Timer event code at predetermined intervals, so I set the timer's interval to 60,000 milliseconds, or 1 minute. Because the Timer event fires every minute, the longest delay between the time a customer exceeds the $5,000 credit limit and the time the AP manager is notified is just a couple of minutes.
Figure 3 shows the functional portion of the MAPIDEMO.FRM VB program. I put the main logic behind a VB timer control. You can set the timer control's Interval property to run the Timer event code at predetermined intervals, so I set the timer's interval to 60,000 milliseconds, or 1 minute. Because the Timer event fires every minute, the longest delay between the time a customer exceeds the $5,000 credit limit and the time the AP manager is notified is just a couple of minutes.
There are three main sections of the VB program. The FORM_LOAD sub-routine is executed first when the program runs. This subroutine sets up the data queue functions and starts the MAPI session. It also sets the timer control interval and enables the timer control. The TIMER1_TIMER routine is called when the timer control's interval has expired. In this routine, the data queue is read and, if there is a new entry, a message is created and sent by the MailAPMessage subroutine. When the program ends, the FORM_UNLOAD subroutine runs and logs the program off the MAPI session.
Since the VBprogram ideally runs as a standalone application requiring no user intervention, the program needs to explicitly log on to the mail system before the message is sent. Otherwise, everytime it sends the message using the MAPI functions, it presents the user with a dialog box requiring him to log on. If the program logs on explicitly, it remains logged on until it explicitly logs off. Since it needs to log on only once, I put the code to log on to the mail system in the FORM_LOAD procedure.
When you log on to a MAPI session, one of the parameters that gets set at login is the session ID. The session ID is a numeric variable that represents a "handle" to a particular mail session. After logging in, you can use the session ID when calling other MAPI functions to let the system know which session you are referring to. It is possible to have more than one MAPI session going at a time, and this number is important in those circumstances. I saved the session ID in the global variable glSession.
Message in a Sub
The VB subroutine that creates and sends the message to the MAPI system is the MailAPMessage routine. In this routine, the MAPISendMail function actually sends the message, but you need to set several data structures first. The data structures are defined in the MAPILIB.BAS module shown in 2. These structures provide the API functions with information regarding the recipients of the message and any possible file attachments, as well as other necessary information.
The VB subroutine that creates and sends the message to the MAPI system is the MailAPMessage routine. In this routine, the MAPISendMail function actually sends the message, but you need to set several data structures first. The data structures are defined in the MAPILIB.BAS module shown in Figure 2. These structures provide the API functions with information regarding the recipients of the message and any possible file attachments, as well as other necessary information.
The MAPIMessage user-defined type holds the message-specific information. The relevant elements in this structure are the subject (Subject), the note text (NoteText), the recipient count (RecipCount), and the file count (FileCount). The Subject element is the subject line of the message, limited to 256 characters. The NoteText element is the body of the message. This item's size limitation depends on your vendor's particular implementation of MAPI. The RecipCount element contains the number of message recipients, and the FileCount element contains the number of file attachments for this message.
The MAPIRecip structure defines information about the message recipients. The relevant data elements in this structure are the recipient's class (RecipClass), the recipient's name (Name), and, optionally, the recipient's address (Address).
For outbound messages, the recipient's class indicates what type of recipient is referred to by this structure. Valid recipient types are originator (MAPI_ORIG), main recipient (MAPI_TO), courtesy copy recipient (MAPI_CC), and blind courtesy copy recipient (MAPI_BCC). A blind courtesy copy recipient receives a copy of the message, but there is no indication to other recipients that someone else received the message (a nice way to get people in trouble).
The Name element of the MAPIRecip structure is the recipient's name as displayed in the post office address book.
The Address, an optional field, is a provider-specific means of identifying a recipient. Here, you can enter the address of a recipient that is not in your post office address book, and the message goes to this address if the systems are connected correctly.
The MAPIFile structure is not used in this example, but if you need to send files with a message, this structure tells MAPI where the file is. The Position element determines where in the message the file is placed, the PathName element points to the path where the file is located, and the FileName element contains the name of the file. The FileType element tells the operating system what type of file the attachment is so the system can use the proper program to open the file. This element is usually set to "" because Windows determines which application created the file by the file name's extension.
You can define the MAPIRecip and the MAPIFile structures as arrays to allow multiple recipients and multiple file attachments. If you need multiple recipients or file attachments, simply pass in the appropriate array's first element when you call MAPISendMail. When you pass in the first element and a count, the MAPI functions process each element up to the element number specified by the count. Be sure you set the RecipCount and the FileCount elements of the MAPIMessage type to the correct number.
Once you've set all the structures properly, sending the message is a simple call to the MAPISendMail function. This function actually sends the message to the messaging system and returns an error code if there is a problem. You can check the return code for an error, and, if there is one, call a routine that displays a message indicating what the problem is.
When you are done, you must log off the mail system by calling the MAPILogoff function in the FORM_UNLOAD sub. The main parameter to the MAPILogoff function is the session ID; it identifies which session we are logging off. We stored the session ID glSession variable in the FORM_LOAD subroutine when we logged on to the MAPI session.
Reading the Data Queue
"Client Access Data Queue APIs" (MC, March 1995) detailed the use of VB to retrieve values from AS/400 data queues. To retrieve the data from our data queue, I borrowed some of the following techniques from that article.
You must declare any functions in EHNDQW.DLL before you can call them. The functions you need are EHNDQ_SetMode and EHNDQ_Receive. The EHNDQ_SetMode function tells the data queue APIs to translate between EBCDIC and ASCII, and the EHNDQ_Receive retrieves the data from the data queue.
Call the EHNDQ_SetMode function in your FORM_LOAD routine, because you only need to execute it once at the beginning of the program. The code that reads the data queue is in the TIMER1_TIMER routine. The EHNDQ_Receive function is called only once every time this function is executed. For each entry in the data queue, the program extracts the customer name and sends a message to the AP manager by the MailAPMessage subroutine.
In the example, the program reads the data queue only a single time every minute. Ideally, you should read all entries on the data queue every minute, in case more than one customer goes over the $5,000 limit in a single minute. I'll leave that for you to implement.
Creating the Trigger
The trigger program captures changes to the QCUSTCDT file. Create the trigger on the QCUSTCDT file in the QIWS library. For this example, you apply the trigger to both the add and update database operations because you want to know when a user adds new data or changes existing data. The program shown in 4 is called from both triggers. To create the trigger that fires when a user adds records to the QCUSTCDT file, you enter the following command:
The trigger program captures changes to the QCUSTCDT file. Create the trigger on the QCUSTCDT file in the QIWS library. For this example, you apply the trigger to both the add and update database operations because you want to know when a user adds new data or changes existing data. The program shown in Figure 4 is called from both triggers. To create the trigger that fires when a user adds records to the QCUSTCDT file, you enter the following command:
ADDPFTRG FILE(QIWS/QCUSTCDT) + TRGTIME(*AFTER) + TRGEVENT(*INSERT) + PGM(TRG001RG)
To create the trigger that fires when a user changes any record in the QCUSTCDT file, you enter the following command.
ADDPFTRG FILE(QIWS/QCUSTCDT) + TRGTIME(*AFTER) + TRGEVENT(*UPDATE) + PGM(TRG001RG) + TRGUPDCND(*CHANGE)
The trigger program simply takes the data from the new record and places it on the data queue MAPIDQ. Before you can run this program, you must create the data queue using this command:
CRTDTAQ DTAQ(QGPL/MAPIDQ) + MAXLEN(8) TEXT('Data Queue + for MAPI Demonstration')
Looking down the Barrel
The trigger is an ILE RPG program (see 4) that is called whenever a record is added or updated in the QCUSTCDT file. The data structures represent the information available to a trigger program, including the date and time of the modification. It is possible to get an image of what the record looked like before the add or update and what the new field values are after the operation. For now, you are only interested in the new field values, which will end up in the NEWREC data structure. The NEWNAM element of this data structure needs to be put on the MAPIDQ data queue.
The trigger is an ILE RPG program (see Figure 4) that is called whenever a record is added or updated in the QCUSTCDT file. The data structures represent the information available to a trigger program, including the date and time of the modification. It is possible to get an image of what the record looked like before the add or update and what the new field values are after the operation. For now, you are only interested in the new field values, which will end up in the NEWREC data structure. The NEWNAM element of this data structure needs to be put on the MAPIDQ data queue.
The program is actually very simple. After all the declarations, the new record image is simply moved into the data structure. Then, if the value in the credit amount field (NEWCDD) is more than the hard-coded value of $5,000, the QSNDDTAQ API is called to put the NEWNAM field into the data queue. Setting on LR ends the program. Note that the value $5,000 and the library name of the data queue are hard coded into the program for example purposes only. Hard coding values like this is something you of course would never do in the real world?right?
That's all there is to the AS/400 side of this equation. There are only a few lines of code that actually do the work.
Article_Logoff
There are many things you can do with MAPI. I've barely scratched the surface, but I hope I've stimulated your thoughts so you can dream up some interesting solutions to real-world problems. If you do come up with some unique MAPI applications, I'd like to hear about them. Send me an E-mail message.
Brian Singleton is an AS/400 client/server programmer/analyst. He can be reached through Midrange Computing or Internet E-mail at
Automatic Messaging with MAPI
Choose Your MAPI
You can implement MAPI in VB applications a couple of ways. One way is to use the control supplied with the VB Professional Edition (MSMAPI.VBX). This Visual Basic Extension (VBX) has properties and events that allow easy logon, sending, and receiving of E-mail messages. It is a simple implementation, and it shields the developer from any application program interface (API) calls.
Another method of implementing MAPI functionality in a VB program is through the use of the APIs in MAPI.DLL. This method requires declaring the DLL functions and provides no real "interface" for setting parameters, but it does offer some additional functionality.
I chose to use the API method to implement the MAPI functionality in this example. There are a couple of reasons why I would choose this method over the VBX method in a professional application. The first and biggest reason is that if you create a program that uses the MSMAPI.VBX and try to use it on a machine that doesn't have MAPI, the program won't run. There is nothing you can do about it, because VB attempts to load the VBX before any lines of code in your program are run. If the VBX doesn't find MAPI.DLL, the program blows up. This is obviously not acceptable in a program that takes advantage of E-mail if it exists but does not require a mail system to run. Another reason I don't use the MSMAPI.VBX is that it is just one more file to install on the target machine and one more component that could potentially fail.
Before you use any of the API calls, however, you should check for the existence of MAPI.DLL to determine if the user has a mail system installed. Once you've determined that there's a mail system, you're on your way. Microsoft provides a sample VB MAPI module that you can use in your programs. This module contains the declarations for the functions as well as some constants that MAPI uses. You can obtain this module from the Microsoft Mail SDK. I recommend developing MAPI applications without MSMAPI.VBX, and I highly recommend obtaining this SDK to do it. Doing things "the hard way" by using the API calls instead of the VBX gives you more control over the environment and provides greater application stability.
Automatic Messaging with MAPI
Figure 1: Sample System Overview
Automatic Messaging with MAPI
Figure 2: MAPILIB.BAS Module
Option Explicit '----------------------------------------------------------------------- ' Copyright (C) 1993 Microsoft Corporation ' ' You have a royalty-free right to use, modify, reproduce and distribute ' the Sample Application Files (and/or any modified version) in any way ' you find useful, provided that you agree that Microsoft has no warranty, ' obligations or liability for any Sample Application Files. ' ' ----------------------------------------------------------------------- '*************************************************** ' MAPI Message holds information about a message '*************************************************** Type MAPIMessage Reserved As Long Subject As String NoteText As String MessageType As String DateReceived As String ConversationID As String Flags As Long RecipCount As Long FileCount As Long End Type '************************************************ ' MAPIRecip holds information about a message ' originator or recipient '************************************************ Type MapiRecip Reserved As Long RecipClass As Long Name As String Address As String EIDSize As Long EntryID As String End Type '****************************************************** ' MapiFile holds information about file attachments '****************************************************** Type MapiFile Reserved As Long Flags As Long Position As Long PathName As String FileName As String FileType As String End Type '*************************** ' FUNCTION Declarations '*************************** Declare Function MAPILogon Lib "MAPI.DLL" (ByVal UIParam As Long, ByVal User As String, ByVal Password As String, ByVal Flags As Long, ByVal Reserved As Long, Session As Long) As Long Declare Function MAPILogoff Lib "MAPI.DLL" (ByVal Session As Long, ByVal IParam As Long, ByVal Flags As Long, ByVal Reserved As Long) As Long Declare Function MAPISendMail Lib "MAPI.DLL" Alias "BMAPISendMail" (ByVal Session As Long, ByVal UIParam As Long, Message As MAPIMessage, Recipient As MapiRecip, File As MapiFile, ByVal Flags As Long, ByVal Reserved As Long) As Long '************************** ' CONSTANT Declarations '************************** ' Global Const SUCCESS_SUCCESS = 0 Global Const MAPI_USER_ABORT = 1 Global Const MAPI_E_FAILURE = 2 Global Const MAPI_E_LOGIN_FAILURE = 3 Global Const MAPI_E_DISK_FULL = 4 Global Const MAPI_E_INSUFFICIENT_MEMORY = 5 Global Const MAPI_E_BLK_TOO_SMALL = 6 Global Const MAPI_E_TOO_MANY_SESSIONS = 8 Global Const MAPI_E_TOO_MANY_FILES = 9 Global Const MAPI_E_TOO_MANY_RECIPIENTS = 10 Global Const MAPI_E_ATTACHMENT_NOT_FOUND = 11 Global Const MAPI_E_ATTACHMENT_OPEN_FAILURE = 12 Global Const MAPI_E_ATTACHMENT_WRITE_FAILURE = 13 Global Const MAPI_E_UNKNOWN_RECIPIENT = 14 Global Const MAPI_E_BAD_RECIPTYPE = 15 Global Const MAPI_E_NO_MESSAGES = 16 Global Const MAPI_E_INVALID_MESSAGE = 17 Global Const MAPI_E_TEXT_TOO_LARGE = 18 Global Const MAPI_E_INVALID_SESSION = 19 Global Const MAPI_E_TYPE_NOT_SUPPORTED = 20 Global Const MAPI_E_AMBIGUOUS_RECIPIENT = 21 Global Const MAPI_E_MESSAGE_IN_USE = 22 Global Const MAPI_E_NETWORK_FAILURE = 23 Global Const MAPI_E_INVALID_EDITFIELDS = 24 Global Const MAPI_E_INVALID_RECIPS = 25 Global Const MAPI_E_NOT_SUPPORTED = 26 Global Const MAPI_ORIG = 0 Global Const MAPI_TO = 1 Global Const MAPI_CC = 2 Global Const MAPI_BCC = 3 Global Const MAPI_UNREAD = &H1 Global Const MAPI_RECEIPT_REQUESTED = &H2 Global Const MAPI_SENT = &H4 '*********************** ' FLAG Declarations '*********************** Global Const MAPI_LOGON_UI = &H1 Global Const MAPI_NEW_SESSION = &H2 Global Const MAPI_DIALOG = &H8 Global Const MAPI_UNREAD_ONLY = &H20 Global Const MAPI_ENVELOPE_ONLY = &H40 Global Const MAPI_PEEK = &H80 Global Const MAPI_GUARANTEE_FIFO = &H100 Global Const MAPI_BODY_AS_FILE = &H200 Global Const MAPI_AB_NOMODIFY = &H400 Global Const MAPI_SUPPRESS_ATTACH = &H800 Global Const MAPI_FORCE_DOWNLOAD = &H1000 Global Const MAPI_OLE = &H1 Global Const MAPI_OLE_STATIC = &H2 Function GetMAPIErrorText (ByVal errorCode As Integer) As String Dim s As String Select Case errorCode Case MAPI_USER_ABORT s = "The operation was cancelled by the user" Case MAPI_E_FAILURE s = "MAPI failure" Case MAPI_E_LOGIN_FAILURE s = "Login failure" Case MAPI_E_DISK_FULL s = "Disk Full" Case MAPI_E_INSUFFICIENT_MEMORY s = "Insufficient memory to complete operation" Case MAPI_E_BLK_TOO_SMALL s = "Access denied" Case MAPI_E_TOO_MANY_SESSIONS s = "Too many sessions" Case MAPI_E_TOO_MANY_FILES s = "Too many files" Case MAPI_E_TOO_MANY_RECIPIENTS s = "Too many recipients" Case MAPI_E_ATTACHMENT_NOT_FOUND s = "Attachment not found" Case MAPI_E_ATTACHMENT_OPEN_FAILURE s = "Attachment open failure" Case MAPI_E_ATTACHMENT_WRITE_FAILURE s = "Attachment write failure" Case MAPI_E_UNKNOWN_RECIPIENT s = "Some names could not be matched to names in the address list" Case MAPI_E_BAD_RECIPTYPE s = "Bad recipient type" Case MAPI_E_NO_MESSAGES s = "No messages" Case MAPI_E_INVALID_MESSAGE s = "Invalid message" Case MAPI_E_TEXT_TOO_LARGE s = "Text too large" Case MAPI_E_INVALID_SESSION s = "Invalid session" Case MAPI_E_TYPE_NOT_SUPPORTED s = "Type not supported" Case MAPI_E_AMBIGUOUS_RECIPIENT s = "Some names could not be matched to a name in the address list. Please refine the currently selected name in the list" Case MAPI_E_MESSAGE_IN_USE s = "Message is in use by another process" Case MAPI_E_NETWORK_FAILURE s = "Network Failure" Case MAPI_E_INVALID_EDITFIELDS s = "Invalid Edit Fields" Case MAPI_E_INVALID_RECIPS s = "Invalid Recips" Case MAPI_E_NOT_SUPPORTED s = "MAPI: Not Supported" Case Else ' default to MAPI FAILURE for unknown mapi errors. s = "MAPI failure" End Select GetMAPIErrorText = s End Function
Automatic Messaging with MAPI
Figure 3: MAPIDEMO.FRM VB Program
VERSION 2.00 Begin Form Form1 Caption = "Form1" ClientHeight = 3795 ClientLeft = 1200 ClientTop = 1695 ClientWidth = 5670 Height = 4260 Left = 1140 LinkTopic = "Form1" ScaleHeight = 3795 ScaleWidth = 5670 Top = 1290 Width = 5790 Begin Timer Timer1 Left = 2220 Top = 1656 End End Option Explicit ' Declares for the data queue API functions Declare Function EHNDQ_SetMode Lib "EHNDQW.DLL" (ByVal hWnd As Integer, ByVal sQueueLocation As String, ByVal lMode As Long) As Integer Declare Function EHNDQ_Receive Lib "EHNDQW.DLL" (ByVal hWnd As Integer, ByVal sQueueName As String, ByVal sQueueLocation As String, ByVal lWaitTime As Long, ByVal nSenderID As Integer, ByVal sInputBuffer As String, lDataLength As Long, ByVal sSenderIDInfo As String) As Integer ' Dimension a message user-defined type Dim udtMessage As MAPIMessage Dim udtRecipient As MapiRecip Dim udtFiles As MapiFile Dim glSession As Long Const MB_ICONEXCLAMATION = 48 Sub Form_Load () Dim nRtnCode As Long ' Set the data queue APIs to translate ' between EBCDIC and ASCII nRtnCode = EHNDQ_SetMode(Me.hWnd, "", 1) ' Set the timer timer1.Interval = 60000 timer1.Enabled = True ' Log on to MAPI (Mail must be loaded!) nRtnCode = MAPILogon(0, "AP Robot", "AP Robot", 0, 0, glSession) ' Check for errors If nRtnCode <> 0 Then MsgBox GetMAPIErrorText(nRtnCode), MB_ICONEXCLAMATION, "Mail Error" End If End Sub Sub Form_Unload (Cancel As Integer) Dim nRtnCode As Long ' Log off the mail system nRtnCode = MAPILogoff(glSession, 0, 0, 0) ' Check for errors If nRtnCode <> 0 Then MsgBox GetMAPIErrorText(nRtnCode), MB_ICONEXCLAMATION, "Mail Error" End If End Sub Sub MailAPMessage (sCustomerName As String) '------------------------------------------- ' Send the AP manager a message indicating ' that the customer in sCustomerName has ' a credit balance of over $5k '------------------------------------------- Dim nRtnCode As Long Dim sMsgText As String sMsgText = "The customer " & sCustomerName & " has exceeded a $5k credit balance." ' Set the variables passed to the function udtMessage.Reserved = 0 udtMessage.Subject = "Credit Limit Over $5k" udtMessage.NoteText = sMsgText udtMessage.MessageType = "" udtMessage.RecipCount = 1 udtMessage.FileCount = 0 udtRecipient.Reserved = 0 udtRecipient.RecipClass = MAPI_TO udtRecipient.Name = "AP Manager" udtRecipient.Address = "" ' Send the message nRtnCode = MAPISendMail(glSession, 0, udtMessage, udtRecipient, udtFiles, 0, 0) ' Check for errors If nRtnCode <> 0 Then MsgBox GetMAPIErrorText(nRtnCode), MB_ICONEXCLAMATION, "Mail Error" End If End Sub Sub Timer1_Timer () Dim nRtnCode As Integer Dim sCustomerName As String Dim sInputBuffer As String * 8 Dim lBufferLen As Long Dim sMessage As String * 200 Dim nLen As Integer ' Grab the value from the data queue lBufferLen = Len(sInputBuffer) sInputBuffer = Space$(8) nRtnCode = EHNDQ_Receive(Me.hWnd, "QGPL/MAPIDQ", "", 5, 0, sInputBuffer, lBufferLen, "") If nRtnCode <> 0 Then MsgBox "Data queue receive failure.", MB_ICONEXCLAMATION, "Error" Else ' Extract the customer name and send to sub sCustomerName = Trim$(sInputBuffer) If lBufferLen > 0 Then MailAPMessage sCustomerName End If End If End Sub
Automatic Messaging with MAPI
Figure 4: ILE RPG Trigger Program TRG001RG
*----------------------------------------------------* * Definition of the structure to be received inside * * trigger program - buffer length * *----------------------------------------------------* * THE FIELDS DESCRIPTION: * * FNAME = PHYSICAL FILE NAME * * LNAME = PHYSICAL FILE LIBRARY * * MNAME = MEMBER NAME * * TEVEN = TRIGGER EVENT * * TTIME = TRIGGER TIME * * CMTLCK= COMMIT LOCK LEVEL * * FILL1 = RESERVED * * CCSID = CCSID * * FILL2 = RESERVED * * OLDOFF= OFFSET TO THE ORIGINAL RECORD * * OLDLEN= LENGTH OF THE ORIGINAL RECORD * * ONOFF = OFFSET TO THE ORIGINAL RECORD NULL BYTE MAP* * ONLEN = LENGTH OF THE NULL BYTE MAP * * NOFF = OFFSET TO THE NEW RECORD * * NEWLEN= LENGTH OF THE NEW RECORD * * NNOF = OFFSET TO THE NEW RECORD NULL BYTE MAP * * NNLEN = LENGTH OF THE NULL BYTE MAP * * RESV3 = RESERVED * * OREC = OLD RECORD * * OOMAP = NULL BYTE MAP OF OLD RECORD * * RECORD= NEW RECORD * * NMAP = NULL BYTE MAP OF NEW RECORD * *----------------------------------------------------* D PARM1 DS D FNAME 1 10 D LNAME 11 20 D MNAME 21 30 D TEVEN 31 31 D TTIME 32 32 D CMTLCK 33 33 D FILL1 34 36 D CCSID 37 40B 0 D FILL2 41 48 D OLDOFF 49 52B 0 D OLDLEN 53 56B 0 D ONOFF 57 60B 0 D ONLEN 61 64B 0 D NOFF 65 68B 0 D NEWLEN 69 72B 0 D NNOFF 73 76B 0 D NNLEN 77 80B 0 D RESV3 81 96 D OREC 97 156 D OOMAP 157 167 D RECORD 168 227 D NNMAP 228 236 *--------------------------------------------------* * Definition of the buffer length * *--------------------------------------------------* D PARM2 DS D LENG 1 4B 0 * *--------------------------------------------------* * The new record data structure * *--------------------------------------------------* D NEWREC DS D NEWNUN 1 6 D NEWNAM 7 14 D NEWINI 15 17 D NEWSTR 18 30 D NEWCTY 31 36 D NEWSTE 37 38 D NEWZIP 39 43 0 D NEWCLM 44 47 0 D NEWCCD 48 48 0 D NEWBAL 49 54 2 D NEWCDD 55 60 2 * C *ENTRY PLIST C PARM1 PARM PARM1 C PARM2 PARM PARM2 * C MOVEL RECORD NEWREC * *-----------------------------------------------------* * Put the new record on the data queue if credit * * limit is over $5,000. * *-----------------------------------------------------* * C IF NEWCDD > 5000 C CALL 'QSNDDTAQ' C PARM 'MAPIDQ' DTQNAM 10 C PARM 'QGPL' DTQLIB 10 C PARM 8 LEN 5 0 C PARM NEWNAM C ENDIF * C EVAL *INLR = *ON
LATEST COMMENTS
MC Press Online