-- File: AltoFile.mesa
-- Last edited by Levin: 30-Apr-81 13:46:41
DIRECTORY
AltoDefs USING [BytesPerPage, MaxFilePage, PageNumber],
AltoFileDefs USING [CFP, DEfile, DEfree, DirFP, DV, FilenameChars, FP, LD, SN],
DiskIODefs USING [DiskRequest, FID, fillInvDA, vDA],
FileDefs USING [defaultTime, FileHandle, FileTime, Operations, Position];
AltoFile: DEFINITIONS =
BEGIN OPEN DiskIODefs;
-- This interface contains procedures specific to the Alto file system. It contains
-- procedures for use by VM clients who wish to perform operations that may not
-- have analogues in other file systems and therefore do not appear in the VMDefs
-- interface. However, this interface by itself is not complete; it is expected
-- to be used in conjunction with the operations obtained through the FileDefs
-- interface by logging into the Alto file system.
-- This interface provides a file abstraction characterized by the following
-- properties:
-- 1) Files consist of a sequence of 512-byte pages.
-- 2) Files are considered to be a sequence of bytes, numbered by the pair
-- <page, byte>. Both 'page' and 'byte' are 0-origin, so that the first byte of
-- data in the file is <0,0>.
-- 3) All bytes of the file are under the client's exclusive control; the
-- implementation of this interface stores no information within the data portion
-- of the file.
-- 4) A file is named by an identifier called a "file pointer" (FP), which locates
-- the file uniquely on the disk and establishes the location of the information
-- used internally by the implementation to describe and manage the file.
-- These conventions permit an implementation that is compatible with the Alto file
-- system assumptions and which does not introduce noticeable overheads. The
-- implementation recognizes the differences in file addressing implied by the
-- conventions above and performs the appropriate transformations to ensure
-- compatibility.
-- The file interface consists of four logical components: (1) file manipulation,
-- (2) file i/o support, (3) disk space management, and (4) directory management.
-- Definitions for these components are grouped together below.
-- Access to operations provided indirectly through FileDefs --
altoOps: FileDefs.Operations;
-- (1) File Manipulation --
-- Types and Related Constants --
FileHandle: TYPE = FileDefs.FileHandle;
FP: TYPE = AltoFileDefs.FP;
CFP: TYPE = AltoFileDefs.CFP;
FPPtr: TYPE = POINTER TO FP;
PageNumber: TYPE = [0..AltoDefs.MaxFilePage];
ByteNumber: TYPE = [0..AltoDefs.BytesPerPage);
Position: TYPE = FileDefs.Position;
FileTime: TYPE = FileDefs.FileTime;
defaultTime: FileTime = FileDefs.defaultTime;
-- Procedures and Signals --
OpenFromFP: PROCEDURE [fp: FP, markWritten: BOOLEAN] RETURNS [FileHandle];
-- The file specified by 'fp' is opened (it may already be open). The read time of
-- the file will be set to the current time. If 'markWritten' is TRUE, the written
-- and creation times of the file will be set to the current time. If the argument
-- file pointer is invalid, InvalidFP will be raised.
CloseFile: PROCEDURE [FileHandle];
-- closes the indicated file. This procedure is intended to be used on FileHandles
-- returned by OpenFromFP.
InvalidFP: ERROR [fp: FP];
-- The parameter does not correspond to an extant file.
GetFileTimes: PROCEDURE [file: FileHandle]
RETURNS [read, write, create: FileTime];
-- returns time stamps associated with 'file'. Note that 'read' will correspond
-- with the time the file was opened.
SetFileTimes: PROCEDURE [file: FileHandle,
read, write, create: FileTime ← defaultTime];
-- writes time stamps associated with 'file'. Defaulted values are set to "now".
CreateFile: PROCEDURE [name: STRING, directory: FP, leadervDA: vDA ← fillInvDA]
RETURNS [FP];
-- creates an empty file with name 'name' in 'directory', and returns its fp.
-- If 'leadervDA' is not equal to fillInvDA, CreateFile will attempt to place the
-- file's leader page as close as possible to the indicated disk address.
-- (2) File Input/Output --
-- This interface is closely related to the file manipulation facilities, but implies
-- a more intimate understanding of the representation of disk files. It is intended
-- for use by programs that do their own specialized input/output on files using the
-- DiskIODefs interface.
-- Types --
LD: TYPE = AltoFileDefs.LD;
LDPtr: TYPE = POINTER TO LD;
-- Procedures and Signals --
GetFileID: PROCEDURE [file: FileHandle] RETURNS [FID];
-- maps a FileHandle to the low-level identifier required by
-- DiskIODefs.DiskRequest.fileID.
FileToAltoPageNumber: PROCEDURE [page: PageNumber]
RETURNS [AltoDefs.PageNumber];
-- converts a FileDefs.PageNumber into an AltoDefs.PageNumber, which is suitable for
-- use in DiskIODefs.DiskRequest.firstPage.
MapPageToDiskAddress: PROCEDURE [file: FileHandle, page: PageNumber,
successors: CARDINAL ← 1]
RETURNS [nearPage: PageNumber, nearvda: vDA, knownPages: CARDINAL];
-- map the indicated 'page' of the given 'file' to a "nearby" disk address.
-- 'nearPage' will be the largest page number less than or equal to 'page' for which
-- the disk address is known, and 'nearvda' will be its disk address. If
-- nearPage ~= page, then knownPages will be 1. If nearPage = page, knownPages will
-- be the number of pages (limited to at most 'successors'+1) beginning at 'page' for
-- which the disk address is known.
EnterDiskAddress: PROCEDURE [file: FileHandle, page: AltoDefs.PageNumber, vda: vDA];
-- establishes a mapping between the indicated 'page' of 'file' and the disk address
-- 'vda'. Note that 'page' is an AltoDefs.PageNumber, not a FileDefs.PageNumber (the
-- two are incompatible). EnterDiskAddress is intended to be called only from a
-- DiskIODefs.VerboseCompletionProcedure, using label.page as the page number. This
-- interface does not define an official mapping between these two forms of PageNumber.
ReadLeaderPage: PROCEDURE [file: FileHandle, request: POINTER TO DiskRequest]
RETURNS [leader: LDPtr];
-- reads the leader page of 'file' into core, returning a pointer to it and leaving
-- request↑ suitable for calling RewriteLeaderPage.
RewriteLeaderPage: PROCEDURE [
file: FileHandle, request: POINTER TO DiskRequest, leader: LDPtr];
-- writes the leader page 'leader' onto 'file'. The storage associated with
-- 'leader' is then released.
-- (3) Disk Space Management --
-- Miscellaneous Declarations --
FreePageFileID: FID = FID[version: 177777B, serial: [[1, 1, 1], 17777B, 177777B]];
-- Procedures and Signals --
WaitForSpaceCrunch: PROCEDURE [pages: CARDINAL] RETURNS [BOOLEAN];
-- waits until the number of remaining free pages on the disk is less than or equal
-- to 'pages', then returns. Normally, this procedure returns TRUE; it returns FALSE
-- to all processes that are waiting when the file system is shut down. Note:
-- WaitForSpaceCrunch relies on internal hints in the disk descriptor. If these
-- hints are substantially incorrect, it may return too soon or not at all.
AllocateDiskPage: PROCEDURE [vda: vDA] RETURNS [vDA];
-- returns the address of the first available disk page following 'vda'.
DiskFull: ERROR;
-- raised by AllocateDiskPage if no available disk pages remain.
FreeDiskPage: PROCEDURE [vda: vDA];
-- releases the disk page whose address is 'vda'.
NewSN: PROCEDURE RETURNS [AltoFileDefs.SN];
-- allocates and returns a new (unique) serial number.
-- (4) Directory Manipulation --
-- Types and Related Constants --
DV: TYPE = AltoFileDefs.DV;
DVPtr: TYPE = POINTER TO DV;
sysDirFP: FP = AltoFileDefs.DirFP;
fileNameChars: CARDINAL = AltoFileDefs.FilenameChars;
DirHandle: TYPE = POINTER TO DirObject;
DirObject: TYPE;
DEfile: CARDINAL = AltoFileDefs.DEfile;
DEfree: CARDINAL = AltoFileDefs.DEfree;
LookupAction: TYPE = RECORD [
SELECT tag: * FROM old => NULL, new => [leadervDA: vDA ← fillInvDA], ENDCASE];
VersionOption: TYPE = {old, new, oldOrNew};
-- Procedures and Signals --
MapFileNameToFP: PROCEDURE [
name: STRING, version: VersionOption, leadervDA: vDA ← fillInvDA]
RETURNS [FP];
-- maps the 'name' to an associated FP using the system directory (SysDir). IF
-- 'version' is 'old' but no extant mapping can be found, NoSuchFile is raised. If
-- 'version' is 'new' and a mapping exists, FileAlreadyExists is raised. Otherwise,
-- if no mapping exists, a new unique ID is generated and the mapping established,
-- thereby creating a new file and entering it in the directory. In this case, the
-- optional parameter 'leadervDA', if supplied, indicates the desired starting
-- address on the disk.
NoSuchFile: ERROR;
FileAlreadyExists: ERROR;
IllegalFileName: ERROR;
OpenDirectory: PROCEDURE [fp: FP] RETURNS [dir: DirHandle];
-- opens the indicated file as a directory, returning a handle suitable for use by
-- the other directory manipulation procedures.
CloseDirectory: PROCEDURE [dir: DirHandle];
-- closes the indicated directory.
Lookup: PROCEDURE [
dir: DirHandle, name: STRING, fp: FPPtr, action: LookupAction ← [old[]]]
RETURNS [found, new: BOOLEAN];
-- looks up the given 'name' in 'dir'. If the name is found, fp↑ is filled in
-- with the associated file pointer from the directory, 'found' is TRUE, and 'new'
-- is FALSE. If the name is not found, the outcome is determined by 'action'. If
-- action is 'old[]', fp↑ (and the directory) are unchanged, and both 'found' and
-- 'new' are FALSE. If action is 'new[vda]', a new unique ID is generated,
-- an FP is constructed (and filled into fp↑), and an empty file with
-- that FP is created and entered in the directory. In this case, 'vda', if not
-- defaulted, indicates the desired starting address on disk, 'found' is FALSE,
-- and 'new' is TRUE.
LookupFP: PROCEDURE [dir: DirHandle, fp: FPPtr, name: STRING]
RETURNS [found: BOOLEAN];
-- looks up fp↑ in 'dir'. If the FP is found, 'name' is filled in with the associated
-- file name from the directory and 'found' is TRUE. If the FP is not found, 'name'
-- is unchanged and 'found' is FALSE.
Enter: PROCEDURE [dir: DirHandle, name: STRING, fp: FPPtr]
RETURNS [entered: BOOLEAN];
-- looks up the given 'name' in 'dir'. If the name is found, the directory remains
-- unchanged and 'entered' is FALSE. If the name is not found, it is entered in the
-- directory with fp↑ and 'entered' is TRUE.
Delete: PROCEDURE [dir: DirHandle, name: STRING, fp: FPPtr ← NIL]
RETURNS [found: BOOLEAN];
-- looks up the given 'name' in 'dir'. If the name is found, the entry is removed
-- from the directory and 'found' is TRUE. In this case, if 'fp' is non-NIL, fp↑ is
-- filled in with the file pointer that was stored in the entry. Otherwise, the
-- directory is unchanged and 'found' is FALSE. Note that only the entry is deleted,
-- not the associated file.
DeleteFP: PROCEDURE [dir: DirHandle, fp: FPPtr, name: STRING ← NIL]
RETURNS [found: BOOLEAN];
-- looks up fp↑ in 'dir'. If the FP is found, the entry is removed from the
-- directory and 'found' is TRUE. In this case, if 'name' is non-NIL, it is filled
-- in with the file name that was stored in the entry. Otherwise, the directory is
-- unchanged and 'found' is FALSE. Note that only the entry is deleted, not the
-- associated file.
Enumerate: PROCEDURE [
dir: DirHandle,
proc: PROCEDURE [entry: DVPtr, name: STRING] RETURNS [BOOLEAN]]
RETURNS [found: BOOLEAN];
-- scans directory 'dir' calling 'proc' for each item. 'entry' contains the fixed
-- information, 'name' is valid only when entry.type = DEfile.
END.