CrRPCImpl.mesa
Copyright Ó 1986, 1990, 1991 by Xerox Corporation. All rights reserved.
Demers, April 25, 1990 8:11 am PDT
Willie-sue Orr, December 9, 1991 4:46 pm PST
Michael Plass, April 16, 1990 9:43 am PDT
Christian Jacobi, July 24, 1992 7:35 pm PDT
Courier runtime support.
DIRECTORY
Basics USING [Card16FromH, FWORD, HFromCard16, HWORD],
CrRPC USING [BulkDataSink, BulkDataSource, ErrorReason, GetCard16, GetHWord, Handle, HandleClass, HandleKind, Object, ProcsObject, PutCard16, RefAddress, SeqCard16, SeqCard16Object, SeqHWord, SeqHWordObject, ServerProc, StopServerQueryProc],
CrRPCBackdoor USING [CreateClientHandleProc, StartServerInstanceProc],
FinalizeOps USING [CallQueue, CreateCallQueue, EnableFinalization, FinalizeProc, Handle, ReenableFinalization],
IO USING [EndOfStream, GetChar, GetRope, PutChar, PutRope, STREAM, UnsafeGetBlock, UnsafePutBlock],
RefTab USING [Create, Fetch, Ref, Store],
Rope USING [Length, ROPE];
CrRPCImpl:
CEDAR
MONITOR
IMPORTS Basics, CrRPC, FinalizeOps, RefTab, Rope
EXPORTS CrRPC, CrRPCBackdoor
~ {
FWORD: TYPE ~ Basics.FWORD;
HWORD: TYPE ~ Basics.HWORD;
ROPE: TYPE ~ Rope.ROPE;
Handle: TYPE ~ CrRPC.Handle;
STREAM: TYPE ~ IO.STREAM;
bigEndianHWords: BOOL ~ (LOOPHOLE[Basics.HFromCard16[1], CARD16] = 1); -- ????
Errors
Error:
PUBLIC
ERROR [
h: Handle,
errorReason: CrRPC.ErrorReason,
text: ROPE] ~ CODE;
Create / Destroy for Client Handles
CreateClientHandleProcValue: TYPE ~ REF CreateClientHandleProcValueObject;
CreateClientHandleProcValueObject:
TYPE ~
RECORD [
createClientHandleProc: CrRPCBackdoor.CreateClientHandleProc ];
createClientHandleProcTable: RefTab.Ref ¬ RefTab.Create[];
RegisterCreateClientHandleProc:
PUBLIC
PROC [
class:
ATOM, proc: CrRPCBackdoor.CreateClientHandleProc]
N.B. This would need to be an ENTRY proc except that the RefTab package handles concurrent clients.
~ {
[] ¬ RefTab.Store[x~createClientHandleProcTable, key~class, val~NEW[CreateClientHandleProcValueObject ¬ [proc]]];
};
LookupCreateClientHandleProc:
PROC [class:
ATOM]
RETURNS [CrRPCBackdoor.CreateClientHandleProc] ~ {
N.B. This would need to be an ENTRY proc except that the RefTab package handles concurrent clients.
found: BOOL;
val: REF;
[found, val] ¬ RefTab.Fetch[x~createClientHandleProcTable, key~class];
IF found
THEN RETURN [NARROW[val, CreateClientHandleProcValue].createClientHandleProc]
ELSE RETURN [NIL];
};
CreateClientHandle:
PUBLIC
PROC [class:
ATOM, remote: CrRPC.RefAddress]
RETURNS [CrRPC.Handle] ~ {
proc: CrRPCBackdoor.CreateClientHandleProc ~ LookupCreateClientHandleProc[class];
IF proc = NIL THEN ERROR Error[NIL, unknownClass, NIL];
RETURN [proc[remote]]
};
Create / Destroy for Servers
ServerValue: TYPE ~ REF ServerValueObject;
ServerValueObject:
TYPE ~
RECORD [
next: ServerValue,
pgm: CARD32,
pgmLoVersion: CARD16,
pgmHiVersion: CARD16,
serverProc: CrRPC.ServerProc,
stopServerQueryProc: CrRPC.StopServerQueryProc];
serverTableSize: CARDINAL ~ 101; -- a modest prime
ServerTable: TYPE ~ REF ServerTableObject;
ServerTableObject:
TYPE ~
RECORD [
values: ARRAY [0..serverTableSize) OF ServerValue];
serverTable: ServerTable ¬
NEW[ServerTableObject ¬ [
ALL[
NIL]]];
HashServer:
INTERNAL
PROC [pgm:
CARD32]
RETURNS[index:
CARD] ~
INLINE { index ¬ pgm
MOD
CARD[serverTableSize] };
FetchServerValue:
INTERNAL
PROC [pgm:
CARD32, pgmVersion:
CARD16]
RETURNS [ServerValue] ~ {
index: CARD ~ HashServer[pgm];
FOR p: ServerValue ¬ serverTable.values[index], p.next
WHILE p #
NIL
DO
IF (p.pgm = pgm) AND (p.pgmLoVersion <= pgmVersion) AND (p.pgmHiVersion >= pgmVersion) THEN RETURN [p];
ENDLOOP;
RETURN [NIL];
};
RegisterServerProcs:
PUBLIC ENTRY
PROC [pgm:
CARD32, pgmLoVersion:
CARD16, pgmHiVersion:
CARD16, serverProc: CrRPC.ServerProc, stopServerQueryProc: CrRPC.StopServerQueryProc] ~ {
ENABLE UNWIND => NULL;
index: CARD;
index ¬ HashServer[pgm];
serverTable.values[index] ¬ NEW[ServerValueObject ¬
[next~serverTable.values[index], pgm~pgm, pgmLoVersion~pgmLoVersion, pgmHiVersion~pgmHiVersion, serverProc~serverProc, stopServerQueryProc~stopServerQueryProc]];
};
LookUpServerProcs:
PUBLIC
ENTRY
PROC [pgm:
CARD32, pgmVersion:
CARD16]
RETURNS [serverProc: CrRPC.ServerProc, stopServerQueryProc: CrRPC.StopServerQueryProc] ~ {
serverValue: ServerValue ~ FetchServerValue[pgm, pgmVersion];
IF serverValue #
NIL
THEN RETURN [serverValue.serverProc, serverValue.stopServerQueryProc]
ELSE RETURN [NIL, NIL];
};
StartInstanceProcValue: TYPE ~ REF StartInstanceProcValueObject;
StartInstanceProcValueObject:
TYPE ~
RECORD [
startInstance: CrRPCBackdoor.StartServerInstanceProc];
startInstanceProcTable: RefTab.Ref ¬ RefTab.Create[];
RegisterStartServerInstanceProc:
PUBLIC
PROC [
class: CrRPC.HandleClass,
startServerInstanceProc: CrRPCBackdoor.StartServerInstanceProc]
N.B. This would need to be an ENTRY proc except that the RefTab package handles concurrent clients.
~ {
[] ¬ RefTab.Store[x~startInstanceProcTable, key~class,
val~NEW[StartInstanceProcValueObject ¬ [startServerInstanceProc]]];
};
LookupStartServerInstanceProc:
PROC [class:
ATOM]
RETURNS [CrRPCBackdoor.StartServerInstanceProc] ~ {
N.B. This would need to be an ENTRY proc except that the RefTab package handles concurrent clients.
found: BOOL;
val: REF;
[found, val] ¬ RefTab.Fetch[x~startInstanceProcTable, key~class];
IF found
THEN RETURN [NARROW[val, StartInstanceProcValue].startInstance]
ELSE RETURN [NIL];
};
StartServerInstance:
PUBLIC
PROC [
pgm:
CARD32,
pgmVersion:
CARD16,
class: CrRPC.HandleClass,
local: CrRPC.RefAddress] ~ {
proc: CrRPCBackdoor.StartServerInstanceProc ~ LookupStartServerInstanceProc[class];
IF proc = NIL THEN ERROR Error[NIL, unknownClass, NIL];
proc[pgm, pgmVersion, local];
};
Marshalling Procs
GetSeqHWord:
PUBLIC
PROC [s:
STREAM]
RETURNS [seqHWord: CrRPC.SeqHWord] ~ {
n: CARD16;
nBytes, nBytesRead: INT;
n ¬ CrRPC.GetCard16[s];
seqHWord ¬ NEW[CrRPC.SeqHWordObject[n]];
nBytes ¬ (n*BITS[HWORD])/BITS[BYTE];
TRUSTED {
nBytesRead ¬ IO.UnsafeGetBlock[self~s, block~[base~LOOPHOLE[seqHWord], startIndex~BITS[CrRPC.SeqHWordObject[0]]/BITS[BYTE], count~nBytes]] };
IF nBytesRead # nBytes THEN ERROR IO.EndOfStream[s] };
PutSeqHWORD:
PUBLIC
PROC [s:
STREAM, seqHWord: CrRPC.SeqHWord] ~ {
n: CARD16;
nBytes: INT;
n ¬ seqHWord.length;
nBytes ¬ (n*BITS[HWORD])/BITS[BYTE];
CrRPC.PutCard16[s, n];
TRUSTED {
IO.UnsafePutBlock[self~s, block~[base~LOOPHOLE[seqHWord], startIndex~BITS[CrRPC.SeqHWordObject[0]]/BITS[BYTE], count~nBytes]] };
};
GetSeqCard16:
PUBLIC
PROC [s:
STREAM]
RETURNS [seqCard16: CrRPC.SeqCard16] ~ {
n: CARD16;
nBytes, nBytesRead: INT;
n ¬ CrRPC.GetCard16[s];
seqCard16 ¬ NEW[CrRPC.SeqCard16Object[n]];
nBytes ¬ (n*BITS[HWORD])/BITS[BYTE];
TRUSTED {
nBytesRead ¬ IO.UnsafeGetBlock[self~s, block~[base~LOOPHOLE[seqCard16], startIndex~BITS[CrRPC.SeqCard16Object[0]]/BITS[BYTE], count~nBytes]] };
IF nBytesRead # nBytes THEN ERROR IO.EndOfStream[s];
IF
NOT bigEndianHWords
THEN
FOR i:
CARDINAL
IN [0..n)
DO
seqCard16.body[i] ¬ Basics.Card16FromH[LOOPHOLE[seqCard16.body[i]]];
ENDLOOP;
};
PutSeqCard16:
PUBLIC
PROC [s:
STREAM, seqCard16: CrRPC.SeqCard16] ~ {
n: CARD16;
nBytes: INT;
n ¬ seqCard16.length;
nBytes ¬ (n*BITS[HWORD])/BITS[BYTE];
CrRPC.PutCard16[s, n];
IF
NOT bigEndianHWords
THEN
FOR i:
CARDINAL
IN [0..n)
DO
seqCard16.body[i] ¬ LOOPHOLE[Basics.HFromCard16[seqCard16.body[i]]];
ENDLOOP;
TRUSTED {
IO.UnsafePutBlock[self~s, block~[base~LOOPHOLE[seqCard16], startIndex~BITS[CrRPC.SeqCard16Object[0]]/BITS[BYTE], count~nBytes]] };
};
SkipSeqHWord,
SkipSeqCard16:
PUBLIC
PROC [s:
STREAM] ~ {
n: CARDINAL ~ CrRPC.GetCard16[s];
THROUGH [0 .. n)
DO
[] ¬ CrRPC.GetHWord[s];
ENDLOOP;
};
GetRope:
PUBLIC PROC [s:
STREAM]
RETURNS [rope:
ROPE] ~ {
len: CARDINAL ¬ CrRPC.GetCard16[s];
rope ¬ IO.GetRope[s, len, TRUE];
IF (len MOD 2) # 0 THEN [] ¬ IO.GetChar[s];
};
PutRope:
PUBLIC PROC [s:
STREAM, rope:
ROPE] ~ {
len: INT ~ Rope.Length[rope];
CrRPC.PutCard16[s, len];
IO.PutRope[s, rope];
IF (len MOD 2) # 0 THEN IO.PutChar[s, VAL[0]];
};
SkipROPE:
PUBLIC PROC [h: Handle, s:
STREAM] ~ {
len: CARDINAL ¬ CrRPC.GetCard16[s];
IF (len MOD 2) # 0 THEN len ¬ len + 1;
THROUGH [0 .. len)
DO
[] ¬ IO.GetChar[s];
ENDLOOP;
};
MarshalledRopeHWords:
PUBLIC PROC [rope:
ROPE]
RETURNS [hWords:
CARDINAL] ~ {
hWords ¬ (Rope.Length[rope] + 2*(BITS[HWORD]/BITS[BYTE]) - 1) / (BITS[HWORD]/BITS[BYTE]) };
GetBulkDataSource:
PUBLIC
PROC [h: Handle, s:
STREAM]
RETURNS [CrRPC.BulkDataSource] ~ {
RETURN [h.procs.getBulkDataSource[h, s]] };
GetBulkDataSink:
PUBLIC
PROC [h: Handle, s:
STREAM]
RETURNS [CrRPC.BulkDataSink] ~ {
RETURN [h.procs.getBulkDataSink[h, s]] };
FinalizeOps
finalizationQueue: FinalizeOps.CallQueue ¬ FinalizeOps.CreateCallQueue[ClientHandleFinalizer];
NewClientObject:
PUBLIC
PROC [class: CrRPC.HandleClass,
procs:
REF CrRPC.ProcsObject, data:
REF ¬
NIL, clientData:
REF ¬
NIL]
RETURNS [h: Handle] ~ {
h ¬ NEW[CrRPC.Object ¬ [class~class, kind~client, procs~procs, data~data, clientData~clientData]];
[] ¬ FinalizeOps.EnableFinalization[h, finalizationQueue];
};
ClientHandleFinalizer: FinalizeOps.FinalizeProc ~ {
h: Handle ¬ NARROW[object];
IF h.procs.finalize #
NIL
THEN
IF ( h.procs.finalize[h] ) THEN [] ¬ FinalizeOps.ReenableFinalization[handle];
};
}.