-- AlpineOwner.mesa -- Procedures for owner database maintenance. -- Last edited by -- Kolling on March 8, 1983 4:21 pm -- MBrown on March 3, 1983 2:45 pm -- Some aspects of owner database maintenance are decentralized, in that normal Alpine -- users may perform them. These include inspecting individual owner records and -- updating certain fields of owner records (these updates are restricted by access control -- checks that are a function of the owner). -- Other aspects of owner database maintenance are reserved for Alpine administrators. -- These include creating and deleting owner records, updating disk space quotas, -- and enumerating the entire set of owners. -- On a particular server, these operations may only be invoked by individuals who belong -- to that server's AlpineWheels group. Since these operations are potentially destructive, -- they must be explicitly "enabled" by a call to AlpineTransaction.AssertAlpineWheel. DIRECTORY AlpineEnvironment; AlpineOwner: DEFINITIONS = BEGIN AccessList: TYPE = AlpineEnvironment.AccessList; -- necessary, or lupine bombs out. Conversation: TYPE = AlpineEnvironment.Conversation; OwnerName: TYPE = AlpineEnvironment.OwnerName; PageCount: TYPE = AlpineEnvironment.PageCount; TransID: TYPE = AlpineEnvironment.TransID; VolumeGroupID: TYPE = AlpineEnvironment.VolumeGroupID; -- When a procedure raises AccessFailed [alpineWheel] below, this always means that -- the (conversation, transID) pair passed to the procedure needed to be asserted -- (by AlpineTransaction.AssertAlpineWheel[enable: TRUE]), but was not. -- Procedures for both Alpine users and Alpine administrators. OwnerProperty: TYPE = AlpineEnvironment.OwnerProperty; OwnerPropertyValuePair: TYPE = AlpineEnvironment.OwnerPropertyValuePair; OwnerPropertySet: TYPE = AlpineEnvironment.OwnerPropertySet; allOwnerProperties: OwnerPropertySet = AlpineEnvironment.allOwnerProperties; ReadProperties: PROC [ conversation: Conversation, transID: TransID, volumeGroupID: VolumeGroupID, owner: OwnerName, desiredProperties: OwnerPropertySet ← allOwnerProperties] RETURNS [properties: LIST OF OwnerPropertyValuePair]; -- ! LockFailed {timeout}, -- ! StaticallyInvalid, -- ! Unknown {owner, transID, volumeGroupID}. -- Reads the properties specified by desiredProperties, ordered as in the declaration -- of OwnerProperty. WriteProperties: PROC [ conversation: Conversation, transID: TransID, volumeGroupID: VolumeGroupID, owner: OwnerName, properties: LIST OF OwnerPropertyValuePair, enforceTotalQuota: BOOL ← FALSE]; -- ! AccessFailed {alpineWheel, ownerEntry}, -- ! LockFailed {timeout}, -- ! OperationFailed {ownerRecordFull, ownerRecordInUse, -- regServersUnavailable, totalQuotaExceeded}, -- ! StaticallyInvalid, -- ! Unknown {owner, transID, volumeGroupID}. -- Writes the supplied properties, leaving the others unchanged. Obtains a write -- lock on the owner record. (For now, WriteProperties fails by raising -- OperationFailed [ownerRecordInUse] if a write of the quota is requested and -- another transaction is concurrently changing the space in use by the given -- owner. Retrying may succeed.) -- The owner, and members of the owner's Modify access list, can update the -- Create access list property of an owner record. The owner, and members of -- the owner's Create access list can update the rootFile property of an owner record. -- If an update is restricted to the these properties, but the access control checks -- fail, then WriteProperties raises AccessFailed [ownerEntry]. The spaceInUse property -- is read only. -- If enforceTotalQuota = TRUE and properties includes quota, then WriteProperties -- raises OperationFailed [totalQuotaExceeded] if the total of all quotas in the owner -- database, including the specified update, exceeds the total number of disk pages -- on the volume group. -- On all updates, certain high-level invariants are enforced: owner access lists always -- have world = FALSE and owner = TRUE. -- An update to an access control list may raise OperationFailed [ownerRecordFull]. -- The system guarantees to reserve enough space for access control list storage so that -- each list can contain two maximum-length RNames, but does not control the -- division of space between lists. In order to add an element to one list it may be -- necessary to remove an element from another. -- Procedures for Alpine administrators only. These procedures require that -- (conversation, transID) be asserted as an Alpine Wheel. Create: PROC [ conversation: Conversation, transID: TransID, volumeGroupID: VolumeGroupID, owner: OwnerName, properties: LIST OF OwnerPropertyValuePair, enforceTotalQuota: BOOL ← FALSE] RETURNS [spaceLeftOnVolumeGroup: PageCount]; -- ! AccessFailed {alpineWheel}, -- ! LockFailed {timeout}, -- ! OperationFailed {duplicateOwner, ownerDatabaseFull, -- ownerRecordFull, totalQuotaExceeded}, -- ! StaticallyInvalid, -- ! Unknown {transID, volumeGroupID}. -- Creates a new owner in the specified VolumeGroup. The properties of the new -- owner are derived by (in effect) setting all properties to their default values, then -- calling WriteProperties with the specified list of properties. Destroy: PROC [ conversation: Conversation, transID: TransID, volumeGroupID: VolumeGroupID, owner: OwnerName]; -- ! AccessFailed {alpineWheel}, -- ! LockFailed {timeout}, -- ! OperationFailed {ownerRecordInUse, spaceInUseByThisOwner}, -- ! StaticallyInvalid, -- ! Unknown {owner, transID, volumeGroupID}. -- Destroys an existing owner in the specified VolumeGroup. -- Raises OperationFailed [spaceInUseByThisOwner] if any files exist whose disk space -- is charged against owner. ReadNext: PROC [ conversation: Conversation, transID: TransID, volumeGroupID: VolumeGroupID, previousOwner: OwnerName, desiredProperties: OwnerPropertySet ← allOwnerProperties] RETURNS [owner: OwnerName, properties: LIST OF OwnerPropertyValuePair]; -- ! AccessFailed {alpineWheel}, -- ! LockFailed {timeout}, -- ! StaticallyInvalid, -- ! Unknown {owner, transID, volumeGroupID}. -- Stateless enumerator for the owner database. previousOwner = NIL starts an -- enumeration, and owner = NIL is returned at the end of an enumeration. -- This call locks the entire owner database in write mode to ensure consistency, -- which is the reason for restricting its use to Alpine administrators. ReadDBProperties: PROC [ conversation: Conversation, transID: TransID, volumeGroupID: VolumeGroupID] RETURNS [nOwners, nEntriesUsed, nEntries: NAT, totalQuota, totalSpaceInUse, volumeGroupSize: PageCount]; -- ! AccessFailed {alpineWheel}, -- ! LockFailed {timeout}, -- ! Unknown {transID, volumeGroupID}. -- Returns aggregate information about the owner database. -- <Locking?> -- nOwners is the number of owners in the database, while nEntriesUsed is the -- number of database entries in use (deleted entries may occupy space). -- When nEntriesUsed = nEntries, any Create call will raise OperationFailed -- [ownerDatabaseFull]; a call to ReorganizeDB is required (see below) ReorganizeDB: PROC [ conversation: Conversation, transID: TransID, volumeGroupID: VolumeGroupID, nEntries: NAT]; -- ! AccessFailed {alpineWheel}, -- ! LockFailed {timeout}, -- ! OperationFailed {insufficientSpace, ownerDatabaseFull}, -- ! Unknown {transID, volumeGroupID}. -- Performs a complete reorganization of the owner database, locking it in write mode -- and thereby making it unavailable during the reorganization. -- Reorganization is called for when the owner database becomes full (Create raises -- OperationFailed [ownerDatabaseFull]), or when the performance of owner database -- operations degrades due to hash collisions or deletions. -- The new owner database file allows up to nEntries owners; ReorganizeDB raises -- OperationFailed [ownerDatabaseFull] if the existing database contains more than -- this many owners. ReorganizeDB raises OperationFailed [insufficientSpace] -- if there is not enough scratch space on the volume group to perform -- the reorganization. -- Errors AccessFailed: ERROR [missingAccess: AlpineEnvironment.NeededAccess]; LockFailed: ERROR [why: AlpineEnvironment.LockFailure]; OperationFailed: ERROR [why: AlpineEnvironment.OperationFailure]; StaticallyInvalid: ERROR; Unknown: ERROR [what: AlpineEnvironment.UnknownType]; END.