; ; B$DEALOCATE ; ; B$DEALOCATE - INTERNAL ROUTINE TO DEALOCATE BLOCKS ; ; ROUTINE NAME: B$DEALOCATE ; ; PURPOSE: Dealocates blocks in a database file and adds them ; to the free list. ; ; CALLABLE: From MACRO only. ; ; PARAMETERS: ; R4 Pointer to root block and I/O buffers. ; R3 Scratch regester used to hold the address of the ; block to be dealocated. ; R2 The level table stack pointer. ; R1 Scratch regester to contain the block number. ; R0 Another scratch block number. ; ; ROUTINES USED: B$IOERROR, READVB and WRITEVB macros. ; ; AUTHOR: Mike Higgins ; ; SOURCE LANGUAGE: MACRO11 with SUPERMAC ; ; OBJECT MODULE NAME: B$DEAL ; ; LIBRARY: [60,100]DATABASE ; ; MAINTENANCE: See Mike Higgins ; ; ;REGESTER ASSIGNMENTS ROOT=R4 BUF=R3 LEVEL=R2 BLK=R1 NXT=R0 .MCALL SUPER SUPER PROCEDURE B$DEALOCATE LET BUF := RT.BUF(ROOT) ;GET THE ADDRESS OF THE BLOCK LET NXT := DB.PNB(BUF) ;GET THE ADDRESS OF IT'S OFSPRING LET DB.PNB(BUF) := RT.FRE(ROOT) ;POINT THE BLOCK AT THE TOP OF THE FREE LIST LET RT.FRE(ROOT) := LV.PCB(LEVEL) ;POINT THE FREE LIST AT THE BLOCK LET DB.BLT(BUF) := #"FR ;MARK THE BLOCK AS A FREE BLOCK ;THE ROOT BLOCK HAS BEEN MODIFIED, MARK ;IT FOR WRITING TO THE DISK LET RT.FLG(ROOT) := RT.FLG(ROOT) SET.BY #FL.MOD ;THE DEALOCATED BLOCK MUST BE WRITTEN ;OUT ALSO LET LV.FLG(LEVEL) := . SET.BY #FL.MOD ;CALCULATE THE ADDRESS OF THE PARENT ;KEYS OFSPRING POINTER LET BLK := LV.PCE-LV.SIZE(LEVEL) + LV.LEN-LV.SIZE(LEVEL) - #2 IF (BLK) EQ RT.FRE(ROOT) ;IS THIS THE BLOCK I JUST DEALOCATED? ;YES, MARK THE PARENT KEYS BLOCK AS ;MIDIFIED, LET LV.FLG-LV.SIZE(LEVEL) := . SET.BY #FL.MOD LET (BLK) := NXT ;AND MODIFY THE KEYS POINTER IF RESULT IS EQ ;ARE THERE ANY MORE OSPRING BLOCKS? ;NO, DE-ACIVATE THIS LEVEL LET LV.FLG(LEVEL) := . OFF.BY #FL.ACT RETURN ERROR ;AND RETURN ERROR TO SIGNIFY THIS ELSE ;YES, WRITE THE NEW FREE BLOCK OUT WRITEVB RT.FRE(ROOT),BUF READVB NXT,BUF ;AND READ IN THE FIRST SIBBLING BLOCK ;POINT THE LEVEL TABLE AT THIS BLOCK LET LV.PCB(LEVEL) := NXT LET LV.PCE(LEVEL) := BUF ;TURN THE MODIFIED BIT OFF FOR THIS ONE LET LV.FLG(LEVEL) := . OFF.BY #FL.MOD RETURN NOERROR END END ;IF THE BLOCK DEALOCATED WAS NOT THE ;FIRST SIBBLING BLOCK, I MUST LINK ;THROUGH ALL THE REST OF THE BLOCKS ;UNTIL I FIND THE BLOCK THAT POINTED ;TO THE DEALOCATED ONE, AND LINK HIM ;PAST IT LET BLK := (BLK) ;GET THE BLOCK NUMBER OF THE FIRST SIBLING IF #FL.MOD SET.IN LV.FLG(LEVEL) ;MUST I WRITE OUT THE ONE IN CORE? WRITEVB RT.FREE(ROOT),BUF ;YES, I GUESS SO ;CLEAR THE MOD BIT AFTERWARDS LET LV.FLG(LEVEL) := . OFF.BY #FL.MOD END REPEAT ;LOOP FOR ALL THE SIBBLING BLOCKS READVB BLK,BUF ;READ IN THE NEXT ONE ;IS THIS THE ONE THAT POINTS TO THE ;DEALOCATED BLOCK??? IF DB.PNB(BUF) EQ RT.FRE(ROOT) ;YES, INITALIZE THE LEVEL TABLE TO ;POINT AT THIS ONE LET LV.PCB(LEVEL) := BLK ;POINT THIS BLOCK PAST THE DEALOCATED ONE LET DB.PNB(BUF) := NXT ;NOW THIS BLOCK IS MODIFIED LET LV.FLG(LEVEL) := . SET.BY #FL.MOD RETURN NOERROR END ;NOPE, THIS ISNT THE ONE, I MUST ;LINK TO THE NEXT SIBLING LET BLK := DB.PNB(BUF) END ; INFINATE REPEAT ENDPROCEDURE B$DEALOCATE .END