sys7.1-doc-wip/OS/HFS/Extensions/BTreeMgr/BTreeSvcs.a

1358 lines
45 KiB
Plaintext

;
; Hacks to match MacOS (most recent first):
;
; <Sys7.1> 8/3/92 Re-routed the unused function ExtBTUpdate through the trap table.
; 9/2/94 SuperMario ROM source dump (header preserved below)
;
;
; 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 jBTUpdate,-(SP) ; jumptable entry for vBTUpdate <25Oct85> <Sys7.1>
RTS ; go there <25Oct85> <Sys7.1>
vExtBTUpdate ; <Sys7.1>
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