AccessControl
USING[AccessFailed, AddOwner, EnumerateAllOwners, LockFailed, OperationFailed, ReadOwnerFileProperties, ReadOwnerProperties, ReorganizeOwnerFile, RemoveOwner, StaticallyInvalid, Unknown, WriteOwnerProperties],
AlpineEnvironment
USING[Conversation, LockFailure, NeededAccess, OperationFailure, OwnerName, OwnerProperty, OwnerPropertySet, OwnerPropertyValuePair, PageCount, TransID, UnknownType, VolumeGroupID],
AlpineOwner
USING[AccessFailed, LockFailed, OperationFailed, StaticallyInvalid, Unknown],
FilePrivate
USING[EstablishTransactionContext, TransactionWork];
OwnerActionsImpl:
PROGRAM
IMPORTS AC: AccessControl, AO: AlpineOwner, FP: FilePrivate
EXPORTS AlpineOwner =
BEGIN OPEN AE: AlpineEnvironment;
Create:
PUBLIC
PROCEDURE[conversation:
AE.Conversation, transID:
AE.TransID, volumeGroupID:
AE.VolumeGroupID, owner:
AE.OwnerName, properties:
LIST
OF
AE.OwnerPropertyValuePair, enforceTotalQuota:
BOOLEAN]
RETURNS[spaceLeftOnVolumeGroup:
AE.PageCount] =
BEGIN -- non system-fatal errors: AccessFailed[alpineWheel], LockFailed[timeout], OperationFailed[duplicateOwner, ownerDatabaseFull, ownerRecordFull, totalQuotaExceeded], StaticallyInvalid, Unknown[transID, volumeGroupID].
whyOpFailed: AE.OperationFailure;
whyUnknown: AE.UnknownType;
Work:
FP.TransactionWork
--[trans, pUpdateCost]-- =
BEGIN
FOR item: LIST OF AE.OwnerPropertyValuePair ← properties, item.rest
WHILE item #
NIL DO
IF item.first.property NOT IN AE.OwnerProperty THEN ERROR AO.StaticallyInvalid;
ENDLOOP;
spaceLeftOnVolumeGroup ←
AC.AddOwner[conversation, trans, volumeGroupID, owner, (
NOT enforceTotalQuota), properties
!
AC.AccessFailed =>
GOTO noAccess;
AC.LockFailed => GOTO lockFailed;
AC.OperationFailed => BEGIN whyOpFailed ← why; GOTO opFailed; END;
AC.StaticallyInvalid => GOTO statInvalid;
AC.Unknown => BEGIN whyUnknown ← why; GOTO unknown; END;]
EXITS
noAccess => ERROR AO.AccessFailed[alpineWheel];
lockFailed => ERROR AO.LockFailed[timeout];
opFailed => ERROR AO.OperationFailed[whyOpFailed];
statInvalid => ERROR AO.StaticallyInvalid;
unknown => ERROR AO.Unknown[whyUnknown];
END; -- Work
FP.EstablishTransactionContext[conversation: conversation, transID: transID, work: Work, workLevel: hard]; -- This must start work with workLevel = hard because it dirties the owner data base
END;
Destroy:
PUBLIC
PROCEDURE[conversation:
AE.Conversation, transID:
AE.TransID,
volumeGroupID:
AE.VolumeGroupID, owner:
AE.OwnerName] =
BEGIN -- non system-fatal errors: AccessFailed[alpineWheel], LockFailed[timeout], OperationFailed[ownerRecordInUse, spaceInUseByThisOwner], StaticallyInvalid, Unknown[owner, transID, volumeGroupID].
whyOpFailed: AE.OperationFailure;
whyUnknown: AE.UnknownType;
Work:
FP.TransactionWork
--[trans, pUpdateCost]-- =
BEGIN
AC.RemoveOwner[conversation, trans, volumeGroupID, owner
!
AC.AccessFailed =>
GOTO noAccess;
AC.LockFailed => GOTO lockFailed;
AC.OperationFailed => BEGIN whyOpFailed ← why; GOTO opFailed; END;
AC.StaticallyInvalid => GOTO statInvalid;
AC.Unknown => BEGIN whyUnknown ← why; GOTO unknown; END];
EXITS
noAccess => ERROR AO.AccessFailed[alpineWheel];
lockFailed => ERROR AO.LockFailed[timeout];
opFailed => ERROR AO.OperationFailed[whyOpFailed];
statInvalid => ERROR AO.StaticallyInvalid;
unknown => ERROR AO.Unknown[whyUnknown];
END; -- Work
FP.EstablishTransactionContext[conversation: conversation, transID: transID, work: Work, workLevel: hard]; -- This must start work with workLevel=hard because it dirties the owner data base
END;
ReadProperties:
PUBLIC
PROCEDURE[conversation:
AE.Conversation, transID:
AE.TransID, volumeGroupID:
AE.VolumeGroupID, owner:
AE.OwnerName, desiredProperties:
AE.OwnerPropertySet]
RETURNS [properties:
LIST
OF
AE.OwnerPropertyValuePair] =
BEGIN -- non system-fatal errors: LockFailed[timeout], StaticallyInvalid, Unknown[owner, transID, volumeGroupID].
whyUnknown: AE.UnknownType;
Work:
FP.TransactionWork
--[trans, pUpdateCost]-- =
BEGIN
properties ←
AC.ReadOwnerProperties[conversation, trans, volumeGroupID, owner, desiredProperties
!
AC.LockFailed =>
GOTO lockFailed;
AC.StaticallyInvalid => GOTO statInvalid;
AC.Unknown => BEGIN whyUnknown ← why; GOTO unknown; END];
EXITS
lockFailed => ERROR AO.LockFailed[timeout];
statInvalid => ERROR AO.StaticallyInvalid;
unknown => ERROR AO.Unknown[whyUnknown];
END; -- Work
FP.EstablishTransactionContext[conversation, transID, Work];
END;
WriteProperties:
PUBLIC
PROCEDURE[conversation:
AE.Conversation, transID:
AE.TransID, volumeGroupID:
AE.VolumeGroupID, owner:
AE.OwnerName, properties:
LIST
OF
AE.OwnerPropertyValuePair, enforceTotalQuota:
BOOLEAN] =
BEGIN -- non system-fatal errors: AccessFailed[alpineWheel, ownerEntry], LockFailed[timeout], OperationFailed[ownerRecordFull, ownerRecordInUse, regServersUnavailable, totalQuotaExceeded], StaticallyInvalid, Unknown[owner, transID, volumeGroupID].
whyAccess: AE.NeededAccess;
whyOpFailed: AE.OperationFailure;
whyUnknown: AE.UnknownType;
Work:
FP.TransactionWork
--[trans, pUpdateCost]-- =
BEGIN
FOR item: LIST OF AE.OwnerPropertyValuePair ← properties, item.rest
WHILE item #
NIL DO
IF item.first.property NOT IN AE.OwnerProperty THEN ERROR AO.StaticallyInvalid;
ENDLOOP;
[] ←
AC.WriteOwnerProperties[conversation, trans, volumeGroupID, owner, (
NOT enforceTotalQuota), properties
!
AC.AccessFailed =>
BEGIN whyAccess ← why;
GOTO noAccess;
END;
AC.LockFailed => GOTO lockFailed;
AC.OperationFailed => BEGIN whyOpFailed ← why; GOTO opFailed; END;
AC.StaticallyInvalid => GOTO statInvalid;
AC.Unknown => BEGIN whyUnknown ← why; GOTO unknown; END];
EXITS
noAccess => ERROR AO.AccessFailed[whyAccess];
lockFailed => ERROR AO.LockFailed[timeout];
opFailed => ERROR AO.OperationFailed[whyOpFailed];
statInvalid => ERROR AO.StaticallyInvalid;
unknown => ERROR AO.Unknown[whyUnknown];
END; -- Work
FP.EstablishTransactionContext[conversation: conversation, transID: transID, work: Work, workLevel: hard]; -- This must start work with workLevel=hard because it dirties the owner data base
END;
ReadDBProperties:
PUBLIC
PROCEDURE[conversation:
AE.Conversation, transID:
AE.TransID, volumeGroupID:
AE.VolumeGroupID]
RETURNS [nOwners, nEntriesUsed, nEntries:
NAT, totalQuota, totalSpaceInUse, volumeGroupSize:
AE.PageCount] =
BEGIN -- non system-fatal errors: AccessFailed[alpineWheel], LockFailed[timeout], Unknown[transID, volumeGroupID].
whyUnknown: AE.UnknownType;
Work:
FP.TransactionWork
--[trans, pUpdateCost]-- =
BEGIN
quotaLeft: AlpineEnvironment.PageCount;
[totalQuota: totalQuota, quotaLeft: quotaLeft, volumeGroupSize: volumeGroupSize, numberOfOwners: nOwners, numberOfOwnerSlotsInUse: nEntriesUsed, maxNumberOfOwnersAllowed: nEntries] ←
AC.ReadOwnerFileProperties[conversation, trans, volumeGroupID
!
AC.AccessFailed =>
GOTO noAccess;
AC.LockFailed => GOTO lockFailed;
AC.Unknown => BEGIN whyUnknown ← why; GOTO unknown; END];
totalSpaceInUse ← totalQuota - quotaLeft;
EXITS
noAccess => ERROR AO.AccessFailed[alpineWheel];
lockFailed => ERROR AO.LockFailed[timeout];
unknown => ERROR AO.Unknown[whyUnknown];
END; -- Work
FP.EstablishTransactionContext[conversation, transID, Work];
END;
ReadNext:
PUBLIC
PROCEDURE[conversation:
AE.Conversation, transID:
AE.TransID, volumeGroupID:
AE.VolumeGroupID, previousOwner:
AE.OwnerName, desiredProperties:
AE.OwnerPropertySet]
RETURNS [owner:
AE.OwnerName, properties:
LIST
OF
AE.OwnerPropertyValuePair] =
BEGIN -- non system-fatal errors: AccessFailed[alpineWheel], LockFailed[timeout], StaticallyInvalid, Unknown[owner, transID, volumeGroupID].
whyUnknown: AE.UnknownType;
Work:
FP.TransactionWork
--[trans, pUpdateCost]-- =
BEGIN
[owner, properties] ←
AC.EnumerateAllOwners[conversation, trans, volumeGroupID, previousOwner, desiredProperties
!
AC.AccessFailed =>
GOTO noAccess;
AC.LockFailed => GOTO lockFailed;
AC.StaticallyInvalid => GOTO statInvalid;
AC.Unknown => BEGIN whyUnknown ← why; GOTO unknown; END];
EXITS
noAccess => ERROR AO.AccessFailed[alpineWheel];
lockFailed => ERROR AO.LockFailed[timeout];
statInvalid => ERROR AO.StaticallyInvalid;
unknown => ERROR AO.Unknown[whyUnknown];
END; -- Work
FP.EstablishTransactionContext[conversation, transID, Work];
END;
ReorganizeDB:
PUBLIC
PROCEDURE [conversation:
AE.Conversation, transID:
AE.TransID, volumeGroupID:
AE.VolumeGroupID, nEntries:
NAT] =
BEGIN -- non system-fatal errors: AccessFailed[alpineWheel], LockFailed[timeout], OperationFailed[insufficientSpace, ownerDatabaseFull], Unknown[transID, volumeGroupID].
whyOpFailed: AE.OperationFailure;
whyUnknown: AE.UnknownType;
Work:
FP.TransactionWork
--[trans, pUpdateCost]-- =
BEGIN
AC.ReorganizeOwnerFile[conversation, trans, volumeGroupID, nEntries
!
AC.AccessFailed =>
GOTO noAccess;
AC.LockFailed => GOTO lockFailed;
AC.OperationFailed => BEGIN whyOpFailed ← why; GOTO opFailed; END;
AC.Unknown => BEGIN whyUnknown ← why; GOTO unknown; END];
EXITS
noAccess => ERROR AO.AccessFailed[alpineWheel];
lockFailed => ERROR AO.LockFailed[timeout];
opFailed => ERROR AO.OperationFailed[whyOpFailed];
unknown => ERROR AO.Unknown[whyUnknown];
END; -- Work
FP.EstablishTransactionContext[conversation, transID, Work, hard]; -- This must start work with workLevel=hard because it dirties the owner data base
END;
END.