#!/bin/rc # prototype proof of concept timewarping rc script # needs a .sim file with siminit updatestate msgproc tickstate fns # usually launched by whatsit.rc cancels=() debug=() msgforme=no while (~ $1 -*){ switch($1){ case -c cancels=yes shift case -d debug=yes shift case * echo bad flag $1 shift } } if(! test -e $1){ echo no sim file found exit } . $1 # NOTE: many of these fields are not currently used fn parsemsg{ vrt=$msg(1) vst=$msg(2) rcvr=$msg(3) sndr=$msg(4) sign=$msg(5) gid=$msg(6) body=$msg(7-) } # this is a horribly inefficent function. not needed in hypercubic implementation fn cancelinq{ for(i in `{ls inq}){ chksign=`{cat $i} if(~ $chksign(5) neg){ for(j in `{ls inq}){ chkmatch=`{cat $j} if(~ $chkmatch(5) pos){ if(~ $chkmatch(6) $chksign(6)){ echo removing $i $j rm $i rm $j } } } } } } if(! test -e /tmp/$mynum){ mkdir /tmp/$mynum mkdir /tmp/$mynum/inq mkdir /tmp/$mynum/antiq } cd /tmp/$mynum rm state.* rm inq/* rm antiq/* dim=`{echo -n $mynum |wc -c} cvt=0 # call user supplied siminit fn to initialize $state and $sendout siminit echo $state >state.$cvt if(~ $#simend 0) simend=64 if(~ $#simlimit 0) simlimit=32 sleep 30 ### BEGIN MAIN LOOP - only exits when sim completes # enter sim loop "halfway" through first tick and send $sendout and save state while(test $cvt -lt $simend){ cvt=`{echo $cvt + 1 |hoc} port=`{echo $cvt - 1 |hoc} if(test $port -ge $dim) port=`{echo $port^' % '^$dim |hoc} if(test $cvt -gt $simlimit) port=$dim neighbor=`{hyper -id $port -f $mynum} outmsg=($cvt $cvt $neighbor $mynum pos $mynum.$cvt $sendout) antimsg=($cvt $cvt $neighbor $mynum neg $mynum.$cvt $sendout) prevmsg=`{cat antiq/$cvt >[2] /dev/null} if(~ $debug yes){ echo CVT $cvt STATE $state echo OUT $outmsg PREV $prevmsg } if(test $#prevmsg -gt 5){ if(! ~ $"antimsg $"prevmsg){ echo $prevmsg >>/n/cube/$port echo $outmsg >>/n/cube/$port echo $antimsg >antiq/$cvt } } if(! test $#prevmsg -gt 5){ echo $outmsg >>/n/cube/$port echo $antimsg >antiq/$cvt } echo $state >state.$cvt # messages have been sent and state saved. # wait for message and check if it is for us, pass it on if not while(~ $msgforme no){ if(~ $debug yes) echo MSG $msg msg=`{read} if(test $#msg -gt 5){ if(~ $msg(3) $mynum) msgforme=yes if not{ route=`{hyper -pno -d $dim -f $mynum -t $msg(3)} if(! ~ $#route 0){ echo wormhole msg for $msg(3) to $route echo $msg >>/n/cube/$route } } } if(test $#msg -lt 5) msgforme=yes } msgforme=no # message is for us. check its time and rollback if needed if(test $#msg -gt 5){ parsemsg echo $msg >inq/$vrt if(test $vrt -lt $cvt){ if(~ $debug yes) echo ROLLBACK to $vrt cvt=$vrt if(test -e state.$cvt) state=`{cat state.$cvt >[2] /dev/null} } if(~ $cancels yes) cancelinq } # call user updatestate, then msgproc if this tick has msg, then tickstate updatestate if(test -e inq/$cvt){ msg=`{cat inq/$cvt >[2] /dev/null} if(~ $debug yes) echo INQ $cvt $msg parsemsg if(~ $sign pos) msgproc } tickstate } # when we loop here, we have set up the $state and $sendout vars but not saved or sent them # the sequence each tick is as follows # BEGIN at cvt 0 # increment cvt and set message port # compare outmsg and any saved antimsg and dispatch as dictated by Time Warp algo # save state # block waiting for next message # check if received message is for us and pass it on if not # rollback if needed, initialize $state and call user updatestate() # process message unless its just a STEP tick by calling user msgproc() # finalize $state and $outmsg with user tickstate() # END at cvt $simend # no changes in state occur after cvt $simlimit