-- CopyOp.mesa -- edited by Schroeder, February 5, 1981 5:18 PM -- edited by Andrew Birrell, January 14, 1981 3:40 PM -- edited by Brotz, March 9, 1981 4:25 PM DIRECTORY opD: FROM "OperationsDefs", ovD: FROM "OverviewDefs", TimeDefs; CopyOp: MONITOR IMPORTS opD EXPORTS opD = PUBLIC BEGIN Copy: PROCEDURE [source, target: STRING, OverwriteOK: PROC RETURNS [BOOLEAN] ] RETURNS [error: ovD.ErrorCode, getOrPut: opD.GetOrPutType, errorString: STRING, bytesCopied: LONG CARDINAL] = BEGIN state: {start, bufferEmpty, bufferFull, stop}; resumeExpander, resumeStuffer: CONDITION; bufferP: POINTER; bufferC: CARDINAL; ec: ovD.ErrorCode; es: STRING; stufferProcess: PROCESS RETURNS [ovD.ErrorCode, STRING]; stufferStarted: BOOLEAN _ FALSE; GetReady: PROCEDURE [bytes: LONG CARDINAL, created: TimeDefs.PackedTime] = BEGIN stufferProcess _ FORK StartStuffer[created]; stufferStarted _ TRUE; END; --GetReady-- StartStuffer: PROCEDURE [t: TimeDefs.PackedTime] RETURNS [e: ovD.ErrorCode, s: STRING] = BEGIN [e, s] _ opD.Stuff[target, Stuffer, OverwriteAllowed, t]; IF e=ovD.cancelCode THEN e _ ovD.ok; IF e#ovD.ok THEN StopExpander[]; END; --StartStuffer-- OverwriteAllowed: PROCEDURE RETURNS [allowed: BOOLEAN] = BEGIN allowed _ OverwriteOK[]; IF NOT allowed THEN StopExpander[]; END; --OverwriteAllowed-- Stuffer: ENTRY PROCEDURE RETURNS [p: POINTER, c: CARDINAL, e: ovD.ErrorCode] = BEGIN IF state#stop THEN BEGIN state _ bufferEmpty; NOTIFY resumeExpander; UNTIL state#bufferEmpty DO WAIT resumeStuffer; ENDLOOP; p _ bufferP; c _ bufferC; END; e _ IF state=bufferFull THEN ovD.ok ELSE ovD.cancelCode; END; --Stuffer-- StopExpander: ENTRY PROCEDURE = {state _ stop; NOTIFY resumeExpander}; StopStuffer: ENTRY PROCEDURE = {state _ stop; NOTIFY resumeStuffer}; Expander: ENTRY PROCEDURE [p: POINTER, c: CARDINAL] RETURNS [e: ovD.ErrorCode] = BEGIN UNTIL state#start DO WAIT resumeExpander; ENDLOOP; IF state#stop THEN BEGIN bufferP _ p; bufferC _ c; state _ bufferFull; NOTIFY resumeStuffer; bytesCopied _ bytesCopied + c; END; IF c#0 THEN UNTIL state#bufferFull DO WAIT resumeExpander; ENDLOOP; e _ IF state=bufferEmpty THEN ovD.ok ELSE ovD.cancelCode; END; --Expander-- bytesCopied _ 0; state _ start; getOrPut _ get; [error, errorString] _ opD.Expand[source, Expander, GetReady]; IF error=ovD.cancelCode THEN error _ ovD.ok; IF stufferStarted THEN BEGIN IF error#ovD.ok THEN StopStuffer[]; [ec, es] _ JOIN stufferProcess; IF error=ovD.ok THEN {error _ ec; errorString _ es; getOrPut _ put} ELSE {IF es#NIL THEN opD.FreeErrorString[es]}; END; END; --Copy-- END. --CopyOp-- (635)\f1