-- File: BSPSink.mesa - last edit: -- AOF 17-Feb-88 17:06:28 -- WIrish 5-Feb-88 12:03:17 -- HGM 25-Jun-85 3:14:02 -- Copyright (C) 1983, 1984, 1985, 1988 by Xerox Corporation. All rights reserved. DIRECTORY Environment USING [Byte], Event USING [aboutToSwap], EventTypes USING [aboutToBoot, aboutToBootPhysicalVolume], FormSW USING [ AllocateItemDescriptor, newLine, ClientItemsProcType, ProcType, FindItem, Display, CommandItem, BooleanItem], Process USING [Yield], Put USING [Line], Runtime USING [GetBcdTime], Stream USING [Handle, GetBlock, Delete], String USING [AppendChar, AppendString], Supervisor USING [ AddDependency, AgentProcedure, CreateSubsystem, RemoveDependency, SubsystemHandle], Time USING [Append, AppendCurrent, Unpack], Tool USING [Create, MakeSWsProc, MakeMsgSW, MakeFormSW], ToolWindow USING [TransitionProcType], Window USING [Handle], PupDefs USING [PupPackageMake, PupPackageDestroy, AppendHostName, veryLongWait], PupStream USING [ CreatePupByteStreamListener, DestroyPupListener, RejectThisRequest, StreamClosing, PupListener, PupAddress], PupTypes USING [bspTestSoc], Stats USING [ StatCounterIndex, StatIncr, StatBump, StatsStringToIndex], StatsOps USING [StatArray, statGrand]; BSPSink: MONITOR IMPORTS Event, FormSW, Process, Put, Runtime, Stream, String, Supervisor, Time, Tool, PupDefs, PupStream, Stats, StatsOps = BEGIN OPEN Stats, PupDefs; statBytesReceived: PUBLIC StatCounterIndex; statConnectionsOpened: PUBLIC StatCounterIndex; stats: StatsOps.StatArray ← StatsOps.statGrand; useCount: CARDINAL ← 0; pleaseStop, running, verbose, superQuiet: BOOLEAN ← FALSE; listener: PupStream.PupListener; tool, msg, form: Window.Handle ← NIL; broom: Supervisor.SubsystemHandle = Supervisor.CreateSubsystem[Broom]; sinks: CARDINAL ← 0; maxSinks: CARDINAL ← 4; Init: PROCEDURE = BEGIN herald: LONG STRING = [100]; String.AppendString[herald, "BSP Sink Tool of "L]; Time.Append[herald, Time.Unpack[Runtime.GetBcdTime[]]]; SetupListenerThings[]; tool ← Tool.Create[ name: herald, makeSWsProc: MakeSWs, clientTransition: ClientTransition]; END; SetupListenerThings: PUBLIC PROCEDURE = BEGIN statBytesReceived ← StatsStringToIndex["BSP Sink - Bytes received"]; statConnectionsOpened ← StatsStringToIndex["BSP Sink - Connections opened"]; END; ListenerOn: PUBLIC PROCEDURE = BEGIN IF (useCount ← useCount + 1) = 1 THEN BEGIN Supervisor.AddDependency[client: broom, implementor: Event.aboutToSwap]; running ← TRUE; Starter[]; END; UpdatePicture[]; END; Starter: PROCEDURE = BEGIN pleaseStop ← FALSE; [] ← PupDefs.PupPackageMake[]; listener ← PupStream.CreatePupByteStreamListener[ PupTypes.bspTestSoc, Sink, veryLongWait, Check]; END; Check: ENTRY PROCEDURE [who: PupStream.PupAddress] = BEGIN IF sinks >= maxSinks THEN PupStream.RejectThisRequest["Sorry, I'm full now."L]; sinks ← sinks + 1; Stats.StatIncr[statConnectionsOpened]; END; ListenerOff: PUBLIC PROCEDURE = BEGIN IF useCount # 0 AND (useCount ← useCount - 1) = 0 THEN BEGIN running ← FALSE; Stopper[]; Supervisor.RemoveDependency[client: broom, implementor: Event.aboutToSwap]; END; UpdatePicture[]; END; Stopper: PROCEDURE = BEGIN pleaseStop ← TRUE; UNTIL sinks = 0 DO Process.Yield[]; ENDLOOP; PupStream.DestroyPupListener[listener]; PupDefs.PupPackageDestroy[]; END; UpdatePicture: PROCEDURE = BEGIN IF form = NIL THEN RETURN; FormSW.FindItem[form, startIX].flags.invisible ← running; FormSW.FindItem[form, stopIX].flags.invisible ← ~running; FormSW.Display[form]; END; Sink: PROCEDURE [stream: Stream.Handle, who: PupStream.PupAddress] = BEGIN KillSinkLocked: ENTRY PROCEDURE = BEGIN sinks ← sinks - 1; END; bytesPerClump: CARDINAL = 512; buffer: PACKED ARRAY [0..bytesPerClump) OF Environment.Byte; bytes: CARDINAL; Announce[who, "Creating"L]; BEGIN ENABLE PupStream.StreamClosing => CONTINUE; UNTIL pleaseStop DO [bytes, ] ← Stream.GetBlock[stream, [@buffer, 0, bytesPerClump]]; Stats.StatBump[statBytesReceived, bytes]; ENDLOOP; END; Stream.Delete[stream]; Announce[who, "Destroying"L]; KillSinkLocked[]; END; Announce: PROCEDURE [who: PupStream.PupAddress, arg: STRING] = BEGIN text: STRING = [100]; IF superQuiet THEN RETURN; Time.AppendCurrent[text]; String.AppendString[text, " BSP: "L]; String.AppendString[text, arg]; String.AppendString[text, " BSP connection for "L]; PupDefs.AppendHostName[text, who]; String.AppendChar[text, '.]; IF msg # NIL THEN Put.Line[msg, text]; Put.Line[NIL, text]; END; Start: FormSW.ProcType = BEGIN ListenerOn[]; END; Stop: FormSW.ProcType = BEGIN ListenerOff[]; END; MakeSWs: Tool.MakeSWsProc = BEGIN msg ← Tool.MakeMsgSW[window: window, lines: 5]; form ← Tool.MakeFormSW[window: window, formProc: MakeForm]; END; startIX: CARDINAL = 0; stopIX: CARDINAL = 1; MakeForm: FormSW.ClientItemsProcType = BEGIN nParams: CARDINAL = 5; items ← FormSW.AllocateItemDescriptor[nParams]; items[0] ← FormSW.CommandItem[ tag: "Start"L, proc: Start, place: FormSW.newLine, invisible: running]; items[1] ← FormSW.CommandItem[ tag: "Stop"L, proc: Stop, place: FormSW.newLine, invisible: ~running]; items[2] ← FormSW.BooleanItem[ tag: "Running"L, switch: @running, readOnly: TRUE]; items[3] ← FormSW.BooleanItem[tag: "Verbose"L, switch: @verbose]; items[4] ← FormSW.BooleanItem[tag: "SuperQuiet"L, switch: @superQuiet]; RETURN[items, TRUE]; END; ClientTransition: ToolWindow.TransitionProcType = BEGIN IF new = inactive THEN msg ← form ← NIL; END; Broom: Supervisor.AgentProcedure = BEGIN SELECT event FROM EventTypes.aboutToBoot, EventTypes.aboutToBootPhysicalVolume => IF running THEN Stopper[]; ENDCASE => NULL; END; -- initialization Init[]; ListenerOn[]; END.