func test_StrId() { rout := router.New(router.StrID(), 32, router.BroadcastPolicy) chi1 := make(chan string) chi2 := make(chan string) cho := make(chan string) done := make(chan bool) rout.AttachSendChan(router.StrID("test"), cho) rout.AttachRecvChan(router.StrID("test"), chi1) rout.AttachRecvChan(router.StrID("test"), chi2) go func() { cho <- "hello" cho <- "from StrID" close(cho) }() go func() { for v := range chi1 { fmt.Println("StrId/sink1 got: ", v) } done <- true }() go func() { for v := range chi2 { fmt.Println("StrId/sink2 got: ", v) } done <- true }() <-done <-done }
func (dt *DbTask) handleCmd(cmd string) bool { cont := true svcname := "" idx := strings.Index(cmd, ":") if idx > 0 { svcname = cmd[idx+1:] cmd = cmd[0:idx] } switch cmd { case "Start": dt.numTrans = 0 dt.role = Active case "Stop": dt.role = Standby case "Shutdown": cont = false case "AddService": if len(svcname) > 0 { ch := make(chan string) dt.dbRespChans[svcname] = ch dt.rot.AttachSendChan(router.StrID("/DB/Response/App/"+svcname), ch) } case "DelService": if len(svcname) > 0 { ch, ok := dt.dbRespChans[svcname] if ok { delete(dt.dbRespChans, svcname) dt.rot.DetachChan(router.StrID("/DB/Response/App/"+svcname), ch) } } default: } return cont }
func main() { flag.Parse() if flag.NArg() < 1 { fmt.Println("Usage: game6 num_runs hideTrace") return } else if flag.NArg() > 1 { showPingPong = false } numRuns, _ := strconv.Atoi(flag.Arg(0)) c0, c1 := net.Pipe() done := make(chan bool) //create router and connect it to io conn rot1 := router.New(router.StrID(), 32, router.BroadcastPolicy) go rot1.ConnectRemote(c0, router.GobMarshaling, router.XOnOffFlowController) //hook up Pinger and Ponger newPinger(rot1, done, numRuns) //create router and connect it to io conn rot2 := router.New(router.StrID(), 32, router.BroadcastPolicy) rot2.ConnectRemote(c1, router.GobMarshaling, router.XOnOffFlowController) //hook up Ponger newPonger(rot2, done) //wait for ping-pong to finish <-done <-done }
func (ft *FaultMgrTask) handleCmd(cmd string) bool { cont := true svcname := "" idx := strings.Index(cmd, ":") if idx > 0 { svcname = cmd[idx+1:] cmd = cmd[0:idx] } switch cmd { case "Start": ft.role = Active case "Stop": ft.role = Standby case "Shutdown": cont = false case "AddService": if len(svcname) > 0 { ch := make(chan string) ft.svcCmdChans[svcname] = ch ft.rot.AttachSendChan(router.StrID("/Fault/Command/App/"+svcname), ch) } case "DelService": if len(svcname) > 0 { ch, ok := ft.svcCmdChans[svcname] if ok { delete(ft.svcCmdChans, svcname) ft.rot.DetachChan(router.StrID("/Fault/Command/App/"+svcname), ch) } } default: } return cont }
func (smt *SysMgrTask) init(r router.Router, n string, role ServantRole) { smt.rot = r smt.name = n smt.role = role smt.htbtSendChan = make(chan time.Time) smt.htbtRecvChan = make(chan time.Time) smt.sysCmdChan = make(chan string) smt.sysOOSChan = make(chan string) smt.childBindChan = make(chan *router.BindEvent, 1) smt.startChan = make(chan bool, 1) smt.stopChan = make(chan bool, 1) smt.exitChanMap = make(map[string]chan bool) //output_intf or send chans smt.rot.AttachSendChan(router.StrID("/Sys/Command"), smt.sysCmdChan, smt.childBindChan) smt.rot.AttachSendChan(router.StrID("/Sys/Ctrl/Heartbeat", router.ScopeRemote), smt.htbtSendChan) //input_intf or recv chans smt.rot.AttachRecvChan(router.StrID("/Sys/Ctrl/Heartbeat", router.ScopeRemote), smt.htbtRecvChan) smt.rot.AttachRecvChan(router.StrID("/Sys/OutOfService"), smt.sysOOSChan) // smt.rmtPubChan = make(chan *router.ChanInfoMsg) smt.rmtUnpubChan = make(chan *router.ChanInfoMsg) smt.locUnpubChan = make(chan *router.ChanInfoMsg) //use pubBindChan/unpubBindChan when attaching chans to PubId/UnPubId, so that they will not be //closed when all clients close and leave smt.pubBindChan = make(chan *router.BindEvent, 1) smt.unpubBindChan = make(chan *router.BindEvent, 1) smt.rot.AttachRecvChan(smt.rot.NewSysID(router.PubId, router.ScopeRemote), smt.rmtPubChan, smt.pubBindChan) smt.rot.AttachRecvChan(smt.rot.NewSysID(router.UnPubId, router.ScopeRemote), smt.rmtUnpubChan, smt.unpubBindChan) smt.rot.AttachRecvChan(smt.rot.NewSysID(router.UnPubId, router.ScopeLocal), smt.locUnpubChan) }
func test_notification() { rout := router.New(router.StrID(), 32, router.BroadcastPolicy) chi1 := make(chan string) chi2 := make(chan string) chiN := make(chan *router.ChanInfoMsg) cho := make(chan string) bound := make(chan *router.BindEvent, 1) done := make(chan bool) //subscribe to recver attach events rout.AttachRecvChan(rout.SysID(router.SubId), chiN) // rout.AttachSendChan(router.StrID("test"), cho, bound) rout.AttachRecvChan(router.StrID("test"), chi1) rout.AttachRecvChan(router.StrID("test"), chi2) //wait for two recvers to connect for { if (<-bound).Count == 2 { break } } go func() { cho <- "hello1" cho <- "hello2" cho <- "hello3" cho <- "from notif" close(cho) }() go func() { for v := range chi1 { fmt.Println("notif/sink1 got: ", v) } done <- true }() go func() { for v := range chi2 { fmt.Println("notif/sink2 got: ", v) rout.DetachChan(router.StrID("test"), chi2) } done <- true }() go func() { count := 0 for m := range chiN { for _, v := range m.Info { fmt.Println("got sub notif: ", v.Id) } count++ if count >= 2 { break } } done <- true }() <-done <-done <-done rout.Close() }
func (c *Chatter) Leave(s string) { subj, ok := c.subjectMap[s] if !ok { return } delete(c.subjectMap, s) c.r.DetachChan(router.StrID(s, router.ScopeRemote), subj.recvChan) c.r.DetachChan(router.StrID(s, router.ScopeRemote), subj.sendChan) }
func main() { flag.Parse() if flag.NArg() < 2 { fmt.Println("Usage: client ServiceName numRuns") return } svcName := flag.Arg(0) numRuns, _ := strconv.Atoi(flag.Arg(1)) conn1, _ := net.Dial("unix", ServantAddr1) fmt.Println("conn to servant1 up") conn2, _ := net.Dial("unix", ServantAddr2) fmt.Println("conn to servant2 up") //create router and connect it to both active and standby servants rot := router.New(router.StrID(), 32, router.BroadcastPolicy /* , "cli", router.ScopeLocal*/) proxy1 := router.NewProxy(rot, "proxy1", nil, nil) proxy2 := router.NewProxy(rot, "proxy2", nil, nil) proxy1.ConnectRemote(conn1, router.GobMarshaling, router.XOnOffFlowController) proxy2.ConnectRemote(conn2, router.GobMarshaling, router.XOnOffFlowController) reqChan := make(chan string) rspChan := make(chan string) bindChan := make(chan *router.BindEvent, 1) rot.AttachSendChan(router.StrID("/App/"+svcName+"/Request"), reqChan, bindChan) rot.AttachRecvChan(router.StrID("/App/"+svcName+"/Response"), rspChan) //make sure client connect to 2 servants before sending requests for { if (<-bindChan).Count > 1 { break } } cont := true for i := 0; i < numRuns && cont; i++ { req := fmt.Sprintf("request %d", i) fmt.Printf("client sent request [%s] to serivce [%s]\n", req, svcName) reqChan <- req timer := time.NewTimer(6e8) //the wait for response will time out in less than 1 sec select { case rsp, chOpen := <-rspChan: if !chOpen { fmt.Println("client response closed, exit") cont = false } else { fmt.Printf("client recv response ( %s )\n", rsp) } case <-timer.C: fmt.Printf("time out for reqest [%s]\n", req) i-- //resend it } timer.Stop() } fmt.Printf("client exit\n") conn1.Close() conn2.Close() rot.Close() }
func (ft *FaultMgrTask) shutdown() { for k, v := range ft.svcCmdChans { ft.rot.DetachChan(router.StrID("/Fault/Command/App/"+k), v) } ft.rot.DetachChan(router.StrID("/Sys/OutOfService"), ft.sysOOSChan) ft.rot.DetachChan(router.StrID("/Fault/DB/Exception"), ft.faultReportChan) ft.rot.DetachChan(router.StrID("/Fault/AppService/Exception"), ft.faultReportChan) ft.rot.DetachChan(router.StrID("/Sys/Command"), ft.sysCmdChan) }
func newPonger(rot router.Router, done chan<- bool) { //attach chans to router pingChan := make(chan Msg) pongChan := make(chan Msg) rot.AttachSendChan(router.StrID("pong"), pongChan) rot.AttachRecvChan(router.StrID("ping"), pingChan) //start ponger pong := &Ponger{pongChan, pingChan, done} go pong.Run() }
func newPinger(rot router.Router, done chan<- bool, numRuns int) { //attach chans to router pingChan := make(chan *Msg) pongChan := make(chan *Msg) rot.AttachSendChan(router.StrID("ping"), pingChan) rot.AttachRecvChan(router.StrID("pong"), pongChan) //start pinger ping := &Pinger{pingChan, pongChan, done, numRuns} go ping.Run() }
func (dt *DbTask) shutdown() { //output_intf or send chans dt.FaultRaiser.Close() for k, v := range dt.dbRespChans { dt.rot.DetachChan(router.StrID("/DB/Response/App/"+k), v) } //input_intf or recv chans dt.rot.DetachChan(router.StrID("/Sys/Command"), dt.sysCmdChan) dt.rot.DetachChan(router.StrID("/DB/Request"), dt.dbReqChan) }
func (smt *SysMgrTask) shutdown() { //output_intf or send chans smt.rot.DetachChan(router.StrID("/Sys/Command"), smt.sysCmdChan) smt.rot.DetachChan(router.StrID("/Sys/Ctrl/Heartbeat", router.ScopeRemote), smt.htbtSendChan) //input_intf or recv chans smt.rot.DetachChan(router.StrID("/Sys/Ctrl/Heartbeat", router.ScopeRemote), smt.htbtRecvChan) smt.rot.DetachChan(router.StrID("/Sys/OutOfService"), smt.sysOOSChan) // smt.rot.DetachChan(smt.rot.NewSysID(router.PubId, router.ScopeRemote), smt.rmtPubChan) smt.rot.DetachChan(smt.rot.NewSysID(router.UnPubId, router.ScopeRemote), smt.rmtUnpubChan) smt.rot.DetachChan(smt.rot.NewSysID(router.UnPubId, router.ScopeLocal), smt.locUnpubChan) }
func main() { flag.Parse() if flag.NArg() < 1 { fmt.Println("Usage: game4 num_runs hideTrace") return } else if flag.NArg() > 1 { showPingPong = false } //clean up test sock addr := "/tmp/pingpong.test" os.Remove(addr) // numRuns, _ := strconv.Atoi(flag.Arg(0)) done := make(chan bool) connNow := make(chan bool) //start two goroutines to setup a unix sock connection //connect two routers thru unix sock //and then hook up Pinger and Ponger to the routers go func() { //setup Pinger sock conn //wait for ponger up <-connNow //set up an io conn to ponger thru unix sock addr := "/tmp/pingpong.test" conn, _ := net.Dial("unix", addr) fmt.Println("ping conn up") //create router and connect it to io conn rot := router.New(router.StrID(), 32, router.BroadcastPolicy /*, "pinger", router.ScopeLocal*/) rot.ConnectRemote(conn, router.JsonMarshaling) //hook up Pinger and Ponger newPinger(rot, done, numRuns) }() go func() { //setup Ponger sock conn //wait to set up an io conn thru unix sock l, _ := net.Listen("unix", addr) connNow <- true //notify pinger that ponger's ready to accept conn, _ := l.Accept() fmt.Println("pong conn up") //create router and connect it to io conn rot := router.New(router.StrID(), 32, router.BroadcastPolicy /*, "ponger", router.ScopeLocal*/) rot.ConnectRemote(conn, router.JsonMarshaling) //hook up Ponger newPonger(rot, done) }() //wait for ping-pong to finish <-done <-done }
func (ft *FaultMgrTask) init(r router.Router, sn string, role ServantRole) { ft.rot = r ft.role = role ft.servName = sn ft.svcCmdChans = make(map[string](chan string)) ft.sysOOSChan = make(chan string) ft.faultReportChan = make(chan *router.FaultRecord) ft.sysCmdChan = make(chan string) ft.rot.AttachSendChan(router.StrID("/Sys/OutOfService"), ft.sysOOSChan) ft.rot.AttachRecvChan(router.StrID("/Sys/Command"), ft.sysCmdChan) //use a bindChan to keep faultReportChan open when all clients exit bc := make(chan *router.BindEvent, 1) ft.rot.AttachRecvChan(router.StrID("/Fault/DB/Exception"), ft.faultReportChan, bc) ft.rot.AttachRecvChan(router.StrID("/Fault/AppService/Exception"), ft.faultReportChan, bc) }
func (dt *DbTask) init(r router.Router, sn string, role ServantRole) { dt.rot = r dt.role = role dt.servName = sn dt.random = rand.New(rand.NewSource(time.Now().UnixNano())) dt.dbRespChans = make(map[string](chan string)) dt.dbReqChan = make(chan *DbReq) dt.sysCmdChan = make(chan string) //output_intf or send chans dt.FaultRaiser = router.NewFaultRaiser(router.StrID("/Fault/DB/Exception"), r, "DbTask") //input_intf or recv chans r.AttachRecvChan(router.StrID("/Sys/Command"), dt.sysCmdChan) //use a bindChan to keep dbReqChan open when all clients detach & exit bc := make(chan *router.BindEvent, 1) r.AttachRecvChan(router.StrID("/DB/Request"), dt.dbReqChan, bc) }
func main() { flag.Parse() if flag.NArg() < 1 { fmt.Println("Usage: game5 num_runs hideTrace") return } else if flag.NArg() > 1 { showPingPong = false } numRuns, _ := strconv.Atoi(flag.Arg(0)) done := make(chan bool) connNow := make(chan bool) //start two goroutines to setup a unix sock connection //connect two routers thru unix sock //and then hook up Pinger and Ponger to the routers go func() { //setup Pinger sock conn //wait for ponger up <-connNow //set up an io conn to ponger thru tcp sock conn, _ := net.Dial("tcp", "[::]:9099") fmt.Println("ping conn up") //create router and connect it to io conn rot := router.New(router.StrID(), 32, router.BroadcastPolicy) rot.ConnectRemote(conn, router.GobMarshaling, router.XOnOffFlowController) //hook up Pinger and Ponger newPinger(rot, done, numRuns) }() go func() { //setup Ponger sock conn //wait to set up an io conn thru tcp sock l, _ := net.Listen("tcp", ":9099") connNow <- true //notify pinger that ponger's ready to accept conn, _ := l.Accept() fmt.Println("pong conn up") //create router and connect it to io conn rot := router.New(router.StrID(), 32, router.BroadcastPolicy) rot.ConnectRemote(conn, router.GobMarshaling, router.XOnOffFlowController) //hook up Ponger newPonger(rot, done) }() //wait for ping-pong to finish <-done <-done }
func main() { flag.Parse() if flag.NArg() < 3 { fmt.Println("Usage: chatcli chatter_name srv_name srv_port") return } myName := flag.Arg(0) srvName := flag.Arg(1) srvPort := flag.Arg(2) dialaddr := srvName + ":" + srvPort conn, err := net.Dial("tcp", dialaddr) if err != nil { fmt.Println(err) } fmt.Println("client connect") rot := router.New(router.StrID(), 32, router.BroadcastPolicy /*, "client", router.ScopeLocal*/) _, err = rot.ConnectRemote(conn, router.JsonMarshaling) if err != nil { fmt.Println(err) return } chatter := newChatter(myName, rot) cont := true input := bufio.NewReader(os.Stdin) for cont { fmt.Println("action: 1 - Join, 2 - Leave, 3 - Send, 4 - Exit") action, _ := input.ReadString('\n') switch action[0] { case '1', '2', '3': fmt.Println("subject:") subj, _ := input.ReadString('\n') switch action[0] { case '1': chatter.Join(subj[0 : len(subj)-1]) case '2': chatter.Leave(subj[0 : len(subj)-1]) case '3': fmt.Println("message:") msg, _ := input.ReadString('\n') chatter.Send(subj[0:len(subj)-1], msg[0:len(msg)-1]) default: fmt.Println("invalid action") } case '4': cont = false default: fmt.Println("invalid action") } } fmt.Println("client exit") conn.Close() rot.Close() }
func newPonger(rot router.Router, done chan<- bool) { //attach chans to router pingChan := make(chan *Msg) pongChan := make(chan *Msg) //bindChan := make(chan *router.BindEvent, 1) rot.AttachSendChan(router.StrID("pong"), pongChan /*, bindChan*/) rot.AttachRecvChan(router.StrID("ping"), pingChan) //wait for pinger connecting /* for { if (<-bindChan).Count > 0 { break } } */ //start ponger pong := &Ponger{pongChan, pingChan, done} go pong.Run() }
func main() { flag.Parse() if flag.NArg() < 1 { fmt.Println("Usage: game3 num_runs hideTrace") return } else if flag.NArg() > 1 { showPingPong = false } numRuns, _ := strconv.Atoi(flag.Arg(0)) //alloc two routers to connect them rot1 := router.New(router.StrID(), 32, router.BroadcastPolicy) rot2 := router.New(router.StrID(), 32, router.BroadcastPolicy) rot1.Connect(rot2) done := make(chan bool) //hook up Pinger and Ponger newPinger(rot1, done, numRuns) newPonger(rot2, done) //wait for ping-pong to finish <-done <-done }
func (c *Chatter) Join(s string) { _, ok := c.subjectMap[s] if ok { return } subj := newSubject() c.subjectMap[s] = subj //use ScopeRemote to send msgs to peers in connected routers c.r.AttachSendChan(router.StrID(s, router.ScopeRemote), subj.sendChan) c.r.AttachRecvChan(router.StrID(s, router.ScopeRemote), subj.recvChan) //start reading/recving subject msgs go func() { for { msg, chOpen := <-subj.recvChan if !chOpen { break } fmt.Printf("recv: [%s]\n", msg) } fmt.Println("client recv goroutine exit") }() }
func NewServant(n string, role ServantRole, done chan bool) *Servant { s := new(Servant) s.Rot = router.New(router.StrID(), 32, router.BroadcastPolicy /* , n, router.ScopeLocal*/) s.role = role s.name = n //start system tasks, ServiceTask will be created when clients connect NewSysMgrTask(s.Rot, n, role) NewDbTask(s.Rot, n, role) NewFaultMgrTask(s.Rot, n, role) //run Servant mainloop to wait for client connection go s.Run(done) return s }
func (at *ServiceTask) shutdown() { svcname := "/App/" + at.name //output_intf or send chans at.FaultRaiser.Close() at.rot.DetachChan(router.StrID(svcname+"/Response"), at.svcRespChan) at.rot.DetachChan(router.StrID("/DB/Request"), at.dbReqChan) //input_intf or recv chans at.rot.DetachChan(router.StrID(svcname+"/Request"), at.svcReqChan) at.rot.DetachChan(router.StrID("/Sys/Command"), at.sysCmdChan) at.rot.DetachChan(router.StrID("/Fault/Command"+svcname), at.svcCmdChan) at.rot.DetachChan(router.StrID("/DB/Response"+svcname), at.dbRespChan) }
func (at *ServiceTask) init(r router.Router, sn string, n string, role ServantRole) { at.rot = r at.name = n at.servantName = sn at.role = role at.random = rand.New(rand.NewSource(time.Now().UnixNano())) at.svcRespChan = make(chan string) at.dbReqChan = make(chan *DbReq) at.svcReqChan = make(chan string) at.sysCmdChan = make(chan string) at.svcCmdChan = make(chan string) at.dbRespChan = make(chan string) svcname := "/App/" + at.name //output_intf or send chans at.FaultRaiser = router.NewFaultRaiser(router.StrID("/Fault/AppService/Exception"), at.rot, at.name) at.rot.AttachSendChan(router.StrID("/DB/Request"), at.dbReqChan) at.rot.AttachSendChan(router.StrID(svcname+"/Response"), at.svcRespChan) //input_intf or recv chans at.rot.AttachRecvChan(router.StrID("/Sys/Command"), at.sysCmdChan) at.rot.AttachRecvChan(router.StrID("/Fault/Command"+svcname), at.svcCmdChan) at.rot.AttachRecvChan(router.StrID("/DB/Response"+svcname), at.dbRespChan) at.rot.AttachRecvChan(router.StrID(svcname+"/Request"), at.svcReqChan) }
func main() { l, err := net.Listen("tcp", ":0") if err != nil { fmt.Println(err) return } fmt.Println(l.Addr().String()) subjMap := make(map[string]*Subject) rot := router.New(router.StrID(), 32, router.BroadcastPolicy /*, "chatsrv", router.ScopeLocal*/) //start server mainloop in a separate goroutine, and recv client conn in main goroutine go func() { //subscribe to remote publications, so learn what subjects are created pubChan := make(chan *router.ChanInfoMsg) //attach a recv chan with a "chan BindEvent" //this recv chan will not be closed when all senders detach bindChan := make(chan *router.BindEvent, 1) rot.AttachRecvChan(rot.NewSysID(router.PubId, router.ScopeRemote), pubChan, bindChan) //stopChan to notify when all people leave a subject stopChan := make(chan string, 36) for { select { case idstr := <-stopChan: delete(subjMap, idstr) case pub := <-pubChan: //process recved client publication of subjects for _, v := range pub.Info { id := v.Id.(*router.StrId) //get the real id type subj, ok := subjMap[id.Val] if ok { continue } fmt.Printf("add subject: %v\n", id.Val) //add a new subject with ScopeRemote, so that msgs are forwarded //to peers in connected routers id.ScopeVal = router.ScopeRemote id.MemberVal = router.MemberLocal subj = newSubject() subjMap[id.Val] = subj //subscribe to new subjects, forward recved msgs to other rot.AttachSendChan(id, subj.sendChan) rot.AttachRecvChan(id, subj.recvChan) //start forwarding go func(subjname string) { for val := range subj.recvChan { fmt.Printf("chatsrv forward: subject[%v], msg[%s]\n", subjname, val) subj.sendChan <- val } stopChan <- subjname fmt.Printf("chatsrv stop forwarding for : %v\n", subjname) }(id.Val) } } } }() //keep accepting client conn and connect local router to it for { conn, err := l.Accept() if err != nil { fmt.Println(err) return } fmt.Println("one client connect") _, err = rot.ConnectRemote(conn, router.JsonMarshaling) if err != nil { fmt.Println(err) return } } //in fact never reach here rot.Close() l.Close() }