GeneralFSImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Doug Terry, November 26, 1985 5:46:38 pm PST
Interface for opening and creating FS files regardless of whether thay are actually managed by FS, AlpineFS, or StableFS. The following heuristics are used to guess the class of the file from the file's server name:
1) a file whose server name contains ".alpine" is presumed to be an Alpine file.
2) the special server name "StableStorage" identifies a file residing in stable storage; the file name syntax is [StableStorage]<bank>copy.broadside where bank in [0..15], copy in [0..3], and broadside in [0..1].
3) any other file is presumed to be an ordinary FS file.
The operations provided herein are syntactically identical to those defined in FS. Clients that need to pass parameters particular to AlpineFS.Open, for instance, should access that interface directly.
*** Currently, all of the code for accessing StableFS is commented out. ***
DIRECTORY
AlpineFS USING [Open, Create, OpenOrCreate, StreamOpen],
BasicTime USING [GMT, nullGMT],
Convert USING [CardFromRope],
FS USING [--Close,-- ComponentPositions, Create, --Error,-- ExpandName, Lock, Open, OpenFile, OpenOrCreate, StreamOpen, --StreamFromOpenFile,-- AccessOptions, StreamOptions, defaultStreamOptions, ByteCount, StreamBufferParms, defaultStreamBufferParms, ExtendFileProc, nullOpenFile],
IO USING [STREAM],
Rope USING [Equal, Find, ROPE, Substr],
StableFS USING [Open, Create, BankID],
GeneralFS;
GeneralFSImpl: CEDAR PROGRAM
IMPORTS AlpineFS, --Convert,-- FS, Rope--, StableFS--
EXPORTS GeneralFS
~ BEGIN
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
FileClass: TYPE = {local, alpine, stable};
GuessClass: PROC [name: ROPE, wDir: ROPE] RETURNS [class: FileClass, fname: ROPE] ~ {
cp: FS.ComponentPositions;
server: ROPE;
[fname, cp] ← FS.ExpandName[name, wDir];
server ← Rope.Substr[fname, cp.server.start, cp.server.length];
class ← SELECT TRUE FROM
Rope.Find[server, ".Alpine", 0, FALSE] # -1 => alpine,
Rope.Equal[server, "StableStorage", FALSE] => stable,
ENDCASE => local;
};
NameToStableID: PROC [name: ROPE] RETURNS [StableFS.BankID] ~ {
Assumes that name is of the form [StableStorage]<bank>copy.broadside.
stableID: StableFS.BankID;
cp: FS.ComponentPositions ← FS.ExpandName[name].cp;
IF cp.dir.length # 0 THEN
stableID.bank ← Convert.CardFromRope[Rope.Substr[name, cp.dir.start, cp.dir.length]];
IF cp.base.length # 0 THEN
stableID.copy ← Convert.CardFromRope[Rope.Substr[name, cp.base.start, cp.base.length]];
IF cp.ext.length # 0 THEN
stableID.broadside ← Convert.CardFromRope[Rope.Substr[name, cp.ext.start, cp.ext.length]];
RETURN[stableID];
};
Open: PUBLIC PROC [name: ROPE,
lock: FS.Lock ← $read,
wantedCreatedTime: BasicTime.GMT ← BasicTime.nullGMT,
remoteCheck: BOOLTRUE,
wDir: ROPENIL
] RETURNS [FS.OpenFile] ~ {
fname: ROPE;
class: FileClass;
[class, fname] ← GuessClass[name, wDir];
RETURN[ SELECT class FROM
local => FS.Open[fname, lock, wantedCreatedTime, remoteCheck, wDir],
alpine => AlpineFS.Open[name: fname, wantedCreatedTime: wantedCreatedTime, access: lock, wDir: wDir],
stable => StableFS.Open[NameToStableID[fname]],
ENDCASE => FS.nullOpenFile];
};
Create: PUBLIC PROC [name: ROPE,
setPages: BOOLTRUE, pages: INT ← 0,
setKeep: BOOLFALSE, keep: CARDINAL ← 1,
wDir: ROPENIL
] RETURNS [FS.OpenFile] ~ {
fname: ROPE;
class: FileClass;
[class, fname] ← GuessClass[name, wDir];
RETURN[ SELECT class FROM
local => FS.Create[fname, setPages, pages, setKeep, keep, wDir],
alpine => AlpineFS.Create[name: fname, pages: pages, keep: keep, wDir: wDir],
stable => StableFS.Create[NameToStableID[fname]],
ENDCASE => FS.nullOpenFile];
};
OpenOrCreate: PUBLIC PROC [name: ROPE,
keep: CARDINAL ← 1, pages: INT ← 5, wDir: ROPENIL
] RETURNS [FS.OpenFile] ~ {
fname: ROPE;
class: FileClass;
[class, fname] ← GuessClass[name, wDir];
RETURN[ SELECT class FROM
local => FS.OpenOrCreate[fname, keep, pages, wDir],
alpine => AlpineFS.OpenOrCreate[name: fname, pages: pages, keep: keep, wDir: wDir],
stable => StableFS.Open[NameToStableID[fname]],
ENDCASE => FS.nullOpenFile];
};
StreamOpen: PUBLIC PROC [fileName: ROPE,
accessOptions: FS.AccessOptions ← $read,
streamOptions: FS.StreamOptions ← FS.defaultStreamOptions,
keep: CARDINAL ← 1,
createByteCount: FS.ByteCount ← 2560,
streamBufferParms: FS.StreamBufferParms ← FS.defaultStreamBufferParms,
extendFileProc: FS.ExtendFileProc ← NIL,
wantedCreatedTime: BasicTime.GMT ← BasicTime.nullGMT,
remoteCheck: BOOLTRUE,
wDir: ROPENIL
] RETURNS [STREAM] ~ {
StableStreamOpen: PROC [sid: StableFS.BankID] RETURNS [STREAM] ~ {
open: FS.OpenFile;
open ← SELECT accessOptions FROM
$read => StableFS.Open[sid],
$create => StableFS.Create[sid],
$append => StableFS.Open[sid],
$write => StableFS.Open[sid],
ENDCASE => ERROR;
RETURN[FS.StreamFromOpenFile[openFile: open, accessRights: IF accessOptions = $read THEN $read ELSE $write, initialPosition: IF accessOptions = $append THEN $end ELSE $start, streamOptions: streamOptions, streamBufferParms: streamBufferParms, extendFileProc: extendFileProc
! FS.Error => FS.Close[open]]];
};
fname: ROPE;
class: FileClass;
[class, fname] ← GuessClass[fileName, wDir];
RETURN[ SELECT class FROM
local => FS.StreamOpen[fname, accessOptions, streamOptions, keep, createByteCount, streamBufferParms, extendFileProc, wantedCreatedTime, remoteCheck, wDir],
alpine => AlpineFS.StreamOpen[fname, accessOptions, [], keep, createByteCount, streamBufferParms, extendFileProc, wDir],
stable => StableStreamOpen[NameToStableID[fname]],
ENDCASE => NIL];
};
END.
Doug Terry November 18, 1985
created