-- File: FileStreamProcessCacheImpl.mesa
-- Please maintain change log at end of file.
-- Last Edited by
-- Hagmann on December 6, 1983 4:50 pm
DIRECTORY
FileStreamPrivate USING [ BufferNodeHandle, BufferNode,
      FileDataHandle, FileData, NodeStatus, ProcessNode ],
FS,
IO,
Process,
Rope;
FileStreamProcessCacheImpl: CEDAR MONITOR
IMPORTS
FileStreamPrivate,
Process
EXPORTS
FileStreamPrivate
= BEGIN
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
FileData: TYPE = FileStreamPrivate.FileData;
BufferNode: TYPE = FileStreamPrivate.BufferNode;
FileDataHandle: TYPE = FileStreamPrivate.FileDataHandle;
BufferNodeHandle: TYPE = FileStreamPrivate.BufferNodeHandle;
NumberOfProcesses: INT = 3 ;
ModuleCondition: CONDITION;
QueueRecord: TYPE = RECORD [
fileData: FileDataHandle,
node: BufferNodeHandle
,nodeStatus: FileStreamPrivate.NodeStatus
,nodeFirstFileByteInBuffer: INT
];
QUEUESIZE: INT = 20 ;
Queue: ARRAY [0..QUEUESIZE) OF QueueRecord ;
PutQueue: INT ← 0 ;
GetQueue: INT ← 0 ;
NoEntries: INT ← 0 ;
Queue up a request. Normal case is to queue and BROADCAST without waiting. If the queue is full, then wait for an entry to free up and then queue request.
StartRequest: PUBLIC ENTRY PROC [ fileData: FileDataHandle, node: BufferNodeHandle ] = {
tempCount: INT ← NoEntries ;
ptr: INT ← GetQueue ;
IF node.status # needsParallelRead AND node.status # needsParallelWrite THEN ERROR ;
WHILE tempCount > 0 DO
IF Queue[ptr].node = node THEN ERROR ;
ptr ← IF ptr = QUEUESIZE-1 THEN 0 ELSE ptr+1 ;
tempCount ← tempCount - 1 ;
ENDLOOP;
WHILE NoEntries >= QUEUESIZE - 1 DO
WAIT ModuleCondition ;
ENDLOOP;
Queue[PutQueue] ← [fileData, node --, node.status, node.firstFileByteInBuffer--];
PutQueue ← IF PutQueue = QUEUESIZE-1 THEN 0 ELSE PutQueue+1 ;
NoEntries ← NoEntries + 1;
BROADCAST ModuleCondition ;
};
FindSomethingToDo: ENTRY PROC []
RETURNS [fileData: FileDataHandle, node: BufferNodeHandle ]= {
WHILE NoEntries = 0 DO
WAIT ModuleCondition ;
ENDLOOP;
[fileData, node ] ← Queue[GetQueue] ;
Queue[GetQueue] ← [NIL,NIL];
GetQueue ← IF GetQueue = QUEUESIZE-1 THEN 0 ELSE GetQueue+1 ;
NoEntries ← NoEntries - 1;
BROADCAST ModuleCondition ;
};
This procedure is the top of the processes that do all the parallel reads and writes.
FileStreamForegroundProcess: PROC [] = {
DO
fileData: FileDataHandle ;
node: BufferNodeHandle;
[fileData, node] ← FindSomethingToDo [];
FileStreamPrivate.ProcessNode[fileData, node] ;
ENDLOOP;
};
myPriority: Process.Priority ;
myPriority ← Process.GetPriority[];
Process.SetPriority[Process.priorityForeground];
FOR I:INT IN [1..NumberOfProcesses] DO
process: PROCESS;
process ← FORK FileStreamForegroundProcess[];
TRUSTED {Process.Detach[process]; };
ENDLOOP;
Process.SetPriority[myPriority];
END.
CHANGE LOG
Created by Hagmann on December 6, 1983 3:02 pm
From a suggestion by Mark Brown, implement a cache of processes on a package wide basis.