Tivoli Service Desk 6.0 Developer's Toolkit Interface Designer Guide
The Common Programming Interface for Communications (CPIC) provides a consistent API for applications that require application-to-application communication. The CPIC interface makes use of SNA's LU 6.2 to create a set of interapplication services, including:
CPIC commands are built into the TSD Script language to extend these services to the TSD Script programmer. CPIC was chosen over the base APPC macros to ensure consistency across platforms.
This section of the book is intended as a guide to TSD Script programmers using CPIC to build TPs. For detailed information on SAA CPIC programming, refer to the IBM manual, Systems Application Architecture Common Programming Interface for Communications Reference, SC26-4399.
CPIC must be installed for any CPIC commands to work. If CPIC is not installed correctly, the use of CPIC commands causes Tivoli Service Desk (TSD) Developer's Toolkit to display an error message indicating that CPIC could not be loaded.
APPC is advanced peer-to-peer communication.
Basic conversation is a conversation type in which applications exchange data in a standard byte stream format. This format contains two-byte length fields (called LLs) which specify the length of the buffer to follow. Each grouping of LL data is called a logical record.
A conversation is the logical connection between two applications using CPIC or APPC to exchange data. There are two types of conversation, mapped, and basic. A conversation connects applications using a session. A CPIC application may converse with an APPC application in the same manner that it converses with another CPIC application.
A DDF (Data Description File) is a file that is used to map the relationship between TSD Script record structures and transmitted byte buffers.
A LU (Logical Unit) is, effectively, a virtual machine. While you may designate each physical machine as a LU, it is also possible to configure multiple LUs in one physical machine. Note that CPIC uses only LU Type 6.2 nodes.
A mapped conversation is a conversation type that allows partners to exchange arbitrary data records in pre-determined formats.
A mode names is used by APPC to designate the properties for the session between the LUs during a conversation. These properties include the class of service.
A node service is a application (or set of applications) that provides basic utility functions for an LU. Services provided include manipulation of side information, application start-up processing, and application-termination processing. OS/2's node services are provided by Communications Manager (CM) or Communications Manager/2 (CM/2).
Partners are two CPIC applications that exchange data over CPIC conversations.
CPIC conversations can be full duplex. This means that at any given period during a CPIC conversation, one partner has permission to send and the other partner is in receive state (meaning it is ready to receive the data). A application that is in receive state can issue a request to send when it needs to send data. The partner is notified of this request, and the requesting application receives notification in the StatusReceived parameter.
SDN (Symbolic Destination Name) is a CPIC configuration name in Communications Manager/2 that allows a application to indicate a set of attributes to be used for a conversation allocation request.
A session is a logical connection between two LUs. LUs communicate through sessions.
Initialization information used by CPIC during an attempt to establish a conversation. Side information includes the partner LU name, mode name, and TP name. This information is configured in advance of the conversation.
Note: Side information is referenced by an SDN.
An SNA network is a logical network of LUs.
Sync level indicates the degree of synchronization a CPIC conversation uses. The sync level can be one of the following:
SYNC_POINT indicates that your application supports full SAA Resource Recovery operations, such as Take Commit and Take Backout notifications.
Note: SYNC_POINT is not supported in OS/2.
TP (Transaction Program) is an application that uses CPIC or APPC commands to participate in a conversation.
The TP name is the name of a transaction application. This name is specified in side information. Depending on the operating system, the TP name may specify a table entry for the target LU's node services application. This table is used to look up the information needed to start the TP.
Following is a short example of the method used when an application starts a conversation with another application.
TSD Script does not allow direct control of the allocated size of memory structures, which frees programmers from having to worry about the size of the records they declare.
Although this is considered an attractive attribute of a fourth generation language, it can present difficulties in working with CPIC applications. CPIC applications send and receive byte buffers of a specific size and format. A partner application may use different storage formats than the local application, including non-Intel integers and EBCDIC character strings.
Data description files (or DDFs) address the possibilities of different buffer sizes. A DDF defines the exact form of a transmitted byte buffer and specifies format translation/conversion. TSD Developer's Toolkit uses these DDFs as "filters" for both outgoing and incoming buffers to a CPIC application.
The basic structure of a DDF is:
-- Double dashes are comment to end of line. -- The first section is the partner section. *PARTNER -- character conversion types EBCDIC=TRUE -- integer byte order NON_INTEL=TRUE -- character conversion table. If not specified, TSD Developer's Toolkit will -- use the CM/2 AE table. This default table -- may be insufficient for your use (for example, it -- converts embedded spaces to x'00'). If you want a -- more normal conversion table, set the CM/2 translation -- table file name to ACSGTAB.DAT, which is provided with -- CM/2. Then set CUSTOM_CONVERT to TRUE. CUSTOM_CONVERT=TRUE -- This section is the field section. It is used -- to describe each field of the record and its byte -- mapping and translation. Essentially, this section -- shows how the data buffer should look just after it -- is received (before conversion), or just before a -- send (after conversion). *FIELDS -- Fieldname Type ByteWidth SendUnknowns? Default name CHAR 20 FALSE street CHAR 20 TRUE age INTEGER 20 TRUE birthDate CCYYMMDD 8 FALSE
In this example, the partner application runs on an EBCDIC machine with non-Intel style integers (such as an IBM System 370). The record that is sent is declared in TSD Script like this:
SomeRecordName IS RECORD name :STRING; street :STRING; age :INTEGER; birthDate :DATE; description:STRING; END;
The description field is not included in the DDF, which means that the description field is not transferred during CPIC communications.
This section of a DDF describes the partner application's machine type. The beginning of this section is marked by the text *PARTNER. The partner section indicates the types of data conversions that TSD Developer's Toolkit performs. For instance, setting EBCDIC=TRUE means that TSD Developer's Toolkit converts all character strings to and from EBCDIC when communicating with the partner application.
In the Partner section, the following attributes should be set. Any attributes you do not set take the indicated default value.
This DDF section specifies fields and the field types to be packed or unpacked in CPIC data buffers. This section in the DDF begins with the line containing "*FIELDS". Each line in the Fields section applies to one TSD Script transferred record field. The format of such a line is as follows:
{fieldname} {fieldtype} {bytewidth} {sendunknowns?} {default}
White space divides each column; the column definitions are listed here:
The $INCLUDE command simplifies the organization of a DDF. This command provides the ability to "link" other files dynamically. When TSD Developer's Toolkit encounters the $INCLUDE command, it loads the specified DDF and places its field definitions in the current DDF.
The $INCLUDE command can be included anywhere in the Fields section. The format of the $INCLUDE command is:
$INCLUDE({DDFname})
If the file is not in the current directory, TSD Developer's Toolkit searches the DPATH for the file. If it is not found, then TSD Developer's Toolkit returns an error.
The $SIZEOF command automatically recalculates the size of the included files Included files do not have to be manually recounted if another field is added to them.
The $SIZEOF and $INCLUDE commands are used in special cases, like setting up a vectored buffer. They can be used in combination like this:
*PARTNER EBCDIC =TRUE NON_INTEL =TRUE CUSTOM_CONVERT =TRUE *FIELDS GDS1310 INT 2 TRUE 4880 GDS1311LEN INT 2 TRUE $SIZEOF(1311.DDF) + 2 $INCLUDE(1311.DDF) GDS1549LEN INT 2 TRUE $SIZEOF(1549.DDF) + 2 $INCLUDE(1549.DDF) DataLen INT 2 TRUE $SIZEOF(RTRNDATA.DDF) + 2 $INCLUDE(RTRNDATA.DDF)
The types recognized for DDF processing are:
There are several details you should know before you attempt to write an OS/2 CPIC application. Some of these can be grouped by the type of node services you have on your system.
Because of the way node services set a TP to receive an incoming allocation, an OS/2 CPIC application cannot be an SNA Service TP. Review the following steps that summarize how an incoming allocation is handled:
If you have more than one TSD Script application for which you want to set up a TP, you have to do a special set up. Communications Manager/2 only allows you to specify kml.exe as the OS/2 application PATH and file for one TP definition. For the other one, create an OS/2 command file containing the following commands:
SET APPCTPN={your TP name} START /C KML /U{path to your KB} {your KB name} EXIT
Communications Manager/2 allows a single CPIC process to accept multiple conversations. Additionally, a CPIC application may issue one Initialize command, as long as no prior Accept commands have been issued.
This section is a brief case study of the process for creating a simple CPIC application. The application is designed to complete a file transfer.
To illustrate the benefits of CPIC, the case study has two example modules. The application is created in the first example module. In the second example module, some minor changes have been made to the application to improve performance.
This case study makes several assumptions about your familiarity with CPIC, Communications Manager/2, and communications processing in general. For example, it is assumed that you are familiar with the Communications Manager/2 CMSETUP utility.
To begin, review the partner application that is written in REXX.
The REXX partner application is named RCV.CMD. Essentially, this application receives data (storing it in a stem variable) until the status received parameter indicates that the application may now send data.
Following this code example are explanations that provide additional details about the application.
/* RCV.CMD */ /* Receives data strings, building a buffer of all data. /*Upon completion of*/ /* receiving, sends back the buffer. */ /* CPIC commands used: CMACCP */ /* CMCFMD */ /* CMDEAL */ /* CMRCV */ /* CMSEND */
/* a few useful constants */ CM_OK = 0 /* status received */ CM_SEND_RECEIVED = 1 CM_CONFIRM_RECEIVED = 2 /* data received */ CM_NO_DATA_RECEIVED = 0
MaxLength = 257; BufferLen = 0; FileBuffer.0 = 0; 'CPICREXX'
address cpicomm 'CMACCP Conv_ID RetC'; if \(RetC = CM_OK) then do SAY 'ACCP = 'Retc end;
'CMRCV Conv_ID Data MaxLength DataReceived ReceivedLength StatusRecvd ReqToSendRecvd Retc'; if \(RetC = CM_OK) then do SAY 'RCV = 'Retc end;
do while (RetC = CM_OK) & (StatusRecvd \= CM_SEND_RECEIVED) if (DataReceived \= CM_NO_DATA_RECEIVED) then do /* SAY Data */ FileBuffer.0 = FileBuffer.0 + 1; i = FileBuffer.0; FileBuffer.i = Data; end; if (StatusRecvd = CM_CONFIRM_RECEIVED) then do 'CMCFMD Conv_ID RetC'; end; 'CMRCV Conv_ID Data MaxLength DataReceived ReceivedLength StatusRecvd ReqToSendRecvd Retc'; if (RetC \= CM_OK) then do SAY 'RCV = 'Retc end; end;
SAY 'Re-transmitting file'
DO i = 1 TO FileBuffer.0 BufferLen = LENGTH(FileBuffer.i); Data = FileBuffer.i; 'CMSEND Conv_ID Data BufferLen ReqToSendRecvd RetC'; if (RetC \= CM_OK) then do SAY 'SND = 'Retc end; END; 'CMDEAL Conv_ID RetC'; address cmd 'EXIT'
The goal of this application is to read a text file and to transmit each line to a partner application. After the application completes the file transfer, it begins receiving the same file back again and displays each line in a display window.
Beginning with Step 3, you set up an entry into Communication Manager/2's Side Information Table. The Side Information Table is used during initialization of a conversation. Initialization occurs as follows:
Using this method, CPIC applications can be written that have no hard-coded, site-specific information. It also provides a standard method for all CPIC applications to access this type of information.
Beginning with Step 8, a TP definition is created. This entry tells node services how to start a certain TP.
When a conversation is allocated, the LU that requested the allocation sends the desired TP name to the target LU node services system. The node services system checks to see if that TP name is defined on the system. If it is defined, the node services follow the instructions on how to start the TP. If it can successfully start the application, it does (when Attach Manager started is set for the TP). The TP then issues a CPICAccept. The requesting LU gets a success indication and the conversation is started.
For this REXX application, an OS/2 command processor starts (CMD.EXE). The parameter string tells CMD.EXE to exit when the command is completed (/C) and what command to run (RCV.CMD).
The next part of the case study starts the RCV.CMD file from the OS/2 command line.
This transmits the source file back and forth between the two applications, and then displays the results in a window.
It may take a little time for the double transfer to finish. Below the file listing in the window, you see the timing results.
Additionally, notice the line number for each line of the file. These numbers were transmitted back and forth with each line of the text file.
Following this section of numbered lines is a discussion about the file.
1 2 KNOWLEDGEBASE FILESND; 3 4 ROUTINES 5 PROCEDURE DoConversation(VAL Args:List of String); 6 (* sdn, infile *) 7 8 9 PRIVATE 10 11 CONSTANTS 12 CPIC_SUCCESS IS 1; 13 14 TYPES 15 FileRec IS RECORD 16 LineNbr:Integer; 17 Buff:String; 18 END; 19 20 ROUTINES 21 22 FUNCTION RcvData(REF w:WINDOW, VAL Conv:Conversation) :INTEGER IS 23 VARIABLES 24 totalBuff :FileRec; 25 dataRcvd :integer; 26 statRcvd :integer; 27 reqTSRcvd :integer; 28 rc :integer; 29 ACTIONS 30 IF (not(Known(w))) THEN 31 WinCreateScrollWindow($DESKTOP,w, 32 $NullHandler, 1,1,67,7, 'FileSnd','', 0, $WinBorder+ $WinTitle+ $WinHScroll+ $WinVScroll+ $WinSysMenu+ $WinResize); END; 33 REPEAT 34 rc := CPICReceive(Conv,'FILEREC.DDF', totalBuff,DataRcvd, StatRcvd,ReqTSRcvd); 35 IF (rc > 0) THEN 36 IF ((StatRcvd = $CPICConfirmReceived) or 37 (StatRcvd = $CPICConfirmSend Received)) THEN 38 rc := CPICConfirmed(Conv); 39 END; 40 totalBuff.buff := StrTrim (totalBuff.buff); 41 WinWriteLn(w,totalBuff.lineNbr:5&' :'&totalBuff.buff); 42 END; 43 UNTIL ((rc <> 1) OR ((StatRcvd = $CPICSendReceived) OR 44 (StatRcvd = $CPICConfirmSend Received))); 45 Exit(rc); 46 END; -- RcvData 47 48 49 --------------------------------------------- 50 -- Description: Reads in the specified file, transmitting each line via CPIC 51 -- to the partner specified through the given SDN. 52 --------------------------------------------- 53 PROCEDURE DoConversation(VAL Args:List of String) IS 54 VARIABLES 55 Conv :Conversation; 56 fRec :FileRec; 57 ReqTSRcvd:INTEGER; 58 rc :INTEGER; 59 inf :FILE; 60 w :WINDOW; 61 t1,t2 :TIME; 62 ACTIONS 63 t1 := $NOW; 64 IF (ListLength(Args) <2) THEN WinMessageBox($DESKTOP,ÒopsÒ¬ $MBOK,Ò‹ML FILESND {SDN} {INFILE}Ò©; Exit; END; FOpen(inf,Args[2],$Read); rc :="CPICInitialize(Conv,Args[1]);" IF (rc <CPIC_SUCCESS) THEN WinMessageBox($DESKTOP, ÒƒPIC ErrorÒ¬$MBOK, Ò‰nit returns Ѧrc); Exit; END; rc :="CPICSetSyncLevel(Conv," $CPICNone); IF (rc <CPIC_SUCCESS) THEN WinMessageBox($DESKTOP, ÒƒPIC ErrorÒ¬$MBOK, Ò“SL returns Ѧrc); END; rc :="CPICAllocate(Conv);" IF (rc < CPIC_SUCCESS) THEN WinMessageBox($DESKTOP, ÒƒPIC ErrorÒ¬$MBOK, Òllc returns Ѧrc); Exit; END; rc :="CPICSetPrepareToReceiveType" (Conv, $CPICPrepToReceiveFlush); IF (rc < CPIC_SUCCESS) THEN WinMessageBox($DESKTOP, ÒƒPIC ErrorÒ¬$MBOK, Ò“PTR returns Ѧrc); END; fRec.lineNbr :="0;" while (FReadLn(inf,fRec.Buff)> <2) THEN 65 WinMessageBox($DESKTOP,'Oops', $MBOK,'KML FILESND {SDN} {INFILE}'); 66 Exit; 67 END; 68 69 FOpen(inf,Args[2],$Read); 70 71 rc := CPICInitialize(Conv,Args[1]); 72 IF (rc < CPIC_SUCCESS) THEN 73 WinMessageBox($DESKTOP, 'CPIC Error',$MBOK, 'Init returns '&rc); 74 Exit; 75 END; 76 rc := CPICSetSyncLevel(Conv, $CPICNone); 77 IF (rc < CPIC_SUCCESS) THEN 78 WinMessageBox($DESKTOP, 'CPIC Error',$MBOK, 'SSL returns '&rc); 79 END; 80 rc := CPICAllocate(Conv); 81 IF (rc < CPIC_SUCCESS) THEN 82 WinMessageBox($DESKTOP, 'CPIC Error',$MBOK, 'Allc returns '&rc); 83 Exit; 84 END; 85 86 rc := CPICSetPrepareToReceiveType (Conv, $CPICPrepToReceiveFlush); 87 IF (rc < CPIC_SUCCESS) THEN 88 WinMessageBox($DESKTOP, 'CPIC Error',$MBOK, 'SPTR returns '&rc); 89 END; 90 91 fRec.lineNbr := 0; 92 while (FReadLn(inf,fRec.Buff) > 0) do 93 fRec.Buff := fRec.Buff & Char(13) & Char(10); -- add CR LF 94 fRec.lineNbr := fRec.lineNbr + 1; 95 rc := CPICSend(Conv, 'FILEREC.DDF', fRec, ReqTSRcvd); 96 IF (rc < CPIC_SUCCESS) THEN 97 WinMessageBox($DESKTOP, 'CPIC Error',$MBOK, 'Send returns '&rc); 98 ExitLoop; 99 END; 100 CPICFlush(Conv); 101 END; 102 FClose(inf); 103 104 IF (rc = CPIC_SUCCESS) THEN 105 CPICPrepareToReceive(Conv); -- Indicates Partner may send now. 106 t2 := $NOW; 107 RcvData(w,Conv); 108 END; 109 110 CPICDeallocate(Conv); 111 WinWriteLn(w,'<<<<<<<<<<<<<<<<<<<<<<<< >>>>>>>>>>>>>>>>>>'); 112 WinWriteLn(w,'Elapsed time for outgoing transmission: '& 113 TimeDif(t2,t1,$SECONDS)&' seconds'); 114 WinWait(w); 115 END; 116 117
Following is a review that explains the preceding code sample.
Line 42 contains some vestige code. This application was originally written to use the sync level of $CPICConfirm, and RcvData had to detect and acknowledge any confirms by the partner. Since the sync level is set to $CPICNone in line 80, this does not happen.
Lines 75-93 contain the conversation setup commands. $CPICNone is the default for a conversation, so does not need to be set.
In line 90, after the CPICAllocate, the prepare to receive type is set. This indicates the type of action to be taken whenever CPICPrepareToReceive is called. Flush was chosen so that the last buffer is transmitted as soon as data is ready for receipt.
File transmission is accomplished in lines 96-105. Notice that this occurs with only two CPIC commands (CPICSend and CPICFlush). A record, defined in lines 15-17, is sent.
The map file FILEREC.DDF looks like:
1 2 *PARTNER 3 EBCDIC = FALSE 4 NON_INTEL = FALSE 5 CUSTOM_CONVERT = TRUE 6 7 *FIELDS 8 LineNbr INTEGER 2 TRUE 9 Buff ASE_STRING VAR TRUE 10
Both the line number and the line contents are transmitted to the partner application. Because the REXX application treats the buffer as one string, the buffer can be sent back, and TSD Developer's Toolkit can once again extract the two fields.
Line 104 is where the buffer flushes. This causes the data passed to CPICSend to be transmitted to the partner immediately.
After transmitting the file, the partner is notified that it may begin sending data. The RcvData function (line 22) handles the incoming data.
RcvData receives incoming FILEREC data until either there is an error (including the partner deallocating the conversation) or the application again receives the send notification.
The conversation is deallocated in line 114.
This is the second example module. The goal of this application is the same as the first example. The difference between the two is that some of the code was changed to gain performance.
You can use the same SDN for FILESND2 as you did for FILESND.
Here is a listing of FILESND2.KB:
1 2 -- A little more efficient example. 3 -- Note that certain lines have been commented out. These were vestiges 4 -- from the original FILESND.KB. New lines are marked by (* NEW *). 5 6 KNOWLEDGEBASE FILESND2; 7 8 ROUTINES 9 PROCEDURE DoConversation(VAL Args: List of String); 10 (* sdn, infile *) 11 12 13 PRIVATE 14 15 CONSTANTS 16 CPIC_SUCCESS IS 1; 17 18 TYPES 19 FileRec IS RECORD 20 LineNbr:Integer; 21 Buff:String; 22 END; 23 24 ROUTINES 25 26 FUNCTION RcvData(REF w:WINDOW, VAL Conv: Conversation):INTEGER IS 27 VARIABLES 28 totalBuff :FileRec; 29 dataRcvd :integer; 30 statRcvd :integer; 31 reqTSRcvd :integer; 32 rc :integer; 33 ACTIONS 34 IF (not(Known(w))) THEN 35 WinCreateScrollWindow($DESKTOP,w, 36 $NullHandler, 37 1,1,67,7, 'FileSnd2','', 0, $WinBorder+ $WinTitle+ $WinHScroll+ $WinVScroll+ 38 $WinSysMenu+ $WinResize); 39 END; 40 REPEAT 41 rc := CPICReceive(Conv,'FILEREC.DDF', totalBuff,DataRcvd, StatRcvd,ReqTSRcvd); 42 IF (rc > 0) THEN 43 IF ((StatRcvd = $CPICConfirmReceived)or 44 (StatRcvd=$CPICConfirmSendReceived)) THEN 45 rc := CPICConfirmed(Conv); 46 END; 47 totalBuff.buff := StrTrim (totalBuff.buff); 48 WinWriteLn(w,totalBuff.lineNbr:5&': '&totalBuff.buff); 49 END; 50 UNTIL ((rc <> 1) OR ((StatRcvd = $CPICSendReceived) OR 51 StatRcvd= $CPICConfirmSendReceived))); 52 Exit(rc); 53 END; -- RcvData 54 55 56 --------------------------------------------- 57 -- Description: Reads in the specified file, transmitting each line via CPIC 58 -- to the partner specified through the given SDN 59 --------------------------------------------- 60 PROCEDURE DoConversation(VAL Args: List of String) IS 61 VARIABLES 62 Conv :Conversation; 63 fRec :FileRec; 64 ReqTSRcvd :INTEGER; 65 rc :INTEGER; 66 inf :FILE; 67 w :WINDOW; 68 t1,t2 :TIME; 69 ACTIONS 70 t1 := $NOW; 71 IF (ListLength(Args) < 2) THEN 72 WinMessageBox($DESKTOP,'Oops', $MBOK,'KML FILESND {SDN} {INFILE}'); 73 Exit; 74 END; 75 76 FOpen(inf,Args[2],$Read); 77 78 rc := CPICInitialize(Conv,Args[1]); 79 IF (rc < CPIC_SUCCESS) THEN 80 WinMessageBox($DESKTOP,'CPIC Error', $MBOK,'Init returns '&rc); 81 Exit; 82 END; 83 rc := CPICSetSyncLevel(Conv, $CPICNone); 84 IF (rc < CPIC_SUCCESS) THEN 85 WinMessageBox($DESKTOP,'CPIC Error', $MBOK,'SSL returns '&rc); 86 END; 87 rc := CPICAllocate(Conv); 88 IF (rc < CPIC_SUCCESS) THEN 89 WinMessageBox($DESKTOP,'CPIC Error', $MBOK,'Allc returns '&rc); 90 Exit; 91 END; 92 rc := CPICSetPrepareToReceiveType(Conv, 93 $CPICPrep ToReceiveFlush); 94 IF (rc < CPIC_SUCCESS) THEN 95 WinMessageBox($DESKTOP,'CPIC Error', $MBOK,'SPTR returns '&rc); 96 END; 97 98 fRec.lineNbr := 0; 99 while (FReadLn(inf,fRec.Buff) > 0) do 100(* NEW *) 101-- By knowing if you are at the end of the file, you can set the appropriate 102-- send type. This allows you to avoid calling CPICPrepareToReceive later 103-- and it avoids making the node services system do an extra transmission 104-- to the partner. 105 IF (FEnd(inf)) THEN 106 CPICSetSendType(Conv, $CPICSendAndPrep ToReceive); END; 107 (* END NEW *) 108 fRec.Buff := fRec.Buff & Char(13) & Char(10); -- add CR LF 109 fRec.lineNbr := fRec.lineNbr + 1; 110 rc := CPICSend(Conv, 'FILEREC.DDF', fRec, ReqTSRcvd);
111 IF (rc < CPIC_SUCCESS) THEN 112 WinMessageBox($DESKTOP,'CPIC Error', $MBOK,'Send returns '&rc); ExitLoop; 113 END; 114-- Let CM/2 do buffering. The other end will still see the 115-- same number of sent buffers. CM/2 may batch some 116-- of the buffers for efficiency 117 (* CPICFlush(Conv); *) 118 119 END; 120 FClose(inf); 121 122 IF (rc = CPIC_SUCCESS) THEN 123-- Don't have to do this, because this notification sent along with last send. 124 CPICPrepareToReceive(Conv); -- Indicates Partner may send now. -- 125 t2 := $NOW; 126 RcvData(w,Conv); 127 END; 128 129 CPICDeallocate(Conv); 130 WinWriteLn(w,'<<<<<<<<<<<<<<<<<<<<<<<< >>>>>>>>>>>>>>>>>>'); 131 WinWriteLn(w,'Elapsed time for outgoing transmission: '& TimeDif(t2,t1,$SECONDS)&' seconds'); WinWait(w); 132END;
As you can see, it did not take much effort to make this application run faster. Lines 105-108 were added and lines 117 and 124 removed (commented out).
The changes implemented in FILESND2.KB are:
There are drawbacks to using the data buffering of CPIC. The main problem is that your application is not "in contact" as frequently with the partner application. In the case of this example, this does not matter. However, there are many cases where partner applications need to be able to request the right to send dynamically. In these cases, it is best that you control the flushing of the buffer in order to receive flags from the partner application as often as possible.
Tivoli Service Desk 6.0 Developer's Toolkit Legacy APIs Guide