File: DBIndexHandleImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Created by: Suzuki, December 8, 1980 2:19 PM
Last edited by:
Suzuki, December 8, 1980 3:09 PM
MBrown, February 27, 1981 5:31 PM
Cattell, September 15, 1983 4:05 pm
Willie-Sue on February 18, 1985 1:19:53 pm PST
Widom on September 4, 1985 9:12:43 pm PDT
DIRECTORY
DBCommon,
DBSegment,
DBStorage,
DBStorageInternal,
DBIndex,
DBIndexHandle,
IO;
DBIndexHandleImpl:
CEDAR PROGRAM
IMPORTS
DBCommon,
DBSegment,
DBStorageInternal,
IO
= {
RealIndexHandle: TYPE = DBIndex.RealIndexHandle;
IndexObject: TYPE = DBIndex.IndexObject;
PriorityList: RealIndexHandle;
this points to a ring buffer of RealIndexHandle's. They form a LRU list, with PriorityList pointing to the most recently used Index and the next one is PriorityList.back, ...back. If what PriorityList points to is free, then everything on the ring buffer is free. If there is any free Index, PriorityList.fron points to a free Index.
FinalizeIndexHandle:
PUBLIC
PROC [s: DBCommon.Segment] =
BEGIN
i: RealIndexHandle;
FOR i ← PriorityList, i.back
UNTIL i.back = PriorityList
DO
IF DBSegment.SegmentFromTID[i.tid] = s
THEN {
IF i.free AND i.depth # 0 THEN ERROR;
i.free ← TRUE; i.depth ← 0 };
ENDLOOP;
END;
IndexHandle manipulation
CreateNewRealIndexHandle:
PUBLIC
PROC [tid: DBStorageInternal.
TID] =
Creates a RealIndexHandle at the head of LRU queue, and set tid.
BEGIN
q: RealIndexHandle;
IF PriorityList.front.free
THEN
BEGIN PriorityList ← PriorityList.front; GOTO Initialize END
ELSE
BEGIN
q ← NEW[IndexObject];
q.front ← PriorityList.front;
q.back ← PriorityList;
PriorityList.front.back ← q;
PriorityList.front ← q;
PriorityList ← q;
GOTO Initialize
END;
EXITS
Initialize => {
PriorityList^ ←
[tid, Segment[tid], DBCommon.NullDBPage,
NIL, 0, PriorityList.front,
PriorityList.back, FALSE]};
END;
GetOldRealIndexHandle:
PUBLIC
PROC [x: DBStorage.IndexHandle]
RETURNS [RealIndexHandle] =
Returns the actual index handle out of the tuple level's tuple that represents it.
BEGIN
q: RealIndexHandle ← PriorityList;
tid: DBStorageInternal.TID ← DBStorageInternal.TIDOfTuple[x];
DO
IF q.free THEN GOTO NotFound;
IF q.tid = tid
THEN {
put it at the front of PriorityList
IF q = PriorityList THEN GOTO Found;
q.front.back ← q.back;
q.back.front ← q.front;
q.front ← PriorityList.front;
PriorityList.front.back ← q;
PriorityList.front ← q;
q.back ← PriorityList;
PriorityList ← q;
GOTO Found};
q ← q.back;
IF q = PriorityList THEN GOTO NotFound;
REPEAT
Found => {RETURN[q]};
NotFound => {
ttr: DBStorageInternal.TupleTree← NEW[DBStorageInternal.TupleTreeRecord];
CreateNewRealIndexHandle[tid];
DBStorageInternal.ReadIndexObject[x, ttr];
PriorityList.rootDB ← ttr.rootPA;
PriorityList.depth ← ttr.depth;
RETURN[PriorityList]};
ENDLOOP;
END;
DestroyIndexHandle:
PUBLIC
PROC [q: RealIndexHandle] =
Deallocates the IndexObject. The real one, not the tuple level's.
Doesn't actually free any storage to system, just marks it free.
BEGIN
IF q.front = q
THEN
-- there is only on item
NULL
ELSE
IF q = PriorityList THEN PriorityList ← PriorityList.back
ELSE
BEGIN
q.front.back ← q.back;
q.back.front ← q.front;
q.front ← PriorityList.front;
q.back ← PriorityList;
q.front.back ← q;
PriorityList.front ← q
END;
q.free ← TRUE;
END;
DeleteHandle:
PUBLIC
PROC [q: RealIndexHandle] =
Deallocates the IndexObject
BEGIN
IF q.front = q
THEN
-- there is only on item
NULL
ELSE
IF q = PriorityList THEN PriorityList ← PriorityList.back
ELSE
BEGIN
q.front.back ← q.back;
q.back.front ← q.front;
q.front ← PriorityList.front;
q.back ← PriorityList;
q.front.back ← q;
PriorityList.front ← q
END;
q.rootDB ← DBCommon.NullDBPage;
q.root ← NIL;
q.depth ← 0;
q.free ← TRUE;
END;
Segment:
PROC [tid: DBStorageInternal.
TID]
RETURNS [DBCommon.DBPage] =
Returns the segment in which "tid" exists
BEGIN OPEN DBStorageInternal;
segment: DBCommon.DBPage;
tuple: DBStorage.TupleHandle ← MakeTupleHandle[tid, ];
segment ← SegmentIDOfTuple[tuple];
ReleaseTupleHandle[tuple];
RETURN[segment]
END;
PrintHandle:
PROC = {
q: RealIndexHandle ← PriorityList;
DO
DBCommon.GetDebugStream[].PutF["tid: %12bB, rootDB: %12bB, depth: %bB, %s*n",
IO.card[q.tid], IO.card[q.rootDB], IO.card[q.depth], IO.rope[IF q.free THEN "free" ELSE "not free"]];
q ← q.back;
IF q=PriorityList THEN EXIT;
ENDLOOP;
};
PriorityList ← NEW[IndexObject];
PriorityList.front ← PriorityList.back ← PriorityList;
PriorityList.free ← TRUE;
}.
CHANGE LOG
Changed by MBrown on December 15, 1980 10:15 AM
In FinalizeIndexHandle, set i.free ← TRUE in loop.
Changed by MBrown on February 27, 1981 5:34 PM
Allocate from zone. Use CWF instead of IODefs and StringDefs (!)
Changed by Cattell sometime in March 1981
Removed use of CWF.
Changed by Cattell on June 20, 1982 6:23 pm
Added some comments to procedures. Bad names for procs, should change the interface and recompile everything sometime.
Changed by Willie-Sue on June 25, 1982 9:19 am
IOStream => IO
Changed by Willie-Sue on June 30, 1982 4:50 pm
PrivateIO.DebugStream => DBCommon.GetDebugStream[]
Changed by Cattell on August 6, 1982 4:48 pm
POINTERs to REFs.
Changed by Cattell on September 21, 1982 9:20 pm
Re-organization of DBIndex level.
Changed by Willie-Sue on February 18, 1985
made Cedar, added tioga formatting