Horizon SOUL sample programs
Overview
This topic presents sample Horizon User Language (SOUL) client and server programs, a subroutine to check Horizon return codes, and an example of remote file updating.
Client Program
The following example is a small client program that establishes a conversation with a partner process, sends a message to the partner, receives messages from the partner, and ends the conversation.
The STAT_CHECK subroutine is used after each HORIZON statement to determine the appropriate subsequent action for the program to take. Subroutine STAT_CHECK is found in Subroutine to check Horizon return codes.
The HORIZON LINK, PROCESSGROUP, and PROCESS definition commands are included as comments at the beginning of the procedure, for convenient reference.
Companion program
Server sample has an example of a server program that can communicate with the client program shown here.
Program
PROCEDURE CLIENT BEGIN ****************************************************************** *** S A M P L E H O R I Z O N C L I E N T P R O G R A M *** ****************************************************************** ***************************************** *** NETWORK DEFINITIONS *** ***************************************** * * DEFINE LINK VIRGINIA WITH SCOPE=SYSTEM LOCALID=FREDBURG - * INBUFSIZE=2048 TRANSPORT=VTAM PROTOCOL=LU62 SESSIONS=4 * * DEFINE PROCESSGROUP BOULDER WITH SCOPE=SYSTEM OUTLIMIT=4 - * INLIMIT=0 REMOTEID=COLORADO LINK=VIRGINIA * * DEFINE PROCESS WEEKEND WITH SCOPE=SYSTEM PARTNER=SOMEFUN - * DESTINATION=(BOULDER,FAC,MOAB,ARCHES) DATALEN=500 * ****************************************** *** DATA AND SUBROUTINES *** ****************************************** %CID IS STRING LEN 8 %RECVMSG IS STRING LEN 255 %RESULT IS STRING LEN 15 %REQSEND IS FLOAT %ADVICE IS FLOAT %CID = 'MADAME' INCLUDE STAT_CHECK *************************************** *** MAIN PROGRAM *** *************************************** OPEN PROCESS WEEKEND CID %CID AT FAC CALL STAT_CHECK (%CID, %HRZN_OPEN, %RESULT, %REQSEND, %ADVICE) JUMP TO (ABORT) %ADVICE - 1 *** FALL THROUGH WHEN ADVICE=1 (OPEN SUCCEEDED) *** SEND 'HELLO, MADAME!' TO %CID REQSEND %REQSEND CALL STAT_CHECK (%CID, %HRZN_SEND, %RESULT, %REQSEND, %ADVICE) JUMP TO (ABORT, - HANDLE_ERROR, - HANDLE_SIGNAL) %ADVICE - 1 *** FALL THROUGH WHEN ADVICE=1 (SEND SUCCEEDED) *** RECEIVE_LOOP: RECEIVE %RECVMSG FROM %CID RESULT %RESULT CALL STAT_CHECK (%CID, %HRZN_RECEIVE, %RESULT, %REQSEND, - %ADVICE) JUMP TO (ABORT, - HANDLE_ERROR,- BOGUS, - SEND, - HANDLE_CLOSE, - HANDLE_CONFIRM) %ADVICE - 1 *** FALL THROUGH WHEN ADVICE=1 (RECEIVED DATA) *** PRINT 'RECEIVED FROM PARTNER:' AND %RECVMSG JUMP TO RECEIVE_LOOP SEND: SEND 'GOODBYE, MADAME!' TO %CID REQSEND %REQSEND CALL STAT_CHECK (%CID, %HRZN_SEND, %RESULT, %REQSEND, %ADVICE) JUMP TO (ABORT, - HANDLE_ERROR, - HANDLE_SIGNAL) %ADVICE - 1 *** FALL THROUGH WHEN ADVICE=1 (SEND SUCCEEDED) *** CLOSE PROCESS %CID CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE) JUMP TO (END, - ABORT, - HANDLE_ERROR) %ADVICE ************************************************** *** EXCEPTION HANDLERS *** ************************************************** HANDLE_CONFIRM: PRINT '*** PARTNER REQUESTED CONFIRMATION ***' SEND ERROR TO %CID REQSEND %REQSEND CALL STAT_CHECK(%CID, %HRZN_SEND_ERROR, %RESULT, %REQSEND, - %ADVICE) JUMP TO (ABORT, - BOGUS, - ABORT) %ADVICE - 1 *** FALL THROUGH IF ADVICE = 1 (SEND ERROR SUCCEEDED) *** CLOSE PROCESS %CID CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE) *** IF CLOSE FAILED, JUST GIVE UP JUMP TO (END, - END, - END) %ADVICE HANDLE_SIGNAL: PRINT '*** PARTNER SENT SIGNAL - CLOSING CONVERSATION ***' CLOSE PROCESS %CID CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE) *** IF CLOSE FAILED, JUST GIVE UP JUMP TO (END, - END, - END) %ADVICE HANDLE_ERROR: PRINT '*** PARTNER SENT ERROR - CLOSING CONVERSATION ***' CLOSE PROCESS %CID CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE) *** IF CLOSE FAILED, JUST GIVE UP JUMP TO (END, - END, - END) %ADVICE HANDLE_CLOSE: PRINT '*** PARTNER CLOSED CONVERSATION ***' CLOSE PROCESS %CID CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE) *** IF CLOSE FAILED, JUST GIVE UP JUMP TO (END, - END, - END) %ADVICE BOGUS: PRINT '*** STAT_CHECK RETURNED AN UNDEFINED ADVICE CODE ***' JUMP TO END ABORT: PRINT '*** STAT_CHECK ADVISES THAT WE ABORT ***' JUMP TO END END: END END PROCEDURE
Server Sample
The following example is a server program that receives messages from a partner program and sends back a message to the partner, repeating this sequence until the partner ends the conversation.
The STAT_CHECK subroutine is used after each HORIZON statement to determine the appropriate subsequent action for the program to take. Subroutine STAT_CHECK is found in Subroutine to check Horizon return codes.
The HORIZON LINK, PROCESSGROUP, and PROCESS definition commands are included as comments at the beginning of the procedure for convenient reference.
In this example, the server program is invoked using the Remote Procedure Invocation (RPI) subsystem. See Application testing with the RPI subsystem.
Companion program
Client program has an example of a client program that can communicate with the server program shown here.
Program
PROCEDURE SERVER BEGIN ****************************************************************** *** S A M P L E H O R I Z O N S E R V E R P R O G R A M *** ****************************************************************** ****************************************** *** NETWORK DEFINITIONS *** ****************************************** * * DEFINE LINK BOULDER WITH SCOPE=SYSTEM LOCALID=COLORADO - * INBUFSIZE=2048 TRANSPORT=VTAM PROTOCOL=LU62 SESSIONS=4 * * DEFINE PROCESSGROUP VIRGINIA WITH SCOPE=SYSTEM OUTLIMIT=0 - * INLIMIT=4 REMOTEID=FREDBURG LINK=BOULDER LOGIN=NOTRUST - * GUESTUSER=REJECT * * DEFINE PROCESS SOMEFUN WITH SCOPE=SYSTEM SUBSYSTEM=RPI - * FROM=(VIRGINIA) DATALEN=500 SUBSYSPARM='MYFILE SERVER OPEN' * ****************************************** *** DATA AND SUBROUTINES *** ****************************************** %CID IS STRING LEN 8 %RECVMSG IS STRING LEN 255 %RESULT IS STRING LEN 15 %REQSEND IS FLOAT %ADVICE IS FLOAT %CID = 'SAILOR' INCLUDE STAT_CHECK ****************************************** *** MAIN PROGRAM *** ****************************************** OPEN PROCESS SOMEFUN CID %CID ACCEPT CALL STAT_CHECK (%CID, %HRZN_OPEN, %RESULT, %REQSEND, %ADVICE) JUMP TO (ABORT) %ADVICE - 1 *** FALL THROUGH WHEN ADVICE=1 (OPEN SUCCEEDED) *** AUDIT 'CONVERSATION HAS BEGUN' RECEIVE_LOOP: RECEIVE %RECVMSG FROM %CID RESULT %RESULT CALL STAT_CHECK (%CID, %HRZN_RECEIVE, %RESULT, %REQSEND, - %ADVICE) JUMP TO (ABORT, - HANDLE_ERROR, - BOGUS, - SEND, - HANDLE_CLOSE, - HANDLE_CONFIRM) %ADVICE - 1 *** FALL THROUGH WHEN ADVICE=1 (RECEIVED DATA) *** AUDIT 'RECEIVED FROM PARTNER:' AND %RECVMSG JUMP TO RECEIVE_LOOP SEND: SEND 'HELLO, SAILOR!' TO %CID REQSEND %REQSEND CALL STAT_CHECK (%CID, %HRZN_SEND, %RESULT, %REQSEND, %ADVICE) JUMP TO (ABORT, - HANDLE_ERROR, - HANDLE_SIGNAL) %ADVICE - 1 *** FALL THROUGH WHEN ADVICE=1 (SEND SUCCEEDED) *** JUMP TO RECEIVE_LOOP ****************************************** *** EXCEPTION HANDLERS *** ****************************************** HANDLE_CONFIRM: AUDIT '*** PARTNER REQUESTED CONFIRMATION ***' SEND ERROR TO %CID REQSEND %REQSEND CALL STAT_CHECK(%CID, %HRZN_SEND_ERROR, %RESULT, %REQSEND, - %ADVICE) JUMP TO (ABORT, - BOGUS, - ABORT) %ADVICE - 1 *** FALL THROUGH IF ADVICE = 1 (SEND ERROR SUCCEEDED) *** CLOSE PROCESS %CID *** IF CLOSE FAILS, JUST GIVE UP CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE) JUMP TO (END, - END, - END) %ADVICE HANDLE_SIGNAL: AUDIT '*** PARTNER SENT SIGNAL - CLOSING CONVERSATION ***' CLOSE PROCESS %CID *** IF CLOSE FAILS, JUST GIVE UP CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE) JUMP TO (END, - END, - END) %ADVICE HANDLE_ERROR: AUDIT '*** PARTNER SENT ERROR - CLOSING CONVERSATION ***' CLOSE PROCESS %CID *** IF CLOSE FAILS, JUST GIVE UP CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE) JUMP TO (END, - END, - END) %ADVICE HANDLE_CLOSE: AUDIT '*** PARTNER CLOSED CONVERSATION ***' CLOSE PROCESS %CID *** IF CLOSE FAILS, JUST GIVE UP CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE) JUMP TO (END, - END, - END) %ADVICE BOGUS: AUDIT '*** STAT_CHECK RETURNED AN UNDEFINED ADVICE CODE ***' JUMP TO END ABORT: AUDIT '*** STAT_CHECK ADVISES THAT WE ABORT ***' JUMP TO END END: *** ALWAYS SET THE APSY COMMUNICATION VARIABLE BEFORE LEAVING %X = $SETG('COMM','EXIT') END END PROCEDURE
Subroutine to Check Horizon Return Codes
The following subroutine can be used in Horizon User Language (SOUL) programs to simplify the checking of the status information that is set by each HORIZON statement. The subroutine condenses the large number of combinations of $STATUS codes, RESULT codes, and so on into a small set of recommended actions for the program:
- Continue normally.
- Terminate immediately.
- Respond to partner's SEND ERROR.
- Respond to partner's SIGNAL PROCESS.
- Start to SEND.
- Partner has closed conversation.
- Respond to partner's CONFIRM.
- No more data expected.
- Expected data has not arrived.
Refer to the client and server program samples for illustrations of how the subroutine is to be used.
Subroutine
PROCEDURE STAT_CHECK ************************************************************************* SUBROUTINE STAT_CHECK ( %PROCESS IS STRING LEN 10 INPUT - %STATEMENT IS FLOAT INPUT, - %RESULT IS STRING LEN 15 INPUT, - %REQSEND IS FLOAT INPUT, - %ADVICE IS FLOAT OUTPUT ) ********************************************************************** * STAT_CHECK SHOULD BE CALLED AFTER EACH HORIZON STATEMENT. * * IT EVALUATES THE RELEVANT STATUS INFORMATION THAT WAS SET BY * * THE STATEMENT AND RETURNS A RECOMMENDED PROGRAM-ACTION CODE. * * * * %PROCESS -- THE CONVERSATION ID (CID) OF THE PROCESS * * %STATEMENT-- THE HORIZON STATEMENT JUST ISSUED * * 1 = OPEN (O) 8 = SEND (S) * * 2 = CONFIRM (CF) 9 = SEND ERROR (SE) * * 3 = CONFIRMED (CFD) 10 = SIGNAL (SP) * * 4 = CLOSE (C) 11 = INVITE (I) * * 5 = FLUSH (F) 12 = TEST (T) * * 6 = QUERY (Q) 13 = WAIT (W) * * 7 = RECEIVE (R) * * %RESULT -- THE RESULT VARIABLE FROM THE 'RECEIVE' STATEMENT * * %REQSEND -- THE REQSEND VARIABLE FROM 'SEND' OR 'SEND ERROR' * * %ADVICE -- (OUTPUT) THE RECOMMENDED ACTION TO TAKE. USE THE * * FOLLOWING CHART TO DETERMINE WHICH ADVICE CODES * * STAT_CHECK CAN RETURN FOR DIFFERENT HORIZON * * STATEMENTS: * * * * - - - S T A T E M E N T S - - - - - A D V I C E C O D E S - - * * * * O CF CFD C F I Q R S SE SP T W * * X X X X X X X X X X X X X 1 - CONTINUE * * X X X X X X X X X X X X X 2 - ABORT * * - X - X - X - X X - - - - 3 - GOT 'SEND ERROR' * * - X - - - - - - X X - - - 4 - GOT 'SIGNAL PROCESS' * * - - X - - - - X - - - - - 5 - TRANSITION TO 'SEND' * * - - X - - X - X - - - - - 6 - PARTNER CLOSED CONVERSATION * * - - - - - - - X - - - - - 7 - TRANSITION TO 'CONFIRM' * * - - - - - - - - - - - X X 8 - NO OUTSTANDING INVITES * * - - - - - - - - - - - X - 9 - NO RECEIPTS YET * ********************************************************************** %STATUS = $STATUS %STATUSD = $STATUSD JUMP TO (O,CF,CFD,C,F,Q,R,S,SE,SP,I,T,W) %STATEMENT X: ********************************** * INVALID STATEMENT CODE * ********************************** JUMP TO ABORT O: ********************************** * OPEN PROCESS * ********************************** IF %STATUS = 0 THEN JUMP TO CONTINUE ELSE JUMP TO ABORT END IF CF: ********************************** * CONFIRM * ********************************** *** FIRST SEE IF SIGNAL RECEIVED FROM PARTNER IF %REQSEND = 1 THEN JUMP TO REQUEST_TO_SEND ELSEIF %STATUS = 0 THEN JUMP TO CONTINUE *** CHECK FOR 2/2 (PARTNER RESPONDED TO CONFIRM WITH SEND ERROR) ELSEIF %STATUS = 2 AND %STATUSD = 2 THEN JUMP TO SEND_ERROR ELSE JUMP TO ABORT END IF CFD: ********************************** * CONFIRMED * ********************************** %S IS STRING LEN 8 IF %STATUS = 0 THEN *** SEE WHAT THE CONVERSATION STATE HAS CHANGED TO QUERY PROCESS %PROCESS STATE %S IF %S = 'CLOSE' THEN JUMP TO CLOSE_BY_REMOTE ELSEIF %S = 'SEND' THEN JUMP TO SEND ELSE JUMP TO CONTINUE END IF ELSE JUMP TO ABORT END IF C: ********************************** * CLOSE PROCESS * ********************************** IF %STATUS = 0 THEN JUMP TO CONTINUE *** CHECK FOR 2/2 (PARTNER RESPONDED TO CONFIRM WITH SEND ERROR) ELSEIF %STATUS = 2 AND %STATUSD = 2 THEN JUMP TO SEND_ERROR ELSE JUMP TO ABORT END IF F: ********************************** * FLUSH PROCESS * ********************************** IF %STATUS = 0 THEN JUMP TO CONTINUE ELSE JUMP TO ABORT END IF Q: ********************************** * QUERY PROCESS * ********************************** IF %STATUS = 0 THEN JUMP TO CONTINUE ELSE JUMP TO ABORT END IF R: ********************************** * RECEIVE * ********************************** IF %STATUS = 0 THEN JUMP TO CONTINUE ELSEIF %STATUS = 1 THEN *** ANALYZE THE RESULT VARIABLE FOR APPROPRIATE ACTION *** DATA TRUNCATED OR INCOMPLETE - ASSUME THIS ISN'T DESIRABLE IF %RESULT = 'DATA TRUNCATED' THEN JUMP TO ABORT ELSEIF %RESULT = 'DATA INCOMPLETE' THEN JUMP TO ABORT ELSEIF %RESULT = 'SEND' THEN JUMP TO SEND *** ALL FLAVORS OF CONFIRM STATE - TELL USER TO DO 'CONFIRMED'. *** AFTERWARD, STAT_CHECK WILL SAY 'SEND', 'CLOSE', ETC. ELSEIF %RESULT = 'CONFIRM' THEN JUMP TO CONFIRM ELSEIF %RESULT = 'CONFIRM SEND' THEN JUMP TO CONFIRM ELSEIF %RESULT = 'CONFIRM CLOSE' THEN JUMP TO CONFIRM ELSE JUMP TO ABORT END IF *** CHECK FOR 2/2 (PARTNER RESPONDED TO CONFIRM WITH SEND ERROR) ELSEIF %STATUS = 2 AND %STATUSD = 2 THEN JUMP TO SEND_ERROR *** CHECK FOR 4/0 (INDICATES PARTNER ENDED CONVERSATION NORMALLY) ELSEIF %STATUS = 4 AND %STATUSD = 0 THEN JUMP TO CLOSE_BY_REMOTE ELSE JUMP TO ABORT END IF S: ********************************** * SEND * ********************************** IF %STATUS = 0 THEN *** SEE IF SIGNAL RECEIVED FROM PARTNER IF %REQSEND = 1 THEN JUMP TO REQUEST_TO_SEND ELSE JUMP TO CONTINUE END IF *** CHECK FOR 2/2 (PARTNER RESPONDED TO CONFIRM WITH SEND ERROR) ELSEIF %STATUS = 2 AND %STATUSD = 2 THEN JUMP TO SEND_ERROR ELSE JUMP TO ABORT END IF SE: ********************************** * SEND ERROR * ********************************** *** SEE IF SIGNAL RECEIVED FROM PARTNER IF %REQSEND = 1 THEN JUMP TO REQUEST_TO_SEND *** NO SIGNAL, SO CHECK %STATUS ELSEIF %STATUS = 0 THEN JUMP TO CONTINUE ELSE JUMP TO ABORT END IF SP: ********************************** * SIGNAL PROCESS * ********************************** IF %STATUS = 0 THEN JUMP TO CONTINUE ELSE JUMP TO ABORT END IF I: ********************************** * INVITE * ********************************** IF %STATUS = 0 THEN JUMP TO CONTINUE ELSEIF %STATUS = 2 AND %STATUSD = 2 THEN JUMP TO SEND_ERROR ELSEIF %STATUS = 4 THEN IF %STATUSD = 0 THEN JUMP TO CLOSE_BY_REMOTE ELSE JUMP TO ABORT END IF ELSE JUMP TO ABORT END IF T: ********************************** * TEST FOR RECEIPT * ********************************** IF %STATUS = 0 THEN JUMP TO CONTINUE ELSEIF %STATUS = 1 THEN IF %STATUSD = 1 THEN JUMP TO NEVER_MORE ELSEIF %STATUSD = 2 THEN JUMP TO NOT_YET ELSE JUMP TO ABORT END IF ELSE JUMP TO ABORT END IF W: ********************************** * WAIT FOR RECEIPT * ********************************** IF %STATUS = 0 THEN JUMP TO CONTINUE ELSEIF %STATUS = 1 THEN IF %STATUSD = 2 THEN JUMP TO NEVER_MORE END IF END IF JUMP TO ABORT ****************************************************************** *** SET THE ADVICE CODE AND EXIT. *** ****************************************************************** CONTINUE: %ADVICE = 1 JUMP TO EXIT ABORT: %ADVICE = 2 JUMP TO EXIT SEND_ERROR: %ADVICE = 3 JUMP TO EXIT REQUEST_TO_SEND: %ADVICE = 4 JUMP TO EXIT SEND: %ADVICE = 5 JUMP TO EXIT CLOSE_BY_REMOTE: %ADVICE = 6 JUMP TO EXIT CONFIRM: %ADVICE = 7 JUMP TO EXIT NEVER_MORE: %ADVICE = 8 JUMP TO EXIT NOT_YET: %ADVICE = 9 JUMP TO EXIT ****************************************************************** *** SUBROUTINE EXIT PATH *** ****************************************************************** EXIT: ****************************************************************** *** NOTE: THE FOLLOWING AUDIT LOGIC IS USEFUL AS A DEBUGGING *** *** TOOL FOR TRACING HORIZON STATEMENTS BUT MAY BE REMOVED *** *** OR BYPASSED FOR EFFICIENCY IF DESIRED. *** ****************************************************************** *** AUDIT RESULT OF EACH STAT_CHECK INVOCATION *** %STMT IS STRING LEN 14 IF %STATEMENT = 1 THEN %STMT = 'OPEN' ELSEIF %STATEMENT = 2 THEN %STMT = 'CONFIRM' ELSEIF %STATEMENT = 3 THEN %STMT = 'CONFIRMED' ELSEIF %STATEMENT = 4 THEN %STMT = 'CLOSE' ELSEIF %STATEMENT = 5 THEN %STMT = 'FLUSH' ELSEIF %STATEMENT = 6 THEN %STMT = 'QUERY' ELSEIF %STATEMENT = 7 THEN %STMT = 'RECEIVE' ELSEIF %STATEMENT = 8 THEN %STMT = 'SEND' ELSEIF %STATEMENT = 9 THEN %STMT = 'SEND ERROR' ELSEIF %STATEMENT = 10 THEN %STMT = 'SIGNAL PROCESS' ELSEIF %STATEMENT = 11 THEN %STMT = 'INVITE' ELSEIF %STATEMENT = 12 THEN %STMT = 'TEST' ELSEIF %STATEMENT = 13 THEN %STMT = 'WAIT' ELSE %STMT = '**UNDEFINED**' END IF %ADV IS STRING LEN 20 IF %ADVICE = 1 THEN %ADV = 'CONTINUE' ELSEIF %ADVICE = 2 THEN %ADV = 'ABORT' ELSEIF %ADVICE = 3 THEN %ADV = 'HANDLE SEND ERROR' ELSEIF %ADVICE = 4 THEN %ADV = 'HANDLE SIGNAL' ELSEIF %ADVICE = 5 THEN %ADV = 'START SENDING' ELSEIF %ADVICE = 6 THEN %ADV = 'PARTNER CLOSED' ELSEIF %ADVICE = 7 THEN %ADV = 'HANDLE CONFIRM' ELSEIF %ADVICE = 8 THEN %ADV = 'NOTHING ACTIVE' ELSEIF %ADVICE = 9 THEN %ADV = 'NOTHING YET' END IF QUERY PROCESS %PROCESS STATE %S %TRACE IS STRING LEN 255 %TRACE = 'STAT_CHECK:' - WITH ' Statement=' WITH %STMT - WITH ' %STATUS=' WITH %STATUS WITH '/' WITH %STATUSD *** AUDIT RESULT VARIABLE AFTER RECEIVE IF %STATEMENT = 7 THEN %TRACE = %TRACE WITH ' Result=' WITH %RESULT *** AUDIT REQSEND VARIABLE AFTER SEND OR SEND ERROR ELSEIF %STATEMENT = 8 OR %STATEMENT = 9 THEN %TRACE = %TRACE WITH ' Reqsend=' WITH %REQSEND END IF %TRACE = %TRACE - WITH ' State=' WITH %S - WITH ' Advice=' WITH %ADVICE WITH '/' WITH %ADV - WITH ' Cid=' WITH %PROCESS *** USE 'PRINT' FOR CLIENT PROGRAM, 'AUDIT' FOR SERVER PROGRAM IF $VIEW('IODEV') EQ '27' THEN AUDIT %TRACE ELSE PRINT %TRACE END IF ****************************************************************** *** END OF AUDITING *** ****************************************************************** RETURN: RETURN END SUBROUTINE STAT_CHECK ******************************************************************* * * * THE FOLLOWING VARIABLES MAY BE USED AS THE %STATEMENT PARAMETER * * IN A CALL TO STAT_CHECK, TO MAKE YOUR PROGRAM EASIER TO READ * * (BE SURE TO EXECUTE THESE ASSIGNMENT STATEMENTS *BEFORE* YOU * * REFERENCE THE VARIABLES.) * * * * EXAMPLE: OPEN PROCESS %CID * * CALL STAT_CHECK(%CID,%HRZN_OPEN,%RESULT,%REQSEND,%ADVICE) * * * ******************************************************************* %HRZN_OPEN = 1 %HRZN_CONFIRM = 2 %HRZN_CONFIRMED = 3 %HRZN_CLOSE = 4 %HRZN_FLUSH = 5 %HRZN_QUERY = 6 %HRZN_RECEIVE = 7 %HRZN_SEND = 8 %HRZN_SEND_ERROR = 9 %HRZN_SIGNAL = 10 %HRZN_INVITE = 11 %HRZN_TEST = 12 %HRZN_WAIT = 13 END PROCEDURE
Remote Updating Example
The applications considered thus far have been inquiry-only, but Horizon also permits remote file updating. By definition, remote updating of a local node occurs when data received at the local node during a Horizon conversation is stored at the local node. Horizon accommodates this single node updating using standard Model 204 recovery features.
Coordinated updating and recovery between multiple nodes is not provided with Version 2, Release 2 of Horizon. Multiple-node updating and recovery requires an additional conversation protocol, called two-phase commit, along with corresponding enhancements to the recovery logic of Model 204.
The example (in pseudo code) in Single-node remote update illustrates how a Horizon single-node remote update can be accomplished using existing Model 204 recovery logic. The arrows in the example indicate when data is physically transmitted across the network. The numbers in parentheses show the order in which the statements in the programs are processed.
The steps shown in parentheses in Single-node remote update are as follows:
Step | Description |
---|---|
(1) | Program A sends data to its remote partner. |
(2) | Program A issues a confirmation request. This causes the data and a confirmation indicator to be sent to Program B. |
(3) | Program B receives the data. If the receive fails for any reason, the appropriate cleanup logic is invoked. |
(4) | Program B does a second RECEIVE, and verifies that what it has received is the confirmation request. If the confirmation request is not present, the cleanup logic is called. An update unit is never started. |
(5) | Program B stores the data it receives into its file, and this begins an update unit. |
(6) | Program B acknowledges that it has made the update by issuing a CONFIRMED statement. |
(7) | If Program A is still active, $STATUS from the confirmation is 0, and Program B commits the current update unit. Otherwise, Program B backs the update out. |
(8-9) | When something (a confirmation or an error indication) is received, Program A reports the result to the end user. |
Multiple-node updating
An application that requires updates at more than one node can be written using the current version of Horizon, provided that it does not depend upon Model 204 recovery alone to assure it of database consistency across network nodes. Such an application can be designed in one of two ways:
-
The application is designed so that there are no database consistency dependencies across nodes.
In this case, Model 204 recovery protects each individual node. Such a design implies that each node's update is seen by recovery as a separate transaction, disjoint from updates at any other node.
- The application is designed so that the application takes responsibility for detecting and correcting cross-node inconsistencies.
Such a recovery scheme can sometimes be designed, but an extensive discussion of the issues involved is beyond the scope of this topic.
Double-node update shows an application that performs updates at two nodes. The numbers in parentheses show the order in which the statements in the programs are processed.
The steps shown in parentheses in Double-node update are as follows:
Steps | Description |
---|---|
(1) | Program A stores data into a record, and this begins an update unit. |
(2) | Program A sends a copy of the data to its remote partner. |
(3) | Program A issues a confirmation request. This causes the data and a confirmation indicator to be sent to Program B. |
(4) | Program B receives the data. If the RECEIVE fails for any reason, the appropriate cleanup logic is invoked. |
(5) | Program B stores the data it receives into its file. This begins an update unit. |
(6) | Program B verifies that what it has received is the confirmation request. If the confirmation request is not present, the update unit is backed out and the cleanup logic is called. |
(7) | Program B acknowledges that it has made the update by issuing a CONFIRMED statement. |
(8) | This step begins when the confirmation is sent. If Program A is still active, $STATUS from the confirmation is 0, and Program B commits the current update unit. |
(9) | When something (a confirmation or an error indication) is received, Program A acts according to what it receives:
|
Between-node data consistency
A database consistency problem can occur if Program A terminates before it gets a chance to make the decision at Step 9, or if Program B terminates before it completes Step 8. The application should be designed to check (perhaps at initialization time or just before performing a given update) that the database at each node "looks correct."
Another alternative is for the initiating node to keep a file to which it logs records of the nodes that have been successfully updated. In the event of a network failure, the data in this log file is used for manually coordinating recovery.
Note: The physical consistency of any Model 204 file is always taken care of by Model 204 recovery, and is not a consideration here. Logical consistency within a single Model 204 system is also provided. The only issue that the application designer needs to worry about is logical consistency of data among the different nodes that the application attempts to update.