<> <> <> <> <> <> <> DIRECTORY AlpFile USING [allProperties, Handle, LockOption, PropertySet, PropertyValuePair, ReferencePattern, RecoveryOption], AlpTransaction USING [Handle], BasicTime USING [GMT, nullGMT], FS USING [AccessOptions, ByteCount, defaultStreamBufferParms, ErrorDesc, ErrorGroup, ExtendFileProc, InfoProc, InitialPosition, Lock, NameProc, OpenFile, StreamBufferParms], IO USING [STREAM], Rope USING [ROPE]; AlpineFS: CEDAR DEFINITIONS = BEGIN ROPE: TYPE = Rope.ROPE; <> <> <> <> <> ErrorDesc: TYPE = FS.ErrorDesc; -- RECORD [group: ErrorGroup, code: ATOM, explanation: ROPE] _ [ok, NIL, NIL]; ErrorGroup: TYPE = FS.ErrorGroup; -- {ok, bug, environment, lock, client, user}; ErrorCode: PRIVATE TYPE = { <> <> <> badByteCount, -- tried to set byte count beyond end of file or negative. invalidOpenFile, -- FS.OpenFile is closed. notImplemented, -- called a procedure that is not provided for this FS.OpenFile. unknownPage, -- tried to read or write a page that is beyond end of the file or to set the page count to an illegal value. unwritableProperty, -- attempted to write the type or version property. wrongLock, -- operation required file to be open with access=$write and only $read was specified. (Note: this has nothing to do with the Alpine LockOption, which is upgraded automatically.) <> accessDenied, -- caller has insufficient permission to perform requested operation. badCredentials, -- caller not logged in properly. circularLink, -- creating this link would complete a circularity. danglingLink, -- referent of link does not exist. lockConflict, -- LockOption.ifConflict=$fail and a lock cannot immediately be set because a conflicting lock is already set by another transaction. lockTimeout, -- lock cannot be set even after waiting a long time, perhaps due to undetected deadlock. other, -- unspecified problem detected by server. quotaExceeded, -- attempt to create or extend file would exceed owner's quota. regServersUnavailable, -- access check failed due to Grapevine unavailability. remoteCallFailed, -- communication with server has broken down. serverBusy, -- server is too busy to start another transaction. serverInaccessible, -- failed to establish communication with server. transAborted, -- transaction created by this call went away. It is not useful to attempt any further operations under the same transaction. volumeFull, -- server volume full. <> <> <> cantUpdateTiogaFile, -- tried to open a file stream to write on a Tioga-format file. fileAlreadyExists, -- attempted to create a file that already exists. illegalName, -- file name, directory name, or pattern has illegal syntax or characters, or is too long. noKeeps, -- tried to set the keep on a server that does not implement keeps. ownerNotFound, -- owner not registered on the Alpine server. patternNotAllowed, -- name contained a "*" and procedure doesn't allow patterns. unknownCreatedTime, -- no version of the given FName has the specified created time. unknownFile, -- no such file name exists in the designated directory. unknownServer -- the server named in the server part is unknown. }; ProduceError: PRIVATE PROCEDURE [code: ErrorCode, explanation: ROPE]; <> <> <> <> <> <> <> <> <> Lock: TYPE = FS.Lock; -- this is distinct from the AlpFile.LockOption OpenFile: TYPE = FS.OpenFile; FileOptions: TYPE = RECORD [ updateCreateTime: BOOL _ TRUE, -- set create date to now if access=write. referencePattern: AlpFile.ReferencePattern _ $random, -- expected style of access {random, sequential}. Setting this correctly can have substantial performance benefits. recoveryOption: AlpFile.RecoveryOption _ $log, -- see Alpine documentation. finishTransOnClose: BOOLEAN _ TRUE -- when file is closed, also commit the transaction. ]; Open: PROCEDURE [name: ROPE, wantedCreatedTime: BasicTime.GMT _ BasicTime.nullGMT, access: Lock _ $read, lock: AlpFile.LockOption _ [$none, $wait], options: FileOptions _ [], wDir: ROPE _ NIL, transHandle: AlpTransaction.Handle _ NIL] RETURNS [OpenFile]; <> <> < $readOnly, $write => $readWrite).>> < [$read, wait], $write => [$write, wait]). The value of lock.ifConflict also determines the disposition of lock conflicts that occur during any subsequent operation on the OpenFile. See the Alpine documentation for details on locking.>> <> <> Create: PROCEDURE [name: ROPE, pages: INT _ 10, keep: CARDINAL _ 0, options: FileOptions _ [], wDir: ROPE _ NIL, transHandle: AlpTransaction.Handle _ NIL] RETURNS [OpenFile]; <> <> <> <> <> <> OpenOrCreate: PROCEDURE [name: ROPE, pages: INT _ 10, keep: CARDINAL _ 0, options: FileOptions _ [], wDir: ROPE _ NIL, transHandle: AlpTransaction.Handle _ NIL] RETURNS [OpenFile]; <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> GetFileOptions: PROCEDURE [file: OpenFile] RETURNS [options: FileOptions]; <> <> SetFileOptions: PROCEDURE [file: OpenFile, options: FileOptions]; <> <> <> GetLockOption: PROCEDURE [file: OpenFile] RETURNS [lock: AlpFile.LockOption]; <> <> <> SetLockOption: PROCEDURE [file: OpenFile, lock: AlpFile.LockOption]; <> <> <> ReadProperties: PROCEDURE [file: OpenFile, desiredProperties: AlpFile.PropertySet _ AlpFile.allProperties] RETURNS [properties: LIST OF AlpFile.PropertyValuePair]; <> <> <> WriteProperties: PROCEDURE [file: OpenFile, properties: LIST OF AlpFile.PropertyValuePair]; <> <> <> Abort: PROCEDURE [file: OpenFile]; <> <> <> GetAlpFileHandle: PROCEDURE [file: OpenFile] RETURNS [handle: AlpFile.Handle]; <> <> <> <> STREAM: TYPE = IO.STREAM; AccessOptions: TYPE = FS.AccessOptions; -- {read, create, append, write} ByteCount: TYPE = FS.ByteCount; StreamBufferParms: TYPE = FS.StreamBufferParms; -- RECORD [vmPagesPerBuffer: INT [1..128], nBuffers: INT [1..4]] defaultStreamBufferParms: StreamBufferParms = FS.defaultStreamBufferParms; -- [16, 2] StreamOptions: TYPE = RECORD [ <> tiogaRead: BOOLEAN _ TRUE, -- if accessOptions=$read and file is in Tioga format, read only plain text portion of the file (ignore "looks" and nodes with the comment property). If accessOptions#$read and file is in Tioga format, raise FS.Error[$cantUpdateTiogaFile]. truncatePagesOnClose: BOOLEAN _ TRUE, -- the IO.Close call causes extra pages of the file to be freed. closeFSOpenFileOnClose: BOOLEAN _ TRUE, -- the IO.Close call performs FS.Close on the underlying FS.OpenFile. <> commitAndReopenTransOnFlush: BOOLEAN _ TRUE, -- each IO.Flush call "checkpoints" the transaction being used by the stream. finishTransOnClose: BOOLEAN _ TRUE, -- the IO.Close call causes the transaction to be committed or aborted, according to the abort parameter to IO.Close. abortTransOnFinalize: BOOLEAN _ TRUE -- if the stream is abandoned (finalized without IO.Close having been called) and finishTransOnClose=TRUE, this option determines how the transaction is to be finished. Ordinarily one wants abandoned transactions to be aborted, but for debugging it may be useful to commit them anyway. ]; ExtendFileProc: TYPE = FS.ExtendFileProc; -- PROC [ByteCount] RETURNS [ByteCount] StreamOpen: PROCEDURE [name: ROPE, accessOptions: AccessOptions _ $read, streamOptions: StreamOptions _ [], keep: CARDINAL _ 1, createByteCount: ByteCount _ 2560, streamBufferParms: StreamBufferParms _ defaultStreamBufferParms, extendFileProc: ExtendFileProc _ NIL, wDir: ROPE _ NIL, transHandle: AlpTransaction.Handle _ NIL] RETURNS [STREAM]; <> <> <> <> <> InitialPosition: TYPE = FS.InitialPosition; -- {start, end} StreamFromOpenFile: PROCEDURE [openFile: OpenFile, accessRights: Lock _ $read, initialPosition: InitialPosition _ $start, streamOptions: StreamOptions _ [], streamBufferParms: StreamBufferParms _ defaultStreamBufferParms, extendFileProc: ExtendFileProc _ NIL] RETURNS [STREAM]; <> <> <> <> OpenFileFromStream: PROCEDURE [self: STREAM] RETURNS [OpenFile]; <> <> StreamFromOpenStream: PROCEDURE [self: STREAM] RETURNS [STREAM]; <> <> ErrorFromStream: PROCEDURE [self: STREAM] RETURNS [ErrorDesc]; <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> FileInfo: PROCEDURE [name: ROPE, wantedCreatedTime: BasicTime.GMT _ BasicTime.nullGMT, wDir: ROPE _ NIL, transHandle: AlpTransaction.Handle _ NIL] RETURNS [fullFName, attachedTo: ROPE, keep: CARDINAL, bytes: INT, created: BasicTime.GMT]; <> <> <> <> InfoProc: TYPE = FS.InfoProc; -- PROC [fullFName, attachedTo: ROPE, created: BasicTime.GMT, bytes: INT, keep: CARDINAL] RETURNS [continue: BOOLEAN]; EnumerateForInfo: PROCEDURE [pattern: ROPE, proc: InfoProc, wDir: ROPE _ NIL, transHandle: AlpTransaction.Handle _ NIL]; <> <> <> NameProc: TYPE = FS.NameProc; -- PROC [fullFName: ROPE] RETURNS [continue: BOOLEAN]; EnumerateForNames: PROCEDURE [pattern: ROPE, proc: NameProc, wDir: ROPE _ NIL, transHandle: AlpTransaction.Handle _ NIL]; <> <> <> Delete: PROCEDURE [name: ROPE, wantedCreatedTime: BasicTime.GMT _ BasicTime.nullGMT, wDir: ROPE _ NIL, transHandle: AlpTransaction.Handle _ NIL]; <> <> <> <> Copy: PROCEDURE [from, to: ROPE, wantedCreatedTime: BasicTime.GMT _ BasicTime.nullGMT, wDir: ROPE _ NIL, transHandle: AlpTransaction.Handle _ NIL] RETURNS [toFName: ROPE]; <> <> <> Rename: PROCEDURE [from, to: ROPE, wantedCreatedTime: BasicTime.GMT _ BasicTime.nullGMT, wDir: ROPE _ NIL, transHandle: AlpTransaction.Handle _ NIL] RETURNS [toFName: ROPE]; <> <> <> SetKeep: PROCEDURE [name: ROPE, keep: CARDINAL _ 1, wDir: ROPE _ NIL, transHandle: AlpTransaction.Handle _ NIL]; <> <> <> CreateLink: PROCEDURE [name: ROPE, referent: ROPE, wDir: ROPE _ NIL, transHandle: AlpTransaction.Handle _ NIL] RETURNS [fullFName, referentName: ROPE]; <> <> < referent in the directory. Subsequently, whenever name is looked up in the directory, the link will be followed to as many levels as necessary until an actual file is reached; and that file will be the one accessed.>> <> <> END.