-- DirectoryContextsImpl.mesa (last edited by: Keith on: January 8, 1981 2:33 PM) -- DIRECTORY Directory, DirectoryContexts, DirectoryExtras, DirectoryFiles, DirectoryInternal, DirectoryTrees, File USING [Capability], Heap USING [Create], Space USING [Create, Delete, Handle, Unmap, PageCount, virtualMemory], String USING [AppendChar, AppendString], Volume USING [GetLabelString, nullID, systemID]; DirectoryContextsImpl: MONITOR LOCKS DirectoryInternal.DirectoryLock IMPORTS Directory, DirectoryFiles, DirectoryInternal, DirectoryTrees, Heap, Space, String, Volume EXPORTS Directory, DirectoryContexts, DirectoryExtras = BEGIN -- Contexts Context: PUBLIC TYPE = DirectoryInternal.Context; Handle: TYPE = DirectoryContexts.Handle; ContextSpace: PUBLIC UNCOUNTED ZONE; contextSpaceHandle: Space.Handle; contextHeapSize: Space.PageCount = 100; -- size of heap used to store contexts initialContextHeapSize: Space.PageCount = 1; -- initial size of heap... will be used for WD part ContextTable: TYPE = ARRAY [0.. DirectoryContexts.maxContexts) OF Handle; contextTable: PUBLIC LONG POINTER TO ContextTable _ NIL; topContext: [0.. DirectoryContexts.maxContexts) _ 0; defaultContextDefined: BOOLEAN _ FALSE; -- TRUE if the default context has been defined eType: Directory.ErrorType; -- entry and external procedures CopyContext: PUBLIC ENTRY PROC [context: Handle] RETURNS [Handle] = -- create a new context and initialize to the values of the passed context BEGIN ENABLE {UNWIND => NULL; Directory.Error => {eType _ type; GOTO AnError}}; newContext: Handle; context _ ValidateContext[context]; newContext _ NewContext[context]; RETURN [newContext] EXITS AnError => RETURN WITH ERROR Directory.Error[eType]; END; ForgetVolumes: PUBLIC ENTRY PROCEDURE = -- Releases all information kept by Directory about non-system Pilot volumes BEGIN ENABLE UNWIND => NULL; pVT, pDC: CARDINAL; FOR pVT IN [0.. DirectoryFiles.maxDVolumes) DO IF (DirectoryFiles.volumeTable[pVT].volID = Volume.systemID) OR (DirectoryFiles.volumeTable[pVT].volID = Volume.nullID) THEN LOOP; DirectoryFiles.volumeTable[pVT].volID _ Volume.nullID; DirectoryFiles.volumeTable[pVT].volName.length _ 0; Space.Delete[DirectoryFiles.volumeTable[pVT].dtSpace]; FOR pDC IN [1.. DirectoryFiles.maxDCache] DO IF (DirectoryFiles.directoryCache[pDC].pVT # pVT) OR (DirectoryFiles.directoryCache[pDC].refCount = 0) THEN LOOP; DirectoryFiles.directoryCache[pDC].refCount _ 0; Space.Delete[DirectoryFiles.directoryCache[pDC].dir.space]; InvalidateContext[pDC]; ENDLOOP; ENDLOOP; END; GetDefaultContext: PUBLIC ENTRY PROC RETURNS [context: Handle] = -- Create a context with values equal to the default context BEGIN ENABLE {UNWIND => NULL; Directory.Error => {eType _ type; GOTO AnError}}; context _ ValidateContext[Directory.defaultContext]; context _ NewContext[context]; RETURN; EXITS AnError => RETURN WITH ERROR Directory.Error[eType]; END; GetSPElement: PUBLIC ENTRY PROC [element: CARDINAL, pathName: LONG STRING, context: Handle] = -- return the search path element BEGIN ENABLE {UNWIND => NULL; Directory.Error => {eType _ type; GOTO AnError}}; pSP: LONG POINTER TO DirectoryInternal.SPRecord; context _ ValidateContext[context ! Directory.Error => IF type = fileNotFound THEN CONTINUE]; pSP _ context.pSP; THROUGH [0.. element) DO IF pSP.pSP = NIL THEN RETURN WITH ERROR Directory.OutOfBounds; pSP _ pSP.pSP; ENDLOOP; DirectoryTrees.MoveLongString[from: @pSP.spName, to: pathName]; IF pathName.maxlength < pSP.spName.length THEN RETURN WITH ERROR Directory.Error[stringTooShort]; RETURN EXITS AnError => RETURN WITH ERROR Directory.Error[eType]; END; GetWD: PUBLIC ENTRY PROC [context: Handle, pathName: LONG STRING] = -- return the working directory field from the context BEGIN ENABLE {UNWIND => NULL; Directory.Error => {eType _ type; GOTO AnError}}; context _ ValidateContext[context ! Directory.Error => IF type = fileNotFound THEN CONTINUE]; DirectoryTrees.MoveLongString[from: @context.wdName, to: pathName]; IF pathName.maxlength < context.wdName.length THEN RETURN WITH ERROR Directory.Error[stringTooShort]; RETURN EXITS AnError => RETURN WITH ERROR Directory.Error[eType]; END; KillContext: PUBLIC ENTRY PROC [context: Handle] = -- Deletes a context BEGIN ENABLE {UNWIND => NULL; Directory.Error => {eType _ type; GOTO AnError}}; IF context = Directory.defaultContext OR context = contextTable[0] THEN RETURN; OldContext[ValidateContext[context ! Directory.Error => IF type = fileNotFound THEN CONTINUE]]; EXITS AnError => RETURN WITH ERROR Directory.Error[eType]; END; SetDefaultContext: PUBLIC ENTRY PROC [context: Handle] RETURNS [oldContext: Handle] = -- Defines the default context BEGIN ENABLE {UNWIND => NULL; Directory.Error => {eType _ type; GOTO AnError}}; oldContext _ contextTable[0]; IF context = Directory.defaultContext THEN DefineDefaultContext[] ELSE contextTable[0] _ NewContext[ValidateContext[context]]; IF topContext = DirectoryContexts.maxContexts THEN ERROR; topContext _ topContext+1; contextTable[topContext] _ oldContext; EXITS AnError => RETURN WITH ERROR Directory.Error[eType]; END; -- internal procedures DefineDefaultContext: INTERNAL PROC = -- gives the default context the values wd = SysDir>, sp = WorkDir> BEGIN defaultHandle: Handle; defaultSP: LONG POINTER TO withWD DirectoryInternal.SPRecord; wdpDT: DirectoryInternal.PDT; wdpDTNode: DirectoryInternal.PDTNode; wdName: STRING _ [100]; sysvolLabel: STRING _ [40]; defaultContextDefined _ TRUE; -- allocate new working directory area defaultHandle _ contextTable[0] _ ContextSpace.NEW[Context]; wdpDT _ DirectoryFiles.volumeTable[DirectoryFiles.GetVTEntryFromID[Volume.systemID]].pDT; wdpDTNode _ DirectoryTrees.DTFirst[wdpDT]; -- pointer to root directory IF wdpDTNode = DirectoryInternal.pDTnil THEN ERROR Directory.VolumeError[rootNotFound, Volume.systemID]; wdpDTNode _ DirectoryTrees.DTFind[wdpDT, wdpDTNode, "SysDir"L]; IF wdpDTNode = DirectoryInternal.pDTnil THEN ERROR Directory.VolumeError[directoryNeedsScavenging, Volume.systemID]; defaultHandle.pDC _ DirectoryFiles.GetDirectoryCache[wdpDT[wdpDTNode].cap]; defaultHandle.wdName _ [length: 0, maxlength: Directory.maxPathNameLength, text:]; defaultHandle.valid _ TRUE; wdName.length _ 0; String.AppendChar[wdName, '<]; Volume.GetLabelString[Volume.systemID, sysvolLabel]; String.AppendString[wdName, sysvolLabel]; String.AppendChar[wdName, '>]; String.AppendString[wdName, "SysDir>"]; DirectoryTrees.MoveLongString[to: @defaultHandle.wdName, from: wdName]; -- allocate new search path element area defaultSP _ defaultHandle.pSP _ ContextSpace.NEW[withWD DirectoryInternal.SPRecord]; defaultSP.spName _ [length: 0, maxlength: Directory.maxPathNameLength, text:]; DirectoryTrees.MoveLongString[to: @defaultSP.spName, from: "WorkDir>"L]; defaultSP.pSP _ NIL; defaultSP.pDC _ 0; defaultSP.defined _ FALSE; defaultSP.pWD _ contextTable[0]; defaultContextDefined _ TRUE; RETURN END; NewContext: INTERNAL PROC [context: Handle] RETURNS [newContext: Handle] = -- creates a new context with values equal to the old context BEGIN pSP, newSP: LONG POINTER TO DirectoryInternal.SPRecord; IF topContext = DirectoryContexts.maxContexts THEN ERROR; newContext _ ContextSpace.NEW[Context _ context^]; topContext _ topContext+1; contextTable[topContext] _ newContext; DirectoryFiles.directoryCache[context.pDC].refCount _ DirectoryFiles.directoryCache[context.pDC].refCount + 1; pSP _ context.pSP; IF pSP = NIL THEN ERROR; --this shouldn't happen!! newSP _ newContext.pSP _ ContextSpace.NEW[DirectoryInternal.SPRecord _ pSP^]; IF pSP.defined THEN DirectoryFiles.directoryCache[pSP.pDC].refCount _ DirectoryFiles.directoryCache[pSP.pDC].refCount+1; WITH sp: newSP^ SELECT FROM withWD => sp.pWD _ newContext; ENDCASE; FOR pSP _ pSP.pSP, pSP.pSP UNTIL pSP = NIL DO newSP.pSP _ ContextSpace.NEW[DirectoryInternal.SPRecord _ pSP^]; IF pSP.defined THEN DirectoryFiles.directoryCache[pSP.pDC].refCount _ DirectoryFiles.directoryCache[pSP.pDC].refCount+1; WITH sp: newSP.pSP^ SELECT FROM withWD => sp.pWD _ newContext; ENDCASE; newSP _ newSP.pSP; ENDLOOP; RETURN [newContext] END; OldContext: INTERNAL PROC [context: Handle] = -- Delete the context BEGIN startCompress: BOOLEAN _ FALSE; pSP: LONG POINTER TO DirectoryInternal.SPRecord _ context.pSP; nextSP: LONG POINTER TO DirectoryInternal.SPRecord; spaceToKill: Space.Handle; IF context.valid THEN { DirectoryFiles.directoryCache[context.pDC].refCount _ DirectoryFiles.directoryCache[context.pDC].refCount-1; IF DirectoryFiles.directoryCache[context.pDC].refCount = 0 THEN { spaceToKill _ DirectoryFiles.directoryCache[context.pDC].dir.space; Space.Unmap[spaceToKill]; Space.Delete[spaceToKill]}}; FOR i: CARDINAL IN (0.. topContext] DO IF startCompress THEN contextTable[i-1] _ contextTable[i] ELSE IF contextTable[i] = context THEN startCompress _ TRUE; ENDLOOP; contextTable[topContext] _ NIL; topContext _ topContext-1; ContextSpace.FREE[@context]; WHILE pSP # NIL DO IF pSP.defined THEN { DirectoryFiles.directoryCache[pSP.pDC].refCount _ DirectoryFiles.directoryCache[pSP.pDC].refCount-1; IF DirectoryFiles.directoryCache[pSP.pDC].refCount = 0 THEN { spaceToKill _ DirectoryFiles.directoryCache[pSP.pDC].dir.space; Space.Unmap[spaceToKill]; Space.Delete[spaceToKill]}}; nextSP _ pSP.pSP; ContextSpace.FREE[@pSP]; pSP _ nextSP ENDLOOP; END; InvalidateContext: PUBLIC INTERNAL PROC [pDC: CARDINAL] = -- invalidates contexts that refer to the indicated directory cache BEGIN wd: Handle; sp: LONG POINTER TO DirectoryInternal.SPRecord; FOR i: CARDINAL IN [0.. topContext] DO wd _ contextTable[i]; IF wd.pDC = pDC THEN wd.valid _ FALSE; sp _ wd.pSP; WHILE sp # NIL DO IF sp.defined AND (sp.pDC = pDC) THEN sp.defined _ FALSE; sp _ sp.pSP; ENDLOOP; ENDLOOP; RETURN END; ValidateContext: PUBLIC INTERNAL PROC [context: Handle] RETURNS [Handle] = -- checks that the passed context is valid, and expands the default context BEGIN returnHandle: Handle; IF ~ defaultContextDefined THEN DefineDefaultContext[]; IF context = Directory.defaultContext THEN returnHandle _ contextTable[0] ELSE FOR i: CARDINAL IN [0.. topContext] DO IF context = contextTable[i] THEN {returnHandle _ context; EXIT} REPEAT FINISHED => ERROR Directory.Error[invalidContext]; ENDLOOP; IF returnHandle.valid THEN RETURN [returnHandle] ELSE ERROR Directory.Error[fileNotFound]; END; -- Initialization -- Create the heap for contexts and the context table contextSpaceHandle _ Space.Create[size: contextHeapSize, parent: Space.virtualMemory]; ContextSpace _ Heap.Create[ initial: initialContextHeapSize, parent: contextSpaceHandle, swapUnit: DirectoryInternal.swapUnitSize]; contextTable _ ContextSpace.NEW[ContextTable _ ALL[Directory.defaultContext]]; END. LOG Time: August 28, 1980 10:54 AM By: Marzullo Action: Created File Time: October 8, 1980 10:58 PM By: Keith Action: Fixed AR 6178: WD max length too small in DefineContext. Time: October 12, 1980 4:32 PM By: Fay Action: Changes for merge of DirectoryExtras into Directory. Time: October 15, 1980 11:42 AM By: Keith Action: SetDefaultContext didn't enter oldContext into contextTable and NewContext did not set pWD in search paths correctly (AR 6258).. Time: January 7, 1981 8:11 PM By: Keith Action: Moved contextTable to hyperspace, added entry proc ForgetVolumes and fixed OldContext to correctly update contextTable. (1792)\3b21B6i55I587bi8BI4b7B204i41I53i48I240i44I37bi30BI2b13B57b2B3i71I1b4B80b4B20b4B36b4B35b4B83b4B8b13B27i80I816b19B54i57I1b4B137b4B117b14B91i30I1b4B648b5B47b1B18i51I1b4B445b14B46i17I342b19B79i27I467bi20BI46i74I274i43I210i27I820i45I504i58I11b4B118b4B126b4B117b4B19b4B27i23I1b4B78b4B211b4B46b4B67b4B209b4B21b4B11b4B82i20I1300i66I441i72I478bi20BI2i56I330i78I1i114I1i108I1i187I1i101bI14Bi55I