-- file CoreDefs.Mesa
-- Last edited by Horning, December 20, 1977 10:45 AM.
-- Last edited by Kierr, February 8, 1978 3:08 PM.
-- Last edited by Wegbreit, November 18, 1977 11:33 AM.
-- Last edited by Brotz, February 19, 1981 9:26 PM.
-- Last edited by Levin, September 17, 1980 6:21 PM.
-- Last edited by Schroeder, January 19, 1981 8:49 AM.

DIRECTORY
AltoFileDefs,
gsD: FROM "GlobalStorageDefs",
SegmentDefs,
TimeDefs,
ovD: FROM "OverviewDefs";

crD: DEFINITIONS = BEGIN

-- Distributed File Department of the Core Division. This is a mini file system for DMS. It
-- uses several, and as yet unspecified, file servers. The name of the file server is
-- encoded in the UFilename (DMS generalized filename).

-- Common attributes of file department interfaces:

-- (1) INDEX STRUCTURE. Files are indexed by page number and byte within each page.
-- The data pages in a file are numbered starting at 0, and the bytes in a page are
-- numbered [0 .. 511]. The header page on Alto files is totally invisible to Core interface
-- users.

-- (2) NAMING BYTES. UFilePosition: PseudoTYPE = RECORD[ i: CARDINAL, j: [0 .. 512)]
-- then i*512+j = byte number (byte numbers start with 0). For file length, the
-- UFilePosition of the first free byte is used.
-- Some cases:
--
an empty file -0,0
--
a file with 1 good byte -0,1
--
a file with 511 good byes -0,511
--
a file with 512 good bytes -1,0
--
a file with 513 good bytes -1,1


OpenFile: PROCEDURE [user: DMSUser, filename: UFilename, mode: OpenMode]
RETURNS [ovD.ErrorCode, UFileHandle];
-- Opens the specified file in the specified mode, and returns a handle to the opened file.
-- (Handles are useable until a CloseFile or DeleteFile. When OpenFile fails, i.e. ErrorCode
-- # ok, a special handle, NIL, is returned.)
-- Error Codes: diskError, diskFull, diskCorrupted, illegalFilename, fileInUse, fileTooBig.


-- Note: All of the following operations require a UFileHandle which has been returned by a
-- successful call to OpenFile and not yet "closed" or "deleted". And if given a
-- UFileHandle which has been "closed" or "deleted", their operation is unpredictable.
-- Exception: CloseFile and DeleteFile on NIL (i.e. the return of an unsuccessful call to
-- OpenFile) is a no-op.


CloseFile: PROCEDURE [UFileHandle] RETURNS [ovD.ErrorCode];
-- Closes the specified file. (Special Case: a nop if handle = NIL.) The handle is closed and
-- should not be re-used by the caller.
-- Error Codes: diskError.


DeleteFile: PROCEDURE [UFileHandle] RETURNS [ovD.ErrorCode];
-- Deletes the file associated with the file handle. (Special case: a nop if handle = NIL.) The handle is closed and should not be re-used by the caller.
-- Error Codes: diskError.


GetUFileTimes: PROCEDURE [UFileHandle]
RETURNS [read, write, create: TimeDefs.PackedTime, ec: ovD.ErrorCode];
-- Reads the read, write, and create times associated with the file handle.
-- Error Codes: diskError.


SetUFileTimes: PROCEDURE [uFH: UFileHandle,
read, write, create: TimeDefs.PackedTime ← TimeDefs.DefaultTime]
RETURNS [ovD.ErrorCode];
-- Sets the read, write, and create times associated with the file handle.
-- If a time is set to TimeDefs.DefaultTime then the current time is used.
-- Error Codes: diskError.


UFileLength: PROCEDURE [UFileHandle]
RETURNS [erc: ovD.ErrorCode, lastPage: PageNumber, byteFF: PageByte];
-- Returns the first free byte in the file, i.e. its length, via the formula (lastPage*512 +
-- byteFF). Any data that has been written since the file was opened is included. (Note,
-- empty files return [0,0].)
-- Error Codes: (None for Alto.)


UFileTruncate: PROCEDURE [lastPage: PageNumber, byteFF: PageByte, uFH: UFileHandle]
RETURNS [ovD.ErrorCode];
-- Shorten a file which has been opened by OpenFile. The position has the same semantics
-- as UFileLength.
-- Do NOT use to LENGTHEN a file!
-- Error Codes: fileIsReadOnly, diskError.


ReadPages: PROCEDURE [buffer: gsD.MemoryPagePtr, byteCount: CARDINAL,
pageNumber: PageNumber, uFH: UFileHandle]
RETURNS [erc: ovD.ErrorCode, bytesRead: CARDINAL];
-- Reads up to "byteCount" bytes of data from the file asscoiated with uFH beginning with
-- page "pageNumber" into the memory page(s) beginning at "buffer". The byteCount
-- must be a multiple of 512 (an even page). The bytesRead returned is the count of bytes
-- actually read and will be equal to the requested byteCount except at EOF, when it may
-- be less. (Note that if pageNumber is beyound the end-of-file then bytesRead=0 is
-- returned.)
-- Error Codes: diskError.


WritePages: PROCEDURE [buffer: gsD.MemoryPagePtr, byteCount: CARDINAL,
pageNumber: PageNumber, uFH: UFileHandle] RETURNS [erc: ovD.ErrorCode];
-- Writes byteCount of data from memory, beginning at buffer, to pageNumber of the file
-- uFH. The operation is legal only if the file was opened in update OpenMode. This can
-- be used to extend the file’s size by writing beyond the current end. (Note, however,
-- that the file is never shortened.) The byteCount must always be a multiple of 512, an
-- even page, except on the last page of the file.
-- Regarding byteCount, let "remainder" be (byteCount MOD 512). If non-zero, remainder
-- denotes the number of bytes supplied by the client to be written on the last page of the
-- current transaction. The number of byte actually written will be the MAX[current-
-- bytes-on-that-file-page, remainder]; the value of all bytes beyond remainder are
-- indeterminate.
-- Side effects: Updates the file size in the uFH as needed.
-- Error Codes: fileIsReadOnly, diskFull, diskError.



-- Interfaces to file-servers. There is an Open here for each file-server; the rest of the server-specific procedures are in server-implementing modules.


AltoOpenFile, LeafOpenFile: PROCEDURE [user: DMSUser, filename: UFilename,
mode: OpenMode] RETURNS [ovD.ErrorCode, UFileHandle];


-- I don’t know where to put this, so until it becomes obvious it goes here. This procedure
-- is valid for the Alto only. It is exported by AltoCore (which is current an internal
-- module to Core). I don’t know what we will provide for other file servers.


InsertInFileCache: PROCEDURE [name: STRING, fH: SegmentDefs.FileHandle];
-- Return immediately iff fH=NIL. Else copy the name and fH into the cache.

FreeCacheEntry: PROCEDURE [fH: SegmentDefs.FileHandle];
-- Flushes the entry for the given fH from the cache (it better be there).

LookupInFileCache: PROCEDURE [name: STRING] RETURNS [fH: SegmentDefs.FileHandle];
-- Returns the Mesa file handle associated with the name (or NIL if no such file).


SetAltoFreePageMonitor: PROCEDURE [proc: PROCEDURE [count: CARDINAL]];
-- The arg, proc, is called immediately and whenever the tally of Alto free pages changes.
-- (Note that this tally is only a hint.) To inhibit the function, call
-- InhibitAltoFreePageMonitor.


InhibitAltoFreePageMonitor: PROCEDURE;
-- Any free page monitoring set up by SetAltoFreePageMonitor is discontinued.


CountAltoFreePages: PROCEDURE RETURNS [freePages: CARDINAL];
-- Returns the number of pages available on the Alto disk pack. This number is a real
-- count, not just a hint.


-- Data Structures and Types.

DMSUser: TYPE = RECORD [name: STRING, registry: STRING, password: STRING];

UFilename: TYPE = STRING;
-- format is: [Site]<Directory>SimpleName.Extension

UFileHandle: TYPE = POINTER TO UFileObject;
AltoFileHandle: TYPE = POINTER TO alto UFileObject;
LeafFileHandle: TYPE = POINTER TO leaf UFileObject;

UFileObject: TYPE = RECORD
[access: OpenMode,
lastFilePage: PageNumber, -- Last page of the file; may contain 0 bytes.
byteFF: PageByte, -- First free on lastFilePage.
-- File server specific procedures.
close: PROC [UFileHandle] RETURNS [ovD.ErrorCode],
delete: PROC [UFileHandle] RETURNS [ovD.ErrorCode],
length: PROC [UFileHandle] RETURNS [ovD.ErrorCode, PageNumber, PageByte],
getTimes: PROC[UFileHandle]
RETURNS [read, write, create: TimeDefs.PackedTime, ec: ovD.ErrorCode],
setTimes: PROCEDURE [uFH: UFileHandle, read, write, create: TimeDefs.PackedTime]
RETURNS [ovD.ErrorCode],
truncate: PROC [PageNumber, PageByte, UFileHandle] RETURNS [ovD.ErrorCode],
read: PROC [gsD.MemoryPagePtr, CARDINAL, PageNumber, UFileHandle]
RETURNS [ovD.ErrorCode, CARDINAL],
write: PROC [gsD.MemoryPagePtr, CARDINAL, PageNumber, UFileHandle]
RETURNS [ovD.ErrorCode],
varpart: SELECT UFileObjectType: * FROM
alto => [handle: SegmentDefs.FileHandle,
vDATable: VDATablePtr],
leaf => [sequinList: POINTER, -- so as not to depend on Sequin and Leaf.
leafHandle: POINTER], -- so as not to depend on Leaf.
ENDCASE];

OpenMode: TYPE =
{read,-- SegmentDefs.Read only; the file must exist
update};-- SegmentDefs.(Read+Write+Append); if the file exists then the old version is
-- referenced; otherwise, a new file is created.

PageNumber: TYPE = CARDINAL[0 .. 77777B];
PageByte: TYPE = CARDINAL[0 .. 512);


-- These are used by AltoCore, and are needed for AltoFileHandle.

VDATablePtr: TYPE = POINTER TO VDATable;
VDATable: TYPE = ARRAY [0 .. numberOfChunks) OF VDAsPtr;
VDAsPtr: TYPE = POINTER TO ARRAY [0 .. 0) OF AltoFileDefs.vDA;

numberOfChunks: CARDINAL = 32;


-- Alto filename cache.

fileCacheHeader: CacheNodePtr;

CacheNode: TYPE = RECORD
[next: CacheNodePtr,
fp: AltoFileDefs.FP,
key: STRING];

CacheNodePtr: TYPE = POINTER TO CacheNode;

END. -- of CoreDefs --