{- Distributed Events; runs on 1 to 2+ machines. Imagine a formal hall dinner. Due to security reasons, we want to know about all people who came to a dinner late (i.e. after a gong), missed speech, but had a toast following the speech. Specify your machines in config file, the first machine should be used to compile and execute hallevent.pi. Usage: start np on remote machines, np hallevent.pi on current machine. Note: if IP address of some machine appears in config more than once (with different port numbers) then you may need to execute np on that machine with an option -p to specify which port number shall be used. -} import "Events/Event" {- Some event types. -} type ActiveBadge = [room=String name=String] type Video = String {- Define event channels. -} new gong : ^(Event Int) new badge : ^(Event ActiveBadge) new speech : ^(Event Video) new toast : ^(Event Video) program param : []= ( {- Create some event server. -} val t = 1 {- delay of event collection from distributed sources [sec.] -} val server = (event.engine (sys.get_site 0) t) agent securityGuard = ( {- This agent wants to know only about suspects. -} val site = (sys.get_site 0) val this = (event.address securityGuard site) migrate to site def print (t:Time n:Int v:[[Int ActiveBadge] String]) : [] = (val [[gong badge] toast]= v (prNL (+$ "TIME:" (+$ (int.toString t) (+$ " NAME:" (+$ badge.name (+$ " TOAST:" toast))))))) {- create composite event channels -} val latecomer = (event.followby_ gong badge server this) val toast_latecomer = (event._followbywithout latecomer toast speech server this) agent securityGuard2 = ( {- This agent wants to know about all latecomers. -} val place2 = (sys.get_site 1) migrate to place2 {- it has just moved to place 2 -} def print (t:Time n:Int v:[Int ActiveBadge]) : [] = (val [_ badge] = v (prNL (+$ "TIME:" (+$ (int.toString t) (+$ " NAME:" badge.name))))) {- register an event channel, listen to the channel and print events -} ( event.register![latecomer server (event.address securityGuard2 place2)] | latecomer ?* e = ((event.pr e print); ())) ) {- listen to channels and print events -} (latecomer ?* e = () | toast_latecomer ?* e = ((event.pr e print); ())) ) {- Create and spawn event sources. -} agent activeBadgeSource = ( {- declare event types -} event.declare![badge server] {- create events and notify the server -} | event.submit![1 badge [room="Hall" name="Richard"] server] | event.submit![3 badge [room="Hall" name="Luisa"] server] | event.submit![5 badge [room="Hall" name="President"] server] | event.submit![11 badge [room="Hall" name="Bursar"] server] | event.submit![12 badge [room="Hall" name="Pawel"] server] | event.submit![16 badge [room="Hall" name="Snoopy"] server] ) agent videoRecorderSource = ( {- declare event types -} event.declare![gong server] | event.declare![toast server] | event.declare![speech server] {- create events and notify the server -} | event.submit![4 gong 0 server] | event.submit![7 speech "Benedictus, Benedicti." server] | event.submit![2 toast "Cheers Everybody!" server] | event.submit![10 toast "Cheers President!" server] | event.submit![14 toast "Cheers latecomers!" server]) ()) {- Encode ordered event notification delivery. -} {toplevel P prog_param }^Int = (new counter : ^Int run counter!0 { P }counter) { agent a=P in Q }counter = (agent A = (val !a = A new counter : ^Int run counter!0 {P}counter) in {Q}counter) { c?*w=P }counter = {- order events at client -} c?*p= counter?i = (val !w = p if (== i (event.number {{w}})) then (counter!(inc i) | {P}counter) else (counter!i | c!{{w}})) {- The SecurityGuard reports: TIME:14 NAME:Pawel TOAST:Cheers latecomers! TIME:14 NAME:Bursar TOAST:Cheers latecomers! The SecurityGuard2 reports: TIME:5 NAME:President TIME:11 NAME:Bursar TIME:12 NAME:Pawel TIME:16 NAME:Snoopy -}