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 ~ { tableSize: CARDINAL ~ 31; longTimeout: CARD _ 5000; Address: TYPE ~ Arpa.Address; Handle: TYPE ~ SunRPC.Handle; Conversation: TYPE ~ SunRPCAuth.Conversation; MapEntry: TYPE ~ SunPMap.MapEntry; 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]; }; 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]] ~ { 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 _ 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[]; }; }... SunPMapServerImpl.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. Demers, November 4, 1987 11:47:53 am PST Parameters Types Map Procedures It's okay to do this without holding the monitor lock because REF operations are atomic ... ΚΒ˜code™K™šœ œ œ"œ˜†Kšœœœ˜—Kšœ˜—KšœœD˜XKšœœ˜K˜K˜—šžœœŸTœ˜xKšœ ˜&K˜K˜—šž œœœœœœ œ˜TK˜Kšœœ˜%Kšœ œ˜Kšœœ˜š˜Kšœœœœ˜šœœ˜>šœ˜Kšœ œ˜Kšœœœœ˜CK˜—šœ˜K˜ K˜——K˜ Kšœ˜—K˜K˜—šžœœŸ]œ˜…Jšœ,˜2K˜K˜—šž œœœœœœœ˜_Kšœœ˜%šœ(œœ˜>šœ œ œ!˜iKšœœ˜—Kšœ˜—Kšœ˜ K˜K˜—šžœœŸ@œ˜bJšœ˜K˜K˜—šž œœœœ˜9K™[šœœœ˜&šœœœ˜1Kšœ˜Kšœ˜—Kšœ˜—K˜K˜—šžœœŸ{œ˜‘Jšœ œœ˜Kšœiœœ˜{Kšœ œœ#˜9K˜K˜—šž œœœœœœ œ œœœ œœ˜”Kšœœ˜Kšœœ˜!šžœœ˜Kšœ œœ$œ˜>Kšœœœ6œ˜VK˜—K˜šœœœ˜Kšœœ˜Kšœ=˜=Kšœ œœ%˜;Kšœb˜bK˜%Kšœ?˜?Kšœ.˜.Kšœ>˜>Kšœ&˜&Kšœ˜Kšœ*˜*K˜—J˜ K˜K˜——K˜—J˜—…—"δ