-- Copyright (C) 1981, 1984  by Xerox Corporation. All rights reserved. 
-- IFSFilePrivate.mesa, HGM, 15-Sep-85  9:12:01

-- Last edited by Levin:  27-Feb-81 15:06:07

DIRECTORY
  FileDefs USING [
    Buffer, Completer, CompleterArg, defaultTime, FileTime, PageNumber, Position],
  Leaf USING [FileAddress, Handle, LeafType, OpSpecificFileAddress],
  PupDefs USING [PupAddress],
  Sequin USING [Buffer, Handle],
  VMDefs USING [AccessFailure, OpenOptions];

IFSFilePrivate: DEFINITIONS =

  BEGIN OPEN FileDefs;


  -- Types and Related Constants --

  FSObject: TYPE = MONITORED RECORD [
    primaryName, primaryPassword: LONG STRING,
    secondaryName, secondaryPassword: LONG STRING,
    serverAddr: PupDefs.PupAddress,
    fileList: FileHandle ← NIL,
    changeInOpenState: CONDITION ← [timeout: 0]];

  FSInstance: TYPE = LONG POINTER TO FSObject;

  FileObject: TYPE = MONITORED RECORD [
    sequin: Sequin.Handle ← NULL,
    ioPending: IORequest ← NIL,
    ioSynch: CONDITION ← [timeout: 0],
    length: Position ← NULL,
    openCount: [0..128) ← 1,
    locked: BOOLEAN ← FALSE,
    seal: FileSeal ← underwaySeal,
    state: FileState ← alive,
    link: FileHandle,
    leafHandle: Leaf.Handle ← NULL,
    name: LONG STRING,
    fs: FSInstance,
    watcher: PROCESS RETURNS [BOOLEAN] ← NULL];

  FileHandle: TYPE = LONG POINTER TO FileObject;

  FileState: TYPE = {alive, flush, closing, closed};

  FileSeal: TYPE = [0..77B];

  openSeal: FileSeal = 41B;
  underwaySeal: FileSeal = 22B;
  closedSeal: FileSeal = 55B;

  IORequestBlock: TYPE = RECORD [
    link: IORequest ← NULL,
    buffer: Buffer,
    address: Leaf.FileAddress,
    op: Leaf.LeafType,
    bytesToGo: [0..512],
    proc: Completer ← NULL,
    arg: CompleterArg ← NULL];

  IORequest: TYPE = LONG POINTER TO IORequestBlock;

  IFSTimes: TYPE = MACHINE DEPENDENT RECORD [create, write, read: IFSTIME];

  IFSTIME: TYPE = MACHINE DEPENDENT RECORD [high, low: CARDINAL];

  fileTimeAddress: Leaf.FileAddress = [high: 3777B, low: 174000B];


  -- Procedures for the Operations level --

  Open: PROCEDURE [
    instance: FSInstance, name: LONG STRING, options: VMDefs.OpenOptions ← oldReadOnly]
    RETURNS [FileHandle];

  Close: PROCEDURE [FileHandle];

  Abandon: PROCEDURE [FileHandle];

  Destroy: PROCEDURE [file: FileHandle];

  GetLength: PROCEDURE [file: FileHandle] RETURNS [Position];

  SetLength: PROCEDURE [file: FileHandle, length: Position];

  Extend: PROCEDURE [file: FileHandle, length: Position, buffer: LONG POINTER];

  Truncate: PROCEDURE [file: FileHandle, length: Position];

  StartRead: PROCEDURE [
    file: FileHandle, page: PageNumber, buffer: Buffer, callback: Completer,
    arg: CompleterArg];

  StartWrite: PROCEDURE [
    file: FileHandle, page: PageNumber, buffer: Buffer, callback: Completer,
    arg: CompleterArg];

  GetTimes: PROCEDURE [file: FileHandle] RETURNS [read, write, create: FileTime];

  SetCreationTime: PROCEDURE [file: FileHandle, create: FileTime ← defaultTime];


  -- Other File Manipulation Procedures --

  InsertFile: PROCEDURE [
    fs: FSInstance, name: LONG STRING,
    openProc: PROCEDURE [FileHandle] RETURNS [VMDefs.AccessFailure]]
    RETURNS [FileHandle];
  -- The file 'name' is checked against files presently open under file system
  -- 'fs'.  If the file is not already open, 'openProc' is called.  If 'openProc'
  -- returns an AccessFailure other than 'ok', the open is considered to have
  -- failed, otherwise, the use count of the file handle is incremented.

  ReleaseFile: PROCEDURE [file: FileHandle, closeProc: PROCEDURE [FileHandle]];
  -- The use count on the indicated file is decremented and, if zero, 'closeProc'
  -- is called.  The FileHandle then becomes invalid.  If the use count is still
  -- greater than zero, closeProc is not called and the FileHandle remains usable.

  PurgeFile: PROCEDURE [file: FileHandle, destroyProc: PROCEDURE [FileHandle]];
  -- The use count on the indicated file must be zero, otherwise an error occurs.
  -- 'destroyProc' is called and it is expected to remove all traces of the file.

  ValidateFile: PROCEDURE [file: FileHandle];


  -- I/O --

  DoRead: PROCEDURE [file: FileHandle, request: IORequest];
  -- initiates a read operation as described by 'file' and 'request'.

  DoWrite: PROCEDURE [file: FileHandle, request: IORequest];
  -- initiates a write operation as described by 'file' and 'request'.

  FileWatcher: PROCEDURE [file: FileHandle] RETURNS [BOOLEAN];
  -- handles responses from the server to operations requested by StartRead,
  -- StartWrite, and Extend.  The return value indicates whether the file operations
  -- were shut down normally or abnormally.


  -- FreeList Management --

  InitializeFreeList: PROCEDURE;

  FinalizeFreeList: PROCEDURE;

  GetIORequestBlock: PROCEDURE RETURNS [IORequest];

  FreeIORequestBlock: PROCEDURE [request: IORequest];


  -- Miscellaneous Utilities --

  CopyString: PROCEDURE [s: LONG STRING] RETURNS [ns: LONG STRING];

  AddStringToBuffer: PROCEDURE [buffer: LONG POINTER TO Sequin.Buffer, s: LONG STRING];

  FileAddressToPosition: PROCEDURE [fa: Leaf.FileAddress]
    RETURNS [FileDefs.Position];

  PositionToFileAddress: PROCEDURE [
    pos: FileDefs.Position, opSpecific: Leaf.OpSpecificFileAddress ← [read[]]]
    RETURNS [Leaf.FileAddress];


  -- Statistics Logging --

  ifsFiles: CARDINAL;
  -- count of number of open files at any IFS server.

  END.