-- InitProcsImpl.mesa -- Last edited by -- MBrown on January 31, 1984 5:34:13 pm PST -- Kolling on July 6, 1983 10:52 am DIRECTORY AccessControl, AlpineControl USING [TypeOfRestart], AlpineDebug, AlpineEnvironment USING [FileID, nullFileID, FileStore, PageCount, TransID, VolumeID, VolumeGroupID], AlpineFile, AlpineIdentity USING [myLocalConversation], AlpineImport USING [Handle, Register], AlpineOwner, AlpineTransaction USING[Create, Finish], AlpineTransMgr, AlpineTransMgrRpcControl USING [InterfaceRecord, NewInterfaceRecord], AlpineVolume, AlpineZones USING [], ConversationTable USING [Initialize, Fetch], CoordinatorControl USING [Initialize, CallAfterAnalysisPass, CallAfterUpdatePass], File, FileControl USING [Initialize, CallBeforeUpdatePass, CallAfterUpdatePass, RegisterVolumeGroup], FileMap USING [Handle, Initialize, Register], FilePageMgr USING [ Create, InitializeFilePageMgr, ReadPages, UsePages, ReleaseVMPageSet, VMPageSet], OpenFileMap USING [Initialize], InitProcs USING [], LockControl USING [Initialize, ForkWatchdogProcess], LogControl USING [Format, Recover, ForkCheckpointProcess], Rope, RPC USING [Conversation, ConversationID, EncryptionKey, GetConversationID, MakeKey], SafeStorage USING [GetSystemZone], TransactionMap USING [GetHandle, GetTransID, Handle], WorkerControl USING [Initialize, CallAfterAnalysisPass, CallAfterUpdatePass]; InitProcsImpl: MONITOR IMPORTS AccessControl, AlpineImport, AlpineIdentity, AlpineTransaction, AlpineTransMgr, AlpineTransMgrRpcControl, ConversationTable, CoordinatorControl, File, FileControl, FileMap, FilePageMgr, LockControl, LogControl, OpenFileMap, Rope, RPC, SafeStorage, TransactionMap, WorkerControl EXPORTS AlpineControl, AlpineIdentity, AlpineZones, InitProcs = BEGIN VolumeID: TYPE = AlpineEnvironment.VolumeID; FileID: TYPE = AlpineEnvironment.FileID; FileStore: TYPE = AlpineEnvironment.FileStore; PageCount: TYPE = AlpineEnvironment.PageCount; ROPE: TYPE = Rope.ROPE; -- Exported to AlpineIdentity: myFileStore: PUBLIC FileStore; myLogVolumeID: PUBLIC VolumeID; myEncryptionKey: PUBLIC RPC.EncryptionKey; myAlpineImportHandle: PUBLIC AlpineImport.Handle; myLocalConversation: PUBLIC RPC.Conversation; myLocalConversationID: PUBLIC RPC.ConversationID; static: PUBLIC ZONE _ SafeStorage.GetSystemZone[]; -- AlpineZones.static isInitialized: BOOL _ FALSE; isStarted: BOOL _ FALSE; Initialize: PUBLIC ENTRY PROC [ filePageMgrNormalChunks, filePageMgrLogChunks, filePageMgrLeaderChunks: NAT, coordinatorMapHashArraySlots, transactionMapHashArraySlots: NAT, fileMapHashArraySlots, openFileMapHashArraySlots: NAT, lockHashArraySlots: NAT, fileMapFinalizationQueueLength: NAT, nAccessCacheEntries: NAT, alpineWheels: ROPE] = { -- AlpineControl.Initialize IF isInitialized THEN RETURN; FilePageMgr.InitializeFilePageMgr[ nNormalChunksInCache: filePageMgrNormalChunks, nLogChunksInCache: filePageMgrLogChunks, nLeaderChunksInCache: filePageMgrLeaderChunks]; ConversationTable.Initialize[17]; LockControl.Initialize[lockZoneInitialSize: 2048, hashArraySize: 256]; WorkerControl.Initialize[transactionMapHashArraySlots]; CoordinatorControl.Initialize[coordinatorMapHashArraySlots]; FileMap.Initialize[fileMapHashArraySlots, fileMapFinalizationQueueLength]; OpenFileMap.Initialize[openFileMapHashArraySlots]; FileControl.Initialize[]; AccessControl.InitVolatileData[ nAccessCacheEntries: nAccessCacheEntries, alpineWheels: alpineWheels]; isInitialized _ TRUE; }; Start: PUBLIC ENTRY PROC [ fileStore: FileStore, typeOfRestart: AlpineControl.TypeOfRestart, nLogPages, nOwners: INT] = { volume: File.Volume; volumeID: VolumeID; { ENABLE UNWIND => NULL; IF NOT isInitialized THEN ERROR; IF isStarted THEN RETURN; IF (volume _ File.FindVolumeFromName[fileStore]) = NIL THEN { IF fileStore.Equal["Local.alpine", FALSE] THEN volume _ File.SystemVolume[] ELSE ERROR; }; }; volumeID _ [File.GetVolumeID[volume]]; SELECT typeOfRestart FROM warmStart => NULL; coldStart => EraseFileStore[volumeID, fileStore]; createServer => { IF volume # File.SystemVolume[] THEN File.EraseVolume[volume]; CreateFileStore[volumeID, nLogPages, fileStore]; }; ENDCASE => ERROR; Recover[logVolume: volumeID, initOwnerFile: typeOfRestart = createServer, nOwners: nOwners]; isStarted _ TRUE; }; IsStarted: PUBLIC ENTRY PROC [] RETURNS [BOOL] = { RETURN [isStarted]; }; CreateFileStore: PROC [ logVolume: VolumeID, logPages: PageCount, fileStore: FileStore] = { -- Formats the given volume to a well-defined initial state that is acceptable to --Recover below. This should not be called while the server is running. --Call Create, then call Recover, in order to cold-start a server on an empty volume. logFile, restartFile: FileID; logFile _ CreateFile[logVolume, logPages]; restartFile _ CreateFile[logVolume, 1]; SetRootFiles[logVolume, logFile, restartFile]; LogControl.Format[logVolume, logFile, restartFile, fileStore]; }; EraseFileStore: PROC [logVolume: VolumeID, fileStore: FileStore] = { -- Like CreateFileStore, but assumes that the logVolume already contains a log file --and a restart file. Call EraseFileStore, then call Recover, in order to cold-start a --server on an existing volume. logFile, restartFile: FileID; [logFile, restartFile] _ GetRootFiles[logVolume]; LogControl.Format[logVolume, logFile, restartFile, fileStore]; }; Recover: PROC [ logVolume: VolumeID, initOwnerFile: BOOL, nOwners: INT] = { -- Starts the server using the indicated state. logFile, restartFile, ownerFile, newOwnerFileID: FileID; ownerFileTrans: TransactionMap.Handle; -- Temporary kludges (this entire proc might be so regarded ...) [logFile, restartFile] _ GetRootFiles[logVolume]; FileControl.RegisterVolumeGroup[ volumeGroupID: GetVolumeGroupID[logVolume], volumes: CONS[first: logVolume, rest: NIL]]; -- Recover state from the log. LogControl.Recover[logVolume, logFile, restartFile]; -- Tell AccessControl about the owner file. ownerFileTrans _ CreateLocalTrans[]; IF initOwnerFile THEN { ownerFile _ AccessControl.CreateAndInitializeOwnerFile[ conversation: AlpineIdentity.myLocalConversation, transHandle: ownerFileTrans, volGroupID: GetVolumeGroupID[logVolume], ownerFileVolID: logVolume, totalQuota: 10000, volumeGroupSize: 15000, overCommitQuotaDuringInitializeIfNeeded: TRUE, maxNumberOfOwnersAllowed: nOwners, nOwnerCacheEntries: 10]; SetOwnerRootFile[logVolume, ownerFile]; } ELSE ownerFile _ GetOwnerRootFile[logVolume]; newOwnerFileID _ AccessControl.RegisterVolumeGroup[ conversation: AlpineIdentity.myLocalConversation, transHandle: ownerFileTrans, volGroupID: GetVolumeGroupID[logVolume], ownerFileUniversalFile: [logVolume, ownerFile], nOwnerCacheEntries: 10]; IF ownerFile # newOwnerFileID THEN SetOwnerRootFile[logVolume, newOwnerFileID]; CommitLocalTrans[ownerFileTrans]; LogControl.ForkCheckpointProcess[ myFileStore: myFileStore, wakeupPeriodInSeconds: 60]; LockControl.ForkWatchdogProcess[ wakeupPeriod: 1000, abortWaitingRequestInterval: 30, abortInactiveGrantedRequestInterval: 20]; }; CreateLocalTrans: PROC [] RETURNS [TransactionMap.Handle] = { transID: AlpineEnvironment.TransID = AlpineTransaction.Create[ conversation: AlpineIdentity.myLocalConversation, createLocalWorker: TRUE]; RETURN [TransactionMap.GetHandle[transID]]; }; CommitLocalTrans: PROC [t: TransactionMap.Handle] = { IF AlpineTransaction.Finish[ conversation: AlpineIdentity.myLocalConversation, transID: TransactionMap.GetTransID[t], requestedOutcome: commit, continue: FALSE].outcome # commit THEN ERROR; }; CreateFile: PROC [volume: VolumeID, nPages: PageCount] RETURNS [createdFileID: FileID] = { NoteFileID: SAFE PROC [fileID: FileID] = CHECKED { createdFileID _ fileID }; FilePageMgr.Create[volumeID: volume, initialSize: nPages, proc: NoteFileID]; }; AlpineRootFileRecord: TYPE = MACHINE DEPENDENT RECORD [ logFile: FileID, restartFile: FileID, ownerFile: FileID]; -- Format of file that is stored as File.VolumeFile.alpine in Cedar volume. SetRootFiles: PROC [logVolume: VolumeID, logFile, restartFile: FileID] = { rootVolume: File.Volume = File.FindVolumeFromID[logVolume]; rootFP: FileID _ File.GetRoot[rootVolume, $alpine].fp; IF rootFP = AlpineEnvironment.nullFileID THEN { rootFP _ CreateFile[logVolume, 1]; File.SetRoot[root: $alpine, file: File.Open[volume: rootVolume, fp: rootFP]]; }; { rootFileHandle: FileMap.Handle = FileMap.Register[volumeID: logVolume, fileID: rootFP]; chunk: FilePageMgr.VMPageSet = FilePageMgr.UsePages[fileHandle: rootFileHandle, pageRun: [firstPage: 0, count: 1]]; rootFileRecord: LONG POINTER TO AlpineRootFileRecord = LOOPHOLE[chunk.pages]; rootFileRecord^ _ [ logFile: logFile, restartFile: restartFile, ownerFile: AlpineEnvironment.nullFileID]; FilePageMgr.ReleaseVMPageSet[ vMPageSet: chunk, releaseState: writeIndividualWait, keep: FALSE]; }; }; GetRootFiles: PROC [logVolume: VolumeID] RETURNS [logFile, restartFile: FileID] = { rootVolume: File.Volume = File.FindVolumeFromID[logVolume]; rootFP: FileID _ File.GetRoot[rootVolume, $alpine].fp; IF rootFP = AlpineEnvironment.nullFileID THEN ERROR; { rootFileHandle: FileMap.Handle = FileMap.Register[volumeID: logVolume, fileID: rootFP]; chunk: FilePageMgr.VMPageSet = FilePageMgr.ReadPages[fileHandle: rootFileHandle, pageRun: [firstPage: 0, count: 1]]; rootFileRecord: LONG POINTER TO AlpineRootFileRecord = LOOPHOLE[chunk.pages]; [logFile: logFile, restartFile: restartFile] _ rootFileRecord^; FilePageMgr.ReleaseVMPageSet[ vMPageSet: chunk, releaseState: clean, keep: FALSE]; }; }; SetOwnerRootFile: PROC [logVolume: VolumeID, ownerFile: FileID] = { rootVolume: File.Volume = File.FindVolumeFromID[logVolume]; rootFP: FileID _ File.GetRoot[rootVolume, $alpine].fp; IF rootFP = AlpineEnvironment.nullFileID THEN ERROR; { rootFileHandle: FileMap.Handle = FileMap.Register[volumeID: logVolume, fileID: rootFP]; chunk: FilePageMgr.VMPageSet = FilePageMgr.ReadPages[fileHandle: rootFileHandle, pageRun: [firstPage: 0, count: 1]]; rootFileRecord: LONG POINTER TO AlpineRootFileRecord = LOOPHOLE[chunk.pages]; rootFileRecord.ownerFile _ ownerFile; FilePageMgr.ReleaseVMPageSet[ vMPageSet: chunk, releaseState: writeIndividualWait, keep: FALSE]; }; }; GetOwnerRootFile: PROC [logVolume: VolumeID] RETURNS [ownerRootFile: FileID] = { rootVolume: File.Volume = File.FindVolumeFromID[logVolume]; rootFP: FileID _ File.GetRoot[rootVolume, $alpine].fp; IF rootFP = AlpineEnvironment.nullFileID THEN ERROR; { rootFileHandle: FileMap.Handle = FileMap.Register[volumeID: logVolume, fileID: rootFP]; chunk: FilePageMgr.VMPageSet = FilePageMgr.ReadPages[fileHandle: rootFileHandle, pageRun: [firstPage: 0, count: 1]]; rootFileRecord: LONG POINTER TO AlpineRootFileRecord = LOOPHOLE[chunk.pages]; [ownerFile: ownerRootFile] _ rootFileRecord^; FilePageMgr.ReleaseVMPageSet[ vMPageSet: chunk, releaseState: clean, keep: FALSE]; }; }; GetVolumeGroupID: PROC [volumeID: VolumeID] RETURNS [volumeGroupID: AlpineEnvironment.VolumeGroupID] = { -- This kludge is guaranteed to work for a 1-volume system ... ID: TYPE = RECORD [a, b, c: CARDINAL, sequence: LONG CARDINAL]; id: ID _ LOOPHOLE[volumeID]; id.sequence _ id.sequence - 1; RETURN [LOOPHOLE[id]]; }; -- Procedures exported to InitProcs CalledBeforeAnalysisPass: PUBLIC PROC [ fileStore: FileStore, logVolume: VolumeID] = { myFileStore _ fileStore; myLogVolumeID _ logVolume; myEncryptionKey _ RPC.MakeKey["RPC"]; myAlpineImportHandle _ AlpineImport.Register[fileStore]; myAlpineImportHandle.first.local _ TRUE; { interface: AlpineTransMgrRpcControl.InterfaceRecord _ AlpineTransMgrRpcControl.NewInterfaceRecord[]; interface.RegisterWorker _ AlpineTransMgr.RegisterWorker; interface.WorkerPrepare _ AlpineTransMgr.WorkerPrepare; interface.WorkerFinish _ AlpineTransMgr.WorkerFinish; interface.Refused _ AlpineTransMgr.Refused; myAlpineImportHandle.first.transMgrInterface _ interface; }; myLocalConversation _ ConversationTable.Fetch[myAlpineImportHandle]; myLocalConversationID _ RPC.GetConversationID[myLocalConversation]; }; CalledAfterAnalysisPass: PUBLIC PROC [] = { WorkerControl.CallAfterAnalysisPass[]; CoordinatorControl.CallAfterAnalysisPass[]; }; CalledBeforeUpdatePass: PUBLIC PROC [] = { FileControl.CallBeforeUpdatePass[]; }; CalledAfterUpdatePass: PUBLIC PROC [] = { FileControl.CallAfterUpdatePass[]; WorkerControl.CallAfterUpdatePass[]; CoordinatorControl.CallAfterUpdatePass[]; }; END.--InitProcsImpl CHANGE LOG Changed by MBrown on April 1, 1983 1:25 pm -- Checkpoint process is now implemented in LogImpl. Added some parms to Initialize. Changed by MBrown on January 31, 1984 5:32:54 pm PST -- Conversion to Cedar 5.0.