mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-09 02:30:13 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
1348 lines
44 KiB
Plaintext
1348 lines
44 KiB
Plaintext
;
|
|
; File: BTreeSvcs.a
|
|
;
|
|
; Contains: These routines provide service functions used to access
|
|
; and maintain a BTree file.
|
|
;
|
|
; Modified for Sys7.0 B*tree Manager by Kenny SC. Tung
|
|
;
|
|
; Copyright: © 1984-1992 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <SM1> 4/1/92 kc Changed the name prefex used to distinguish
|
|
; routines used by the external B-Tree manager
|
|
; from the versions used by the File System.
|
|
; ¥ Pre-SuperMario comments follow ¥
|
|
; <13> 9/16/91 JSM Cleanup header.
|
|
; <12> 2/21/91 KST dnf, #83596: Do not check for volume offline.
|
|
; <11> 11/12/90 dnf include FileMgrPrivateEqu.a
|
|
; <10> 9/27/90 KST Documentation changes only.
|
|
; <9> 8/3/90 KST ExtBTFlush should't call FlushCache directly. It will call FS's <SM1>
|
|
; flushfile only if D5 flag is set now.
|
|
; <8> 4/11/90 KST Use ExtBTMaxDepth and related equates. <SM1>
|
|
; <7> 4/5/90 KST make btDebug symbol default to 0.
|
|
; <6> 4/4/90 KST BTInsert didn't check for MaxDepth limit and returns no error.
|
|
; <5> 2/22/90 KST Documentation change and cleanup.
|
|
; <4> 2/16/90 KST Take out debugger code.
|
|
; <3> 2/16/90 KST Adding ExtGetUpdateHdr, ExtUpdateHdr routines for "RelMap" change.
|
|
; <2> 2/12/90 KST Adding documentation for BTInsert using new buffer scheme.
|
|
; 9/27/89 KSCT It used to use cache queue ptr from BTCCQptr(A4).now we pass
|
|
; SysCtlCPtr in BTFlush. The code will run on 7.0 without
|
|
; RamCAche.
|
|
; 8/31/89 KSCT We can't mark block before Updating the leaf record because of
|
|
; the new buffer scheme, not cache
|
|
; 8/29/89 KSCT Fixed 2 bugs in BTSearch. It branches to the wrong label
|
|
; (BSExit). This will causing a crash if the node hint is bad or
|
|
; the node is bad.
|
|
; 5/4/89 KSCT Fixed a bug in BTDelete, MOVE should be a long, not word.
|
|
; 4/11/89 KSCT Fixing a serious bug that B*Tree grows without checking the
|
|
; depth limit.
|
|
; 9/25/86 BB Updated to use new MPW equate files.
|
|
; 1/20/86 BB Fixed bug on CalBTVars, did not include space for a node pointer
|
|
; in the index record size calculation (not patched in ROm75).
|
|
; 12/18/85 BB BTInsert now checks for errors returned from ExtInitNode (not
|
|
; patched in ROm75).
|
|
; 11/20/85 BB Fixed update depth bug in BTDelete (ROM75 patch). Fixed ExtGetNode
|
|
; error return bug in BTDelete (ROM75 patch).
|
|
; 10/25/85 BB Added vectors for ROM versions.
|
|
; 10/22/85 BB Moved BTClose, BTFlush, and BTOpen to ExtBTSvcs from BtIntf.
|
|
; 10/21/85 BB Fixed bug in BTGetRecord which was trying to release a node it
|
|
; didn't have after getting an IO error.
|
|
; 10/14/85 BB Added use of new MOVEQ error equates.
|
|
; 10/10/85 BB Fixed BTDelete and BtInsert to use MarkBlock instead of always
|
|
; releasing nodes as "dirty". Added use of new MOVEQ equates for
|
|
; GetBlock,RelBlock, and FlushCache. Did some minor code clean up.
|
|
; 10/9/85 BB Fixed bug in calulation of the size of BTree variables.
|
|
; 10/1/85 LAK Changed to .Include TFSEqu for cache, BTree equates.
|
|
; 9/23/85 BB Modified BTDelete to call ExtClrNode for nodes being freed.
|
|
; 9/23/85 BB Modified BTInsert to not check for a null node pointer before
|
|
; calling ExtRelNode. ExtRelNode now checks for it.
|
|
; 9/3/85 BB Fixed bug in Btdelete that was releasing parent nodes as dirty.
|
|
; 8/29/85 BB Fixed bug in BTInsert that was releasing a node twice.
|
|
; 8/9/85 BB Added code to maintain leaf record count and 1st and last node
|
|
; numbers.
|
|
; 8/6/85 BB Updated to use equates for index and leaf node types.
|
|
; 7/10/85 BB Removed calls to BTFlush. This is now done by CM and FXM.
|
|
; 7/8/85 BB Modified BTInsert and BTDelete to maintain links for index nodes
|
|
; and to use the new ExtGetLtSib/ExtGetRtSib interface.
|
|
; 6/10/85 BB Added BTSetUP and BTCleanup subroutines.
|
|
; 6/5/85 BB Removed use of BTVars for temporary storage of data records.
|
|
; 5/30/85 BB Modified BTGetRecord to set up default node and index markers
|
|
; for BTree underflow/overflow conditions.
|
|
; 5/24/85 BB Added call to BTFlush after an insert or delete.
|
|
; 5/24/85 BB Modified all routines to selectively clear BTCB flags.
|
|
; 4/21/85 BB Modified BTGetRecord to update current node and record index
|
|
; marks after each successful call.
|
|
; 3/15/85 BB Modified to use A6 stack.
|
|
; 3/11/85 BB Added extend BTree file stuff.
|
|
; 2/26/85 BB Finished adding hints.
|
|
; 2/21/85 BB Added use of hints.
|
|
; 2/18/85 BB Modified to support variable length keys in leaf nodes.
|
|
; 2/12/85 BB Added save/restore for scratch registers
|
|
; 1/17/85 BB Removed use of BTree Global area (BTG).
|
|
; 1/5/85 BB Modified to return pointers to key and data record for BTSearch
|
|
; and BTGetRecord. BTDelete also modified to no longer return
|
|
; deleted record.
|
|
; 1/1/85 BB Modified BTOpen to set up address of external key-compare
|
|
; routine (currently "KeyCompare") in BTCB.
|
|
; 10/10/84 BB Modified for BTree files.
|
|
; 9/27/84 BB New today.
|
|
;
|
|
|
|
;__________________________________________________________________________________
|
|
;
|
|
; External
|
|
; Routines: BTClose - Closes a BTree file.
|
|
; BTDelete - Deletes a record from a BTree file given the key.
|
|
; BTFlush - Flushes a BTree file.
|
|
; BTGetRecord - Gets the next/previous record from a BTree file.
|
|
; BTInsert - Inserts a record into a BTree file given the key
|
|
; and data record.
|
|
; BTOpen - Opens a BTree file.
|
|
; BTSearch - Searches a BTree file for a record given the key.
|
|
; ExtBTUpdate - Marks the cache buffer containing the specified
|
|
; BTree node as updated (dirty).
|
|
; Internal
|
|
; Subroutines: BTCleanUp - Cleans up after a BTree service call.
|
|
; BTSetUp - Sets up for a BTree service call.
|
|
; CalBTVars - Calculates the size of the BTree Variable storage
|
|
; area (BTVars).
|
|
;
|
|
;__________________________________________________________________________________
|
|
|
|
BLANKS ON
|
|
STRING ASIS
|
|
|
|
PRINT OFF
|
|
LOAD 'StandardEqu.d'
|
|
INCLUDE 'BtreeEqu.a'
|
|
INCLUDE 'BtreePrivate.a' ; Use ExtBTMaxDepth <11Apr90><SM1>
|
|
include 'FileMgrPrivate.a'
|
|
PRINT ON
|
|
PRINT NOGEN
|
|
|
|
IF &trim(&type('btDebug')) = 'UNDEFINED' THEN
|
|
btDebug EQU 0
|
|
ENDIF
|
|
|
|
ExtBTSvcs PROC EXPORT
|
|
|
|
EXPORT ExtBTClose,ExtBTDelete,ExtBTFlush,ExtBTGetRecord,ExtBTInsert,ExtBTSearch ;<SM1>
|
|
EXPORT ExtBTUpdate
|
|
Export ExtGetUpdateHdr, ExtUpdateHdr ; <16Feb90>
|
|
|
|
IMPORT ExtAllocNode,ExtExtBTFile,ExtFreeNode
|
|
IMPORT ExtBuildIRec,ExtDeleteRec,ExtGetLtSib,ExtGetMaxkey,ExtGetRecA,ExtGetRtSib
|
|
IMPORT ExtInitNode,ExtInsertRec,ExtLocRec,ExtLocTPR,ExtSearchNode
|
|
IMPORT ExtUpdDRec,ExtUpdIKey, ExtLocBTCB
|
|
IMPORT ExtRotateLt,ExtSplitLT,ExtTreeSearch
|
|
IMPORT ExtClrNode,ExtGetNode,ExtRelNode
|
|
IMPORT ExtMarkBlock, ExtWriteBlock, ExtDoAOCRWF ;<SM1>
|
|
|
|
|
|
;__________________________________________________________________________________
|
|
;
|
|
; Routine: BTClose
|
|
;
|
|
; Function: Closes a BTree file. The BTree Header (BTH) is updated and the
|
|
; cache is flushed and trashed for the specified file. The BTCB
|
|
; memory is also released.
|
|
; Note: ExtBTFlush only flushes buffers to FS DiskCache not to disk. <SM1>
|
|
; Input: D0.W - file refnum
|
|
;
|
|
; Output: D0.W - result code
|
|
; 0 = ok
|
|
; -n = IO error
|
|
; 25Sep89 KSCT Don't call FlushCache, it is called in ExtBTFlush.
|
|
;__________________________________________________________________________________
|
|
ExtBTClose ;<SM1>
|
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|
MOVEM.L D1-D5/A0-A4,-(A6) ; save regs
|
|
MOVE.W D0,D3 ; D3 = file refnum
|
|
MOVE.W D3,D0 ; locate the BTCB
|
|
JSR ExtLocBTCB ;
|
|
;
|
|
; flush the BTCB and cache buffers for the file
|
|
MOVEQ #0,D5 ; clear flag so that it will not flush fs cache
|
|
JSR ExtBTFlush ; Flush everything first <SM1>
|
|
BNE.S BCExit ; error ->
|
|
|
|
; release BTCB memory
|
|
;
|
|
@2 MOVEA.L A4,A0 ; release the BTCB
|
|
_DisposPtr ;
|
|
MOVEA.L FCBSPtr,A4 ; clear BTCB ptr
|
|
CLR.L FCBBTCBptr(A4,D3.W) ; ... in FCB
|
|
|
|
CLR.W D0 ; result = 'ok'
|
|
BCExit
|
|
MOVEM.L (A6)+,D1-D5/A0-A4 ; restore regs
|
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|
TST.W D0 ; set condition codes
|
|
RTS ; exit BTClose
|
|
|
|
|
|
|
|
|
|
;__________________________________________________________________________________
|
|
;
|
|
; Routine: BTDelete
|
|
;
|
|
; Function: Deletes a record from a BTree file given the key.
|
|
;
|
|
; Input: A0.L - address of key
|
|
; D0.W - file refnum
|
|
;
|
|
; Output: D0.W - result code
|
|
; 0 = ok
|
|
; BTnotfound = record not found
|
|
; other = error
|
|
;__________________________________________________________________________________
|
|
|
|
ExtBTDelete ;<SM1>
|
|
; MOVE.L jBTDelete,-(SP) ; jumptable entry for vBTDelete <25Oct85>
|
|
; RTS ; go there <25Oct85>
|
|
;vBTDelete ; 'vectored' BTDelete routine <25Oct85>
|
|
|
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|
MOVEM.L D1-D5/A0-A4,-(A6) ; save regs
|
|
;
|
|
; initialize some things
|
|
;
|
|
BSR BTSetUp ; set up common stuff
|
|
|
|
CLR.L BTCNodeM(A4) ; invalidate current node mark
|
|
|
|
SUBA.L A2,A2 ; ...no left node buffer
|
|
SUBA.L A3,A3 ; ...no right node buffer
|
|
;
|
|
; search tree for key
|
|
;
|
|
JSR ExtTreeSearch ; search for key
|
|
MOVEA.L A1,A3 ; A3 = ptr(node buffer)
|
|
BNE BDExit1 ; didn't find it ->
|
|
MOVE.W D1,D5 ; D5 = record index
|
|
;
|
|
; delete record from node
|
|
;
|
|
BDDelete
|
|
MOVEA.L A3,A1 ; ptr(node buffer)
|
|
MOVE.W D5,D1 ; record index
|
|
JSR ExtDeleteRec ; delete it
|
|
|
|
MOVEA.L A3,A0 ; ptr(node buffer) <10Oct85>
|
|
JSR ExtMarkBlock ; mark it dirty <10Oct85> <SM1>
|
|
|
|
TST.W D5 ; delete 1st record ?
|
|
BNE.S @1 ; no ->
|
|
BSET #BTCKeyUpd,BTCFlags(A4) ; indicate key update required
|
|
|
|
@1 CMPI.B #NDLeafNode,NDType(A3) ; at leaf level?
|
|
BNE.S BDRemove ; no ->
|
|
SUB.L #1,BTCNRecs(A4) ; decrement number of leaf records
|
|
|
|
;
|
|
; unlink the node if the last record was deleted
|
|
;
|
|
BDRemove
|
|
TST.W NDNRecs(A3) ; node empty ?
|
|
BGT.S BDNxtLev ; no ->
|
|
|
|
MOVEA.L A3,A0 ; ptr(node buffer)
|
|
JSR ExtGetLtSib ; get left sibling node
|
|
BNE BDExit1 ; error ->
|
|
TST.L D1 ; is there a left sibling ?
|
|
BEQ.S @1 ; no ->
|
|
|
|
MOVE.L NDFlink(A3),NDFlink(A1) ; update forward link
|
|
MOVEQ #kRBdirty,D1 ; release <10Oct85>
|
|
MOVEA.L A1,A0 ;
|
|
JSR ExtRelNode ; ...left node buffer
|
|
|
|
@1 MOVEA.L A3,A0 ; ptr(node buffer)
|
|
JSR ExtGetRtSib ; get right sibling node
|
|
BNE BDExit1 ; error ->
|
|
TST.L D1 ; is there a right sibling ?
|
|
BEQ.S BDUpdPtrs ; no ->
|
|
|
|
MOVE.L NDBlink(A3),NDBlink(A1) ; update backward link
|
|
MOVEQ #kRBdirty,D1 ; release <10Oct85>
|
|
MOVEA.L A1,A0 ;
|
|
JSR ExtRelNode ; ...right node buffer
|
|
;
|
|
; update 1st and last node pointers
|
|
;
|
|
BDUpdPtrs
|
|
CMPI.B #NDLeafNode,NDType(A3) ; at leaf level?
|
|
BNE.S BDFree ; no ->
|
|
|
|
TST.L NDBLink(A3) ; backward link = 0?
|
|
BNE.S @1 ; no ->
|
|
MOVE.L NDFlink(A3),BTCFNode(A4) ; yes, update 1st node number
|
|
|
|
@1 TST.L NDFLink(A3) ; forward link = 0?
|
|
BNE.S BDFree ; no ->
|
|
MOVE.L NDBlink(A3),BTCLNode(A4) ; yes, update last node number
|
|
;
|
|
; free the empty node
|
|
;
|
|
BDFree
|
|
MOVEA.L A3,A0 ; clear the empty node <23Sep85>
|
|
JSR ExtClrNode ; <23Sep85>
|
|
|
|
MOVEQ #kRBdirty,D1 ; release <10Oct85>
|
|
JSR ExtRelNode ; ...node buffer
|
|
SUBA.L A3,A3 ; indicate no buffer
|
|
|
|
MOVE.W BTCLevel(A4),D0 ; locate
|
|
JSR ExtLocTPR ; ...TPR
|
|
|
|
MOVE.L TPRNodeN(A0),D1 ; free
|
|
MOVE.W BTCRefNum(A4),D0 ;
|
|
JSR ExtFreeNode ; ...the disk node
|
|
|
|
BSET #BTCDelIRec,BTCFlags(A4) ; indicate index record delete
|
|
BCLR #BTCKeyUpd,BTCFlags(A4) ; ...and no key update
|
|
;
|
|
; move to next level
|
|
;
|
|
BDNxtLev
|
|
SUB.W #1,BTCLevel(A4) ; bump to next level up
|
|
BEQ.S BDRoot ; up to root level ->
|
|
|
|
BTST #BTCKeyUpd,BTCFlags(A4) ; key update required ? <03Sep85>
|
|
BNE.S @1 ; yes -> <03Sep85>
|
|
BTST #BTCDelIRec,BTCFlags(A4) ; index record delete required ? <03Sep85>
|
|
BEQ BDExit ; no, all done -> <03Sep85>
|
|
|
|
@1 MOVE.W BTCLevel(A4),D0 ; locate TPR
|
|
JSR ExtLocTPR ; for this level
|
|
MOVE.W TPRRIndx(A0),D5 ; D5 = parent record index
|
|
MOVE.L TPRNodeN(A0),D2 ; D2 = parent node number
|
|
|
|
MOVEQ #0,D1 ; get parent node <10Oct85>
|
|
JSR ExtGetNode ;
|
|
BNE BDExit1 ; error -> <20Nov85>
|
|
MOVEA.L A0,A2 ; A2 = ptr(parent node buffer)
|
|
;
|
|
; update parent key
|
|
;
|
|
BDUpdKey
|
|
BTST #BTCKeyUpd,BTCFlags(A4) ; key update required ?
|
|
BEQ.S @1 ; no ->
|
|
|
|
MOVE.W D5,D0 ; locate
|
|
MOVEA.L A2,A1 ;
|
|
JSR ExtGetRecA ; ...parent index record
|
|
MOVE.L A0,-(SP) ; ...and save it
|
|
MOVE.L A3,A1 ; locate 1st key
|
|
CLR.W D0 ;
|
|
JSR ExtGetRecA ; ...in node
|
|
MOVEA.L (SP)+,A1 ; ptr(parent index record)
|
|
|
|
JSR ExtUpdIKey ; update the key
|
|
|
|
MOVEA.L A2,A0 ; ptr(parent node buffer) <10Oct85>
|
|
JSR ExtMarkBlock ; write it back <20Feb90><SM1>
|
|
|
|
TST.W D5 ; update to 1st key in node ?
|
|
BEQ.S @1 ; yes, leave flag set ->
|
|
BCLR #BTCKeyUpd,BTCFlags(A4) ; don't need to update next level
|
|
|
|
@1 MOVEQ #0,D1 ; release child <10Oct85>
|
|
MOVE.L A3,A0 ;
|
|
JSR ExtRelNode ; ...node buffer
|
|
|
|
MOVEA.L A2,A3 ; new child node = parent node
|
|
MOVE.L D2,D3 ; should be a long, not word <5/4/89>
|
|
;
|
|
; check if done
|
|
;
|
|
BCLR #BTCDelIRec,BTCFlags(A4) ; indx rec delete required ? <03Sep85>
|
|
BEQ.S @2 ; no ->
|
|
BRA BDDelete ; delete parent index record ->
|
|
|
|
@2 BTST #BTCKeyUpd,BTCFlags(A4) ; another key update required ?
|
|
BNE.S BDNxtLev ; yes ->
|
|
BRA.S BDExit ; no, all done ->
|
|
;
|
|
; up to the root, check for an empty tree
|
|
;
|
|
BDRoot
|
|
MOVE.L A3,D0 ; root node released?
|
|
BNE.S BDUpdDepth ; no ->
|
|
CLR.W BTCDepth(A4) ; set tree to empty state
|
|
CLR.L BTCRoot(A4) ;
|
|
BRA.S BDExit ; exit ->
|
|
;
|
|
; update tree depth
|
|
;
|
|
BDUpdDepth
|
|
CMPI.W #1,NDNRecs(A3) ; check # of records left in root
|
|
BGT.S BDExit ; > 1, all done ->
|
|
TST.B NDType(A3) ; index node ?
|
|
BNE.S BDExit ; no, all done ->
|
|
|
|
SUBQ.W #1,BTCDepth(A4) ; decrement tree depth
|
|
|
|
MOVEQ #0,D1 ; locate key and data for 1st record <10Oct85>
|
|
MOVEA.L A3,A1 ;
|
|
JSR ExtLocRec ; ... in node <10Oct85>
|
|
MOVE.L (A1),BTCRoot(A4) ; new root = child node <10Oct85>
|
|
;
|
|
; release the previous root node
|
|
;
|
|
MOVEA.L A3,A0 ; clear the node buffer <23Sep85>
|
|
JSR ExtClrNode ; <23Sep85>
|
|
|
|
MOVEQ #kRBdirty,D1 ; release the <10Oct85>
|
|
JSR ExtRelNode ; ...node buffer
|
|
SUBA.L A3,A3 ; indicate no buffer
|
|
|
|
MOVE.L D3,D1 ; free
|
|
MOVE.W BTCRefNum(A4),D0 ;
|
|
JSR ExtFreeNode ; ...the node
|
|
; <20Nov85>
|
|
; get new root node and check if depth can be reduced again <20Nov85>
|
|
; <20Nov85>
|
|
MOVE.L BTCRoot(A4),D3 ; D3 = new root node # <20Nov85>
|
|
MOVE.L D3,D2 ; get the new root node <20Nov85>
|
|
MOVEQ #0,D1 ; <20Nov85>
|
|
JSR ExtGetNode ; <20Nov85>
|
|
BNE.S BDExit1 ; error -> <20Nov85>
|
|
|
|
MOVEA.L A0,A3 ; A3 = ptr to node buffer <20Nov85>
|
|
BRA.S BDUpdDepth ; check out new root -> <20Nov85>
|
|
|
|
;
|
|
; release last node and exit
|
|
;
|
|
BDExit
|
|
BSET #BTCDirty,BTCFlags(A4) ; mark BTCB dirty
|
|
CLR.W D0 ; result = ok
|
|
BDExit1
|
|
MOVE.W D0,-(A6) ; save result code
|
|
|
|
MOVEA.L A3,A0 ; ptr(node buffer) <23Sep85>
|
|
MOVEQ #0,D1 ; <10Oct85>
|
|
JSR ExtRelNode ; release it
|
|
|
|
MOVE.W (A6)+,D0 ; restore result code
|
|
|
|
BSR BTCleanUP ; clean up
|
|
|
|
MOVEM.L (A6)+,D1-D5/A0-A4 ; restore regs <29Aug85>
|
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|
TST.W D0 ; set condition codes
|
|
RTS ; exit BTDelete
|
|
|
|
|
|
|
|
|
|
|
|
;__________________________________________________________________________________
|
|
;
|
|
; Routine: BTFlush
|
|
;
|
|
; Function: Flushes a BTree file. The BTree Header (BTH) is updated and the
|
|
; cache is flushed for the specified file.
|
|
;
|
|
; Input: D0.W - file refnum
|
|
; A4.L - BTCB
|
|
; D5.B - Write flag, If set then flush file system cache.
|
|
; Output: D0.W - result code
|
|
; 0 = ok
|
|
; -n = IO error
|
|
; 30Jul90 KST Flush B*Tree private cache buffers for the specific file.
|
|
; Only call FlushCache if D5 flag is set.
|
|
;__________________________________________________________________________________
|
|
|
|
ExtBTFlush ; 'vectored' BTFlush routine <25Oct85><SM1>
|
|
|
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|
MOVEM.L D1-D4/A0-A4,-(A6) ; save regs
|
|
MOVE.W D0,D3 ; D3 = file refnum
|
|
MOVEA.L FCBsPtr,A1 ; point into FCB array
|
|
MOVEA.L FCBVPtr(A1,D3.W),A2; point to VCB
|
|
|
|
; we have the BTCB already
|
|
; JSR ExtLocBTCB ; locate the BTCB
|
|
BCLR #BTCdirty,BTCFlags(A4) ; is the BTCB dirty?
|
|
BEQ.S BFFlush ; no, just flush cache ->
|
|
|
|
BSR.S ExtGetUpdateHdr ; get BTH from disk in A3 and update it
|
|
BNE.S BFExit ; can't get it <2/16/90>
|
|
; release cache buffer
|
|
MOVEQ #kRBdirty,D1 ; release 'dirty' <14Oct85>
|
|
MOVEA.L A3,A0 ; cache buffer ptr
|
|
JSR ExtRelNode ; release it
|
|
BNE.S BFExit ; error ->
|
|
;
|
|
; flush the private cache buffers for the B*Tree manager, don't call FlushCache.
|
|
; Note: this is a delayed write if D5 is not set. <01Aug90>
|
|
BFFlush
|
|
MOVEA.L BTCCQptr(A4),A3 ; ptr to cache queue <30Jul90>
|
|
MOVE.W btQBSize(A3),D4 ; D4=INIT B*Tree buffer size <30Jul90>
|
|
LEA btQBStart(A3),A3 ; A3=first buffer <30Jul90>
|
|
MOVEQ #btBufferN,D1 ; number of private buffers <30Jul90>
|
|
SUBQ #1,D1 ; for dbring <30Jul90>
|
|
@flushLoop
|
|
CMP.W btBHRefNum(A3),D3 ; same file? <30Jul90>
|
|
BNE.S @4 ; no <30Jul90>
|
|
BCLR #CBHdirty,btBHFlags(A3) ; buffer dirty? <30Jul90>
|
|
BEQ.S @4 ; no <30Jul90>
|
|
;; buffer dirty, so write it to FS, A4 trashed here. <30Jul90>
|
|
MOVEA.L A3,A4 ; A4 = ptr(buffer header) <30Jul90>
|
|
JSR ExtWriteBlock ; write block to FS <30Jul90>
|
|
|
|
@4 ADDA.W D4,A3 ; next buffer <30Jul90>
|
|
ADDA.W #lenBTBH,A3 ; ... and skip header <30Jul90>
|
|
DBRA D1,@flushLoop ; continue <30Jul90>
|
|
|
|
TST.B D5 ; flush fs cache? <01Aug90>
|
|
BEQ.S @BFRet ; no, all done <01Aug90>
|
|
;; here, call file system's flushcache <01Aug90>
|
|
MOVEa.L FSVarsPtr,A1 ; <01Aug90>
|
|
MOVEA.L fsVars.btMgr(A1),A1 ; <01Aug90>
|
|
MOVEA.L btVParam(A1),A0 ; A0 = BT Param <01Aug90>
|
|
MOVE.W D3,ioRefNum(A0) ; file refnum <01Aug90>
|
|
MOVEQ #DoFlushFile,D1 ; indicate this is FlushFile <01Aug90>
|
|
BSR ExtDoAOCRWF ; flush cache <01Aug90>
|
|
BNE.S BFExit ; error <01Aug90>
|
|
|
|
@BFRet MOVEQ #0,D0 ; no error <01Aug90>
|
|
; clean up and exit
|
|
;
|
|
BFExit
|
|
MOVEM.L (A6)+,D1-D4/A0-A4 ; restore regs
|
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|
TST.W D0 ; set condition codes
|
|
RTS ; exit BTFlush
|
|
|
|
; __________________________________________________________________________
|
|
; Function: get BTH from disk and update it from BTCB info
|
|
; Input: A4.L - BTCB <2/16/90>
|
|
; Output: D0=0 if read header and then A3.L = header buffer ptr
|
|
; Trashes: D0, D1, D2, A0, A1, A3
|
|
; __________________________________________________________________________
|
|
ExtGetUpdateHdr
|
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|
MOVEQ #0,D1 ; no options
|
|
MOVEQ #0,D2 ; BTH is disk block 0
|
|
JSR ExtGetNode ; get disk block
|
|
BNE.S @6 ; couldn't get it ->
|
|
MOVEA.L A0,A3 ; A3 = cache buffer ptr
|
|
BSR.S ExtUpdateHdr
|
|
|
|
@6 MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|
TST.W D0 ; set condition codes
|
|
RTS ; exit BTFlush
|
|
; __________________________________________________________________________
|
|
; Function: update BTH from BTCB info. This routine is SYNC.
|
|
; Input: A4.L = BTCB, A3.L = header buffer ptr.
|
|
; Output: D0=0 <2/16/90>
|
|
; Trashes: D0, A0, A1
|
|
; __________________________________________________________________________
|
|
ExtUpdateHdr
|
|
MOVE.W #LenMemBTH-1,D0 ; loop index
|
|
LEA BTCDepth(A4),A0 ; ptr(source)
|
|
LEA lenND(A3),A1 ; ptr(destination)
|
|
@4 MOVE.B (A0)+,(A1)+ ; move it
|
|
DBRA D0,@4 ; ...in
|
|
|
|
MOVEQ #0,D0
|
|
RTS
|
|
|
|
;__________________________________________________________________________________
|
|
;
|
|
; Routine: BTGetRecord
|
|
;
|
|
; Function: Gets a record from a BTree file. Any previous, current,
|
|
; or next record relative to the last BTSearch or BTGetRecord
|
|
; operation may be obtained.
|
|
;
|
|
; Input: D0.W - refnum
|
|
; D1.W - selection code
|
|
; -n = previous record
|
|
; 0 = current record
|
|
; +n = next record
|
|
;
|
|
; Output: D0.W - result code
|
|
; 0 = ok
|
|
; BTnotfound = record not found
|
|
; other = error
|
|
; A0.L - pointer to key
|
|
; A1.L - pointer to data record
|
|
; D1.W - size of data record
|
|
; D2.L - BTree hint
|
|
;__________________________________________________________________________________
|
|
|
|
ExtBTGetRecord ;
|
|
; MOVE.L jBTGetRecord,-(SP) ; jumptable entry for vBTGetRecord <25Oct85>
|
|
; RTS ; go there <25Oct85>
|
|
;vBTGetRecord ; 'vectored' BTGetRecord routine <25Oct85>
|
|
|
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|
MOVEM.L D3-D5/A2-A4,-(A6) ; save regs
|
|
;
|
|
; initialize some things
|
|
;
|
|
BSR BTSetUp ; set up common stuff
|
|
|
|
MOVE.W D1,D5 ; D5 = selection code
|
|
SUBA.L A3,A3 ; indicate no node buffer
|
|
;
|
|
; set up starting position in BTree
|
|
;
|
|
MOVE.W BTCIndexM(A4),D4 ; current index mark
|
|
MOVE.L BTCNodeM(A4),D3 ; current node mark
|
|
BNE.S @1 ; valid node number ->
|
|
MOVEQ #BTnotfound,D0 ; set return code <14Oct85>
|
|
BRA.S GRExit1 ; exit ->
|
|
@1 ADD.W D5,D4 ; adjust index
|
|
;
|
|
; locate the record relative to the starting position
|
|
;
|
|
GRLocate
|
|
BSR.S GRGetNode ; get the node
|
|
BNE.S GRExit1 ; error ->
|
|
|
|
@1 TST.W D4 ; check index bounds
|
|
BLT.S @3 ; < 0, get previous node ->
|
|
MOVE.W NDNRecs(A3),D1 ;
|
|
CMP.W D1,D4 ;
|
|
BLT.S GRGotIt ; < #recs, got it ->
|
|
|
|
MOVE.L NDFlink(A3),D0 ; get next node number
|
|
BEQ.S @2 ; don't have one ->
|
|
MOVE.L D0,D3 ; D3 = next node number
|
|
SUB.W D1,D4 ; adjust index
|
|
BRA.S GRLocate ; try next node
|
|
|
|
@2 MOVE.W D1,D4 ; new index mark = index of last record
|
|
SUBQ.W #1,D4 ;
|
|
BRA.S @5 ; use common exit ->
|
|
|
|
@3 MOVE.L NDBlink(A3),D0 ; get previous node number
|
|
BEQ.S @4 ; don't have one ->
|
|
MOVE.L D0,D3 ; D3 = previous node number
|
|
BSR.S GRGetNode ; get the previous node
|
|
BNE.S GRExit1 ; error ->
|
|
ADD.W NDNRecs(A3),D4 ; adjust index
|
|
BRA.S @1 ; check bounds again ->
|
|
|
|
@4 MOVEQ #0,D4 ; new index mark = index of first record
|
|
|
|
@5 MOVE.L D3,BTCNodeM(A4) ; new node mark
|
|
MOVE.W D4,BTCIndexM(A4) ; new index mark
|
|
MOVEQ #BTnotfound,D0 ; set return code <14Oct85>
|
|
BRA.S GRExit1 ; exit ->
|
|
;
|
|
; found the record, set up pointers to key and data
|
|
;
|
|
GRGotIt
|
|
MOVE.W D4,D1 ; record index
|
|
MOVEA.L A3,A1 ; ptr(node buffer)
|
|
JSR ExtLocRec ; locate key and data record
|
|
|
|
MOVE.L D3,BTCNodeM(A4) ; update current node
|
|
MOVE.W D4,BTCIndexM(A4) ; ...and index markers
|
|
;
|
|
; release node buffer and exit
|
|
;
|
|
GRExit
|
|
CLR.W D0 ; result = ok
|
|
GRExit1
|
|
MOVEM.L D0-D1/A0-A1,-(A6) ; save return stuff
|
|
BSR.S GRRelNode ; release node buffer
|
|
MOVEM.L (A6)+,D0-D1/A0-A1 ; restore return stuff
|
|
|
|
MOVE.L D3,D2 ; hint = node number
|
|
|
|
BSR BTCleanUP ; clean up
|
|
|
|
MOVEM.L (A6)+,D3-D5/A2-A4 ; restore regs
|
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|
TST.W D0 ; set condition codes
|
|
RTS ; exit BTGetRecord
|
|
|
|
;
|
|
; GRGetNode subroutine - releases current node and gets the next node.
|
|
; A3.L = ptr(current node buffer)
|
|
; D3.L = next node number
|
|
;
|
|
GRGetNode
|
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|
BSR.S GRRelNode ; release current node
|
|
MOVEQ #0,D1 ; no GetBlock options <10Oct85>
|
|
MOVE.L D3,D2 ; node number
|
|
JSR ExtGetNode ; get the node
|
|
BNE.S @1 ; error -> <21Oct85>
|
|
MOVEA.L A0,A3 ; A3 = ptr(next node buffer)
|
|
@1 MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|
TST.W D0 ; set condition codes
|
|
RTS ; exit GRGetNode
|
|
|
|
|
|
;
|
|
; GRRelNode subroutine - releases current node buffer.
|
|
; A3.L = ptr(current node buffer)
|
|
;
|
|
|
|
GRRelNode
|
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|
|
|
MOVEQ #0,D1 ; no RelBlock options <10Oct85>
|
|
MOVEA.L A3,A0 ; ptr(node buffer) <23Sep85>
|
|
JSR ExtRelNode ; release the node
|
|
SUBA.L A3,A3 ; indicate no node buffer
|
|
|
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|
TST.W D0 ; set condition codes
|
|
RTS ; exit GRRelNode
|
|
|
|
|
|
|
|
|
|
|
|
;__________________________________________________________________________________
|
|
;
|
|
; Routine: BTInsert
|
|
;
|
|
; Function: Inserts a record into a BTree file given the
|
|
; record key and data.
|
|
;
|
|
; Input: A0.L - address of key
|
|
; A1.L - address of record data
|
|
; D0.W - file refnum
|
|
; D1.W - size of DATA record
|
|
; D2.L - actual data size (in number of nodes) <23Feb90>
|
|
; Output: D0.W - result code
|
|
; 0 = ok
|
|
; BTexists = key already exists
|
|
; other = error
|
|
; D2.L - BTree hint
|
|
;__________________________________________________________________________________
|
|
|
|
ExtBTInsert ;
|
|
; MOVE.L jBTInsert,-(SP) ; jumptable entry for vBTInsert <25Oct85>
|
|
; RTS ; go there <25Oct85>
|
|
;vBTInsert ; 'vectored' BTInsert routine <25Oct85>
|
|
|
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|
MOVEM.L D1/D3-D7/A0-A4,-(A6) ; save registers
|
|
|
|
JSR ExtLocBTCB ; locate BTCB
|
|
|
|
MOVE.L A1,D7 ; D7 = ptr(record)
|
|
MOVE.W D1,D6 ; D6 = size of record
|
|
MOVE.L A0,D5 ; D5 = ptr(key)
|
|
;
|
|
; make sure there is enough file space for a worst case split
|
|
; In supporting the new special data record, no code needs to be changed at this lower
|
|
; level (the data record (A1) and size (D1) are representing the special record, not the
|
|
; actual data), except in allocating more disk space for the data. <23Feb90>
|
|
|
|
MOVEQ #1,D3 ; required space (in nodes) =
|
|
ADD.W BTCDepth(A4),D3 ; tree depth + 1
|
|
CMP.L BTCFree(A4),D3 ; enough space?
|
|
BLE.S BIInit ; yes ->
|
|
@1 JSR ExtExtBTFile ; extend the file
|
|
BNE BIExit2 ; couldn't do it ->
|
|
|
|
CMP.L BTCFree(A4),D3 ; enough space now?
|
|
BGT.S @1 ; no ->
|
|
;
|
|
; initialize some things
|
|
;
|
|
BIInit
|
|
MOVE.W BTCRefNum(A4),D0 ; set up common stuff
|
|
BSR BTSetUp ;
|
|
|
|
MOVEM.L D6/D7,-(A6) ;save input record size and ptr
|
|
|
|
MOVEQ #0,D4 ; indicate no parent node buffer <29Aug85>
|
|
SUBA.L A2,A2 ; ...no left node buffer
|
|
SUBA.L A3,A3 ; ...no right node buffer
|
|
|
|
CLR.L BTCNodeM(A4) ; invalidate current node mark
|
|
;
|
|
; build BTree record consisting of input key with a junk data record
|
|
;
|
|
MOVEA.L BTCVarPtr(A4),A1 ; dest = record buffer
|
|
LEA ExtBTVRecord(A1),A1 ; maxDepth changed <11Apr90>
|
|
MOVEA.L D5,A0 ; source = input key
|
|
MOVEQ #0,D0 ; get key length
|
|
MOVE.B (A0),D0 ;
|
|
ADDQ.L #2,D0 ; include length byte
|
|
LSR.L #1,D0 ;
|
|
LSL.L #1,D0 ; ...and adjust to word boundry
|
|
ADD.W D0,D6 ; total size = key size + data size
|
|
_BlockMove ; move in the key
|
|
|
|
ADDQ.W #1,D6 ; adjust total size to word boundry
|
|
LSR.W #1,D6 ;
|
|
LSL.W #1,D6 ;
|
|
MOVE.L A1,D7 ; D7 = ptr(Btree record)
|
|
;
|
|
; search tree for key
|
|
;
|
|
BISearch
|
|
JSR ExtTreeSearch ; search for key
|
|
MOVEA.L A1,A3 ; A3 = ptr(right node buffer)
|
|
BNE.S @1 ; key not found or error ->
|
|
MOVEQ #BTexists,D0 ; error, it already exists <14Oct85>
|
|
BRA BIExit1 ; exit ->
|
|
@1 CMP.W #BTnotfound,D0 ; key not found ?
|
|
BNE BIExit1 ; no, must be IO error ->
|
|
MOVE.L D2,D3 ; D3 = right node number
|
|
MOVE.W D1,D5 ; D5 = insert index
|
|
;
|
|
; if tree is empty, add 1st leaf node
|
|
;
|
|
TST.W BTCLevel(A4) ; tree empty ?
|
|
BGT.S BIInsert ; no ->
|
|
|
|
MOVE.W BTCRefNum(A4),D0 ; file refnum
|
|
JSR ExtAllocNode ; allocate the node
|
|
BNE BIExit1 ; error ->
|
|
|
|
MOVE.L D1,D3 ; D3 = new node number
|
|
|
|
JSR ExtInitNode ; get an initialized node
|
|
BNE BIExit1 ; error -> <18Dec85>
|
|
MOVEA.L A0,A3 ; A3 = ptr(new root node)
|
|
|
|
MOVE.B #NDLeafNode,NDType(A3) ; type = leaf node
|
|
MOVEQ #1,D0 ; node height = 1
|
|
MOVE.B D0,NDNHeight(A3) ;
|
|
|
|
MOVE.W D0,BTCDepth(A4) ; tree depth = 1
|
|
MOVE.L D3,BTCRoot(A4) ; new root node number
|
|
|
|
MOVE.L D3,BTCFNode(A4) ; 1st and last node pointers
|
|
MOVE.L D3,BTCLNode(A4) ;
|
|
|
|
MOVE.W #1,BTCLevel(A4) ; current level = 1
|
|
;
|
|
; try a simple insert first
|
|
;
|
|
BIInsert
|
|
MOVEA.L D7,A0 ; ptr(record)
|
|
MOVE.W D6,D0 ; record size
|
|
MOVEA.L A3,A1 ; ptr(node buffer)
|
|
MOVE.W D5,D1 ; insert index
|
|
JSR ExtInsertRec ; try to insert it
|
|
BNE.S BIRotate ; didn't make it ->
|
|
|
|
TST.W D5 ; insert a new 1st record ?
|
|
BNE.S BIInsDone ; no, insert complete ->
|
|
BSET #BTCKeyUpd,BTCFlags(A4) ; indicate key update required
|
|
BRA.S BIInsDone ; insert complete ->
|
|
;
|
|
; insert didn't work, try rotation into left sibling node
|
|
;
|
|
BIRotate
|
|
MOVEA.L A3,A0 ; ptr(node buffer)
|
|
JSR ExtGetLtSib ; get left sibling node
|
|
BNE BIExit1 ; error ->
|
|
TST.L D1 ; is there a left sibling ?
|
|
BEQ.S BISplit ; no ->
|
|
MOVE.L D1,D2 ; D2 = left node number
|
|
MOVEA.L A1,A2 ; A2 = ptr(left node buffer)
|
|
|
|
MOVEA.L D7,A0 ; ptr(record)
|
|
MOVE.W D6,D0 ; record size
|
|
MOVE.W D5,D1 ; insert index
|
|
JSR ExtRotateLt ; try rotating left, and insert the record
|
|
BNE.S BISplit ; didn't make it ->
|
|
BRA.S BISplit1 ; use common code -> <10Oct85>
|
|
;
|
|
; rotate didn't work, got to split
|
|
;
|
|
BISplit MOVEA.L D7,A0 ; ptr(record)
|
|
MOVE.W D6,D0 ; record size
|
|
MOVE.W D5,D1 ; insert index
|
|
JSR ExtSplitLT ; split left
|
|
BEQ.S @1 ; ok ->
|
|
MOVEQ #BTnoFit,D0 ; result = 'no fit' <14Oct85>
|
|
BRA BIExit1 ; exit ->
|
|
@1 BSET #BTCNewIRec,BTCFlags(A4) ; indicate new index record required <10Oct85>
|
|
|
|
BISplit1 ; <10Oct85>
|
|
BSET #BTCKeyUpd,BTCFlags(A4) ; indicate key update required <10Oct85>
|
|
MOVE.W D1,D5 ; D5 = new record index <10Oct85>
|
|
|
|
;; another problem with the new buffer scheme using ExtMarkBlock;<9/6/89>
|
|
;; A1.L=ptr(node buffer) containing new record ;<9/6/89>
|
|
CMPA.L A2,A1 ; new record in left node? ;<9/6/89>
|
|
BNE.S @4 ; no ;<9/6/89>
|
|
CMPI.B #NDleafNode,NDType(A1) ; leaf level? ;<9/6/89>
|
|
BNE.S @4 ; no, -> ;<9/6/89>
|
|
;; before we marking the leaf, update the data ;<9/6/89>
|
|
MOVEM.L (A6),A0/D0 ; get input record ptr and size ;<9/6/89>
|
|
JSR ExtUpdDRec ; replace the junk data record ;<9/6/89>
|
|
@4 MOVEA.L A2,A0 ; mark the left node dirty <10Oct85>
|
|
JSR ExtMarkBlock ; write it back <20Feb90>
|
|
;
|
|
; completed the record insert, clean up
|
|
;
|
|
BIInsDone
|
|
;; We can't mark block before Updating the leaf record: <8/31/89>
|
|
;; (because ExtMarkBlock is now writing block to cache)
|
|
CMPI.B #NDleafNode,NDType(A1) ; leaf level? <8/31/89>
|
|
BEQ.S @0 ; yes, -> <8/31/89>
|
|
MOVEA.L A3,A0 ; no, not leaf <8/31/89>
|
|
JSR ExtMarkBlock ; write it back <20Feb90>
|
|
BRA.S BICkDone ; all done if not leaf <8/31/89>
|
|
|
|
@0 MOVEM.L (A6),A0/D0 ; get input record ptr and size <8/31/89>
|
|
JSR ExtUpdDRec ; replace the junk data record <8/31/89>
|
|
MOVEA.L A3,A0 ; update and then mark it <8/31/89>
|
|
JSR ExtMarkBlock ; write it back <20Feb90>
|
|
|
|
ADD.L #1,BTCNRecs(A4) ; bump leaf record count
|
|
|
|
MOVE.W D5,BTCIndexM(A4) ; save index marker
|
|
MOVE.L D3,D0 ; assume right node number
|
|
CMPA.L A3,A1 ; is new record in right node?
|
|
BEQ.S @1 ; yes ->
|
|
MOVE.L D2,D0 ; no, use left node number
|
|
@1 MOVE.L D0,BTCNodeM(A4) ; save node marker
|
|
;
|
|
; Check if all done
|
|
;
|
|
BICkDone
|
|
BTST #BTCKeyUpd,BTCFlags(A4) ; key update required ?
|
|
BNE.S BINxtLev ; yes, move to next level ->
|
|
BTST #BTCNewIRec,BTCFlags(A4) ; new index record required ?
|
|
BEQ BIExit ; no, all done ->
|
|
;
|
|
; move to next level
|
|
;
|
|
BINxtLev
|
|
SUB.W #1,BTCLevel(A4) ; bump to next level up
|
|
BEQ BIRoot ; up to root level ->
|
|
|
|
MOVE.W BTCLevel(A4),D0 ; locate TPR
|
|
JSR ExtLocTPR ; for this level
|
|
MOVE.W TPRRIndx(A0),D5 ; D5 = parent record index
|
|
MOVE.L TPRNodeN(A0),D3 ; D3 = parent node number
|
|
|
|
MOVE.L D2,-(A6) ; save D2 (node hint)
|
|
MOVEQ #0,D1 ; get parent node <10Oct85>
|
|
MOVE.L D3,D2 ;
|
|
JSR ExtGetNode ;
|
|
|
|
BNE BIExit1 ; error -> D2 on a6 ????? <KSCT>
|
|
MOVE.L A0,D4 ; D4 = ptr(parent node buffer)
|
|
MOVE.L (A6)+,D2 ; restore D2
|
|
;
|
|
; update parent key
|
|
;
|
|
BIUpdKey
|
|
BTST #BTCKeyUpd,BTCFlags(A4) ; key update required ?
|
|
BEQ.S @1 ; no ->
|
|
|
|
MOVE.W D5,D0 ; locate
|
|
MOVEA.L D4,A1 ;
|
|
JSR ExtGetRecA ; ...parent index record
|
|
MOVE.L A0,-(SP) ; ...and save it
|
|
MOVEA.L A3,A1 ; locate 1st key
|
|
CLR.W D0 ;
|
|
JSR ExtGetRecA ; ...in right node
|
|
MOVEA.L (SP)+,A1 ; ptr(parent index record)
|
|
|
|
JSR ExtUpdIKey ; update the key
|
|
|
|
MOVEA.L D4,A0 ; mark the parent node dirty <10Oct85>
|
|
JSR ExtMarkBlock ; write it back <20Feb90>
|
|
|
|
TST.W D5 ; update to 1st key in node ?
|
|
BEQ.S @1 ; yes, leave flag set ->
|
|
BCLR #BTCKeyUpd,BTCFlags(A4) ; don't need to update next level
|
|
|
|
@1 MOVEQ #0,D1 ; release <10Oct85>
|
|
MOVEA.L A3,A0 ;
|
|
JSR ExtRelNode ; ... right node buffer
|
|
|
|
MOVEA.L D4,A3 ; parent is new right node
|
|
MOVEQ #0,D4 ; indicate no parent node buffer <29Aug85>
|
|
;
|
|
; build new index record pointing at new left node
|
|
;
|
|
BINewRec
|
|
BTST #BTCNewIRec,BTCFlags(A4) ; new index record required ?
|
|
BEQ.S @1 ; no ->
|
|
|
|
MOVEA.L A2,A1 ; left node
|
|
MOVE.L D2,D0 ; left node number
|
|
JSR ExtBuildIRec ; build index record
|
|
|
|
@1 MOVEQ #0,D1 ; release <10Oct85>
|
|
MOVEA.L A2,A0 ;
|
|
JSR ExtRelNode ; ... left node buffer
|
|
SUBA.L A2,A2 ; indicate no left node
|
|
;
|
|
; set up for insert of new index record
|
|
;
|
|
BTST #BTCNewIRec,BTCFlags(A4) ; new index record required ?
|
|
BEQ BICkDone ; no, check if done ->
|
|
|
|
MOVEA.L BTCVarPtr(A4),A0 ; locate new index record
|
|
LEA ExtBTVRecord(A0),A0 ; maxDepth changed <11Apr90>
|
|
MOVE.L A0,D7 ; D7 = ptr to new record
|
|
JSR ExtGetMaxkey ; max key length + 4 <10Oct85>
|
|
ADDQ.W #4,D0 ; = size of index record <10Oct85>
|
|
MOVE.W D0,D6 ; D6 = size of new record <10Oct85>
|
|
BCLR #BTCNewIRec,BTCFlags(A4) ; clear new index rec flag
|
|
BRA BIInsert ; insert new index record ->
|
|
;
|
|
; we updated the root, must add a level if it was split
|
|
;
|
|
BIRoot
|
|
BTST #BTCNewIRec,BTCFlags(A4) ; was root node split ?
|
|
BEQ BIExit ; no, all done ->
|
|
;
|
|
; set up a new root index node
|
|
;
|
|
|
|
MOVE.W BTCDepth(A4),D0 ; check tree depth <04Apr90>
|
|
CMPI #ExtBTMaxDepth,D0 ; is this the limit? <11Apr90>
|
|
BNE.S @0 ; no <04Apr90>
|
|
IF btDebug THEN
|
|
_debugger ; fatal error <04Apr90>
|
|
ENDIF
|
|
MOVE.W #btDepthErr,D0 ; punt on <04Apr90>
|
|
BRA.S BIExit1 ; error -> <04Apr90>
|
|
|
|
@0 MOVE.W BTCRefNum(A4),D0 ; volume refnum
|
|
JSR ExtAllocNode ; allocate the node
|
|
BNE.S BIExit1 ; error ->
|
|
|
|
MOVE.L D1,D3 ; D3 = new root node number
|
|
|
|
MOVE.L D3,D1 ; new node number
|
|
JSR ExtInitNode ; get an initialized node
|
|
BNE.S BIExit1 ; error -> <18Dec85>
|
|
MOVE.L A0,D4 ; D4 = ptr(new root node buffer)
|
|
|
|
MOVE.B #NDIndxNode,NDType(A0) ; type = index node
|
|
MOVEQ #1,D0 ; node height
|
|
ADD.W BTCDepth(A4),D0 ; = previous depth +1
|
|
MOVE.B D0,NDNHeight(A0) ;
|
|
;
|
|
; add index record for left node
|
|
;
|
|
MOVEA.L A2,A1 ; build index record
|
|
MOVE.L D2,D0 ;
|
|
JSR ExtBuildIRec ; ...for left node
|
|
|
|
JSR ExtGetMaxkey ; max key length + 4 <10Oct85>
|
|
ADDQ.W #4,D0 ; = size of index record <10Oct85>
|
|
MOVEA.L BTCVarPtr(A4),A0 ; locate new index record
|
|
LEA ExtBTVRecord(A0),A0 ; maxDepth changed <11Apr90>
|
|
MOVEA.L D4,A1 ; ptr(root node buffer)
|
|
CLR.W D1 ; insert index = 0
|
|
JSR ExtInsertRec ; insert it
|
|
;
|
|
; add index record for right node (previous root)
|
|
;
|
|
MOVE.W #1,D0 ; get node number
|
|
JSR ExtLocTPR ;
|
|
MOVE.L TPRNodeN(A0),D0 ; ...of previous root
|
|
MOVEA.L A3,A1 ; ptr(node buffer)
|
|
JSR ExtBuildIRec ; build index record
|
|
|
|
JSR ExtGetMaxkey ; max key length + 4 <10Oct85>
|
|
ADDQ.W #4,D0 ; = size of index record <10Oct85>
|
|
MOVEA.L BTCVarPtr(A4),A0 ; locate new index record
|
|
LEA ExtBTVRecord(A0),A0 ; maxDepth changed <11Apr90>
|
|
MOVEA.L D4,A1 ; ptr(root node buffer)
|
|
MOVE.W #1,D1 ; insert index = 1
|
|
JSR ExtInsertRec ; insert it
|
|
|
|
MOVEA.L D4,A0 ; mark the new root node dirty <10Oct85>
|
|
JSR ExtMarkBlock ; write it back <20Feb90>
|
|
;
|
|
; update BTCB
|
|
;
|
|
ADD.W #1,BTCDepth(A4) ; add a level
|
|
MOVE.L D3,BTCRoot(A4) ; new root node number
|
|
;
|
|
; clean up and exit
|
|
;
|
|
BIExit
|
|
BSET #BTCDirty,BTCFlags(A4) ; mark BTCB dirty
|
|
CLR.W D0 ; result = ok
|
|
BIExit1
|
|
MOVE.W D0,-(A6) ; save result code
|
|
|
|
MOVEA.L A2,A0 ; ptr(left node buffer) <23Sep85>
|
|
MOVEQ #0,D1 ; no RelBlock options <10Oct85>
|
|
JSR ExtRelNode ; release it
|
|
|
|
MOVEA.L A3,A0 ; ptr(right node buffer) <23Sep85>
|
|
JSR ExtRelNode ; release it
|
|
|
|
MOVEA.L D4,A0 ; ptr(parent node buffer) <23Sep85>
|
|
JSR ExtRelNode ; release it
|
|
|
|
MOVE.W (A6)+,D0 ; restore result code
|
|
|
|
MOVE.L BTCNodeM(A4),D2 ; return hint (node number)
|
|
CLR.L BTCNodeM(A4) ; invalidate current record markers
|
|
|
|
BSR BTCleanUP ; clean up
|
|
|
|
ADDQ.L #8,A6 ; deallocate saved stuff
|
|
BIExit2
|
|
MOVEM.L (A6)+,D1/D3-D7/A0-A4 ; restore regs
|
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|
TST.W D0 ; set condition codes
|
|
RTS ; exit BTInsert
|
|
|
|
|
|
;__________________________________________________________________________________
|
|
;
|
|
; Routine: BTSearch
|
|
;
|
|
; Function: Searches a BTree file for a record given the key. If a hint is
|
|
; given, the BTree node identified by that hint is obtained and
|
|
; searched first. Then, if the record is not found, a normal tree
|
|
; search is performed.
|
|
;
|
|
; Input: A0.L - pointer to key
|
|
; D0.W - file refnum
|
|
; D2.L - BTree hint
|
|
; 0 = no hint
|
|
;
|
|
; Output: D0.W - result code
|
|
; 0 = ok
|
|
; BTnotfound = record not found
|
|
; other = error
|
|
; A0.L - pointer to key
|
|
; A1.L - pointer to data record
|
|
; D1.W - size of data record
|
|
; D2.L - new BTree hint
|
|
;__________________________________________________________________________________
|
|
|
|
ExtBTSearch ;
|
|
; MOVE.L jBTSearch,-(SP) ; jumptable entry for vBTSearch <25Oct85>
|
|
; RTS ; go there <25Oct85>
|
|
;vBTSearch ; 'vectored' BTSearch routine <25Oct85>
|
|
|
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|
MOVEM.L D3-D7/A2-A4,-(A6) ; save regs
|
|
;
|
|
; initialize some things
|
|
;
|
|
BSR BTSetUp ; set up common stuff
|
|
|
|
MOVEA.L A0,A3 ; A3 = ptr to key
|
|
SUBA.L A2,A2 ; indicate no node buffer
|
|
;
|
|
; go directly to the leaf node if hint is given
|
|
;
|
|
TST.L D2 ; hint given?
|
|
BEQ.S BSTSrch ; no, do tree search ->
|
|
|
|
MOVEQ #0,D1 ; get target node <10Oct85>
|
|
JSR ExtGetNode ;
|
|
BNE.S BSExit1 ; error -> <07Sep89>
|
|
; this node has been released <07Sep89>
|
|
MOVEA.L A0,A2 ; A2 = ptr(node buffer)
|
|
|
|
CMPI.B #NDLeafNode,NDType(A0) ; leaf node?
|
|
BNE.S @1 ; no ->
|
|
TST.W NDNRecs(A0) ; node empty?
|
|
BLE.S @1 ; yes ->
|
|
|
|
MOVEA.L A3,A0 ; search node for key
|
|
MOVEA.L A2,A1 ;
|
|
JSR ExtSearchNode ;
|
|
BEQ.S BSTSrch1 ; found it ->
|
|
|
|
@1 MOVEA.L A2,A0 ; release node buffer
|
|
MOVEQ #0,D1 ; no RelBlock options <10Oct85>
|
|
JSR ExtRelNode ;
|
|
BNE.S BSExit1 ; error -> <07Sep89>
|
|
;
|
|
; search tree for key
|
|
;
|
|
BSTSrch
|
|
MOVEA.L A3,A0 ; ptr to key
|
|
JSR ExtTreeSearch ; search tree for key
|
|
MOVEA.L A1,A2 ; A2 = ptr(node buffer)
|
|
BEQ.S BSTSrch1 ; key found ->
|
|
CMP.W #BTnotfound,D0 ; key not found error ?
|
|
BNE.S BSExit1 ; no, must be IO error ->
|
|
BSTSrch1 MOVE.W D1,D5 ; D5 = record index
|
|
MOVE.W D0,-(A6) ; save search result
|
|
;
|
|
; update current markers in BTCB
|
|
;
|
|
MOVE.L D2,BTCNodeM(A4) ; update current node mark
|
|
MOVE.W D5,BTCIndexM(A4) ; ... and record index mark
|
|
;
|
|
; set up pointers to key and data record
|
|
;
|
|
TST.W (A6) ; record found?
|
|
BNE.S BSExit ; no ->
|
|
MOVE.W D5,D0 ; record index
|
|
MOVEA.L A2,A1 ; ptr(node buffer)
|
|
JSR ExtLocRec ; locate the record
|
|
;
|
|
; release node buffer and exit
|
|
;
|
|
BSExit
|
|
MOVEM.L D1-D2/A0-A1,-(A6) ; save return stuff
|
|
|
|
MOVEA.L A2,A0 ; ptr(node buffer) <23Sep85>
|
|
MOVEQ #0,D1 ; no RelBlock options <10Oct85>
|
|
JSR ExtRelNode ; release it
|
|
MOVEM.L (A6)+,D1-D2/A0-A1 ; restore return stuff
|
|
|
|
MOVE.W (A6)+,D0 ; restore search result
|
|
BSExit1
|
|
BSR.S BTCleanUP ; clean up
|
|
|
|
MOVEM.L (A6)+,D3-D7/A2-A4 ; restore regs
|
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|
TST.W D0 ; set condition codes
|
|
RTS ; exit BTSearch
|
|
|
|
|
|
|
|
|
|
|
|
;__________________________________________________________________________________
|
|
;
|
|
; Routine: ExtBTUpdate
|
|
;
|
|
; Function: Marks a buffer containing the specified BTree node as being
|
|
; updated (dirty).
|
|
;
|
|
; Input: D0.L - file refnum
|
|
; D2.L - BTree hint (node number of dirty node)
|
|
;
|
|
; Output: D0.W - result code
|
|
; 0 = ok
|
|
; BTnotfound = node not found
|
|
; other = IO error
|
|
;__________________________________________________________________________________
|
|
|
|
ExtBTUpdate
|
|
|
|
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
|
|
MOVEM.L D1/A0-A1/A4,-(A6) ; save regs
|
|
|
|
JSR ExtLocBTCB ; locate BTCB
|
|
|
|
MOVEQ #kGBexist,D1 ; indicate existing cache block <10Oct85>
|
|
JSR ExtGetNode ; get the node
|
|
BNE.S BUExit ; error ->
|
|
|
|
MOVEQ #kRBdirty,D1 ; indicate dirty buffer
|
|
JSR ExtRelNode ; release the node
|
|
BNE.S BUExit ; error ->
|
|
|
|
CLR.W D0 ; indicate no error
|
|
BUExit
|
|
MOVEM.L (A6)+,D1/A0-A1/A4 ; restore regs
|
|
MOVE.L (A6)+,-(SP) ; put return address back on stack
|
|
TST.W D0 ; set condition codes
|
|
RTS ; exit ExtBTUpdate
|
|
|
|
|
|
|
|
|
|
|
|
;__________________________________________________________________________________
|
|
;
|
|
; Internal Subroutines
|
|
;__________________________________________________________________________________
|
|
|
|
;__________________________________________________________________________________
|
|
;
|
|
; Subroutine: BTCleanUp (BTree Clean Up)
|
|
;
|
|
; Function: Cleans up after a BTree service call. Space for the BTree
|
|
; variable storage area (BTVars) is released and the pointer to
|
|
; BTVars in the BTCB is cleared.
|
|
;
|
|
; Input: A4.L - pointer to BTCB
|
|
;
|
|
; Output: none
|
|
;__________________________________________________________________________________
|
|
|
|
BTCleanUp
|
|
MOVE.L D0,-(SP) ; save registers
|
|
|
|
BSR.S CalBTVars ; calculate size of BTVars
|
|
ADDA.L D0,A6 ; remove BTVars from A6 stack
|
|
CLR.L BTCVarPtr(A4) ; clear pointer in BTCB
|
|
|
|
MOVE.L (SP)+,D0 ; restore registers
|
|
RTS ; exit BTCleanUp
|
|
|
|
|
|
|
|
|
|
|
|
;__________________________________________________________________________________
|
|
;
|
|
; Subroutine: BTSetUp (BTree Set Up)
|
|
;
|
|
; Function: Sets up for a BTree service call. The BTCB is located and space
|
|
; for the BTree variable storage area (BTVars) is allocated on the
|
|
; A6 stack. A pointer to BTVars is saved in the BTCB. All call-
|
|
; specific status flags in the BTCB are also cleared.
|
|
;
|
|
; Input: D0.W - file refnum
|
|
;
|
|
; Output: A4.L - pointer to BTCB
|
|
;__________________________________________________________________________________
|
|
|
|
BTSetUp
|
|
MOVE.L D0,-(SP) ; save registers
|
|
|
|
JSR ExtLocBTCB ; locate the BTCB
|
|
|
|
BSR.S CalBTVars ; calculate size of BTVars
|
|
SUBA.L D0,A6 ; allocate space on A6 stack
|
|
MOVE.L A6,BTCVarPtr(A4) ; save pointer in BTCB
|
|
|
|
BCLR #BTCNewIRec,BTCFlags(A4) ; clear status flags
|
|
BCLR #BTCDelIRec,BTCFlags(A4) ;
|
|
BCLR #BTCKeyUpd,BTCFlags(A4) ;
|
|
|
|
MOVE.L (SP)+,D0 ; restore registers
|
|
RTS ; exit BTSetUp
|
|
|
|
|
|
|
|
|
|
|
|
;__________________________________________________________________________________
|
|
;
|
|
; Subroutine: CalBTVars (Calculate size of BTVars)
|
|
;
|
|
; Function: Calculates the size of the BTree variable storage area (BTVars).
|
|
;
|
|
; Input: A4.L - pointer to BTCB
|
|
;
|
|
; Output: D0.L - size of BTVars
|
|
;__________________________________________________________________________________
|
|
|
|
CalBTVars
|
|
JSR ExtGetMaxkey ; get max key size <10Oct85>
|
|
ADDI.W #ExtlenTPT+4,D0 ; size of BTVars = length of TPT <11Apr90>
|
|
|
|
RTS ; exit CalBTVars
|
|
|
|
END
|
|
|
|
|