-- Coordinator.mesa
-- Defines the volatile state of a coordinator.
-- Last edited by
-- MBrown on January 30, 1984 11:51:40 am PST
DIRECTORY
AlpineEnvironment,
AlpineImport USING [Handle],
AlpineInternal USING [LogRecordID, nullLogRecordID],
BasicTime USING [GMT],
RPC USING [maxShortStringLength];
Coordinator: DEFINITIONS LOCKS c USING c: Handle =
BEGIN
Object: TYPE = MONITORED RECORD [
transID: AlpineEnvironment.TransID ← TRASH, --immutable--
beginRecord: AlpineInternal.LogRecordID ← AlpineInternal.nullLogRecordID, --immutable--
state: State ← active,
--increases monotonically from active to complete
outcome: Outcome ← unknown,
-- Changes to abort or commit during state transition collecting -> completing.
finishInProgress: BOOL ← FALSE,
-- A process that sets this TRUE is responsible for finishing the transaction.
aWorkerBecameReady: BOOL ← FALSE,
-- TRUE iff some worker returns "ready" from WorkerPrepare call.
workers: WorkerHandle ← NIL,
-- Elements added only when state = active.
resultsReturned: CONDITION,
-- Finish process waits here for remote calls to return, or for timeout
--in order to delay sending new calls.
forceRecord: AlpineInternal.LogRecordID ← AlpineInternal.nullLogRecordID,
-- ID of log record following last-written coordinator log record
next: Handle ← nullHandle
--CoordinatorMap data structure
];
Handle: TYPE = REF Object;
nullHandle: Handle = NIL;
State: TYPE = {active, collecting, completing, complete};
Outcome: TYPE = AlpineEnvironment.Outcome --{abort, commit, unknown}--;
WorkerObject: TYPE = RECORD [
worker: AlpineImport.Handle, --immutable--
state: WorkerState ← active, --increases monotonically from active to complete--
communicationTrouble: BOOL ← FALSE,
callInProgress: Call ← none, --communication in progress with worker--
resultsOfMostRecentCall: Results ← [none, none[]],
timeForNextCall: BasicTime.GMT ← TRASH,
-- meaningful only if communicationTrouble
lastPrepareResult: Results ← [none, none[]],
lastFinishResult: Results ← [none, none[]]
];
WorkerHandle: TYPE = LIST OF WorkerObject;
WorkerState: TYPE = { active, ready, complete };
Call: TYPE = { none, prepare, finish };
Results: TYPE = RECORD [
communicationError: CommunicationError,
body: SELECT call: Call FROM
none => [],
prepare => [prepareResult: AlpineEnvironment.WorkerState],
finish => []
ENDCASE
];
CommunicationError: TYPE = { none, bindingFailed, callFailed, busy };
-- bindingFailed means that no call was made
-- callFailed means that call may or may not have been made
-- busy is equivalent to callFailed, but retrying is more likely to succeed.
-- Format of persistent coordinator state.
-- Note that coordinatorBegin and coordinatorComplete log records contain no information
--other than the transaction ID, so we don't define structures for them here.
RegisterWorkerLogRep: TYPE = MACHINE DEPENDENT RECORD [
worker: StrBody];
CompletingLogRep: TYPE = MACHINE DEPENDENT RECORD [
outcome: AlpineEnvironment.CommitOrAbort];
StrBody: TYPE = MACHINE DEPENDENT RECORD [
length: CARDINAL ← 0, maxLength: CARDINAL ← RPC.maxShortStringLength,
text: PACKED ARRAY[0..RPC.maxShortStringLength) OF CHAR];
END.