Trailing-Edge
-
PDP-10 Archives
-
704rmsf2
-
10,7/rms10/rmssrc/rmssdr.b36
There are 6 other files named rmssdr.b36 in the archive. Click here to see a list.
MODULE SDR =
BEGIN
GLOBAL BIND SDRV = 1^24 + 0^18 + 9; !EDIT DATE: 3-APR-78
%([
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 /EGM
THIS MODULE CONTAINS ALL ROUTINES WHICH DEAL PRIMARILY
WITH SECONDARY DATA RECORDS. SEVERAL OTHER ROUTINES
THROUGHOUT RMS-20 ALSO PROCESS SECONDARY RECORDS (CALLED
"SIDR" RECORDS ) BUT THESE ROUTINES PROCESS ONLY THESE
DATA RECORDS.
********** TABLE OF CONTENTS **************
ROUTINE FUNCTION
======= ========
MAKESIDR CREATE A SECONDARY DATA RECORD
BLDCSIDR BUILD A CONTINUATION SIDR
DOSIDR PROCESS THE SIDR INSERTION
INSRTSIDR OUTER-LEVEL SIDR INSERTION ROUTINE
BLDISIDR BUILD AN INITIAL SIDR
DELSIDR DELETE A SIDR RECORD
SQUEEZESIDR SQUEEZE ONE SIDR RECORD FROM BUCKET
PUTSIDR INSERT CURRENT RECORD INTO SECONDARY INDEX
REVISION HISTORY:
PRODUCT LOCAL
EDIT EDIT DATE WHO PURPOSE
==== ==== ==== === =======
- 1 11-OCT-76 SB ADD DELSIDR
- 2 28-OCT-76 SB FIX BUG IN MOVEDOWN ARG IN DOSIDR
- 3 7-NOV-76 SB ADD DELETED RFA BIT
- 4 9-DEC-76 SB FIX BUG SO THAT IF ALL
SIDR RECORDS ARE MOVED OUT
OF THE BUCKET ON A SPLIT, THE
NEW HIGH-KE IS OF R-NEW
- 5 8-MAR-77 SB TAKE OUR CHECK FOR SIDR ALREADY DELETED
- 6 3-MAY-77 SB ADD FIX FOR SIDRELEMENT FIELD
6 7 26-JAN-78 SB IF SIDR BKT IS FULL, FREESPACE
WAS NEGATIVE, CHECK WAS BAD
*************************************************
* *
* NEW REVISION HISTORY *
* *
*************************************************
PRODUCT MODULE SPR
EDIT EDIT QAR DESCRIPTION
====== ====== ===== ===========
12 8 11439 RST KEY BUFFER IS NOT BEING UPDATED WHEN A SIDR
BUCKET SPLITS. THIS CAUSES THE ALTERNATE KEY ROOT
BUCKET TO BE UPDATED INCORRECTLY, SOMETIMES WITH
KEY VALUES FROM OTHER INDEX LEVELS (SUCH AS PRIMARY).
THE END RESULT IS THAT A VALID GET/FIND LOSES.
MAKE SURE THE LAST KEY FROM THE ORIGINAL BUCKET IS
COPIED TO THE RST KEY BUFFER AFTER A SPLIT OCCURS.
ALSO - FIX AN OFF BY 1 BUG (END POINTER) WHICH
GARBAGES THE CURRENT AND FOLLOWING SIDR AFTER SPLIT
MOVES THE CURRENT SIDR TO A NEW BUCKET.
****************** Start RMS-10 V1.1 *********************
********************* TOPS-10 ONLY ***********************
PRODUCT MODULE SPR
EDIT EDIT QAR DESCRIPTION
====== ====== ===== ===========
100 9 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 BLDISIDR,
DELSIDR;
%([ EXTERNAL DECLARATIONS ])%
EXTERNAL ROUTINE
ALCBKT, ! ALLOCATE A NEW BUCKET
CRASH, ! FOR DEBUGGING
FNDDATA, ! FIND SIDR BUCKET ON LEVEL 0
FNDREC, ! LOCATE DATA RECORD
ALCNEWIDS, ! ASSIGN NEW ID'S TO SIDRS
PUTBKT, ! WRITE OUT A FIL BUCKET
SPLIT, ! SPLIT A DATA BUCKET
ALCRFA, ! ALLOCATE A RECORD ADDRESS
DUMP, ! SAME
MOVEKEY; ! MOVE A KEY STRING
%([ ERROR MESSAGES REFERENCED IN THIS MODULE ])%
EXTERNAL
MSGFLAGS, ! BAD FLAG VALUES
MSGNOCALL, ! ROUTINE SHOULD NOT HAVE BEEN CALED
MSGRFA, ! BAD RFA VALUE FOUND IN SIDR
MSGSPLIT, ! BAD SPLIT PARAMETERS
MSGFAILURE, ! A ROUTINE FAILED
MSGCOUNT, ! BAD COUNT VALUE
MSGINPUT, ! BAD INPUT VALUES
MSGPTR; ! BAD PTR VALUE
REQUIRE 'RMSREQ';
EXTDECLARATIONS;
! MAKESIDR
! ========
! ROUTINE TO CREATE A SECONDARY INDEX DATA RECORD (SIDR).
! THIS ROUTINE ASSUME THAT THE CORRECT POSITION TO
! CREATE THE RECORD HAS BEEN FOUND. NO ADJUSTMENT
! OF THE BUCKET HEADER INFO, NOR ANY INDEX UPDATES
! ARE DONE WITHIN THIS ROUTINE.
! THE RFA FOR THE SIDR MUST BE ALLOCATED BEFORE THIS
! ROUTNE IS CALLED
! INPUT:
! RECDESC RECORD DESCRIPTOR PACKET
! RFA RFA OF SIDR RECORD
! RRV RECORD POINTER TO INSERT INTO SIDR
! USERPTR ADDRESS OF SEARCH KEY STRING
!
! SIDRPTR ADDRESS TO WRITE RECORD
! OUTPUT:
! <NO STATUS RETURNED>
! INPUT ARGS MODIFIED:
! RECORD DESCRIPTOR:
! <NONE>
! ROUTINES CALLED:
! <NONE>
GLOBAL ROUTINE MAKESIDR ( RECDESC, SIDRPTR ): NOVALUE =
BEGIN
ARGUMENT (RECDESC,BASEADD);
ARGUMENT (SIDRPTR,BASEADD);
MAP
RECDESC: POINTER,
SIDRPTR: POINTER;
REGISTER
KEYSIZEINWORDS; ! SIZE OF KEY STRING
TRACE ('MAKESIDR');
%([ STORE THE FLAGS AND THE ID OF THE SIDR ])%
KEYSIZEINWORDS = .KDB [ KDBKSZW ]; ! GET THIS NOW
SIDRPTR [ DRFLAGS ] = DEFSIDRFLAGS;
SIDRPTR [ DRRECORDID ] = IDOFRFA ( .RECDESC [ RDRFA ] );
SIDRPTR [ SIDRRECSIZE ] = .KEYSIZEINWORDS + 1; ! KEY + 1 PTR
SIDRPTR [ SIDRDUPCOUNT ] = ZERO; ! FOR FUTURE
INC ( SIDRPTR, SIDRHDRSIZE );
%([ MOVE THE KEY STRING INTO THE RECORD ])%
MOVEWORDS ( %(FROM)% .RECDESC [ RDUSERPTR ],
%(TO)% .SIDRPTR,
%(SIZE)% .KEYSIZEINWORDS );
%([ BUMP PTR PAST THE DATA PORTION ])%
INC ( SIDRPTR, .KEYSIZEINWORDS );
SIDRPTR [ WHOLEWORD ] = .RECDESC [ RDRRV ]; ! STORE PTR
RETURN
END; %(OF MAKESIDR)%
! BLDCSIDR
! ========
! ROUTINE TO BUILD A CONTINUATION SECONDARY INDEX DATA RECORD (SIDR)
! THIS ROUTINE IS CALLED WHEN THE CURRENT BUCKET BECOMES FILLED
! WITH OTHER RECORDS (MAYBE DUPLICATES OF THIS KEY VALUE), AND
! A NEW SIDR IS NEEDED. THIS SIDR IS ALLOCATED IN ITS OWN
! BUCKET WHICH IS THEN <NOT> ENTERED INTO THE INDEX STRUCTURE.
! THIS MEANS THAT THE INDEX WILL CONTAIN ONE INDEX RECORD
! WHICH REPRESENTS MORE THAN ONE DATA BUCKET...NAMELY ALL
! THOSE BUCKETS WHICH CONTAIN A SINGLE CONTINUATION SIDR
! FOR THIS KEY. THUS, ONCE A CONTINUATION SIDR HAS BEEN
! BUILT IN A PARTICULAR BUCKET, NO OTHER RECORDS ARE
! ENTERED INTO THE BUCKET. THAT SIDR WILL CONTINUE TO GROW
! UNTIL IT FILLS THE BUCKET...AT WHICH TIME A NEW CONTINUATION
! SIDR IS BUILT IN A NEW BUCKET.
!
! THIS ROUTINE DOES THE FOLLOWING:
!
! 1. ALLOCATE A NEW BUCKET TO USE
! 2. LINK IT INTO THE BUCKET CHAIN
! 3. BUILD A NEW SIDR AT THE TOP OF IT.
!
! NOTES:
!
! 1. A CONTINUATION SIDR LOOKS JUST LIKE THE INITIAL SIDR.
! IF DUP COUNTS ARE EVER SUPPORTED, THAT FIELD IN THE
! CONTINUATION SIDR CAN BE USED FOR SOME OTHER PURPOSE
! SINCE THE DUP COUNT IS NEEDED ONLY IN THE INITIAL
! SIDR RECORD.
!
! 2. THE COUNT FIELD IN THE RECORD DESC. IS NOT ALTERED
! HERE, SO IF A SIDR BUCKET IS SPLITTING, WHOEVER CALLS
! THIS ROUTINE MUST UPDATE THE COUNT FIELD.
! INPUT:
! RECDESC RECORD DESCRIPTOR PACKET
! RRV RECORD POINTER TO USE
! RECPTR <IGNORED>
!
! SIDRBD BUCKET DESCRIPTOR OF SIDR BUCKET (OLD BUCKET)
! NEWBD BUCKET DESCRIPTOR OF NEW BUCKET (RETURNED)
! OUTPUT:
! TRUE: OK, SIDR CREATED
! FALSE: ERROR
! NO MORE BUCKET LEFT
! BUCKET BUSY
! ROUTNES CALLED:
! ALCBKT
! MAKESIDR
GLOBAL ROUTINE BLDCSIDR ( RECDESC, SIDRBD, NEWBD ) =
BEGIN
ARGUMENT (RECDESC,BASEADD);
ARGUMENT (SIDRBD,BASEADD);
ARGUMENT (NEWBD,BASEADD);
MAP
RECDESC: POINTER,
SIDRBD: POINTER,
NEWBD: POINTER;
LOCAL
BKTSIZE, ! SIZE OF THIS BUCKET
THISLEVEL, ! LEVEL OF THIS BUCKET
NEWFLAGS, ! FLAGS FOR NEW BUCKET
TPTR: POINTER;
REGISTER
OLDBKTPTR: POINTER, ! PTR TO OLD SIDR BUCKET
NEWBKTPTR: POINTER;
TRACE ('BLDCSIDR');
OLDBKTPTR = .SIDRBD [ BKDBKTADR ]; ! GET SOME POINTERS
NEWFLAGS = .OLDBKTPTR [ BHFLAGS ] AND BHFLGEND; ! SAVE END BIT
%([ ALLOCATE A NEW BUCKET ])%
IF CALLALCBKT (%(TYPE)% PCI ( BTYPEDATA ),
%(FLAGS)% LCI ( NEWFLAGS ),
%(LEVEL)% PCI ( DATALEVEL ),
%(BD)% BPT ( NEWBD ) ) IS FALSE
THEN
RETURN FALSE;
%([ WE NOW HAVE A BUCKET. FIRST, WE MUST CLEAR THE END
BIT OF THE OLD BUCKET ])%
CLRFLAG ( OLDBKTPTR [ BHFLAGS ], BHFLGEND );
%([ LINK THIS BUCKET INTO THE CHAIN ])%
NEWBKTPTR = .NEWBD [ BKDBKTADR ];
NEWBKTPTR [ BHNEXTBKT ] = .OLDBKTPTR [ BHNEXTBKT ]; ! MOVE VALUE OVER
OLDBKTPTR [ BHNEXTBKT ] = .NEWBD [ BKDBKTNO ]; ! LINK TO LAST ONE
%([ NOW, CREATE A NEW SIDR RECORD AT THE TOP OF THE BUCKET ])%
TPTR = .NEWBKTPTR + BHHDRSIZE; ! STORE IN LOCAL
RECDESC [ RDRECPTR ] = .TPTR; ! RETURN IT TO CALLER
%([ ALLOCATE RFA FOR SIDR RECORD ])%
RECDESC [ RDRFA ] = CALLALCRFA ( BPT ( NEWBD ) );
CALLMAKESIDR ( %(RD)% BPT ( RECDESC ),
%(PTR)% LPT ( TPTR ) );
%([ BUMP THE BUCKET HEADER DATA ])%
INC ( NEWBKTPTR [ BHNEXTBYTE ], SIDRHDRSIZE + .KDB [ KDBKSZW ] + 1 );
GOODRETURN
END; %(OF BLDCSIDR)%
! DOSIDR
! ======
! ROUTINE TO PERFORM THE ACTUAL INSERTION OF A SIDR RECORD.
! THIS ROUTINE DETERMINES WHETHER THE INSERTION WILL
! CAUSE THE CREATION OF A BRAND NEW SIDR RECORD, A
! CONTINUATION RECORD (DUPS ALLOWED ONLY), OR JUST
! THE ADDITION OF A RECORD POINTER THE THE END OF AN
! EXISTING SIDR ARRAY.
!
! NO INDEX MODIFICATION OR FILE BUCKET UPDATING IS DONE
! WITHIN THIS ROUTINE
! INPUT:
! RECDESC RECORD DESCRIPTOR PACKET
! RRV RECORD POINTER TO INSERT INTO SIDR
! RECPTR ADDRESS OF SEARCH TERMINATION
! (I.E., 1ST RECORD WITH KEY > K(S) )
! LASTRECPTR RECORD BEFORE SEARCH TERMINATION RECORD
!
! SIDRBD BUCKET DESCRIPTOR OF CURRENT SIDR BUCKET
! SPLITBD BUCKET DESCRIPTOR OF EXTRA BUCKET (RETURNED)
! OUTPUT:
! TRUE: OK, SIDR IS INSERTED
! FALSE: ERROR
! NO MORE BUCKETS
! BUCKET BUSY
! INPUT ARGS MODIFIED:
! RECORD DESCRIPTOR:
! RECPTR ADDRESS OF THE SIDR RECORD
! SIDRELEMENT OFFSET INTO SIDR OF CURRENT RECORD POINTER
!
! NOTES:
!
! 1. IF NO DUP RECORDS WERE SEEN, THEN RECPTR POINTS TO
! THE PLACE WHERE WE NEED TO INSERT THE NEW SIDR
! RECORD. IF DUPS WERE SEEN, THEN RECPTR POINTS TO
![12] THE FINAL DUPLICATE SIDR ARRAY (INCLUDING CONTINUATIONS),
![12] AND LASTRECPTR HAS BEEN RESET TO POINT TO THE PREVIOUS SIDR.
GLOBAL ROUTINE DOSIDR ( RECDESC, SIDRBD, SPLITBD ) =
BEGIN
ARGUMENT (RECDESC,BASEADD);
ARGUMENT (SIDRBD,BASEADD);
ARGUMENT (SPLITBD,BASEADD);
MAP
RECDESC: POINTER,
SIDRBD: POINTER,
SPLITBD: POINTER;
LABEL LOOP;
REGISTER
SIDRPTR: POINTER, ! PTR TO CURRENT SIDR
TPTR: POINTER, ! TEMP POINTER
TEMPAC; ! TEMP AC
LOCAL
TOPOFBKTPTR: POINTER, ! PTR TO TOP OF CURRENT BUCKET
ENDBKTPTR: POINTER, ! PTR TO END OF CURRENT BUCKET
DATAPTR: POINTER, ! PTR TO DATA PORTION OF SIDR
FREESPACE, ! AMOUNT OF SPACE LEFT IN THIS BUCKET
DUMMYBD: FORMATS[ BDSIZE ], ! DUMMY BKT DESC USED FOR SPLIT
KEYSIZEINWORDS, ! SAME AS IN KDB
savestatus, ! **B36. TO SAVE STATUS OF A ROUTINE
!** [12] ROUTINE:DOSIDR AT LINE 6976, EGM, 3-APR-78
%([12])% ENDOFSIDRPTR: POINTER, ! PTR TO EN OF CURRENT SIDR
%([12])% KEYBUFFPTR: POINTER; ! PTR TO RST KEY BUFFER
TRACE ('DOSIDR');
CHECKEXACTCOUNT;
%([ SET UP SOME BUCKET POINTERS ])%
TOPOFBKTPTR = .SIDRBD [ BKDBKTADR ];
FREESPACE = ( .KDB [ KDBDBKZ ] ^ B2W ) - ( ENDBKTPTR =
.TOPOFBKTPTR [ BHNEXTBYTE ] );
LOOKAT (' FREE-SPACE: ', FREESPACE );
INC ( ENDBKTPTR, .TOPOFBKTPTR ); ! FORM ABS PTR TO END
%([ DID WE SEE A DUPLICATE RECORD? IF SO, THEN WE NEED
TO TRY TO ADD ONE MORE POINTER TO THE ARRAY. IF NOT,
WE MUST CREATE AN ENTIRELY NEW SIDR RECORD ])%
IF DUPLICATEFLAG ( RECDESC ) IS OFF
THEN %(THIS IS THE FIRST INSERT OF THIS KEY)%
BEGIN
%([ INDICATE THAT THE CURRENT POINTER IS FIRST IN ARRAY ])%
RECDESC [ RDSIDRELEMENT ] = 1;
RETURN CALLBLDISIDR ( %(RD)% BPT ( RECDESC ),
%(BD)% BPT ( SIDRBD ),
%(SPLIT)% BPT ( SPLITBD ) )
END; %(OF IF NO DUP WAS SEEN)%
%([ WE HAVE ALREADY PROCESSED A DUP OF THIS KEY VALUE ])%
%IF DBUG %THEN
IF ( CHKFLAG ( KDB [ KDBFLAGS ], FLGDUP ) IS OFF ) THEN RMSBUG ( MSGFLAGS );
%FI
!** [12] ROUTINE:DOSIDR AT LINE 7013, EGM, 3-APR-78
%([12])% SIDRPTR = .RECDESC [ RDRECPTR ]; ! GET ADDRESS OF LAST SIDR
LOOKAT (' CURRENT SIDR REC IS AT: ', SIDRPTR );
%([ CHECK THAT IT IS IN THE CURRENT BUCKET ])%
IF ( ( .SIDRPTR LEQ .TOPOFBKTPTR )
OR
( .SIDRPTR GTR .ENDBKTPTR ) ) THEN RMSBUG ( MSGPTR );
%([ UNLESS THIS BUCKET IS COMPLETELY FILLED, WE CAN ALWAYS
FIT ONE MORE RECORD POINTER INTO THE ARRAY. THEREFORE,
WE MUST DETERMINE IF THE BUCKET IS FULL AND IF NOT,
WE WILL MORE THE BOTTOM DOWN AND INSERT THE RECORD
POINTER. IF SO, WE MUST EITHER SPLIT THE BUCKET OR
CREATE A CONTINUATION SIDR ])%
KEYSIZEINWORDS = .KDB [ KDBKSZW ]; ! MAKE THIS HANDY
DATAPTR = .SIDRPTR + SIDRHDRSIZE; ! GET PTR TO DATA PORTION OF SIDR
ENDOFSIDRPTR = .DATAPTR + .SIDRPTR [ SIDRRECSIZE ] -1;
%([ COMPUTE THE OFFSET INTO THE SIDR OF THE CURRENT POINTER ])%
RECDESC [ RDSIDRELEMENT ] = .ENDOFSIDRPTR - .DATAPTR -.KEYSIZEINWORDS + 1;
IF .FREESPACE LEQ ZERO !**[6]**MAY BE NEGATIVE IF COMPLETELY FULL
THEN %(THE BUCKET IS COMPLETELY FULL)%
BEGIN
RTRACE (%STRING(' BKT IS FULL...',%CHAR(13),%CHAR(10)));
%([ WE CAN'T FIT THE NEW SIDR IN THE BUCKET, SO
WE MUST SPLIT. HOWEVER, IF THIS ARRAY IS
THE LAST RECORD IN THE BUCKET, THEN WE
DON'T WANT TO SPLIT THE BUCKETS EVENLY
BECAUSE THAT WOULD UNNECESSARILY DISTRIBUTE
DUP RECORDS ACROSS BUCKETS. WHAT WE NEED TO
DO IS TO BUILD A CONTINUATION RECORD IN A
NEW BUCKET BY ITSELF. THEN, IT WILL GROW
UNTIL IT FILLS UP THAT BUCKET, THEN ANOTHER
CONTINUATION WILL BE ALLOCATED, ETC. ])%
IF ( .ENDOFSIDRPTR + 1 ) IS .ENDBKTPTR
THEN %(WE NEED A CONTINUATION RECORD)%
BEGIN
RTRACE (%STRING(' BUILDING CONT. RECORD',%CHAR(13),%CHAR(10)));
SAVESTATUS = CALLBLDCSIDR (BPT ( RECDESC ),
BPT ( SIDRBD ),
BPT ( SPLITBD ) );
%([ WE MUST INSURE THAT THE CONTINUATION SIDR
GETS WRITTEN OUT, BUT IT SHOULD NOT BE
ENTERED INTO THE INDEX. ])%
RECDESC [ RDCOUNT ] = 1; ! BKT WILL BE UPDATED
RETURN .SAVESTATUS
END; %(OF IF THIS IS LAST SIDR IN BUCKET)%
RECDESC [ RDLENGTH ] = ZERO; ! JUST SPLIT, DONT INSERT
%([ SPLIT THE SIDR BUCKET ])%
IF CALLSPLIT ( BPT ( RECDESC ),
BPT ( SIDRBD ),
BPT ( SPLITBD ),
LCT ( DUMMYBD ) ) IS FALSE
THEN
RETURN FALSE;
%([ WE NOW MUST ASSIGN NEW ID'S FOR ALL THE SIDR
RECORDS WHICH MOVED TO THE NEW BUCKET. ])%
CALLALCNEWIDS ( %(NEW BKT)% BPT ( SPLITBD ) );
%([ CHECK TO SEE IF THE SIDR MOVED TO THE NEW
BUCKET ])%
%([ NOW, THE SIDR IS EITHER IN THE CURRENT BUCKET
OR IT WAS MOVED TO THE TOP OF THE NEXT BUCKET.
THIS IS TRUE BECAUSE THE SPLIT ALGORITHM ALWAYS
TRIES TO KEEP R-NEW ON THE CURRENT BUCKET AND
SINCE THE SIZE OF R-NEW WAS ZERO, THIS WILL ALWAYS
BE TRUE. SO, WE MUST CHECK RECPTR AND IF IT POINTS
TO THE END OF THIS BUCKET, THEN WE KNOW THE SIDR
IS REALLY AT THE TOP OF THE NEXT BUCKET. ])%
IF ( .SIDRPTR - .TOPOFBKTPTR ) IS ( .TOPOFBKTPTR [ BHNEXTBYTE ] )
THEN %(THE SIDR HAS MOVED TO TOP OF NEXT BUCKET)%
BEGIN
SIDRPTR = .SPLITBD [ BKDBKTADR ] + BHHDRSIZE;
RTRACE (%STRING(' SIDR MOVED TO NEW BKT',%CHAR(13),%CHAR(10)));
TOPOFBKTPTR = .SPLITBD [ BKDBKTADR ];
!** [12] ROUTINE:DOSIDR AT LINE 7106, EGM, 3-APR-78
%([12])% ENDOFSIDRPTR = .SIDRPTR + SIDRHDRSIZE
%([12])% + .SIDRPTR [ SIDRRECSIZE ] - 1
%([12])% END; %(OF IF SIDR MOVED)%
%([12])%
%([12])% %([ RDLASTRECPTR NOW POINTS TO THE LAST SIDR ARRAY )%
%([12])% %( IN THE ORIGINAL BUCKET, HAVING BEEN RESET )%
%([12])% %( BY SPLIT (SIDR IN OLD) OR LEFT AS RECIEVED FROM )%
%([12])% %( PUTSIDR (SIDR IN NEW). )%
%([12])% %( MOVE THIS NEW HIGH KEY VALUE INTO THE RST )%
%([12])% %( KEY BUFFER. ])%
%([12])%
%([12])% TPTR = .RECDESC [ RDLASTRECPTR ] + SIDRHDRSIZE;
%([12])% KEYBUFFPTR = .RST [ RSTKEYBUFF ] + ( .FST [ FSTKBFSIZE ] / 2 );
%([12])% MOVEWORDS ( %(FROM)% .TPTR,
%([12])% %(TO)% .KEYBUFFPTR,
%([12])% %(SIZE)% .KDB [ KDBKSZW ] )
END; %(OF IF BUCKET IS FULL)%
%([ RE-COMPUTE THE ENDOF THIS BUCKET DATA ])%
ENDBKTPTR = .TOPOFBKTPTR + .TOPOFBKTPTR [ BHNEXTBYTE ];
%([ MOVE THE DATA DOWN IN THE BUCKET ])%
TEMPAC = .ENDBKTPTR - .ENDOFSIDRPTR - 1; ! COMPUTE HOW MUCH TO MOVE
IF .TEMPAC ISNT ZERO
THEN %(WE NEED TO MOVE SOME DATA DOWN)%
BEGIN
MOVEDOWN ( %(START)% (.ENDOFSIDRPTR + 1),
%(END)% .ENDBKTPTR -1,
%(SIZE)% 1 )
END; %(OF IF WE NEED TO MOVE DATA)%
%([ BUMP THE END-OF-BUCKET INDICATOR ])%
INC ( TOPOFBKTPTR [ BHNEXTBYTE ], 1);
%([ STORE THE NEW RECORD POINTER ])%
ENDOFSIDRPTR [ 1, WRD ] = .RECDESC [ RDRRV ];
%([ BUMP THE SIZE OF THIS SIDR RECORD ])%
INC ( SIDRPTR [ SIDRRECSIZE ], 1 );
%([ RESET RECPTR TO POINT TO THE LOCATION OF THE SIDR ])%
RECDESC [ RDRECPTR ] = .SIDRPTR;
GOODRETURN
END; %(OF DOSIDR)%
! INSRTSIDR
! =========
! ROUTINE TO INSERT A SECONDARY DATA RECORD (SIDR).
! THIS ROUTINE ACTUALLY IS THE OUTER-LEVEL ROUTINE
! WHICH GUIDES THE INSERTION OF THE SIDR. IT PERFORMS
! NO DATA MANIPULATION OR RECORD CREATION. SUCH
! ACTIONS ARE DONE BY "DOSIDR". THIS ROUTINE SIMPLY
! CALLS DOSIDR AND THEN UPDATES ANY FILE PAGES
! WHICH NEED TO BE WRITTEN TO THE FILE.
! INPUT:
! RECDESC RECORD DESCRIPTOR PACKET
! RRV RECORD POINTER TO INSERT INTO SIDR
! RECPTR ADDRESS OF SEARCH TERMINATION
! (I.E., 1ST RECORD WITH K > K(S) )
! LASTRECPTR RECORD BEFORE SEARCH TERMINATION RECORD
!
! SIDRBD BUCKET DESCRIPTOR OF CURRENT SIDR BUCKET
! SPLITBD BUCKET DESCRIPTOR OF EXTRA BUCKET (RETURNED)
! OUTPUT:
! TRUE: SIDR RECORD INSERTED PROPERLY AND FILE UPDATED
! FALSE: ERROR
! NO MORE BUCKETS
! ROUTINES CALLED:
! DOSIDR
GLOBAL ROUTINE INSRTSIDR ( RECDESC, SIDRBD, SPLITBD ) =
BEGIN
ARGUMENT (RECDESC,BASEADD);
ARGUMENT (SIDRBD,BASEADD);
ARGUMENT (SPLITBD,BASEADD);
MAP
RECDESC: POINTER,
SIDRBD: POINTER,
SPLITBD: POINTER;
TRACE ('INSRTSIDR');
%([ CLEAR THE NUMBER OF NEW SPLIT BUCKETS ])%
RECDESC [ RDCOUNT ] = ZERO;
%([ DO THE INSERTION ])%
IF CALLDOSIDR ( %(REC DESC)% BPT ( RECDESC ),
%(BKT)% BPT ( SIDRBD ),
%(SPLIT)% BPT ( SPLITBD ) ) IS FALSE
%([ WHAT HAPPENED? ])%
THEN
RETURN FALSE;
%([ IF WE SPLIT, THEN WE MUST UPDATE THE NEW FILE BUCKET ])%
IF .RECDESC [ RDCOUNT ] IS 1
THEN
CALLPUTBKT ( %(UPDATE)% PCI ( TRUE ),
%(BUCKET)% BPT ( SPLITBD ) );
%([ UPDATE THE BUCKET IN WHICH THE SIDR WAS INSERTED ])%
CALLPUTBKT ( %(UPDATE)% PCI ( TRUE ),
%(BUCKET)% BPT ( SIDRBD ) );
GOODRETURN
END; %(OF INSRTSIDR)%
! BLDISIDR
! ========
! ROUTINE TO BUILD THE FIRST INSTANCE OF A SPECIFIC SECONDARY
! DATA RECORD. THIS ROUTINE IS CALLED ONLY WHEN THE SIDR
! RECORD IS BEING INITIALLY CREATED. CONTINUATION SIDR'S
! ARE CREATED ONLY BY "BLDCSIDR".
! INPUT:
! RECDESC RECORD DESCRIPTOR PACKET
! RRV RECORD POINTER TO USE
! RECPTR ADDRESS TO INSERT SIDR
!
! SIDRBD BUCKET DESCRIPTOR OF SIDR BUCKET (OLD BUCKET)
! NEWBD BUCKET DESCRIPTOR OF NEW BUCKET (RETURNED)
!
! OUTPUT:
! TRUE: SIDR INSERTED CORRECTLY
! FALSE: SIDR COULD NOT BE INSERTED (ERROR CODE IS IN USRSTS)
!
! ROUTINES CALLED:
! SPLIT
! MAKESIDR
! ALCNEWIDS
GLOBAL ROUTINE BLDISIDR ( RECDESC, SIDRBD, SPLITBD ) =
BEGIN
ARGUMENT (RECDESC,BASEADD);
ARGUMENT (SIDRBD,BASEADD);
ARGUMENT (SPLITBD,BASEADD);
MAP
RECDESC: POINTER,
SIDRBD: POINTER,
SPLITBD: POINTER;
REGISTER
PTRAC: POINTER,
BKTPTR: POINTER, ! PTR TO TOP OF CURRENT BUCKET
TEMPAC;
LOCAL
ENDPTR: POINTER, ! PTR TO END OF CURRENT BUCKET
INSERTPTR: POINTER, ! PTR TO PLACE TO INSERT NEWSIDR
DUMMYBD: FORMATS[ BDSIZE ], ! DUMMY BKT DESC FOR SPLIT
CURRENTBD: FORMATS[ BDSIZE ], ! CURRENT BUCKET
SPLITFLAG, ! FOR IS ON IF WE SPLI THE BUCKET
MAXOFFSET, ! OFFSET INTO BUCKET TO DETERMINE IF FULL
KEYBUFFPTR: POINTER, ! PTR TO RST KEY BUFFER
SPACENEEDED; ! SIZE OF NEW SIDR
TRACE ('BLDISIDR');
%([ ASSUME NO SPLITS ])%
SPLITFLAG = FALSE;
%([ SET UP SOME POINTERS AND FIGURE OUT HOW MUCH SPACE
WE HAVE LEFT IN THIS BUCKET ])%
INSERTPTR = .RECDESC [ RDRECPTR ];
BKTPTR = .SIDRBD [ BKDBKTADR ]; ! ADDRESS OF BUCKET
RECDESC [ RDLENGTH ] = ( SPACENEEDED = SIDRHDRSIZE + .KDB [ KDBKSZW ] + 1);
LOOKAT (' SPACE-NEEDED: ',SPACENEEDED );
%([ CAN THIS NEW SIDR FIT ONTO THE BUCKET? ])%
MAXOFFSET = .KDB [ KDBDBKZ ] ^ B2W; ! FIND MAX SIZE OF BUCKET
IF ( CHKFLAG ( RAB [ RABROP ], ROPLOA ) ISON )
THEN %(USER WANTS TO SPECIFY LOAD FILL PERCENT)%
MAXOFFSET = .KDB [ KDBDFLOFFSET ];
%([ WILL THE NEW SIDR FIT IN THIS BUCKET? ])%
IF ( .BKTPTR [ BHNEXTBYTE ] + .SPACENEEDED ) GTR .MAXOFFSET
THEN %(IT WONT FIT...WE MUST SPLIT THE SIDR BUCKET)%
BEGIN
RTRACE (%STRING(' SIDR WONT FIT...',%CHAR(13),%CHAR(10)));
%([ SPLIT THE SIDR BUCKET ])%
IF CALLSPLIT ( BPT ( RECDESC ),
BPT ( SIDRBD ),
BPT ( SPLITBD ),
LCT ( DUMMYBD ) ) IS FALSE
%([ WHAT HAPPENED? ])%
THEN
RETURN FALSE;
SPLITFLAG = 1; ! SET THIS FLAG FOR LATER
%IF DBUG %THEN
IF .RECDESC [ RDCOUNT ] GEQ 2 THEN RMSBUG ( MSGSPLIT );
%FI
%([ DETERMINE IF THE INSERTION POINT WAS MOVED
TO THE NEW BUCKET ])%
INSERTPTR = .RECDESC [ RDRECPTR ]; ! FETCH ADDR OF SIDR
END %(OF IF WE NEED TO SPLIT)%
ELSE %(THE SIDR CAN FIT IN THIS BUCKET...)%
BEGIN
%([ WE NOW MUST LOCATE THE END OF THE DATA IN THE
CURRENT BUCKET ])%
ENDPTR = .BKTPTR + .BKTPTR [ BHNEXTBYTE ];
%([ COMPUTE AMOUNT OF DATA TO MOVE DOWN ])%
TEMPAC = .ENDPTR - .INSERTPTR;
LOOKAT (' AMOUNT-TO-MOVE: ', TEMPAC );
%IF DBUG %THEN
IF .TEMPAC LSS ZERO THEN RMSBUG ( MSGCOUNT );
%FI
IF .TEMPAC ISNT ZERO
THEN
BEGIN
MOVEDOWN ( %(START)% .INSERTPTR,
%(END)% .ENDPTR -1,
%(SIZE)% .SPACENEEDED )
END; %(OF IF WE NEED TO MOVE DATA DOWN)%
%([ ALLOCATE AN RFA FOR THE NEW SIDR (SPLIT ALREADY
DID THIS FOR US IF THE BUCKET SPLIT) ])%
RECDESC [ RDRFA ] = CALLALCRFA ( BPT ( SIDRBD ) );
%([ BUMP THE BUCKET HEADER NEXT-BYTE VALUE ])%
INC ( BKTPTR [ BHNEXTBYTE ], .SPACENEEDED )
END; %(OF THE SIDR BUCKET DOES NOT HAVE TO BE SPLIT)%
%([ CREATE THE SIDR RECORD ])%
CALLMAKESIDR ( %(RD)% BPT ( RECDESC ),
%(PLACE)% LPT ( INSERTPTR ) );
%([ IF WE DIDNT'T SPLIT THE SIDR BUCKET, THEN WE CAN EXIT ])%
IF .SPLITFLAG IS FALSE THEN GOODRETURN;
%([ WE NOW MUST ASSIGN ID'S FOR ALL SIDR RECORDS WHICH
MOVED TO THE NEW BUCKET. WE ALSO MUST MOVE THE NEW
HIGH-KEY VALUE IN THE ORIGINAL BUCKET INTO THE KEY
BUFFER (THE BOTTOM HALF OF IT) SO THAT "INDEX-UPDATE"
WILL KNOW WHAT KEY TO PUT IN THE OLD INDEX RECORD.
NOTE THAT THE MOVING OF THIS KEY MUST BE DONE AFTER
THE NEW SIDR IS CREATED SINCE THE NEW RECORD TO BE
INSERTED MAY BE THE NEW HIGH-KEY RECORD. ])%
%([ **NOTE THAT THE INDEX-UPDATE FLAG BIT WAS SET BY SPLIT*** ])%
%([ WE NOW MUST MOVE THE NEW HIGH-KEY VALUE FOR THE
ORIGINAL BUCKET INTO THE RST KEY BUFFER ])%
PTRAC = .RECDESC [ RDLASTRECPTR ] + SIDRHDRSIZE; ! PTR TO KEY
KEYBUFFPTR = .RST [ RSTKEYBUFF ] + ( .FST [ FSTKBFSIZE ] ^ DIVIDEBY2LSH );
MOVEWORDS ( %(FROM)% .PTRAC,
%(TO)% .KEYBUFFPTR,
%(SIZE)% .KDB [ KDBKSZW ] );
%([ WE NOW MUST ASSIGN NEW ID'S FOR ALL THE SIDR
RECORDS WHICH MOVED TO THE NEW BUCKET. ])%
CALLALCNEWIDS ( %(NEW BKT)% BPT ( SPLITBD ) );
GOODRETURN
END; %(OF BLDISIDR)%
! DELSIDR
! =======
! ROUTINE TO DELETE A SINGLE RECORD-POINTER FROM THE SECONDARY
! INDEX DATA RECORDS. THIS ROUTINE IS CALLED WHENEVER
! A $PUT TO AN INDEXED FILE RESULTS IN AN ERROR DURING
! PROCESSING OF ONE OF THE SECONDARY INDICES. IN SUCH A
! CASE, ALL THE PREVIOUS SECONARY INDICES MUST BE MODIFIED
! SO THAT THE RECORD IS REMOVED.
!
! IF THE SECONDARY INDEX ALLOWS DUPLICATES, THEN EACH SIDR
! POINTER ARRAY MUST BE SCANNED UNTIL THE CORRECT ENTRY IS
! FOUND AND THEN IT CAN BE DELETED. IF NO DUPLICATES ARE
! ALLOWED, THEN THE ENTIRE SECONDARY DATA RECORD CAN BE
! SQUEEZED FROM THE BUCKET.
! INPUT:
! RECDESC RECORD DESCRIPTOR PACKET
! USERPTR ADDRESS OF SEARCH KEY STRING
! USERSIZE SIZE OF SEARCH KEY STRING
! RRV RFA OF RECORD TO BE DELETED
! OUTPUT:
! TRUE: RECORD FOUND AND DELETED
! FALSE: ERROR
! RECORD NOT FOUND
!
! NOTES:
!
! 1. THE INDEX MUST BE LOCKED WHEN THIS ROUTINE IS CALLED.
! ROUTINES CALLED:
! FNDREC
GLOBAL ROUTINE DELSIDR ( RECDESC ) =
BEGIN
ARGUMENT (RECDESC,BASEADD);
MAP
RECDESC: POINTER;
REGISTER
SIDRPTR: POINTER, ! PTR TO CURRENT SIDR
ARRAYPTR: POINTER; ! PTR TO SIDR POINTER ARRAY
LOCAL
SIDRBD: FORMATS[ BDSIZE ], ! BKT DESC FOR SIDR BUCKETS
DUMMYBD: FORMATS[ BDSIZE ], ! A TEMPORARY BKT DESCRIPTOR
RECORDPOINTER, ! RFA TO SEARCH FOR
DUMMYPTR: POINTER, ! USED TO PASS SIDRPTR AS LOCAL
BKTPTR: POINTER, ! PTR TO CURRENT SIDR BUCKET
ENDPTR: POINTER, ! PTR TO END OF CURRENT BUCKET
AMOUNTTOMOVE, ! AMOUNT OF DATA TO SQUEEZE
PTRCOUNT, ! # OF PTRS IN CURRENT ARRAY
OFFSETTOPTRS, ! OFFSET TO PTRS IN SIDR ARRAY
SAVEDSTATUS; ! RESULTS OF A ROUTINE
EXTERNAL ROUTINE
SQUEEZESIDR;
LABEL BIGLOOP; ! LABELS
TRACE ('DELSIDR');
CHECKEXACTCOUNT;
%([ CHECK A FEW THINGS ])%
%IF DBUG %THEN
IF .KDB [ KDBREF ] IS REFPRIMARY THEN RMSBUG ( MSGINPUT );
%FI
%([ SET UP THE RFA OF OUR TARGET RECORD ])%
RECORDPOINTER = .RECDESC [ RDRRV ];
%([ WE WILL TRY TO SEARCH THE ENTIRE INDEX AND POSITION
TO THE SIDR RECORD ])%
IF CALLFNDDATA ( %(RD)% BPT ( RECDESC ),
%(BKT)% LCT ( SIDRBD ) ) IS FALSE
THEN
RETURN FALSE;
%([ DID WE STOP AT THE DATA LEVEL? ])%
IF .RECDESC [ RDLASTLEVEL ] ISNT DATALEVEL THEN BADRETURN;
%([ AT THIS POINT, WE WILL DEFINE A DUMMY BLOCK WHICH
WE WILL BE ABLE TO EXIT FROM. ])%
BIGLOOP: BEGIN
%([ THE RECORD WAS EITHER NOT FOUND, OR THERE WAS AN
EXACT MATCH. CHECK IF THE RECORD WAS FOUND ])%
IF CHKFLAG ( RECDESC [ RDSTATUS ], RDFLGPST+RDFLGLSS) ISON
THEN %(THE RECORD WASNT FOUND)%
LEAVE BIGLOOP WITH ( SAVEDSTATUS = FALSE );
%([ WE HAVE FOUND AN EXACT MATCH. WE MUST NOW CHECK IF WE
CAN FIND THE RECORD POINTER IN THIS ARRAY. ])%
SIDRPTR = .RECDESC [ RDRECPTR ]; ! GET PTR TO SIDR
OFFSETTOPTRS = SIDRHDRSIZE + .KDB [ KDBKSZW ]; ! COMPUTE THIS NOW
%([ IF NO DUPS ARE ALLOWED, THEN WE MUST COMPARE OUR
SEARCH KEY RECORD ADDRESS WITH THE ONE IN THIS SIDR. ])%
IF CHKFLAG ( KDB [ KDBFLAGS ], FLGDUP ) IS OFF
THEN %(NO DUPS ARE ALLOWED)%
BEGIN
RTRACE (%STRING(' SEARCHING THIS SIDR...',%CHAR(13),%CHAR(10)));
ARRAYPTR = .SIDRPTR + .OFFSETTOPTRS; ! PTR TO RFA'S
IF .ARRAYPTR [ WHOLEWORD ] ISNT .RECORDPOINTER
THEN %(THE RECORD WASNT FOUND)%
LEAVE BIGLOOP WITH ( SAVEDSTATUS = FALSE );
%([ WE CAN SET THIS RFA TO BE DELETED ])%
DUMMYPTR = .SIDRPTR; ! STORE PTR AS LOCAL
CALLSQUEEZESIDR ( LPT ( DUMMYPTR ),
LCT ( SIDRBD ) );
SAVEDSTATUS = TRUE
END %(IF IF NO DUPS ARE ALLOWED)%
ELSE %(DUPS ARE ALLOWED)%
BEGIN
%([ WE MUST SCAN ALL SIDR'S UNTIL WE FIND THE CORRECT
RECORD POINTER. WE MAY HIT THE END OF THE CHAIN
FIRST, IN WHICH CASE WE MUST EXIT WITH FAILURE. ])%
REPEAT %(THIS LOOP FOREVER)%
BEGIN
RTRACE (%STRING(' SCANNING SIDR...',%CHAR(13),%CHAR(10)));
SIDRPTR = .RECDESC [ RDRECPTR ]; ! GET SIDR PTR AGAIN
BKTPTR = .SIDRBD [ BKDBKTADR ]; ! FETCH THIS AGAIN
ENDPTR = .BKTPTR + .BKTPTR [ BHNEXTBYTE ];
PTRCOUNT = .SIDRPTR [ SIDRRECSIZE ] - .KDB [ KDBKSZW ];
ARRAYPTR = .SIDRPTR + .OFFSETTOPTRS; ! GET PTR TO RFA'S
LOOKAT (' SIDRPTR: ', SIDRPTR );
LOOKAT (' # OF PTRS: ', PTRCOUNT );
%([ LOOP OVER ALL POINTERS IN THE ARRAY ])%
INCR J FROM 0 TO .PTRCOUNT -1
DO
BEGIN
IF ( .ARRAYPTR [ WHOLEWORD ] AND ( NOT ALLRFAFLAGS ) ) IS .RECORDPOINTER
THEN
BEGIN
LOOKAT (' FOUND RFA AT: ', ARRAYPTR );
%([ NOTE NO CHECK FOR SIDR ALREADY DELETED ])%
SETUPD (SIDRBD); !INDIC THIS PG TO BE UPDATED
SETDELETEDRFA ( ARRAYPTR );
LEAVE BIGLOOP WITH ( SAVEDSTATUS = TRUE)
END; %(OF IF THIS IS THE RIGHT PTR)%
INC ( ARRAYPTR, 1 )
END; %(OF INCR LOOP)%
%([ AT THIS POINT, WE DIDNT FIND THE RP IN
THE SIDR. SO, WE MUST CHECK IF THERE ARE
ANY CONTINUATION SIDR'S AND IF SO, WE MUST
SCAN ALL OF THEM TO SEE IF WE CAN FIND THE
CORRECT RFA. ])%
RTRACE (%STRING(' DIDNT FIND RFA IN SIDR...',%CHAR(13),%CHAR(10)));
LOOKAT (' ARRAY-PTR: ', ARRAYPTR );
IF .ARRAYPTR ISNT .ENDPTR
THEN %(THERE ARE NO MORE CONTINUATION SIDR'S)%
LEAVE BIGLOOP WITH ( SAVEDSTATUS = FALSE );
%([ START THE SEARCH AT THE END OF THIS BUCKET.
ALSO, INDICATE THAT A HORIZONTAL SEARCH IS OK. ])%
RTRACE (%STRING(' SEARCHING FOR CONT SIDRS...',%CHAR(13),%CHAR(10)));
SETFLAG ( RECDESC [ RDFLAGS ], RDFLGHORIZOK );
RECDESC [ RDRECPTR ] = .ENDPTR;
%([ WE MUST MOVE THE SIDR BUCKET DESCRIPTOR
TO A TEMP LOCATION TO INPUT IT TO FNDREC. ])%
MOVEBKTDESC ( %(FROM)% SIDRBD, %(TO)% DUMMYBD );
SAVEDSTATUS = CALLFNDREC ( BPT ( RECDESC ),
LCT ( DUMMYBD ),
LCT ( SIDRBD ) );
%([ AT THIS POINT, FNDREC RETURNED A STATUS OF TRUE
UNLESS THERE WAS A FATAL PROBLEM (NO SPACE LEFT
FOR BUCKETS, ...). HOWEVER, WE MUST CHECK THE
STATUS BITS BECAUSE THE NEW RECORD MAY NOT
BE A CONTINUATION RECORD, OR THE END OF THE
BUCKET CHAIN MAY HAVE BEEN REACHED. IN ALL THESE
CASES, WE MUST EXIT FROM THE LOOP. ])%
IF ( .SAVEDSTATUS IS FALSE )
OR
( CHKFLAG ( RECDESC [ RDSTATUS ], RDFLGLSS+RDFLGPST) ISON )
THEN %(THIS WAS NOT A CONTINUATION SIDR)%
LEAVE BIGLOOP WITH ( SAVEDSTATUS = FALSE )
END %(OF REPEAT LOOP)%
END %(OF ELSE DUPS ARE ALLOWED)%
END; %(OF BIGLOOP)%
%([ COME HERE WITH SAVEDSTATUS = STATUS OF OUR OPERATION.
WE MUST RELEASE THE CURRENT BUCKET AND RETURN
TO THE CALLER. ])%
%([ NOTE THAT WE WILL NOT WRITE OUT THIS BUCKET NOW.
IT IS VERY LIKELY THAT IT WILL GO OUT SOON, AND WE NEED
TO SAVE SOME TIME. ])%
CALLPUTBKT ( %(NO UPDATE)% PCI ( FALSE ),
%(SIDR)% LCT ( SIDRBD ) );
RETURN .SAVEDSTATUS
END; %(OF DELSIDR)%
! SQUEEZESIDR
! ===========
! ROUTINE TO SQUEEZE A SINGLE SECONDARY DATA RECORD FROM A BUCKET.
! THIS ROUTINE CAN ONLY BE CALLED IF THE SIDR CONTAINS ONLY
! ONE RECORD POINTER.
! INPUT:
! SIDRPTR ADDRESS OF SIDR RECORD
! SIDRBD BUCKET DESCRIPTOR OF SIDR BUCKET
! OUTPUT:
! <NO STATUS RETURNED>
! ROUTINES CALLED:
! <NONE>
GLOBAL ROUTINE SQUEEZESIDR ( SIDRPTR, SIDRBD ):NOVALUE =
BEGIN
ARGUMENT (SIDRPTR,BASEADD);
ARGUMENT (SIDRBD,BASEADD);
MAP
SIDRPTR: POINTER,
SIDRBD: POINTER;
REGISTER
BKTPTR: POINTER, ! PTR TO SIDR BUCKET
ENDPTR: POINTER; ! PTR TO END OF SIDR BUCKET
LOCAL
AMOUNTTOMOVE, ! DATA TO MOVE UP IN BUCKET
SIZEOFSIDR; ! SIZE OF SIDR HEADER AND KEY
TRACE ('SQUEEZESIDR');
%([ PICK UP THE BUCKET ADDRESS AND FIND END OF BUCKET ])%
SETUPD (SIDRBD); !INDIC THIS PG TO BE UPDATED
BKTPTR = .SIDRBD [ BKDBKTADR ];
ENDPTR = .BKTPTR + .BKTPTR [ BHNEXTBYTE ];
SIZEOFSIDR = SIDRHDRSIZE + .KDB [ KDBKSZW ] + 1;
AMOUNTTOMOVE = .ENDPTR - .SIDRPTR - .SIZEOFSIDR;
LOOKAT (' AMOUNT-TO-MOVE: ', AMOUNTTOMOVE );
LOOKAT (' END OF BKT: ', ENDPTR );
IF .AMOUNTTOMOVE ISNT ZERO
THEN %(WE HAVE SOME TO MOVE)%
BEGIN
RTRACE (%STRING(' SQUEEZING BUCKET...',%CHAR(13),%CHAR(10)));
MOVEWORDS ( %(FROM)% .SIDRPTR + .SIZEOFSIDR,
%(TO)% .SIDRPTR,
%(SIZE)% .AMOUNTTOMOVE )
END; %(OF IF THERE IS DATA TO MOVE)%
%([ UPDATE THE BUCKET HEADER INFO ])%
DEC ( BKTPTR [ BHNEXTBYTE ], ( .SIZEOFSIDR) );
RETURN
END; %(OF SQUEEZE-SIDR)%
! PUTSIDR
! =======
! ROUTINE TO INSERT A KEY FROM THE USER DATA RECORD INTO A
! SECONDARY INDEX. THIS ROUTINE IS CALLED FROM $PUT
! AND $UPDATE WHENEVER A NEW KEY IS BEING INSERTED
! INTO THE FILE. THE USER DATA RECORD MUST ALREADY HAVE
! BEEN CHECK TO MAKE SURE IT IS BIG ENOUGH TO HOLD THE
! ENTIRE KEY STRING FOR THIS KEY OF REFERENCE.
! INPUT:
! RECDESC RECORD DESCRIPTOR PACKET
! RRV RECORD ADDRESS TO INSERT INTO SECONDARY INDEX
! OUTPUT:
! TRUE: OK...RECORD INSERTED INTO SECONDARY INDEX
! FALSE: ERROR
! INPUT ARGS MODIFIED:
!
! RECORD DESCRIPTOR:
! STATUS OPERATION STATUS BITS
! FLGIDXERROR INDEX UPDATE ERROR OCCURED
! ROUTINES CALLED:
! MAKIDX
! FOLLOWPATH
! CHKDUP
! INSRTSIDR
! IDXUPDATE
! NOTES:
!
! 1. KDB MUST BE SET UP ON ENTRY FOR THE CURRENT KEY.
!
! 2. THE INDEX MUST BE LOCKED WHEN THIS ROUTINE IS CALLED.
GLOBAL ROUTINE PUTSIDR ( RECDESC ) =
BEGIN
ARGUMENT (RECDESC,BASEADD); ! RECORD DESC PACKET
MAP
RECDESC: POINTER;
LABEL LOOP;
LOCAL
USERRECORDPTR: POINTER, ! PTR TO USER DATA RECORD
SECKEYBUFFER: VECTOR[ MAXKSZW ], ! TEMP BUFFER FOR SEC KEY
BKTDESC: FORMATS[ BDSIZE ], ! BUCKET DESC FOR SIDR BUCKET
!** [12] ROUTINE:PUTSIDR AT LINE 7725, EGM, 3-APR-78
%([12])% SPLITBD1: FORMATS[ BDSIZE ], ! BKT DESC FOR SPLITS
%([12])% OLDLASTRECPTR; ! SAVED PTR TO LAST SIDR ARRAY
EXTERNAL ROUTINE
FOLLOWPATH, ! TRAVERSE THE INDEX
CHKDUP, ! CHECK FOR DUPS
MAKIDX, ! CREATE A NEW INDEX
MOVEKEY, ! MOVE THE SEC KEY INTO BUFFER
INSRTSIDR, ! INSERT THE NEW SIDR
IDXUPDATE; ! UPDATE THE INDEX
TRACE ('PUTSIDR');
%([ CHECK IF THERE IS AN INDEX ])%
IF NOINDEXFLAG ISON
THEN
BEGIN
CALLMAKIDX; ! MAKE ONE
%([ IF THE NO-INDEX IS STILL ON, THERE WAS A PROBLEM ])%
IF NOINDEXFLAG ISON
THEN
BADRETURN
END; %(OF IF NOINDEX FLAG ISON)%
%([ FETCH THE ADDRESS OF THE USER'S NEW RECORD ])%
USERRECORDPTR = .RAB [ RABRBF ];
%([ MOVE THE SECONDARY KEY STRING TO THE TEMPORARY BUFFER ])%
CALLMOVEKEY ( %(FROM)% LPT ( USERRECORDPTR ),
%(TO)% LCT ( SECKEYBUFFER ) );
RECDESC [ RDUSERPTR ] = SECKEYBUFFER;
RECDESC [ RDUSERSIZE ] = .KDB [ KDBKSZ ];
%([ ***NEXT INSTR ASSUMES RDFLAGS AND RDSTATUS ARE IN WORD 0 ])%
RECDESC [ WHOLEWORD ] = ZERO;
%([ SEARCH THE SECONDARY INDEX ])%
IF CALLFOLLOWPATH ( BPT ( RECDESC ),
LCT ( BKTDESC )) IS FALSE
THEN
RETURN FALSE;
!** [12] ROUTINE:PUTSIDR AT LINE 7773, EGM, 3-APR-78
%([12])%
%([12])% %([ SAVE THE LAST RECORD POINTER AROUND THE CALL TO CHKDUP ])%
%([12])%
%([12])% OLDLASTRECPTR = .RECDESC [ RDLASTRECPTR ];
%([ CHECK FOR DUPLICATE VALUES ])%
%([ WE MUST NOW INSERT THE SIDR RECORD INTO
THE SIDR BUCKET ])%
LOOP: BEGIN
IF CALLCHKDUP ( BPT ( RECDESC ),
LCT ( BKTDESC ) ) ISNT FALSE
THEN
!** [12] ROUTINE:PUTSIDR AT LINE 7785, EGM, 3-APR-78
%([12])% BEGIN
%([12])%
%([12])% %([ IF DUPLICATES WERE FOUND, BACKUP THE RECORD POINTERS )%
%([12])% %( TO CORRECTLY POINT TO THE FINAL DUPLICATE SIDR ARRAY, )%
%([12])% %( AND THE PREVIOUS SIDR ARRAY. THIS MUST BE DONE SO THAT )%
%([12])% %( THE RST KEY BUFFER CAN BE UPDATED PROPERLY ON A SPLIT ])%
%([12])%
%([12])% IF DUPLICATEFLAG (RECDESC) ISON
%([12])% THEN
%([12])% BEGIN
%([12])% RECDESC [ RDRECPTR ] = .RECDESC [ RDLASTRECPTR ];
%([12])% RECDESC [ RDLASTRECPTR ] = .OLDLASTRECPTR
%([12])% END;
%([12])%
%([12])% IF CALLINSRTSIDR ( BPT ( RECDESC ),
%([12])% LCT ( BKTDESC ),
%([12])% LCT ( SPLITBD1 ) ) ISNT FALSE
%([12])% THEN
LEAVE LOOP WITH TRUE;
END;
BEGIN
CALLPUTBKT ( %(NO)% PCI ( FALSE ),
%(BKT)% LCT ( BKTDESC ) );
BADRETURN
END; %(OF IF ERROR IN CHKDUP OR INSRTSIDR)%
END; %( OF LOOP )%
%([ CHECK FOR INDEX UPDATE ])%
IF IDXUPDATEFLAG ( RECDESC ) ISON
THEN
BEGIN
IF CALLIDXUPDATE ( BPT ( RECDESC ),
LCT ( BKTDESC ),
LCT ( SPLITBD1 ),
PCI ( ZERO ) ) ! ONLY 1 EXTRA BKT
IS FALSE THEN
%([ WHAT HAPPENED? ])%
SETIDXERRORFLAG ( RECDESC ); ! SET THE FLAG
END; %(OF IF INDEX UPDATE REQUIRED)%
%([ RETURN AFTER INSERTING NEW SIDR RECORD ])%
GOODRETURN
END; %(OF PUTSIDR)%
END
ELUDOM