Google
 

Trailing-Edge - PDP-10 Archives - RMS-10_T10_704_FT2_880425 - 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