InitProcsImpl.mesa
Copyright © 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, March 26, 1987 11:37:59 am PST
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;
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: BOOLFALSE;
isStarted: BOOLFALSE;
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,
additionalVolumes: LIST OF ROPENIL,
logVolumeName: ROPENIL,
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] = {
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, backupBTree: FileID;
logFile ← CreateFile[logVolume, logPages];
restartFile ← CreateFile[logVolume, 1];
SetRootFiles[logVolume, logFile, restartFile, backupBTree];
LogControl.Format[logVolume, logFile, restartFile, fileStore];
};
ResizeLog: PROC [
logVolume: VolumeID, logPages: PageCount, fileStore: FileStore] = {
Formats a log of the requested size to a well-defined initial state that is acceptable to
Recover below. This should not be called while the server is running.
Calling ResizeLog, then Recover, is equivalent to a cold-start.
logFile, restartFile, ownerFile, backupBTree: FileID;
[logFile, restartFile, ownerFile, backupBTree] ← GetRootFiles[logVolume];
File.Delete[File.LabeledOpen[File.FindVolumeFromID[logVolume], logFile] !
File.Error => SELECT why FROM
unknownFile => CONTINUE;
ENDCASE => REJECT
];
logFile ← CreateFile[logVolume, logPages];
SetRootFiles[logVolume, logFile, restartFile, ownerFile, backupBTree];
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, additionalVolumes: LIST OF 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: additionalVolumes]];
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,
backupBTree: FileID
];
Format of file that is stored as File.VolumeFile.alpine in Cedar volume.
SetRootFiles: PROC [logVolume: VolumeID, logFile, restartFile: FileID, ownerFile, backupBTree: 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[volume: rootVolume, root: $alpine, file: File.LabeledOpen[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, backupBTree: backupBTree];
FilePageMgr.ReleaseVMPageSet[
vMPageSet: chunk, releaseState: writeIndividualWait, keep: FALSE];
};
};
GetRootFiles: PROC [logVolume: VolumeID] RETURNS [logFile, restartFile, ownerFile, backupBTree: 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, backupBTree: backupBTree] ← 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] =
{
This kludge is guaranteed to work for a 1-volume system ...
ID: TYPE = RECORD [a, b, c: CARDINAL, sequence: LONG CARDINAL];
id: IDLOOPHOLE[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.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
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.
Nodified: Hauser: March 4, 1985
Hauser, March 8, 1985 10:35:14 am PST
Added copyright.