Trailing-Edge
-
PDP-10 Archives
-
BB-JF18A-BM
-
sources/rms/rmsudm.b36
There are 6 other files named rmsudm.b36 in the archive. Click here to see a list.
%TITLE 'U D 2 -- RMSUDR utilities'
!<BLF/REQUIRE 'RMSBLF.REQ'>
MODULE ud2 (IDENT = '2.0'
) =
BEGIN
GLOBAL BIND
ud2v = 2^24 + 0^18 + 400; ! Edit date: 22-Apr-83
!+
!
!
! PURPOSE: UTILITIES FOR RMSUDR.
!
!
! COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1977, 1986.
! ALL RIGHTS RESERVED.
!
! THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND
! COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH
! THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR
! ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE
! AVAILABLE TO ANY OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE
! SOFTWARE IS HEREBY TRANSFERRED.
!
! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT
! NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL
! EQUIPMENT CORPORATION.
!
! DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF
! ITS SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
!
!
!
! 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 *
! * *
! *************************************************
!
! PRODUCT MODULE SPR
! EDIT EDIT QAR DESCRIPTION
! ====== ====== ===== ===========
!
! ** Begin RMS v2 Development **
!
! 400 400 xxxxx Clean up BLISS code (RL,22-Apr-83)
!
! ***** END OF REVISION HISTORY *****
!
!
!
!
!-
REQUIRE 'rmsreq';
%SBTTL 'ALCRFA - Allocate new RFA'
GLOBAL ROUTINE alcrfa (bktdesc) =
! 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)
!
BEGIN
REGISTER
newrfa : BLOCK [1], ! THE RFA OF RECORD
bktptr : REF BLOCK,
tempac;
MAP
bktdesc : REF BLOCK;
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 ! Garbage collect on the IDs
BEGIN
rtrace (%STRING ('** No ID found in bucket', !
%CHAR (13), %CHAR (10)));
IF (newrfa<lh> = shuffleids (.bktdesc)) EQL false ! LH stands for RFAID
THEN
RETURN false
END;
!+
! WE NOW HAVE OUR ID
!-
lookat (' NEW RFA FOR RECORD: ', newrfa);
RETURN .newrfa
END; ! End ALCRFA
%SBTTL 'SHUFFLEIDS - coalesce unused IDs'
GLOBAL ROUTINE shuffleids (bktdesc) =
! 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 COALESCE 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>
!
BEGIN
MAP
bktdesc : REF BLOCK;
LITERAL
minholesize = 2; ! HOLE MUST BE THIS BIG
REGISTER
lowid, ! CURRENT BASE LEVEL ID
tempac, ! TEMP
movingptr : REF BLOCK; ! USED TO SCAN THE BUCKET
LOCAL
bktptr : REF BLOCK, ! PTR TO TOP OF BUCKET
highid, ! CURRENT TOP OF HOLE ID
currentid, ! ID OF CURRENT RECORD
endptr : REF BLOCK, ! PTR TO END OF BUCKET
fixedptr : REF BLOCK; ! PTR TO CURRENT "LOWID" RECORD
TRACE ('SHUFFLEIDS');
!+
! 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 = 0; ! 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
! Find 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;
!+
! 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;
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;
rmsbug (msgcantgethere);
0
END; ! End SHUFFLEIDS
%SBTTL 'FBYRFA - find record using RFA'
GLOBAL ROUTINE fbyrfa (recdesc, bktdesc, p_lockflag) =
! 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.
BEGIN
BIND
lockflag = .p_lockflag;
LOCAL
bktno, ! A BUCKET NUMBER
bktsize, ! A BUCKET SIZE
rfa : BLOCK [1]; ! AN RFA
MAP
recdesc : REF BLOCK,
bktdesc : REF BLOCK;
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 getbkt (.bktno, ! Bucket number
.bktsize, ! Bucket size
.lockflag, ! Lock flag
.bktdesc) EQL false ! Bucket
THEN
RETURN false;
lookat (' GOT BKT: ', bktno);
!+
! FIND THE RECORD(RFA) IN THE BUCKET
!-
lookat (' START SEARCH AT: ', recdesc [rdrecptr]);
IF sdatabkt (.recdesc, .bktdesc) EQL false
THEN
BEGIN ! Return bucket if search fails
putbkt (false, .bktdesc);
RETURN false
END;
lookat (' FOUND RECORD AT: ', recdesc [rdrecptr]);
!+
! DONE
!-
RETURN true
END; ! End FBYRFA
%SBTTL 'FBYRRV - find record using RRV'
GLOBAL ROUTINE fbyrrv (recdesc, databd) =
! 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.
BEGIN
MAP
recdesc : REF BLOCK,
databd : REF BLOCK;
LOCAL
rrvbd : BLOCK [bdsize],
savedkdb, ! SAVE THE KDB ON ENTRANCE
savedstatus; ! WE MUST REMEMBER THE STATUS
LABEL
loop; ! USE A LOOP TO JUMP OUT OF
REGISTER
recordptr : REF BLOCK;
TRACE ('FBYRRV');
lookat (' TRYING TO FIND RRV: ', recdesc [rdrfa]);
!+
! INSURE THAT THE SEARCH WILL START AT TOP OF BUCKET
!-
recdesc [rdrecptr] = 0;
!+
! 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 = fbyrfa (.recdesc, .databd, false)) EQL 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) EQL 0
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 (databd, rrvbd);
recdesc [rdrecptr] = 0; ! START AT TOP
savedstatus = fbyrfa (.recdesc, .databd, false);
!+
! SAVE THE CURRENT STATUS
!-
!+
! RELEASE THE RRV BUCKET, REGARDLESS OF WHETHER WE MADE
! AN ERROR OR NOT
!-
putbkt (false, ! No update
rrvbd) ! RRV bucket
END; ! OF THE DUMMY LOOP
kdb = .savedkdb;
RETURN .savedstatus
END; ! End FBYRRV
%SBTTL 'SKIPRECORD - get next data record'
GLOBAL ROUTINE skiprecord (recdesc, databd, p_lockflag) =
! 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
BEGIN
BIND
lockflag = .p_lockflag;
MAP
recdesc : REF BLOCK,
databd : REF BLOCK;
LABEL
loop;
LOCAL
nextbd : BLOCK [bdsize], ! BKT DESC OF NEXT BKT IN CHAIN
endptr : REF BLOCK, ! PTR TO END OF BUCKET
bktptr : REF BLOCK, ! PTR TO THIS BUCKET
datarecordptr : REF BLOCK; ! PTR TO DATA RECORD
REGISTER
movingptr : REF BLOCK,
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) NEQ 0) 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) EQL 0)) 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) NEQ 0
THEN ! End of chain
BEGIN
rtrace (%STRING (' End of chain found...', !
%CHAR (13), %CHAR (10)));
setpastlastflag (recdesc);
returnstatus (er$eof) ! RETURN ERROR CODE
END;
!+
! THERE IS ANOTHER BUCKET. WE MUST LOCK IT BEFORE
! WE UNLOCK THIS ONE
!-
IF gtnbkt (.databd, ! This bucket
nextbd, ! Next one
.lockflag) EQL false ! Lock
THEN
RETURN false;
!+
! WE CAN NOW UNLOCK THE CURRENT BUCKET SINCE
! WE HAVE GOTTEN THE NEXT BUCKET
!-
putbkt (false, .databd);
!+
! MAKE THE NEXT BUCKET OUR CURRENT BUCKET
!-
movebktdesc (nextbd, 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) NEQ 0) 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] EQL refprimary
THEN
ckeyku (.recdesc, ! Search key
.datarecordptr) ! Target
ELSE ! This is a secondary record
ckeykk (.recdesc, ! Search key
.datarecordptr); ! Target
RETURN true
END; ! End SKIPRECORD
END
ELUDOM