Example: Power-handling CL program

You can use the sample program with a full uninterruptible power supply.

Although this sample CL program will work correctly as written, you should tailor it to your specific system requirements. For example, add additional recovery to the program by monitoring for error conditions specific to your system. You will also need to supply a user-written program that performs the steps necessary to prepare for a normal shutdown of the system. These steps may include holding job queues, sending messages, and ending subsystems. The program should restart normal operations should the power outage end before the system is powered down.

Note: By using the code examples, you agree to the terms of the Code license and disclaimer information.

The program performs the following:

  1. The power-handling program retrieves the system value QUPSMSGQ into the variables &LIB and &MSGQ. Although this is not absolutely necessary, it does help to ensure that the correct message queue is allocated each time the program is started. The program then deletes the message queue (if it already exists) and then creates it again. This step helps eliminate clearing the message queue or any problems that might occur if the message queue is damaged.
  2. After the message queue has been created, the program must allocate (ALCOBJ command) the message queue exclusively.
    Note: When the system value QUPSDLYTIM is set to *NOMAX, use one of the following methods to allocate the message queue that is specified for system value QUPSMSGQ:
    • Use the command CHGMSGQ MSGQ(UPSLIB/UPSMSGQ) MODE(*BREAK)
    • Include the ALCOBJ command within the power-handling program

    You may only use one of the methods that are listed.

    If a user or a program has not allocated the message queue, and a power outage occurs, the system performs an immediate quick shut down.

  3. At label A in the example power handling program, the Receive Message (RCVMSG) command is used to determine what message has been sent to the message queue. The RCVMSG command is also used to determine the amount of wait time (WAIT parameter) throughout the program.

    On line 27.00 of the example power-handling program, the value of the WAIT parameter on the RCVMSG command causes the program to wait 600 seconds (ten minutes). After ten minutes, the program checks to see if a controlled end to the job has occurred (using the ENDSBS or ENDJOB command). This prevents the program from delaying the ENDJOB or ENDSBS command.

    If you use ENDSBS *IMMED or ENDJOB *IMMED, then this part of the program can be removed. You can change the value for the WAIT parameter on the RCVMSG command to *MAX. The RCVMSG command runs immediately if the system sends a message to the message queue that is specified on the RCVMSG command. This occurs regardless of the value that is specified for the WAIT parameter.

  4. If the message that is received by the RCVMSG command is CPF1816 (system utility power failed), the program checks to see if this is a short power failure. The program runs a second RCVMSG command with a value of ten seconds for the WAIT parameter (you must decide how many seconds is adequate for your site).

    If the message that is received by the RCVMSG command within the specified ten seconds is CPF1817 (system utility power restored), then power was restored. The program returns to label A and starts the cycle again.

    If the ten second limit is reached and no message is received, then the power failure is longer than ten seconds and additional steps are necessary. At this point, you can call a user-written program that performs the following actions:
    • The program uses the HLDJOBQ command to hold certain long running batch jobs
    • The program notifies unaffected remote users
    • The program begins ending jobs and subsystems in an orderly manner
  5. At label B, in the example power-handling program, the program attempts to wait-out the power failure. The program retrieves the present time and places this information into a CL variable that is named &START. The present time is used to determine how much uninterruptible power supply time is left.

    A third RCVMSG command runs, and a CL variable that is named &WAIT (that was changed earlier in the program) determines the value for the WAIT parameter. The CL variable &WAIT is the amount of reserve power the uninterruptible power supply can provide. The value for the &WAIT variable at label A should be adjusted to the amount of reserve power that the uninterruptible power supply can provide. (The amount of reserve power is measured in seconds.)

    In the example program, the value of the &WAIT variable is set to 1200 seconds (20 minutes). If message CPF1817 (System utility power restored) is received during that time, then power has been restored, and another program can be called to restart normal system operations. The program then returns to label A and starts the cycle again. If message CPF1817 is not sent after 1200 seconds, then RCVMSG returns a blank message ID (not equal to CPF1817). This indicates that power has not been restored and an immediate system shut down is started. If a message other than CPF1817 is received during this 1200 second wait, the following actions occur:

    1. The program retrieves the present time, and calculates how much of the 1200 second wait period has elapsed.
    2. The program subtracts the difference, and changes the CL variable &WAIT to reflect that amount.
    3. The program returns to label B to use the remaining power that is provided by the uninterruptible power supply.

    This part of the program checks to see if a date change occurs, which is necessary should the power outage occur on a different date.

SEQNBR*...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...
 1.00        PGM
 2.00        DCL      VAR(&UPSMSGQ)  TYPE(*CHAR)  LEN(20)
 3.00        DCL      VAR(&LIB)      TYPE(*CHAR)  LEN(20)
 4.00        DCL      VAR(&MSGQ)     TYPE(*CHAR)  LEN(20)
 5.00        DCL      VAR(&MSGID)    TYPE(*CHAR)  LEN(7)
 6.00        DCL      VAR(&ENDSTS)   TYPE(*CHAR)  LEN(1)
 7.00        DCL      VAR(&WAIT)     TYPE(*DEC)   LEN(6)
 8.00        DCL      VAR(&HOUR)     TYPE(*DEC)   LEN(6)
 9.00        DCL      VAR(&MIN)      TYPE(*DEC)   LEN(6)
10.00        DCL      VAR(&SEC)      TYPE(*DEC)   LEN(6)
11.00        DCL      VAR(&TIME)     TYPE(*CHAR)  LEN(6)
12.00        DCL      VAR(&START)    TYPE(*DEC)   LEN(6)
13.00        DCL      VAR(&END)      TYPE(*DEC)   LEN(6)
14.00        DCL      VAR(&RESULT)   TYPE(*DEC)   LEN(6)
15.00
16.00        RTVSYSVAL  SYSVAL(QUPSMSGQ) RTNVAR(&UPSMSGQ)
17.00        CHGVAR     VAR(&MSGQ) VALUE(%SST(&UPSMSGQ 1 10))
18.00        CHGVAR     VAR(&LIB)  VALUE(%SST(&UPSMSGQ 11 10))
19.00        DLTMSGQ    MSGQ(&LIB/&MSGQ)
20.00        MONMSG     MSGID(CPF2105) /* Message queue not found. */
21.00        CRTMSGQ    MSGQ(&LIB/&MSGQ) TEXT('UPS Power handling +
22.00                          program message queue') AUT(*EXCLUDE)
23.00        ALCOBJ     OBJ((&LIB/&MSGQ *MSGQ *EXCL))
24.00
25.00  A:    RCVMSG     MSGQ(&LIB/&MSGQ) WAIT(600) RMV(*YES) +
26.00                          MSGID(&MSGID)
27.00        IF         COND(&MSGID *NE CPF1816) THEN(DO)
28.00        RTVJOBA    ENDSTS(&ENDSTS)
29.00        IF         COND(&ENDSTS *EQ '1') THEN(GOTO CMDLBL(ENDPGM))
30.00        GOTO       CMDLBL(A)
31.00        ENDDO
32.00
33.00       /* Check to see if this is a short power outage. */
34.00       IF         COND(&MSGID *EQ CPF1816) THEN(DO)
35.00       RCVMSG     MSGQ(&LIB/&MSGQ); WAIT(10) RMV(*YES) +
36.00                     MSGID(&MSGID); /* Wait ten seconds)
37.00       IF         COND(&MSGID *EQ CPF1817) THEN(GOTO CMDLBL(A))
38.00       ENDDO
39.00
40.00       /* Power outage was longer than 10 seconds.  */
41.00       CALL       PGM(LIB/PGM) /* User program that prepares +
42.00                          system for possible shutdown. */
43.00
44.00      /* Check to see if this is a long power outage. */
45.00       CHGVAR     VAR(&WAIT); VALUE(01200) /* 20 minutes. */
46.00  B:   RTVSYSVAL  SYSVAL(QTIME) RTNVAR(&TIME);
47.00       CHGVAR     VAR(&HOUR);  VALUE(%SST(&TIME 1 2))
48.00       CHGVAR     VAR(&MIN);   VALUE(%SST(&TIME 3 2))
49.00       CHGVAR     VAR(&SEC);   VALUE(%SST(&TIME 5 2))
50.00       CHGVAR     VAR(&START); VALUE((&SEC); + (&MIN * 60) + +
51.00                     (&HOUR * 3600))
52.00       RCVMSG     MSGQ(&LIB/&MSGQ); WAIT(&WAIT); RMV(*YES) +
53.00                          MSGID(&MSGID);
54.00       IF         COND(&MSGID *EQ CPF1817) THEN(DO)
55.00       CALL       PGM(LIB/PGM) /* User program that restarts +
56.00                     system operations. */
57.00       GOTO       CMDLBL(A)
58.00       ENDDO
59.00
60.00       IF         COND(&MSGID *NE CPF1817) THEN(DO)
61.00       RTVSYSVAL  SYSVAL(QTIME) RTNVAR(&TIME)
62.00       CHGVAR     VAR(&HOUR)  VALUE(%SST(&TIME 1 2))
63.00       CHGVAR     VAR(&MIN)   VALUE(%SST(&TIME 3 2))
64.00       CHGVAR     VAR(&SEC)   VALUE(%SST(&TIME 5 2))
65.00       CHGVAR     VAR(&END)   VALUE((&SEC) + (&MIN * 60) + +
66.00                   (&HOUR * 3600))
67.00       CHGVAR     VAR(&RESULT); VALUE(&END - &START)
68.00       IF         COND(&RESULT < 0) THEN(CHGVAR VAR(&RESULT) +
69.00                     VALUE(86400 + &RESULT)) /* Check for +
70.00                          change of day.  86400 = 24 hours. */
71.00       IF         COND(&RESULT *GE &WAIT) THEN(PWRDWNSYS +
72.00                   OPTION(*IMMED) /* uninterruptible power supply
											 battery reserve has expired. */
74.00                    
75.00       CHGVAR     VAR(&WAIT) VALUE(&WAIT - &RESULT) /* UPS +
76.00                          battery reserve has not expired. */
77.00       GOTO       CMDLBL(B)
78.00       ENDDO
79.00
80.00  ENDPGM:    DLCOBJ     OBJ((&LIB/&MSGQ *MSGQ *EXCL))
81.00             ENDPGM
Related tasks
Implementing a power-handling program
Related reference
Example: Testing a power-handling CL program