DIRECTORY
CrRPC USING [Handle],
IO USING [STREAM],
PFS USING [RopeFromPath, FileType, InfoProc, Mutability, nullUniqueID, tUnspecified, UniqueID],
PFSBackdoor USING [ProduceError],
PFSClass USING [AttachProc, CloseProc, CopyProc, DeleteProc, EnumerateClientPropertiesProc, EnumerateForInfoProc, EnumerateForNamesProc, FileInfoProc, FileManipulationProcs, FileManipulationProcsObject, FSHandle, FSObject, GetClientPropertyProc, GetHandleProc, GetInfoProc, LookupNameProc, MaintenanceProcs, MaintenanceProcsObject, OpenFile, OpenFileObject, OpenProc, ReadProc, Register, RenameProc, RetrieveProc, SetAttributesProc, SetByteCountAndUniqueIDProc, SetClientPropertyProc, StoreProc, SweepProc, ValidateProc, WriteProc],
PFSNames USING [Component, PATH, ShortName, Version],
Rope USING [ROPE],
XNSFilingFileMgr USING [CloseFileOp, OpenFile, OpenFileOp, ReadFileOp, WriteFileOp],
XNSFilingOps USING [CallProtected, EnumProc, EnumerateOp],
XNSFilingPrivate USING [DebugOut],
XNSFilingSession USING [ServerHandle, XNSGetServer, XNSSweep, XNSValidate];
XNSFilingViewImpl:
CEDAR
MONITOR
LOCKS tr
USING tr: Transport
IMPORTS PFS, PFSBackdoor, PFSClass, PFSNames, XNSFilingFileMgr, XNSFilingOps, XNSFilingPrivate, XNSFilingSession ~ {
OPEN XNSFilingFileMgr, XNSFilingOps, XNSFilingSession;
ROPE: TYPE ~ Rope.ROPE;
PFS Class name
xnsFlavor: ATOM ~ $XNS;
Maintenance Object
mo: PFSClass.MaintenanceProcs ~
NEW [PFSClass.MaintenanceProcsObject ← [
sweep: Sweep,
validate: Validate
]];
File Manipulation Object
fmo: PFSClass.FileManipulationProcs ~
NEW[PFSClass.FileManipulationProcsObject ← [
delete: Delete,
enumerateForInfo: EnumerateForInfo,
enumerateForNames: EnumerateForNames,
fileInfo: FileInfo,
lookupName: Lookup,
rename: Rename,
copy: Copy,
setAttributes: SetAttributes,
setByteCountAndUniqueID: SetByteCountAndUniqueID,
setClientProperty: SetClientProperty,
getClientProperty: GetClientProperty,
enumerateClientProperties: EnumerateClientProperties,
read: Read,
write: Write,
open: Open,
close: Close,
store: Store,
retrieve: Retrieve,
attach: Attach,
getInfo: GetInfo
]];
Initialized Data - order is important!
vfsClass: PFSClass.FSHandle ~
NEW [PFSClass.FSObject ← [
flavor: xnsFlavor,
name: NIL, -- filled in upon instantiation
maintenanceProcs: mo,
procs: fmo,
data: NIL -- filled in upon instantiation
]];
Transport Management
TransportProc: TYPE ~ PROC; -- [tr: Transport];
Transport: TYPE ~ REF TransportBody;
TransportBody:
TYPE ~
MONITORED
RECORD [
crH: CrRPC.Handle,
vfs: VFS
];
CallMonitored:
PROC [vfs:
VFS, inner: TransportProc] ~ {
crH: CrRPC.Handle ~ NIL;
link: Transport ~ NEW[TransportBody ← [crH, vfs]];
UnderLock: --ENTRY-- TransportProc ~ {
ENABLE UNWIND => { NULL };
inner[];
};
UnderLock[link];
CallProtected[vfs.sH.mnt, inner];
};
XNS Virtual File System(s)
VFS: TYPE ~ REF VFSInstance;
VFSInstance:
TYPE ~
RECORD [
fs: ROPE,
flavorSpecified: BOOL,
sH: ServerHandle
];
GetHandle: PFSClass.GetHandleProc ~ {
vfs: VFS ~ NEW[VFSInstance ← [fs: fs, flavorSpecified: flavorSpecified, sH: NIL] ];
{
Attempt to Attach new vfs[h]
sH: ServerHandle; downMsg ← NIL;
[sH, downMsg] ← XNSGetServer[fs];
vfs.sH ← sH;
};
h ← NEW[PFSClass.FSObject ← vfsClass^];
h.name ← fs;
h.data ← vfs;
};
Maintenance Operations
Sweep: PFSClass.SweepProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
sH: ServerHandle ~ vfs.sH;
XNSSweep[sH, seconds];
NULL;
};
Validate: PFSClass.ValidateProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
sH: ServerHandle ~ vfs.sH;
obsolete ← FALSE; downMsg ← NIL;
[obsolete, downMsg] ← XNSValidate[sH];
IF ( FALSE ) THEN { obsolete ← TRUE; downMsg ← NIL };
IF ( FALSE ) THEN { obsolete ← FALSE; downMsg ← "downMsg" };
};
File Manipulation Procs
EnumerateForInfo: PFSClass.EnumerateForInfoProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
pat: ROPE ~ PFS.RopeFromPath[pattern];
EnumerateForInfoInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
Lister: EnumProc ~ {
eFile: PFSNames.PATH, eInfo: Info, pathy: PFSNames.PATH
fullFName: PFSNames.PATH ← pathy;
attachedTo: PFSNames.PATH ← NIL;
uniqueID: PFS.UniqueID ← [[time: eInfo.created]];
bytes: INT ← eInfo.bytes;
mutability: PFS.Mutability ← $immutable; -- policy decision!
fileType: PFS.FileType ← [eInfo.fileType]; -- identical type defs?
continue ← IF ( proc = NIL ) THEN TRUE ELSE
proc[fullFName, attachedTo, uniqueID, bytes, mutability, fileType];
};
createdOn: CARD32 ~ BasicTime.ToNSTime[wantedUniqueID.egmt.time];
EnumerateOp[vfs.sH.mnt, pattern, Lister, $enumerate];
};
XNSFilingPrivate.DebugOut["XNSFilingViewImpl.EnumerateForInfo"];
XNSFilingPrivate.DebugOut[PFS.RopeFromPath[pattern]];
CallMonitored[vfs, EnumerateForInfoInner];
};
EnumerateForNames: PFSClass.EnumerateForNamesProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
Info:
PFS.InfoProc ~ {
name: PFSNames.PATH ~ fullFName;
continue ← IF ( proc = NIL ) THEN TRUE ELSE proc[name];
};
XNSFilingPrivate.DebugOut["XNSFilingViewImpl.EnumerateForNames"];
XNSFilingPrivate.DebugOut[PFS.RopeFromPath[pattern]];
EnumerateForInfo[h, pattern, Info, lbound, hbound];
EnumerateForNamesInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
UnImplemented["XNSFilingViewImpl.EnumerateForNamesInner"];
};
CallMonitored[vfs, EnumerateForNamesInner];
};
FileInfo: PFSClass.FileInfoProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
pattern: PFSNames.PATH ~ file;
zversion: PFSNames.Version ← [none];
zattachedTo: PFSNames.PATH ← NIL;
zuniqueID: PFS.UniqueID ← PFS.nullUniqueID;
zbytes: INT ← 0;
zmutability: PFS.Mutability ← $immutable;
zfileType: PFS.FileType ← PFS.tUnspecified;
Info:
PFS.InfoProc ~ {
shortName: PFSNames.Component ~ PFSNames.ShortName[fullFName];
SELECT
TRUE
FROM
( wantedUniqueID =
PFS.nullUniqueID ) => {
perhaps we should be checking for the *best* match?
continue ← TRUE;
};
( uniqueID = wantedUniqueID ) => { continue ← FALSE };
ENDCASE => { RETURN };
zversion ← shortName.version;
zattachedTo ← attachedTo;
zbytes ← bytes;
zuniqueID ← uniqueID;
zmutability ← mutability;
zfileType ← fileType;
};
XNSFilingPrivate.DebugOut["XNSFilingViewImpl.FileInfo"];
XNSFilingPrivate.DebugOut[PFS.RopeFromPath[pattern]];
EnumerateForInfo[h, pattern, Info, NIL, NIL];
RETURN[zversion, zattachedTo, zbytes, zuniqueID, zmutability, zfileType];
FileInfoInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
UnImplemented["XNSFilingViewImpl.FileInfoInner"];
};
CallMonitored[vfs, FileInfoInner];
};
GetInfo: PFSClass.GetInfoProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
XNSFilingPrivate.DebugOut["XNSFilingViewImpl.GetInfo"];
Generic Implementation
fullFName ← file.fullFName;
attachedTo ← file.attachedTo;
uniqueID ← file.uniqueID;
bytes ← file.bytes;
mutability ← file.mutability;
fileType ← file.fileType;
GetInfoInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
UnImplemented["XNSFilingViewImpl.GetInfoInner"];
};
CallMonitored[vfs, GetInfoInner];
};
File Operations
Read: PFSClass.ReadProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
ReadInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
xnsFile: XNSFilingFileMgr.OpenFile ~ NARROW[file.data];
XNSFilingPrivate.DebugOut["XNSFilingViewImpl.ReadInner"];
XNSFilingPrivate.DebugOut[PFS.RopeFromPath[file.fullFName]];
bytesRead ← ReadFileOp[vfs.sH.mnt, xnsFile, filePosition, nBytes, to];
};
bytesRead ← 0;
CallMonitored[vfs, ReadInner];
};
Write: PFSClass.WriteProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
WriteInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
xnsFile: XNSFilingFileMgr.OpenFile ~ NARROW[file.data];
XNSFilingPrivate.DebugOut["XNSFilingViewImpl.WriteInner"];
XNSFilingPrivate.DebugOut[PFS.RopeFromPath[file.fullFName]];
bytesWritten ← WriteFileOp[vfs.sH.mnt, xnsFile, filePosition, nBytes, from];
};
bytesWritten ← 0;
CallMonitored[vfs, WriteInner];
};
Close: PFSClass.CloseProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
CloseInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
xnsFile: XNSFilingFileMgr.OpenFile ~ NARROW[file.data];
XNSFilingPrivate.DebugOut["XNSFilingViewImpl.CloseInner"];
XNSFilingPrivate.DebugOut[PFS.RopeFromPath[file.fullFName]];
CloseFileOp[vfs.sH.mnt, xnsFile];
};
CallMonitored[vfs, CloseInner];
};
Open: PFSClass.OpenProc ~ {
file: PATH, wantedUniqueID: UniqueID, access: PFS.AccessOptions, checkFileType: BOOL, fileType: PFS.FileType, createOptions: PFS.CreateOptions
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
LegitimateMatch:
PROC
RETURNS [match:
BOOL] ~ {
match ← TRUE;
};
version: PFSNames.Version;
attachedTo: PFSNames.PATH;
bytes: INT;
uniqueID: PFS.UniqueID;
mutability: PFS.Mutability;
zfileType: PFS.FileType;
of: PFSClass.OpenFile ← NIL;
OpenInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
fullFName: PFSNames.PATH ~ file;
fs: PFSClass.FSHandle ~ h;
xnsFile: XNSFilingFileMgr.OpenFile ~ OpenFileOp[vfs.sH.mnt, fullFName];
data: REF ~ xnsFile;
new: PFSClass.OpenFile ~ NEW[PFSClass.OpenFileObject ← [fs, fullFName, attachedTo, uniqueID, bytes, mutability, zfileType, $open, data]];
XNSFilingPrivate.DebugOut["XNSFilingViewImpl.OpenInner"];
XNSFilingPrivate.DebugOut[PFS.RopeFromPath[fullFName]];
of ← new;
};
[version, attachedTo, bytes, uniqueID, mutability, zfileType] ←
FileInfo[h, file, wantedUniqueID];
IF (
NOT LegitimateMatch[] )
THEN {
PFSBackdoor.ProduceError[unknownFile, "XNSFilingViewImpl.OpenInner"];
RETURN[NIL]; -- not reached!
};
XNSFilingPrivate.DebugOut["XNSFilingViewImpl.Open"];
XNSFilingPrivate.DebugOut[PFS.RopeFromPath[file]];
CallMonitored[vfs, OpenInner];
RETURN[of];
};
Utilities
UnImplemented:
PROC [msg:
ROPE] ~ {
XNSFilingPrivate.DebugOut[msg];
PFSBackdoor.ProduceError[notImplemented, msg];
};
UnImplemented so far...
Delete: PFSClass.DeleteProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
DeleteInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
fullName: PFSNames.PATH ← NIL;
uniqueID: PFS.UniqueID ← PFS.nullUniqueID;
continue: BOOL ← IF ( proc = NIL ) THEN TRUE ELSE proc[fullName, uniqueID];
UnImplemented["XNSFilingViewImpl.DeleteInner"];
};
CallMonitored[vfs, DeleteInner];
};
Lookup: PFSClass.LookupNameProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
path: PFSNames.PATH;
LookupInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
path ← NIL;
UnImplemented["XNSFilingViewImpl.LookupInner"];
};
CallMonitored[vfs, LookupInner];
RETURN[path];
};
Rename: PFSClass.RenameProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
RenameInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
done ← TRUE;
UnImplemented["XNSFilingViewImpl.RenameInner"];
};
CallMonitored[vfs, RenameInner];
};
Copy: PFSClass.CopyProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
CopyInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
done ← TRUE;
UnImplemented["XNSFilingViewImpl.CopyInner"];
};
CallMonitored[vfs, CopyInner];
};
SetAttributes: PFSClass.SetAttributesProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
SetAttributesInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
NULL;
UnImplemented["XNSFilingViewImpl.SetAttributesInner"];
};
CallMonitored[vfs, SetAttributesInner];
};
SetByteCountAndUniqueID: PFSClass.SetByteCountAndUniqueIDProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
SetByteCountAndUniqueIDInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
NULL;
UnImplemented["XNSFilingViewImpl.SetByteCountAndUniqueIDInner"];
};
CallMonitored[vfs, SetByteCountAndUniqueIDInner];
};
SetClientProperty: PFSClass.SetClientPropertyProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
SetClientPropertyInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
NULL;
UnImplemented["XNSFilingViewImpl.SetClientPropertyInner"];
};
CallMonitored[vfs, SetClientPropertyInner];
};
GetClientProperty: PFSClass.GetClientPropertyProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
GetClientPropertyInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
propertyValue ← NIL;
UnImplemented["XNSFilingViewImpl.GetClientPropertyInner"];
};
CallMonitored[vfs, GetClientPropertyInner];
};
EnumerateClientProperties: PFSClass.EnumerateClientPropertiesProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
EnumerateClientPropertiesInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
propertyName: ROPE; propertyValue: ROPE;
continue: BOOL ← IF ( proc = NIL ) THEN TRUE ELSE proc[propertyName, propertyValue];
UnImplemented["XNSFilingViewImpl.EnumerateClientPropertiesInner"];
};
CallMonitored[vfs, EnumerateClientPropertiesInner];
};
Store: PFSClass.StoreProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
StoreInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
fullName: PFSNames.PATH ← NIL;
continue: BOOL ← IF ( proc = NIL ) THEN TRUE ELSE proc[fullName];
UnImplemented["XNSFilingViewImpl.StoreInner"];
};
CallMonitored[vfs, StoreInner];
};
Retrieve: PFSClass.RetrieveProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
RetrieveInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
fullFName: PFSNames.PATH ← NIL;
bytes: INT ← 0;
uniqueID: PFS.UniqueID ← PFS.nullUniqueID;
s: IO.STREAM ← IF ( proc = NIL ) THEN NIL ELSE proc[fullFName, bytes, uniqueID];
IF ( s = NIL ) THEN ERROR;
UnImplemented["XNSFilingViewImpl.RetrieveInner"];
};
CallMonitored[vfs, RetrieveInner];
};
Attach: PFSClass.AttachProc ~ {
class: PFSClass.FSHandle ~ h;
vfs: VFS ~ NARROW[class.data];
AttachInner: TransportProc ~ {
ENABLE UNWIND => { NULL };
toFName ← NIL;
UnImplemented["XNSFilingViewImpl.AttachInner"];
};
CallMonitored[vfs, AttachInner];
};
Init:
PROC ~ {
PFSClass.Register[xnsFlavor, GetHandle];
PFSClass.ClearCachedServer["*-XNS"];
};
Init[];
}.