<> <> <> <> DIRECTORY Basics, DocCache, PFS, PFSNames, SymTab, RedBlackTree, Rope, TiogaIO, TiogaOps, ViewerClasses, ViewerOps; DocCacheImpl: CEDAR MONITOR IMPORTS PFS, PFSNames, SymTab, RedBlackTree, Rope, TiogaIO, TiogaOps, ViewerOps EXPORTS DocCache = BEGIN OPEN DocCache; byRef: RedBlackTree.Table = RedBlackTree.Create[GetRef, CompareRef]; byName: SymTab.Ref = SymTab.Create[case: FALSE]; lastRef: INT ¬ FIRST[INT]; lastFile: ROPE ¬ NIL; lastDoc: TiogaNode ¬ NIL; cacheLimit: NAT ¬ 10; GetRef: PROC [data: REF ANY] RETURNS [key: REF INT] --RedBlackTree.GetKey-- = { e: Entry = NARROW[data]; key ¬ e.ref; }; CompareRef: PROC [k, data: REF ANY] RETURNS [c: Basics.Comparison] --RedBlackTree.Compare-- = { k1: REF INT = NARROW[k]; k2: REF INT = GetRef[data]; c ¬ SELECT k1­ FROM < k2­ => less, = k2­ => equal, > k2­ => greater, ENDCASE => ERROR; }; Entry: TYPE = REF EntryPrivate; EntryPrivate: TYPE = RECORD [ fullFileName: ROPE, doc: TiogaNode, ref: REF INT ]; GetDoc: PUBLIC PROC [fileName: ROPE] RETURNS [doc: TiogaNode] = { fullFileName: ROPE; --for debugging, until Cirio can read PFS.PATHs fullPath: PFS.PATH; short: PFSNames.Component; Search: PROC [v: ViewerClasses.Viewer] RETURNS [continue: BOOL ¬ TRUE]--ViewerOps.EnumProc-- = { IF v.file.Equal[fullFileName, FALSE] AND v.class.flavor = $Text THEN { tor: TiogaOps.Ref = TiogaOps.ViewerDoc[v]; IF tor # NIL THEN { TRUSTED {doc ¬ LOOPHOLE[tor]}; continue ¬ FALSE; }; }; }; GetFromCache: ENTRY PROC = { ENABLE UNWIND => { byRef.DestroyTable[]; byName.Erase[]; lastRef ¬ FIRST[INT]}; e: Entry; IF fullFileName.Equal[lastFile, FALSE] THEN {doc ¬ lastDoc; RETURN}; e ¬ NARROW[byName.Fetch[fullFileName].val]; IF e = NIL THEN { doc ¬ TiogaIO.FromFile[PFS.PathFromRope[fullFileName] ! TiogaIO.Error, PFS.Error => CONTINUE].root; IF doc=NIL THEN RETURN; e ¬ NEW [EntryPrivate ¬ [ fullFileName, doc, NEW [INT ¬ lastRef ¬ lastRef + 1] ]]; WHILE byRef.Size[] >= cacheLimit DO lru: Entry = NARROW[byRef.LookupSmallest[]]; [] ¬ byRef.Delete[lru.ref]; [] ¬ byName.Delete[lru.fullFileName]; ENDLOOP; IF NOT byName.Insert[fullFileName, e] THEN ERROR; byRef.Insert[e, e.ref]; } ELSE { doc ¬ e.doc; [] ¬ byRef.Delete[e.ref]; e.ref­ ¬ lastRef ¬ lastRef + 1; byRef.Insert[e, e.ref]; }; lastFile ¬ fullFileName; lastDoc ¬ doc; }; doc ¬ NIL; {ENABLE PFS.Error => {doc ¬ NIL; CONTINUE}; fullPath ¬ PFS.AbsoluteName[PFS.PathFromRope[fileName]]; short ¬ fullPath.ShortName[]; IF short.version = [none] THEN fullPath ¬ PFS.FileInfo[fullPath].fullFName; fullFileName ¬ PFS.RopeFromPath[fullPath]; ViewerOps.EnumerateViewers[Search]; IF doc # NIL THEN RETURN; GetFromCache[]; }}; END.