-- FileStreamPrivate.mesa -- Last edited by -- MBrown on September 17, 1983 8:42 pm -- Teitelman on May 26, 1982 4:52 pm -- Last Edited by: Levin, September 22, 1983 2:48 pm -- Last Edited by: Hagmann December 5, 1983 1:22 pm DIRECTORY FileStream USING [ FinalizationProc ], FS USING [ErrorDesc, ExtendFileProc, Lock, OpenFile, StreamBufferParms, StreamOptions], IO USING [STREAM, StreamProcs], Rope USING [ROPE], VM USING [Interval]; FileStreamPrivate: CEDAR DEFINITIONS = BEGIN ROPE: TYPE = Rope.ROPE; -- DoFinalization should always be TRUE for released software. -- It is set to FALSE for testing. DoFinalization: BOOL = TRUE ; -- We model the behavior of a File IOStream with variables "file", "fileLen", and --"streamIndex", where -- file is an ARRAY [0..fileLen) OF CHAR -- streamIndex is an INT [0..fileLen] -- Key in this design is the assumption that a file stream will only be used by -- one process at a time. Processes are free to pass the stream around, but they must -- synchronize their access to the stream at a higher level than the stream. Two -- streams on the same file, the second one created by StreamFromOpenStream, -- do not need synchronization above the stream level unless the application requires it. -- The real stream contains a lot of redundant state to make the frequently-used --operations GetChar and PutChar fast. We shall list some invariant properties of --this state below. (Redundant properties, included for their intuitive value, are given in --parentheses.) -- We also define a piece of fictional state: trueDataBytesInBuffer. -- trueDataBytesInBuffer ::= MIN[bufferBytes, fileLen - firstByteInBuffer]. -- trueDataBytesInBuffer is too expensive for PutByte to maintain at all times, but it --is useful for other operations. ProcHandle: TYPE = REF IO.StreamProcs; STREAM: TYPE = IO.STREAM; -- Exported by FileStreamImpl.mesa ProcHandleFromAccessRights: PROC [accessRights: FS.Lock] RETURNS [ProcHandle]; SetupBuffer: PROC [fileData: FileDataHandle, fsData: FSDataHandle, fileByte: INT] RETURNS [currentNode: BufferNodeHandle] ; ProcessNode: PROC [ fileData: FileDataHandle, node: BufferNodeHandle ] ; -- Exported by FileStreamProcessCacheImpl.mesa StartRequest: PROC [ fileData: FileDataHandle, node: BufferNodeHandle ] ; FSDataHandle: TYPE = REF Data; BufferNodeHandle: TYPE = REF BufferNode ; FileDataHandle: TYPE = REF FileData ; -- data kept on a per stream basis Data: TYPE = RECORD [ index: CARDINAL _ 0, -- index is IN [0..currentNode.bufferBytes]. -- currentNode.didPut AND index >= dataBytesInBuffer => -- trueDataBytesInBuffer = index. -- This field has the property that is can be freely updated by the stream, -- and it can be read by the other streams under the monitor. -- It is always less than 64K, so that updates are always atomic (All D-machines -- write at least 16 bits at a time). currentNode: BufferNodeHandle _ NIL, -- All streams have a buffer of data in memory associated with the stream. -- This buffer may be empty -- This field is always non-NIL between calls the the package unless the -- stream has been closed. -- The control information for this buffer is a BufferNode. -- The node currently is use by this stream (and possibly other streams) -- is referred to via this field. -- Both currentNode and readAheadNode may only be changed under the -- monitor, and then only by this stream. readAheadNode: BufferNodeHandle _ NIL, -- If non-NIL, refers to buffer for read ahead data. lastFirstByteInBuffer: INT _ -1, -- This is the previous value in currentNode.firstByteInBuffer. -- It is used to detect sequentiality in reads in the preread logic. -- If this stream accesses buffer n, then buffer n+1, then if accesses buffer -- n+2 then a pre-read will be attempted given that there is more data in -- the file, there is a free buffer to use, and no other pre-read is in progress. isWriteStream: BOOL _ FALSE, -- If TRUE, then this record is referred to in fileData.writeStreamData and this -- stream was opened by StreamFromOpenFile with (logical) write access. -- If FALSE, this stream is referred to in fileData.firstReadStream, and was -- opened by StreamFromOpenFile with (logical) read access, or it was opened -- by StreamFromOpenStream. streamIsClosed: BOOL _ FALSE, -- stream.Close[] was called. -- (all operations should now raise StreamError[streamClosed]). fileData: FileDataHandle, -- Refers to the data that is related to the file and not to the stream (there can -- be multiple streams refering to the same file) FSErrorDesc: FS.ErrorDesc, -- last FS error on this stream. Initially set to [ok,NIL,NIL]. StreamClassData: REF ANY _ NIL, -- data for use by FSStreamImpl or AlpineStreamImpl or other file system specific code. FinalizationProc: FileStream.FinalizationProc _ NIL -- Client supplied finalization procedure, if any. ]; NodeStatus: TYPE = {valid, invalid, needsParallelRead, parallelReadActive, needsSequentialRead, sequentialReadActive, needsParallelWrite, parallelWriteActive, needsSequentialWrite, sequentialWriteActive}; -- valid - data in buffer is valid -- invalid - buffer not active, and data is not valid -- otherwise, need => this node has to have this action performed. -- Some process finds this, and does the action setting the node active. -- control information for a buffer BufferNode: TYPE = RECORD [ buffer: LONG POINTER TO PACKED ARRAY [0..0) OF CHAR _ NIL, -- buffer is really PACKED ARRAY [0..bufferBytes) OF CHAR. bufferInterval: VM.Interval _ TRASH, -- A space of pages for the stream buffer above. -- Although all buffers for a file stream are of the same length, -- this is kept on a per node basis so that a finalization routine can release -- the buffer space. bufferBytes: CARDINAL _ 0, -- Size of buffer in bytes dataBytesInBuffer: CARDINAL _ 0, -- dataBytesInBuffer is IN [0..trueDataBytesInBuffer] => IN [0..bufferBytes]. -- NOT didPut OR (didPut AND index <= dataBytesInBuffer) => -- trueDataBytesInBuffer = dataBytesInBuffer. -- The update of this field is protected by the monitor, but either the reader -- or the writer may do the update. firstFileByteInBuffer: INT _ -1, -- streamIndex = firstFileByteInBuffer + index. -- firstFileByteInBuffer < fileLen OR firstFileByteInBuffer = fileLen = 0. -- normally, firstFileByteInBuffer MOD bufferBytes = 0, but it is set to -1 -- initally to indicate that this buffer does not match any file page. -- (buffer[0] is indentified with file[firstFileByteInBuffer]. There is always -- one file byte in the buffer unless file is empty.) didPut: BOOL _ FALSE, -- (somebody has done a Put and not updated dataBytesInBuffer, FileLength, and --bufferDirty). bufferDirty: BOOL _ FALSE, -- didPut OR bufferDirty => there exists some i IN [0..trueDataBytesInBuffer) such --that buffer[i] # file[i] as last read from file system. -- You must hold the monitor to update this entry. useCount: INT _ 0, -- Number of streams using this node. This reflects the fact that some Data record -- has currentNode or readAheadNode referring to this node. This can only be -- changed under the monitor, and outside the monitor is always the count of -- REFs pointing at this buffer. LRUCount: INT _ 0, -- This counter is used to try to do a LRU use of the buffers. To update, you need -- the monitor. status: NodeStatus _ invalid, -- Changing the status requires owning the monitor nextBufferNode: BufferNodeHandle _ NIL -- The nodes are kept as a linked list, starting with FileData.firstBufferNode. -- Modification requires the monitor. ]; -- data kept on a per file basis FileData: TYPE = RECORD [ lockRecord: MONITORED RECORD [], -- Although the monitor is here, it logically covers many fields in BufferNode -- and Data records associated with this file. fileName: ROPE, firstBufferNode: BufferNodeHandle, -- first of a list of nodes for buffers. -- Update requires the monitor. firstReadStream: FSDataHandle _ NIL, -- First read stream or NIL if no readers -- Currently, there is only one reader. -- Update requires the monitor. accessRights: FS.Lock, tiogaReader: BOOL _ FALSE, -- TRUE iff file is being read as a Tioga file (reading the plain text only). --This implies that the file length shown in the stream is not the true file length, --but instead is the Tioga plain text length. fileLength: INT _ 0, -- NOT didPut => fileLen = fileLength. -- didPut AND index > dataBytesInBuffer => fileLen = firstFileByteInBuffer + -- index (index is from the writeStreamData). preReadInProgress: BOOL _ FALSE, -- Changed under the monitor, this is used to insure that only one pre-read -- occurs at a time. writeCount: INT _ 0, -- Count of writes pending. Changed only under the monitor. -- Currently this is not allowed to exceed 1. somethingHappened: CONDITION, -- General wait condition. It is BROADCAST when various interesting events -- occur such as the finish of a preread, and it is WAITed for by code that -- needs buffers or results from parallel processes. fileHandle: FS.OpenFile, streamBufferParms: FS.StreamBufferParms, extendFileProc: FS.ExtendFileProc, streamOptions: FS.StreamOptions, numberOfStreams: INT _ 1, -- The number of streams, read or write, that are open on this file. -- Do not close the file until this is 0. -- Except for initialization, this is modified under the monitor. byteLength: INT, --current value of fileHandle.OpenInfo[].bytes byteSize: INT, --current value of fileHandle.OpenInfo[].pages*bytesPerPage validBytesOnDisk: INT, -- The count of bytes on disk in the beginning of the file that are valid. -- Writing bytes past this count should not cause a read to fill the buffer. writeStreamData: FSDataHandle _ NIL -- refers to the write stream data (if any) for this file. ]; END. CHANGE LOG Created by MBrown on December 12, 1980 12:04 PM Changed by MBrown on January 6, 1981 8:53 PM -- Added Invalidate, added trans field to pilot data. Changed by MBrown on January 16, 1981 10:00 AM -- DataObject is now defined without using a Stream.Handle (copied structure from --FileStreamImpl). Changed by MBrown on January 18, 1981 1:00 AM -- LeaderPage now defined here (but it uses something called FileStream.Subtype for its --"dataType" field). Changed by MBrown on 18-Jan-81 16:49:31 -- Added bufferDirty (for juniper stream use). and streamIsClosed (for diagnosis from --the debugger). Improved the description of invariants. Changed by MBrown on January 21, 1981 3:45 PM -- Complete re-think of Pilot FileStream state, to make Put faster and generally reduce --the number of expensive conversions betweeen pages and bytes. Not yet implemented. Changed by MBrown on January 22, 1981 3:12 PM -- Improved comments on invariants. Changed by MBrown on January 25, 1981 8:19 PM -- Added Juniper variant of Data. Changed by MBrown on 27-Jan-81 15:10:07 -- FileByteStreamJuniper -> Juniper. Changed by MBrown on 29-Jan-81 20:43:05 -- Added JOpen, POpen. Changed by Russ Atkinson on 26-May-81 14:07:10 -- CedarString -> Rope, LONG CARDINAL -> LONG INTEGER Changed by MBrown on 7-Dec-81 10:30:56 -- Conversion to IO, INT, ROPE, etc. Changed by MBrown on March 26, 1982 4:40 pm -- Added tiogaReader field (this is redundant, but may be useful for debugging), and the --IsThisThingATiogaFile proc. Changed by Teitelman on May 26, 1982 4:52 pm -- changed to safe language, name change IOStream -> IO. Changed by MBrown on August 23, 1982 2:18 pm -- Eliminated TEXTDataOffset, added bufferParms, renamed JOpen -> JuniperOpen, --POpen -> ComSoftOpen, added CIFSOpen, added CIFS open file to pilot variant of Data. Changed by MBrown on May 16, 1983 2:03 pm -- Eliminated Juniper stuff, added Alpine stuff. Changed by MBrown on June 22, 1983 11:29 am -- Eliminated Pilot stuff, added FS stuff. Changed by MBrown on September 17, 1983 8:42 pm -- Eliminated all procs, since file stream impl is one module (FS). Changed by Hagmann on November 22, 1983 4:28 pm -- added modifications for multiple buffering and multiple streams on the same file -- added procs from split of FSFileIOImpl (since compiler blows up in pass 3) -- Renamed to FileStreamPrivate from FSFileIOPrivate from FILEIOPrivate Changed by Hagmann on November 28, 1983 11:57 am -- added DoFinalization for help in testing Changed by Hagmann on December 5, 1983 -- added ProcessNode and StartRequest for process cache -- deleted process counts in FileData. Ê«˜Jš.ÏcæœÏk œžœžœžœRžœžœžœžœžœžœžœ$žœž œžœžœžœžœ?œÐcsœžœžœ˜™Jšœ“ ˜“ JšœÄ˜ÄJšœN˜NJšœ‚˜‚Jšœ—R˜—R—…—2^3