SunPMapServerImpl.mesa
Copyright Ó 1987, 1991, 1992 by Xerox Corporation. All rights reserved.
Demers, November 4, 1987 11:47:53 am PST
Willie-s, August 21, 1991 12:40 pm PDT
Chauser, January 3, 1992 10:57 am PST
DIRECTORY
Arpa USING [Address, MyAddress],
Basics USING [HFromCard16],
RefText USING [New],
SunPMap USING [CallitProc, DumpProc, GetPortProc, ipProtocolUDP, MapEntry, NullProc, SetProc, UnsetProc],
SunPMapLocal USING [],
SunPMapServer USING [],
SunRPC USING [BytesRemaining, Destroy, Error, GetBlock, Handle, PutBlock, SendCallAndReceiveReply, StartCall],
SunRPCOnUDP USING [Create],
SunRPCAuth USING [Conversation, Initiate, Terminate]
;
SunPMapServerImpl: CEDAR MONITOR
IMPORTS Arpa, Basics, RefText, SunRPC, SunRPCOnUDP, 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: BOOL ¬ FALSE;
[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 ¬ SunRPCOnUDP.Create[remoteAddress~Arpa.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[];
};
}...