DIRECTORY AccessControl, AlpineControl USING [TypeOfRestart], AlpineDebug, AlpineEnvironment USING [Conversation, 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, FileBackdoor, 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, FileBackdoor, 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; 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[]; 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] = { 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, additionalVolumes: LIST OF ROPE _ NIL, logVolumeName: ROPE _ NIL, typeOfRestart: AlpineControl.TypeOfRestart, nLogPages, nOwners: INT] = { logVolume: File.Volume; logVolumeID: VolumeID; additionalVolumeIDs: LIST OF VolumeID _ NIL; IF logVolumeName=NIL THEN logVolumeName _ fileStore; { ENABLE UNWIND => NULL; IF NOT isInitialized THEN ERROR; IF isStarted THEN RETURN; IF (logVolume _ File.FindVolumeFromName[logVolumeName]) = NIL THEN { IF fileStore.Equal["Local.alpine", FALSE] THEN logVolume _ File.SystemVolume[] ELSE ERROR; }; FOR volNames: LIST OF ROPE _ additionalVolumes, volNames.rest WHILE volNames # NIL DO { volID: VolumeID = [File.GetVolumeID[File.FindVolumeFromName[volNames.first]]]; additionalVolumeIDs _ CONS[ volID, additionalVolumeIDs ]; } ENDLOOP; }; logVolumeID _ [File.GetVolumeID[logVolume]]; SELECT typeOfRestart FROM warmStart => NULL; coldStart => EraseFileStore[logVolumeID, fileStore]; resizeLog => ResizeLog[logVolumeID, nLogPages, fileStore]; createServer => { IF logVolume # File.SystemVolume[] THEN FileBackdoor.EraseVolume[logVolume]; CreateFileStore[logVolumeID, nLogPages, fileStore]; }; ENDCASE => ERROR; Recover[logVolume: logVolumeID, additionalVolumes: additionalVolumeIDs, initOwnerFile: typeOfRestart = createServer, nOwners: nOwners]; isStarted _ TRUE; }; IsStarted: PUBLIC ENTRY PROC [] RETURNS [BOOL] = { RETURN [isStarted]; }; CreateFileStore: PROC [ logVolume: VolumeID, logPages: PageCount, fileStore: FileStore] = { logFile, restartFile: FileID; logFile _ CreateFile[logVolume, logPages]; restartFile _ CreateFile[logVolume, 1]; SetRootFiles[logVolume, logFile, restartFile]; LogControl.Format[logVolume, logFile, restartFile, fileStore]; }; ResizeLog: PROC [ logVolume: VolumeID, logPages: PageCount, fileStore: FileStore] = { logFile, restartFile, ownerFile: FileID; [logFile, restartFile, ownerFile] _ GetRootFiles[logVolume]; File.Delete[File.Open[File.FindVolumeFromID[logVolume], logFile] ! File.Error => SELECT why FROM unknownFile => CONTINUE; ENDCASE => REJECT ]; logFile _ CreateFile[logVolume, logPages]; SetRootFiles[logVolume, logFile, restartFile, ownerFile]; LogControl.Format[logVolume, logFile, restartFile, fileStore]; }; EraseFileStore: PROC [logVolume: VolumeID, fileStore: FileStore] = { logFile, restartFile: FileID; [logFile, restartFile, ] _ GetRootFiles[logVolume]; LogControl.Format[logVolume, logFile, restartFile, fileStore]; }; Recover: PROC [ logVolume: VolumeID, additionalVolumes: LIST OF VolumeID, initOwnerFile: BOOL, nOwners: INT] = { logFile, restartFile, ownerFile, newOwnerFileID: FileID; ownerFileTrans: TransactionMap.Handle; [logFile, restartFile, ] _ GetRootFiles[logVolume]; FileControl.RegisterVolumeGroup[ volumeGroupID: GetVolumeGroupID[logVolume], volumes: CONS[first: logVolume, rest: additionalVolumes]]; LogControl.Recover[logVolume, logFile, restartFile]; 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]; SetRootFiles: PROC [logVolume: VolumeID, logFile, restartFile: FileID, ownerFile: FileID _ AlpineEnvironment.nullFileID] = { rootVolume: File.Volume = File.FindVolumeFromID[logVolume]; rootFP: FileID _ FileBackdoor.GetRoot[rootVolume, $alpine].fp; IF rootFP = AlpineEnvironment.nullFileID THEN { rootFP _ CreateFile[logVolume, 1]; FileBackdoor.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: ownerFile]; FilePageMgr.ReleaseVMPageSet[ vMPageSet: chunk, releaseState: writeIndividualWait, keep: FALSE]; }; }; GetRootFiles: PROC [logVolume: VolumeID] RETURNS [logFile, restartFile, ownerFile: FileID] = { rootVolume: File.Volume = File.FindVolumeFromID[logVolume]; rootFP: FileID _ FileBackdoor.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, ownerFile: ownerFile] _ rootFileRecord^; FilePageMgr.ReleaseVMPageSet[ vMPageSet: chunk, releaseState: clean, keep: FALSE]; }; }; SetOwnerRootFile: PROC [logVolume: VolumeID, ownerFile: FileID] = { rootVolume: File.Volume = File.FindVolumeFromID[logVolume]; rootFP: FileID _ FileBackdoor.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 _ FileBackdoor.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] = { ID: TYPE = RECORD [a, b, c: CARDINAL, sequence: LONG CARDINAL]; id: ID _ LOOPHOLE[volumeID]; id.sequence _ id.sequence - 1; RETURN [LOOPHOLE[id]]; }; 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.clientStubRegisterWorker _ RegisterWorker; interface.clientStubWorkerPrepare _ WorkerPrepare; interface.clientStubWorkerFinish _ WorkerFinish; interface.Refused _ AlpineTransMgr.Refused; myAlpineImportHandle.first.transMgrInterface _ interface; }; myLocalConversation _ ConversationTable.Fetch[myAlpineImportHandle]; myLocalConversationID _ RPC.GetConversationID[myLocalConversation]; }; RegisterWorker: PROCEDURE [interface: AlpineTransMgrRpcControl.InterfaceRecord, conversation: AlpineEnvironment.Conversation, trans: AlpineEnvironment.TransID] RETURNS [AlpineTransMgr.RegisterWorkerResult] = { RETURN AlpineTransMgr.RegisterWorker[conversation, trans]}; WorkerPrepare: PROCEDURE [interface: AlpineTransMgrRpcControl.InterfaceRecord, conversation: AlpineEnvironment.Conversation, trans: AlpineEnvironment.TransID, newTrans: AlpineEnvironment.TransID] RETURNS [AlpineTransMgr.WorkerState] = { RETURN AlpineTransMgr.WorkerPrepare[conversation, trans, newTrans]}; WorkerFinish: PROCEDURE [interface: AlpineTransMgrRpcControl.InterfaceRecord, conversation: AlpineEnvironment.Conversation, trans: AlpineEnvironment.TransID, requiredOutcome: AlpineTransMgr.RequiredOutcome] = { AlpineTransMgr.WorkerFinish[conversation, trans, requiredOutcome]}; 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 Changed by MBrown on January 31, 1984 5:32:54 pm PST InitProcsImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last edited by MBrown on January 31, 1984 5:34:13 pm PST Kolling on July 6, 1983 10:52 am Hauser, April 22, 1985 1:48:30 pm PST Carl Hauser, July 20, 1985 3:55:39 pm PDT Exported to AlpineIdentity: AlpineZones.static AlpineControl.Initialize 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. 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 ResizeLog, then call Recover, in order to cold-start a server on an empty volume. 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. Starts the server using the indicated state. Temporary kludges (this entire proc might be so regarded ...) Recover state from the log. Tell AccessControl about the owner file. Format of file that is stored as File.VolumeFile.alpine in Cedar volume. This kludge is guaranteed to work for a 1-volume system ... Procedures exported to InitProcs Checkpoint process is now implemented in LogImpl. Added some parms to Initialize. Conversion to Cedar 5.0. Nodified: Hauser: March 4, 1985 Hauser, March 8, 1985 10:35:14 am PST Added copyright. Κ }˜šœ™Icodešœ Οmœ1™<—šœ™Jšœ)™)Jšœ ™ K™%K™)—˜šΟk ˜ J˜Jšœžœ˜$J˜ ˜Jšžœ\˜a—J˜ Jšœžœ˜+Jšœ žœ˜&J˜ Jšœžœ˜(J˜Jšœžœ'˜EJ˜ Jšœ žœ˜Jšœžœ˜,Jšœžœ:˜RJ˜J˜ šœ žœ8˜IJ˜—Jšœžœ ˜-šœ žœ˜J˜Q—Jšœ žœ˜Jšœ žœ˜Jšœ žœ#˜4Jšœ žœ*˜:J˜šžœžœA˜JJ˜ —Jšœ žœ˜"Jšœžœ!˜5Jšœžœ:˜MJ˜——šœž˜šž˜J˜J˜ J˜J˜J˜J˜J˜J˜J˜J˜ J˜ J˜J˜ J˜ J˜ J˜ J˜Jšžœ˜J˜ J˜J˜ —šž˜J˜J˜J˜ J˜ —Jšœž˜Jšœ žœ˜,Jšœžœ˜(Jšœ žœ˜.Jšœ žœ˜.Jšžœžœžœ˜J˜Jšœ™Jšœ žœ ˜Jšœžœ ˜Jšœžœžœ˜*Jšœžœ˜1Jšœžœžœ˜-Jšœžœžœ˜1J˜šœžœžœ˜2Jšœ™J˜—Jšœžœžœ˜Jšœ žœžœ˜J˜šΟn œžœžœžœ˜JšœHžœ˜LJšœ<žœ˜@Jšœ2žœ˜6Jšœžœ˜Jšœ žœ˜$Jšœžœ˜Jšœžœ˜—šœ˜Jšœ™Jšžœžœžœ˜˜"J˜.J˜(J˜/—J˜!J˜FJ˜7J˜J˜J˜—šŸ œžœ˜J˜B—˜JšœN™NJšœF™FJšœV™VJ˜(J˜=šœB˜Bšœžœž˜Jšœžœ˜Jšžœž˜—Jšœ˜—J˜*J˜9J˜>J˜J˜—JšŸœžœ/˜Cšœ˜JšœP™PJšœU™UJšœ™J˜J˜3J˜>J˜J˜—šŸœžœ˜Jš œ(žœžœžœ žœ˜_—šœ˜Jšœ,™,J˜8J˜&Jšœ=™=J˜3˜ J˜+Jšœ žœ-˜:—Jšœ™J˜4Jšœ(™(J˜$šžœžœ˜˜7J˜1J˜J˜(J˜J˜J˜Jšœ)žœ˜.J˜"J˜J˜'—J˜—Jšžœ)˜-˜3J˜1J˜J˜(J˜/J˜—Jšžœžœ-˜OJ˜!˜!J˜J˜—˜ J˜J˜ J˜)—J˜J˜—JšŸœžœžœ˜<šœ˜˜>J˜1Jšœžœ˜—Jšžœ%˜+J˜J˜—JšŸœžœ˜4šœ˜šžœ˜J˜1J˜&Jšœ$žœžœžœ˜G—J˜J˜—šŸ œžœ&˜6Jšžœ˜"—šœ˜JšŸ œžœžœžœ˜LJ˜LJ˜J˜—š œžœžœž œžœ˜7J˜J˜J˜JšœH™HJ˜—JšŸ œžœi˜{šœ˜J˜;J˜>šžœ'žœ˜/J˜"J˜UJ˜—˜J˜W˜J˜T—Jš œžœžœžœžœ˜M˜JšœB˜B—˜Jšœ;žœ˜B—J˜—J˜J˜—JšŸ œžœžœ-˜]šœ˜J˜;J˜>Jšžœ'žœžœ˜4˜J˜W˜J˜U—Jš œžœžœžœžœ˜MJšœU˜U˜Jšœ-žœ˜4—J˜—J˜J˜—JšŸœžœ,˜Bšœ˜J˜;J˜>Jšžœ'žœžœ˜4˜J˜W˜J˜U—Jš œžœžœžœžœ˜MJ˜%˜Jšœ;žœ˜B—J˜—J˜J˜—šŸœžœ˜,Jšžœ˜"—šœ˜J˜;J˜>Jšžœ'žœžœ˜4˜J˜W˜J˜U—Jš œžœžœžœžœ˜MJ˜-˜Jšœ-žœ˜4—J˜—J˜J˜—šŸœžœ˜+Jšžœ4˜;—šœ˜Jšœ;™;Jš žœžœžœ žœ žœžœ˜?Jšœžœžœ ˜J˜Jšžœžœ˜J˜J˜—Jšœ ™ J˜šŸœžœžœ˜'J˜-—˜J˜J˜Jšœžœ˜%J˜8Jšœ#žœ˜(˜7J˜.J˜4J˜2J˜0J˜+J˜9J˜—J˜DJšœžœ(˜CJ˜J˜—šŸœΒ˜ΠJ˜>—šŸ œκ˜χJšœG˜G—šŸ œΡ˜έJšœF˜FJ˜—JšŸœžœžœ˜*šœ˜J˜&J˜+J˜J˜—JšŸœžœžœ˜)šœ˜J˜#J˜J˜—JšŸœžœžœ˜(šœ˜J˜"J˜$J˜)J˜J˜—JšžœΟc˜J˜—Jšžœž˜ J˜J˜*JšœR™RJ˜Jšœ1ž˜4Jšœ™J™J™™%K™—K™—…—4πFm