FileActionsImpl.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Carl Hauser, January 8, 1987 1:52:47 pm PST
Last edited by:
Taft on May 25, 1983 4:59 pm
MBrown on February 1, 1984 5:00:04 pm PST
Kolling on May 31, 1983 5:39 pm
Last Edited by: Kupfer, February 28, 1985 1:22:25 pm PST
Loose ends:
1. When we get around to implementing the resumable signal PossiblyDamaged, the catch of ANY in EstablishTransactionContext will need to be reconsidered.
2. If client can predict what OpenFileID will be returned by Open or Create, he may be able to sneak in by virtue of the temporary access provided for AccessControl operations. Is this worth fixing? If so, how?
3. Similarly, if client can predict what FileID will be generated by Create, he may be able to do an Open that references the leader page before it has been initialized, with undefined results.
4. Should we prevent a client from setting locks inconsistent with the client's access to the file (e.g., write locks on a read-only file, or any locks on a read-protected file)? Permitting this enables a client to tie up an arbitrary file with locks and thereby interfere with other clients' access.
5. Create needs to restrict file types.
DIRECTORY
OldAlpineFile,
AlpineFile, 
OldAlpineEnvironment;
FileActionsImpl: PROGRAM
IMPORTS AlpineFile, OldAlpineFile
EXPORTS OldAlpineFile =
BEGIN OPEN OldAlpineFile;
OldAlpineFile.
Open: PUBLIC PROCEDURE [conversation: Conversation, transID: TransID, universalFile: UniversalFile, access: AccessRights ← readOnly, lock: LockOption ← [intendRead, wait], recoveryOption: RecoveryOption ← log, referencePattern: ReferencePattern ← random] RETURNS [openFileID: OpenFileID, fileID: FileID] =
BEGIN
Work: PROC = {
[openFileID, fileID] ← AlpineFile.Open[conversation, transID, universalFile, access, lock, recoveryOption, referencePattern];
};
DoWork[Work];
END;
Create: PUBLIC PROCEDURE [conversation: Conversation, transID: TransID, volumeID: VolOrVolGroupID, owner: OwnerName, initialSize: PageCount, recoveryOption: RecoveryOption ← log, referencePattern: ReferencePattern ← random] RETURNS [openFileID: OpenFileID, universalFile: UniversalFile] =
BEGIN
Work: PROC = {
[openFileID, universalFile] ← AlpineFile.Create[conversation, transID, volumeID, owner, initialSize, recoveryOption, referencePattern];
};
DoWork[Work];
END;
Close: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] =
BEGIN
Work: PROC = {
AlpineFile.Close[conversation, openFileID];
};
DoWork[Work];
END;
Delete: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] =
BEGIN
Work: PROC = {
AlpineFile.Delete[conversation, openFileID];
};
DoWork[Work];
END;
GetUniversalFile: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] RETURNS [universalFile: UniversalFile] =
BEGIN
Work: PROC = {
universalFile ← AlpineFile.GetUniversalFile[conversation, openFileID];
};
DoWork[Work];
END;
GetTransID: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] RETURNS [transID: TransID] =
BEGIN
Work: PROC = {
transID ← AlpineFile.GetTransID[conversation, openFileID];
};
DoWork[Work];
END;
GetAccessRights: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] RETURNS [access: AccessRights] =
BEGIN
Work: PROC = {
access ← AlpineFile.GetAccessRights[conversation, openFileID];
};
DoWork[Work];
END;
GetLockOption: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] RETURNS [lock: LockOption] =
BEGIN
Work: PROC = {
lock ← AlpineFile.GetLockOption[conversation, openFileID];
};
DoWork[Work];
END;
SetLockOption: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID, lock: LockOption] =
BEGIN
Work: PROC = {
AlpineFile.SetLockOption[conversation, openFileID, lock];
};
DoWork[Work];
END;
GetRecoveryOption: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] RETURNS [recoveryOption: RecoveryOption] =
BEGIN
Work: PROC = {
recoveryOption ← AlpineFile.GetRecoveryOption[conversation, openFileID];
};
DoWork[Work];
END;
GetReferencePattern: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] RETURNS [referencePattern: ReferencePattern] =
BEGIN
Work: PROC = {
referencePattern ← AlpineFile.GetReferencePattern[conversation, openFileID];
};
DoWork[Work];
END;
SetReferencePattern: PUBLIC PROCEDURE [ conversation: Conversation, openFileID: OpenFileID, referencePattern: ReferencePattern] =
BEGIN
Work: PROC = {
AlpineFile.SetReferencePattern[conversation, openFileID, referencePattern];
};
DoWork[Work];
END;
ReadProperties: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID, desiredProperties: PropertySet ← allProperties, lock: LockOption ← [read, wait]] RETURNS [properties: LIST OF PropertyValuePair] =
BEGIN
Work: PROC = {
properties ← AlpineFile.ReadProperties[conversation, openFileID, desiredProperties, lock];
};
DoWork[Work];
END;
WriteProperties: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID, properties: LIST OF PropertyValuePair, lock: LockOption ← [update, wait]] =
BEGIN
Work: PROC = {
AlpineFile.WriteProperties[conversation, openFileID, properties, lock];
};
DoWork[Work];
END;
UnlockVersion: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] =
BEGIN
Work: PROC = {
AlpineFile.UnlockVersion[conversation, openFileID];
};
DoWork[Work];
END;
IncrementVersion: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID, increment: LONG CARDINAL] =
BEGIN
Work: PROC = {
AlpineFile.IncrementVersion [conversation, openFileID, increment];
};
DoWork[Work];
END;
GetSize: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID, lock: LockOption ← [read, wait]] RETURNS [size: PageCount] =
BEGIN
Work: PROC = {
size ← AlpineFile.GetSize [conversation, openFileID, lock];
};
DoWork[Work];
END;
SetSize: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID, size: PageCount, lock: LockOption ← [update, wait]] =
BEGIN
Work: PROC = {
AlpineFile.SetSize [conversation, openFileID, size, lock];
};
DoWork[Work];
END;
UnlockFile: PUBLIC PROCEDURE [conversation: Conversation, openFileID: OpenFileID] =
BEGIN
Work: PROC = {
AlpineFile.UnlockFile [conversation, openFileID];
};
DoWork[Work];
END;
DoWork: PROC [work: PROC] RETURNS [] ~ {
accessReason: OldAlpineEnvironment.NeededAccess;
lockReason: OldAlpineEnvironment.LockFailure;
operationReason: OldAlpineEnvironment.OperationFailure;
unknownWhat: OldAlpineEnvironment.UnknownType;
{
ENABLE {
AlpineFile.AccessFailed => {accessReason ← missingAccess; GOTO accessFailed};
AlpineFile.LockFailed => {
lockReason ← SELECT why FROM
conflict, cantConvert => conflict,
timeout => timeout,
ENDCASE => ERROR;
GOTO lockFailed};
AlpineFile.OperationFailed => {operationReason ← why; GOTO operationFailed};
AlpineFile.StaticallyInvalid => {GOTO staticallyInvalid};
AlpineFile.Unknown => {unknownWhat ← what; GOTO unknown};
};
work[];
EXITS
accessFailed => ERROR OldAlpineFile.AccessFailed[accessReason];
lockFailed => ERROR OldAlpineFile.LockFailed[lockReason];
operationFailed => ERROR OldAlpineFile.OperationFailed[operationReason];
staticallyInvalid => ERROR OldAlpineFile.StaticallyInvalid;
unknown => ERROR OldAlpineFile.Unknown[unknownWhat];
};
};
END.