-- File: DBIndexHandleImpl.mesa -- 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 June 30, 1982 4:50 pm DIRECTORY DBCommon, DBStorage, DBStorageInternal, DBIndex, DBIndexHandle, IO; DBIndexHandleImpl: PROGRAM IMPORTS DBCommon, DBStorageInternal, IO EXPORTS DBIndexHandle = { 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 = BEGIN i: RealIndexHandle; FOR i ← PriorityList, i.back UNTIL i.back = PriorityList DO 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.