SunPMapServerImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Demers, November 4, 1987 11:47:53 am PST
DIRECTORY
Arpa USING [Address],
ArpaExtras USING [MyAddress],
Basics USING [HFromCard16],
RefText USING [New],
SunPMap USING [CallitProc, DumpProc, GetPortProc, ipProtocolUDP, MapEntry, NullProc, SetProc, UnsetProc],
SunPMapLocal USING [],
SunPMapServer USING [],
SunRPC USING [BytesRemaining, Create, Destroy, Error, GetBlock, Handle, PutBlock, SendCallAndReceiveReply, StartCall],
SunRPCAuth USING [Conversation, Initiate, Terminate]
;
SunPMapServerImpl: CEDAR MONITOR
IMPORTS ArpaExtras, Basics, RefText, SunRPC, SunRPCAuth
EXPORTS SunPMapLocal, SunPMapServer
~ {
Parameters
tableSize: CARDINAL ~ 31;
longTimeout: CARD ← 5000;
Types
Address: TYPE ~ Arpa.Address;
Handle: TYPE ~ SunRPC.Handle;
Conversation: TYPE ~ SunRPCAuth.Conversation;
MapEntry: TYPE ~ SunPMap.MapEntry;
Map
Item: TYPE ~ REF ItemObject;
ItemObject: TYPE ~ RECORD [
next: Item,
entry: MapEntry
];
Headers: TYPE ~ REF HeadersObject;
HeadersObject: TYPE ~ ARRAY [0 .. tableSize) OF Item;
headers: Headers ← NEW[HeadersObject];
Hash: PROC [program, version: CARD] RETURNS [CARD] ~ {
RETURN [(3*program + version) MOD tableSize];
};
Procedures
Null: PUBLIC SunPMap.NullProc -- [h: Handle, c: Conversation] -- ~ {
NULL;
};
Set: PUBLIC SunPMap.SetProc -- [h: Handle, c: Conversation, program, version, protocol, port: CARD32] RETURNS [success: BOOL] -- ~ {
RETURN [SetLocal[program, version, protocol, port]];
};
SetLocal: PUBLIC ENTRY PROC [program, version, protocol, port: CARD32]
RETURNS [success: BOOL] ~ {
index: CARD ← Hash[program, version];
FOR item: Item ← headers[index], item.next WHILE item # NIL DO
IF (item.entry.program = program) AND (item.entry.version = version) AND (item.entry.protocol = protocol) AND (item.entry.port = port)
THEN RETURN [FALSE];
ENDLOOP;
headers[index] ← NEW[ItemObject ← [headers[index], [program, version, protocol, port]]];
RETURN [TRUE];
};
Unset: PUBLIC SunPMap.UnsetProc -- [h: Handle, c: Conversation, program, version: CARD32] RETURNS [success: BOOL] -- ~ {
RETURN [UnsetLocal[program, version]];
};
UnsetLocal: PUBLIC ENTRY PROC [program, version: CARD32] RETURNS [success: BOOL] ~ {
prev, p: Item;
index: CARD ← Hash[program, version];
success ← FALSE;
prev ← NIL; p ← headers[index];
DO
IF p = NIL THEN RETURN;
IF (p.entry.program = program) AND (p.entry.version = version)
THEN {
success ← TRUE;
IF prev = NIL THEN headers[index] ← p.next ELSE prev.next ← p.next;
}
ELSE {
prev ← p;
};
p ← p.next;
ENDLOOP;
};
GetPort: PUBLIC SunPMap.GetPortProc -- [h: Handle, c: Conversation, program, version, protocol: CARD32] RETURNS [port: CARD32] -- ~ {
RETURN [GetPortLocal[program, version, protocol]];
};
GetPortLocal: PUBLIC ENTRY PROC [program, version, protocol: CARD32]
RETURNS [port: CARD32] ~ {
index: CARD ← Hash[program, version];
FOR item: Item ← headers[index], item.next WHILE item # NIL DO
IF (item.entry.program = program) AND (item.entry.version = version) AND (item.entry.protocol = protocol)
THEN RETURN [item.entry.port];
ENDLOOP;
RETURN [0];
};
Dump: PUBLIC SunPMap.DumpProc -- [h: Handle, c: Conversation, eachMapEntry: PROC[MapEntry]] -- ~ {
DumpLocal[eachMapEntry];
};
DumpLocal: PUBLIC PROC [eachMapEntry: PROC[MapEntry]] ~ {
It's okay to do this without holding the monitor lock because REF operations are atomic ...
FOR i: CARDINAL IN [0 .. tableSize) DO
FOR p: Item ← headers[i], p.next WHILE p # NIL DO
eachMapEntry[p.entry];
ENDLOOP;
ENDLOOP;
};
Callit: PUBLIC SunPMap.CallitProc -- [h: Handle, c: Conversation, program, version, proc: CARD32, args: REF TEXT] RETURNS [port: CARD32, result: REF TEXT] -- ~ {
gotError: BOOLFALSE;
[port, result] ← CallitLocal[program, version, proc, args, longTimeout, 0
! SunRPC.Error => { gotError ← TRUE; CONTINUE }];
IF gotError THEN ERROR SunRPC.Error[$abortWithoutReturn];
};
CallitLocal: PUBLIC PROC [program, version, proc: CARD32, args: REF TEXT, timeout: CARD, retries: CARD] RETURNS [port: CARD32, result: REF TEXT] ~ {
hLocal: Handle ← NIL;
conversation: Conversation ← NIL;
CleanUp: PROC ~ {
IF hLocal # NIL
THEN { SunRPC.Destroy[hLocal]; hLocal ← NIL };
IF conversation # NIL
THEN { SunRPCAuth.Terminate[conversation]; conversation ← NIL };
};
{ ENABLE UNWIND => CleanUp[];
bytes: CARDINAL;
port ← GetPortLocal[program, version, SunPMap.ipProtocolUDP];
IF port = 0 THEN ERROR SunRPC.Error[$serviceNotRegistered];
hLocal ← SunRPC.Create[remoteAddress~ArpaExtras.MyAddress[], remotePort~Basics.HFromCard16[port]];
conversation ← SunRPCAuth.Initiate[];
SunRPC.StartCall[hLocal, conversation, program, version, proc];
SunRPC.PutBlock[hLocal, args, 0, args.length];
[] ← SunRPC.SendCallAndReceiveReply[hLocal, timeout, retries];
bytes ← SunRPC.BytesRemaining[hLocal];
result ← RefText.New[bytes];
SunRPC.GetBlock[hLocal, result, 0, bytes];
};
CleanUp[];
};
}...