DIRECTORY CIFS, Environment, File, Process, RefText, Rope, RTTypesBasic, SafeStorage, Space, UFFileManager; UFFileManagerImpl: CEDAR MONITOR IMPORTS CIFS, File, Process, RefText, Rope, RTTypesBasic, SafeStorage, Space EXPORTS UFFileManager = BEGIN OPEN UFFileManager; FontFile: PUBLIC TYPE = REF FontFilePermission; FontFilePermission: PUBLIC TYPE = RECORD [ link: REF FontFilePermission, key: Key ]; qZone: ZONE _ SafeStorage.NewZone[quantized]; FontFileDescription: TYPE = RECORD [ permissions: REF FontFilePermission, permissionHint: REF FontFilePermission, clientData: REF _ NIL, openFile: CIFS.OpenFile, errorCode: CIFS.ErrorCode, errorMsg: Rope.ROPE, space: Space.Handle, origin: LONG POINTER, size: INT -- in words ]; keyTable: REF KeyTableRec _ NEW[KeyTableRec[6]]; KeyTableRec: TYPE = RECORD [ numberOfEntries: NAT _ 0, entries: SEQUENCE length: NAT OF NameFilePair ]; NameFilePair: TYPE = RECORD [fileName: ROPE, description: REF FontFileDescription]; permissionCount: INT _ 0; permissionsSinceCollectionRequest: NAT _ 0; permissionThreshold: NAT _ 96; RequestCollection: PROC = { permissionsSinceCollectionRequest _ 0; SafeStorage.ReclaimCollectibleObjects[]; }; finalizationQueue: RTTypesBasic.FinalizationQueue _ RTTypesBasic.NewFQ[permissionThreshold]; FinalizerProcess: PROCEDURE [finalizationQueue: RTTypesBasic.FinalizationQueue] = { DO permission: REF FontFilePermission _ NARROW[RTTypesBasic.FQNext[finalizationQueue]]; key: Key _ permission.key; closed: BOOLEAN _ Finalize[permission]; permission _ NIL; IF closed THEN fontFileWatcherProc[key, close]; IF RTTypesBasic.FQEmpty[finalizationQueue] THEN RequestCollection[]; ENDLOOP; }; Finalize: ENTRY PROCEDURE [permission: REF FontFilePermission] RETURNS [closed: BOOLEAN _ FALSE] = TRUSTED { ENABLE UNWIND => NULL; key: Key _ permission.key; description: REF FontFileDescription _ keyTable[key.index].description; IF permission = description.permissions THEN { description.permissions _ permission.link; } ELSE { prev: REF FontFilePermission _ description.permissions; FOR p: REF FontFilePermission _ description.permissions.link, p.link UNTIL p=permission DO prev _ p; ENDLOOP; prev.link _ permission.link; }; permission.link _ NIL; IF description.permissions = NIL THEN { IF description.openFile # NIL THEN { Space.Delete[description.space]; CIFS.Close[description.openFile]; closed _ TRUE; }; keyTable[key.index].description _ NIL; }; permissionCount _ permissionCount-1; }; Init: ENTRY PROCEDURE = TRUSTED { ENABLE UNWIND => NULL; RTTypesBasic.EstablishFinalization[CODE[FontFilePermission], 1, finalizationQueue]; Process.Detach[FORK FinalizerProcess[finalizationQueue]]; }; KeyOf: PUBLIC ENTRY PROCEDURE [fileName: ROPE] RETURNS [key: Key] = { ENABLE UNWIND => NULL; len: NAT _ fileName.Length[]; canonicalName: REF TEXT _ RefText.ObtainScratch[len]; i: NAT _ 0; Getc: PROC RETURNS [ch: CHAR] = {IF i {Put['/]; c _ Getc[]}; '] => {Put['/]; IF (c _ Getc[]) = '< THEN c _ Getc[]}; '> => {Put['/]; c _ Getc[]}; IN ['a .. 'z] => {Put[c + lowerToUpper]; c _ Getc[]}; ENDCASE => {Put[c]; c _ Getc[]}; ENDLOOP; canonicalName.length _ j; FOR k: NAT IN [0..keyTable.numberOfEntries) DO IF Match[keyTable[k].fileName] THEN {key _ [index: k]; EXIT}; ENDLOOP; IF key.index = LAST[NAT] THEN { PreventTableOverflow[]; keyTable[keyTable.numberOfEntries] _ [fileName: Rope.FromRefText[canonicalName], description: NIL]; key _ [index: keyTable.numberOfEntries]; keyTable.numberOfEntries _ keyTable.numberOfEntries+1; }; RefText.ReleaseScratch[canonicalName]; }; KeyOfRefText: PUBLIC PROCEDURE [fileName: REF TEXT] RETURNS [key: Key] = { key _ KeyOf[RefText.TrustTextAsRope[fileName]]; }; waitTime: Process.Ticks _ Process.MsecToTicks[5000]; fileHintTimeout: CONDITION; fileHintTimeoutProcess: PROCESS _ NIL; FileHintTimeoutProcess: ENTRY PROCEDURE = { ENABLE UNWIND => NULL; WAIT fileHintTimeout; fileHintTimeoutProcess _ NIL; FOR i: NAT IN [0..keyTable.numberOfEntries) DO description: REF FontFileDescription _ keyTable[i].description; IF description#NIL THEN description.permissionHint _ NIL; ENDLOOP; WAIT fileHintTimeout; IF fileHintTimeoutProcess = NIL THEN SafeStorage.ReclaimCollectibleObjects[suspendMe: FALSE]; }; StartFileHintTimeout: ENTRY PROCEDURE = TRUSTED { ENABLE UNWIND => NULL; IF fileHintTimeoutProcess=NIL THEN { Process.InitializeCondition[@fileHintTimeout, waitTime]; Process.Detach[fileHintTimeoutProcess _ FORK FileHintTimeoutProcess[]]; }; }; Open: PUBLIC PROCEDURE [key: Key, initProc: InitProc _ NIL] RETURNS [fontFile: FontFile] = { description: REF FontFileDescription _ keyTable[key.index].description; IF description#NIL THEN fontFile _ description.permissionHint; IF fontFile=NIL THEN { triedToOpen: BOOLEAN; [fontFile, triedToOpen] _ MonitoredOpen[key, initProc]; IF triedToOpen THEN fontFileWatcherProc[key, IF Status[fontFile].ok THEN open ELSE openFailed]; IF permissionsSinceCollectionRequest>permissionThreshold THEN RequestCollection[]; }; IF fileHintTimeoutProcess=NIL THEN StartFileHintTimeout[]; }; MonitoredOpen: ENTRY PROCEDURE [key: Key, initProc: InitProc _ NIL] RETURNS [fontFile: FontFile, triedToOpen: BOOLEAN _ FALSE] = { ENABLE UNWIND => NULL; description: REF FontFileDescription _ keyTable[key.index].description; openOk: BOOLEAN _ TRUE; IF description = NIL THEN { description _ NEW[FontFileDescription]; description.space _ Space.nullHandle; description.openFile _ CIFS.Open[keyTable[key.index].fileName, CIFS.read + CIFS.dontCheck ! CIFS.Error => TRUSTED {openOk _ FALSE; description.errorCode _ code; description.errorMsg _ error; CONTINUE}]; triedToOpen _ TRUE; IF openOk THEN TRUSTED { capability: File.Capability _ CIFS.GetFC[description.openFile]; pages: File.PageCount _ File.GetSize[capability]; description.size _ INT[pages]*Environment.wordsPerPage; description.space _ Space.Create[size: pages, parent: Space.virtualMemory]; Space.Map[space: description.space, window: [file: capability, base: 1]]; description.origin _ Space.LongPointer[description.space]; } ELSE description.openFile _ NIL; }; keyTable[key.index].description _ description; fontFile _ qZone.NEW[FontFilePermission]; permissionCount _ permissionCount + 1; permissionsSinceCollectionRequest _ permissionsSinceCollectionRequest + 1; fontFile.link _ description.permissions; description.permissions _ fontFile; fontFile.key _ key; IF description.clientData = NIL AND description.openFile # NIL AND initProc # NIL THEN description.clientData _ initProc[key, fontFile]; description.permissionHint _ fontFile; }; GetData: PUBLIC PROCEDURE [fontFile: FontFile] RETURNS [REF] = { RETURN[keyTable[fontFile.key.index].description.clientData]; }; Status: PUBLIC PROCEDURE [fontFile: FontFile] RETURNS [errorCode: CIFS.ErrorCode, errorMsg: Rope.ROPE, ok: BOOLEAN] = { description: REF FontFileDescription _ keyTable[fontFile.key.index].description; errorCode _ description.errorCode; errorMsg _ description.errorMsg; ok _ description.openFile # NIL }; Pointer: PUBLIC UNSAFE PROCEDURE [fontFile: FontFile] RETURNS [origin: LONG POINTER] = { origin _ keyTable[fontFile.key.index].description.origin; }; NameOf: PUBLIC PROCEDURE [key: Key] RETURNS [fileName: ROPE] = { IF key.index= 0 AND addr >= org AND addr + sizeInWords <= end ]; }; fontFileWatcherProc: FontFileWatcher _ defaultFontFileWatcher; defaultFontFileWatcher: FontFileWatcher = {}; RegisterFontFileWatcher: PUBLIC PROCEDURE [fontFileWatcher: FontFileWatcher] = { fontFileWatcherProc _ fontFileWatcher; }; PermissionCount: PUBLIC PROCEDURE RETURNS [INT] = {RETURN[permissionCount]}; EnumerateOpenFontFiles: PUBLIC PROCEDURE [visit: PROC[Rope.ROPE]] = { i: NAT _ 0; DO table: REF KeyTableRec _ keyTable; rope: Rope.ROPE _ NIL; IF i>= table.numberOfEntries THEN EXIT; IF table[i].description # NIL THEN rope _ table[i].fileName; table _ NIL; IF rope # NIL THEN visit[rope]; i _ i+1; ENDLOOP; }; Init[]; END. όUFFileManagerImpl.mesa Created January 7, 1983 Last edit by Michael Plass on February 25, 1983 10:47 am Used only for FontFilePermissions. This is written so it doesn't have to be an entry procedure, so it doesn't matter if the visit proc hangs. Κ ͺ˜Jšœ™Jšœ™Jšœ8™8IunitšΟk œœ]˜kKšœœ˜ Jšœœ@˜LJšœ˜Jšœœ˜Kšœ œœœ˜/šœœœœ˜*Jšœœ˜Jšœ˜J˜—šœœ"˜-Jšœ Οs™"—šœœœ˜$Jšœ œ˜$Jšœœ˜'Jšœ œœ˜Jšœ œ ˜Jšœ œ ˜Jšœœ˜J˜Jšœœœ˜JšœœΟc ˜J˜—Kšœ œœ˜0šœ œœ˜Jšœœ˜Jšœ œ œœ ˜-J˜—Kš œœœ œœ˜SKšœœ˜Kšœ#œ˜+Kšœœ˜šΟnœœ˜Jšœ&˜&Jšœ(˜(Jšœ˜—Kšœ\˜\š œ œ8˜Sš˜Jšœ œœ)˜TJšœ˜Jšœœ˜'Jšœ œ˜Jšœœ!˜/Jšœ(œ˜DJšœ˜—Jšœ˜—š œœ œœœ œœœ˜lJšœœœ˜Jšœ˜Jšœ œ7˜Gšœ%œ˜.Jšœ*˜*J˜—šœ˜Jšœœ.˜7šœœ;œ˜ZJšœ ˜ Jšœ˜—Jšœ˜J˜—Jšœ˜šœœœ˜'šœœœ˜$Jšœ ˜ Jšœ˜!Jšœ œ˜J˜—Jšœ"œ˜&J˜—Jšœ$˜$Jšœ˜—š œœ œœ˜!Jšœœœ˜Jšœ#œ,˜SJšœœ&˜9Jšœ˜—š  œœœ œ œœ˜EJšœœœ˜Jšœœ˜Jšœœœ˜5Jšœœ˜ Jš œœœœœœœ˜YJšœœ ˜Jšœœ˜ Jš œœœ'˜:š œœ˜Jšœ œ˜(šœœ˜#Jš œ œœ œœœ˜WJšœ&˜&šœœœ˜Jšœ˜Jšœ˜—Jšœ˜J˜—J˜—š  œœ œœœ˜3Jšœœœœ˜&š œœ œœ˜"Jšœ"œœœ˜7Jšœ˜—Jšœœ˜ J˜—Jšœœ ˜ Jšœ œœ˜šœ˜ šœ˜ J˜J˜6J˜J˜5Jšœ˜ —Jšœ˜—Jšœ˜šœœœ˜.Jšœœœ˜=Jšœ˜—šœ œœœ˜Jšœ˜Jšœ^œ˜cJšœ(˜(Jšœ6˜6J˜—Jšœ&˜&Jšœ˜—š   œœ œ œœœ˜JJšœ/˜/Jšœ˜—K˜4Kšœ ˜Kšœœœ˜&š œœ œ˜+Jšœœœ˜Jšœ˜Jšœœ˜šœœœ˜.Jšœ œ/˜?Jšœ œœœ˜9Jš˜—Jšœ˜Jšœœœ2œ˜]Jšœ˜—š œœ œœ˜1Jšœœœ˜šœœœ˜$Jšœ8˜8Jšœ(œ˜GJšœ˜—Jšœ˜—š  œœ œ!œœ˜\Jšœ œ7˜GJšœ œœ'˜>šœ œœ˜Jšœ œ˜Jšœ7˜7Jš œ œœœœ˜`Jšœ6œ˜RJ˜—Jšœœœ˜:Jšœ˜—š  œœ œ!œœ#œœ˜‚Jšœœœ˜Jšœ œ7˜GJšœœœ˜šœœœ˜Jšœœ˜'Jšœ%˜%Jšœœ$œœ œ œ œ>œ˜ΚJšœœ˜šœœœ˜Jšœœ˜?Jšœ1˜1Jšœœ!˜7JšœK˜KJšœI˜IJšœ:˜:J˜—Jšœœ˜ Jšœ˜—Jšœ.˜.Jšœœ˜)J˜&J˜JJšœ(˜(Jšœ#˜#Jšœ˜š œœœœœ œ˜VJšœ1˜1—Jšœ&˜&Jšœ˜—š  œœ œœœ˜@Jšœ6˜˜>Kšœ-˜-š œœ œ'˜PJšœ&˜&Jšœ˜—Kš  œœ œœœœ˜Lš  œœ œ œœ˜EJ™jJšœœ˜ š˜Jšœœ˜"Jšœ œœ˜Jšœœœ˜'Jšœœœ˜