DIRECTORY CrRPC USING [Handle, PutArgsProc], Rope USING [ROPE], CourierBinding USING [Address, Predicate, Range, Registration, RegistrationObject], CourierBindingProtocol USING [program, version, socket]; CourierBindingServerImpl: CEDAR MONITOR EXPORTS CourierBinding ~ { Address: TYPE ~ CourierBinding.Address; Handle: TYPE ~ CrRPC.Handle; Predicate: TYPE ~ CourierBinding.Predicate; PutArgsProc: TYPE ~ CrRPC.PutArgsProc; Range: TYPE ~ CourierBinding.Range; Registration: TYPE ~ CourierBinding.Registration; RegistrationObject: TYPE ~ CourierBinding.RegistrationObject; ROPE: TYPE ~ Rope.ROPE; RegistrationList: TYPE ~ LIST OF Registration; registered: RegistrationList; Intersect: PROC [a, b: Range]RETURNS [Range] ~ INLINE { RETURN[[MAX[a.lowVersion, b.lowVersion], MIN[a.highVersion, b.highVersion]]]; }; LegalRange: PROC [r: Range] RETURNS [BOOLEAN] ~ INLINE { RETURN[r.lowVersion <= r.highVersion]; }; Error: ERROR[r: ROPE] ~ CODE; RaiseError: PROC [r: ROPE] ~ { Error[r] }; Compare: PROC [i, j: Registration] RETURNS [x: {less, equal, greater}] ~ { SELECT TRUE FROM (i.program < j.program) => { RETURN [less]; }; (i.program = j.program) => { SELECT TRUE FROM (i.range.lowVersion < j.range.lowVersion) => { RETURN [less]; }; (i.range.lowVersion = j.range.lowVersion) => { SELECT TRUE FROM (i.range.highVersion < j.range.highVersion) => { RETURN [less]; }; (i.range.highVersion = j.range.highVersion) => { RETURN [equal]; }; ENDCASE => { RETURN [greater]; }; }; ENDCASE => { RETURN [greater]; }; }; ENDCASE => { RETURN [greater]; }; }; InsertInternal: INTERNAL PROC [n: Registration] ~ { g: RegistrationList; IF (registered = NIL) OR (Compare[n, registered.first] = greater) THEN { registered _ CONS[n, registered]; RETURN; }; FOR g _ registered, g.rest UNTIL (g.rest = NIL) DO SELECT Compare[g.rest.first, n] FROM less => { NULL; }; equal => { RaiseError["Abort to smash old Registration" ! ABORTED => { g.rest _ CONS[n, g.rest]; CONTINUE; } ]; }; ENDCASE => { g.rest _ CONS[n, g.rest]; }; ENDLOOP; g.rest _ CONS[n, NIL]; }; Locate: INTERNAL PROC [program: CARD, version: CARDINAL] ~ { }; RemoveInternal: INTERNAL PROC [n: Registration] ~ { g: RegistrationList; IF (registered = NIL) THEN ERROR; IF (Compare[n, registered.first] = equal) THEN { registered _ registered.rest; RETURN; }; FOR g _ registered, g.rest UNTIL (g.rest = NIL) DO SELECT Compare[g.rest.first, n] FROM less => { NULL; }; equal => { g _ g.rest; }; ENDCASE => { ERROR; -- not here! }; ENDLOOP; ERROR; }; Dispatcher: PROC [h: Handle, program: CARD, version: CARDINAL] ~ { }; Init: PROC ~ { }; Register: PUBLIC ENTRY PROC [program: CARD, range: Range, predicate: Predicate, clientData: REF] RETURNS [r: Registration] ~ { ENABLE UNWIND => NULL; r _ NEW [RegistrationObject _ [clientData, predicate, program, range]]; InsertInternal[r]; }; UnRegister: PUBLIC ENTRY PROC [r: Registration] ~ { ENABLE UNWIND => NULL; RemoveInternal[r]; }; Init[]; }... ΈCourierBindingServerImpl.mesa Copyright (C) 1985, 1986 by Xerox Corporation. All rights reserved. kam 17-Jan-86 11:14:30 Bill Jackson (bj) June 23, 1986 1:50:48 am PDT Copied Types Types Global State (Monitored) Inline Procs Error Routines RegistrationList Procs this should be illegal New Head New Internal Node (trick is that g.first is already less) this is pretty nasty! What if (when!) they collide? New Tail Delete Head Delete Internal Node (trick is that g.first is already less) Reached Tail Dispatcher & Worker Bees token: Server _ CreateServer[$EXCHANGE, program, [version, version], socket, Dispatcher]; StartListener[]; Funny Procs MaybeSendReply: PROC [b: Buffer.NSBuffer, trans: CARDINAL, program: LONG CARDINAL, sH: Stream.Handle] ~ { intersection: Courier.VersionRange _ Exports[program, sH]; IF LegalRange[intersection] THEN { msg: REF return CourierBindingProtocol.Message _ LOOPHOLE[@b.ns.exchangeBody]; Socket.SwapSourceAndDestination[b]; Socket.SetPacketWords[b, CourierBindingProtocol.sizeReply]; msg^ _ [ range, return[ transaction: trans, response: [versions: intersection, me: Courier.LocalSystemElement[]]]]; Socket.PutPacket[ch, b] } ELSE Socket.ReturnBuffer[b]; }; SendErrorReply: PROC [b: Buffer.NSBuffer, type: CourierProtocol.RejectCode, trans: CARDINAL] ~ { msg: REF reject CourierBindingProtocol.Message _ LOOPHOLE[@b.ns.exchangeBody]; IF HostNumbers.IsMulticastID[LOOPHOLE[@b.ns.destination.host]] THEN { Socket.ReturnBuffer[b]; RETURN }; Socket.SwapSourceAndDestination[b]; msg^ _ [protRange: range, body: reject[transaction: trans, rejectBody:]]; SELECT type FROM noSuchProgramNumber => { msg.rejectBody _ noSuchProgramNumber[]; Socket.SetPacketWords[ b, CourierBindingProtocol.pexOverhead + SIZE[ noSuchProgramNumber reject CourierBindingProtocol.Message]]}; noSuchProcedureValue => { msg.rejectBody _ noSuchProcedureValue[]; Socket.SetPacketWords[ b, CourierBindingProtocol.pexOverhead + SIZE[ noSuchProcedureValue reject CourierBindingProtocol.Message]]}; invalidArguments => { msg.rejectBody _ invalidArguments[]; Socket.SetPacketWords[ b, CourierBindingProtocol.pexOverhead + SIZE[ invalidArguments reject CourierBindingProtocol.Message]]}; noSuchVersionNumber => { msg.rejectBody _ noSuchVersionNumber[ [CourierBindingProtocol.version, CourierBindingProtocol.version]]; Socket.SetPacketWords[ b, CourierBindingProtocol.pexOverhead + SIZE[ noSuchVersionNumber reject CourierBindingProtocol.Message]]}; ENDCASE; Socket.PutPacket[ch, b]; }; StartListener: PROC ~ { Socket.SetWaitTime[(ch _ Socket.Create[CourierBindingProtocol.socket]), Socket.WaitTime.LAST]; Process.Detach[FORK Watcher[]]; }; Watcher: PROC ~ { DO ENABLE ABORTED => EXIT; b _ Socket.GetPacket[ch]; h _ LOOPHOLE[@b.ns.exchangeBody]; WITH messageBody: h^ SELECT FROM call => SELECT TRUE FROM messageBody.program # CourierInternal.ExchWords[ CourierBindingProtocol.program] AND messageBody.program # CourierInternal.ExchWords[ CourierBindingProtocol.oldProgram] => SendErrorReply[b, noSuchProgramNumber, messageBody.transaction]; messageBody.procedure # CourierBindingProtocol.procedure => SendErrorReply[b, noSuchProcedureValue, messageBody.transaction]; messageBody.version # CourierBindingProtocol.version => SendErrorReply[b, noSuchVersionNumber, messageBody.transaction]; ENDCASE => { block: Environment.Block _ [ LOOPHOLE[@messageBody.request], 0, Socket.GetPacketBytes[b] - (CourierBindingProtocol.pexOverhead + CourierBindingProtocol.callOverhead) * Environment.bytesPerWord ]; sH: Stream.Handle _ MemoryStream.Create[block]; MaybeSendReply[b, messageBody.transaction, CourierInternal.ExchWords[messageBody.request.program], sH]; MemoryStream.Destroy[sH]; }; ENDCASE => Socket.ReturnBuffer[b]; ENDLOOP; }; Entry Procs Exports: ENTRY PROC [program: LONG CARDINAL, sH: Stream.Handle] RETURNS [exported: Courier.VersionRange _ [1, 0]] ~ { ENABLE UNWIND => NULL; Description: Courier.Description ~ { data: REF ArgRecord _ notes.noteSize[SIZE[ArgRecord]]; notes.noteLongCardinal[@data.program]; notes.noteDisjointData[@data.user, (IF reg = NIL OR argProblem THEN NIL ELSE reg.description)]; }; arg: ArgRecord; argProblem: BOOLEAN _ FALSE; exports: REF Courier.Exports _ Courier.EnumerateExports[]; i: CARDINAL; reg: REF Registered _ registered; UNTIL ((reg = NIL) OR (reg.program = program)) DO reg _ reg.next ENDLOOP; Courier.DeserializeParameters[[@arg, Description], sH ! Courier.Error => {argProblem _ TRUE; CONTINUE}]; FOR i IN [0..exports.LENGTH) DO IF (exports[i].programNumber = program) AND LegalRange[(exported _ Intersect[arg.range, exports[i].versionRange])] AND(argProblem OR (reg = NIL) OR (reg.predicate = NIL) OR reg.predicate[program, exported, arg.user]) THEN { EXIT; }; REPEAT FINISHED => { exported _ [1, 0]; }; ENDLOOP; }; Κ 2˜šœ™JšœD™DJšœ&™&Icode™.—J˜šΟk ˜ Jšœœ˜"Jšœœœ˜Jšœœ?˜SJš œœΟnœžœΟbœ˜8—J˜šžœœ˜'Jšœ˜—J˜šœ ™ J™Jšœ œ˜'Jšœœ˜Jšœ œ˜+Jšœ œ˜&Jšœœ˜#Jšœœ˜1Jšœœ%˜=Jšœœœ˜J˜—šœ™J™Jšœœœœ˜.J˜—šœ™J™Jšœ˜J˜—šœ ™ J˜šž œœœ œ˜7Jšœœœ!˜MJšœ˜J˜—š ž œœ œœœ˜8Jšœ ˜&Jšœ˜—J™—šœ™J˜šžœœœœ˜J˜—šž œœœ˜J˜Jšœ˜—J™—šœ™J˜šžœœœ ˜Jšœœ˜˜Jšœ˜Jšœ˜—˜šœœ˜šœ.˜.Jšœ˜Jšœ˜—šœ.˜.Jšœ™šœœ˜šœ0˜0Jšœ˜Jšœ˜—šœ0˜0Jšœ ˜J˜—šœ˜ Jšœ ˜J˜——J˜—šœ˜ Jšœ ˜J˜——J˜—šœ˜ Jšœ ˜J˜——šœ˜J˜——šžœœœ˜3šœ˜J˜—šœ™J˜šœœœ*œ˜HJšœ œ˜!Jšœ˜Jšœ˜J˜——šœ9™9J˜šœœ œ˜2Jšœ˜$šœ ˜ Jšœ˜Jšœ˜J˜—šœ ˜ Jšœ4™4šœ,˜,šœœ˜Jšœ œ ˜Jšœ˜ Jšœ˜—Jšœ˜—Jšœ˜—J˜šœ˜ Jšœ œ ˜J˜—Jšœ˜J˜——šœ™J˜Jšœ œœ˜—Jšœ˜J˜—š žœœœ œ œ˜———™J™$™J™šœ%œ™*J™:———™™%J™B—™J™šœ%œ™*J™=———Jšœ™—J™Jšœ™J™—šž œœ™JšœXœ™^Jšœœ ™Jšœ™J™—šžœœ™š™Jšœœœ™J™Jšœœ™!šœœ™ ™šœœ™™0Jšœ ™#™0J™%—J™@—™;J™A—™7J™@—šœ™ ™Jšœ™Jšœ™J™€J™—J™/J™gJ™Jšœ™———Jšœ™"—Jšœ™—Jšœ™—J™—šœ ™ J™Jš žœœœ œœœ.™ušœœœ™J™šž œ™$Jšœœœ ™6J™&Jš œ$œœœ œœœ™_Jšœ™J™—J™Jšœ œœ™Jšœ œ.™:Jšœœ™ šœœ™!J™—Jš œœœœœœ™I™5Jšœ!œœ™2—šœœ œ™šœ%™'JšœG™JJšœ œœœœœœ-œ™lJšœ™J™—š™Jšœ™#—Jšœ™—Jšœ™J™—J˜šžœœœœ œ2œœ˜~Jšœœœ˜Jšœœ@˜GJšœ˜Jšœ˜J˜—šž œœœœ˜3Jšœœœ˜Jšœ˜Jšœ˜——J˜J˜J˜šœ˜J˜J˜J˜—J˜—…— –(€