Trailing-Edge
-
PDP-10 Archives
-
704rmsf2
-
10,7/rms10/rmssrc/rmsbkt.b36
There are 6 other files named rmsbkt.b36 in the archive. Click here to see a list.
MODULE BUCKET =
BEGIN
GLOBAL BIND BUKTV = 1^24 + 0^18 + 17; !EDIT DATE: 5-MAY-77
%([
FUNCTION: THIS MODULE CONTAINS ALL ROUTINES WHICH PROCESS
FILE BUCKETS WITHIN RMS-20 FILES.
AUTHOR: S. BLOUNT
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
TABLE OF CONTENTS
===== == ========
ROUTINE FUNCTION
======= ========
GETBKT MAKE SURE SPECIFIED BUCKET IS IN CORE AND AVAILABLE
PUTBKT RELEASE SPECIFIED BUCKET
ALCBKT ALLOCATE A BUCKET (ALSO PERFORM 'GETBKT')
REVISION HISTORY:
EDIT WHO DATE PURPOSE
==== === ==== =======
0 JK 16-JUL-76 RECREATE RMSBKT.BLI
1 JK 30-AUG-76 CLEAR UNUSED BITS WHEN BUCKET ALLOCATED.
2 JK 1-SEP-76 'BHNEXTID' SHOULD BE INIT'D TO 'FIRSTID'.
3 JK 3-SEP-76 SET FLGBUSY IF BUCKET IS BUSY.
4 JK 9-SEP-76 CHECK FOR BAD BKT DESC IN 'PUTBKT'.
5 SB 4-OCT-76 DONT LOCK PROLOG IF ONLY 1 KEY
6 SB 22-OCT-76 MAKE BUSY RETURN GIVE ERRLK
7 SB 7-NOV-76 MAKE BUCKETS BE IN UNITS OF PAGES
8 SB 1-DEC-76 PUT IN ALCBKT
9 SB 27-DEC-76 CHANGE UNLOCKPAGE TO UNLOCKBUCKET
10 SB 31-JAN-77 SET FSTHYBTE IN ALCBKT
11 SB 10-FEB-77 TAKE OUT BUSYFLAG
12 SB 25-FEB-77 ADD NEW ARG (CONTIGFLAG) TO CALLGETBUF
13 SB 1-MAR-77 SET WANTTOLOCK IN GETBKT (GOT DELETED SOMEHOW)
14 SB 4-APR-77 ADD DEFERRED WRITE
15 SB 6-APR-77 CHANGE HYBYTE TO RST
16 SB 13-APR-77 MOVE LOCKING AFTER PAGE MAP IN GETBKT
17 SB 5-MAY-77 RETURN BUFFER IF LOCK FAILS
*************************************************
* *
* NEW REVISION HISTORY *
* *
*************************************************
PRODUCT MODULE SPR
EDIT EDIT QAR DESCRIPTION
====== ====== ===== ===========
***** END OF REVISION HISTORY *****
])%
%([ FORWARD DECLARATIONS ])%
%([ EXTERNAL DECLARATIONS ])%
EXTERNAL ROUTINE
GETBUF, ! GET A BUFFER
PUTBUF, ! RELEASE A BUFFER
DUMP, ! PRINT DEBUG INFO
CRASH, ! HANDLE BUGS
LOCKIT; ! LOCK THE ALLOCATION CAPABILITY
%([ ERROR MESSAGES REFERENCED IN THIS MODULE ])%
EXTERNAL
! MSGUNLOCKED, ! RECORD/BUCKET WAS SUPPOSED TO BE LOCKED
MSGINPUT; ! INCORRECT ROUTINE ARGUMENTS
REQUIRE 'RMSREQ';
EXTDECLARATIONS;
! GETBKT
! ======
!
! THIS ROUTINE PERFORMS THE MAPPING AND LOCKING TO ASSURE THAT THE
! SPECIFIED BUCKET OF AN INDEXED FILE IS IN CORE AND AVAILABLE FOR
! USE BY THE CALLER. NO MAPPING IS NECESSARY IF THE BUCKET IS
! STILL IN CORE FROM A PREVIOUS OPERATION. A NON-SUCCESSFUL RETURN
! WILL BE GIVEN IF THE BUCKET IS BUSY. SEE THE FILE "BUFFER.REQ" FOR
! A DESCRIPTION OF THE FORMAT OF A BUCKET DESCRIPTOR.
!
! THIS ROUTINE DETERMINES WHETHER "CONTIGUOUS" ALLOCATION
! IS REQUIRED FROM THE BUFFER MANAGER. THIS CONCEPT IS USED
! ONLY FOR SEQUENTIAL AND RELATIVE FILES AND MEANS THAT IF
! THE TARGET BUCKET IS NOT IN THE BUFFER POOL, THEN IT IS TO
! BE MAPPED INTO THE FIRST BUFFER, AND THE REST OF THE BUFFERS
! ARE TO RECIEVE THE NEXT PAGES IN SEQUENCE. IT THUS ASSUMES
! THAT BUFFER ALLOCATION WAS CONTIGUOUS WHEN THE RECORD STREAM
! WAS INITIATED.
!
! ARGUMENTS:
! BKTNO = BUCKET NUMBER (ACTUALLY A 18-BIT PAGE NUMBER )
! BKTSIZ = BUCKET SIZE ( IN BLOCKS )
! LOCKFLAG = TRUE IF CALLER WANTS BUCKET LOCKED
! BKTDESC = BUCKET DESCRIPTOR (FIELDS WILL BE RETURNED)
!
! RETURN VALUE:
! TRUE = SUCCESSFUL
! FALSE = UNSUCCESSFUL
! NO ROOM FOR BUCKET IN CORE
! BUCKET IS BUSY
! UNEXPECTED ENQUE/DEQUE ERRORS
! NOTES:
!
! 1. ON ALL ERRORS IN THIS ROUTINE, USRSTS WILL BE SET UP
!
! 2. THIS ROUTINE MAKES THE ASSUMPTION (ALSO MADE BY GETBUF)
! THAT FOR SEQUENTIAL AND RELATIVE FILES, ONLY ONE BUFFER
! CAN BE ALLOCATED AT A TIME. THIS IS NECESSARY FOR
! CONTIGUOUS BUFFER ALLOCATION TO WORK.
!
! 3. THIS ROUTINE MAPS THE BUCKET INTO THE BUFFER POOL BEFORE
! AN ATTEMPT IS MADE TO LOCK IT. THIS IS TO OVERLAP THE
! PAGE I/O WITH THE ENQ REQUEST. WITH LUCK, WE MAY BE ABLE
! TO ESSENTIALLY GET THE ENQ FOR FREE. IF THE LOCK FAILS,
! THEN A PAGE IS ALREADY COMING IN THAT WE DON'T WANT, BUT
! IT IS LIKELY THAT THE USER WILL RE-ACCESS IT SOON.
GLOBAL ROUTINE GETBKT ( BKTNO, BKTSIZ, LOCKFLAG, BKTDESC ) =
BEGIN
ARGUMENT(BKTNO,VALUE); ! BUCKET NUMBER
ARGUMENT(BKTSIZ,VALUE); ! BUCKET SIZE
ARGUMENT(LOCKFLAG,VALUE); ! LOCK FLAG
ARGUMENT(BKTDESC,BASEADD); ! BUCKET DESCRIPTOR ADDRESS
MAP
BKTDESC: POINTER;
REGISTER
TEMPAC;
LOCAL
FPAGE, ! A FILE PAGE NO.
CONTIGFLAG, ! FLAG FOR CONTIGUOUS BUFFER ALLOCATION
NOPAGES, ! A COUNT OF PAGES
LOCKACC, ! LOCK ACCESS (ENQSHR/ENQEXC)
BPAGE, ! A BUFFER PAGE NO.
INCORE, ! AN INCORE FLAG
BFDADR, ! A BUFFER DESCRIPTOR ADDRESS
WANTTOLOCK, ! TRUE IF BUCKET SHOULD BE LOCKED
TEMP; ! TEMP
TRACE ( 'GETBKT' );
LOOKAT ( ' GETTING BKT: ' , BKTNO );
%([ IF CALLER WANTED TO LOCK BUCKET, AND WE ARE LOCKING, THEN REMEMBER IT ])%
WANTTOLOCK = .LOCKFLAG AND LOCKING;
%([ ASSUME NON-CONTIGUOUS BUFFER ALLOCATION ])%
CONTIGFLAG = FALSE;
%([ PERFORM LOCKING, IF NECESSARY ])%
FPAGE = .BKTNO ; ! COMPUTE FILE PAGE NO. OF BUCKET
%([ FOR SEQ/REL FILES, WE MUST CHECK IF THE USER
WANTED READ-AHEAD. IF SO, WE WILL ASK FOR CONTIGUOUS
BUFFER ALLOCATION ])%
IF NOT IDXFILE
THEN
IF READAHEAD THEN CONTIGFLAG = 1;
%([ GET A BUFFER FOR BUCKET ])%
NOPAGES = ( .BKTSIZ ); ! GET # OF PAGES
IF (TEMPAC = CALLGETBUF ( %( FILE PAGE NO. )% LCI ( FPAGE ),
%( NO. PAGES )% LCI ( NOPAGES ),
%( CONTIGUOUS )% LCI ( CONTIGFLAG ),
%( BUF PAGE NO. )% RLCI ( BPAGE ),
%( INCORE FLAG )% RLCI ( INCORE ),
%( BFD ADR )% RLCI ( BFDADR ))) IS FALSE THEN
RETURN .TEMPAC;
%([ FOR CONTIGUOUS ALLOCATION, WE MUST MAP ALL PAGES THAT WILL FIT ])%
IF .CONTIGFLAG ISNT FALSE THEN NOPAGES = .BKTSIZ * .RST [ RSTBFDCOUNT ];
%([ IF BUFFER IS EMPTY, MAP BUCKET INTO IT ])%
IF .INCORE IS FALSE
THEN
BEGIN %( MAP BUCKET INTO BUFFER )%
LOOKAT ( ' MAPPING BKT INTO PAGE: ' , BPAGE );
LOOKAT ( ' PAGE COUNT: ' , NOPAGES );
$CALL (PAGIN, %( JFN )% .FST [ FSTJFN ],
%( FILE PAGE NO. )% .FPAGE,
%( DEST. PAGE NO. )% .BPAGE,
%( ACCESS BITS )% .FST[FSTFAC],
%( PAGE COUNT )% .NOPAGES);
END;
%([ LOCK THE BUCKET IF THE CALLER WANTED US TO ])%
BKTDESC [ BKDFLAGS ] = ZERO;
IF .WANTTOLOCK
THEN
BEGIN %( LOCK THE BUCKET )%
IF INPUTMODE
THEN
LOCKACC = ENQSHR ! SHARABLE LOCK
ELSE
LOCKACC = ENQEXC; ! EXCLUSIVE LOCK
IF LOCKBUCKET (.LOCKACC,.FPAGE) IS FALSE
THEN
BEGIN
CALLPUTBUF ( %(BKT SIZE)% LCI ( NOPAGES ),
%(BUFF PAGE)% LCI ( BPAGE ),
%(FLAG)% LCI ( INCORE ),
%(BF-DESC)% LCI ( BFDADR ) );
RETURNSTATUS ( ER$RLK )
END; %(OF ONERROR)%
BKTDESC [ BKDFLAGS ] = BKDFLGLOCKED ! MARK AS LOCKED
END; %(OF IF WANTTOLOCK)%
%([ RETURN FIELDS IN THE BUCKET DESCRIPTOR ])%
BKTDESC [ BKDBFDADR ] = .BFDADR; ! ADR OF BUFFER DESCRIPTOR
BKTDESC [ BKDBKTSIZE ] = .BKTSIZ; ! BUCKET SIZE IN BLOCKS
BKTDESC [ BKDBKTNO ] = .BKTNO; ! BUCKET NO.
BKTDESC [ BKDBKTADR ] = .BPAGE ^ P2W; ! ADDRESS OF BUCKET IN CORE
%([ DONE ])%
GOODRETURN
END; %( OF GETBKT )%
! PUTBKT
! ======
!
! THIS ROUTINE PERFORMS ALL FUNCTIONS RELATED TO RELEASING A
! BUCKET ( AND ITS ASSOCIATED BUFFER ) WHICH WAS OBTAINED VIA
! A CALL TO 'GETBKT'.
!
! ARGUMENTS:
! UPDATEFLAG = TRUE IF FILE BUCKET SHOULD BE UPDATED IMMEDIATELY
! BKTDESC = ADDRESS OF THE BUCKET DESCRIPTOR WHICH CONTAINS
! THE VALUES RETURNED BY 'GETBKT'
!
! RETURN VALUE:
! <NONE>
GLOBAL ROUTINE PUTBKT ( UPDATEFLAG, BKTDESC ):NOVALUE =
BEGIN
ARGUMENT (UPDATEFLAG,VALUE); ! UPDATE FILE PAGES FLAG
ARGUMENT (BKTDESC,BASEADD); ! ADR OF BUCKET DESCRIPTOR
MAP
BKTDESC: POINTER;
LOCAL
FPAGE, ! A FILE PAGE NO.
NOPAGES, ! A COUNT OF PAGES
BFDADR: POINTER, ! A POINTER TO A BFD
BPAGE; ! A BUFFER PAGE NO.
TRACE ( 'PUTBKT' );
CHECKINPUT( BKTDESC [ BKDBKTSIZE ] , ISNT , ZERO );
CHECKINPUT( BKTDESC [ BKDBKTADR ] , ISNT , ZERO );
BFDADR = .BKTDESC [ BKDBFDADR ]; ! GET BUFFER DESCRIPTOR ADDRESS
BPAGE = .BKTDESC [ BKDBKTADR ] ^ W2P; ! COMPUTE BUFFER PAGE NO.
!IF UPDATE APPLIES THEN IF NON-DEFERRED OR DYN-ALC THEN OUTPUT NOW.
IF ( .UPDATEFLAG ISNT FALSE )
THEN IF ( NOT DEFERREDWRITE ) OR .BKTDESC[BKDBFDADR] IS ZERO
THEN BEGIN %( UPDATE THE FILE PAGES )%
LOOKAT ( ' UPDATING BKT: ' , BKTDESC [ BKDBKTNO ] );
$CALL (PAGOUT, %( JFN )% .FST [ FSTJFN ],
%( FILE PAGE )% .BKTDESC [ BKDBKTNO ] ,
%( MEM PAGE )% .BPAGE,
%( PAGE COUNT )% .BKTDESC [ BKDBKTSIZE ] );
CLEARBFDUPD(BFDADR) !RESET FLAG
END %( OF UPDATE THE FILE PAGES )%
ELSE SETBFDUPD(BFDADR); !PRESERVE FACT THAT BKT NEEDS WRITING
%([ UNLOCK BUCKET IF 'GETBKT' LOCKED IT ])%
FPAGE = .BKTDESC [ BKDBKTNO ] ; ! GET FILE PAGE NO. OF BUCKET
IF BKTLOCKED (BKTDESC) ! IS BUCKET LOCKED?
THEN
BEGIN %( UNLOCK THE BUCKET )%
LOOKAT ( ' UNLOCKING BKT: ' , BKTDESC [ BKDBKTNO ] );
UNLOCKBUCKET ( .FPAGE ) ! YES, UNLOCK IT
END; %( OF UNLOCK THE BUCKET )%
%([ GIVE BUFFER BACK TO BUFFER MANAGER ])%
NOPAGES = .BKTDESC [ BKDBKTSIZE ];
BPAGE = .BKTDESC [ BKDBKTADR ] ^ W2P; ! COMPUTE BUFFER PAGE NO.
CALLPUTBUF ( %( NO. PAGES )% LCI ( NOPAGES ),
%( BUF PAGE NO. )% LCI ( BPAGE ),
%( INCORE FLAG )% PCI ( TRUE ),
%( BFD ADR )% LCI ( BFDADR ));
LOOKAT ( ' GAVE UP BUFFER FOR BUCKET: ' , BKTDESC [ BKDBKTNO ] );
%([ INDICATE THAT THIS BUCKET DESCRIPTOR IS EMPTY ])%
SETNULLBD ( BKTDESC );
%([ DONE ])%
RETURN
END; %( OF PUTBKT )%
! ALCBKT
! ======
!
! THIS ROUTINE ALLOCATES A BUCKET AT THE END OF AN INDEXED
! FILE. THE "END" OF FILE IS DETERMINED BY THE 'NXTBKT' FIELD
! IN THE FILE PROLOGUE TABLE. 'NXTBKT' WILL BE INCREMENTED TO
! POINT TO THE NEW "END" OF FILE.
!
!
! ARGUMENTS:
! BKTTYPE = BUCKET TYPE ( INDEX / DATA )
! BKTFLAGS = FLAGS TO BE STORED IN BUCKET HEADER
! LEVELNO = LEVEL NUMBER
! BKTDESC = BUCKET DESCRIPTOR ADDRESS (BKD FIELDS WILL BE RETURNED )
!
! RETURN VALUE:
! TRUE = SUCCESS
! FALSE = FAILURE:
! FILE IS FULL ( STATUS ERFUL )
! DYNAMIC MEMORY EXHAUSTED ( STATUS ERDME )
! <MISC. ERRORS RETURNED BY 'LOCKIT'>
!
! ARGUMENTS MODIFIED:
! BKTDESC = FIELDS IN BKD WILL BE RETURNED
!
! NOTES:
!
! 1. NOTE THAT BLOCK ZERO MAY NOT BE ALLOCATTED SINCE ZERO
! INDICATES THE "FILE IS FULL" CONDITION. BUT THIS IS OKAY SINCE
! THE FPT OWNS BLOCK ZERO ANYWAY.
!
GLOBAL ROUTINE ALCBKT ( BKTTYPE, BKTFLAGS, LEVELNO, BKTDESC ) =
BEGIN
%IF INDX %THEN
ARGUMENT(BKTTYPE,VALUE); ! BUCKET TYPE
ARGUMENT(BKTFLAGS,VALUE); ! BUCKET HEADER FLAGS
ARGUMENT(LEVELNO,VALUE); ! LEVEL NUMBER
ARGUMENT(BKTDESC,BASEADD); ! ADDRESS OF BUCKET DESCRIPTOR
MAP
BKTDESC: POINTER;
LOCAL
TEMP, ! TEMP
BKTNO, ! BUCKET NUMBER
LOCKFLAG, ! FLAG TO LOCK PROLOGUE
BKT: POINTER, ! POINTER TO A BUCKET
BKD: FORMATS[ BDSIZE ]; ! A BUCKET DESCRIPTOR
REGISTER
BKTSIZE, ! BUCKET SIZE
FPT: POINTER; ! POINTER TO FILE PROLOGUE TABLE
TRACE ( 'ALCBKT' );
%([ GET BUCKET SIZE DEPENDING ON BUCKET TYPE ( INDEX/DATA ) ])%
IF .BKTTYPE IS BTYPEINDEX ! FIND BUCKET SIZE:
THEN BKTSIZE = .KDB [ KDBIBKZ ] ! BKT SIZE FOR INDEX BUCKET
ELSE BKTSIZE = .KDB [ KDBDBKZ ]; ! BKT SIZE FOR DATA BUCKET
%([ GET FILE PROLOGUE TABLE SO THAT WE CAN INCREMENT 'NXTBKT' ])%
RTRACE ( %STRING(' GETTING FPT',%CHAR(13),%CHAR(10)) );
IF CALLGETBKT (%( BUCKET NO. )% PCI ( FPTBLOCKNO ),
%( BKT SIZE )% PCI ( 1 ),
%( LOCK FLAG )% PCI ( FALSE ),
%( BUCKET DESC. )% LCT ( BKD )) IS FALSE
THEN BADRETURN; ! RETURN TO CALLER ON ERRROR
%([ GET ADR OF FPT ])%
FPT = .BKD [ BKDBKTADR ]; ! GET ADR OF FILE PROLOGUE TABLE
LOOKAT ( ' INPUT BUCKET SIZE: ' , BKTSIZE );
%([ GET THE NUMBER OF THE NEXT BUCKET TO ALLOCATE ])%
BKTNO = .FPT [ FPTNXTBKT ]; ! FETCH CURRENT 'NXTBKT'
LOOKAT ( ' CURRENT NXTBKT: ' , BKTNO );
%([ CHECK TO SEE IF THE FILE IS COMPLETELY FULL ])%
IF ( ( .BKTNO + .BKTSIZE ) LEQ HIGHESTBUCKETNO )
AND
.BKTNO ISNT ZERO
THEN FPT [ FPTNXTBKT ] = .BKTNO + .BKTSIZE ! STORE NEW 'NXTBKT'
ELSE FPT [ FPTNXTBKT ] = ZERO; ! INDICATE "FILE IS FULL" CONDITION
%([ REMEMBER THE HIGHEST BYTE IN THIS NEW BUCKET, SO THE
FILE'S EOF POINTER CAN BE SET PROPERLY WHEN THE FILE
IS CLOSED. ])%
RST [ RSTHYBYTE ] = .FPT [ FPTNXTBKT ] ^ B2W;
SIZEOFFILE = .RST [RSTHYBYTE]; !CROCK
LOOKAT ( ' NEW NXTBKT: ' , FPT [ FPTNXTBKT ] );
RTRACE ( %STRING(' RELEASING FPT',%CHAR(13),%CHAR(10)) );
%([ RELEASE THE FILE PROLOGUE PAGE ])%
CALLPUTBKT ( %( UPDATE FLAG )% PCI ( TRUE ),
%( BKT DESC. )% LCT ( BKD ));
%([ MAKE SURE FILE HASN'T RUN OUT OF SPACE ])%
IF ( .BKTNO + .BKTSIZE - 1 ) GTR HIGHESTBUCKETNO ! IS FILE FULL?
OR
.BKTNO IS ZERO
THEN
BEGIN %( HANDLE FULL FILE )%
RTRACE ( %STRING(' FILE IS FULL',%CHAR(13),%CHAR(10)) );
RETURNSTATUS ( ER$FUL ) ! YES, RETURN "FILE IS FULL" CONDITION TO CALLER
END; %( OF HANDLE FILE IS FULL )%
%([ NOW GET THE NEW BUCKET INTO A BUFFER ])%
LOOKAT ( ' GETTING BKT: ' , BKTNO );
LOOKAT ( ' SIZE (IN BLOCKS) IS: ' , BKTSIZE );
TEMP = .BKTSIZE; ! STORE IN LOCAL
IF CALLGETBKT (%( BUCKET NO. )% LCI ( BKTNO ),
%( BUCKET SIZE )% LCI ( TEMP ),
%( LOCK FLAG )% PCI ( FALSE ),
%( BUCKET DESC. ADR )% BPT ( BKTDESC )) IS FALSE
THEN BADRETURN;
%([ NOW FILL IN THE BUCKET HEADER ])%
BKT = .BKTDESC [ BKDBKTADR ]; ! GET ADR OF BUCKET
BKT [ BHBTYPE ] = .BKTTYPE; ! FILL IN BUCKET TYPE (INDEX/DATA)
BKT [ BHFLAGS ] = .BKTFLAGS; ! FILL IN BUCKET HEADER FLAGS
BKT [ BHNEXTBYTE ] = BHHDRSIZE; ! FILL IN FIRST FREE BYTE NO.
IF .BKTTYPE IS BTYPEINDEX
THEN
BKT [ BHTHISAREA ] = .KDB [ KDBIAN ] ! FILL IN AREA NO. FOR INDEX BUCKET
ELSE
BKT [ BHTHISAREA ] = .KDB [ KDBDAN ]; ! FILL IN AREA NO. FOR DATA BUCKET
BKT [ BHLASTID ] = HIGHESTID; ! INITIALIZE LAST RECORD ID
BKT [ BHNEXTID ] = FIRSTID; ! INITIALIZE NEXT ID TO USE
BKT [ BHLEVEL ] = .LEVELNO; ! INITIALIZE LEVEL NO.
BKT [ BHUNUSED ] = ZERO; ! CLEAR UNUSED BITS
%([ DONE ])%
GOODRETURN ! GIVE SUCCESSFUL RETURN TO CALLER
%FI
END; %( OF ALCBKT )%
END
ELUDOM