<<>> <> <> <> <> <> <> <<>> <> 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); -- ???? <> Error: PUBLIC ERROR [ h: Handle, errorReason: CrRPC.ErrorReason, text: ROPE] ~ CODE; <> CreateClientHandleProcValue: TYPE ~ REF CreateClientHandleProcValueObject; CreateClientHandleProcValueObject: TYPE ~ RECORD [ createClientHandleProc: CrRPCBackdoor.CreateClientHandleProc ]; createClientHandleProcTable: RefTab.Ref ¬ RefTab.Create[]; RegisterCreateClientHandleProc: PUBLIC PROC [ class: ATOM, proc: CrRPCBackdoor.CreateClientHandleProc] <> ~ { [] ¬ RefTab.Store[x~createClientHandleProcTable, key~class, val~NEW[CreateClientHandleProcValueObject ¬ [proc]]]; }; LookupCreateClientHandleProc: PROC [class: ATOM] RETURNS [CrRPCBackdoor.CreateClientHandleProc] ~ { <> 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]] }; <> 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] <> ~ { [] ¬ RefTab.Store[x~startInstanceProcTable, key~class, val~NEW[StartInstanceProcValueObject ¬ [startServerInstanceProc]]]; }; LookupStartServerInstanceProc: PROC [class: ATOM] RETURNS [CrRPCBackdoor.StartServerInstanceProc] ~ { <> 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]; }; <> 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]] }; <> 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]; }; }.