Trailing-Edge
-
PDP-10 Archives
-
BB-H506D-SM_1983
-
cobol/source/lsu.mac
There are 14 other files named lsu.mac in the archive. Click here to see a list.
; UPD ID= 3573 on 6/9/81 at 5:13 PM by MAYBERRY
TITLE LSU FOR LIBOL
SUBTTL LIBOL'S SIMULTANEOUS UPDATE PACKAGE.
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1974, 1981 BY DIGITAL EQUIPMENT CORPORATION
;REVISION HISTORY:
;V12 *****
; WTK 01-Nov-80 ;[654] Supplement ENQ/DEQ error return message.
; HAM 03-Oct-80 ;[650] Make CNTRY external.
; HAM 21-MAR-79 ;[565] FIX LFENQ. CALL TO C.OPEN, FLAG TO SHOW IT'S DONE
; HAM 16-JAN-79 ;[550] FIX NULL CONVERSION IN LRDEQ
; EHM 12-SEP-78 ;[534] FIX EOF FOR LOW-VALUES READ OF ISAM FILES
; EHM 23-JUN-78 ;[532] FIX ILLEGAL INSTRUCTION
;V10 *****
; DW-EM 27-FEB-78 ;[524] FIX RETAIN/READ OF COMP ISAM KEYS
; 13-SEP-76 ; [456] FIX RANDOM BLOCK NUMBER CALCULATION SO
; CORRECT BLOCK NUMBER GETS UPDATED WHEN IT SHOULD
; 02-SEP-76 ; [455] FIX KEY OF 0 READ OF RANDOM FILES WITH
; MISSING RECORDS, REQUIRES CHANGE TO COMUNI
; 16-AUG-76 ; [447] FIX LOW-VALUES SIMUL UPDATE READS OF
; ISAM FILES WHEN IN-CORE MODE AND RECORDING MODE
; ARE DIFFERENT
; 11-AUG-76 ; [446] FIX LOW-VALUES SIMUL UPDATE READS OF
; ISAM FILES SO END OF FILE DOES NOT GIVE ATTEMPT
; TO READ RECORD NOT RETAINED ERROR
; 11-AUG-76 ; [445] FIX LOW-VALUES SIMUL UPDATE READS OF
; ISAM FILE WITH DISPLAY NUMERIC KEYS
;SSC 2-AUG-76 ADD TEST FOR ALREADY RETAINED DBMS RESOURCES
; 27-JUL-76 ; [443] SET UP AP SO LREDQX WORKS FOR ISAM FREES
; 01-JUN-76 ; [437] SET UP FOUR TABLES AND INITIALIZE COUNT PROPERLY FOR RANDOM FILES.
; PATCH IN CBLIO ALSO.
; 05-APR-76 ; [434] FIX SIMULTANEOUS UPDATE FOR UNAVAILABLE CLAUSE
; 16-MAY-75 /GPS CREATION.
;*****
SALL
HISEG
SEARCH LBLPRM
SEARCH FTDEFS
IFN LSTATS,<
SEARCH METUNV ;LSTATS METER DEFINITIONS
>
IFN TOPS20,<
SEARCH MONSYM,MACSYM
>
IFE TOPS20,<
SEARCH UUOSYM,MACTEN
>
DEFINE TYPE(ADDR),<
IFN TOPS20,<
HRROI 1,ADDR
PSOUT%
>
IFE TOPS20,<
OUTSTR ADDR
>
>;END DEFINE TYPE
; THE LIBOL SIMULTANEOUS UPDATE PACKAGE: LRENQ, LRDEQ, LFENQ,
; SU.RD, SU.RW, SU.WR,
; SU.DL, AND SU.CL
;
;
;
; THIS PACKAGE IMPLEMENTS IN LIBOL THE COBOL SIMULTANEOUS UPDATE
; FEATURE.
;
;
; LRENQ: LIBOL RECORD ENQUEUE
;
;
; THE FOLLOWING PROCEDURE, LRENQ, IS CALLED BY THE COBOL OBJECT
; PROGRAM ONCE FOR THE EXECUTION OF EACH RETAIN STATEMENT.
;
; LRENQ EXPECTS TO FIND IN AC16 THE ADDRESS OF AN ARGUMENT LIST,
; STRUCTURED AS FOLLOWS:
;
; WORD 1: RH = NUMBER OF RECORDS TO BE RETAINED (N)
; LH = 0 => USER DID NOT SUPPLY AN UNAVAILABLE STATEMENT
; LH = 1 => USER SUPPLIED AN UNAVAILABLE STATEMENT
;
; WORD 2: BITS 0-8: 147
; BIT 9: SET IF USER INTENDS TO READ
; BIT 10: SET IF USER INTENDS TO REWRITE
; BIT 11: SET IF USER INTENDS TO WRITE
; BIT 12: SET IF USER INTENDS TO DELETE
; BIT 13: SET IF USER SPECIFIED UNTIL FREED
; BIT 14: SET IF USER SPECIFIED A RECORD IDENTIFIER
; (AS OPPOSED TO IMPLICITLY DESIGNATING THE
; CURRENT RECORD. IF THIS BIT IS SET, THE NEXT
; WORD DESIGNATES THE RECORD; OTHERWISE THE NEXT
; WORD DESIGNATES THE NEXT RECORD TO BE RETAINED
; AND HAS THE SAME FORMAT AS THIS ONE.)
; BIT 15: (COBOL-74 ONLY): "RETAIN NEXT RECORD..."
; BITS 16-17: NOT USED
; RH = FILE TABLE LOCATION FOR THE FILE CONTAINING THIS
; RECORD.
;
; WORD 3: (IF BIT 14 OF PRECEDING WORD = 1)
;
; BITS 0-8: 0
; BITS 9-12: TYPE (SEE BELOW)
; BITS 13-35: FULL ADDRESS, USING I,X AND Y
;
; TYPE = 2 => ADDRESS IS ADDRESS OF A ONE WORD
; COMPUTATIONAL ITEM (INTEGER)
;
; TYPE = 11 (BASE 8) => ADDRESS IS ADDRESS OF A TWO WORD
; COMPUTATIONAL ITEM (INTEGER)
;
; TYPE = 4 MEANS ADDRESS IS ADDRESS OF A ONE WORD
; COMPUTATIONAL-1 ITEM (FLOATING POINT)
;
; TYPE = 15 (BASE 8) => MEANS ADDRESS IS ADDRESS OF A TWO
; WORD DESCRIPTOR OF A DISPLAY-6,
; DISPLAY-7 OR DISPLAY-8 ITEM; THE
; DESCRIPTOR HAS THE FOLLOWING
; FORMAT:
;
; WORD 1: A BYTE POINTER TO THE IDENTIFIER OR
; LITERAL
;
; WORD 2: BIT 0 = 1 => ITEM IS NUMERIC
; BIT 1 = 1 => ITEM IS SIGNED
; BIT 2 = 1 => ITEM IS A FIGURATIVE
; CONSTANT
; BIT 3 = 1 => ITEM IS A LITERAL
; BITS 4-11 ARE NOT USED
; BIT 12 = 1 IF P OCCURS IN THE ITEM'S
; PICTURE
; BITS 13-17 CONTAIN THE NUMBER OF DECIMAL
; PLACES CONTAINED IN THE ITEM
; BITS 18-35 CONTAIN THE SIZE OF THE ITEM
; IN BYTES
;
; (THE PATTERN OF WORDS 2 AND 3 IS REPEATED UNTIL N IS EXHAUSTED)
;
;
; THE FOLLOWING RESTRICTIONS APPLY TO THE USER SUPPLIED RECORD
; IDENTIFIERS:
;
; (1) FOR SEQUENTIAL FILES, THE RECORD IDENTIFIER MUST BE TYPE 2
; (A ONE WORD COMPUTATIONAL ITEM).
;
; (2) FOR RANDOM FILES, THE RECORD IDENTIFIER MUST BE TYPE 2
; (A ONE WORD COMPUTATIONAL ITEM).
;
; (3) FOR INDEXED FILES, THE RECORD IDENTIFIER MUST AGREE WITH
; THE RECORD KEY DEFINED FOR THE FILE IN CLASS, USAGE, SIZE,
; AND NUMBER OF DECIMAL PLACES. IT MAY NOT BE A LITERAL
; OR FIGURATIVE CONSTAND, EXCEPT LOW-VALUES.
;
;
;
; AN IMPORTANT ASSUMPTION MADE BY THIS ROUTINE IS THAT THE
; ABOVE RESTRICTIONS WERE CHECKED AT COMPILE TIME
; THIS PROCEDURE USES A DATA STRUCTURE CALLED THE RETAINED
; RECORDS TABLE. THE FORMAT OF THIS TABLE IS AS FOLLOWS:
;
; WORD 1: THE MISCELLANEOUS WORD (0)
;
; BITS 0-2: QUEUEING TECHNIQUE (QT)
; BITS 3-8: ENQUEUEING FLAGS (EF)
; BIT 9: F BIT (SET TO INDICATE THIS ENTRY SHOULD BE
; FREED)
; BITS 10-17: THE INCREMENT TO THE NEXT ENTRY,
; IN WORDS (INE)
; BITS 18-35: LOCATION OF THE FILE TABLE OR 0,
; INDICATING THE RECORD HAS BEEN FREED.
;
;
; WORD 2: BLOCK NUMBER
;
; WORDS 3-N: KEY
;
;
; THE VALUES FOR QUEUEING TECHNIQUE (QT) ARE:
;
; 0: NO QUEUEING
; 1: SHARED
; 2: EXCLUSIVE
; 3: INDEX-EXCLUSIVE
; 4: SHARED, BUT COVERED BY ANOTHER ITEM'S INDEX-EXCLUSIVE
; 5: EXCLUSIVE, BUT COVERED BY ANOTHER ITEM'S
; INDEX-EXCLUSIVE
; 7: RANDOM RECORD RETAINED WITH KEY OF 0, FILE IS EXCLUSIVE
;
;
; THE VALUES FOR ENQUEUEING FLAGS (EF) ARE:
;
; BIT 0: READ
; BIT 1: REWRITE
; BIT 2: WRITE
; BIT 3: DELETE
; BIT 4: UNTIL FREED (UF)
; BIT 5: KEY SPECIFIED (KS)
; REGISTER ASSIGNMENTS
;
; NOTE: REGISTERS 0, 1, 2, AND 3 ARE DESTROYED BY A RESTORE OPERATION
; (THIS AFFECTS ACRR2, ACRR3, AND K AS REGISTERS ARE CURRENTLY DEFINED)
ACRR==7 ;CURRENT RETAINED RECORDS TABLE ENTRY
AURS==13 ;CURRENT USER RECORD SPECIFICATION
I==10 ;COUNTER
J==14 ;COUNTER
K==3 ;COUNTER
AT1==4 ;TEMP NOTE: AT1, AT2, AND AT3 MUST BE CONTIGUOUS
AT2==5 ;TEMP
AT3==6 ;TEMP
AT4==12 ;TEMP
AT5==11 ;TEMP - MUST NOT BE A REGISTER THAT NEEDS TO BE SAVED
AFT==15 ;FILE TABLE POINTER
AP==16 ;PARAMETER LIST POINTER (MUST BE AC16)
PP==17 ;PUSHDOWN LIST POINTER (MUST BE AC17)
ACRR2==1 ;ANOTHER CURRENT RETAINED RECORDS TABLE ENTRY
ACRR3==2 ;STILL ANOTHER CURRENT RETAINED RECORDS TABLE
;ENTRY
AUFS==AURS ;CURRENT USER FILE SPECIFICATION
;
;
;
;
; FIELD VALUES
;
%FAM.D==2 ; ACCESS MODE VALUE FOR 74 DYNAMIC ACCESS
INDEXD==4 ;VALUE OF ACCESS MODE FOR INDEXED
RANDOM==RANFIL## ;VALUE OF ACCESS MODE FOR RANDOM
COMPLT==3 ;VALUE OF TYPE OF KEY FOR COMP <= 10
;DIGITS
COMP1==5 ;VALUE OF TYPE OF KEY FOR COMP-1
COMPGT==4 ;VALUE OF TYPE OF KEY FOR COMP > 10
;DIGITS
UNTFRD==2 ;UNTIL FREED FLAG BIT IN URSFLG
USRSKY==000010 ;USER SUPPLIED KEY BIT IN FREE ARG
FREFEV==000200 ;FREE ALL IN FILE BIT IN USER ARG
FREALR==000400 ;FREE ALL RECORDS BIT IN USR ARG
JSTWRT==000015 ;(EF) IN RETAIN REC ENTRY,MASK ALL
;BUT WRITE BIT (USED TO CHECK WRITE ONLY
JSTRWT==000013 ;(EF) AS ABOVE, BUT TO CHECK FOR REWRITE ONLY
;
; FIELDS VALUES IN RETAINED RECORDS TABLE ENTRY
;
RTTRD==10 ;RETAINED FOR READ (USING FIRST 4 EF BITS)
RTTNRD==7 ;MASKS ALL BUT READ BITS ( " )
RTDLRW==05 ; MASKS FOR DELETE OR REWRITE RETAIN
;
;
; EXTERNAL ENTRY POINTS
;
;
ENTRY LFENQ.,LRENQ.,LRDEQ.,LRDEQX,SU.RD,SU.RW,SU.WR,SU.DL,SU.CL
; MACROS
DEFINE SAVE<
MOVEI AT5,SU.SAV ;SAVE REGISTERS
BLT AT5,SU.SAV+3
MOVEM 12,SU.SAV+4>
DEFINE RESTRM<
HRLZI AT5,SU.SAV ;RESTORE REGISTERS
BLT AT5,3
MOVE 12,SU.SAV+4>
; MRHDCT IS A MACRO TO INCREMENT A METER BUCKET WITHIN
;THE TRAILER BLOCK.
;
;ARGUEMENTS: OFF THE BUCKET OFFSET WITH THE TRAILER
; R A REGISTER TO USE FOR INDEXING
;
DEFINE MRHDCT (OFF,R)<
IFN LSTATS,<
MOVE R,MRTDBP ;GET METER TRAILER ADDRESS
AOS OFF(R) ;INCREMENT TRAILER BUCKET
>
>
; BYTE POINTERS
;
URSCON: POINT 9,0(AURS),8 ;CONSTANT IN USER RECORD SPECIFICATION
URSFLG: POINT 6,0(AURS),14 ;FLAGS IN USER RECORD SPECIFICATION
URSTYP: POINT 4,1(AURS),12 ;TYPE IN USER RECORD SPECIFICATION
IFN ANS74,<
URSNXT: POINT 1,0(AURS),15 ;"NEXT RECORD" FLAG
>;END IFN ANS74
CRRFLG: POINT 6,0(ACRR),8 ;ENQUEUEING FLAGS IN RETAINED RECORDS
;TABLE ENTRY
CRRFG4: POINT 4,0(ACRR),6 ;FIRST FOUR ENQUEUEING FLAGS IN RETAINED
;RECORDS TABLE ENTRY (READ, REWRITE,
;WRITE, DELETE)
CRRQT: POINT 3,0(ACRR),2 ;QUEUEING TECHNIQUE IN RETAINED RECORDS
;TABLE
CRRINE: POINT 8,0(ACRR),17 ;INCREMENT TO THE NEXT ENTRY IN
;THE RETAINED RECORDS TABLE
CRRF: POINT 1,0(ACRR),9 ;FREE FLAG
CRRQT2: POINT 3,0(ACRR2),2 ;SAME AS CRRQT, EXCEPT XR = ACRR2
CRRQT3: POINT 3,0(ACRR3),2 ;SAME AS CRRQT, EXCEPT XR = ACRR3
CRRIN2: POINT 8,0(ACRR2),17 ;SAME AS CRRINE, EXCEPT XR = ACRR2
CRRIN3: POINT 8,0(ACRR3),17 ;SAME AS CRRINE, EXCEPT XR = ACRR3
CRRBLK: POINT 33,1(ACRR),35 ;BLOCK NUMBER OF THIS RECORD
CRRBK2: POINT 33,1(ACRR2),35 ;SAME AS CRRBLK, EXCEPT XR = ACRR2
CRRBK3: POINT 33,1(ACRR3),35 ;SAME AS CRRBLK, EXCEPT NR = ACRR3
RRTNXT: POINT 1,1(ACRR),0 ;SET IF RETAINING "NEXT" RECORD
RRTHVF: POINT 1,1(ACRR),1 ;SET IF NEXT RECORD DOESN'T EXIST
AT1HVF: POINT 1,1(AT1),1 ;SAME AS RRTHVF WITH XR = AT1
RRTNX3: POINT 1,1(ACRR3),0 ;"NEXT" FLAG WITH XR = ACRR3
; BYTE PTRS TO FILE TABLE INFO
FTAM: POINT 3,F.WFLG(AFT),17 ;ACCESS MODE FIELD IN FILE TABLE
FTKLB: POINT 12,F.WIKD(AFT),35 ;KEY LENGTH IN BYTES IN FILE TABLE
FTKT: POINT 3,F.WIKD(AFT),17 ;KEY TYPE IN FILE TABLE
FTRM: POINT 3,F.WFLG(AFT),14 ;RECORDING MODE IN FILE TABLE
LFQOPN: POINT 1,F.WSMU(AP),15 ;[565] LFENQ. OPEN FLAG BIT
;[565] =0 IF LFENQ. C.OPEN CALL NOT DONE
;[565] =1 IF C.OPEN CALL DONE
;[650] CNTRY==117 ;POINTER TO CURRENT RECORD IN CBLIO'S
;BUFFER FOR ISAM FILE
FTCN: POINT 4,D.CN(AFT),15 ;CHANNEL NUMBER IN FILE TABLE
FTBF: POINT 12,F.WBKF(AFT),17 ;BLOCKING FACTOR IN FILE TABLE
FTOWA: POINT 4,F.WSMU(AFT),3 ;OWN ACCESS IN FILE TABLE (READ,
;REWRITE, WRITE, DELETE)
FTOTA: POINT 4,F.WSMU(AFT),12 ;OTHERS ACCESS IN FILE TABLE
;(READ, REWRITE, WRITE, DELETE)
UFSCON=URSCON ;CONSTANT IN USER FILE SPECIFICATION
UFSFLG: POINT 7,0(AUFS),15 ;FLAGS IN USER FILE SPECIFICATION
IDXSHR: POINT 2,F.WSMU(AFT),17 ;FLAG INDICATING SHARED/EXCLUSIVE
;=0 IF INDEX EXCLUSIVE
;=1 IF INDEX SHARED
;=3 IF INDEX GROUP SHARED
; INTERFACE WITH CBLIO
;
;
; MAPPING OF KEYS INTO BLOCK NUMBERS
;
; ONE FUNCTION REQUIRED OF CBLIO FOR ISAM FILES IS THE MAPPING
; OF SYMBOLIC KEYS INTO BLOCK NUMBERS. THIS IS ACCOMPLISHED IN
; THE FOLLOWING WAY:
;
; AFTER SAVING REGISTERS IT REQUIRES, SETTING SU.FRF TO -1, AND SETTING SU.RBP TO 0
; (EXPLAINED BELOW), THIS PACKAGE SETS AC16 WITH A SPECIAL
; FLAG IN LH (DEFINED BY RFLAG INTERNALLY) AND A FILE TABLE
; ADDRESS IN RH. "SYMBOLIC KEY" IS SAVED AND CHANGED TO CONTAIN
; THE KEY THAT IS TO BE MAPPED INTO A BLOCK NUMBER. THEN A
; PUSHJ IS DONE TO THE EXTERNAL SYMBOL "FAKER.".
;
; CBLIO PERFORMS A READ OF THE RECORD WITH THE KEY IN SYMBOLIC
; KEY, AND TAKES THESE SPECIAL ACTIONS:
;
; 1: IT SETS FS.BN TO THE BLOCK NUMBER OF THE BLOCK CONTATING
; THE KEY.
;
; 2: IT FAILS TO MOVE THE RECORD INTO THE USER'S RECORD AREA.
;
; 3. IF THE VALUE OF "SYMBOLIC KEY" IS LOW-VALUES, IT PUTS
; INTO SU.RBP A BYTE POINTER TO THE ACTUAL KEY OF THE RECORD.
;
;
; FILLING AND FLUSHING BUFFERS
;
; WHEN THE USER RETAINS A RECORD, IT IS IMPERATIVE THAT A
; SUBSEQUENT READ RETRIEVE THE VERY LATEST VERSION OF THAT
; RECORD. THEREFORE IF RETAIN DISCOVERS THAT A BLOCK
; CONTAINING A RECORD BEING RETAINED IS CURRENTLY IN THE USER'S
; BUFFER, THAT BUFFER MUST BE REFILLED FROM DISC. THIS IS
; DONE BY CALLING CBLIO AT THE ENTRY POINT FORCR. (FORCE READ).
; THE ONLY PARAMETER REQUIRED IS A FILE TABLE ADDRESS IN AC16,
; SINCE THERE IS ONLY ONE CURRENT BUFFER.
; (SU PACKAGE MUST SAVE ANY REGISTERS IT NEEDS BEFORE CALLING FORCR.)
;
; SIMILARLY, WHEN THE USER FREES A RECORD, IT IS IMPERATIVE
; THAT THE RECORD BE WRITTEN ON DISC BEFORE IT IS FREED,
; SO THAT ANOTHER USER RECEIVES THE VERY LATEST COPY. THEREFORE,
; WHEN FREE DETECTS THAT THE RECORD BEING FREED IS IN THE
; CURRENT BUFFER, AND THAT THE USER HAS MODIFIED THE RECORD,
; IT CALLS CBLIO AT THE ENTRY POINT FORCW. (FORCE WRITE), WITH
; AC16 SET TO A FILE TABLE ADDRESS.
; (SU PACKAGE MUST SAVE ANY REGISTERS IT NEEDS BEFORE CALLING FORCW.)
;
;
; MOVING LOW-VALUES TO CURRENT SYMBOLIC KEY
;
; THE CBLIO ROUTINE LV2SK. IS USED TO MOVE LOW-VALUES TO THE
; SYMBOLIC KEY. IT IS ASSUMED THAT ALL REGISTERS ARE DESTROYED
; BY LV2SK.. AC16 POINTS TO THE FILE TABLE UPON PUSHJ PP, LV2SK..
; THERE ARE NO ERROR RETURNS FROM LV2SK..
;
;
; COMPARING A KEY AGAINST LOW-VALUES
;
; THE CBLIO ROUTINE LVTST IS USED TO COMPARE A KEY TO
; LOW-VALUES. ON INPUT, A BYTE POINTER TO THE KEY TO BE TESTED
; IS SET IN AC1 AND AC16 CONTAINS A FILE TABLE POINTER. LVTST
; RETURNS TO 0 IF THE KEY IS EQUAL TO LOW-VALUES, TO 1 IF IT IS
; NOT.
; (SU PACKAGE MUST SAVE ANY REGISTERS IT NEEDS BEFORE CALLING LVTST.)
;
;
;
; REFRESHING IN-CORE STORAGE ALLOCATION TABLES
;
; LSU SETS USOBJ+13 TO ZERO TO MAKE CBLIO REFRESH ITS IN-CORE
; STORAGE ALLOCATION TABLES. SEE ZSATB ROUTINE.
EXTERN FAKER. ;ENTRY INTO CBLIO
EXTERN FS.BN ;LOCATION WHERE CBLIO RETURNS BLOCK
;NUMBER
IFN ANS74,<
EXTERN F.BFAM ;FILE ACCESS MODE BYTE PTR
EXTERN SAVNXT ; D.RFLG field for del/rewrt next rec position
>
IFN ANS68, RFLAG==002100 ;THE FAKE READ FLAG
IFN ANS74, RFLAG==002000 ;SET IN LH OF 16 WHEN CALLING FAKER.
IFN ANS74, RNFLAG==RFLAG!200 ;NEXTR (READ NEXT RECORD)
EXTERN GDPSK ;[445][447] LOCATION IN DEVICE TABLE POINTING TO
;ANOTHER TABLE CONTAINING THE LAST
;VERB EXECUTED BY THIS USER, WHETHER
;THE CURRENT BUFFER CONTAINS LIVE DATA,
;AND ALSO THE NEXT RECORD FLAG.
EXTERN CHTAB ;[447] TABLE OF INPUT CONVERSION INSTRUCTIONS
LASTUU==7 ;OFFSET IN THE TABLE POINTED TO BY
;THE LEFT HALF OF D.BL THAT CONTAINS
;MINUS 1 IF THE LAST VERB FOR THIS FILE
;WAS A WRITE.
LIVDAT==6 ;OFFSET IN THE SAME TABLE WHICH CONTAINS
;MINUS 1 IF THE BUFFER CONTAINS LIVE
;DATA
NXTREC==NNTRY## ;OFFSET IN THE SAME TABLE WHICH CONTAINS
;-1 IF THE "CURRENT RECORD" IS IN
;FACT, THE "NEXT RECORD".
EXTERN LV2SK. ;CBLIO ROUTINE FOR SETTING SYMBOLIC
;KEY TO LOW-VALUES
IFN ANS68, EXTERN LVTST ;CBLIO ROUTINE FOR COMPARING A KEY TO
;LOW-VALUES
EXTERN FORCR. ;ENTRY POINT IN CBLIO THAT REFILLS A
;BUFFER
EXTERN FORCW. ;ENTRY POINT IN CBLIO THAT FLUSHES A
;BUFFER
;
; CHECKING ACCESS TO RECORDS BEFORE READ, REWRITE, WRITE OR DELETE
;
; WHEN CBLIO DETECTS THAT A FILE IS OPEN FOR SIMULTANEOUS UPDATE,
; IT CALLS SU.RD, SU.RW, SU.WR, SU.DL, OR SU.CL, AS APPROPRIATE
; (SEE DESCRIPTION OF THESE ROUTINES BELOW).
;
;
; IMPLICIT FREEING OF RECORDS.
;
; AFTER EXECUTION OF A READ, REWRITE, WRITE, OR DELETE, CBLIO
; CALLS LRDEQX VIA PUSHJ WITH NO PARAMETERS OR RETURNED VALUES
; TO ACCOMPLISH ANY IMPLICIT FREEING OF RECORDS THAT MAY BE
; REQUIRED.
; (LRDEQX SAVES ALL REGISTERS FOR CBLIO)
;
;
; OPENING AND CLOSING FILES.
;
; LFENQ. OPENS AND CLOSES FILES BY CALLING C.OPEN AND C.CLOS
; WITH 16 LH CONTAINING FLAGS INDICATING THE FILE IS TO
; BE OPENED FOR I-O AND 16 RH CONTAINING A FILE TABLE ADDRESS.
EXTERN C.OPEN,C.CLOS,USOBJ
EXTERN RET.1,RET.2
; THIS ROUTINE USES THE FOLLOWING CONVENTIONS FOR BLOCK NUMBERS:
;
; BLOCKS 1 TO 2 ** 33 - 6: DATA BLOCKS
; BLOCK 2 ** 33 - 5: THE FILE READ QUEUE
; BLOCK 2 ** 33 - 4: THE FILE REWRITE QUEUE
; BLOCK 2 ** 33 - 3: THE FILE WRITE QUEUE
; BLOCK 2 ** 33 - 2: THE FILE DELETE QUEUE
; BLOCK 2 ** 33 - 1: THE PRIMARY INDEX OF THE FILE
;
;
; WHEN WE CALL ENQ/DEQ WITH A 33 BIT IDENTIFIER EQUAL TO
; 2 ** 33 - 1 WE ARE LOCKING THE INDEX OF THE FILE. IF WE
; CALL ENQ/DEQ WITH A 33 BIT IDENTIFIER EQUAL TO 1234 WE
; ARE LOCKING DATA BLOCK NUMBER 1234. ETC.
; TEMPORARY STORAGE
;
;
EXTERN SU.RR ;COUNT OF RECORDS RETAINED BY THE USER
EXTERN SU.DBR ;COUNT OF USER-RETAINED DBMS RESOURCES
EXTERN SU.EQ ;COUNT OF ENTRIES IN THE ENQUEUE TABLE
;(AS OPPOSED TO THE DEQUEUE TABLE OR
;(THE MODIFY TABLE)
EXTERN SU.DQ ;COUNT OF ENTRIES IN THE DEQUEUE TABLE
EXTERN SU.MQ ;COUNT OF ENTRIES IN THE MODIFY TABLE
EXTERN SU.RRT ;LOCATION OF THE RETAINED RECORDS TABLE
EXTERN SU.T1 ;TEMP ONE
EXTERN SU.T2 ;TEMP TWO
EXTERN SU.T3 ;TEMP THREE
EXTERN SU.T4 ;TEMP FOUR
EXTERN SU.T5 ;TEMP FIVE
EXTERN SU.T6 ;TEMP SIX
EXTERN SU.T7 ;TEMP SEVEN
EXTERN SU.T8 ;TEMP EIGHT
EXTERN SU.T9 ;[445] TEMP NINE
EXTERN SU.CRH ;USED TO STORE THE HIGHEST VALUE OF ACRR
;(TOTAL LENGTH OF THE RETAINED RECORDS
;TABLE)
EXTERN SU.EQT ;LOCATION OF THE ENQUEUE TABLE
EXTERN SU.DQT ;LOCATION OF THE DEQUEUE TABLE
EXTERN SU.MQT ;LOCATION OF THE MODIFY TABLE
EXTERN SU.Y ;FLAG
EXTERN SU.RBP ;RECORD BYTE POINTER - SPECIAL POINTER
;TO HANDLE LOW-VALUES (SEE CBLIO
;INTERFACE)
EXTERN SU.MRR ;MORE RETAINED RECORDS FLAG
EXTERN SU.SBD ;SAME BLOCK, DIFFERENT QUEUEING
;TECHNIQUE FLAG
EXTERN SU.RLV ;[455] RANDOM KEY OF 0 FLAG
EXTERN SU.RND ;[455] FILE IS RANDOM FLAG
EXTERN SU.SFQ ;SAME FILE FLAG
EXTERN SU.SFS ;SAME FILE, SAME QUEUEING TECHNIQUE FLAG
EXTERN SU.SBS ;SAME BLOCK, SAME QUEUEING TECHNIQUE
;FLAG
EXTERN SU.NR ;NOT RETAINED FLAG
EXTERN SU.FR ;COUNT OF FILES CURRENTLY OPENED FOR
;SIMULTANEOUS UPDATE
EXTERN SU.AK ;TEMPORARY USED FOR ABSOLUTE KEY
EXTERN SU.FBT ;LOCATION OF THE FILL/FLUSH BUFFER TABLE
EXTERN SU.CFB ;COUNT OF ENTRIES IN THE FILL/FLUSH
;BUFFER TABLE
EXTERN SU.VRB ;INDICATOR OF CURRENT VERB BEING EXECUTED
;20 = CLOSE, 10 = READ, 4 = REWRITE,
;2 = WRITE, 1 = DELETE
EXTERN SU.HV ;[447] SET TO -1 WHEN HIGH VALUES USED
EXTERN SU.CK ;COMPARISON KEY
EXTERN SU.SVK ;TEMP USED TO SAVE KEY
EXTERN SU.CL1,SU.CL2,SU.CLR,SU.CLS ;TEMPS FOR SU.CL -
;SU.CL1 AND SU.CL2 MUST BE
;CONTIGUOUS
EXTERN SU.SAV ;AREA TO SAVE REGISTERS 1,2,3,0, AND 12
EXTERN FET1,FET2,FET3,FET4 ;FILE ENQUEUE TEMPS
EXTERN SU.FRF ;THE FAKE READ FLAG 0 = REGULAR -1 = FAKE
IFN LSTATS,<
IFN TOPS20,<
EXTERN MRTM.E,MRTM.S
>
EXTERN MRTMB.,MBTIM.,MRTDBP ;METER TIMING ROUTINES AND LOCATIONS
>;END IFN LSTATS
; DEBUGGING
;
;
; IF THE TRNA FOLLOWING LABEL ED3 IN ENQDEQ
; (AN INTERNAL SUBROUTINE) IS CHANGED TO TRN, ANY LIBOL ROUTINE DOING ENQUEUEING
; OR DEQUEUEING WILL TYPE THE PARAMETERS TO ENQ/DEQ ON TTY BEFORE
; CALLING ENQ/DEQ.
; INITIALIZATION.
;
; CHECK THAT NO RECORDS ARE CURRENTLY RETAINED. INITIALIZE
; VARIABLES. POINT AN AC TO THE BEGINNING OF THE USER'S
; RETAINED RECORDS TABLE, AND ANOTHER AC TO THE FIRST USER
; RECORD SPECIFICATION IN THE ARGUMENT LIST.
LRENQ.:
MRTMS. (AT1) ;START METER TIMING
SAVE
SKIPG SU.DBR ;ANY DBMS RETAINS IN PLACE, ALSO BAD
SKIPE SU.RR
JRST SU.ER1 ;JUMP IF USER IS CURRENTLY RETAINING
;RECORDS - HE MAY NOT EXECUTE A RETAIN
;STATEMENT UNLESS ALL RECORDS ARE FREE.
SETZM SU.EQ ;SET THE NUMBER OF ENTRIES IN THE
;ENQUEUE TABLE TO ZERO (LRENQ WILL
;NOT USE THE DEQUEUE TABLE OR THE
;MODIFY TABLE)
SETZM SU.CFB ;ZERO THE NUMBER OF ENTRIES IN THE
;FILL/FLUSH BUFFER TABLE
MOVE ACRR,SU.RRT ;POINT ACRR TO THE BEGINNING OF THE
;RETAINED RECORDS TABLE
MOVEI AURS,1(AP) ;POINT AURS TO THE FIRST USER RECORD
;SPECIFICATION IN THE ARGUMENT LIST
HRRZ I,0(AP) ;COUNT USER RECORD SPECS IN I
IFN LSTATS,<
HLRZ AT2,0(AP) ;GET UNAVAILABLE FLAG
JUMPE AT2,LRMRXX ;SKIP OUT IF NO UNAVAILABLE CLAUSE
MRHDCT (MB.RTU,AT1) ;INCREMENT METER BUCKET
LRMRXX:>;END IFN LSTATS
MOVEM I,SU.RR ;SAVE NUMBER OF RECORDS RETAINED IN SU.RR
JUMPN I,LRENQ8
RESTRM
POPJ PP, ;RETURN IF COUNT = 0
; FIRST LOOP.
;
; LOOK AT EACH USER RECORD SPECIFICATION. DETERMINE THE QUEUEING
; TECHNIQUE FOR EACH AND CREATE AN ENTRY IN THE RETAINED RECORDS
; TABLE CONTAINING THE QUEUEING TECHNIQUE, FILE TABLE POINTER,
; ENQUEUEING FLAGS, KEY VALUE, AND A ZERO BLOCK NUMBER. THE
; QUEUEING TECHNIQUES HAVE THE FOLLOWING MEANINGS:
;
; 0: ACCESS TO THIS RECORD AS DEFINED BY THE ENQUEUEING FLAGS
; REQUIRES NO ACTION ON OUR PART
;
; 1: ACCESS TO THIS RECORD REQUIRES SHARED ENQUEUEING ON THE
; BLOCK IN WHICH THE RECORD RESIDES, AND IF THE FILE IS INDEXED,
; SHARED QUEUEING ON THE INDEX
;
; 2: SAME AS 1 EXCEPT EXCLUSIVE QUEUEING REQUIRED ON THE BLOCK.
;
; 3: ACCESS TO THIS RECORD AS DEFINED BY THE ENQUEUEING FLAGS
; REQUIRES EXCLUSIVE ENQUEUEING OF THE INDEX
;
; 4: ACCESS TO THIS RECORD WOULD NORMALLY REQUIRE QUEUEING
; TECHNIQUE 1, BUT ANOTHER REQUEST REQUIRES TECHNIQUE 3 AND
; THEREFORE NO ACTION IS REQUIRED FROM US UNLESS THE REQUEST
; REQUIRING TECHNIQUE 3 IS TERMINATED (THE RECORD IS FREED)
;
; 5: SAME AS 4 EXCEPT ACCESS TO THIS RECORD WOULD NORMALLY
; REQUIRE TECHNIQUE 2
;
; 7: THIS RECORD IS FROM A RANDOM FILE AND HAS A KEY OF ZERO (0)
; WHICH MEANS THE WHOLE FILE MUST BE ENQUEUED EXCLUSIVE.
; NORMALLY A RANDOM FILE IS ENQUEUED SHARED, BUT AS LONG AS
; ANY RECORD IN THE FILE IS BEING RETAINED WITH A KEY OF 0,
; THE FILE MUST BE ENQUEUED EXCLUSIVE.
LRENQ8: LDB AT1,URSCON
CAIE AT1,147 ;MAKE A LITTLE VALIDITY CHECK
JRST SU.ER2
SETZM 0(ACRR) ;ZERO MISCELLANEOUS WORD IN THE
;CURRENT ENTRY OF THE RETAINED RECORDS
;TABLE
LDB AT1,URSFLG ;MOVE FLAGS FROM THE USER RECORD
;SPECIFICATION TO THE RETAINED RECORDS
;TABLE
DPB AT1,CRRFLG
IFN LSTATS,<
TRNN AT1,UNTFRD ;UNTIL FREED ?
JRST LREQMX ;NO, GIT
MRHDCT (MB.RTF,AT1) ;YES, INCREMENT METER BUCKET
LREQMX:>;
HRRZ AFT,0(AURS) ;SIMILARLY, MOVE FILE TABLE ADDRESS,
;LEAVING IT IN AFT FOR FUTURE USE
HRRM AFT,0(ACRR)
SETZM 1(ACRR) ;ZERO BLOCK NUMBER
SETO AT1, ;INITIALIZE THE DEFINITION OF
;"RECORD 0" IN THE FILE TABLE OF THE
;FILE CONTAINING THIS RECORD
HRRM AT1,F.WSMU(AFT)
LDB AT1,FTOWA ;GET FLAGS SPECIFIED WHEN THE FILE WAS
;OPENED
LDB AT2,CRRFG4 ;GET CORRESPONDING FLAGS FROM THIS
;REQUEST
SETCA AT1, ;SET A BIT FOR EACH BIT THAT MUST BE
;ZERO IN REQUEST
TRNE AT2,0(AT1)
JRST SU.ER3 ;JUMP IF USER ATTEMPTING TO RETAIN
;A RECORD FOR A FUNCTION NOT SPECIFIED
;WHEN THE FILE WAS OPENED
LDB AT3,FTOTA ;GET OTHERS' FLAGS
JUMPE AT3,P1 ;JUMP IF OTHERS ALLOWED NONE
OR AT3,AT2
TRNE AT3,777767
JRST P2 ;JUMP IF EITHER WE OR OTHERS ARE
;DOING SOMETHING BESIDES READING
SETZ AT3, ;SET QUEUEING TECHNIQUE TO 0 (NONE)
JRST P1
P2: LDB AT3,FTAM
CAIE AT3,INDEXD
JRST P4 ;JUMP IF FILE NOT INDEXED
TRNN AT2,000003
JRST P5 ;JUMP IF RETAIN NOT FOR "ANY" ,WRITE, OR
;DELETE
MOVEI AT3,3 ;WE HAVE DETERMINED THAT THE FILE IS
;INDEXED AND AN INDEX MODIFYING FUNCTION
;WILL BE EXECUTED - SET QUEUEING
;TECHNIQUE TO 3 (INDEX-EXCLUSIVE)
JRST P1
P4:
IFN ANS68, TRNN AT2,000002
IFN ANS74, TRNN AT2,000007 ;REWRT,DEL IN ANS74 REQUIRES EXCLUSIVE
JRST P7 ;JUMP IF NOT RETAINED FOR WRITE
;(NOR READ-WRITE NOR "ANY")
P6: MOVEI AT3,2 ;WE HAVE DETERMINED THAT THE FILE IS
;NOT INDEXED BUT WRITING WILL OCCUR
;IN A RECORD - SET QUEUEING TECHNIQUE
;TO 2 (EXCLUSIVE)
JRST P1
P5: TRNE AT2,000004 ;CHECK FOR REWRITE
JRST P6 ;WE HAVE DETERMINED THAT THE FILE IS
;INDEXED, THAT NO INDEX-MODIFYING
;FUNCTION WILL BE EXECUTED, BUT THAT
;AN INDIVIDUAL RECORD WILL BE MODIFIED
;- JUMP TO P6 TO SET QT TO 2
P7: TRNN AT2,000010
JRST SU.ER4 ;JUMP IF NOT RETAINED FOR READ
;(INTERNAL ERROR)
MOVEI AT3,1 ;SET QT TO 1 (SHARED)
P1: DPB AT3,CRRQT
; AT THIS POINT IN THE FIRST LOOP WE HAVE COMPLETELY SET UP THE
; RETAINED RECORDS TABLE ENTRY, EXCEPT FOR THE KEY AND THE
; INCREMENT TO THE NEXT ENTRY, WHICH WE WILL NOW DO:
LDB AT3,FTAM
CAIN AT3,INDEXD
JRST Q1 ;JUMP IF FILE INDEXED
Q3: MOVEI AT3,3 ;SET SIZE OF THIS ENTRY IN THE RETAINED
;RECORDS TABLE TO 3 WORDS
JRST Q9
Q1:
IFN ANS74,<
MOVE AT3,D.BL(AFT) ; Get buffer location
SETZM SVNXRT(AT3) ; Clear SAVNXT RETAIN save flag
>
LDB AT3,FTKT ;GET KEY TYPE
CAIE AT3,COMPLT ;CHECK IF COMP < OR = 10 DIGITS
CAIN AT3,COMP1 ;LIKEWISE IF KEY COMP-1
JRST Q3 ;IF SO, SET LENGTH OF ENTRY TO 3 WORDS
CAIE AT3,COMPGT
JRST Q4
MOVEI AT3,4 ;IF COMP > 10 DIGITS, ALLOW FOR 2 WORD
;KEY, SETTING LENGTH OF ENTRY TO 4 WORDS
Q9: DPB AT3,CRRINE
JRST Q2
Q4: LDB AT1,FTRM ;MOVE INTO AT1 THE NUMBER OF BYTES PER
;WORD, BASED ON RECORDING MODE
MOVE AT1,[OCT 4,6,0,5]-1(AT1)
LDB AT3,FTKLB ;MOVE INTO AT3 THE LENGTH OF THE KEY IN
;BYTES
SETZ AT2,
DIV AT2,AT1 ;COMPUTE NUMBER OF WORDS REQUIRED
;TO STORE KEY
SKIPE AT3
ADDI AT2,1
ADDI AT2,2
DPB AT2,CRRINE ;SET LENGTH OF ENTRY TO N + 2 WORDS
Q2: LDB AT1,CRRFLG
TRNN AT1,000001
JRST R1 ;JUMP IF KEY NOT SUPPLIED
LDB AT1,URSTYP
CAIN AT1,2
JRST R2 ;JUMP IF KEY 1 WORD COMP
CAIE AT1,4 ;SKIP IF KEY 1 WORD COMP-1
JRST R3
R2: RESTRM
MOVE AT1,@1(AURS) ;MOVE 1 WORD KEY
MOVEM AT1,2(ACRR)
JRST R4
R3: CAIE AT1,11
JRST R5 ;JUMP IF NOT A 2 WORD KEY
RESTRM
MOVE AT1,@1(AURS)
MOVEM AT1,2(ACRR)
MOVEI AT1,@1(AURS)
MOVE AT1,1(AT1)
MOVEM AT1,3(ACRR)
JRST R4
R5: CAIE AT1,15
JRST SU.ER5 ;JUMP IF INVALID TYPE CODE
RESTRM
MOVEI AT1,@1(AURS) ;GET ADDRESS OF TWO WORD DESCRIPTOR
;IN AT1
HRRZ AT2,1(AT1) ;GET SIZE FIELD FROM TWO WORD DESCRIPTOR
;IN AT2
LDB AT3,FTKLB
CAME AT2,AT3
JRST SU.ER6 ;JUMP IF USER SUPPLIED KEY HAS WRONG
;SIZE
MOVE AT1,0(AT1) ;GET BYTE POINTER TO THE USER KEY IN AT1
PUSHJ PP,USRKEY ;[447] MOVE THE KEY
JRST R4
R1:
IFN ANS74,<
LDB AT3,URSNXT ;GET "NEXT RECORD" FLAG
JUMPE AT3,R1A ; JUMP IF NOT RETAINING "NEXT RECORD"
DPB AT3,RRTNXT ;SET BIT IN RETAINED RECORD TABLE
SETZM 2(ACRR) ;SET KEY TO ZERO
JRST R4 ; AND DON'T MOVE ANY KEY
R1A: >;END IFN ANS74
LDB AT3,FTAM ;KEY IS IMPLIED
CAIE AT3,INDEXD
JRST R6
MOVE AT1,F.WBSK(AFT) ;IF FILE IS INDEXED, USE SYMBOLIC KEY
LDB AT2,FTKLB
PUSHJ PP,USRKEY ;[447]
JRST R4
R6: HRRZ AT2,F.RACK(AFT) ;IF FILE IS RANDOM, USE ACTUAL KEY
SETZ AT1, ;ASSUME SEQ,KEY=0
CAIN AT3,RANDOM
MOVE AT1,0(AT2) ;GET ACTUAL KEY FOR RANDOM CASE
MOVEM AT1,2(ACRR) ;SET KEY VALUE
; AT THIS POINT WE'VE COMPLETED THE PROCESSING OF THE USER
; RECORD SPECIFICATION UNDER CONSIDERATION, THAT'S TO BE
; DONE IN THE FIRST LOOP.
R4: LDB AT2,CRRINE ;INCREMENT ACRR TO POINT TO THE
;NEXT RETAINED RECORDS ENTRY
LDB AT1,CRRFLG ;INCREMENT AURS TO POINT TO THE
ADD ACRR,AT2
;NEXT USER RECORD SPECIFICATION
ADDI AURS,1
TRNE AT1,000001
ADDI AURS,1
SOJG I,LRENQ8 ;END OF FIRST LOOP? IF NOT, JUMP
; SECOND LOOP.
;
; TAKE THE NEXT STEP IN THE DETERMINATION OF THE DEFINITION
; OF "RECORD 0", BY LOOKING FOR A SPECIAL CASE.
;
; INSPECT ALL THE RECORD REQUESTS THAT HAVE BEEN TABULATED IN
; THE RETAINED RECORDS TABLE. DETERMINE THE INDEXES WHICH NEED
; TO BE ENQUEUED, IF ANY, AND ENQUEUE THEM. BE CAREFUL TO ENQUEUE
; EACH REQUIRED INDEX ONLY ONCE. ADJUST THE QUEUEING TECHNIQUE OF
; THOSE RECORD REQUESTS WHICH WOULD NORMALLY REQUIRE SHARED OR
; EXCLUSIVE ACCESS TO A BLOCK, BUT DON'T, BECAUSE ANOTHER REQUEST
; REQUIRES EXCLUSIVE ACCESS TO THE WHOLE INDEX (AND THEREFORE THE
; WHOLE FILE).
; ALSO CHECK FOR A RANDOM FILE HAVING A RECORD RETAINED WITH A KEY
; OF 0. IF SUCH IS THE CASE, THE FILE MUST BE ENQUEUED ON EXCLUSIVE
; SO THE 'NEXT RECORD' WILL NOT CHANGE BETWEEN RETAINING AND
; READING OR WRITING. IF NO KEY OF 0 IS BEING RETAINED, ENQUEUE ON
; THE FILE SHARED AND ON EACH INDIVIDUAL BLOCK ACCORDING TO THE
; REQUESTED OPERATION.
LRENQ1: MOVEM ACRR,SU.CRH ;SAVE THE HIGHEST VALUE OF ACRR (WHICH
;IS THE LENGTH OF THE RETAINED RECORDS
;TABLE), SO WE KNOW WHEN TO LEAVE THE
;SECOND, THIRD, AND FOURTH LOOPS.
MOVEM ACRR,SU.SVK ;INITIALIZE THE POINTER TO WHERE
;WE CAN KEEP KEYS REPRESENTING
;CURRENT POSITIONS OF INDEXED FILES
MOVE ACRR,SU.RRT ;START SECOND LOOP AT THE FIRST ENTRY
LRENQ4: CAML ACRR,SU.CRH ;END OF THE SECOND LOOP?
JRST LRENQ7 ;YES, GO ENQUEUE INDEXES AND ENTER THIRD
;LOOP
;LOOK FOR A SPECIAL CASE IN
;THE DETERMINATION OF "RECORD 0".
;IF THE FILE IS NOT INDEXED AND
;IF KEY IS ZERO, AND THE ENQUEUEING
;FLAGS INDICATE THE USER INTENDS ONLY
;TO WRITE THE RECORD, AND THE USER'S
;PREVIOUS OPERATION ON THE FILE WAS A
;READ, SET F.WSMU TO -2 (F.WSMU WAS
;INITIALIZED IN THE FIRST LOOP TO -1.
;IN THE THIRD LOOP IT WILL BE ADDED TO
;D.RP + 2 (CURRENT RECORD NUMBER + 2)
;TO DETERMINE THE DEFINITION OF
;"RECORD 0".
IFN ANS68,<
SKIPE 2(ACRR)
JRST S19 ;NOT RECORD 0 (NEXT RECORD)
>
IFN ANS74,<
LDB AT1,RRTNXT
JUMPE AT1,S19 ;NOT RECORD 0 (NEXT RECORD)
>;END IFN ANS74
HRRZ AFT,0(ACRR)
LDB AT1,FTAM
CAIN AT1,INDEXD
JRST S19
CAIN AT1,RANDOM ;[455] IS THE FILE RANDOM?
JRST S20 ;[455] YES
LDB AT1,CRRFG4
IFN ANS68,<
TRNE AT1,JSTWRT ;RETAIN WRITE ONLY?
>;
IFN ANS74,<
TRNE AT1,JSTRWT ;RETAIN REWRITE ONLY?
>
JRST S19 ;NO
HLRZ AT1,D.BL(AFT) ;YES,ADDRESS BUFFER AREA
SETO AT2, ;WRITE LAST OPER. FLG
HRREI AT3,-2 ;"KEY 0" VALUE TO GET LAST USED LOCATION
CAME AT2,LASTUU(AT1) ;LAST OPER. WRITE?
HRRM AT3,F.WSMU(AFT) ;NO, RESET TO (RE)WRITE REC JUST READ
S19: LDB AT1,CRRQT
CAIE AT1,3
CAIN AT1,7 ;[455] RANDOM KEY OF 0?
SKIPA ACRR2,SU.RRT ;ENTER SUB-LOOP TO SEE IF A PRIOR
;REQUEST NEEDS EXCLUSIVE ACCESS TO THE SAME INDEX
JRST SS1 ;[455] JUMP IF THIS REQUEST DOESN'T REQUIRE
;[455] INDEX-EXCLUSIVE ACCESS OR RANDOM KEY OF 0
S4: CAMN ACRR2,ACRR ;END OF SUBLOOP?
JRST S5 ;YES
LDB AT1,CRRQT2 ;NO
CAIE AT1,3 ;INDEX-EXCLUSIVE ACCESS?
CAIN AT1,7 ;[455] RANDOM KEY OF 0?
JRST .+2 ;[455] JUMP IF EITHER IS TRUE
JRST SS3 ;NO
HRRZ AT1,0(ACRR2) ;YES
HRRZ AT2,0(ACRR)
CAMN AT1,AT2 ;SAME FILE?
JRST SS2 ;YES, JUMP OUT OF SUBLOOP (ANOTHER
;REQUEST HAS ALREADY ENQUEUED ON THE
;INDEX FOR THIS FILE)
SS3: LDB AT1,CRRIN2 ;MOVE TO THE NEXT ENTRY
ADD ACRR2,AT1
JRST S4 ;RETURN TO BEGINNING OF SUB-LOOP
; IF WE REACH S5, NO OTHER REQUEST HAS ALREADY ENQUEUED ON THE
; INDEX SO WE SHALL DO IT.
S5: SETZ AT1, ;SET LH = EXCLUSIVE, RH = ENQUEUE
SETO AT2, ;-1 MEANS INDEX
PUSHJ PP,QUEUE ;CREATE REQUEST ENTRY
LDB AT1,FTAM ;[455] GET FILE TYPE
CAIE AT1,RANDOM ;[455] IF IT IS A RANDOM FILE DON'T DO ZSATB
PUSHJ PP,ZSATB ;ASK CBLIO TO FORGET ABOUT ITS IN-CORE
;STORAGE ALLOCATION TABLES, IF NECESSARY
JRST SS2 ;MOVE ON TO THE NEXT ENTRY
SS1: JUMPE AT1,SS2 ;JUMP IF NO QUEUEING (QT = 0)
HRRZ AFT,0(ACRR)
LDB AT2,FTAM
CAIE AT2,INDEXD
CAIN AT2,RANDOM ;[455]
SKIPA ACRR2,SU.RRT ;ENTER SUB-LOOP
JRST SS2 ;JUMP IF FILE NOT INDEXED
; HERE WE KNOW THAT THE FILE IS EITHER INDEXED OR RANDOM AND THAT THE QUEUEING
; TECHNIQUE MUST BE EITHER SHARED OR EXCLUSIVE. THE PROBLEM IS
; TO DETERMINE IF (A) A PRIOR REQUEST HAS REQUIRED SHARED ACCESS
; TO THE INDEX OR (B) A REQUEST IN THE TABLE (NOT
; NECESSARILY PRIOR) WILL REQUIRE EXCLUSIVE ACCESS TO THE INDEX.
; IF NEITHER IS TRUE, WE MUST GENERATE A SHARED REQUEST FOR THE
; INDEX; OTHERWISE, WE NEED DO NOTHING.
SETZM SU.Y ;SET Y TO 0
U1: CAML ACRR2,SU.CRH ;END OF SUB-LOOP?
JRST U2 ;YES
HRRZ AT1,0(ACRR2)
HRRZ AT2,0(ACRR)
CAME AT1,AT2 ;SAME FILE?
JRST U3 ;NO, GO TO NEXT ENTRY
LDB AT2,FTAM ;[455] GET FILE TYPE
CAIN AT2,RANDOM ;[455] IS IT RANDOM
JRST S24 ;[455] YES
LDB AT1,CRRQT2
CAIN AT1,3 ;INDEX-EXCLUSIVE ACCESS?
JRST U4 ;YES, GO TO UPDATE QT
U5: CAML ACRR2,ACRR ;[455] ARE WE LOOKING AT A PRIOR ENTRY?
JRST U3 ;NO, GO TO THE NEXT ENTRY
CAIE AT1,1 ;SHARED?
CAIN AT1,2 ;OR EXCLUSIVE?
SETOM SU.Y ;YES, SET Y TO 1
U3: LDB AT1,CRRIN2 ;INCREMENT ACRR2 TO POINT TO THE NEXT
;ENTRY
ADD ACRR2,AT1
JRST U1
U4: LDB AT1,CRRQT ;UPDATE QUEUEING TECHNIQUE TO INDICATE
;THAT ANOTHER ENTRY HAS REQUESTED
;EXCLUSIVE USE OF THE INDEX
ADDI AT1,3
DPB AT1,CRRQT
JRST SS2
U2: SKIPE SU.Y ;IF Y IS NON-ZERO, THEN A PRIOR
;REQUEST HAS TAKEN CARE OF OUR INDEX
;REQUIREMENT
JRST SS2
HRLZI AT1,000001 ;OTHERWISE WE MUST SUBMIT A REQUEST FOR
;SHARED ACCESS TO THE INDEX
SETO AT2,
PUSHJ PP,QUEUE
SS2: LDB AT1,CRRINE ;END OF THE SECOND LOOP
ADD ACRR,AT1 ;POINT TO THE NEXT ENTRY IN THE RETAINED
;RECORDS TABLE
JRST LRENQ4
S24: LDB AT1,CRRQT2 ;[455]
CAIN AT1,7 ;[455] RANDOM KEY OF 0?
JRST SS2 ;[455] YES
JRST U5 ;[455]
S20: LDB AT1,CRRFG4 ;[455] GET RETAINED FOR FLAGS
TRNN AT1,15 ;[455] ARE WE ONLY WRITING?
JRST S22 ;[455] YES
LDB AT1,CRRQT ;[455] GET CURRENT QT
JUMPE AT1,S19 ;[455] QT = 0, FORGET ALL THIS CRAP
S21: MOVEI AT1,7 ;[455] NO, CHANGE CURRENT TO 7
DPB AT1,CRRQT ;[455]
JRST S19 ;[455] BACK TO MAIN ROUTINE
S22: SETZM ACRR3 ;[455] SET UP FOR SUB-LOOP
MOVE ACRR2,SU.RRT ;[455] START AT TOP OF RRT
S26: CAML ACRR2,ACRR ;[455] LOOK AT ALL PRIOR TO FIND JUST PRIOR
JRST S25 ;[455] SEE IF THERE IS A PRIOR
HRRZ AT1,0(ACRR) ;[455]
HRRZ AT2,0(ACRR2) ;[455]
CAMN AT1,AT2 ;[455] THIS ENTRY SAME AS MAJOR ENTRY
MOVE ACRR3,ACRR2 ;[455] YES, SAVE FOR LATER
LDB AT1,CRRIN2 ;[455] LOOK AT NEXT
ADD ACRR2,AT1 ;[455]
JRST S26 ;[455]
S25: JUMPE ACRR3,S23 ;[455] JUMP IF NO PRIOR ENTRY IN TABLE
LDB AT1,[POINT 4,0(ACRR3),6] ;[455] GET PRIOR'S RETAINED FOR FLAG
TRNE AT1,RTTNRD ;[455] PRIOR WAS A READ ONLY?
JRST S21 ;[455] NO
IFN ANS68,< ;[455] USE PRIOR KEY FOR THIS ENTRY SINCE
SKIPN AT1,2(ACRR3) ;[455] THIS ENTRY IS A WRITE AFTER READ,
JRST S21 ;[455] UNLESS THE KEY FOR THE PRIOR ENTRY
>;END IFN ANS68 ;[455] IS ALSO 0
IFN ANS74,< ;[455] PRIOR KEY IS ZERO
LDB AT1,RRTNX3 ;GET "NEXT RECORD" FLAG
JUMPN AT1,S21 ; PRIOR KEY WAS "NEXT RECORD"
MOVE AT1,2(ACRR3) ;NO, GET IT
>;END IFN ANS74
MOVEM AT1,2(ACRR) ;[455] USE PRIOR KEY
JRST S19 ;[455] AND RESUME NORMAL PROCESSING
S23: HLRZ AT1,D.BL(AFT) ;[455] SINCE NO PRIOR ENTRY EXISTS
;[455] IN THE TABLE, SEE WHAT THE LAST
;[455] REAL IO OPERATION WAS FOR THIS FILE
SETO AT2, ;[455]
CAME AT2,LASTUU(AT1) ;[455] WAS THE LAST UUO A READ?
SKIPN AT1,D.RP(AFT) ;[455] YES, USE CURRENT REC # IF NON 0
JRST S21 ;[455] CURRENT REC # IS 0
MOVEM AT1,2(ACRR) ;[455] USE CURRENT REC # FOR THIS ENTRY
;[455] SINCE IT IS A READ AFTER WRITE
JRST S19 ;[455] JOIN NORMAL PROCESSING
; WE HAVE NOW DETERMINED THE QUEUEING REQUIREMENTS FOR INDEXES.
; SO LET'S ASK ENQ/DEQ IF WE CAN HAVE THEM.
LRENQ7: SETZ AT1, ;INDICATE ENQ REQUEST
PUSHJ PP,ENQDEQ
TRNA ;CAN'T HAVE THEM OR SOMETHING'S WRONG
JRST LRENQ0 ;NORMAL RETURN - GO TO THE THIRD LOOP
ABNORM: HLLZ AT1,0(AP) ;IS THERE AN UNAVAILABLE EXIT?
JUMPE AT1,SU.ER7 ;NO, MUST BE AN UNEXPECTED ERROR
AOS 0(PP) ;YES, ADJUST RETURN
SETZM SU.RR ;ZERO NUMBER OF RECORDS RETAINED
RESTRM
POPJ PP, ;RETURN TO THE UNAVAILABLE STATEMENT
; THIRD LOOP.
;
; FINISH THE DETERMINATION OF THE DEFINITION OF "RECORD 0" FOR
; EACH FILE FOR WHICH THE USER HAS SPECIFIED THAT RECORDS BE
; RETAINED
;
; NOW THAT WE'VE BUILT THE TABLE OF RECORDS TO BE RETAINED
; (FIRST LOOP), AND GAINED ACCESS TO THE INDEXES WE REQUIRE
; (SECOND LOOP), IT'S TIME TO DETERMINE WHICH BLOCKS TO WHICH
; WE NEED TO GAIN ACCESS.
;
; AT THIS TIME IN THE PROCESSING WE HAVE ALREADY ENQUEUED ON THE
; INDEX OF AN ISAM FILE AND/OR ON THE ENTIRE FILE FOR A
; RANDOM FILE. THIS GAURANTEES THAT FROM THIS POINT ON NO
; CHANGES CAN BE MADE IN THE FILE BY OTHERS. THIS IS TRUE
; REGARDLESS OF WHETHER WE ENQUEUED SHARED OR EXCLUSIVE.
LRENQ0: MOVE ACRR,SU.RRT ;START WITH THE FIRST ENTRY
SETZM SU.EQ ;ZERO NUMBER OF ENTRIES IN ENQ QUEUE
LRENQ9: CAML ACRR,SU.CRH ;END OF THE THIRD LOOP?
JRST LRENQ5 ;YES, GO GENERATE FINAL ENQ REQUEST IN
;THE FOURTH LOOP
;IF THE FILE IS NOT INDEXED
HRRZ AFT,0(ACRR) ;DEFINE "RECORD 0" FOR THE FILE IN
;WHICH THIS RECORD EXISTS, IF IT HAS
;NOT ALREADY BEEN DEFINED (DUE TO THE
;PROCESSING OF ANOTHER ENTRY SPECIFYING
;ANOTHER RECORD IN THE SAME FILE).
LDB AT2,FTAM
CAIE AT2,INDEXD ;[455]
CAIN AT2,RANDOM ;[455]
JRST V5 ;[455] IF FILE IS INDEXED, OR RANDOM
;GO CALL BLKNUM TO GET BLOCK NUMBER
;AND CHECK FOR LOW-VALUES, REGARDLESS
;OF OTHER CONSIDERATIONS
HRRE AT1,F.WSMU(AFT)
JUMPGE AT1,V2 ;JUMP IF "RECORD 0" ALREADY DEFINED
ADD AT1,D.RP(AFT) ;OTHERWISE RECORD 0 = F.WSMU + D.RP +2
ADDI AT1,2
HRRM AT1,F.WSMU(AFT)
V2: MOVE AT3,2(ACRR) ;[455] IF FILE IS SEQUENTIAL, THEN CONVERT
;THE RELATIVE KEY TO AN ABSOLUTE KEY
;BY ADDING THE DEFINITION OF
;"RECORD 0"
ADD AT3,AT1
MOVEM AT3,2(ACRR)
LDB AT1,CRRQT
SKIPE AT1 ;NO BLOCK REQUIRED IF FILE IS NOT INDEXED AND QT INDICATES
;NO QUEUEING - GO TO END OF LOOP
V5: PUSHJ PP,BLKNUM ;OTHERWISE, GET BLOCK NUMBER
LDB AT1,CRRINE ;MOVE ON TO NEXT REQUEST
ADD ACRR,AT1
JRST LRENQ9
; FOURTH AND FINAL LOOP.
;
; GENERATE AN ENQUEUE REQUEST FOR EACH BLOCK THAT REQUIRES EITHER
; SHARED OR EXCLUSIVE QUEUEING. MAKE SURE THAT EACH BLOCK IS
; QUEUED ONLY ONCE. IF ONE REQUEST ASKS SHARED ACCESS AND ANOTHER
; EXCLUSIVE, QUEUE FOR EXCLUSIVE.
LRENQ5: MOVE ACRR,SU.RRT ;START WITH THE FIRST ENTRY
LREN11: CAML ACRR,SU.CRH ;END OF THE FOURTH LOOP?
JRST LREN12 ;YES, GO ON TO THE FINAL ACT
MOVE ACRR2,SU.RRT ;INITIALIZE FOR SUB-LOOP
SETZM SU.Y ;SET Y TO 0
HRRZ AFT,0(ACRR) ;[455]
LDB AT3,FTAM ;[455] GET FILE TYPE
CAIE AT3,RANDOM ;[455] RANDOM FILE?
IFN ANS68,<
JRST W3A ;[455] NO
>
IFN ANS74,<
JRST W3B ; No
>
MOVE AT2,D.CBN(AFT) ;[455] GET CURRENT REC #
SETZM SU.RND ;[455]
SETZM SU.RLV ;[455]
W9: CAML ACRR2,SU.CRH ;[455] FINISHED SUB-LOOP?
JRST W11 ;[455] YES, MUST BE NO QT 7'S
HRRZ AT1,0(ACRR2) ;[455]
CAME AT1,AFT ;[455] SAME FILE?
JRST W10 ;[455] NO
SKIPN SU.Y ;[455] IS THIS THE FIRST RRT ENTRY FOR THIS FILE?
MOVEM ACRR2,ACRR3 ;[455] YES, SAVE ITS POSITION
SETOM SU.Y ;[455] SET FIRST ALREADY SEEN
LDB AT1,CRRBK2 ;IS THIS AN ENTRY FOR THE CURRENT BLOCK?
CAMN AT1,AT2
SETOM SU.RND ;[455] YES, SET CURRENT BLOCK # SEEN
LDB AT1,CRRQT2 ;[455]
CAIN AT1,7 ;[455] IF ANY ENTRY FOR THIS FILE HAS
;[455] A QT OF 7 THE WHOLE FILE WILL BE
;[455] ENQ'D EXCLUSIVE SO NO NEED TO ENQ ANY
;[455] BLOCKS AT THIS TIME
SETOM SU.RLV ;[455] SET RAND EXCLUSIVE SEEN FLAG
W10: LDB AT1,CRRIN2 ;[455] THIS ONE ISN'T A 7 BUT
ADD ACRR2,AT1 ;[455] CHECK EM ALL
JRST W9 ;[455]
W11: SKIPL SU.RLV ;[455] ANY RAND EXCLUSIVE SEEN?
JRST W13 ;[455] NO, DO IT THE NORMAL WAY
CAMGE ACRR3,ACRR ;[455] HAVE WE ALREADY CHECKED THIS FILE
JRST W1 ;[455] YES GO TO NEXT ONE
LDB AT1,CRRBK3 ;[455] IS THE FIRST RRT FOR THIS FILE A 0 KEY
JUMPE AT1,W12 ;[455] YES DO A FORCR.
SKIPGE SU.RND ;[455] WAS THE CURRENT BLOCK # SEEN?
W12: PUSHJ PP,FF02 ;[455] MAKE AN ENTRY IN SU.FBT
JRST W1 ;[455] CHECK NEXT ENTRY
W13: MOVE ACRR2,SU.RRT ;[455] SET UP ACRR2
SETZM SU.Y ;[455] AND SU.Y
IFN ANS74,<
JRST W3A ;
W3B: CAIE AT3,INDEXD ; Is file indexed?
JRST W3A ; No
HLRZ AT1,D.BL(AFT) ; Get buffer position
SKIPN AT3,SVNXRT(AT1) ; Is current SAVNXT been saved?
JRST W3C ; No, no need to restore it
; Yes, reset RWDLKY to its old value, saved in RWDLRT at BN5 in BLKNUM
; at the same time reset RWDLRT to point at the RETAIN save area, for
; the next call to RETAIN code.
HRRM AT3,D.RFLG(AFT) ; Reset extra flags
SETZM SVNXRT(AT1) ; Clear save flag field
MOVE AT2,RWDLRT(AT1) ; Get retain save area address
MOVE AT3,RWDLKY(AT1) ; Get I-O level NNTRY and save area addr
HRRZM AT3,RWDLRT(AT1) ; Restore retain save area address
MOVEM AT2,RWDLKY(AT1) ; Restore I-O level del/rewrt save area pointer
W3C: HRRZ AT2,D.RFLG(AFT) ; Get savnxt flag
TRNN AT2,SAVNXT ; SAVNXT active at I-O level?
JRST W3A ; No, cont
SETZM CNTRY(AT1) ; Yes, clear fields so that saved position
SETZM NNTRY(AT1) ; Will be restored
>; END IFN ANS74
W3A: LDB AT1,CRRQT
W3: CAIN AT1,1 ;QUEUEING TECHNIQUE IS SHARED?
JRST W2 ;YES
CAIE AT1,2 ;QUEUEING TECHNIQUE IS EXCLUSIVE?
JRST W1 ;NO, LEAVE SUBLOOP AND MOVE ON TO THE
;NEXT MAJOR ENTRY
CAML ACRR2,ACRR
JRST W5 ;JUMP IF EXCLUSIVE AND NO PRIOR EXCLUSIVE
;HERE IF EXCLUSIVE AND IT'S NOT KNOWN
;YET IF THERE IS A PRIOR EXCLUSIVE
W4: HRRZ AT2,0(ACRR)
HRRZ AT3,0(ACRR2)
CAME AT2,AT3 ;SAME FILE?
JRST W7 ;NO, SO GET NEXT ENTRY
LDB AT2,CRRBLK
LDB AT3,CRRBK2 ;SAME BLOCK?
CAME AT2,AT3
JRST W7 ;NO, SO GET NEXT ENTRY
LDB AT2,CRRQT2
CAIN AT2,2 ;EXCLUSIVE?
JRST W1 ;YES, JUMP OUT OF SUB-LOOP AND MOVE
;ON TO THE NEXT MAJOR ENTRY
CAIE AT2,1 ;SHARED?
JRST W7 ;NO, SO GET NEXT ENTRY
CAMGE ACRR2,ACRR ;A PRIOR ENTRY?
SETOM SU.Y ;YES, SET Y TO 1
W7: LDB AT2,CRRIN2 ;GET NEXT ENTRY IN SUB-LOOP
ADD ACRR2,AT2
JRST W3
W2: CAMGE ACRR2,SU.CRH
JRST W4 ;JUMP IF SHARED AND NOT ALL BLOCKS CHECKED
SKIPE SU.Y ;DOES Y = 1 (A PRIOR ENTRY HAS QUEUED
;SHARED ON THIS BLOCK?)
JRST W1 ;YES, MOVE ON TO THE NEXT MAJOR ENTRY
HRLZI AT1,1 ;SET LH TO SHARED, RH TO ENQ
W8: LDB AT2,CRRBLK ;[455] GET BLOCK NUM (FOR FILFLU ROUTINE)
REPEAT 0,<
;THIS CODE HAS BEEN REMOVED (3/31/78) BECAUSE THE BUFFER FILLING
;WAS DONE BEFORE THE .IDA FILE BLOCKS HAD BEEN ENQ'D
; FILFLU MUST BE CALLED TO MAKE CBLIO PRETEND IT HASN'T READ IN
;THAT DATA BLOCK YET. IT WILL BE DONE AT THE "READ".
HRRZ AFT,0(ACRR) ;IF THIS IS AN INDEXED FILE, BUFFER
LDB AT3,FTAM ;FILLING WAS HANDLED IN THE THIRD
LDB AT4,FTOTA
CAIE AT3,INDEXD ;LOOP BY THE BLKNUM ROUTINE
JRST W14
TRNN AT4,3
TRNN AT4,4
JRST .+2
W14:
>;END OF REPEAT 0
PUSHJ PP,FILFLU ;CHECK TO SEE IF BUFFER WILL NEED
;TO BE REFILLED
PUSHJ PP,QUEUE ;QUEUE REQUEST
W1:
IFN LSTATS,<
LDB AT1,CRRQT ;GET QT VALUE
ADD AT1,MRTDBP ;ADD IN TRAILER ADDRESS
AOS MB.RTN(AT1) ;INCREMENT PROPER RETAIN BUCKET
>
LDB AT2,CRRINE ;MOVE ON TO GET NEXT MAJOR ENTRY
ADD ACRR,AT2
JRST LREN11
W5: SETZ AT1, ;SET LH TO EXCLUSIVE, RH TO ENQ
JRST W8
; THE FINAL ACT
;
; CALL ENQ/DEQ TO QUEUE BLOCKS
LREN12: SETZ AT1, ;SET RH TO ENQUEUE
PUSHJ PP,ENQDEQ
JRST LREN99 ;NOT AVAILABLE OR ERROR
MOVEI AT1,AT1
HRLM AT1,SU.FBT
LREN13: RESTRM
SOSGE AT1,SU.CFB ;NORMAL RETURN. WE NOW HAVE DESIRED
;ACCESS TO REQUESTED BLOCKS. ASK CBLIO
;TO REFILL THE CURRENT BUFFER FOR
;EACH FILE, IF, IN FACT, IT CONTAINS
;ONE OF THE BLOCKS WE'VE JUST GAINED
;ACCESS TO.
IFE LSTATS,<
POPJ PP, ;RETURN TO USER
>
IFN LSTATS,<
JRST LRENMR ;METER THEN EXIT
>
MOVE AP,@SU.FBT
PUSHJ PP,FORCR.
JRST LREN13
IFN LSTATS,<
LRENMR: MOVE AT1,MRTDBP ;GET TRAILER ADDRESS
MOVEI AT1,MB.SUT(AT1) ;GET ADDRESS TO RETAIN TIMING BUCKET
MOVEM AT1,MRTMB. ;SAVE TIMING ADDRESS
MRTME. (AT1) ; END RETAIN TIMING
POPJ PP, ;RETURN TO CBL PROGRAM
>;END IFN LSTATS
; THE BLOCKS WEREN'T AVAILABLE, SO NOW WE HAVE TO DEQUEUE THE INDEXES!!!!
LREN99: MOVE ACRR,SU.RRT ;LOOK THROUGH THE RETAINED RECORDS TABLE
SETZM SU.DQ ;ZERO THE NUMBER OF ENTRIES IN THE DEQUEUE QUEUE
LREN95: CAML ACRR,SU.CRH
JRST LREN94 ;JUMP IF END OF TABLE
HRRZ AFT,0(ACRR)
LDB AT1,FTAM
CAIE AT1,RANDOM ;[455] RANDOM FILE?
CAIN AT1,INDEXD ;[455] NO, INDEXED
SKIPA ACRR2,SU.RRT ;[455] YES, MUST BE EITHER RAND OR INDEX
;SEE IF A PREVIOUS ENTRY INVOLVED THE SAME FILE
JRST LREN98 ;[455] IGNORE ENTRY IF FILE NOT INDEXED, OR RANDOM
LREN96: CAML ACRR2,ACRR
JRST LREN97 ;JUMP IF ALL PREVIOUS ENTRIES EXAMINED
HRRZ AT1,0(ACRR2)
CAMN AT1,AFT
JRST LREN98 ;JUMP IF PREVIOUS ENTRY INVOLVED SAME FILE
LDB AT1,CRRIN2 ;OTHERWISE, EXAMINE ANOTHER PREVIOUS ENTRY
ADD ACRR2,AT1
JRST LREN96
LREN97: MOVEI AT1,1 ;DEQUEUE THE INDEX
SETO AT2,
PUSHJ PP,QUEUE
LREN98: LDB AT1,CRRINE ;MOVE ON TO THE NEXT ENTRY
ADD ACRR,AT1
JRST LREN95
LREN94: MOVEI AT1,1
MOVEI AT2,1
PUSHJ PP,ENQDEQ ;ACTUALLY CALL ENQ/DEQ
JRST SU.ER7
JRST ABNORM
; LRDEQ: LIBOL RECORD DEQUEUE - CALLED FOR EACH EXECUTION OF A FREE STATEMENT
;
;
; LRDEQ EXPECTS TO FIND IN AC16 THE ADDRESS OF AN ARGUMENT LIST
; STRUCTURED AS FOLLOWS:
;
; WORD 1: RH = NUMBER OF RECORDS TO BE FREED (N)
; LH = 0 => USER DID NOT SUPPLY A NOT RETAINED STATEMENT
; LH = 1 => USER DID SUPPLY A NOT RETAINED STATEMENT
;
; WORD 2: BITS 0-8: 152
; BIT 9: FREE ALL RECORDS, IF SET
; BIT 10: FREE ALL RECORDS IN THIS FILE, IF SET
; BITS 11-13: NOT USED
; BIT 14: USER SUPPLIED DATA NAME OR LITERAL, IF SET
; BITS 15-17: NOT USED
; RH = FILE TABLE LOCATION
;
; WORDS 3,4,...,N: SAME AS SPECIFIED FOR LRENQ
;
;
; THIS PROCEDURE SHARES ALL DATA STRUCTURES, SUBROUTINES AND
; SYMBOLS WITH LRENQ.
;
;
; THIS PROCEDURE ASSUMES THAT BUFFERS ARE NOT SHARED. SHOULD
; THEY EVER BE SHARED, ONE SMALL CHANGE WILL BE NEEDED IN THE
; ALGORITHM (SEE COMMENT IN THE CODE).
;
; THIS PROCEDURE HAS A SECONDARY ENTRY POINT AT LRDEQX, FOR
; USE IN CASE OF AUTOMATIC FREEING BY READ, REWRITE, WRITE,
; AND DELETE. TO ENTER THIS PROCEDURE AT LRDEQX, SET THE F
; BIT OF ALL RECORDS TO BE FREED IN THE RETAINED RECORDS TABLE
; AND SIMPLY DO A PUSHJ PP, LRDEQX. NO PARAMETERS ARE
; REQUIRED. LRDEQX RETURNS TO 0(PP).
LRDEQ.: SAVE
SKIPE SU.RR ;ARE ANY RECORDS CURRENTLY RETAINED?
JRST A1 ;YES, LET'S DIG DEEPER
HLLZ AT1,0(AP) ;IS THERE A NOT RETAINED EXIT?
SKIPE AT1
AOS 0(PP) ;YES, ADJUST RETURN
RESTRM
POPJ PP, ;RETURN TO USER
A1: MRTMS. (AT1) ;START METER TIMING
SETZM SU.CFB ;ZERO NUMBER OF ENTRIES IN THE FILL/
;FLUSH BUFFER TABLE
MOVE AT1,1(AP)
TLNN AT1,FREALR ;FREE ALL RECORDS?
JRST A2 ;NO
MRHDCT (MB.FEV,AT1) ;COUNT FREE EVERY REC METER POINT
MOVE I,SU.RR
MOVE ACRR,SU.RRT
SETO AT1,
A00: DPB AT1,CRRF ;SET FREE BIT IN EVERY ENTRY OF THE RETAINED RECORDS TABLE
LDB AT2,CRRINE
ADD ACRR,AT2
SOJG I,A00
PUSHJ PP,LRDEQX ;DEQUEUE EVERYTHING
RESTRM
POPJ PP,
A2: SETZM SU.NR ;ZERO NOT RETAINED FLAG, WHICH WE
;WILL SET SHOULD WE DISCOVER THE
;USER ATTEMPTING TO FREE A RECORD HE HAS
;NOT RETAINED
MOVEI AURS,1(AP) ;POINT AURS TO THE 1ST USER RECORD
;SPECIFICATION
HRRZ K,0(AP) ;COUNT USER RECORD SPCEIFICATIONS WITH K
LRDEQ0: LDB AT1,URSCON ;MAKE A LITTLE VALIDITY CHECK
CAIE AT1,152
JRST SU.ER2
MOVE AT1,0(AURS)
MOVSI ACRR2,(JFCL) ;[550] SET UP FOR LATER KEY COMPARE
TLNN AT1,USRSKY ;USER SUPPLIED A KEY?
JRST A4 ;NO
MRHDCT (MB.FRC,AT1) ;COUNT FREE REC METER POINT
LDB AT1,URSTYP ;YES, COMPILER HAS ALREADY CHECKED
;THAT IT MATCHES THE KEY OF THE FILE, SO
;WE CAN TURN OUR ATTENTION
;TO BUILDING A BYTE POINTER TO IT.
CAIN AT1,2
JRST A5 ;JUMP IF KEY 1 WORD COMP
CAIE AT1,4
JRST A6 ;JUMP IF KEY NOT 1 WORD COMP-1
A5: MOVEI AT3,1 ;SET KEY LENGTH IN BYTES IN AT3
JRST A7
A6: CAIE AT1,11
JRST A8 ;JUMP IF NOT 2 WORD KEY
MOVEI AT3,2 ;SET KEY LENGTH IN BYTES IN AT3
A7: MOVE AT2,1(AURS) ;GET ADDRESS FROM USER RECORD
;SPECIFICATION
A12: TLZ AT2,777740 ;ZERO P AND S FIELDS
TLO AT2,444400 ;SET BYTE SIZE TO 36
;WE NOW HAVE A BYTE POINTER TO THE KEY
;[550] MOVSI ACRR2,(JFCL) ;[447] SET UP FOR LATER KEY COMPARE
HRRZ AFT,0(AURS) ;IF FILE IS SEQUENTIAL, OR THE FILE
;IS RANDOM AND THE KEY IS ZERO,
;CONVERT THE RELATIVE KEY INTO AN
;ABSOLUTE KEY BY ADDING THE DEFINITION
;OF "RECORD 0" (F.WSMU). ADJUST AT2 TO
;POINT TO THE ABSOLUTE KEY INSTEAD OF
;THE RELATIVE KEY. NOTE: IF THE FILE
;IS NOT INDEXED, THE KEY IS ALWAYS
;ONE WORD COMP.
LDB AT1,FTAM
CAIN AT1,INDEXD
JRST A9
SKIPN AT4,0(AT2)
JRST A19
CAIN AT1,RANDOM
JRST A9
A19: CAIN AT1,RANDOM ;[455] RANDOM FILE?
JRST FRERLV ;[455] YES
HRRZ AT5,F.WSMU(AFT) ;[455]
ADD AT4,AT5
MOVEM AT4,SU.AK
HRRI AT2,SU.AK
JRST A9
FRERLV:
MOVE ACRR,SU.RRT ;[455] 'FREE' WITH KEY OF 0 WILL
;[455] FREE FIRST RECORD IN RRT WITH
;[455] A KEY OF 0 FOR THAT FILE
CAML ACRR,SU.CRH ;[455] LOOKED AT ALL RECORDS YET?
JRST B6M1 ;[455] YES, NO 0 KEY EXISTS
HRRZ AT1,0(ACRR) ;[455]
CAME AT1,AFT ;[455] SAME FILE?
JRST FRELV1 ;[455] NO
LDB AT1,CRRF ;[455] GET FREED FLAG
JUMPN AT1,FRELV1 ;[455] ARE WE LOOKING AT AN ALREADY FREED REC
IFN ANS74,< ;(ASSUMING A KEY VALUE OF 0 WERE ALLOWED)
LDB AT1,RRTNXT ;IF "NEXT RECORD" WAS RETAINED,
JUMPN AT1,FRELV2 ; THEN NO KEY WAS MOVED
JRST FRELV1 ;NOT AN ENTRY FOR "NEXT RECORD"
>;END IFN ANS74
IFN ANS68,<
SKIPE 2(ACRR) ;[455] IS THIS A 0 KEY?
JRST FRELV1 ;[455] NO
>;END IFN ANS68
FRELV2: SETO AT1, ;[455]
DPB AT1,CRRF ;[455] TURN ON FREE FLAG
JRST B6 ;[455] GO DO NEXT USER RECORD SPEC
FRELV1: LDB AT1,CRRINE ;[455]
ADD ACRR,AT1 ;[455] LOOK AT NEXT ENTRY
JRST FRERLV+1 ;[455]
A8: CAIE AT1,15
JRST SU.ER5 ;JUMP IF INVALID TYPE CODE
;[532] PUSH PP,K
;[532] RESTRM
MOVEI AT1,@1(AURS) ;GET ADDRESS OF 2 WORD DESCRIPTOR
;IN AT1
;[532] POP PP,K
HRRZ AT3,1(AT1) ;GET SIZE FIELD FROM TWO WORD DESCRIPTOR
;IN AT3
;[550] MOVSI ACRR2,(JFCL) ;[532] NO CONVERSION NECESSARY
HRRZ AFT,0(AURS) ;SET FILE TABLE ADDRESS IN AFT
LDB AT2,FTKLB
CAME AT2,AT3
JRST SU.ER6 ;JUMP IF KEY SIZE INAPPROPRIATE; THE
;COMPILER ALREADY CHECKED THIS, BUT
;WHAT THE HELL.
MOVE AT2,0(AT1) ;GET BYTE POINTER TO USER SUPPLIED
;KEY IN AT2
JRST A9
A4:
IFE LSTATS,<
TLNE AT1,FREFEV
JRST A9 ;JUMP IF EVERY RECORD RETAINED FOR
> ;THIS FILE IS TO BE FREED
IFN LSTATS,<
TLNN AT1,FREFEV ;SKIP IF FREE EVERY REC FOR FILE
JRST LDQLST ;NOT EVERY REC, JUMP
MRHDCT (MB.FFE,AT1) ;COUNT METER POINT
JRST A9 ;CONTINUE
LDQLST:>
HRRZ AFT,0(AURS)
LDB AT1,FTAM
CAIE AT1,INDEXD
JRST A11 ;JUMP IF FILE NOT INDEXED
PUSH PP,ACRR2 ;SAVE CONVERT INSTRUCTION
PUSHJ PP,CLVACI ;COMPARE KEY AGAINST LOW-VALUES AND
;CONVERT, IF NECESSARY
JRST [POP PP,(PP) ;THROW AWAY OLD CONVERT INSTR
MOVE ACRR2,D.RCNV(AFT) ;[447] DO FILE TABLE CONV
PUSHJ PP,CHGCNV ;[447] CHECK FOR SPECIAL CONV INSTRS.
MOVE AT2,SU.RBP ;[447] GET DATA-REC-KEY BYTE PTR
JRST A10] ;[534][447] RESUME
;[550] MOVSI ACRR2,(JFCL) ;[447] SET UP PHONY CONV INSTR.
POP PP,ACRR2 ;RESTORE CONVERT INSTR
MOVE AT2,F.WBSK(AFT) ;BYTE POINTER TO SYMBOLIC KEY
A10: LDB AT3,FTKLB ;[534] GET KEY LENGTH IN AT3
JRST A9
A11: MOVEI AT3,1 ;KEY SIZE IS 1 WHETHER RANDOM OR
;SEQUENTIAL
HRRZ AT2,F.RACK(AFT) ;CREATE BYTE POINTER FROM THE
;ADDRESS OF THE ACTUAL KEY
CAIE AT1,RANDOM ;BUT ONLY IF IT'S A RANDOM FILE
MOVEI AT2,[0] ;IF IT'S A SEQUENTIAL FILE USE KEY
;OF ZERO
JRST A12
; AT THIS POINT WE HAVE A BYTE POINTER TO THE KEY OF THE
; RECORD TO BE FREED IN AT2, AND THE LENGTH OF THAT KEY IN AT3.
; (EXCEPT IN THE CASE OF FILENAME - EVERY RECORD)
;
; WE'LL NOW LOCATE THE ONE OR MORE RECORDS TO BE FREED IN THE
; RETAINED RECORDS TABLE, AND SET THEIR F BITS.
A9: MOVE I,SU.RR ;COUNT THE ENTRIES IN THE RETAINED
;RECORDS TABLE IN I
SETZM SU.Y ;ZERO FLAG Y. IN CASE OF THE FILENAME
;EVERY RECORD OPTION, WE'LL SET IT TO
;ONE IF WE FIND A MATCH ON FILENAME IN
;THE RETAINED RECORDS TABLE
MOVE ACRR,SU.RRT ;POINT TO THE 1ST ENTRY IN THE
;RETAINED RECORDS TABLE
B1: HRRZ AT1,0(AURS)
HRRZ AT4,0(ACRR)
CAME AT1,AT4 ;COMPARE FILES
JRST B3 ;JUMP IF NOT THE RIGHT FILE
MOVE AT1,0(AURS)
TLNN AT1,000200 ;EVERY RECORD OPTION?
JRST B4 ;NO, JUMP
SETOB AT1,SU.Y ;YES, SET F BIT IN RETAINED RECORDS
;TABLE SO AS TO FREE RECORD LATER,
;AND ALSO SET Y FLAG TO INDICATE THAT
;WE FOUND ONE
DPB AT1,CRRF
JRST B3 ;CONTINUE TO LOOK FOR OTHER RECORDS
;IN THE SAME FILE
B4: MOVEM AT3,SU.T3 ;COMPARE KEYS
MOVEM AT2,SU.T2 ;SAVE KEY POINTER AND LENGTH
MOVE AT1,AT2 ;GET SIZE FIELD FROM BYTE POINTER
TLZ AT1,770077 ;ISOLATE IT
TLO AT1,440000 ;SET P TO 36
HRRI AT1,2(ACRR) ;SET ADDRESS TO KEY IN RETAINED RECORDS
;TABLE
SKIPE SU.HV ;[447] FORCED HIGH VALUES IN USE?
JRST B8 ;[447] YES
B5: ILDB AT5,AT2 ;[447] USE AC 11 BECAUSE FILE TABLE
;[447] CONV INSTR DOES
XCT ACRR2 ;[447] CONVERT FROM EXT RECORDING MODE
;[447] TO INTERNAL MODE IF NECESSARY
ILDB AT4,AT1 ;[447] SWITCH AT4 FOR AT5
CAME AT4,AT5
JRST B7 ;JUMP IF KEYS NOT EQUAL
SOJG AT3,B5
B9: SETO AT1, ;[447] SET F FIELD IN THE RETAINED RECORDS
;TABLE
DPB AT1,CRRF
JRST B6 ;MOVE ON TO THE NEXT USER RECORD SPEC
B7: MOVE AT2,SU.T2 ;RESTORE KEY POINTER AND COUNT
MOVE AT3,SU.T3
B3: LDB AT1,CRRINE ;POINT TO NEXT ENTRY IN THE
;RETAINED RECORDS TABLE
ADD ACRR,AT1
SOJG I,B1
B2: SKIPN SU.Y ;SET NOT RETAINED FLAG IF NO SUCH
;RECORD FOUND
B6M1: SETOM SU.NR
B6: MOVE AT1,0(AURS)
SETZM SU.HV ;[447] TURN OFF HIGH VALUES USED
ADDI AURS,1
TLNE AT1,000010
ADDI AURS,1
SOJG K,LRDEQ0
A3: PUSHJ PP,LRDEQX ;NOW CONSIDER THE IMPLICATIONS OF
;DELETING THE FLAGGED RECORDS
JRST LRDEQC ;AND FINALLY, GO TO CLEANUP
B8: LDB AT5,AT2 ;[447] GET THE HIGH VALUES CHARACTER
ILDB AT4,AT1 ;[447] GET RRT KEY CHAR
CAME AT4,AT5 ;[447] ARE THEY THE SAME
JRST B7 ;[447] NO--CHECK NEXT RRT ENTRY
SOJG AT3,B8+1 ;[447] YES--CHECK NEXT CHAR IN RRT
JRST B9 ;[447] GOTCHA--JOIN COMMON CODE
; ALL THE RECORDS IN THE RETAINED RECORDS TABLE TO BE FREED HAVE
; NOW BEEN MARKED WITH SET F BITS. WE WILL NEXT CONSIDER THE
; IMPLICATIONS OF FREEING THESE RECORDS, WHICH ARE AS FOLLOWS:
;
; A. IF QUEUEING TECHNIQUE IS 0 (NO QUEUEING), OR 4 OR 5
; (COVERED BY ANOTHER RETAINED RECORD'S REQUIREMENT
; FOR EXCLUSIVE USE OF THE FILE), THEN THERE IS
; NO MORE WORK TO BE DONE.
;
; B. IF QUEUEING TECHNIQUE IS 3 (INDEX-EXCLUSIVE), WE
; NEED TO CHECK IF THERE IS A CONTINUED NEED FOR
; EXCLUSIVE USE OF THE FILE (OR INDEX), AND IF NOT,
; EITHER FREE THE INDEX OR MODIFY ITS USAGE TO SHARED.
; THE LATTER COURSE WOULD BE TAKEN IF ANOTHER REQUEST
; FOR THE SAME FILE HAS QUEUEING TECHNIQUE OF 4 OR 5,
; AND IT WOULD ALSO BE NECESSARY IN THAT CASE TO
; CHANGE THE QT TO 1 OR 2 AND ENQUEUE ON THE
; APPROPRIATE BLOCKS.
;
; C. IF QUEUEING TECHNIQUE IS 2 (EXCLUSIVE), WE NEED TO CHECK IF
; ANOTHER REQUEST HAS EITHER A SHARED OR EXCLUSIVE
; REQUIREMENT FOR THE SAME BLOCK, AND IF SO, REDUCE ITS USAGE
; TO SHARED OR LEAVE IT ENQUEUED EXCLUSIVE. OTHERWISE WE FREE IT.
;
; D. IF QUEUEING TECHNIQUE IS 1 (SHARED), WE NEED TO CHECK
; IF ANOTHER REQUEST HAS A CONTINUING REQUIREMENT FOR
; THE BLOCK. IF SO, WE LEAVE IT ENQUEUED, OTHERWISE
; WE FREE IT.
;
; E. IF QUEUEING TECHNIQUE IS 7 (RANDOM EXCLUSIVE), WE
; NEED TO CHECK IF ANOTHER RECORD FOR THIS FILE HAS A
; QT OF 7. IF THERE IS ANOTHER ONE, WE DO NOTHING, IF
; THERE ISN'T ANOTHER ONE, WE NEED TO MODIFY FILE
; ENQUEUEING TO SHARED. OBVIOUSLY, IF THERE ARE NO OTHER
; RECORDS IN THE RRT FOR THIS FILE AT ALL, THEN WE DEQUE
; THE FILE RESOURCE. ONCE THE FILE RESOURCE IS TAKEN
; CARE OF, THE PROCESSING IN STEPS C AND D ABOVE NEED TO
; BE DONE FOR THE DISK BLOCK.
;
;
; AS WE GO, WE'LL PREPARE THREE LISTS OF ENQ/DEQ REQUESTS:
; ENQUEUE, DEQUEUE, AND MODIFY LISTS.
;
; AS WE FREE A RECORD WE'LL LEAVE ITS F BIT SET AND ALSO
; SET ITS FILE TABLE ADDRESS TO ZERO.
;
; LRDEQX IS THE SECONDARY ENTRY POINT USED BY READ, REWRITE,
; WRITE, AND DELETE WHEN AUTOMATICALLY FREEING RECORDS.
; (SEE COMMENTS ABOVE)
LRDEQX: SETZM SU.EQ ;INITIALIZE NUMBER OF ENTRIES IN EACH
;OF THE ENQ/DEQ TABLES
SETZM SU.CFB ;[437] CLEAR FILL/FLUSH BUFFER
SETZM SU.DQ
SETZM SU.MQ
SETZM SU.MRR ;ZERO THE "MORE RETAINED RECORDS" FLAG
MOVEM PP,20(PP) ;SAVE ALL REGISTERS
MOVEM AP,17(PP)
MOVE AP,PP
MOVEI PP,1(PP)
BLT PP,16(AP)
MOVE PP,20(AP)
MOVE AP,17(PP)
ADD PP,[20,,20]
MOVE I,SU.RR
MOVE ACRR,SU.RRT
C1: HRRZ AFT,0(ACRR)
JUMPE AFT,C3 ;JUMP IF RECORD FREED BY
;PREVIOUS FREE STATEMENT (IF SO,
;FILE TABLE POINTER = 0)
LDB AT1,CRRF
JUMPE AT1,C4 ;JUMP IF RECORD NOT TO BE FREED (F = 0)
LDB AT1,CRRQT
JUMPE AT1,C5 ;JUMP IF QT = 0 (NO QUEUEING)
CAIG AT1,5 ;[455]
CAIGE AT1,4
JRST C6 ;[455] JUMP IF QT NOT 4 OR 5 OR 7
C5: SETZ AT1, ;ZERO FILE TABLE POINTER TO INDICATE
;RECORD FREED
HRRM AT1,0(ACRR)
JRST C3
C4: SETOM SU.MRR ;SET FLAG INDICATING THAT AT LEAST
;ONE RETAINED RECORD REMAINS
JRST C3
C6: MOVE J,SU.RR ;SET J, ACRR2, AND BOOLEAN VARIABLES IN PREPARATION FOR
;SUB-LOOP
MOVE ACRR2,SU.RRT
SETZM SU.SBD
SETZM SU.SFQ
SETZM SU.SFS
SETZM SU.SBS
SETZM SU.RLV ;[455]
SETZM SU.RND ;[455]
C7: CAMN ACRR,ACRR2 ;I = J?
JRST C9 ;YES, JUMP TO END OF SUB-LOOP
HRRZ AT1,0(ACRR) ;SAME FILE (AND J NOT ALREADY FREED)?
HRRZ AT2,0(ACRR2)
CAME AT1,AT2
JRST C9 ;NO, JUMP TO END OF SUB-LOOP
SETOM SU.SFQ ;YES, SET SAME FILE FLAG
LDB AT1,CRRQT
LDB AT2,CRRQT2
CAMN AT1,AT2 ;SAME QUEUEING TECHNIQUE?
SETOM SU.SFS ;YES, SET SAME FILE, SAME QT FLAG
CAIN AT2,7 ;[455] ANY OTHER ENTRYS FOR THIS FILE EXCLUSIVELY
SETOM SU.RLV ;[455] YES, REMEMBER IT
LDB AT3,CRRBLK
LDB AT4,CRRBK2
CAME AT3,AT4 ;SAME BLOCK?
JRST C9 ;NO, JUMP TO END OF SUB-LOOP
CAMN AT1,AT2 ;SAME QUEUEING TECHNIQUE?
JRST C10
SETOM SU.SBD ;NO, SET SAME BLOCK, DIFFERENT QT FLAG
JRST C9
C10: SETOM SU.SBS ;YES, SET SAME BLOCK, SAME QT FLAG
C9: LDB AT1,CRRIN2 ;INCREMENT J
ADD ACRR2,AT1
SOJG J,C7
LDB AT1,CRRQT
CAIE AT1,3 ;QT = 3 (INDEX-EXCLUSIVE)?
JRST C11 ;NO, JUMP
SKIPE SU.SFS ;YES, ANOTHER ENTRY HAS SAME QT?
JRST C5 ;YES!, WE DON'T NEED TO DO ANYTHING.
SKIPE SU.SFQ ;NO, ANOTHER ENTRY FOR THE SAME FILE?
JRST C17 ;YES, JUMP
C16: MOVEI AT1,1 ;NO, DEQUEUE INDEX
SETO AT2, ;SET AT2 TO SPECIAL BLOCK NUMBER
;INDICATING INDEX
C14: PUSHJ PP,QUEUE
JRST C5
C11: HRRZ AFT,0(ACRR) ;[455]
LDB AT2,FTAM ;[455] CHECK FILE TYPE
CAIE AT2,RANDOM ;[455] IS IT A RANDOM FILE?
JRST C11A ;[455] NO
SETOM SU.RND ;[455] YES, REMEMBER IT
SKIPE SU.RLV ;[455] IS THERE A RANDOM EXCLUSIVE ENTRY
JRST C5 ;[455] YES, DO NOTHING ELSE
CAIE AT1,7 ;[455] IS THIS ENTRY A RANDOM EXCLUSIVE?
JRST C11A ;[455] NO, DO IT NORMAL
HLRZ AT4,D.BL(AFT) ;[455] SEE IF THERE IS ANY LIVE DATA IN
SETO AT5, ;[455] THE CURRENT BUFFER. IF THERE IS,
CAMN AT5,LIVDAT(AT4) ;[455] SET AN ENTRY IN SU.FBT SO A FORCW.
PUSHJ PP,FF02 ;[455] HAPPENS
SKIPE SU.SFQ ;[455] YES, ANY OTHER ENTRIES FOR THIS FILE
JRST C17 ;[455] YES, ENQ PROPER BLOCKS, AND CHANGE
;[455] FILE ENQ TO SHARED
JRST C16 ;[455] NO, DEQ FILE AND FREE THIS ENTRY
C11A: CAIE AT1,2 ;[455] QT = 2 (EXCLUSIVE)?
JRST C12 ;NO, JUMP
SKIPE SU.SBS ;YES, ANOTHER REQUEST IS USING THE
;SAME BLOCK THE SAME WAY?
JRST C5 ;YES! DO NOTHING.
SKIPE SU.SBD ;NO, ANOTHER REQUEST IS USING
;THE SAME BLOCK DIFFERENTLY (I.E.,
;IN SHARED MODE)?
JRST C11B ;YES,SKIP AHEAD
SETZ AT1, ;NO, INDICATE EXCLUSIVE DEQ
JRST C13 ; DEQUEUE BLOCK
C11B: MOVE AT1,[1,,2] ; SET AT1 TO INDICATE "MODIFY"
LDB AT2,CRRBLK ;SET BLOCK NUMBER IN AT2
PUSHJ PP,FILFL2 ;CHECK TO SEE IF BUFFER NEEDS TO BE
;WRITTEN ON DISC
JRST C14 ;MODIFY ACCESS TO SHARED
C12: SKIPN SU.SBD ;(QT = 1, SHARED)
SKIPE SU.SBS
JRST C5 ;JUMP IF ANOTHER REQUEST IS USING
;THE SAME BLOCK, EITHER EXCLUSIVELY
;OR SHARED
HRLI AT1,1 ;INDICATE SHARED DEQ
C13: HRRI AT1,1
LDB AT2,CRRBLK
PUSHJ PP,FILFL2 ;CHECK TO SEE IF BUFFER NEEDS TO BE
;WRITTEN ON DISC
PUSHJ PP,QUEUE ;DEQUEUE BLOCK
SKIPE SU.SFQ ;ANOTHER REQUEST FOR THE SAME FILE?
JRST C5 ;YES, WE'RE ALL DONE
C15: HRRZ AFT,0(ACRR) ;NO, IS FILE INDEXED OR RANDOM?
LDB AT1,FTAM
CAIN AT1,SEQFIL## ;[455] IF IT'S A SEQUENTIAL FILE, IT CAN'T
;[455] BE INDEXED OR RANDOM
JRST C5 ;IT'S SEQUENTIAL
MOVEI AT1,12 ;CHECK FOR CLOSE VERB
CAMN AT1,SU.VRB ; is it
JRST C16 ; yes, no need to reset position
; GO DEQUEUE INDEX (RANDOM AND IDX)
CAIE AT1,RANDOM ;[455] IS IT RANDOM OR INDEXED
PUSHJ PP,RESTOR ;INDEXED, RESTORE CURRENT RECORD POINTER,
;IF NECESSARY
JRST C16 ;GO DEQUEUE INDEX (RANDOM AND IDX)
C17: MOVE AT1,[1,,2] ;CHANGE USAGE OF INDEX TO SHARED
SETO AT2,
PUSHJ PP,QUEUE
; AT THIS POINT(WE'RE LOOKING AT AN ENTRY WHICH HAS THE
; ENTIRE INDEX LOCKED, BUT WHICH WE'RE GOING TO FREE),
; WE NEED TO LOCATE THOSE ENTRIES WHICH HAVE PREVIOUSLY BEEN
; COVERED BY THIS ENTRY (QT = 4 OR 5), CHANGE THEIR QUEUEING
; TECHNIQUE TO 1 OR 2 (SHARED OR EXCLUSIVE), AND QUEUE ON THE
; INDIVIDUAL BLOCKS. THIS WILL REQUIRE A SUB-LOOP AND A
; SUB-SUB-LOOP.
MOVE J,SU.RR ;INITIALIZE FOR SUB-LOOP
MOVE ACRR2,SU.RRT
SKIPE SU.RND ;[455] IS THIS A RANDOM FILE?
JRST E1 ;[455] YES
D1: CAMN ACRR,ACRR2 ;I = J?
JRST D2 ;YES, GO TO END OF SUB-LOOP
HRRZ AT2,0(ACRR2)
HRRZ AT1,0(ACRR)
CAME AT1,AT2 ;SAME FILE (AND J NOT ALREADY FREED)?
JRST D2 ;NO, GO TO END OF SUB-LOOP
;AT THIS POINT, QT(J) MUST BE EITHER
;4 OR 5. IF IT WERE 0,1,2 OR 3 WE
;WOULDN'T BE HERE.
;
;IT CAN'T BE 3, BECAUSE SU.SFS (SAME
;FILE, SAME QUEUEING) WOULD HAVE BEEN
;SET, AND WE WOULDN'T BE HERE (SEE LABEL
;C8 ABOVE). IT CAN'T BE 1 OR 2, SINCE
;A VALUE OF 1 OR 2 WOULD NOT HAVE BEEN
;ASSIGNED INITIALLY BECAUSE QT(I)
; = 3, AND FURTHERMORE A CHANGE FROM 4
;OR 5 TO 1 OR 2 COULD HAVE ONLY
;BEEN MADE BY THIS CODE, WHICH COULD NOT
;HAVE HAPPENED BECAUSE FOR ANY L < I,
;THE FACT THAT QT(I) = 3 WOULD HAVE SET
;SU.SFS, AND WE WOULDN'T HAVE COME HERE.
;FINALLY, IT CAN'T BE ZERO BECAUSE QT(I)
; IS NOT ZERO AND SU.RR IS NOT ONE.
LDB AT3,CRRQT2
SUBI AT3,3
DPB AT3,CRRQT2 ;CHANGE QT TO 1 OR 2
MOVE K,SU.RR ;INITIALIZE FOR SUB-LOOP
MOVE ACRR3,SU.RRT
D3: CAMN ACRR2,ACRR3 ;K = J?
JRST D5 ;YES, JUMP
HRRZ AT1,0(ACRR2)
HRRZ AT2,0(ACRR3)
CAME AT1,AT2 ;SAME FILE (AND K NOT ALREADY FREED)?
JRST D5 ;NO, JUMP
LDB AT3,CRRBK2
LDB AT1,CRRBK3 ;SAME BLOCK?
CAME AT1,AT3
JRST D5 ;NO, JUMP
LDB AT1,CRRQT3
CAIN AT1,1 ;QT(K) = SHARED (1)?
JRST D7 ;YES, JUMP
CAIN AT1,2 ;QT(K) = 2 (EXCLUSIVE)?
JRST D2 ;YES, JUMP OUT OF SUB-SUB-LOOP TO
;END OF SUB-LOOP. WE DON'T NEED TO
;DO ANYTHING BECAUSE ANOTHER
;REQUEST HAS ALREADY QUEUED THE
;BLOCK EXCLUSIVE
CAIN AT1,5 ;QT(K) = 5?
JRST D4 ;YES, JUMP
LDB AT1,CRRQT2 ;QT(K) = 4, BY DEFAULT
CAIE AT1,1 ;QT(J) = SHARED?
JRST D10 ;NO, IT MUST BE EXCLUSIVE. NO NEED TO GO
;ANY FURTHER BECAUSE THERE IS NO CHANCE
;OF FINDING A 2 AFTER A 4
JRST D5 ;YES, WE MIGHT STILL FIND A 5, SO
;KEEP LOOKING
D7: LDB AT1,CRRQT2
CAIN AT1,1 ;QT(J) = 1 (SHARED)?
JRST D2 ;YES, NO NEED TO GO ANY FURTHER
;BECAUSE REQUEST(K) WILL CAUSE
;BLOCK TO BE QUEUED. JUMP
;OUT OF SUB-SUB-LOOP TO END OF SUB-LOOP
JRST D5
D4: LDB AT1,CRRQT2
CAIE AT1,2 ;QT(J) = 2 (EXCLUSIVE)?
JRST D2 ;NO, JUMP OUT OF SUB-SUB-LOOP TO END
;OF SUB-LOOP. NO NEED TO GO ON BECAUSE
;REQUEST(K) WILL CAUSE BLOCK TO BE
;QUEUED
D10: SETZ AT1, ;QUEUE THE BLOCK EXCLUSIVE, SINCE
;NO CHANCE OF FINDING A 2
D9: HRRZ AT2,1(ACRR2)
EXCH ACRR2,ACRR
PUSHJ PP,QUEUE
EXCH ACRR2,ACRR
JRST D2
D5: LDB AT1,CRRIN3
ADD ACRR3,AT1
SOJG K,D3
D8: LDB AT1,CRRQT2 ;QT(J) = SHARED?
CAIE AT1,1
JRST D10 ;NO, QUEUE BLOCK EXCLUSIVE
HRLZI AT1,1
JRST D9 ;YES, QUEUE BLOCK SHARED
D2: LDB AT1,CRRIN2 ;INCREMENT J
ADD ACRR2,AT1
SOJG J,D1
JRST C5
E1: CAMN ACRR,ACRR2 ;[455] I = J ?
JRST E2 ;[455] YES, GET NEXT J
HRRZ AT2,0(ACRR2) ;[455] NO
HRRZ AT1,0(ACRR) ;[455]
CAME AT1,AT2 ;[455] J SAME FILE AS I ?
JRST E2 ;[455] NO, GET NEXT J
MOVE ACRR3,SU.RRT ;[455] SET UP K FOR SUB-SUB-LOOP
SETZM SU.Y ;[455] SET TO -1 IF A PRIOR BLOCK HAS
;[455] ENQ'D SHARED ON A BLOCK
E9: CAME ACRR3,ACRR ;[455] K = I ?
CAMN ACRR3,ACRR2 ;[455] NO, K = J ?
JRST E5 ;[455] YES, GET NEXT K IN EITHER CASE
LDB AT1,CRRQT2 ;[455] NO, CHECK J'S QUEUING TECHNIQUE
CAIN AT1,1 ;[455] J SHARED?
JRST E3 ;[455] YES
CAIE AT1,2 ;[455] NO, J EXCLUSIVE?
JRST E2 ;[455] NO
CAMGE ACRR3,ACRR2 ;[455] YES, CHECKED ALL PRIOR TO J YET?
JRST E6 ;[455] NO, JUMP IF J IS EXCLUSIVE AND WE
;[455] DO NOT KNOW YET IF THERE IS A
;[455] PRIOR EXCLUSIVE
JRST E7 ;[455] YES, JUMP IF J IS EXCLUSIVE AND WE
;[455] KNOW THERE IS NO PRIOR EXCLUSIVE
E3: CAML ACRR3,SU.CRH ;[455] HAVE WE CHECKED ALL K'S?
JRST E8 ;[455] YES, JUMP IF J IS SHARED AND WE
;[455] HAVE CHECKED ALL PRIOR ENTRIES
E6: HRRZ AT2,0(ACRR2) ;[455]
HRRZ AT3,0(ACRR3) ;[455]
CAME AT2,AT3 ;[455] J AND K SAME FILE?
JRST E5 ;[455] NO, GET ANOTHER K
LDB AT2,CRRBK2
LDB AT1,CRRBK3 ;J AND K SAME DISK BLOCK?
CAME AT1,AT2
JRST E5 ;[455] NO, GET ANOTHER K
LDB AT3,CRRQT3 ;[455]
CAIN AT3,2 ;[455] K EXCLUSIVE?
JRST E2 ;[455] YES, GET ANOTHER J
CAIE AT3,1 ;[455] NO, K SHARED?
JRST E5 ;[455] NO, GET ANOTHER K
CAMGE ACRR3,ACRR2 ;[455] YES, IS K PRIOR TO J?
SETOM SU.Y ;[455] YES, SET PRIOR SHARED FLAG
E5: LDB AT3,CRRIN3 ;[455] GET NEXT K
ADD ACRR3,AT3 ;[455]
JRST E9 ;[455]
E8: SKIPE SU.Y ;[455] IF Y NOT 0, A PRIOR ENTRY HAS
;[455] ALREADY ENQ'D SHARED ON THIS BLOCK
JRST E2 ;[455] SO GET ANOTHER J
HRLZI AT1,1 ;[455] SET UP FOR SHARED ENQ
E10: LDB AT2,CRRBK2 ;[455] GET BLOCK NUMBER TO BE ENQ'D
PUSHJ PP,QUEUE ;[455] ADD TO ENQ TABLE
E2: LDB AT2,CRRIN2 ;[455] GET NEXT J
ADD ACRR2,AT2 ;[455]
SOJG J,E1 ;[455] CHECK ALL J'S
JRST C5 ;[455] FREE I AND GET ANOTHER I
E7: SETZ AT1, ;[455] SET UP FOR EXCLUSIVE ENQ
JRST E10 ;[455] ADD IT TO ENQ TABLE
C3: LDB AT1,CRRINE
ADD ACRR,AT1
SOJG I,C1
; OUR RESEARCH IS NOW COMPLETE. WE NEED ONLY FLUSH BUFFERS AND CALL ENQ/DEQ
MOVEI AT1,AT1
HRLM AT1,SU.FBT
C2: SOSGE AT1,SU.CFB ;ANY BUFFERS TO BE FLUSHED?
JRST C20 ;NO, GO ENQUEUE, ETC.
MOVE AP,@SU.FBT ;YES
PUSHJ PP,FORCW.
JRST C2
C20: SETZ AT1, ;FIRST WE ENQUEUE WHAT WE NEED
MOVEI AP,[0] ;[443] INSURE AP WILL CAUSE BLOCKING
PUSHJ PP,ENQDEQ
JRST SU.ERD
MOVEI AT1,2 ;THEN WE RELAX WHAT CAN BE RELAXED
PUSHJ PP,ENQDEQ
JRST SU.ERD
MOVEI AT1,1 ;AND FINALLY WE DEQUEUE WHAT WE DON'T
;NEED
PUSHJ PP,ENQDEQ
JRST SU.ERD
SKIPN SU.MRR ;IF NO MORE RETAINED RECORDS, THEN
;SET RR TO ZERO
SETZM SU.RR
HRLZI PP,-17(PP) ;RESTORE ALL REGISTERS
BLT PP,17
POPJ PP, ;RETURN TO THE (INTERNAL) CALLER
; FINAL CLEAN UP AND EXIT TO THE FREE STATEMENT
LRDEQC: RESTRM
IFN LSTATS,<
MOVE AT1,MRTDBP ;GET TRAILER BASE ADDRESS
MOVEI AT1,MB.FRT(AT1) ;ADD FREE TIME BUCKET OFFSET
MOVEM AT1,MRTMB. ;SAVE TIME BUCKET ADDRESS
MRTME. (AT1) ;END METER TIMING
>
HLRZ AT1,0(AP) ;DID USER SUPPLY A NOT RETAINED
;STATEMENT?
JUMPE AT1,RET.1 ;NO, RETURN TO FREE STATEMENT
MRHDCT (MB.FNR,AT1) ;COUNT FREE NOT RETAINED BUCKET
SKIPE SU.NR ;YES, ANY RECORD NOT RETAINED?
AOS 0(PP) ;YES, ADJUST RETURN ADDRESS
POPJ PP, ;RETURN TO FREE STATEMENT
; LFENQ: LIBOL FILE ENQUEUE
;
;
; THIS PROCEDURE IS CALLED ONCE BY THE COBOL OBJECT PROGRAM FOR
; THE EXECUTION OF EACH OPEN STATEMENT THAT CONTAINS SIMULTANEOUS
; UPDATE PARAMETERS.
;
;
; LFENQ EXPECTS TO FIND IN AC16 THE ADDRESS OF AN
; ARGUMENT LIST, STRUCTURED AS FOLLOWS:
;
; WORD 1: RH = NUMBER OF FILES TO BE OPENED FOR
; SIMULTANEOUS UPDATE
; LH = 0 => USER DID NOT SUPPLY AN UNAVAILABLE
; STATEMENT
; LH = 1 => USER SUPPLIED AN UNAVAILABLE STATEMENT
;
;
; NOTE: IF THE USER SUPPLIED AN UNAVAILABLE
; STATEMENT, THIS PROCEDURE RETURNS TO 1(PP)
; IF THE FILE(S) ARE AVAILABLE UNDER THE
; CONDITIONS SPECIFIED, AND RETURNS TO 0(PP)
; IF THEY ARE NOT. THIS IS EXACTLY THE
; OPPOSITE OF THE CONVENTION USED BY LRENQ
; AND LRDEQ (TO SEE WHY, TAKE A LOOK AT THE
; CODE GENERATED BY OPEN, RETAIN, AND FREE).
;
;
; WORDS 2 - N + 1:
; BITS 0 - 8: 143
; BIT 9: SET IF FILE IS BEING OPENED FOR REWRITE
; BIT 10: FOR WRITE
; BIT 11: FOR DELETE
; BIT 12: SET IF OTHERS ARE ALLOWED TO READ
; BIT 13: OTHERS ARE ALLOWED TO REWRITE
; BIT 14: OTHERS ARE ALLOWED TO WRITE
; BIT 15: OTHERS ARE ALLOWED TO DELETE
;
; NOTE: IT IS ALWAYS ASSUMED THAT THE FILE IS
; BEING OPENED FOR READ.
;
; BITS 16 - 17: UNUSED
; RH = FILE TABLE LOCATION
LFENQ.: SAVE
SKIPE SU.FR ;ARE ANY FILES CURRENTLY OPEN FOR
;SIMULTANEOUS UPDATE?
JRST SU.ER9 ;YES, JUMP
HRRZ I,0(AP)
MOVEM I,SU.FR ;SET SU.FR TO COUNT OF FILES BEING
;OPENED FOR SIMULTANEOUS UPDATE, AND
;LEAVE COUNT IN I
SETZM SU.EQ ;SET THE NUMBER OF ENTRIES IN THE
;ENQUEUE TABLE TO ZERO (LFENQ WILL NOT
;USE THE DEQUEUE TABLE OR THE
;MODIFY TABLE).
MOVEI AUFS,1(AP) ;POINT AUFS TO THE FIRST USER FILE
;SPECIFICATION
LFENQ1: MRTMS. (AT4) ;START METER TIMING
LDB AT4,UFSCON ;MAKE A LITTLE VALIDITY CHECK
CAIE AT4,143
JRST SU.ER2
LDB AT4,UFSFLG ;GET FLAGS FROM USER SPEC
TRO AT4,000200 ;SET FOR READ BIT
HRRZ AFT,0(AUFS)
DPB AT4,FTOTA ;SET OTHERS ACCESS IN FILE TABLE
ROT AT4,-4
DPB AT4,FTOWA ;SET OWN ACCESS IN FILE TABLE
HRLI AT4,600 ;GENERATE FAKE PARAMETER TO CBLIO
;OPEN ROUTINE IN FET1
HRR AT4,0(AUFS)
MOVEM AT4,FET1
MOVEM AUFS,FET2 ;SAVE OUR REGISTERS
MOVEM AP,FET3
MOVEM I,FET4
RESTRM ;RESTORE LIBOL REGISTERS
MOVE AP,FET1
PUSHJ PP,C.OPEN ;OPEN THE FILE
SETO I, ;[565] GET ONES
DPB I,LFQOPN ;[565] SET OPENED FROM LFENQ. BIT
MOVE AUFS,FET2 ;RESTORE OUR REGS
MOVE AP,FET3
MOVE I,FET4
HRRZ AFT,0(AUFS)
LDB AT4,FTAM
CAIE AT4,INDEXD
JRST PPF1
HLRZ AT4,D.BL(AFT)
SETOM NXTREC(AT4) ;INITIALIZE NXTREC TO -1 SO THAT
;AN INITIAL RETAIN WILL SAVE
;CORRECT POSITION
PPF1: LDB AT4,FTOWA
LDB AT5,UFSFLG
; AT4 NOW CONTAINS OWN ACCESS BITS FOR READ, REWRITE, WRITE, AND
; DELETE IN THE RIGHT HAND FOUR BITS AND AT5 THE SAME FOR OTHERS.
;
; WE'LL NOW CONSIDER THESE FOUR PAIRS OF BITS AND DETERMINE
; WHICH QUEUES THE USER SHOULD BE QUEUED ON, AND HOW.
; HE QUEUES SHARED ON THE QUEUE (E.G. READ) IF HE WANTS TO
; EXECUTE THE CORRESPONDING VERB WHILE ALLOWING OTHERS TO DO
; THE SAME, EXCLUSIVE IF HE WANTS TO EXECUTE THE CORRESPONDING
; VERB EXCLUSIVELY, GROUP 1 SHARED IF HE DOESN'T WANT TO EXECUTE
; THE CORRESPONDING VERB BUT ALSO WANTS NOONE ELSE TO, AND
; NO QUEUEING AT ALL IF HE WILL NOT EXECUTE THE VERB AND DOESN'T
; CARE WHAT OTHERS WILL DO. WE'LL DO THIS BY CALLING FED, THEN ENQDEQ.
HRRZ ACRR,AUFS ;SET ACRR SUCH THAT 0(ACRR) POINTS TO THE
;FILE TABLE
PUSHJ PP,FED ;CALL FILE ENQUEUE/DEQUEUE ROUTINE
AOS AUFS ;POINT TO THE NEXT USER FILE SPEC,
;IF ANY, AND LOOP BACK
MRTME. (AT1) ;END METER TIMING
SOJG I,LFENQ1 ;CALL ENQDEQ TO DO THE ACTUAL QUEUEING,
;IF ANY
RESTRM
SETZ AT1,
PUSHJ PP,ENQDEQ
JRST G1 ;JUMP IF SOME PROBLEM OR RESOURCES NOT
;AVAILABLE
HLLZ AT1,0(AP) ;EVERYTHING'S OK
JUMPN AT1,RET.2 ;IF UNAVAILABLE STATEMENT SUPPLIED,
;ADJUST RETURN
POPJ PP,
G1: SETZM SU.FR ; [434] CLEAR COUNT OF # OF SIMULTANEOUS FILES
HRRZ I,0(AP) ;CLOSE ALL THE FILES
MOVEI AUFS,1(AP)
CL: HRLI AT4,40 ;GENERATE FAKE PARAMETER TO CBLIO
;CLOSE ROUTINE IN FET1
HRR AT4,0(AUFS)
MOVEM AT4,FET1
MOVEM AUFS,FET2
MOVEM AP,FET3 ;SAVE OUR REGISTERS
MOVEM I,FET4
RESTRM ;RESTORE LIBOL REGISTERS
MOVE AP,FET1
PUSHJ PP,C.CLOS ;CLOSE THE FILE
MOVE AUFS,FET2
MOVE AP,FET3
MOVE I,FET4 ;RESTORE OUR REGISTERS
AOS AUFS ;POINT TO THE NEXT FILE,
;IF ANY, AND LOOP BACK
SOJG I,CL
HLLZ AT1,0(AP)
JUMPE AT1,SU.ER7
POPJ PP, ;RETURN IF UNAVAILABLE STATEMENT
;SUPPLIED
; SU.RD, SU.RW, SU.WR, SU.DL, AND SU.CL: ROUTINES CALLED WHEN
; CBLIO DISCOVERS A FILE IS OPENED FOR SIMULTANEOUS UPDATE
; DURING THE EXECUTION OF A READ, REWRITE, WRITE, DELETE,
; OR CLOSE STATEMENT.
;
;
;
; UPON ENTRY, AC16 CONTAINS A FILE TABLE POINTER.
;
; IF THE OPERATION ATTEMPTED BY THE USER IS ACCORDING TO THE
; RULES OF SIMULTANEOUS UPDATE, CONTROL IS RETURNED TO
; 0(PP).
;
; IF THE OPERATION ATTEMPTED BY THE USER IS NOT ACCORDING TO
; THE RULES OF SIMULTANEOUS UPDATE, A MESSAGE IS PRINTED AND THE USER IS KILLED.
INTERN SU.RD, SU.RW, SU.WR, SU.DL, SU.CL
SU.RD: MOVEI AT5,10 ;SET READ BIT IN AT5 AND JUMP TO
;COMMON CODE
JRST M1
SU.RW: MOVEI AT5,4 ;LIKEWISE, REWRITE BIT
JRST M1
SU.WR: MOVEI AT5,2 ;LIKEWISE, WRITE BIT
JRST M1
SU.DL: MOVEI AT5,1 ;LIKEWISE, DELETE BIT
M1: MOVEM AT5,SU.VRB ;SAVE VERB INDICATOR IN SU.VRB
SETZM SU.Y ;INDICATE NO RETAIN "NEXT" YET SEEN
SAVE
MOVE AT5,SU.VRB
MOVE AFT,AP ;INITIALIZE KEY FOR SEARCHING TABLE OF
;RETAINED RECORDS
LDB AT1,FTAM
CAIN AT1,INDEXD
JRST M3 ;JUMP IF FILE INDEXED
CAIE AT1,RANDOM
JRST M4
HRRZ AT2,F.RACK(AFT)
SETOM SU.Y ;INDICATE RANDOM,RETAIN NEXT INTERESTING
IFN ANS68,<
SKIPE AT3,0(AT2)
JRST M5 ;JUMP IF FILE RANDOM WITH NON-ZERO KEY
>;END IFN ANS68
IFN ANS74,<
MOVE AT3,0(AT2) ;GET KEY VALUE
LDB AT4,F.BFAM ;GET ACCESS MODE
JUMPE AT4,M1A ;SKIP AHEAD IF SEQ ACCESS
TLNN AP,200 ;READ "NEXT RECORD"?
JRST M5 ;NO--GO STORE KEY VALUE
M1A:>;END IFN ANS74
M4: MOVNS SU.Y ;MAKE FLAG POSITIVE,INDICATING "NEXT" I/O
MOVE AT3,D.RP(AFT) ;FILE IS EITHER SEQUENTIAL OR RANDOM
;WITH KEY OF ZERO
IFN ANS68,<
TRNN AT5,2 ;WRITE ONLY
>
IFN ANS74,<
TRNN AT5,4 ;REWRITE ONLY?
>
JRST M6 ;JUMP IF VERB ANYTHING BUT (RE )WRITE
HLRZ AT2,D.BL(AFT)
SETO AT4,
CAMN AT4,LASTUU(AT2) ;SKIP IF LAST VERB A READ
M6: ADDI AT3,1
JRST M5
M3:
IFN ANS74,<
TLNN AP,200 ;READ NEXT?
JRST M333 ;NO, SKIP THIS
>;END IFN ANS74
PUSHJ PP,CLVACI ;CHECK FOR LOW-VALUES AND CONVERT,
;IF NECESSARY
JRST M8
M333: SETO AT4,
HRRM AT4,F.WSMU(AFT) ;INITIALIZE POINTER TO SAVED KEY TO
;NULL, SINCE WE WON'T HAVE TO RESTORE
;OUR PREVIOUS POSITION IN THE FILE
MOVSI ACRR2,(JFCL) ;[447] SET UP PHONY CONV INSTR.
MOVE AT3,F.WBSK(AFT) ;WE'RE JUST ABOUT READY FOR LOOP
JRST M5
M8:
IFN ANS74,<
SKIPE SU.HV ;FOUND EOF?
JRST CHK7EF ;YES, CHECK FOR AN ENTRY LIKE THAT
>;END IFN ANS74
MOVE ACRR2,D.RCNV(AFT) ;[447] USE REAL CONV INSTR.
PUSHJ PP,CHGCNV ;[447] CHECK FOR PHONY CONV INSTRS.
MOVE AT3,SU.RBP ;[447]
M5: SETZM SU.T1 ;NO RETAIN NEXT SEEN YET
MOVEM AT3,SU.CK ;SAVE COMPARISON KEY IN SU.CK
MOVE ACRR,SU.RRT ;INITIALIZE ACRR FOR LOOP TO
;SEARCH THE RETAINED RECORDS TABLE
;FOR THIS RECORD
M7: CAMGE ACRR,SU.CRH ;END OF LOOP?
JRST M7A ;NO, CONT AT NEXT ENTRY
SKIPN ACRR,SU.T1 ;RETAIN "NEXT" ENTRY SEEN?
JRST SU.ERB ;ERROR,NO RETAIN TO COVER THIS RECORD
SKIPL SU.Y ;RANDOM WITH KEY?
JRST M10 ;NO,RETAIN NEXT VALID FOR "KEY 0" TYPE I/O
MOVE AT4,@F.RACK(AP) ;GET ACTUAL KEY
MOVE AT3,D.RP(AP) ;GET CURRENT REC NUMBER
CAIN AT3,AT4 ;RETAINED NEXT=CURRENT NEXT?
JRST M10 ;YES,GOT PROPER RETAIN
JRST SU.ERB ;NO, JUMP TO ERROR, SINCE WE SHOULD
;HAVE FOUND AN ENTRY FOR THIS RECORD
M7A: HRRZ AFT,0(ACRR)
HRRZ AT1,AP
CAME AFT,AT1 ;SAME FILE?
JRST M2 ;IF NOT, JUMP TO NEXT ENTRY IN LOOP
LDB AT4,FTAM
CAIN AT4,INDEXD
JRST M9 ;JUMP IF FILE INDEXED
CAMN AT3,2(ACRR)
JRST M10 ;JUMP IF KEYS MATCH - WE FOUND IT!
SKIPN SU.Y ;SKIP IF "RETAIN NEXT" INTERESTING
JRST M2 ;NO, CONT
IFN ANS74,<
LDB AT4,RRTNXT ;GET RETAIN NEXT FLAG
JUMPE AT4,M2 ;NOT RETAIN NEXT,CONT
>
IFN ANS68,<
SKIPN 2(ACRR) ; ZERO KEY RETAIN ? (SKIP IF NOT)
>
MOVEM ACRR,SU.T1 ;IT IS, SAVE RRT ENTRY ADDRESS
M2: LDB AT4,CRRINE
ADD ACRR,AT4
JRST M7
M9: HLRZ AT4,D.BL(AP) ;[524] POINT TO FILE TABLE
LDB AT4,FTKT ;[524] CHECK FOR NON-DISPLAY KEY TYPES
CAIGE AT4,3 ;[524] DISPLAY?
JRST M9DISP ;[524] YES
CAIL AT4,7 ;[524] COMP-3?
JRST M9DISP ;[524] YES TREAT AS DISPLAY
;[524] KEY IS NOT DISPLAY COMPARE ONE OR TWO WORDS
HRRI AT1,2(ACRR) ;[524] AT1 POINTS TO 1 OF THE RETAINED KEYS
MOVE AT5,(AT1) ;[524] GET 1ST WORD OF RETAINED KEY
CAME AT5,(AT3) ;[524] IS IT THE ONE HE WANTS TO READ?
JRST M12 ;[524] NO GO GET THE NEXT ONE
TRNE AT4,1 ;[524] SKIP IF KEYS ARE 2 WORDS
JRST M10 ;[524] ONE WORD, AND THEY MATCH!
MOVE AT5,1(AT1) ;[524] GET SECOND WORD OF KEY
CAME AT5,1(AT3) ;[524] COMPARE 2ND WORD ALSO
JRST M12 ;[524] NO MATCH
JRST M10 ;[524] MATCH!
M9DISP: LDB AT4,FTRM ;[447] GET INCORE RECORD MODE
MOVE AT4,[OCT 441000000000,440600000000,0,440700000000]-1(AT4) ;[447]
;[447]GET BYTE POS + SIZE BASED ON MODE
HRRI AT4,2(ACRR)
LDB AT1,FTKLB ;[447] USE AT1 FOR LOOP AND AT5 FOR
;[447] ILDB SO CONV INSTR WORKS
SKIPE SU.HV ;[447] FORCED HIGH VALUES BEING USED?
JRST M14 ;[447] YES
M11: ILDB AT5,AT3 ;[447]
XCT ACRR2 ;[447] CONVERT IF NECESSARY
ILDB AT2,AT4
CAME AT5,AT2 ;[447]
JRST M12 ;JUMP IF KEYS NOT EQUAL
SOJG AT1,M11 ;[447]
JRST M10 ;WE'VE FOUND IT!
M12: MOVE AT3,SU.CK
JRST M2
IFN ANS74,<
;LOOP THRU RRT AND MATCH IF WE HAVE A "NEXT RECORD" ENTRY THAT FOUND EOF
CHK7EF: MOVE ACRR,SU.RRT
CHK7F1: CAML ACRR,SU.CRH ;END OF LOOP?
JRST SU.ERB ;YES, ERROR IF NOT FOUND YET
HRRZ AFT,0(ACRR) ;GET FILE
HRRZ AT1,AP
CAME AFT,AT1 ;SAME FILE?
JRST CHK7F2 ;NO, GO ON TO NEXT ENTRY
LDB AT1,RRTHVF ;FOUND EOF IN A "NEXT RECORD" ENTRY?
JUMPN AT1,M10 ;IF YES, MATCH!
CHK7F2: LDB AT4,CRRINE
ADD ACRR,AT4
JRST CHK7F1 ;LOOP
>;END IFN ANS74
M14: LDB AT5,AT3 ;[447] GET THE HIGH VALUES CHAR
ILDB AT2,AT4 ;[447] RRT CHAR
CAME AT5,AT2 ;[447] SAME?
JRST M12 ;[447] NO
SOJG AT1,M14+1 ;[447] YES--CHECK NEXT ONE
M10: LDB AT4,CRRFG4 ;GET VERB FLAGS
SETZM SU.HV ;[447] TURN OFF HIGH VALUES SWITCH
SETCA AT4,
MOVE AT5,SU.VRB
TRNE AT5,0(AT4)
JRST SU.ERC ;JUMP IF FUNCTION NOT RETAINED FOR
LDB AT1,CRRFLG
TRNE AT1,000002
JRST M13 ;JUMP IF UNTIL FREED FLAG SET
TRNN AT4,000017
JRST M13 ;JUMP IF RETAIN FOR ANY VERB
LSH AT1,-2
TRZ AT1,0(AT5) ;ZERO VERB BIT
DPB AT1,CRRFG4
JUMPN AT1,M13 ;JUMP IF NOT ALL VERB BITS ZERO
SETO AT1,
DPB AT1,CRRF ;SET FREE FLAG FOR THIS RECORD
; CBLIO WILL ACTUALLY FREE THE RECORD WE HAVE JUST MARKED
; AFTER EXECUTION OF THE VERB BEING EXECUTED.
M13: RESTRM
POPJ PP, ;NORMAL RETURN TO CBLIO
SU.CL: SKIPN SU.FR ; [434] ANY SIMULTANEOUS FILES OPEN?
POPJ PP, ; [434] NO EXIT
MOVEI AT1,12 ; TELL THE QUEUE ROUTINE THIS IS A
MOVEM AT1,SU.VRB ; CLOSE VERB SO LONG TERM LOCK GETS
; TURNED OFF
MOVEI AT1,1 ;SET UP DUMMY CALL TO LRDEQ,
;REQUESTING THAT ALL THE RECORDS IN THE
;FILE BEING CLOSED BE FREED. SAVE AC12
;AND AC16 FOR CBLIO.
MOVEM AT1,SU.CL1
MOVEI AT1,152200
HRLM AT1,SU.CL2
MOVEM AP,SU.CLR
HRRM AP,SU.CL2
MOVEI AP,SU.CL1
MOVEM 12,SU.CLS
PUSHJ PP,LRDEQ.
MOVE AFT,SU.CLR ;SET AFT TO FILE TABLE POINTER
LDB AT4,FTOWA ;SET AT4 TO OWN ACCESS BITS
LDB AT5,FTOTA ;SET AT5 TO OTHERS ACCESS BITS
MOVEI ACRR,SU.CL2 ;SET ACRR SO THAT 0(ACRR) POINTS TO FILE TABLE
SETZM SU.DQ ;ZERO COUNT OF ITEMS DEQUEUED
HRLI ACRR,1 ;SET LH OF ACRR TO INDICATE DEQUEUE
PUSHJ PP,FED ;PREPARE ENQ/DEQ REQUEST BY CALLING FED
MOVEI AT1,1
MOVEI AP,SU.CL1 ;SET AP SO THAT 0(AP) = 0
SETZM SU.CL1
PUSHJ PP,ENQDEQ ;CALL ENQ/DEQ TO ACTUALLY TO DEQUEUE
JRST SU.ER7
MOVE 12,SU.CLS
MOVE AP,SU.CLR
SETZM F.WSMU(AP) ;ZERO SU WORD IN THE FILE TABLE
SOS SU.FR ;SUBTRACT ONE FROM THE COUNT OF FILES
;OPEN FOR SIMULTANEOUS UPDATE
POPJ PP,
; MOVKEY: A SUBROUTINE THAT MOVES A KEY INTO THE CURRENT RETAINED
; RECORDS TABLE ENTRY
;
;
; ARGUMENTS:
;
; 1: A BYTE POINTER TO THE KEY TO BE MOVED IN AT1
; 2: LENGTH OF THE KEY IN BYTES IN AT2
; 3: POINTER TO A RETAINED RECORDS TABLE ENTRY IN ACRR
; 4: POINTER TO FILE TABLE IN AFT
;
; CHANGES:
;
; AT2
; AT3
; AT4
; AT5
; SU.T4
; SU.HV
MOVKEY: LDB AT3,FTRM ;BUILD BYTE POINTER TO KEY IN RETAINED
;RECORDS TABLE IN AT3
MOVE AT3,[OCT 441000000000,440600000000,0,440700000000]-1(AT3)
;DERIVE BYTE SIZE FROM RECORDING MODE
HRRI AT3,2(ACRR) ;SET ADDRESS FIELD
MOVEM AT1,SU.T4 ;FREE UP AT1
SKIPE SU.HV ;[447] FORCED HIGH VALUES READ
JRST HVLOOP ;[447] YES
MOVE AT4,D.RCNV(AFT) ;[447] NO--DO REAL CONV
MKLOOP: ILDB AT5,SU.T4 ;[447] MOVE BYTES
XCT AT4 ;[447] CONV IF NECESSARY
IDPB AT5,AT3 ;[447]
SOJG AT2,MKLOOP
POPJ PP, ;RETURN
HVLOOP: LDB AT5,SU.T4 ;[447] GET A HIGH VALUES CHAR
IDPB AT5,AT3 ;[447] PUT IT IN RRT
SOJG AT2,.-1 ;[447] DO EM ALL
SETZM SU.HV ;[447] TURN OFF HIGH VALUES FLAG
POPJ PP, ;[447] RETURN
USRKEY: LDB AT3,FTRM ;[447]
MOVE AT3,[OCT 441000000000,440600000000,0,440700000000]-1(AT3) ;[447]
HRRI AT3,2(ACRR) ;[447]
MOVEM AT1,SU.T4 ;[447]
USLOOP: ILDB AT1,SU.T4 ;[447]
IDPB AT1,AT3 ;[447]
SOJG AT2,USLOOP ;[447]
POPJ PP, ;[447]
; QUEUE: A SUBROUTINE THAT CREATES AN ENTRY IN THE ENQUEUE,
; DEQUEUE, OR MODIFY ACCESS TABLE (THESE TABLES ARE IN THE
; FORMAT OF THE ENQ/DEQ PARAMETER LIST).
;
;
; ARGUMENTS:
;
; 1: ACRR POINTS TO THE APPROPRIATE ENTRY IN THE RETAINED
; RECORDS TABLE. BUT USE OF ACRR BY THIS ROUTINE
; IS RESTRICTED TO GETTING THE FILE TABLE LOCATION
; FROM 0(ACRR).
;
; 2: AT1 LH = 0 => EXCLUSIVE
; = 1 => SHARED
; = 3 => GROUP SHARED
;
; RH = 0 => ENQUEUE
; = 1 => DEQUEUE
; = 2 => MODIFY ACCESS
;
; 3: AT2 CONTAINS A 33 BIT USER CODE
;
; CHANGES:
;
; AT1
; AT2
; AT3
; AFT
; QUEUE TABLES: SU.EQT, SU.DQT, SU.MQT
; QUEUE TABLE COUNTERS: SU.EQ, SU.DQ, SU.MQ
;
; QUEUE FIRST CHECKS FOR INDEX QUEUEING, IN WHICH CASE
; A RECORD IS KEPT OF SHARED/EXCLUSIVE MODE UPON ENQUEUE.
; THIS IS LATER USED TO ENSURE THAT DEQUEUE USES THE SAME
; MODE. (ONLY THE 10 NOW (2/79) WORRIES ABOUT THIS)
;
;
QUEUE: HRRZ AFT,0(ACRR) ;GET POINTER TO THE FILE TABLE
AOJN AT2,QUEUX ;SKIP AHEAD IF NOT INDEX QUEUE (AT2 NOT -1)
HRRZ AT3,AT1 ;GET ENQDEQ INDICATER
SOJGE AT3,QUEUA ;SKIP AHEAD IF NOT ENQUEUE REQUEST
HLRZ AT3,AT1 ;GET EXCL/SHARD MARK
DPB AT3,IDXSHR ;SAVE FLAG IN FILTAB F.WSMU WORD
JRST QUEUX ; CONT
QUEUA: SOJGE AT3,QUEUX ;SKIP ALL IF MODIFY
LDB AT3,IDXSHR ;GET FILTAB INDEX ENQ SHARE FLAG
HRL AT1,AT3 ;RESET DEQUEUE MODE TO MATCH ENQUEUE
QUEUX: SOJ AT2, ;RESTORE AT2
MOVE AT3,@[OCT SU.EQ,SU.DQ,SU.MQ](AT1)
LSH AT3,1
ADD AT3,@[OCT SU.EQ,SU.DQ,SU.MQ](AT1)
ADD AT3,@[OCT SU.EQT,SU.DQT,SU.MQT](AT1)
ADDI AT3,2
; AT3 NOW POINTS TO WHERE WE SHOULD GENERATE THE ENQ/DEQ REQUEST
; ENTRY
AOS @[OCT SU.EQ,SU.DQ,SU.MQ](AT1) ;INCREMENT COUNT
SETZM 2(AT3) ;INDICATE WE ARE REFERING TO A
;NON-POOLED RESOURCE
TLZ AT2,700000 ;JAM 5 IN AT2 TO INDICATE 33 BIT USER
;CODE OPTION
TLO AT2,500000
MOVEM AT2,1(AT3) ;STORE AWAY
LDB AT2,FTCN ;GET CHANNEL NUMBER
HLRZ AT1,AT1
ROT AT1,-1 ;GET SHARED/EXCLUSIVE BIT IN BIT 0
HLL AT2,AT1 ;COMBINE WITH CHANNEL
TLO AT2,200000 ;TURN OFF LEVEL CHECKING
PUSH PP,AT1 ;SAVE AT1
MOVEI AT1,12 ;CHECK FOR CLOSE VERB
CAMN AT1,SU.VRB ;IF IT IS, DO NOT SET LONG TERM LOCK
JRST QUEUE1 ;IT IS
HRLOI AT1,577777 ;NOT CLOSE, BUT IS IT AN INDEX OR
;RANDOM FILE RESOURCE?
CAMN AT1,1(AT3) ;IF IT IS EITHER, SET LONG TERM LOCK
IFN TOPS20,< ; [643]
TLO AT2,(EN%LTL) ; [643] IT IS ONE OF THEM
> ; [643]
IFE TOPS20,< ; [643]
TLO AT2,(EQ.FLT) ; [643] IT IS ONE OF THEM
> ; [643]
QUEUE1: POP PP,AT1 ;RESTORE AT1
MOVEM AT2,0(AT3) ;STORE
HRRM AT1,2(AT3) ;SET SHARE GROUP
POPJ PP, ;RETURN
; ENQDEQ: A SUBROUTINE TO ACTUALLY CALL ENQ/DEQ
;
; ARGUMENTS:
;
; 1: AT1: RH = 0 => ENQUEUE
; = 1 => DEQUEUE
; = 2 => MODIFY ACCESS
;
; 2: AP POINTS TO A LOCATION INTERPRETED AS FOLLOWS:
;
; LH = 0 => BLOCK
;
; LH = 1 => RETURN
;
;
; RETURNS:
; TO 0(PP) IF RESOURCES NOT AVAILABLE
; TO 1(PP) IF EVERYTHING'S OK
;
; CHANGES:
;
; AT1
; AT2
; AT3
;
; USES:
;
; QUEUE TABLES: SU.EQU, SU.DQT, SU.MQT
; QUEUE TABLE COUNTERS: SU.EQ, SU.DQ, SU.MQ
;
;
; REINITIALIZES:
;
; SU.EQ
; SU.DQ
; SU.MQ (APPROPRIATE ONE TO ZERO)
;
ENQDEQ: AOS 0(PP) ;SET NORMAL RETURN
SKIPN AT2,@[OCT SU.EQ,SU.DQ,SU.MQ](AT1)
POPJ PP, ;RETURN NORMAL IF NO ENTRIES IN TABLE
MOVE AT3,@[OCT SU.EQT,SU.DQT,SU.MQT](AT1)
SETZM 1(AT3) ;ZERO REQUEST ID AND RESERVED FIELDS
;OF ENQ/DEQ REQUEST
LSH AT2,1
ADD AT2,@[OCT SU.EQ,SU.DQ,SU.MQ](AT1)
ADDI AT2,2 ;COMPUTE LENGTH OF REQUEST BLOCK
HRL AT2,@[OCT SU.EQ,SU.DQ,SU.MQ](AT1)
;MOVE IN NUMBER OF ENTRIES
MOVEM AT2,0(AT3) ;STORE AT HEAD OF REQUEST LIST
SETZ AT3, ;ZERO AT3 TO INDICATE ENQ
CAIN AT1,2
JRST ED1 ;JUMP IF MODIFY ACCESS REQUEST
JUMPN AT1,ED2 ;JUMP IF DEQUEUE REQUEST
HLL AT2,0(AP) ;SET BLOCK OR RETURN FOR ENQ, BASED
;ON WHETHER USER SUPPLIED RETURN
ED3: HRR AT2,@[OCT SU.EQT,SU.DQT,SU.MQT](AT1)
TRNA
PUSHJ PP,PRINT ;IF DEBUGGING SWITCH SET, SEND
;ENQ/DEQ PARAMETERS TO TTY
CALLI AT2,151(AT3) ;CALL ENQ OR DEQ DEPENDING ON SETTING
;OF AT3
JRST ED4 ;ERROR RETURN FROM ENQ/DEQ
POPJ PP, ;NORMAL RETURN FROM ENQ/DEQ -
;RETURN NORMAL TO OUR CALLER
ED1: HRLI AT2,3
JRST ED3
ED2: HRLI AT2,0 ;SET DEQ FUNCTION TO NORMAL DEQ
MOVEI AT3,1 ;SET AT3 TO 1 TO INDICATE DEQ
JRST ED3
PRINT: PUSH PP,AT4 ;SAVE AT4
HRRZ AT4,0(AT2) ;MOVE COUNT OF WORDS TO BE PRINTED
;TO AT4
PUSH PP,ACRR ;SAVE ACRR
PUSH PP,ACRR2 ;SAVE ACRR2
PUSH PP,ACRR3 ;SAVE ACRR3
MOVE ACRR,[POINT 3,0(AT2)]
;SET UP BYTE POINTER IN ACRR
PRINT2: MOVEI ACRR3,14 ;SET COUNT OF OCTITS IN A WORD IN ACRR3
PRINT1: ILDB ACRR2,ACRR ;GET NEXT OCTIT TO BE PRINTED
ADDI ACRR2,"0" ;CONVERT TO ASCII
OUTCHR ACRR2 ;PRINT THE OCTIT
SOJG ACRR3,PRINT1 ;END OF WORD? IF NOT, JUMP
MOVEI ACRR2,015
OUTCHR ACRR2 ;PRINT CARRIAGE RETURN
MOVEI ACRR2,012
OUTCHR ACRR2 ;PRINT LINE FEED
SOJG AT4,PRINT2 ;END OF WORDS TO BE TYPED?
POP PP,ACRR3 ;RESTORE REGISTERS
POP PP,ACRR2
POP PP,ACRR
POP PP,AT4
POPJ PP, ;RETURN
ED4: SOS 0(PP) ;SET OUR ABNORMAL RETURN
CAIN AT2,13
JRST SU.ERE ;INSUFFICIENT CORE
CAIN AT2,21
JRST SU.ERF ;QUOTA EXCEEDED
CAIE AT2,1
JRST SU.ER7 ;SOME CRAZY INTERNAL ERROR
POPJ PP, ;RESOURCES NOT AVAILABLE
; BLKNUM: A SUBROUTINE TO DETERMINE WHICH BLOCK NEEDS TO BE
; ENQUEUED OR DEQUEUED
;
; ARGUMENTS:
;
; 1: ACRR POINTS TO THE APPROPRIATE ENTRY IN THE
; RETAINED RECORDS TABLE. THIS SUBROUTINE GETS WHAT
; IT NEEDS FROM THAT ENTRY, AND SETS THE BLOCK NUMBER
; FIELD IN THAT SAME ENTRY.
;
;
; CHANGES:
;
; ALL REGISTERS EXCEPT AP, ACRR, AND PP
; SU.T1 F.WSMU(AFT)
; SU.T2 FS.BN
; SU.T3 SU.RLV
; SU.Y SU.SVK
; SU.RBP
BLKNUM: HRRZ AFT,0(ACRR)
LDB AT1,FTAM
CAIN AT1,INDEXD
JRST BN1 ;JUMP IF FILE INDEXED
CAIN AT1,RANDOM ;[455]
JRST BN1A
BN0A: MOVE AT1,2(ACRR) ;[456] BLOCK NUMBER =
;KEY + BLOCKING FACTOR - 1 ALL DIVIDED
;BY BLOCKING FACTOR
LDB AT2,FTBF ;[456]
SOSN AT1 ;[456]
TDZA AT2,AT2 ;[456]
IDIV AT1,AT2 ;[456]
IMUL AT1,D.BPL(AFT) ;[456]
ADDI AT1,1 ;[456]
BN5: DPB AT1,CRRBLK
IFN ANS74 ,<
LDB AT1,CRRFG4 ; GET RETAIN VERB FLAGS
TRNn AT1,RTDLRW ; DELETE OR REWRITE RETAIN?
JRST BN5C ; No, check to see if RETAIN save needed
; Clear CNTRY and NNTRY so that next sequential operation will get
; saved position
HLRZ AT1,D.BL(AFT) ; Get buffer position
SETZM CNTRY(AT1) ; Clear current position
SETZM NNTRY(AT1) ; And next position flag
POPJ PP, ; And return
; Other operations have reestablished next record pos for purposes
; of the RETAIN. If not already done, save RWDLKY from I-O level.
BN5C: HLRZ AT1,D.BL(AFT) ; Get buffer position
HRRZ AT2,D.RFLG(AFT) ; Get extra flags
SKIPE SVNXRT(AT1) ; Is current SAVNXT been saved?
JRST BN5A ; Yes, no need to save it again
HRROM AT2,SVNXRT(AT1) ; Save them during retain
; Set left -1 incase no D.RFLG bits set
PUSH PP,AT2 ; And save them for later
HRRZ AT2,RWDLRT(AT1) ; Get retain save area address
MOVE AT3,RWDLKY(AT1) ; Get i-o level NNTRY and save area addr
MOVEM AT2,RWDLKY(AT1) ; Indicate that SAVNXT should use RETAIN's area
MOVEM AT3,RWDLRT(AT1) ; Save I-O level NNTRY and save area addr
; Copy I-O save area to RETAIN area, RWDLRT area is same size as and
; immediatly follows RWDLKY area
HRL AT2,AT3 ; Source addr from I-O save area
HRRZ AT1,AT2 ; Last-word-to-move+1=2*at2-at3
LSH AT1,1 ; At2*2
SUBI AT1,(AT3) ; At2*2-at3
BLT AT2,-1(AT1) ; Copy current saved next record keys
POP PP,AT2 ; Restore D.RFLG
BN5A: TRZN AT2,SAVNXT ; Next rec pos saved?
POPJ PP, ; No, return
HRRM AT2,D.RFLG(AFT) ; Yes reset it off
>; END IFN ANS74
POPJ PP, ; and return
BN1A:
IFN ANS68,<
SKIPN 2(ACRR) ;IF FILE IS RANDOM AND KEY IS 0,
POPJ PP, ;DO NOTHING
>
IFN ANS74,<
LDB AT1,RRTNXT ;RETAIN NEXT?
SKIPE AT1
POPJ PP, ;YES, DO NOTHING
>;END IFN ANS74
JRST BN0A
BN1: MOVEM ACRR,SU.T1 ;GET READY TO CALL CBLIO
MOVEM AP,SU.T2 ;SAVE ACRR, AP IN TEMPORARY
SETZM SU.Y ;SET SU.Y TO 0 TO INDICATE THIS IS NOT
;THE FIRST RECORD RETAINED FOR THIS FILE
;BY THIS RETAIN STATEMENT
IFN ANS74,<
LDB AT1,CRRFG4 ; GET RETAIN VERB FLAGS
TRNE AT1,RTDLRW ; DELETE OR REWRITE RETAIN?
MOVEM AT1,SU.FRF ; YES, SET RETAIN FLAG POS TO INDICATE SO
>; END IFN ASN74
HRRZ AT1,F.WSMU(AFT) ;IF F.WSMU IS STILL AT ITS INITIAL VALUE
;(-1), THEN WE NEED TO SAVE THE KEY
;OF THE CURRENT RECORD
;
; IF WE HAVE ALREADY BEEN THROUGH HERE ONCE FOR THIS ISAM FILE,
; THEN WE SIMPLY GO AND USE THE USER KEY TO READ THE FILE AND
; GET THE BLOCK NUMBER TO ENQUEUE ON. NO FORCED READ WILL HAPPEN
; SINCE IT WILL HAVE BEEN DONE ON THE FIRST TIME THROUGH HERE.
;
CAIE AT1,-1
JRST BN2 ;JUMP, CURRENT KEY ALREADY SAVED
;
; THE FIRST RECORD RETAINED IN EACH RETAIN STATEMENT FOR A GIVEN
; ISAM FILE IS A SPECIAL CASE. THE PROBLEM IS THAT THERE CAN BE
; SEVERAL RECORDS RETAINED IN EACH RETAIN STATEMENT FOR A SINGLE
; ISAM FILE, AND WE MUST LEAVE THE FILE IN THE STATE IT WAS IN
; PRIOR TO THE RETAIN STATEMENT SO THE SUBSEQUENT I-O STATEMENTS
; WORK THE WAY THE USER EXPECTS THEM TO. IF EVERY RECORD BEING
; RETAINED HAS A REAL KEY (NOT LOW-VALUES) THEN THE PROBLEM IS NOT
; BAD, WE CAN JUST GO OFF AND READ EACH KEY NEVER BOTHERING ABOUT
; RESTORING THE FILE. HOWEVER, IF THE FIRST KEY BEING RETAINED IS
; LOW-VALUES, WE MUST WORRY ABOUT RESTORATION, WHICH MEANS WE MUST
; OBTAIN THE KEY OF THE CURRENT RECORD SO WE CAN RESTORE THE FILE
; POSITION WHEN NECESSARY. THE FLOW IS AS FOLLOWS:
;
; 1. CALL CBLIO AT FAKER. SUPPLYING A KEY OF LOW-VALUES.
; BY SETTING NXTREC(AFT) TO -1, CBLIO WILL RETURN TO
; US THE CURRENT RECORD FROM WHICH WE CAN GET ITS KEY.
; THIS KEY WILL BE STORED AT THE END OF THE RETAINED
; RECORDS TABLE (RRT).
;
; NOTE 1: IF THIS IS THE FIRST EVER I-O REQUEST
; FOR THIS FILE, CBLIO WILL HAVE PHYSICALLY
; READ EACH INDEX LEVEL AND THE DATA LEVEL
; THIS FULFILLS THE NEED FOR REFRESHING
; BUFFERS AND IS REMEMBERED FOR LATER USE.
;
; NOTE 2: IF I-O HAS BEEN DONE TO THIS FILE BEFORE
; THIS CALL TO CBLIO WILL NOT HAVE CAUSED
; ANY I-O AND WE WILL STILL HAVE BUFFER
; REFRESHING TO DO LATER.
;
; 2. IF NOTE 1 IS TRUE OR WE ENTER STEP 2 FROM ANOTHER POINT, GO
; AND CALL CBLIO TO READ THE FILE USING THE KEY OF THE RECORD
; BEING RETAINED, BYPASSING ANY FORCED READ. THIS RETURNS TO US
; THE BLOCK NUMBER OF THE RECORD BEING RETAINED, WHICH WE SAVE
; IN THE RRT AND RETURN TO THE MAIN CODE. THIS MAY OR
; MAY NOT CAUSE I-O DEPENDING ON WHERE THIS RECORD IS RELATIVE
; TO THE FIRST DATA BLOCK OF THE FILE, OR THE CURRENT DATA
; BLOCK DEPENDING ON HOW WE GOT TO STEP 2.
;
; 3. IF NOTE 2 IS TRUE, THEN THERE WAS A CURRENT RECORD AND NOW WE
; NEED TO KNOW IF THE RECORD BEING RETAINED HAS A KEY OF LOW-
; VALUES.
;
; 4. IF THE RECORD BEING RETAINED IS NOT FOR LOW-VALUES, THEN WE
; DO NOT NEED TO WORRY ABOUT RESTORING THE FILE TO ITS ORIGINAL
; POSITION. WE SIMPLY GO AND DO STEP 2, EXCEPT WE FORCE CBLIO
; TO DO A BUFFER REFRESH BY CALLING FORCR. PRIOR TO FAKER.
;
; 5. IF THE RECORD BEING RETAINED HAS A KEY OF LOW-VALUES, THEN WE
; MUST CALL CBLIO USING THE KEY OF THE CURRENT RECORD. WE MUST
; ALSO FORCE BUFFER REFRESHING BY DOING A FORCR. THIS GAURANTEES
; THAT THE SUBSEQUENT LOW-VALUES READ WILL GET THE LATEST "NEXT
; RECORD". AFTER FORCE READING THE CURRENT RECORD, WE GO TO
; STEP 2.
;
SETOM SU.Y ;SET SU.Y TO NON-ZERO TO INDICATE THIS
;IS THE FIRST RECORD RETAINED FOR THIS
;FILE BY THIS RETAIN STATEMENT
MOVE ACRR,SU.SVK ;WE'LL SAVE THE KEY AT THE END OF THE
;RETAINED RECORDS TABLE - SET ACRR,
;F.WSMU TO POINT THERE
HRRM ACRR,F.WSMU(AFT)
HLR AT1,D.BL(AFT)
MOVE AT2,NXTREC(AT1) ;THE KEY WE'RE SAVING ACTUALLY HAS TWO
;PARTS: THE KEY ITSELF, AND THE NEXT
;RECORD FLAG
MOVEM AT2,0(ACRR)
IFN ANS74,<
SKIPG SU.FRF ; DON'T RESET NNTRY YET IF DEL OR REWRIT
; SO WE GET A CHANCE TO SAVE THE PROPER VALUE
>
SETOM NXTREC(AT1) ;AFTER SAVING THE NEXT RECORD FLAG IN
;WORD 0, WE'LL TELL CBLIO THAT IT'S THE
;NEXT RECORD, REGARDLESS OF WHETHER IT IS
;OR NOT, SO THAT CBLIO WON'T READ A NEW
;BLOCK WHEN WE DO A LOW-VALUES FAKE READ
;TO GET THE KEY OF THE RECORD CURRENTLY
;BEING POINTED TO
LDB AT1,FTRM
MOVE AT1,[OCT 441000000000,440600000000,0,440700000000]-1(AT1)
HRRI AT1,1(ACRR)
EXCH AT1,F.WBSK(AFT) ;EXCHANGE A BYTE POINTER TO OUR PLACE TO
;SAVE THE KEY WITH THE BYTE POINTER
;TO THE SYMBOLIC KEY
MOVEM AT1,SU.T3 ;SAVE THE SYMBOLIC KEY IN SU.T3
MOVE AP,AFT
HRLI AP,RFLAG
PUSHJ PP,LV2SK. ;CALL CBLIO TO MOVE LOW-VALUES INTO
;WHAT IT THINKS IS THE SYMBOLIC KEY,
;BUT WHICH IS ACTUALLY OUR PLACE AT
;THE END OF THE RETAINED RECORDS
;TABLE USED TO SAVE THE CURRENT KEY.
; NOTE: THIS MUST ALSO BE DONE IN COBOL-74
;BECAUSE THIS TELLS CBLIO WHERE TO START!
HLR AT1,D.BL(AFT)
MOVE AT1,CNTRY(AT1) ;[650] SAVE THE VALUE OF THE POINTER TO
MOVEM AT1,SU.RLV ; THE CURRENT RECORD IN CBLIO'S BUFFERS.
; IT IS USED LATER TO DETERMINE IF THERE
; REALLY WAS A CURRENT RECORD.
IFN ANS68, PUSHJ PP,OWNFAK ;DO A FAKE LOW-VALUES READ
IFN ANS74, PUSHJ PP,FAKNXT
TRN
MOVE ACRR,SU.T1 ;RESTORE ACRR TO RETAINED RECORDS TABLE
;POINTER
HRRZ AFT,0(ACRR) ;RESTORE AFT TO FILE TABLE POINTER
HRRZ ACRR,F.WSMU(AFT) ;RESTORE ACRR TO SAVE KEY POINTER
LDB AT2,FTKLB
MOVE AT1,SU.RBP
SUBI ACRR,1 ;DECREMENT ACRR TO UTILIZE BLOCK NUMBER
;FIELD OF PSEUDO ENTRY IN TABLE
PUSHJ PP,MOVKEY ;MOVE THE CURRENT KEY INTO THE SAVE AREA
MOVE AT1,1(ACRR)
HLR AT2,D.BL(AFT)
MOVEM AT1,NXTREC(AT2) ;RESTORE THE NEXT RECORD FLAG
MOVE AT1,SU.T3
MOVEM AT1,F.WBSK(AFT) ;RESTORE SYMBOLIC KEY
MOVE AT2,ACRR
MOVE ACRR,SU.T1
LDB AT1,CRRINE
ADD AT2,AT1
PUSH PP,AT2 ;SAVE NEW SU.SVK FOR LATER
SKIPN SU.RLV ; WAS THERE A REAL CURRENT RECORD?
JRST BN2C ; NO, DON'T RESTORE ANYTHING
LDB AT1,FTRM ; YES, NOW SEE IF L-V BEING RETAINED
MOVE AT1,[OCT 441000000000,440600000000,0,440700000000]-1(AT1)
HRRI AT1,2(ACRR)
EXCH AT1,F.WBSK(AFT) ;EXCHANGE A BYTE POINTER TO OUR PLACE TO
;SAVE THE KEY WITH THE BYTE POINTER
;TO THE SYMBOLIC KEY
IFN ANS68,<
PUSHJ PP,LVTST ; IS THE KEY BEING RETAINED L-V?
TRNA ; YES, RESTORE FILE ALSO REFRESHES BUFFERS
>;END IFN ANS68
IFN ANS74,<
LDB AT2,RRTNXT ; IS THE KEY BEING RETAINED "NEXT RECORD"?
SKIPN AT2
>;END IFN ANS74
JRST BN2B ; NO, DON'T RESTORE ANYTHING
IFN ANS68,<
SETO AT2, ;SET "RETAINING L-V" BIT IN RRT ENTRY
DPB AT2,RRTNXT
>;END IFN ANS68
PUSH PP,AT1 ; SAVE REAL SYMBOLIC KEY POINTER
LDB AT1,FTOTA
TRNN AT1,000003 ;IF NOT WRITE OR DELETE
JRST BN2A ;SKIP IO SINCE NO ONE COULD AFFECT THE "NEXT RECORD"
PUSHJ PP,FORCR.
MOVE AT1,F.WBSK(AFT)
HRR AT1,SU.SVK
ADDI AT1,1
MOVEM AT1,F.WBSK(AFT)
PUSHJ PP,OWNFAK ;OWNFAK DOES A FAKER.
TRN
SETZM SU.Y ;TURN OFF "FIRST RECORD" FLAG SO LATER
;FORCR. DOES NOT HAPPEN UNNECESSARILY
MOVE ACRR,SU.T1
HRRZ AFT,0(ACRR)
BN2A: POP PP,AT1
BN2B: MOVEM AT1,F.WBSK(AFT)
BN2C: POP PP,SU.SVK ;SET SU.SVK TO NEXT SAVE AREA LOCATION
BN2: HRLI AP,RFLAG ;SET SPECIAL FLAGS
HRR AP,AFT ;SET FILE TABLE LOCATION
LDB AT1,FTRM ;BUILD A BYTE POINTER TO OUR KEY
MOVE AT1,[OCT 441000000000,440600000000,0,440700000000]-1(AT1)
HRRI AT1,2(ACRR) ;SET ADDRESS TO LOCATION OF OUR KEY
;IN THE RETAINED RECORDS TABLE
EXCH AT1,F.WBSK(AFT) ;SWAP WITH FILE TABLE SYMBOLIC KEY
;POINTER
MOVEM AT1,SU.T3 ;SAVE SYMBOLIC KEY POINTER FOR FUTURE
;RESTORATION
SETZM SU.RBP ;ZERO RECORD BYTE POINTER
; SKIPE SU.RLV ; WAS THERE A REAL CURRENT RECORD?
SKIPN SU.Y ; IS THIS THE FIRST RECORD IN THIS RETAIN STATEMENT?
JRST BN8A ; NO ON BOTH COUNTS, BUFFER REFRESHING
; HAS ALREADY HAPPENED, DON'T DO IT AGAIN
LDB AT1,FTOTA
TRNE AT1,000003
PUSHJ PP,FORCR. ;ASK CBLIO TO FORGET WHAT'S IN ITS
;INDEX BUFFERS, IF OTHERS DOING
;INSERTING OR DELETING
BN8A:
IFN ANS68,<
PUSHJ PP,OWNFAK ;CALL CBLIO
JRST BN8 ;JUMP IF NOT INVALID KEY
SETZM FS.BN ;USE BLOCK NUMBER OF 0 FOR NON-
;EXISTENT RECORDS
PUSHJ PP,LVTST ;DETERMINE IF INVALID KEY CAUSED
;BY EOF OR INVALID KEY (SKIP
;RETURN IF NOT LOW-VALUES)
PUSHJ PP,[PUSHJ PP,UHV
MOVE ACRR,SU.T1
SETO AT2,
DPB AT2,RRTNXT ;SET FLAGS IN RRT
DPB AT2,RRTHVF ; . .
POPJ PP,]
>;END IFN ANS68
IFN ANS74,<
MOVE ACRR,SU.T1
LDB AT1,RRTNXT
JUMPE AT1,[PUSHJ PP,OWNFAK
JRST BN8 ;NOT INVALID KEY
SETZM FS.BN ;INVALID KEY
JRST BN8] ;DO READ OF THE KEY
; Check for special del/rewrt saved seq position case
; if this case restore proper next record flag
HRRZ AT1,D.RFLG(AFT) ; Get extra flags
TRNN AT1,SAVNXT ; Next rec pos saved?
JRST BN8B ; No cont,
HLRZ AT1,D.BL(AFT) ; Yes, get buffer position
HLRZ AT2,RWDLKY(AT1) ; Get saved next rec flag
HRRM AT2,NNTRY(AT1) ; And set it
; this will ensure that the proper saved
; record position will be used
BN8B: PUSHJ PP,FAKNXT ;DO A "READ NEXT"
JRST BN8 ;NOT INVALID KEY
MOVE ACRR,SU.T1 ;RESTORE ACRR
PUSHJ PP,UHV ;STICK HIGH-VALUES IN KEY
SETO AT1,
DPB AT1,RRTHVF ;INVALID KEY WHEN LOOKING FOR LOW-VALUES.
>;END IFN ANS74
BN8: MOVE ACRR,SU.T1 ;RESTORE ACRR, AP, SYMBOLIC KEY
MOVE AP,SU.T2
MOVE AT1,SU.T3
HRRZ AFT,0(ACRR)
MOVEM AT1,F.WBSK(AFT)
LDB AT2,FTKLB
SKIPN AT1,SU.RBP ;IF SU.RBP IS NON-ZERO THEN USER GAVE
;US LOW-VALUES AND WE MUST MOVE THE
;REAL KEY INTO THE RETAINED RECORDS
;TABLE ENTRY
JRST BN7
PUSHJ PP,MOVKEY
BN7: MOVE AT1,FS.BN ;MOVE BLOCK NUMBER INTO RETAINED
;RECORDS TABLE ENTRY.
JRST BN5
; FILFLU: A SUBROUTINE THAT CHECKS TO SEE IF A BLOCK ABOUT
; TO BE ENQUEUED, DEQUEUED, OR MODIFIED IS IN THE CURRENT
; BUFFER. IF IT IS, THE FILE TABLE ADDRESS IS ADDED TO THE
; FILL/FLUSH BUFFER TABLE.
;
; FILFL2: A SECONDARY ENTRY POINT, WHICH ADDS THE CONDITION THAT
; THE BUFFER MUST HAVE BEEN MODIFIED (CONTAINS "LIVE"
; DATA).
;
;
; ARGUMENTS:
; 1. ACRR POINTS TO AN ENTRY IN THE RETAINED RECORDS
; TABLE.
;
; 2. AT2 CONTAINS A BLOCK NUMBER MOD 2 ** 18
;
;
; CHANGES:
; AFT
; AT4
; AT5
; SU.CFB (COUNT OF ENTRIES IN THE FILL/FLUSH BUFFER TABLE)
; SU.FBT (THE FILL/FLUSH BUFFER TABLE)
; USOBJ(AT5)
;
FILFL2: HRRZ AFT,0(ACRR)
HLRZ AT4,D.BL(AFT)
SETO AT5,
CAME AT5,LIVDAT(AT4)
POPJ PP,
FILFLU: HRRZ AFT,0(ACRR)
MOVE AT4,D.CBN(AFT) ;[455]
LDB AT5,FTAM
CAIE AT5,INDEXD
JRST FF01
HLRZ AT5,D.BL(AFT)
SETZM USOBJ(AT5)
POPJ PP,
FF01: CAME AT2,AT4
POPJ PP,
CAIN AT5,RANDOM
JRST FF02
HLRZ AT5,D.BL(AFT)
SKIPN R.BPLR(AT5)
POPJ PP, ;NO TABLE ENTRY IF SEQIO FILE AND NO IO DONE YET
FF02: MOVEI AT4,AT4
HRLM AT4,SU.FBT
MOVE AT4,SU.CFB
MOVEM AFT,@SU.FBT
AOS SU.CFB
POPJ PP,
; RESTOR: A SUBROUTINE WHICH RESTORES THE DEFINITION OF
; THE CURRENT RECORD IN THE PROCESSING OF AN ISAM FILE.
; IT DOES THIS BY CHECKING F.WSMU IN THE FILE TABLE.
; IF F.WSMU IS NOT -1, THEN IT POINTS TO A PLACE WHERE
; THE NEXT RECORD FLAG AND CURRENT KEY HAVE BEEN SAVED.
;
;
; ARGUMENTS:
;
; AFT POINTS TO A FILE TABLE
;
;
; CHANGES:
;
; ALL REGISTERS EXCEPT ACRR, AFT, AP, PP, I
; SU.T5
; SU.T6
; SU.T7
; SU.T8
; F.WSMU(AFT) (SET TO -1)
; NXTREC(AT3)
RESTOR: HRRZ AT1,F.WSMU(AFT)
CAIN AT1,-1
POPJ PP,
MOVEM I,SU.T8
MOVEM ACRR,SU.T5 ;SAVE I, ACRR
MOVEM AP,SU.T6 ;SAME AP
LDB AT2,FTRM
MOVE AT2,[OCT 441000000000,440600000000,0,440700000000]-1(AT2)
HRRI AT2,1(AT1) ;PREPARE BYTE POINTER TO SAVED KEY
EXCH AT2,F.WBSK(AFT) ;EXCHANGE WITH SYMBOLIC KEY
MOVEM AT2,SU.T7
MOVE AP,AFT
PUSHJ PP,OWNFAK ;DO FAKE READ TO POSITION AT SAVED KEY
TRN
MOVE AFT,AP ;RESTORE AFT
MOVE AP,SU.T6 ;RESTORE AP
HRRZ AT1,F.WSMU(AFT)
MOVE AT2,0(AT1)
HLR AT3,D.BL(AFT)
MOVEM AT2,NXTREC(AT3) ;RESTORE NEXT RECORD FLAG TO ITS SAVED
;VALUE
MOVE AT2,SU.T7
MOVEM AT2,F.WBSK(AFT) ;RESTORE SYMBOLIC KEY
SETO AT2,
HRRM AT2,F.WSMU(AFT) ;SET F.WSMU TO -1 TO INDICATE NOTHING TO
;RESTORE
MOVE ACRR,SU.T5 ;RESTORE ACRR
MOVE I,SU.T8 ;RESTORE I
POPJ PP, ;RETURN
; CLVACI: CHECK FOR LOW-VALUES AND CONVERT, IF NECESSARY
; THIS ROUTINE IS CALLED BY THE READ, WRITE, REWRITE,
; DELETE, AND FREE CODE FOR ISAM FILES. A CHECK IS MADE
; TO SEE IF THE OBJECT RECORD HAS A KEY OF LOW-VALUES.
; IF IT DOES NOT, NOTHING HAPPENS. IF IT DOES, THEN WE
; MUST DETERMINE IF THIS IS THE FIRST OPERATION ON THIS
; FILE SINCE THE RETAIN STATEMENT. THIS IS DETERMINED BY
; CHECKING F.WSMU(AFT). IF IT IS -1, THEN WE HAVE ALREADY
; DONE THIS BEFORE AND CAN RETURN WITH NO FURTHER
; PROCESSING. OTHERWISE, WE HAVE TO CHECK FURTHER. THE
; PROBLEM IS THAT IF SEVERAL RECORDS HAVE BEEN RETAINED FOR
; THE SAME FILE, THEN THE BLKNUM CODE LEFT THE FILE POINTING
; AT THE LAST RECORD RETAINED. BLKNUM ALSO SAVED THE KEY OF
; THE ORIGINAL CURRENT RECORD AT THE END OF THE RRT AND
; PUT A POINTER TO IT IN THE F.WSMU(AFT). SO, WHEN F.WSMU
; DOES NOT EQUAL -1, IT MEANS THAT THIS LOW-VALUES OPERATION
; IS RELATIVE TO THE ORIGINAL CURRENT RECORD AND WE MUST
; NOW RESTORE THE FILE TO THAT POINT. THERE IS A SPECIAL
; CASE, HOWEVER. IF THERE WAS ONLY ONE RECORD RETAINED
; FOR THIS FILE, THEN THE BLKNUM CODE LEFT US POINTING
; AT IT, SO WE CAN TELL CBLIO THAT THE "NEXT RECORD" IS
; REALLY THE CURRENT RECORD. THIS MEANS WE DO NOT HAVE TO
; RESTORE THE FILE, POTENTIALLY SAVING I-O, AND RE-READING
; THE CURRENT RECORD WILL DEFINITELY RESULT IN NO
; I-O.
;
; THE WHOLE REASON FOR READING THIS LOW-VALUES RECORD AT THIS
; TIME IS TO CHECK TO SEE IF THE RECORD BEING READ,
; WRITTEN, REWRITTEN, DELETED, OR FREED IS THE ONE RETAINED.
; ONCE THE READ HAPPENS HERE, THE BLOCK NUMBER AND KEY WILL
; BE COMPARED AGAINST ALL ENTRIES IN THE RRT FOR THIS FILE.
; IF NONE MATCHES, A FATAL ERROR MESSAGES RESULTS.
;
;
;
; ARGUMENTS:
;
; AFT CONTAINS A POINTER TO THE FILE TABLE
;
; RETURN:
;
; TO 1(PP) IF NOT LOW-VALUES
; TO 0(PP) IF LOW-VALUES, KEY IN SU.RBP
;
;
; CHANGES:
;
; ALL REGISTERS EXCEPT K, AURS, AP, PP, ACRR, AFT
; SU.T1
; SU.T2
; SU.T3
; SU.T4
; NXTREC(AT1)
; F.WSMU(AFT)
CLVACI: MOVEM K,SU.T1
MOVEM AURS,SU.T2
MOVEM AP,SU.T3
MOVEM ACRR,SU.T4
MOVE AT1,F.WBSK(AFT)
MOVE AP,AFT
IFN ANS68,<
PUSHJ PP,LVTST ;CALL CBLIO TO COMPARE KEY WITH
;LOW-VALUES
JRST CLVAC1
AOS 0(PP)
>;END IFN ANS68
IFN ANS74,< ;IN ANS74, THIS ROUTINE IS ONLY CALLED
; IF THE GUY IS DEFINITELY DOING I/O TO
; THE "NEXT RECORD".
JRST CLVAC1
>;END IFN ANS74
CLVAC2: MOVE AFT,AP
MOVE K,SU.T1
MOVE AURS,SU.T2
MOVE AP,SU.T3
MOVE ACRR,SU.T4
POPJ PP,
CLVAC1: HRRZ AFT,AP ; IF F.WSMU IS -1, WE HAVE ALREADY
HRRZ AT1,F.WSMU(AFT) ; RESTORED THE FILE ONCE
CAIN AT1,-1
JRST CLVAC3 ;JUMP IF IT'S NOT NECESSARY TO
;RESTORE OUR POSITION IN THE FILE
;
; THE FOLLOWING CODE COMPARES THE FILE TABLE ADDRESS OF THE
; OBJECT RECORD AGAINST ALL THE RRT ENTRIES. IF IT IS
; DETERMINED THAT THERE IS ONLY ONE MATCH, THEN NO RESTORATION
; IS NECESSARY SINCE BLKNUM WILL HAVE LEFT US POINTING AT THE
; CORRECT RECORD.
;
SETZ AT3,
MOVE AT1,SU.RRT
CLVAC5: CAML AT1,SU.CRH
JRST CLVAC6
HRRZ AT2,0(AT1)
CAMN AT2,AFT
ADDI AT3,1
LDB AT2,[POINT 8,0(AT1),17]
ADD AT1,AT2
JRST CLVAC5
CLVAC6: SOJN AT3,CLVAC7 ; REMOVE THE EFFECT OF MATCHING AGAINST ITSELF
; IF THERE WAS MORE THAN ONE RETAINED RECORD FOR THIS FILE
; WE MUST DO REAL RESTORE
MOVE AT1,SU.RRT ;LOOP AGAIN.. IF REALLY LOW-VALUES READ
; AND DIDN'T GET EOF, SET NXTREC=-1
CLVBC5: CAML AT1,SU.CRH
JRST CLVBC6
HRRZ AT2,0(AT1)
CAMN AT2,AFT
JRST SETIFL ;SET NXTREC = -1 IF WE SHOULD
LDB AT2,[POINT 8,0(AT1),17]
ADD AT1,AT2
JRST CLVBC5
SETIFL: LDB AT2,AT1HVF ;EOF BIT - SET IF LV RETAIN FOUND EOF
JUMPN AT2,CLVBC6 ;IF EOF FOUND, DON'T RESET FLAG
HLRZ AT1,D.BL(AFT)
IFN ANS74,<
HRRZ AT2,D.RFLG(AFT) ; First check to see if special del/rewrt
TRNN AT2,SAVNXT ; And if so, need saved next flag value
JRST SETIF1 ; Not special, cont
HLRZ AT2,RWDLKY(AT1) ; Get saved next rec flag
HRRM AT2,NNTRY(AT1) ; And set it
; this will ensure that the proper saved
; record position will be used
TDNA ; Now skip setting NNTRY
SETIF1:
>; END IFN ANS74
SETOM NXTREC(AT1) ; TELL CBLIO THAT THE CURRENT RECORD IS
HLLOS F.WSMU(AFT) ; THE "NEXT RECORD".
JRST CLVAC3
CLVBC6: HLRZ AT1,D.BL(AFT) ; YES, NO RESTORE NECESSARY, TURN OFF F.WSMU
HLLOS F.WSMU(AFT) ;CLEAR "RESTORE NECESSARY" FLAG
JRST CLVAC3
CLVAC7: PUSHJ PP,RESTOR ;RESTORE OUR POSITION IN THE FILE AT
;RETAIN TIME, IF NECESSARY
CLVAC3:
IFN ANS68,<
PUSHJ PP,OWNFAK ;DO FAKE READ
JRST CLVAC4 ;JUMP IF NOT END OF FILE
PUSHJ PP,UHV ;USE HIGH VALUES IF END OF FILE
>;END IFN ANS68
IFN ANS74,<
HRRZ AT2,D.RFLG(AFT) ; First check to see if special del/rewrt
TRNN AT2,SAVNXT ; And if so, need saved next flag value
JRST CLVA3A ; Not special, cont
HLRZ AT1,D.BL(AFT) ; Get buffer location
HLRZ AT2,RWDLKY(AT1) ; Get saved next rec flag
HRRM AT2,NNTRY(AT1) ; And set it
; This will ensure that the proper saved
; record position will be used
CLVA3A:
PUSHJ PP,FAKNXT
JRST CLVAC4 ;NOT EOF
PUSHJ PP,UHV ;USE HIGH VALUES IF END OF FILE
>;END IFN ANS74
HLR AT4,D.BL(AP)
SETZM NXTREC(AT4) ;SET NXTREC TO 0 TO GUARANTEE
;USER GETS END OF FILE ALSO
JRST CLVAC2
CLVAC4: HLR AT4,D.BL(AP) ;SET NEXT RECORD FLAG SO THAT READ
;WILL GET SAME RECORD WE GOT WITH
;THE FAKE READ
SETOM NXTREC(AT4)
JRST CLVAC2
; FED: THE FILE ENQUEUE/DEQUEUE ROUTINE
;
; ARGUMENTS:
;
; 1. AT4: OWN ACCESS BITS FOR READ, REWRITE, WRITE, DELETE
;
; 2: AT5: OTHERS ACCESS BITS FOR SAME
;
; 3: 0(ACRR) POINTS TO THE FILE TABLE FOR THE FILE
;
; 4: ACRR LH = 0 => ENQUEUE; LH = 1 => DEQUEUE
;
;
; CHANGES:
;
; AT4
; AT5
; ANYTHING CHANGED BY QUEUE
; K
; J
; AT1
; AT2
FED: MOVEI J,4
FED1: LDB K,[POINT 1,AT5,32]
TRNE AT4,000010
TRO K,000002
; K NOW CONTAINS AN INTEGER BETWEEN 0 AND 3 REPRESENTING THE FOUR
; COMBINATIONS OF OWN AND OTHERS USE OF THE VERB CURRENTLY
; REPRESENTED IN BIT 32 OF AT4 AND AT5.
JRST .+1(K)
JRST H0 ;NEITHER OWN NOR OTHER USE
JRST H1 ;NOT OWN USE BUT OTHER USE
JRST H2 ;OWN USE BUT NOT OTHER USE
HRLZI AT1,1 ;OWN USE AND OTHER USE
H10: MOVN AT2,J
SUBI AT2,1
HLR AT1,ACRR
PUSHJ PP,QUEUE
H1: LSH AT4,1
LSH AT5,1
SOJG J,FED1
POPJ PP,
H2: TDZA AT1,AT1
H0: HRLZI AT1,3
JRST H10
; ZSATB: A ROUTINE THAT ASKS CBLIO TO REFRESH ITS IN-CORE STORAGE
; ALLOCATION TABLES
;
; INPUTS:
;
; 1. ACRR POINTS TO THE APPROPRIATE ENTRY IN THE RETAINED RECORDS TABLE
;
; RETURNS: NOTHING
;
; CHANGES: AT1, AFT, USOBJ+13(AT1)
ZSATB: HRRZ AFT,0(ACRR)
LDB AT1,FTOTA
TRNN AT1,000003
POPJ PP, ;RETURN IF OTHERS NEITHER
;INSERTING NOR DELETING
HLRZ AT1,D.BL(AFT)
SETZM USOBJ+13(AT1)
POPJ PP,
CHGCNV: CAMN ACRR2,[MOVS AT5,CHTAB(AT5)] ;[447]
HRLI ACRR2,(HLRZ AT5,(AT5)) ;[447]
CAMN ACRR2,[MOVE AT5,CHTAB(AT5)] ;[447]
HRLI ACRR2,(HRRZ AT5,(AT5)) ;[447]
POPJ PP, ;[447]
; UHV: A ROUTINE TO SET HIGH VALUES IN SU.RBP AND 0 IN FS.BN
;
;
; ARGUMENTS:
;
; 1: AP POINTS TO A FILE TABLE
;
; RETURNS:
;
; 1: A BYTE POINTER TO HIGH VALUES IN SU.RBP
;
; 2: ZERO IN FS.BN
;
; 3: -1 IN SU.HV
;
; CHANGES:
;
; AFT, AT1, SU.RBP, FS.BN, SU.HV
UHV: MOVE AFT,AP
LDB AT1,FTRM ;[447] GET RECORD MODE
HRRI AT1,[OCT 377,77,0,177]-1(AT1) ;[447] VARIOUS HIGH VALUES CHARS
HLL AT1,F.WBSK(AFT) ;[447] FILE TABLE SYMBOLIC KEY BYTE PTR
SETZM FS.BN
TLZ AT1,770000 ;[446] IGNORE OLD BIT POS
; TLO AT1,440000 ;[446] WHEN HERE IT IS ALWAYS WORD ALIGNED
MOVEM AT1,SU.RBP
SETOM SU.HV ;[447] TELL WORLD HIGH VALUES BEING USED
POPJ PP,
; OWNFAK: OUR OWN ROUTINE TO CALL CBLIO FAKE READ
;
IFN ANS74,<
FAKNXT: HRLI AP,RNFLAG ;GET FAKE READ NEXT FLAGS
TRNA
>;END IFN ANS74
OWNFAK: HRLI AP,RFLAG
IFN ANS74,<
SKIPN SU.FRF ; IF NOT ALREADY SET BY DEL/REWRT
>
SETOM SU.FRF ; THEN SET FAKE READ FOR RETAIN FLAG
HLR AT1,D.BL(AP) ;[445] GET TABLE ADDR OF ISAM STUFF
MOVE AT2,GDPSK(AT1) ;[445] GET BYTE PTR USED FOR KEY CONV
MOVEM AT2,SU.T9 ;[445] SAVE FOR LATER
MOVEI AT2,44 ;[445] SET UP CORRECT BYTE POS
DPB AT2,[POINT 6,GDPSK(AT1),5] ;[445] MAKE IT RIGHT
IFN ANS74,<
LDB AT2,F.BFAM ; GET FILE ACCESS MODE
PUSH PP,AT2 ; SAVE IT HERE
MOVEI AT2,%FAM.D ; GET DYNAMIC ACCESS
DPB AT2,F.BFAM ; AND SET IT
>
PUSHJ PP,FAKER.
TRNA
IFN ANS68,<
AOS 0(PP)
>
IFN ANS74,<
AOS -1(PP) ; INVALID KEY RETURN
POP PP,AT2 ; RESTORE ACCESS MODE
DPB AT2,F.BFAM ; HERE
>
SETZM SU.FRF
HLR AT1,D.BL(AP) ;[445] GET TABLE ADDR
MOVE AT2,SU.T9 ;[445] GET BACK ORIG BYTE PTR
MOVEM AT2,GDPSK(AT1) ;[445] RESTORE IT
POPJ PP,
; ERROR HANDLING
EXTERN KILL.
DEFINE $SUERR(TEXT),<
TYPE SUHDR ;TYPE HEADER FOR MESSAGE
TYPE [ASCIZ \TEXT\] ;TYPE THE TEXT OF THE ERROR
JRST KILL. ;GO OFF TO KILL.
>
SU.ER1: $SUERR <RETAIN statement executed when records are already retained, which is not allowed>
SU.ER2: $SUERR <Missing constant (internal error)>
SU.ER3: $SUERR <RETAIN statement requesting access by verb not listed at OPEN time>
SU.ER4: $SUERR <Invalid RETAIN flags (internal error)>
SU.ER5: $SUERR <Invalid type code (internal error)>
SU.ER6: $SUERR <Key sizes unequal (internal error)>
SU.ER7: TYPE SUHDR ;TYPE HEADER FOR MESSAGE
TYPE [ASCIZ \Unexpected return from ENQ/DEQ...error code %\] ;[654]
MOVEI AT3,14 ;[654] OUTPUT ENQ/DEQ ERROR RETURN
SUER7A: SETZ AT1, ;[654] CLEAR CHARACTER BUFFER
LSHC AT1,3 ;[654] GET A DIGIT
ADDI AT1,60 ;[654] MAKE IT ASCII
OUTCHR AT1 ;[654] PRINT IT
SOJG AT3,SUER7A ;[654] DO IT AGAIN
JRST KILL.
SU.ER9: $SUERR <OPEN for simultaneous update is not allowed if files are already OPEN for simultaneous update>
SU.ERB: $SUERR <Attempt to execute READ, REWRITE, WRITE, or DELETE on record not retained>
SU.ERC: $SUERR <Attempt to execute READ, REWRITE, WRITE, or DELETE on record not retained for that purpose>
SU.ERD: $SUERR <Unexpected return from ENQ/DEQ during execution of READ, REWRITE, WRITE, or DELETE (internal)>
SU.ERE: $SUERR <Insufficient core for ENQ/DEQ to operate>
SU.ERF: $SUERR <Insufficient quota for ENQ/DEQ; change the ENQ/DEQ quota parameter in the monitor to run this program>
;PRELUDE TO THE ABOVE MESSAGES
SUHDR: ASCIZ/?COBOL: Simultaneous update - /
END