File: DBIndexPageImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Last edited by:
Suzuki: December 16, 1980 5:15 PM
MBrown: May 23, 1983 10:58 am
Cattell: September 21, 1982 9:27 pm
Willie-Sue, February 18, 1985 1:43:21 pm PST
Widom, September 4, 1985 9:41:49 pm PDT
Donahue, November 13, 1985 11:54:25 am PST
DIRECTORY
DBCommon,
DBSegment USING[AllocPage, FreePage, ReadPage, SegmentIDFromDBPage, SegmentIDFromSegment, UnlockPage, WriteLockedPage],
DBStoragePagetags USING [BTree],
DBIndex,
DBIndexPage;
DBIndexPageImpl: CEDAR PROGRAM
IMPORTS
DBSegment
EXPORTS
DBIndexPage
= BEGIN
Core: TYPE = DBIndex.Core;
Page: TYPE = DBIndex.Page;
PageObject: TYPE = DBIndex.PageObject;
RealIndexHandle: TYPE = DBIndex.RealIndexHandle;
global vars
PageList: Page;
TakeALookAtThis: SIGNAL = CODE;
BadPage: PUBLIC SIGNAL = CODE;
Public procs
DestroyPageList: PUBLIC PROC [s: DBCommon.Segment] =
BEGIN
p: Page;
segID: DBCommon.SegmentID = DBSegment.SegmentIDFromSegment[s];
p ← PageList;
DO
IF DBSegment.SegmentIDFromDBPage[p.db] = segID THEN {
IF NOT p.free THEN UnlockPage[p]; -- unlock page
p.tree← NIL; p.cache← NIL; p.db← 0; p.pointer← NIL; p.depth← 0 }; -- erase invalid data
p ← p.front;
IF p=PageList THEN EXIT;
ENDLOOP;
END;
DestroyPage: PUBLIC PROC [
segment: DBCommon.DBPage, p: Page, db: DBCommon.DBPage] =
Deallocates the Page and DBPage; it should have a lock count of 1
BEGIN
DBSegment.FreePage[segment, db, p.cache];
p.free ← TRUE;
END;
UnlockPage: PUBLIC PROC [p: Page] =
BEGIN
CheckTag[p.pointer];
DBSegment.UnlockPage[p.cache];
p.free ← TRUE;
END;
WriteAndUnlockPage: PUBLIC PROC [p: Page] =
BEGIN
CheckTag[p.pointer];
DBSegment.WriteLockedPage[p.cache];
DBSegment.UnlockPage[p.cache];
p.free ← TRUE;
END;
WritePage: PUBLIC PROC [p: DBIndex.Page] =
Mark page p as having been written, but keep locked.
BEGIN
CheckTag[p.pointer];
DBSegment.WriteLockedPage[p.cache];
END;
AllocatePage: PROC RETURNS [Page] =
Just allocates the DBIndex.Page, i.e. the HANDLE for the DBCommon.Page
returns a "free" page; caller is responsible for marking it not free.
BEGIN
ret: Page;
p: Page ← PageList;
UNTIL p.free = TRUE DO
p ← p.front;
IF p=PageList THEN GOTO NoFreePage;
REPEAT
NoFreePage => {ret ← NEW[PageObject];
PageList.front.back ← ret;
ret^ ← [NIL, DBCommon.NullDBPage, NIL, 0, NIL, TRUE, PageList.front, PageList];
PageList.front ← ret;
RETURN[ret]};
FINISHED => {RETURN[p]}
ENDLOOP;
END;
CreateEmptyPage: PUBLIC PROC [
tree: RealIndexHandle, level: CARDINAL, s: DBCommon.DBPage]
RETURNS [Page] = TRUSTED
level = 1 if it is a leaf
BEGIN
cache: DBCommon.CacheHandle;
db: DBCommon.DBPage;
h: Page;
p: LONG POINTER TO Core;
[db, cache, p] ← DBSegment.AllocPage[s];
p.tag.pageTag ← DBStoragePagetags.BTree;
p.left ← p.right ← DBCommon.NullDBPage;
p.size ← 0;
h ← AllocatePage[];
h.tree ← tree; h.db ← db; h.cache ← cache; h.depth ← level; h.pointer ← p;
h.free ← FALSE;
RETURN[h];
END;
GetPage: PUBLIC PROC [
tree: RealIndexHandle, db: DBCommon.DBPage, level: CARDINAL] RETURNS [Page] =
TRUSTED BEGIN
p: Page ← AllocatePage[];
cache: DBCommon.CacheHandle;
pointer: LONG POINTER TO Core;
[cache, pointer] ← DBSegment.ReadPage[db, p.cache];
CheckTag[pointer];
p.tree ← tree; p.db ← db; p.cache ← cache; p.depth ← level; p.pointer ← pointer;
p.free ← FALSE;
RETURN[p]
END;
CheckTag: PUBLIC PROC[p: LONG POINTER TO Core] = TRUSTED {
IF p.tag.pageTag#DBStoragePagetags.BTree THEN SIGNAL BadPage};
Main part
PageList ← NEW[PageObject];
PageList.front ← PageList.back ← PageList;
PageList.free ← TRUE;
END.
Change Log:
Added to check page tag in CreateOldPage
by Suzuki November 24, 1980 9:06 AM
Changed FreePage. Now Unlocks the page
by Suzuki November 24, 1980 1:33 PM
Changed AllocatePage. Now initializes the page if it was obtained via AllocateHeapNode
by MBrown December 13, 1980 12:41 AM
Allocate storage from heap storage mdsZone
by MBrown February 27, 1981 6:18 PM
Convert to Cedar
by Cattell 7-Jun-81 11:24:59
Fixed bug in DestroyPageList: it didn't deallocate the PageObjects, and later code was trying to treat the cache hints to non-existent storage as real!
by Cattell June 24, 1982 11:18 am
Changed PageObjects from POINTERs to REFs.
by Cattell August 6, 1982 5:10 pm
Eliminated import of heap storage allocator.
by MBrown August 7, 1982 9:38 pm
Added BadPage signal.
by Cattell August 25, 1982 5:21 pm
The following invariant of the "page" data structure was getting messed up: NOT p.free iff DBSegment.LockCount[p.db, p.cache] > 0. The problem was that p.free was assigned FALSE, then a DBSegment call was made that can raise transaction aborted, then p.cache was assigned. Fix is to have AllocatePage return a page with p.free = TRUE, then make DBSegment call.
by MBrown May 23, 1983 10:58 am
Changed by Willie-Sue on February 18, 1985
made Cedar, added tioga formatting