Trailing-Edge
-
PDP-10 Archives
-
RMS-10_T10_704_FT2_880425
-
10,7/rms10/rmssrc/rmsudm.b36
There are 6 other files named rmsudm.b36 in the archive. Click here to see a list.
MODULE UD2 =
BEGIN
GLOBAL BIND UD2V = 1^24 + 0^18 + 16; !EDIT DATE: 7-JAN-77
%([
PURPOSE: UTILITIES FOR RMSUDR.
THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
!COPYRIGHT (C) 1977, 1979 BY DIGITAL EQUIPMENT CORPORATION
AUTHOR: S. BLOUNT
********** TABLE OF CONTENTS **************
ROUTINE FUNCTION
======= ========
ALCRFA ALLOCATE A NEW RFA FOR A RECORD
SHUFFLEIDS SHUFFLE THE ID'S IN A DATA BUCKET
FBYRFA FIND A RECORD GIVEN ITS RFA
FBYRRV FOLLOW RRV RECORD TO RECORD GIVEN ITS RFA
SKIPRECORD SKIP A DATA RECORD
REVISION HISTORY:
EDIT DATE WHO PURPOSE
==== ==== === ========
1 24-AUG-76 JK ADD 'UPDRRVS' ROUTINE.
2 1-SEP-76 JK REPLACE REFS TO ZERO ID BY 'NULLID'.
3 1-SEP-76 JK FIX 'UPDRRVS'.
4 1-SEP-76 JK FIX 'UPDRRVS' -- 'UPDBKD' SHOULD BE MAPPED 'FORMAT'.
5 2-SEP-76 JK REMOVE EDIT 3 (EDIT 4 FOUND REAL CULPRIT).
6 2-SEP-76 JK REMOVE EDIT 5, REINSTATE EDIT 3, UPDATE RRV REC. CORRECTLY.
7 2-SEP-76 JK 'UPDRRVS' NOW HANDLES "RRV NOT FOUND" CORRECTLY.
8 3-SEP-76 JK SPLIT RMSUDR INTO RMSUDR, RMSUD2, RMSSPT.
9 8-SEP-76 JK SIMPLIFY 'FBYRFA'.
10 19-OCT-76 SB MAKE SKIPRECORD PROCESS SIDR'S
11 28-OCT-76 SB EDIT LOOKATFIELD, CLEAR RECPTR IN FBYRRV
12 5-NOV-76 SB FIX FBYRRV TO SET UP RRV FIELD IN RD
13 11-NOV-76 SB MAKE FBYRRV USE PRIMARY KDB ALWAYS
14 30-DEC-76 SB ADD LOCK-FLAG TO SKIPRECORD
15 7-JAN-77 SB ADD FLGREO TO SHUFFLEIDS
*************************************************
* *
* NEW REVISION HISTORY *
* *
*************************************************
****************** Start RMS-10 V1.1 *********************
********************* TOPS-10 ONLY ***********************
PRODUCT MODULE SPR
EDIT EDIT QAR DESCRIPTION
====== ====== ===== ===========
100 16 Dev Make declarations for routine names
be EXTERNAL ROUTINE so RMS will compile
under BLISS V4 (RMT, 10/22/85).
***** END OF REVISION HISTORY *****
])%
%([ FORWARD DECLARATIONS ])%
FORWARD ROUTINE SHUFFLEIDS ; ! FIND HOLE OF UNUSED ID'S IN A BKT
%([ EXTERNAL DECLARATIONS ])%
EXTERNAL ROUTINE
CRASH, ! DEBUGGING
GTNBKT, ! GET THE NEXT BUCKET
CKEYKK, ! KEY COMPARISON ROUTINE
CKEYKU, ! KEY COMPARISON ROUTINE
GETBKT, ! OBTAIN A BUCKET
PUTBKT, ! RELEASE A BUCKET
SDATABKT, ! SEARCH A DATA BUCKET
DUMP; ! SAME
%([ ERROR MESSAGES REFERENCED IN THIS MODULE ])%
EXTERNAL
MSGINPUT, ! BAD INPUT VALUES
MSGKDB, ! BAD KDB IS PASSED TO ROUTINE
MSGPTR, ! SOMETHING WRONG IN PTR
MSGCANTGETHERE; ! BAD LOGIC FLOW
REQUIRE 'RMSREQ';
EXTDECLARATIONS;
! ALCRFA
! ======
! THIS ROUTINE ALLOCATES A NEW RFA FOR A RECORD WHICH IS BEING
! INSERTED INTO THE FILE. FOR MOST CASES, THIS ROUTINE IS
! TRIVIAL. BUT, IN SOME CASES WE MUST GARBAGE COLLECT THE
! RECORD ID'S IN THE BUCKET HEADER TO LOOK FOR A SPARE ONE.
! INPUT:
! BKTDESC BUCKET DESCRIPTOR OF BUCKET WHERE RECORD IS TO GO
! OUTPUT:
! NOT FALSE: RFA OF NEW RECORD
! FALSE: ERROR
! ID'S RAN OUT (SHOULD NOT HAPPEN)
! INPUT ARGUMENTS MODIFIED:
! <NONE>
! BUCKET HEADER FIELDS MODIFIED:
! NEXTID
! LASTID (IF ID'S MUST BE SHUFFLED)
GLOBAL ROUTINE ALCRFA ( BKTDESC ) =
BEGIN
ARGUMENT (BKTDESC,BASEADD); ! CURRENT BUCKET
REGISTER
NEWRFA: FORMAT, ! THE RFA OF RECORD
BKTPTR: POINTER,
TEMPAC;
MAP
BKTDESC: POINTER;
TRACE ('ALCRFA');
CHECKEXACTCOUNT;
%([ SET UP A BUCKET POINTER ])%
BKTPTR = .BKTDESC [ BKDBKTADR ];
%([ PUT THE BUCKET NUMBER INTO THE NEW RFA ])%
NEWRFA < RH > = .BKTDESC [ BKDBKTNO ]; ! 'RH' STANDS FOR RFABUCKET IN BUCKET.REQ
NEWRFA < LH > = ( TEMPAC = .BKTPTR [ BHNEXTID ] ); ! GET NEXT ID.'LH' STANDS FOR RFAID
%([ BUMP THE NEXT ID IN THE BUCKET HEADER AND CHECK IF IT'S TOO HIGH ])%
IF ( BKTPTR [ BHNEXTID ] = .TEMPAC + 1 )
GTR
.BKTPTR [ BHLASTID ]
THEN %(WE MUST GARBAGE COLLECT ON THE ID'S)%
BEGIN
RTRACE (%STRING('** NO ID FOUND IN BUCKET',%CHAR(13),%CHAR(10)));
IF ( NEWRFA < LH > = CALLSHUFFLEIDS ( BPT ( BKTDESC ) ) ) IS FALSE ! 'LH' STANDS FOR RFAID
THEN
RETURN FALSE
END; %(OF WE MUST GARBAGE COLLECT)%
%([ WE NOW HAVE OUR ID ])%
LOOKAT (' NEW RFA FOR RECORD: ',NEWRFA);
RETURN .NEWRFA
END; %(OF ALCRFA)%
! SHUFFLEIDS
! ==========
! ROUTINE TO SCAN A DATA BUCKET IN SEARCH OF A "HOLE" OF UNUSED
! RECORD ID'S. THIS ROUTINE IS CALLED WHENEVER "NEXTID"
! IS GREATER THAN "LASTID" IN THE BUCKET HEADER. SUCH A
! SITUATION MEANS THAT WE MUST SCAN THE BUCKET TO SEE IF
! WE CAN COLLESCE SOME OF THE UNUSED RECORD ID'S.
!
! THERE ARE SEVERAL WAYS IN WHICH THIS COULD BE DONE. THE FULL
! BUCKET SCAN TO FIND THE LARGEST HOLE IS A VERY EXPENSIVE
! OPERATION (IT IS AN O(N**2) ALGORITHM....THAT MEANS THAT AS
! THE NUMBER (N) OF RECORDS IN THE BUCKET INCREASES, THE TIME
! TO SEARCH FOR THE LARGEST ID GOES UP AT A RATE OF N SQUARED).
! THEREFORE, WE WOULD LIKE TO SOMETHING WHICH WOULD SPEED UP
! THE SEARCH. THE TECHNIQUE USED IN THIS ROUTINE IS TO SEARCH
! FOR ANY HOLE WHICH IS NON-EMPTY AND TO USE THE FIRST SUCH
! HOLE WHICH IS FOUND. THIS MEANS THAT THIS ROUTINE MAY
! HAVE TO BE CALLED A LITTLE MORE THAN WOULD OTHERWISE BE THE
! CASE, BUT EACH OPERATION WILL BE FAIRLY QUICK. ALSO, SINCE
! RECORDS AT THE TOP OF THE BUCKET WILL TEND TO BE OLDER, IT
! SEEMS REASONABLE THAT THEY ALSO WILL HAVE LOWER ID'S AND THUS
! WILL LIKELY GIVE RISE TO LARGER ID HOLES.
!
! IF THIS ROUTINE IS CALLED, THEN THE FILE SHOULD BE RE-ORGANIZED.
! THIS IS BECAUSE THE RECORD SEARCH ALGORITHMS ASSUME THAT RECORD
! ID'S CANNOT BE RE-USED. IF THIS IS NOT TRUE, THEN A KEY
! COMPARISON MUST BE MADE WHENEVER THE CURRENT RECORD IS BEING
! LOCATED. THUS, TO AVOID THIS OVERHEAD, WE WILL TELL THE USER
! IF HIS ID'S RUN OUT THAT HE SHOULD RE-ORGANIZE THE FILE.
! INPUT:
! BKTDESC BUCKET DESCRIPTOR OF BUCKET
! OUTPUT:
! NOT FALSE: NEW ID TO USE
! FALSE: NO ID'S LEFT IN BUCKET (SHOULD NOT HAPPEN)
! ROUTINES CALLED:
! <NONE>
GLOBAL ROUTINE SHUFFLEIDS ( BKTDESC ) =
BEGIN
ARGUMENT (BKTDESC,BASEADD);
MAP
BKTDESC: POINTER;
LITERAL MINHOLESIZE = 2; ! HOLE MUST BE THIS BIG
REGISTER
LOWID, ! CURRENT BASE LEVEL ID
TEMPAC, ! TEMP
MOVINGPTR: POINTER; ! USED TO SCAN THE BUCKET
LOCAL
BKTPTR: POINTER, ! PTR TO TOP OF BUCKET
HIGHID, ! CURRENT TOP OF HOLE ID
CURRENTID, ! ID OF CURRENT RECORD
ENDPTR: POINTER, ! PTR TO END OF BUCKET
FIXEDPTR: POINTER; ! PTR TO CURRENT "LOWID" RECORD
TRACE ('SHUFFLEIDS');
CHECKEXACTCOUNT;
%([ TELL HIM TO RE-ORGANIZE THE FILE ])%
SETFLAG ( FST [ FSTFLAGS ], FLGREO );
USRSTS = SU$REO; ! SET UP SUCCESS CODE
%([ SET UP SOME POINTERS ])%
BKTPTR = .BKTDESC [ BKDBKTADR ];
FIXEDPTR = .BKTPTR + BHHDRSIZE; ! POINT TO FIRST RECORD
ENDPTR = .BKTPTR + .BKTPTR [ BHNEXTBYTE ]; ! END OF BUCKET
%([ SET UP SOME ID VALUES ])%
LOWID = ZERO; ! LOWEST ID
%([ THIS IS THE MAIN LOOP. THIS WILL BE EXECUTED ONCE
FOR EACH SCAN OF THE BUCKET. ONLY IF THE FIRST RECORD
HAS AN ID WHICH IS 1 LESS THAN SOME OTHER RECORD
WILL IT BE EXECUTED MORE THAN ONCE. ])%
REPEAT %(UNTIL WE FIND A BIG ENOUGH HOLE)%
BEGIN
HIGHID = HIGHESTID+1; ! ASSUME BUCKET IS EMPTY
MOVINGPTR = .BKTPTR + BHHDRSIZE; ! START AT TOP
%([ SCAN THE BUCKET LOOP ])%
UNTIL .MOVINGPTR GEQ .ENDPTR
DO
BEGIN
LOWID = .FIXEDPTR [ DRRECORDID ] + 1; ! GET CURRENTID
CURRENTID = .MOVINGPTR [ DRRECORDID ]; ! GET THIS ONE
%([ IS THIS A SMALLER HOLE? ])%
IF ( .CURRENTID LSS .HIGHID )
AND
( .CURRENTID GEQ .LOWID )
THEN %(WE HAVE FOUND A SMALLER HOLE)%
HIGHID = .CURRENTID;
%([ BUMP THE MOVING POINTER ])%
MOVINGPTR = .MOVINGPTR + SIZEOFANYRECORD ( MOVINGPTR )
END; %(OF BUCKET SCAN)%
%([ WE HAVE NOW SCANNED THE BUCKET ONCE LOOKING FOR HOLES.
DID WE FIND ANY? ])%
LOOKAT (' HIGHID: ',HIGHID );
LOOKAT (' LOWID: ',LOWID );
IF ( .HIGHID - .LOWID ) GEQ MINHOLESIZE
THEN %(OUR HOLE IS OK)%
BEGIN
RTRACE (%STRING(' FOUND NEW HOLE',%CHAR(13),%CHAR(10)));
BKTPTR [ BHNEXTID ] = .LOWID + 1; ! STORE NEXT ID
BKTPTR [ BHLASTID ] = .HIGHID - 1;
RETURN .LOWID ! VALUE IS THIS ID
END; %(OF OUR HOLE IS BIG ENOUGH)%
RTRACE (%STRING('** HOLE IS NOT BIG ENOUGH',%CHAR(13),%CHAR(10)));
%([ BUMP THE FIXED PTR TO THE NEXT RECORD ])%
FIXEDPTR = .FIXEDPTR + SIZEOFANYRECORD ( FIXEDPTR );
%([ IS WE ARE PAST THE END OF THE BUCKET...WE HAVE PROBLEMS ])%
IF .FIXEDPTR GEQ .ENDPTR
THEN
RMSBUG ( MSGPTR )
END; %(OF REPEAT LOOP)%
RMSBUG ( MSGCANTGETHERE )
END; %(OF SHUFFLEIDS)%
! FBYRFA
! ======
!
! THIS ROUTINE WILL FIND A RECORD GIVEN ITS RFA ( THIS
! INCLUDES MAPPING THE OBJECT BUCKET).
!
! INPUT:
! RECDESC = BASE ADDRESS OF RECORD DESCRIPTOR CONTAINING RFA
! RFA = RFA TO SEARCH FOR
! BKTDESC = BASE ADDRESS OF BUCKET DESCRIPTOR (EMPTY)
! LOCKFLAG = FLAG FOR LOCKING OF BUCKET
!
! OUTPUT:
! TRUE = FOUND RECORD
! FALSE = RECORD NOT FOUND,
! CAN'T GET BUCKET
!
! ARGUMENTS MODIFIED:
! RECDESC [ RECPTR ] = ADDRESS OF RECORD
! BKTDESC = ALL FIELD VALUES WILL BE FILLED IN
!
! NOTES:
!
! 1. IF THIS ROUTINE FAILS IN ANY WAY, THE BUCKET
! WHICH WAS USED WILL BE RETURNED TO THE BUCKET
! MANAGER. THUS, IF THIS ROUTINE RETURNS "TRUE",
! THE CALLER MUST DISPOSE OF THE BUCKET, IF IT
! RETURNS "FALSE", THERE IS NO BUCKET TO DISPOSE OF.
GLOBAL ROUTINE FBYRFA ( RECDESC, BKTDESC, LOCKFLAG ) =
BEGIN
ARGUMENT (RECDESC,BASEADD); ! BASE ADDRESS OF RECORD DESCRIPTOR
ARGUMENT (BKTDESC,BASEADD); ! BASE ADDRESS OF BUCKET DESCRIPTOR
ARGUMENT (LOCKFLAG,REFERENCE); ! FLAG FOR LOCKING
LOCAL
BKTNO, ! A BUCKET NUMBER
BKTSIZE, ! A BUCKET SIZE
RFA: FORMAT; ! AN RFA
MAP
RECDESC: POINTER,
BKTDESC: POINTER;
TRACE ( 'FBYRFA' );
%([ GET THE BUCKET CONTAINING THE SPECIFIED RFA ])%
RFA = .RECDESC [ RDRFA ]; ! GET RFA
LOOKAT ( ' TRY TO FIND RFA: ' , RFA );
BKTNO = .RFA [ RFABUCKET ]; ! GET BUCKET NUMBER
BKTSIZE = .KDB [ KDBDBKZ ]; ! GET BUCKET SIZE
%([ DO A SPECIAL CHECK HERE TO INSURE BUCKET NUMBER IS
WITHIN THE SPACE OF THE FILE ])%
IF .BKTNO LSS LOWESTBKTNUM THEN RETURNSTATUS ( ER$RFA ); ! BAD RFA
%([ GET A BUFFER AND MAP BUCKET ])%
IF CALLGETBKT (%( BKTNO )% LCI ( BKTNO ),
%( BKTSIZE )% LCI ( BKTSIZE ),
%( LOCKFLAG )% RLCI ( LOCKFLAG ),
%( BKTDESC )% BPT ( BKTDESC ) ) IS FALSE
THEN
BADRETURN;
LOOKAT ( ' GOT BKT: ' , BKTNO );
%([ FIND THE RECORD(RFA) IN THE BUCKET ])%
LOOKAT ( ' START SEARCH AT: ' , RECDESC [ RDRECPTR ] );
IF CALLSDATABKT (%( RECDESC )% BPT ( RECDESC ),
%( BKTDESC )% BPT ( BKTDESC ) ) IS FALSE
THEN
BEGIN %( GIVE BUCKET BACK ON SEARCH FAILURE )%
CALLPUTBKT ( %( UPDATEFLAG )% PCI ( FALSE ),
%( BKTDESC )% BPT ( BKTDESC ) );
BADRETURN
END; %( OF GIVE BUCKET BACK ON SEARCH FAILURE )%
LOOKAT ( ' FOUND RECORD AT: ' , RECDESC [ RDRECPTR ] );
%([ DONE ])%
GOODRETURN
END; %( OF FBYRFA )%
! FBYRRV
! ======
! ROUTINE TO LOCATE A USER DATA RECORD IN AN INDEXED FILE
! THRU ITS RRV ADDRESS. IF THERE IS NO RRV RECORD
! ASSOCIATED WITH THE DATA RECORD, THEN THIS ROUTINE
! PERFORMS IDENTICALLY TO FBYRFA. HOWEVER, IF THERE
! IS A LEVEL OF INDIRECTION (I.E., THERE IS AN RRV
! RECORD), THEN THIS ROUTINE MUST LOCATE BOTH THE
! RRV AND THE DATA RECORD.
! INPUT:
! RECDESC RECORD DESCRIPTOR PACKET
! RFA RFA TO SEARCH FOR
! RECPTR <IGNORED>
!
! DATABD BUCKET DESCRIPTOR OF DATA (RETURNED)
! OUTPUT:
! TRUE: RECORD FOUND
! FALSE: ERROR
! BUCKET BUSY
! RECORD NOT FOUND
! ARGUMENTS MODIFIED:
! RECDESC:
! RECPTR ADDRESS OF DATA RECORD
! RRV RFA OF THE RRV RECORD FOUND
! NOTES:
!
! 1. IF THE DATA RECORD IS FOUND, THE RRV BUCKET WILL
! BE UNLOCKED.
!
! 2. THE BUCKET SEARCH IS ALWAYS FROM THE TOP OF THE BUCKET.
!
! 3. NOTE THAT THE RRV ADDRESS IS RETURNED IN THE RRV
! FIELD OF THE RECORD DESCRIPTOR.
GLOBAL ROUTINE FBYRRV ( RECDESC, DATABD ) =
BEGIN
ARGUMENT (RECDESC,BASEADD);
ARGUMENT (DATABD,BASEADD);
MAP
RECDESC: POINTER,
DATABD: POINTER;
LOCAL
RRVBD: FORMATS[ BDSIZE ],
SAVEDKDB, ! SAVE THE KDB ON ENTRANCE
SAVEDSTATUS; ! WE MUST REMEMBER THE STATUS
LABEL LOOP; ! USE A LOOP TO JUMP OUT OF
REGISTER
RECORDPTR: POINTER;
TRACE ('FBYRRV');
CHECKEXACTCOUNT;
LOOKAT (' TRYING TO FIND RRV: ', RECDESC [ RDRFA ] );
%([ INSURE THAT THE SEARCH WILL START AT TOP OF BUCKET ])%
RECDESC [ RDRECPTR ] = ZERO;
%([ SINCE THIS ROUTINE CAN OPERATE ONLY ON THE PRIMARY
DATA RECORDS, WE CAN SAVE THE CALLER SOME TROUBLE BY
ALWAYS USING THE PRIMARY KEY DESCRIPTOR BLOCK.
HOWEVER, THIS MEANS THAT WE MUST CREATE A DUMMY LOOP
TO EXIT FROM SO WE CAN RESTORE THE OLD KDB. ])%
SAVEDKDB = .KDB; ! SAVE THIS ONE
KDB = .FST [ FSTKDB ]; ! SET UP PRIMARY
%([ DUMMY LOOP ])%
LOOP: BEGIN
%([ TRY TO LOCATE THE DATA RECORD ])%
IF ( SAVEDSTATUS =CALLFBYRFA ( BPT ( RECDESC ),
BPT ( DATABD ),
PCI ( FALSE ) )) IS FALSE
%([ COULD WE FIND IT? ])%
THEN LEAVE LOOP WITH .SAVEDSTATUS ;
%([ WE FOUND A RECORD. WE MUST SEE IF IT IS A DATA RECORD
OR AN RRV RECORD ])%
RECORDPTR = .RECDESC [ RDRECPTR ];
%([ STORE THE ADDRESS OF THE RRV IN THE RECORD DESCRIPTOR ])%
RECDESC [ RDRRV ] = .RECDESC [ RDRFA ]; ! GET RRV ADDRESS
IF RRVFLAG ( RECORDPTR ) IS OFF
THEN %(THIS IS THE DATA RECORD)%
LEAVE LOOP WITH ( SAVEDSTATUS = TRUE );
%([ THIS IS AN RRV RECORD. WE MUST GO ONE MORE LEVEL ])%
RTRACE (%STRING(' RRV RECORD FOUND...',%CHAR(13),%CHAR(10)));
RECDESC [ RDRFA ] = .RECORDPTR [ DRRRVADDRESS ];
MOVEBKTDESC ( %(FROM)% DATABD, %(TO)% RRVBD );
RECDESC [ RDRECPTR ] = ZERO; ! START AT TOP
SAVEDSTATUS = CALLFBYRFA ( BPT ( RECDESC ),
BPT ( DATABD ),
PCI ( FALSE ) );
%([ SAVE THE CURRENT STATUS ])%
%([ RELEASE THE RRV BUCKET, REGARDLESS OF WHETHER WE MADE
AN ERROR OR NOT ])%
CALLPUTBKT ( %(NO UDATE)% PCI ( FALSE ),
%(RRV BKT)% LCT ( RRVBD ) )
END; ! OF THE DUMMY LOOP
KDB = .SAVEDKDB;
RETURN .SAVEDSTATUS
END; %(OF FBYRRV)%
! SKIPRECORD
! ==========
! ROUTINE TO ADVANCE TO THE NEXT DATA RECORD ( UDR OR SIDR )
! IN AN INDEXED FILE. THIS ROUTINE WILL NOT SKIP OVER
! DELETED RECORDS BUT WILL IGNORE EMPTY BUCKETS AND
! RRV RECORDS.
! INPUT:
! RECDESC RECORD DESCRIPTOR PACKET
! RECPTR ADDRESS OF CURRENT RECORD
!
! DATABD BUCKET DESCRIPTOR OF DATA BUCKET
! LOCKFLAG FLAG FOR LOCKING OF BUCKET
! TRUE LOCK THE BUCKET
! FALSE DONT LOCK THE BUCKET
! OUTPUT:
! TRUE: NEXT RECORD FOUND
! FALSE: COULD NOT GET NEXT RECORD
! BUCKET BUSY (BUSY FLAG WILL BE SET)
! NO NEXT BUCKET (END OF CHAIN)
! NOTES:
! 1. THIS ROUTINE WILL UNLOCK EACH BUCKET
! THAT IT PROCESSES WHEN IT MOVES TO THE
! NEXT BUCKET. HOWEVER, IT WILL ALWAYS
! RETURN A VALID BUCKET (I.E., IT WILL NEVER
! RELEASE ALL BUCKETS).
!
! INPUT ARGS MODIFIED:
! RECORD DESCRIPTOR:
! RECPTR ADDRESS OF NEW RECORD
! LASTRECPTR SAME AS RECPTR ON INPUT
GLOBAL ROUTINE SKIPRECORD ( RECDESC, DATABD, LOCKFLAG ) =
BEGIN
ARGUMENT (RECDESC,BASEADD);
ARGUMENT (DATABD,BASEADD);
ARGUMENT (LOCKFLAG,REFERENCE);
MAP
RECDESC: POINTER,
DATABD: POINTER;
LABEL LOOP;
LOCAL
NEXTBD: FORMATS[ BDSIZE ], ! BKT DESC OF NEXT BKT IN CHAIN
ENDPTR: POINTER, ! PTR TO END OF BUCKET
BKTPTR: POINTER, ! PTR TO THIS BUCKET
DATARECORDPTR: POINTER; ! PTR TO DATA RECORD
REGISTER
MOVINGPTR: POINTER,
TEMPAC;
TRACE ('SKIPRECORD');
%([ FETCH THE BEGINNING POINTER ])%
RECDESC [ RDLASTRECPTR ] = ( MOVINGPTR = .RECDESC [ RDRECPTR ] );
%([ ADVANCE TO THE NEXT RECORD...BUT FIRST, SOME
RANDOM CONSISTENCY CHECKS ])%
%IF DBUG %THEN
IF ( RRVFLAG ( MOVINGPTR ) ISON )
THEN
RMSBUG ( MSGPTR );
%FI
%([ BUMP THE POINTER PAST THIS RECORD ])%
MOVINGPTR = .MOVINGPTR + SIZEOFDATARECRD ( MOVINGPTR );
%([ WE ARE NOW AT THE RECORD PAST THE ONE WE ENTERED
WITH. WE WILL DO THIS LOOP UNTIL ONE OF THE FOLLOWING:
1. END OF CHAIN IS FOUND
2. A DATA RECORD IS FOUND
3. NEXT BUCKET IS LOCKED
])%
LOOP: BEGIN
REPEAT
BEGIN
%([ GET THE ADDRESS OF CURRENT RECORD ])%
RECDESC [ RDRECPTR ] = .MOVINGPTR; ! STORE IN CASE THIS IS END OF BKT
RTRACE (%STRING(' STARTING ITERATION...',%CHAR(13),%CHAR(10)));
BKTPTR = .DATABD [ BKDBKTADR ];
ENDPTR = .BKTPTR + .BKTPTR [ BHNEXTBYTE ];
LOOKAT (' END OF BKT AT: ', ENDPTR );
LOOKAT (' MOVINGPTR: ', MOVINGPTR );
%([ **CONSISTENCY CHECK** ])%
IF ( ( .MOVINGPTR LEQ .BKTPTR )
OR
( .MOVINGPTR GTR .ENDPTR ) )
THEN RMSBUG ( MSGPTR );
%([ NOW, DO THE BIG CHECK. ARE WE NOT AT THE END,
AND IS THIS A DATA RECORD ? ])%
IF ( ( .MOVINGPTR LSS .ENDPTR )
AND
( RRVFLAG ( MOVINGPTR ) IS OFF ) )
THEN LEAVE LOOP; ! FOUND IT
%([ WE ARE EITHER AT THE END OF THE BUCKET, OR WE
ARE AT AN RRV. CHECK TO SEE IF THERE IS ANOUTHER
BUCKET IN THE CHAIN ])%
RTRACE (%STRING(' REACHED END OF BUCKET...',%CHAR(13),%CHAR(10)));
%([ IS THIS THE END OF THE CHAIN? ])%
IF CHKFLAG ( BKTPTR [ BHFLAGS ], BHFLGEND ) ISON
THEN %(END OF CHAIN)%
BEGIN
RTRACE (%STRING(' END OF CHAIN FOUND...',%CHAR(13),%CHAR(10)));
SETPASTLASTFLAG ( RECDESC );
RETURNSTATUS ( ER$EOF ) ! RETURN ERROR CODE
END; %(OF IF END OF CHAIN)%
%([ THERE IS ANOTHER BUCKET. WE MUST LOCK IT BEFORE
WE UNLOCK THIS ONE ])%
IF CALLGTNBKT (%(THIS BKT)% BPT ( DATABD ),
%(NEXT ONE)% LCT ( NEXTBD ),
%(LOCK)% RLCI ( LOCKFLAG ) ) IS FALSE
THEN
RETURN FALSE;
%([ WE CAN NOW UNLOCK THE CURRENT BUCKET SINCE
WE HAVE GOTTEN THE NEXT BUCKET ])%
CALLPUTBKT ( %(NO)% PCI ( FALSE ),
%(BKT)% BPT ( DATABD ) );
%([ MAKE THE NEXT BUCKET OUR CURRENT BUCKET ])%
MOVEBKTDESC ( %(FROM)% NEXTBD, %(TO)% DATABD );
%([ SET THE POINTER BACK TO THE START OF THIS
BUCKET ])%
MOVINGPTR = .DATABD [ BKDBKTADR ] + BHHDRSIZE
END;
END; %(OF REPEAT LOOP)%
%([ AT THIS POINT, WE HAVE REACHED A DATA RECORD. WE NOW MUST
COMPARE THE KEY OF THIS RECORD TO THE SEARCH KEY SO AS
TO SET THE COMPARISON BITS. ALSO, WE NEED TO SET THE
DELETED FLAG IF THIS RECORD IS DELETED. ])%
%([ SET OR CLEAR THE DELETED FLAG ])%
TEMPAC = .RECDESC [ RDSTATUS ];
CLRFLAG ( TEMPAC, RDFLGDELETE );
IF ( CHKFLAG ( MOVINGPTR [ DRFLAGS ], FLGDELETE ) ISON )
THEN
SETFLAG (TEMPAC, RDFLGDELETE );
RECDESC [ RDSTATUS ] = .TEMPAC;
%([ MOVE THE RFA OF THIS RECORD INTO THE RECORD DESCRIPTOR ])%
RECDESC [ RDRFA ] = MAKERFA ( .DATABD [ BKDBKTNO ], .MOVINGPTR [ DRRECORDID ] );
%([ COMPARE THE KEYS ])%
DATARECORDPTR = .MOVINGPTR + .KDB [ KDBHSZ ]; ! USE LOCAL TO PASS IT
IF .KDB [ KDBREF ] IS REFPRIMARY
THEN
CALLCKEYKU ( %(SEARCH KEY)% BPT ( RECDESC ),
%(TARGET)% LPT ( DATARECORDPTR ) )
ELSE %(THIS IS A SECONDARY RECORD)%
CALLCKEYKK ( %(SEARCH KEY)% BPT ( RECDESC ),
%(TARGET)% LPT ( DATARECORDPTR ) );
GOODRETURN
END; %(OF SKIRECORD)%
END
ELUDOM