DIRECTORY Basics USING [LongNumber], Process USING [Detach], SafeStorage USING [CantEstablishFinalization, EnableFinalization, EstablishFinalization, FinalizationQueue, FQNext, NewFQ], YggDID USING [DID, EqualDIDs, HashDID], YggDIDMap USING [RunList], YggFile USING [FileHandle], YggFileInternal USING [FileHandleRep], YggInternal USING [FileHandle]; YggFileTableImpl: CEDAR MONITOR IMPORTS Process, SafeStorage, YggDID EXPORTS YggInternal, YggFileInternal = { FileHandle: TYPE = YggInternal.FileHandle; FileHandleRep: PUBLIC TYPE = YggFileInternal.FileHandleRep; HashValue: TYPE = [0..256); TableEntry: TYPE = LIST OF RECORD[ fh: YggFile.FileHandle, reissued: BOOL _ FALSE ]; Table: TYPE = ARRAY HashValue OF TableEntry; table: REF Table = NEW[Table _ ALL[NIL]]; lastInsert: CARD _ 0; lastRemove: CARD _ 0; contents: INT _ 0; debug: BOOL _ FALSE; Hash: PROC [did: YggDID.DID, fileUse: ATOM] RETURNS [HashValue] = TRUSTED { atomAddress: CARD32 = LOOPHOLE[fileUse]; didHash: CARD32 = YggDID.HashDID[did]; ah: Basics.LongNumber; dh: Basics.LongNumber; bh: CARD32; l: Basics.LongNumber; ah _ LOOPHOLE[atomAddress, Basics.LongNumber]; dh _ LOOPHOLE[didHash, Basics.LongNumber]; bh _ ah.hi + dh.lo; l _ [li[LOOPHOLE[bh]]]; RETURN[l.ll]; }; CountContents: INTERNAL PROC RETURNS [total: INT _ 0] = { FOR h: HashValue IN HashValue DO FOR fileList: TableEntry _ table[h], fileList.rest UNTIL fileList = NIL DO total _ total+1; ENDLOOP; ENDLOOP; }; CheckContents: INTERNAL PROC = { found: INT = CountContents[]; IF found # contents THEN ERROR ConfusedHash[]; }; Lookup: PUBLIC ENTRY PROC [runList: YggDIDMap.RunList, did: YggDID.DID, fileUse: ATOM] RETURNS [file: YggFile.FileHandle] = { ENABLE UNWIND => NULL; fileList: TableEntry; h: HashValue = Hash[did, fileUse]; FOR fileList _ table[h], fileList.rest UNTIL fileList = NIL DO IF YggDID.EqualDIDs[fileList.first.fh.did, did] AND fileList.first.fh.fileUse = fileUse THEN { fileList.first.reissued _ TRUE; file _ fileList.first.fh; EXIT; }; REPEAT FINISHED => { file _ InternalCreate[]; file.did _ did; file.fileUse _ fileUse; file.runList _ runList; FOR rl: YggDIDMap.RunList _ runList, rl.rest UNTIL rl = NIL DO file.sizeInPages _ MAX [rl.first.firstPage+rl.first.pages, file.sizeInPages]; ENDLOOP; InternalInsert[file]; } ENDLOOP; }; ConfusedHash: ERROR = CODE; allocNotInserted: INT _ 0; insertion: CONDITION; AllocForCreate: PUBLIC ENTRY PROC RETURNS [YggFile.FileHandle] = { ENABLE UNWIND => NULL; allocNotInserted _ allocNotInserted+1; RETURN[ InternalCreate[] ] }; Insert: PUBLIC ENTRY PROC [new: YggFile.FileHandle] = { ENABLE UNWIND => NULL; allocNotInserted _ allocNotInserted-1; BROADCAST insertion; InternalInsert[new]; }; DontInsert: PUBLIC ENTRY PROC = { allocNotInserted _ allocNotInserted-1; BROADCAST insertion; }; InternalInsert: INTERNAL PROC [new: YggFile.FileHandle] = { h: HashValue _ Hash[new.did, new.fileUse]; prev: TableEntry _ NIL; fileList: TableEntry _ table[h]; IF debug THEN CheckContents[]; DO IF fileList = NIL THEN { -- stick new at the end of this hash chain lastInsert _ LOOPHOLE[new, LONG CARDINAL]; -- for debugging contents _ contents+1; IF prev = NIL THEN table[h] _ LIST[[new, FALSE]] ELSE prev.rest _ CONS[[new, FALSE], NIL]--prev.rest = NIL--; SafeStorage.EnableFinalization[new]; EXIT }; prev _ fileList; fileList _ fileList.rest; ENDLOOP; IF debug THEN CheckContents[]; }; MyQueue: SafeStorage.FinalizationQueue = SafeStorage.NewFQ[length: 50]; Remove: INTERNAL PROC [old: YggFile.FileHandle] = { h: HashValue = Hash[old.did, old.fileUse]; prev: TableEntry _ NIL; fileList: TableEntry _ table[h]; IF debug THEN CheckContents[]; DO IF fileList = NIL THEN EXIT --ERROR--; -- old was not found in table. IF fileList.first.fh = old THEN { contents _ contents-1; IF prev = NIL THEN table[h] _ fileList.rest ELSE prev.rest _ fileList.rest; EXIT }; prev _ fileList; fileList _ fileList.rest; ENDLOOP; lastRemove _ LOOPHOLE[old, LONG CARDINAL]; IF debug THEN CheckContents[]; }; DuplicateHashTableEntry: ERROR = CODE; InternalCreate: INTERNAL PROC RETURNS [YggFile.FileHandle] = { RETURN[NEW[YggFileInternal.FileHandleRep _ []]] }; FileTableFinalizationProcess: PROC = { DO innerFileTableFinalizationProcess: ENTRY PROC [] = { ENABLE UNWIND => NULL; fileList: TableEntry _ NIL; h: HashValue = Hash[file.did, file.fileUse]; FOR fileList _ table[h], fileList.rest UNTIL fileList = NIL DO IF YggDID.EqualDIDs[fileList.first.fh.did, file.did] AND fileList.first.fh.fileUse = file.fileUse THEN { fileList.first.reissued _ TRUE; IF file # fileList.first.fh THEN ERROR; EXIT; }; REPEAT FINISHED => { -- not found! OK while testing in PrincOps, but ERROR in PCedar }; ENDLOOP; IF fileList # NIL THEN { IF fileList.first.reissued THEN { IF debug THEN { fh: TableEntry _ table[Hash[fileList.first.fh.did, fileList.first.fh.fileUse]]; UNTIL fh = NIL DO IF fh = fileList THEN EXIT ELSE fh _ fh.rest ENDLOOP; }; fileList.first.reissued _ FALSE; SafeStorage.EnableFinalization[fileList]; } ELSE { Remove[fileList.first.fh]; }; }; }; file: REF FileHandleRep _ NIL; file _ NARROW[SafeStorage.FQNext[MyQueue]]; innerFileTableFinalizationProcess[]; file _ NIL; ENDLOOP; }; SafeStorage.EstablishFinalization[type: CODE[YggFileInternal.FileHandleRep], npr: 1, fq: MyQueue ! SafeStorage.CantEstablishFinalization => CONTINUE;]; TRUSTED {Process.Detach[FORK FileTableFinalizationProcess[] ];}; }. VYggFileTableImpl.mesa - global table of open files (to cause sharing of handles) Copyright Σ 1985, 1986, 1988 by Xerox Corporation. All rights reserved. Andrew Birrell November 15, 1983 3:05 pm Levin, August 8, 1983 6:00 pm Schroeder, June 10, 1983 5:20 pm Rovner, November 9, 1983 11:19 am Russ Atkinson (RRA) May 14, 1985 12:35:48 pm PDT Bob Hagmann March 14, 1989 7:46:13 am PST Called by Lookup and by Insert Called only by InternalCreate and FileTableFinalizationProcess Called by Lookup and by AllocForCreate Uncomment the next line for non-PrincOps testing IF fh = NIL THEN ERROR; Κt˜codešœP™PKšœH™HKšœ)™)K™K™ K™!J™0K™)—K™šΟk ˜ Kšœœ˜Kšœœ ˜Kšœ œj˜{Kšœœ˜'Kšœ œ ˜Kšœœ˜Kšœœ˜&Kšœ œ˜—K˜šΟnœœ˜Kšœ˜$Kšœ˜$Kšœœ˜—K˜Kšœ œ˜+Kšœ œ!˜;K˜Kšœ œ ˜K˜š œ œœœœ˜"Kšœ˜Kšœ œ˜K˜—K˜Kšœœœ œ ˜,K˜Kš œœ œ œœ˜)K˜Kšœ œ˜Kšœ œ˜Kšœ œ˜Kšœœœ˜K˜š žœœœ œœœ˜KKšœ œœ ˜(Kšœ œ˜&Kšœ˜Kšœ˜Kšœœ˜ Kšœ˜Kšœœ!˜.Kšœœ˜*Kšœ˜Kšœœ˜Kšœ˜ Kšœ˜—K˜K˜š ž œœœœ œ ˜9šœœ ˜ šœ0œ ˜JKšœ˜Kšœ˜—Kšœ˜—Kšœ˜—K˜šž œœœ˜ Kšœœ˜Kšœœœ˜.Kšœ˜—K˜šžœœœœ*œ œœ˜}Kšœœœ˜Kšœ˜Kšœ"˜"šœ$œ ˜>šœ.œ%œ˜^Kšœœ˜Kšœ˜Kšœ˜Kšœ˜—šœœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜šœ*œœ˜>Kšœœ7˜MKšœ˜—Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜—K˜Kšœœœ˜K˜Kšœœ˜Kšœ  œ˜K˜š žœœœœœ˜BKšœœœ˜Kšœ&˜&Kšœ˜Kšœ˜—K˜šžœœœœ˜7Kšœœœ˜Kšœ' œ ˜;Kšœ˜Kšœ˜—K˜šž œœœœ˜!Kšœ' œ ˜;Kšœ˜—K˜šžœœœ˜;Kšœ™Kšœ*˜*Kšœœ˜Kšœ ˜ Kšœœ˜š˜šœ œœΟc*˜DKšœ œœœŸ˜™>Kšœ*˜*Kšœœ˜Kšœ ˜ Kšœœ˜š˜Kš œ œœŸ œŸ ˜Hšœœ˜!Kšœ˜Kšœœœœ˜KKš˜Kšœ˜—Kšœ˜Kšœ˜Kšœ˜—Kšœ œœœ˜*Kšœœ˜Kšœ˜—K˜Kšœœœ˜&K˜šžœœœœ˜>Kšœ&™&Kšœœ%˜/Kšœ˜—K˜K˜šžœœ˜&š˜šœ#œœ˜4Kšœœœ˜Kšœœ˜Kšœ,˜,šœ$œ œ˜>šœ3œ*œ˜hKšœœ˜Kšœœœ˜'Kšœ˜Kšœ˜—šœœŸΡbcl1˜VK˜—Kšœ˜—šœ œœ˜šœœ˜!šœœ˜KšœO˜Ošœœœœœœœœ˜GKš 0™0—Kšœœœœ™Kšœ˜—Kšœœ˜ Kšœ)˜)Kšœ˜—šœœ˜Kšœ˜Kšœ˜—Kšœ˜—K˜—Kšœœœ˜Kšœœ˜+Kšœ$˜$Kšœœ˜ Kšœ˜—Kšœ˜K˜—Kšœ(œk˜—Kšœœ$˜@K˜Kšœ˜—…—ή