func Benchmark5DoozerConClientSet(b *testing.B) { b.StopTimer() l := mustListen() defer l.Close() a := l.Addr().String() u := mustListenPacket(a) defer u.Close() l1 := mustListen() defer l1.Close() u1 := mustListenPacket(l1.Addr().String()) defer u1.Close() l2 := mustListen() defer l2.Close() u2 := mustListenPacket(l2.Addr().String()) defer u2.Close() l3 := mustListen() defer l3.Close() u3 := mustListenPacket(l3.Addr().String()) defer u3.Close() l4 := mustListen() defer l4.Close() u4 := mustListenPacket(l4.Addr().String()) defer u4.Close() go Main("a", "", u, l, nil, 1e9, 1e8, 3e9) go Main("a", a, u1, l1, nil, 1e9, 1e8, 3e9) go Main("a", a, u2, l2, nil, 1e9, 1e8, 3e9) go Main("a", a, u3, l3, nil, 1e9, 1e8, 3e9) go Main("a", a, u4, l4, nil, 1e9, 1e8, 3e9) cl := client.New("foo", l.Addr().String()) cl.Set("/ctl/cal/1", store.Missing, nil) cl.Set("/ctl/cal/2", store.Missing, nil) cl.Set("/ctl/cal/3", store.Missing, nil) cl.Set("/ctl/cal/4", store.Missing, nil) cls := []*client.Client{ cl, client.New("foo", l1.Addr().String()), client.New("foo", l2.Addr().String()), client.New("foo", l3.Addr().String()), client.New("foo", l4.Addr().String()), } c := make(chan bool, b.N) b.StartTimer() for i := 0; i < b.N; i++ { i := i go func() { cls[i%len(cls)].Set("/test", store.Clobber, nil) c <- true }() } for i := 0; i < b.N; i++ { <-c } }
func nop() { c := client.New("<test>", *addr) err := c.Nop() if err != nil { bail(err) } }
func get(path string) { c := client.New("<test>", *addr) body, _, err := c.Get(path, nil) if err != nil { bail(err) } os.Stdout.Write(body) }
func rev() { c := client.New("<test>", *addr) rev, err := c.Rev() if err != nil { bail(err) } fmt.Println(rev) }
func get(path string) { c := client.New("<test>", *addr) body, rev, err := c.Get(path, nil) if err != nil { bail(err) } fmt.Println(rev, len(body)) os.Stdout.Write(body) fmt.Println() }
func set(path, rev string) { oldRev := mustAtoi64(rev) c := client.New("<test>", *addr) body, err := ioutil.ReadAll(os.Stdin) if err != nil { bail(err) } newRev, err := c.Set(path, oldRev, body) if err != nil { bail(err) } fmt.Println(newRev) }
func Benchmark1DoozerClientSet(b *testing.B) { b.StopTimer() l := mustListen() defer l.Close() a := l.Addr().String() u := mustListenPacket(a) defer u.Close() go Main("a", "", u, l, nil, 1e9, 2e9, 3e9) cl := client.New("foo", l.Addr().String()) b.StartTimer() for i := 0; i < b.N; i++ { cl.Set("/test", store.Clobber, nil) } }
func stat(path string) { c := client.New("<test>", *addr) len, rev, err := c.Stat(path, nil) if err != nil { bail(err) } switch rev { case 0: fmt.Fprintln(os.Stderr, "No such file or directory:", path) os.Exit(proto.Response_NOENT) case -2: fmt.Println("d", len) default: fmt.Println(rev, len) } }
func walk(glob string) { c := client.New("<test>", *addr) w, err := c.Walk(glob, nil, nil, nil) if err != nil { bail(err) } for ev := range w.C { if ev.Err != nil { fmt.Fprintln(os.Stderr, ev.Err) } fmt.Println(ev.Path, ev.Rev, len(ev.Body)) os.Stdout.Write(ev.Body) fmt.Println() } }
func Benchmark5DoozerClientSet(b *testing.B) { b.StopTimer() l := mustListen() defer l.Close() a := l.Addr().String() u := mustListenPacket(a) defer u.Close() l1 := mustListen() defer l1.Close() u1 := mustListenPacket(l1.Addr().String()) defer u1.Close() l2 := mustListen() defer l2.Close() u2 := mustListenPacket(l2.Addr().String()) defer u2.Close() l3 := mustListen() defer l3.Close() u3 := mustListenPacket(l3.Addr().String()) defer u3.Close() l4 := mustListen() defer l4.Close() u4 := mustListenPacket(l4.Addr().String()) defer u4.Close() go Main("a", "", u, l, nil, 1e9, 1e8, 3e9) go Main("a", a, u1, l1, nil, 1e9, 1e8, 3e9) go Main("a", a, u2, l2, nil, 1e9, 1e8, 3e9) go Main("a", a, u3, l3, nil, 1e9, 1e8, 3e9) go Main("a", a, u4, l4, nil, 1e9, 1e8, 3e9) cl := client.New("foo", l.Addr().String()) cl.Set("/ctl/cal/1", store.Missing, nil) cl.Set("/ctl/cal/2", store.Missing, nil) cl.Set("/ctl/cal/3", store.Missing, nil) cl.Set("/ctl/cal/4", store.Missing, nil) b.StartTimer() for i := 0; i < b.N; i++ { cl.Set("/test", store.Clobber, nil) } }
func Benchmark1DoozerConClientSet(b *testing.B) { b.StopTimer() l := mustListen() defer l.Close() a := l.Addr().String() u := mustListenPacket(a) defer u.Close() go Main("a", "", u, l, nil, 1e9, 2e9, 3e9) cl := client.New("foo", l.Addr().String()) c := make(chan bool, b.N) b.StartTimer() for i := 0; i < b.N; i++ { go func() { cl.Set("/test", store.Clobber, nil) c <- true }() } for i := 0; i < b.N; i++ { <-c } }
func Main(clusterName, attachAddr string, udpConn net.PacketConn, listener, webListener net.Listener, pulseInterval, fillDelay, kickTimeout int64) { listenAddr := listener.Addr().String() var activateSeqn int64 useSelf := make(chan bool, 1) self := randId() st := store.New() pr := &proposer{ seqns: make(chan int64, alpha), props: make(chan *consensus.Prop), st: st, } calSrv := func() { go gc.Pulse(self, st.Seqns, pr, pulseInterval) go gc.Clean(st, 360000, time.Tick(1e9)) } if attachAddr == "" { // we are the only node in a new cluster set(st, "/ctl/node/"+self+"/addr", listenAddr, store.Missing) set(st, "/ctl/node/"+self+"/hostname", os.Getenv("HOSTNAME"), store.Missing) set(st, "/ctl/node/"+self+"/version", Version, store.Missing) set(st, "/ctl/cal/0", self, store.Missing) calSrv() close(useSelf) } else { cl := client.New("local", attachAddr) // TODO use real cluster name setC(cl, "/ctl/node/"+self+"/addr", listenAddr, store.Clobber) setC(cl, "/ctl/node/"+self+"/hostname", os.Getenv("HOSTNAME"), store.Clobber) setC(cl, "/ctl/node/"+self+"/version", Version, store.Clobber) rev, err := cl.Rev() if err != nil { panic(err) } walk, err := cl.Walk("/**", &rev, nil, nil) if err != nil { panic(err) } watch, err := cl.Watch("/**", rev+1) if err != nil { panic(err) } go follow(st.Ops, watch.C) follow(st.Ops, walk.C) st.Flush() ch, err := st.Wait(rev + 1) if err == nil { <-ch } go func() { activateSeqn = activate(st, self, cl) calSrv() advanceUntil(cl, st.Seqns, activateSeqn+alpha) err := watch.Cancel() if err != nil { panic(err) } close(useSelf) }() } start := <-st.Seqns cmw := st.Watch(store.Any) in := make(chan consensus.Packet, 50) out := make(chan consensus.Packet, 50) consensus.NewManager(self, start, alpha, in, out, st.Ops, pr.seqns, pr.props, cmw, fillDelay, st) if attachAddr == "" { // Skip ahead alpha steps so that the registrar can provide a // meaningful cluster. for i := start + 1; i < start+alpha+1; i++ { st.Ops <- store.Op{i, store.Nop} } } shun := make(chan string, 3) // sufficient for a cluster of 7 go member.Clean(shun, st, pr) sv := &server.Server{listenAddr, st, pr, self, alpha} go sv.Serve(listener, useSelf) if webListener != nil { web.Store = st web.ClusterName = clusterName go web.Serve(webListener) } go func() { for p := range out { addr, err := net.ResolveUDPAddr(p.Addr) if err != nil { log.Println(err) continue } n, err := udpConn.WriteTo(p.Data, addr) if err != nil { log.Println(err) continue } if n != len(p.Data) { log.Println("packet len too long:", len(p.Data)) continue } } }() lv := liveness{ timeout: kickTimeout, ival: kickTimeout / 2, times: make(map[string]int64), self: self, shun: shun, } for { t := time.Nanoseconds() buf := make([]byte, maxUDPLen) n, addr, err := udpConn.ReadFrom(buf) if err == os.EINVAL { return } if err != nil { log.Println(err) continue } buf = buf[:n] // Update liveness time stamp for this addr lv.times[addr.String()] = t lv.check(t) in <- consensus.Packet{addr.String(), buf} } }