-- RPCBulk.mesa
-- Andrew Birrell  26-Feb-82 10:06:00

DIRECTORY
NameInfoSpecialDefs, Process, MesaRPC, RPCLupine, Runtime, SpyClient, System;

RPCBulk: MONITOR
IMPORTS NameInfoSpecialDefs, Process, MesaRPC, RPCLupine, Runtime, SpyClient, System =

BEGIN

-- ******** Test program ******** --

Finished: SIGNAL = CODE;
signalFinished: BOOLEAN ← TRUE;
tries:          CARDINAL ← 1000;
quit:           BOOLEAN ← FALSE;
gvExport:       BOOLEAN ← TRUE;
gvInstance:     STRING = "RPCRuntime.pa";
nongvInstance:  STRING = "Tokay";
callerName:     MesaRPC.Principal ← "Test.pa";
callerKey:      MesaRPC.EncryptionKey ← MesaRPC.MakeKey["Test"L];
exporterName:   MesaRPC.Principal ← "RPCRuntime.pa";
exporterKey:    MesaRPC.EncryptionKey ← MesaRPC.MakeKey["zzy"L];
userTest:       BOOLEAN ← TRUE;
spyWanted:      BOOLEAN ← FALSE;

import: RPCLupine.ImportHandle ← NIL;


-- Test version of stub code --

StartTransfer: PROC[conv: MesaRPC.Conversation] =
  BEGIN
  pktSpace: ARRAY[1..RPCLupine.pktOverhead+1] OF WORD;
  pkt: RPCLupine.StubPkt = RPCLupine.GetStubPkt[@pktSpace];
  [] ← RPCLupine.StartCall[pkt, import, conv];
  BEGIN
    length: RPCLupine.DataLength;
    last: BOOLEAN;
    pkt[0] ← 1;
    [length, last] ← RPCLupine.Call[pkt, 1, 1, NIL];
    IF NOT last THEN ERROR;
  END;
  END;

SendPage: PROC[conv: MesaRPC.Conversation, page: CARDINAL] =
  BEGIN
  pktSpace: ARRAY[1..RPCLupine.pktOverhead+RPCLupine.maxDataLength] OF WORD;
  pkt: RPCLupine.StubPkt = RPCLupine.GetStubPkt[@pktSpace];
  [] ← RPCLupine.StartCall[pkt, import, conv];
  BEGIN
    length: RPCLupine.DataLength;
    last: BOOLEAN;
    pkt[0] ← 0; pkt[1] ← page;
    [length, last] ← RPCLupine.Call[pkt, RPCLupine.maxDataLength,
                                    RPCLupine.maxDataLength, NIL];
    IF NOT last THEN ERROR;
  END;
  END;

TestDispatcher: RPCLupine.Dispatcher =
  BEGIN
  -- Dummy dispatcher: consumes args and sends dummy result --
  IF NOT lastPkt THEN ERROR;
  SELECT pkt[0] FROM
    0 => AcceptPage[localConversation, pkt[1] ];
    1 => AcceptTransfer[localConversation];
  ENDCASE => ERROR;
  RETURN[0];
  END;


-- Test version of client code --

-- Sender --

conversation: MesaRPC.Conversation;
senderPage: CARDINAL ← 0;

NextPage: ENTRY PROC RETURNS[p: CARDINAL] = INLINE
  { p ← senderPage; senderPage ← senderPage+1 };

Sender: PROC[limit: CARDINAL] =
  BEGIN
  DO p: CARDINAL = NextPage[];
     IF p > limit THEN EXIT;
     SendPage[conversation, p];
  ENDLOOP;
  END;

-- Receiver --

pageCond: CONDITION ← [timeout:0];
receiverPage: CARDINAL ← 0;

AcceptTransfer: ENTRY PROC[conv: MesaRPC.Conversation] =
  BEGIN
  receiverPage ← 0;
  END;

AcceptPage: ENTRY PROC[conv: MesaRPC.Conversation, page: CARDINAL] =
  BEGIN
  UNTIL receiverPage = page DO WAIT pageCond ENDLOOP;
  receiverPage ← page + 1;
  BROADCAST pageCond;
  END;

DoIt: PROC =
   BEGIN
   -- Export and import --

   instance: STRING ← IF gvExport THEN gvInstance ELSE nongvInstance;

   import ← RPCLupine.ImportInterface[["RPC-bulk-test"L, instance], [0,0] !
     MesaRPC.ImportFailed =>
       IF why = unbound OR why = communications
       THEN BEGIN
            [] ← RPCLupine.ExportInterface[exporterName, exporterKey,
		     ["RPC-bulk-test"L, instance], TestDispatcher, [0,0]];
            import ← RPCLupine.ImportInterface[["RPC-bulk-test"L,
                                  instance],[0,0]];
            CONTINUE
            END ];
   BEGIN
     spyAvailable: BOOLEAN = Runtime.IsBound[SpyClient.StartCounting];
     UNTIL quit
     DO UNTIL userTest DO Process.Pause[Process.SecondsToTicks[5]] ENDLOOP;
        conversation ← MesaRPC.StartConversation[callerName, callerKey, exporterName, authOnly];
	senderPage ← 0; StartTransfer[conversation];
        NameInfoSpecialDefs.CleanUp[];
        IF spyWanted AND spyAvailable THEN SpyClient.StartCounting[];
        BEGIN
	    start:   System.Pulses = System.GetClockPulses[];
            end:     System.Pulses;
            elapsed: System.Microseconds;
            first:   PROCESS = FORK Sender[tries];  
	    second:  PROCESS = FORK Sender[tries];
	    third:   PROCESS = FORK Sender[tries];
	    fourth:  PROCESS = FORK Sender[tries];
	    --fifth:   PROCESS = FORK Sender[tries];
	    --sixth:   PROCESS = FORK Sender[tries];
	    --seventh: PROCESS = FORK Sender[tries];
	    JOIN first; JOIN second; JOIN third; JOIN fourth;
	    --JOIN fifth; JOIN sixth; JOIN seventh;
            end ← System.GetClockPulses[];
	    IF spyWanted AND spyAvailable THEN SpyClient.StopCounting[];
            elapsed ← System.PulsesToMicroseconds[[end-start]];
	    MesaRPC.EndConversation[conversation];
            IF signalFinished THEN SIGNAL Finished[];
	END;
     ENDLOOP;
     
     END;
   END;

DoIt[];


END.