This indicates a status update missing for the member. When the
member's status update is missing, the routine has to initiate a takeover
so that another member can assume the member's work. However, once
either of these flags is turned on, XCF does not turn it off until
the member resumes updating its status field. The group user routine
might be called several times, and this flag might continuously be
on. So, the routine has a switch (FUNCTON) that it turns on the first
time it is called for a status update missing.
The routine does the following when first called with either the
GEPLMISR flag or the GEPLMISD flag on:
- The routine turns on its own switch (FUNCTON).
- The routine posts a task whose job is to change user state values
so that the backup member becomes the primary member. The main routine
attached this task with an ECB, and passed a parameter list containing
the address of the member's data structure. The data structure contains
the information the task needs to do the takeover.
- The routine then checks to see if the member must be added to
the table.
If this is not the first time the routine is called with either
the GEPLMISR flag or the GEPLMISD flag on, the routine knows that
no takeover work needs to be done. The routine then checks to see
if the member must be added to the table.
Figure 1. Summary of Group
User Routine Logic (Part 1 of 3)
Figure 2. Summary of
Group User Routine Logic (Part 2 of 3)
Figure 3. Summary of
Group User Routine Logic (Part 3 of 3)
Here is an example
of the group user routine code.
***************************************************************
* *
* GROUP USER ROUTINE *
* *
***************************************************************
GEXIT3 CSECT
GEXIT3 AMODE 31
GEXIT3 RMODE ANY
@MAINENT DS 0H
USING *,R15
B @ENTRY
DC AL1(16)
DC C'GR 90010 GEXIT3'
DROP R15
***************************************************************
* *
* ENTRY LINKAGE *
* *
***************************************************************
@ENTRY STM R14,R12,12(R13)
LR R12,R15
@PSTART EQU GEXIT3
*
* SET UP BASE REGISTER TO 12
*
USING @PSTART,R12
*
* SET UP DYNAMIC AREA
*
SLR R15,R15
IC R15,@SIZDATD
SLR R0,R0
ICM R0,7,@SIZDATD+1
STORAGE OBTAIN,LENGTH=(0),SP=(15)
LR R10,R1
USING @DATD,R10
ST R13,4(,R10)
ST R10,8(,R13)
LM R15,R1,16(R13)
LR R13,R10
***************************************************************
* *
* GROUP USER CODE *
* *
***************************************************************
*
* GET ADDRESSABILITY TO THE PARAMETER LIST
*
LR R8,R1
USING GEPL,R8
*
* CHECK THE GEPLFLG2 FIELD FOR MEMBER-RELATED EVENT
* (GEPLMEME BIT). IF NOT MEMBER-RELATED, BRANCH BECAUSE
* NO ACTION REQUIRED.
*
TM GEPLFLG2,X'80'
BNO @FINI
*
* CHECK THE GEPLFLG2 FIELD FOR STATUS UPDATE MISSING
* (GEPLMISR or GEPLMISD BITS). IF NEITHER BIT IS ON,
* BRANCH TO CHECK FOR TABLE UPDATES.
*
TM GEPLFLG2,X'30'
BZ @NEXTCHK
*
* GET ADDRESSABILITY TO THE MEMBER DATA, WHICH CONTAINS
* THE ADDRESS OF MDATASTR. MDATASTR CONTAINS THE BYTE THAT
* THE GROUP USER ROUTINE TURNS ON IF THIS IS THE FIRST TIME
* CALLED FOR STATUS UPDATE MISSING. IF THE BYTE IS ON ALREADY,
* BRANCH TO CHECK FOR TABLE UPDATES. IF THE BYTE IS NOT ON,
* TURN IT ON.
*
L R5,GEPLMDAT
USING MDATASTR,R5
CLI FUNCTON,X'00'
BNE @NEXTCHK
MVC FUNCTON(1),HEX11
*
* GET THE ADDRESS OF THE TASK'S ECB AND POST THE TASK.
* THE TASK WAS ATTACHED BY THE MAIN ROUTINE. THE MAIN ROUTINE
* PASSED THE ADDRESS OF THE MDATASTR IN THE PARAMETER LIST
* ON THE ATTACH MACRO. THE TASK'S JOB IS TO SWITCH THE
* PRIMARY AND BACKUP MEMBERS.
*
L R7,POSTLNTH MOVE LENGTH OF STATIC AREA TO R7
BCTR R7,0
EX R7,@SETPARM
L R9,TASKECB
POST (R9),LINKAGE=SYSTEM,MF=(E,POSTLSTD)
*
* BRANCH HERE TO CHECK FOR TABLE UPDATES. ONLY MEMBERS WHO
* ARE CURRENTLY ACTIVE OR HAVE BEEN ACTIVE SHOULD BE IN
* THE TABLE. IF THE MEMBER'S CURRENT STATE IS ACTIVE,
* BRANCH SO THE TABLE CAN BE UPDATED IF NECESSARY.
*
@NEXTCHK CLI GEPLNEWS,GEACTIVE
BE @CREATBL
*
* CHECK TO SEE IF THE MEMBER WAS PREVIOUSLY ACTIVE. IF NOT
* PREVIOUSLY ACTIVE, BRANCH TO THE END OF THE PROGRAM.
*
CLI GEPLOLDS,GEACTIVE
BNE @FINI
*
* BRANCH HERE TO SEE IF A MEMBER IS CURRENTLY IN THE TABLE.
* IF SO, UPDATE THE MEMBER'S TOKEN. IF NOT, ADD THE MEMBER.
*
* GET ADDRESSABILITY TO THE MEMBER DATA, WHICH CONTAINS
* THE ADDRESS OF MDATASTR. MDATASTR CONTAINS THE ADDRESS OF
* THE TABLE. LOOP THROUGH THE TABLE TO SEE IF THE MEMBER
* IS THERE. IF THE MEMBER IS THERE, BRANCH OUT OF THE
* TABLE TO UPDATE THE MEMBER. IF THE LOOP COMPLETES WITHOUT
* FINDING THE MEMBER, BRANCH OUT OF THE LOOP TO ADD THE MEMBER.
*
@CREATBL L R5,GEPLMDAT
@CHKTBL L R6,TBLADDR START OF THE TABLE
L R7,NEXTITEM NEXT AVAILABLE SLOT IN TABLE
@TBLLOOP CR R6,R7 IS THIS THE END OF THE TABLE?
BE @STORTBL YES
USING ITEM,R6
CLC NAME(16),GEPLMNAM MEMBER ALREADY IN THE TABLE?
BE @FOUND IF YES, BRANCH
A R6,INCREM MOVE TO NEXT MEMBER IN THE TABLE
B @TBLLOOP
*
* BRANCH HERE WHEN THE MEMBER IS ALREADY IN THE TABLE
*
@FOUND MVC TOKEN(8),GEPLMTOK UPDATE THE CURRENT TOKEN
B @FINI
*
* BRANCH HERE WHEN THE MEMBER IS TO BE ADDED TO THE TABLE
*
@STORTBL L R7,NEXTITEM PLACE THE NEXT SLOT AVAILABLE IN R7
USING ITEM,R7 USE MAPPING OF TABLE CONTENTS
MVC NAME(16),GEPLMNAM STORE THE MEMBER NAME
MVC TOKEN(8),GEPLMTOK STORE THE MEMBER TOKEN
A R7,INCREM INCREMENT THE POINTER
ST R7,NEXTITEM STORE THE POINTER
DROP R7
B @FINI
*
* RELEASE DYNAMIC AREA
*
@FINI LR R1,R10
L R13,4(,R13)
SLR R15,R15
IC R15,@SIZDATD
SLR R0,R0
ICM R0,7,@SIZDATD+1
STORAGE RELEASE,LENGTH=(0),ADDR=(1),SP=(15)
***************************************************************
* *
* EXIT LINKAGE *
* *
***************************************************************
LM R14,R12,12(R13)
BR R14
@SETPARM MVC POSTLSTD(0),POSTLST1 SET UP DYNAMIC AREA FOR POST
GEXIT3 CSECT ,
LTORG
DS 0D
INCREM DC F'24'
HEX11 DC X'11'
POSTLST1 POST MF=L
POSTLNTH DC A(*-POSTLST1)
@SIZDATD DS 0A
DC AL1(0)
DC AL3(@DYNSIZE)
R0 EQU 0
R1 EQU 1
R2 EQU 2
R3 EQU 3
R4 EQU 4
R5 EQU 5
R6 EQU 6
R7 EQU 7
R8 EQU 8
R9 EQU 9
R10 EQU 10
R11 EQU 11
R12 EQU 12
R13 EQU 13
R14 EQU 14
R15 EQU 15
@ENDDATA EQU *
@DATA DS 0H
@DATD DSECT
DS 0F
SAVEAREA DS 18F
POSTLSTD POST MF=L
@ENDDATD DS 0X
@DYNSIZE EQU ((@ENDDATD-@DATD+7)/8)*8
***************************************************************
* *
* MAPPING OF THE DATA STRUCTURE (MDATASTR) POINTED TO BY *
* MEMDATA (GEPLMDAT FIELD IN PARAMETER LIST) *
* *
* THIS SAME DATA STRUCTURE IS USED BY THE STATUS USER *
* ROUTINE. SOME FIELDS ARE NOT USED BY THE GROUP USER *
* ROUTINE, BUT ARE USED ONLY BY THE STATUS USER ROUTINE. *
* *
* TBLADDR ADDRESS OF TABLE MAINTAINED BY *
* GROUP USER ROUTINE *
* NEXTITEM ADDRESS OF NEXT AVAILABLE SLOT IN *
* TABLE *
* WRKQADDR ADDRESS OF MEMBER'S WORK QUEUE *
* (USED BY STATUS USER ROUTINE) *
* NXTWRKAD ADDRESS OF NEXT AVAILABLE SLOT IN *
* MEMBER'S WORK QUEUE *
* (USED BY STATUS USER ROUTINE) *
* TASKECB ADDRESS OF THE ATTACHED TASK'S ECB *
* (THIS TASK IS ATTACHED BY THE MAIN *
* ROUTINE.) *
* MAINECB ADDRESS OF ECB USED FOR SYNCHRONIZING *
* (THE MAIN ROUTINE WAITS ON THIS ECB, *
* WHICH THE ATTACHED TASK POSTS WHEN *
* IT COMPLETES ITS WORK.) *
* FUNCTON GROUP USER ROUTINE TURNS THIS SWITCH *
* ON WHEN CALLED FOR THE FIRST TIME *
* FOR A STATUS UPDATE MISSING. *
* RESUMEB MAIN ROUTINE TURNS THIS SWITCH ON *
* WHEN IT RESUMES UPDATING ITS STATUS *
* FIELD. *
* *
***************************************************************
MDATASTR DSECT
TBLADDR DS 1F
NEXTITEM DS 1F
WRKQADDR DS 1F
NXTWRKAD DS 1F
TASKECB DS 1F
MAINECB DS 1F
FUNCTON DS X
RESUMEB DS X
ITEM DSECT MAPPING OF ELEMENT IN THE TABLE
NAME DS CL16 MEMBER NAME
TOKEN DS XL8 CURRENT TOKEN OF MEMBER
***************************************************************
* *
* MAPPING MACROS *
* *
***************************************************************
IXCYGEPL
END GEXIT3