-- 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.