Horizon SOUL sample programs: Difference between revisions

From m204wiki
Jump to navigation Jump to search
(Created page with "==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 upda...")
 
 
(One intermediate revision by the same user not shown)
Line 203: Line 203:
===Program===
===Program===
<p class="code">PROCEDURE SERVER
<p class="code">PROCEDURE SERVER
BEGIN
BEGIN<nowiki>
<nowiki>
******************************************************************
******************************************************************
***  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  ***
***  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  ***
Line 225: Line 224:
***        DATA AND SUBROUTINES        ***
***        DATA AND SUBROUTINES        ***
******************************************
******************************************
  %CID IS STRING LEN 8
  %CID IS STRING LEN 8
  %RECVMSG IS STRING LEN 255
  %RECVMSG IS STRING LEN 255
Line 249: Line 247:


RECEIVE_LOOP:
RECEIVE_LOOP:
RECEIVE %RECVMSG FROM %CID RESULT %RESULT
RECEIVE %RECVMSG FROM %CID RESULT %RESULT


Line 262: Line 259:


*** FALL THROUGH WHEN ADVICE=1 (RECEIVED DATA) ***
*** FALL THROUGH WHEN ADVICE=1 (RECEIVED DATA) ***
AUDIT 'RECEIVED FROM PARTNER:' AND %RECVMSG
AUDIT 'RECEIVED FROM PARTNER:' AND %RECVMSG


Line 268: Line 264:


SEND:
SEND:
SEND 'HELLO, SAILOR!' TO %CID REQSEND %REQSEND
SEND 'HELLO, SAILOR!' TO %CID REQSEND %REQSEND


Line 277: Line 272:


*** FALL THROUGH WHEN ADVICE=1 (SEND SUCCEEDED) ***
*** FALL THROUGH WHEN ADVICE=1 (SEND SUCCEEDED) ***
JUMP TO RECEIVE_LOOP
JUMP TO RECEIVE_LOOP


Line 285: Line 279:


HANDLE_CONFIRM:
HANDLE_CONFIRM:
AUDIT '*** PARTNER REQUESTED CONFIRMATION ***'
AUDIT '*** PARTNER REQUESTED CONFIRMATION ***'


Line 297: Line 290:


*** FALL THROUGH IF ADVICE = 1 (SEND ERROR SUCCEEDED) ***
*** FALL THROUGH IF ADVICE = 1 (SEND ERROR SUCCEEDED) ***
CLOSE PROCESS %CID
CLOSE PROCESS %CID


*** IF CLOSE FAILS, JUST GIVE UP
*** IF CLOSE FAILS, JUST GIVE UP
CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE)
CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE)
JUMP TO (END, -
JUMP TO (END, -
Line 308: Line 299:


HANDLE_SIGNAL:
HANDLE_SIGNAL:
AUDIT '*** PARTNER SENT SIGNAL - CLOSING CONVERSATION ***'
AUDIT '*** PARTNER SENT SIGNAL - CLOSING CONVERSATION ***'


CLOSE PROCESS %CID
CLOSE PROCESS %CID
*** IF CLOSE FAILS, JUST GIVE UP
*** IF CLOSE FAILS, JUST GIVE UP
CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE)
CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE)
JUMP TO (END, -
JUMP TO (END, -
Line 321: Line 309:


HANDLE_ERROR:
HANDLE_ERROR:
AUDIT '*** PARTNER SENT ERROR - CLOSING CONVERSATION ***'
AUDIT '*** PARTNER SENT ERROR - CLOSING CONVERSATION ***'


CLOSE PROCESS %CID
CLOSE PROCESS %CID
*** IF CLOSE FAILS, JUST GIVE UP
*** IF CLOSE FAILS, JUST GIVE UP
CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE)
CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE)
JUMP TO (END, -
JUMP TO (END, -
Line 334: Line 319:


HANDLE_CLOSE:
HANDLE_CLOSE:
AUDIT '*** PARTNER CLOSED CONVERSATION ***'
AUDIT '*** PARTNER CLOSED CONVERSATION ***'


CLOSE PROCESS %CID
CLOSE PROCESS %CID
*** IF CLOSE FAILS, JUST GIVE UP
*** IF CLOSE FAILS, JUST GIVE UP
CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE)
CALL STAT_CHECK (%CID, %HRZN_CLOSE, %RESULT, %REQSEND, %ADVICE)
JUMP TO (END, -
JUMP TO (END, -
Line 347: Line 329:


BOGUS:
BOGUS:
AUDIT '*** STAT_CHECK RETURNED AN UNDEFINED ADVICE CODE ***'
AUDIT '*** STAT_CHECK RETURNED AN UNDEFINED ADVICE CODE ***'
JUMP TO END
JUMP TO END


ABORT:
ABORT:
AUDIT '*** STAT_CHECK ADVISES THAT WE ABORT ***'
AUDIT '*** STAT_CHECK ADVISES THAT WE ABORT ***'
JUMP TO END
JUMP TO END


END:
END:
*** ALWAYS SET THE APSY COMMUNICATION VARIABLE BEFORE LEAVING
*** ALWAYS SET THE APSY COMMUNICATION VARIABLE BEFORE LEAVING


Line 382: Line 361:


===Subroutine===
===Subroutine===
<p class="code">PROCEDURE STAT_CHECK <nowiki>*************************************************************************
<p class="code">PROCEDURE STAT_CHECK <nowiki>
 
**********************************************************************
SUBROUTINE STAT_CHECK ( %PROCESS IS STRING LEN 10 INPUT -
SUBROUTINE STAT_CHECK ( %PROCESS IS STRING LEN 10 INPUT -
%STATEMENT IS FLOAT INPUT, -
%STATEMENT IS FLOAT INPUT, -
Line 389: Line 368:
%REQSEND IS FLOAT INPUT, -
%REQSEND IS FLOAT INPUT, -
%ADVICE IS FLOAT OUTPUT )
%ADVICE IS FLOAT OUTPUT )
**********************************************************************
**********************************************************************
* STAT_CHECK SHOULD BE CALLED AFTER EACH HORIZON STATEMENT.          *
* STAT_CHECK SHOULD BE CALLED AFTER EACH HORIZON STATEMENT.          *
Line 424: Line 402:
* - -  -  - - - - - -  -  - X -    9 - NO RECEIPTS YET              *
* - -  -  - - - - - -  -  - X -    9 - NO RECEIPTS YET              *
**********************************************************************
**********************************************************************
%STATUS = $STATUS
%STATUS = $STATUS
%STATUSD = $STATUSD
%STATUSD = $STATUSD
JUMP TO (O,CF,CFD,C,F,Q,R,S,SE,SP,I,T,W) %STATEMENT
JUMP TO (O,CF,CFD,C,F,Q,R,S,SE,SP,I,T,W) %STATEMENT
X:  **********************************
X:  **********************************
     *      INVALID STATEMENT CODE    *
     *      INVALID STATEMENT CODE    *
     **********************************
     **********************************
     JUMP TO ABORT
     JUMP TO ABORT
O:  **********************************
O:  **********************************
     *          OPEN PROCESS          *
     *          OPEN PROCESS          *
     **********************************
     **********************************
     IF %STATUS = 0 THEN
     IF %STATUS = 0 THEN
     JUMP TO CONTINUE
     JUMP TO CONTINUE
Line 445: Line 417:
     JUMP TO ABORT
     JUMP TO ABORT
     END IF
     END IF
CF: **********************************
CF: **********************************
     *            CONFIRM            *
     *            CONFIRM            *
     **********************************
     **********************************
     *** FIRST SEE IF SIGNAL RECEIVED FROM PARTNER
     *** FIRST SEE IF SIGNAL RECEIVED FROM PARTNER
  IF %REQSEND = 1 THEN
  IF %REQSEND = 1 THEN
   JUMP TO REQUEST_TO_SEND
   JUMP TO REQUEST_TO_SEND
Line 458: Line 427:


   *** CHECK FOR 2/2 (PARTNER RESPONDED TO CONFIRM WITH SEND ERROR)
   *** CHECK FOR 2/2 (PARTNER RESPONDED TO CONFIRM WITH SEND ERROR)
  ELSEIF %STATUS = 2 AND %STATUSD = 2 THEN
  ELSEIF %STATUS = 2 AND %STATUSD = 2 THEN
   JUMP TO SEND_ERROR
   JUMP TO SEND_ERROR
Line 464: Line 432:
   JUMP TO ABORT
   JUMP TO ABORT
  END IF
  END IF
CFD: **********************************
CFD: **********************************
     *          CONFIRMED            *
     *          CONFIRMED            *
     **********************************
     **********************************
  %S IS STRING LEN 8
  %S IS STRING LEN 8
  IF %STATUS = 0 THEN
  IF %STATUS = 0 THEN


*** SEE WHAT THE CONVERSATION STATE HAS CHANGED TO
*** SEE WHAT THE CONVERSATION STATE HAS CHANGED TO
   QUERY PROCESS %PROCESS STATE %S
   QUERY PROCESS %PROCESS STATE %S
   IF %S = 'CLOSE' THEN
   IF %S = 'CLOSE' THEN
Line 487: Line 451:
   JUMP TO ABORT
   JUMP TO ABORT
  END IF
  END IF
C:  **********************************
C:  **********************************
     *        CLOSE PROCESS          *
     *        CLOSE PROCESS          *
     **********************************
     **********************************
  IF %STATUS = 0 THEN
  IF %STATUS = 0 THEN
   JUMP TO CONTINUE
   JUMP TO CONTINUE


     *** CHECK FOR 2/2 (PARTNER RESPONDED TO CONFIRM WITH SEND ERROR)
     *** CHECK FOR 2/2 (PARTNER RESPONDED TO CONFIRM WITH SEND ERROR)
  ELSEIF %STATUS = 2 AND %STATUSD = 2 THEN
  ELSEIF %STATUS = 2 AND %STATUSD = 2 THEN
   JUMP TO SEND_ERROR
   JUMP TO SEND_ERROR
Line 502: Line 463:
   JUMP TO ABORT
   JUMP TO ABORT
  END IF
  END IF
F:  **********************************
F:  **********************************
     *        FLUSH PROCESS          *
     *        FLUSH PROCESS          *
     **********************************
     **********************************
  IF %STATUS = 0 THEN
  IF %STATUS = 0 THEN
   JUMP TO CONTINUE
   JUMP TO CONTINUE
Line 512: Line 471:
   JUMP TO ABORT
   JUMP TO ABORT
  END IF
  END IF
Q:  **********************************
Q:  **********************************
     *        QUERY PROCESS          *
     *        QUERY PROCESS          *
     **********************************
     **********************************
  IF %STATUS = 0 THEN
  IF %STATUS = 0 THEN
   JUMP TO CONTINUE
   JUMP TO CONTINUE
Line 522: Line 479:
   JUMP TO ABORT
   JUMP TO ABORT
  END IF
  END IF
R:  **********************************
R:  **********************************
     *            RECEIVE            *
     *            RECEIVE            *
Line 532: Line 488:


   *** ANALYZE THE RESULT VARIABLE FOR APPROPRIATE ACTION
   *** ANALYZE THE RESULT VARIABLE FOR APPROPRIATE ACTION
   *** DATA TRUNCATED OR INCOMPLETE - ASSUME THIS ISN'T DESIRABLE
   *** DATA TRUNCATED OR INCOMPLETE - ASSUME THIS ISN'T DESIRABLE
   IF %RESULT = 'DATA TRUNCATED' THEN
   IF %RESULT = 'DATA TRUNCATED' THEN
   JUMP TO ABORT
   JUMP TO ABORT
Line 543: Line 497:


   *** ALL FLAVORS OF CONFIRM STATE - TELL USER TO DO 'CONFIRMED'.
   *** ALL FLAVORS OF CONFIRM STATE - TELL USER TO DO 'CONFIRMED'.
    *** AFTERWARD, STAT_CHECK WILL SAY 'SEND', 'CLOSE', ETC.
  *** AFTERWARD, STAT_CHECK WILL SAY 'SEND', 'CLOSE', ETC.
 
   ELSEIF %RESULT = 'CONFIRM' THEN
   ELSEIF %RESULT = 'CONFIRM' THEN
   JUMP TO CONFIRM
   JUMP TO CONFIRM
Line 556: Line 509:


   *** CHECK FOR 2/2 (PARTNER RESPONDED TO CONFIRM WITH SEND ERROR)
   *** CHECK FOR 2/2 (PARTNER RESPONDED TO CONFIRM WITH SEND ERROR)
  ELSEIF %STATUS = 2 AND %STATUSD = 2 THEN
  ELSEIF %STATUS = 2 AND %STATUSD = 2 THEN
   JUMP TO SEND_ERROR
   JUMP TO SEND_ERROR


   *** CHECK FOR 4/0 (INDICATES PARTNER ENDED CONVERSATION NORMALLY)
   *** CHECK FOR 4/0 (INDICATES PARTNER ENDED CONVERSATION NORMALLY)
  ELSEIF %STATUS = 4 AND %STATUSD = 0 THEN
  ELSEIF %STATUS = 4 AND %STATUSD = 0 THEN
   JUMP TO CLOSE_BY_REMOTE
   JUMP TO CLOSE_BY_REMOTE
Line 567: Line 518:
   JUMP TO ABORT
   JUMP TO ABORT
  END IF
  END IF
S:  **********************************
S:  **********************************
     *              SEND              *
     *              SEND              *
Line 575: Line 525:


     *** SEE IF SIGNAL RECEIVED FROM PARTNER
     *** SEE IF SIGNAL RECEIVED FROM PARTNER
   IF %REQSEND = 1 THEN
   IF %REQSEND = 1 THEN
   JUMP TO REQUEST_TO_SEND
   JUMP TO REQUEST_TO_SEND
Line 583: Line 532:


   *** CHECK FOR 2/2 (PARTNER RESPONDED TO CONFIRM WITH SEND ERROR)
   *** CHECK FOR 2/2 (PARTNER RESPONDED TO CONFIRM WITH SEND ERROR)
  ELSEIF %STATUS = 2 AND %STATUSD = 2 THEN
  ELSEIF %STATUS = 2 AND %STATUSD = 2 THEN
   JUMP TO SEND_ERROR
   JUMP TO SEND_ERROR
Line 589: Line 537:
   JUMP TO ABORT
   JUMP TO ABORT
  END IF
  END IF
SE: **********************************
SE: **********************************
     *          SEND ERROR            *
     *          SEND ERROR            *
Line 595: Line 542:


   *** SEE IF SIGNAL RECEIVED FROM PARTNER
   *** SEE IF SIGNAL RECEIVED FROM PARTNER
  IF %REQSEND = 1 THEN
  IF %REQSEND = 1 THEN
   JUMP TO REQUEST_TO_SEND
   JUMP TO REQUEST_TO_SEND


   *** NO SIGNAL, SO CHECK %STATUS
   *** NO SIGNAL, SO CHECK %STATUS
  ELSEIF %STATUS = 0 THEN
  ELSEIF %STATUS = 0 THEN
   JUMP TO CONTINUE
   JUMP TO CONTINUE
Line 606: Line 551:
   JUMP TO ABORT
   JUMP TO ABORT
  END IF
  END IF
SP: **********************************
SP: **********************************
     *        SIGNAL PROCESS        *
     *        SIGNAL PROCESS        *
     **********************************
     **********************************
  IF %STATUS = 0 THEN
  IF %STATUS = 0 THEN
   JUMP TO CONTINUE
   JUMP TO CONTINUE
Line 616: Line 559:
   JUMP TO ABORT
   JUMP TO ABORT
  END IF
  END IF
I:  **********************************
I:  **********************************
     *        INVITE                *
     *        INVITE                *
     **********************************
     **********************************
  IF %STATUS = 0 THEN
  IF %STATUS = 0 THEN
   JUMP TO CONTINUE
   JUMP TO CONTINUE
Line 634: Line 575:
   JUMP TO ABORT
   JUMP TO ABORT
  END IF
  END IF
  T: **********************************
  T: **********************************
     *      TEST FOR RECEIPT        *
     *      TEST FOR RECEIPT        *
     **********************************
     **********************************
  IF %STATUS = 0 THEN
  IF %STATUS = 0 THEN
   JUMP TO CONTINUE
   JUMP TO CONTINUE
Line 652: Line 591:
   JUMP TO ABORT
   JUMP TO ABORT
  END IF
  END IF
  W: **********************************
  W: **********************************
     *      WAIT FOR RECEIPT        *
     *      WAIT FOR RECEIPT        *
     **********************************
     **********************************
  IF %STATUS = 0 THEN
  IF %STATUS = 0 THEN
   JUMP TO CONTINUE
   JUMP TO CONTINUE
Line 665: Line 602:
  END IF
  END IF
  JUMP TO ABORT
  JUMP TO ABORT
******************************************************************
******************************************************************
***              SET THE ADVICE CODE AND EXIT.                ***
***              SET THE ADVICE CODE AND EXIT.                ***
Line 672: Line 608:
  %ADVICE = 1
  %ADVICE = 1
  JUMP TO EXIT
  JUMP TO EXIT
ABORT:
ABORT:
  %ADVICE = 2
  %ADVICE = 2
  JUMP TO EXIT
  JUMP TO EXIT
SEND_ERROR:
SEND_ERROR:
  %ADVICE = 3
  %ADVICE = 3
  JUMP TO EXIT
  JUMP TO EXIT
REQUEST_TO_SEND:
REQUEST_TO_SEND:
  %ADVICE = 4
  %ADVICE = 4
  JUMP TO EXIT
  JUMP TO EXIT
SEND:
SEND:
  %ADVICE = 5
  %ADVICE = 5
  JUMP TO EXIT
  JUMP TO EXIT
CLOSE_BY_REMOTE:
CLOSE_BY_REMOTE:
  %ADVICE = 6
  %ADVICE = 6
  JUMP TO EXIT
  JUMP TO EXIT
CONFIRM:
CONFIRM:
  %ADVICE = 7
  %ADVICE = 7
  JUMP TO EXIT
  JUMP TO EXIT
NEVER_MORE:
NEVER_MORE:
  %ADVICE = 8
  %ADVICE = 8
  JUMP TO EXIT
  JUMP TO EXIT
NOT_YET:
NOT_YET:
  %ADVICE = 9
  %ADVICE = 9
  JUMP TO EXIT
  JUMP TO EXIT
******************************************************************
******************************************************************
***                  SUBROUTINE EXIT PATH                    ***
***                  SUBROUTINE EXIT PATH                    ***
******************************************************************
******************************************************************
EXIT:
EXIT:
******************************************************************
******************************************************************
***  NOTE: THE FOLLOWING AUDIT LOGIC IS USEFUL AS A DEBUGGING  ***
***  NOTE: THE FOLLOWING AUDIT LOGIC IS USEFUL AS A DEBUGGING  ***
Line 781: Line 706:


     *** AUDIT RESULT VARIABLE AFTER RECEIVE
     *** AUDIT RESULT VARIABLE AFTER RECEIVE
  IF %STATEMENT = 7 THEN
  IF %STATEMENT = 7 THEN
   %TRACE = %TRACE WITH ' Result=' WITH %RESULT
   %TRACE = %TRACE WITH ' Result=' WITH %RESULT


   *** AUDIT REQSEND VARIABLE AFTER SEND OR SEND ERROR
   *** AUDIT REQSEND VARIABLE AFTER SEND OR SEND ERROR
  ELSEIF %STATEMENT = 8 OR %STATEMENT = 9 THEN
  ELSEIF %STATEMENT = 8 OR %STATEMENT = 9 THEN
   %TRACE = %TRACE WITH ' Reqsend=' WITH %REQSEND
   %TRACE = %TRACE WITH ' Reqsend=' WITH %REQSEND
Line 797: Line 720:


   *** USE 'PRINT' FOR CLIENT PROGRAM, 'AUDIT' FOR SERVER PROGRAM
   *** USE 'PRINT' FOR CLIENT PROGRAM, 'AUDIT' FOR SERVER PROGRAM
  IF $VIEW('IODEV') EQ '27' THEN
  IF $VIEW('IODEV') EQ '27' THEN
   AUDIT %TRACE
   AUDIT %TRACE
Line 806: Line 728:
***                      END OF AUDITING                      ***
***                      END OF AUDITING                      ***
******************************************************************
******************************************************************
RETURN: RETURN
RETURN: RETURN
END SUBROUTINE STAT_CHECK
END SUBROUTINE STAT_CHECK
*******************************************************************
*******************************************************************
*                                                                *
*                                                                *
Line 834: Line 754:
%HRZN_TEST          = 12
%HRZN_TEST          = 12
%HRZN_WAIT          = 13
%HRZN_WAIT          = 13
END PROCEDURE
END PROCEDURE</nowiki>  </p>
 
</nowiki>  </p>


==Remote Updating Example ==
==Remote Updating Example ==

Latest revision as of 20:37, 30 September 2015

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.

Single node remote update

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:

  1. 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.

  2. 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.

Double-node update

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:
  • A confirmation ($STATUS=0) signifies that Program B successfully received the update data and stored its record, and is presently committing the update. Program A can therefore commit its update with the near certainty that its partner's commit will also succeed.
  • An error ($STATUS0) signifies that, for some reason, the Program B update did not succeed. Program A therefore backs out its update.

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.