-- AlpineTransMgr.mesa -- Calls between coordinator and worker in two-phase commit protocol. -- Last edited by -- Taft on 30-Jan-82 18:00:29 -- MBrown on October 22, 1982 8:52 pm DIRECTORY AlpineEnvironment; AlpineTransMgr: DEFINITIONS = BEGIN -- Call worker -> coordinator. -- Duplicate call from worker to coordinator (caused e.g. by worker crash or major --communications failure) is an error. RegisterWorker: PROC [ conversation: AlpineEnvironment.Conversation, trans: AlpineEnvironment.TransID] RETURNS [RegisterWorkerResult]; --! (none); RegisterWorkerResult: TYPE = {ok, transNotActive, duplicateCall}; -- Calls coordinator -> worker. -- Duplicate calls are ok, so implementations of these procedures must be --prepared for them. WorkerPrepare: PROC [ conversation: AlpineEnvironment.Conversation, trans: AlpineEnvironment.TransID, newTrans: AlpineEnvironment.TransID] RETURNS [WorkerState --{notReady, readOnlyReady, ready}--]; -- ! Refused {wrongCoordinator}; -- if trans.state = active, then (attempt to make trans ready): -- if trans has performed only reads, return "readOnlyReady" -- else if trans can't get ready, return "notReady" -- else (trans gets ready) return "ready" -- else if trans.state = ready, return "ready" -- else (trans has no volatile state or trans.state = completing) return "notReady" -- -- if "notReady" or "readOnlyReady" result, worker erases volatile -- state of transaction, and coordinator need not call WorkerFinish. -- if "ready" result, coordinator must call WorkerFinish to complete transaction. -- if newTrans # nullTransID and "readOnlyReady", worker starts newTrans --and transfers downgraded locks from trans to newTrans. -- if newTrans # nullTransID and "ready", worker starts newTrans and if --WorkerFinish[requiredOutcome: commit] follows, worker transfers downgraded --locks from trans to newTrans. WorkerFinish: PROC [ conversation: AlpineEnvironment.Conversation, trans: AlpineEnvironment.TransID, requiredOutcome: RequiredOutcome --{abort, commit}--]; -- ! Refused {wrongCoordinator, notReady}; -- if trans.state = active and requiredOutcome = commit then ERROR Refused[notReady] -- else if trans.state = active or ready, then make trans go to requiredOutcome -- else (trans has no volatile state, or trans.state = completing) return. RequiredOutcome: TYPE = AlpineEnvironment.CommitOrAbort; WorkerState: TYPE = AlpineEnvironment.WorkerState; Refused: ERROR [why: Refusal]; Refusal: TYPE = {wrongCoordinator, notReady}; END.