func TestMemberSimple(t *testing.T) { st := store.New(store.DefaultInitialRev) defer close(st.Ops) fp := &test.FakeProposer{Store: st} c := make(chan string) go Clean(c, fp.Store, fp) fp.Propose([]byte(store.MustEncodeSet("/ctl/node/a/x", "a", store.Missing))) fp.Propose([]byte(store.MustEncodeSet("/ctl/node/a/y", "b", store.Missing))) fp.Propose([]byte(store.MustEncodeSet("/ctl/node/a/addr", "1.2.3.4", store.Missing))) fp.Propose([]byte(store.MustEncodeSet("/ctl/cal/0", "a", store.Missing))) calCh, err := fp.Wait(store.MustCompileGlob("/ctl/cal/0"), 1+<-fp.Seqns) if err != nil { panic(err) } nodeCh, err := fp.Wait(store.MustCompileGlob("/ctl/node/a/?"), 1+<-fp.Seqns) if err != nil { panic(err) } // indicate that this peer is inactive go func() { c <- "1.2.3.4" }() ev := <-calCh assert.T(t, ev.IsSet()) assert.Equal(t, "", ev.Body) cs := []int{} ev = <-nodeCh assert.T(t, ev.IsDel()) cs = append(cs, int(ev.Path[len(ev.Path)-1])) nodeCh, err = fp.Wait(store.MustCompileGlob("/ctl/node/a/?"), ev.Seqn+1) if err != nil { panic(err) } ev = <-nodeCh assert.T(t, ev.IsDel()) cs = append(cs, int(ev.Path[len(ev.Path)-1])) sort.Ints(cs) assert.Equal(t, []int{'x', 'y'}, cs) }
package member import ( "github.com/soundcloud/doozerd/consensus" "github.com/soundcloud/doozerd/store" "log" ) var ( calGlob = store.MustCompileGlob("/ctl/cal/*") ) func Clean(c chan string, st *store.Store, p consensus.Proposer) { for addr := range c { _, g := st.Snap() name := getName(addr, g) if name != "" { go func() { clearSlot(p, g, name) removeInfo(p, g, name) }() } } } func getName(addr string, g store.Getter) string { for _, name := range store.Getdir(g, "/ctl/node") { if store.GetString(g, "/ctl/node/"+name+"/addr") == addr { return name } }
"github.com/soundcloud/doozerd/consensus" "github.com/soundcloud/doozerd/gc" "github.com/soundcloud/doozerd/member" "github.com/soundcloud/doozerd/server" "github.com/soundcloud/doozerd/store" "github.com/soundcloud/doozerd/web" ) const ( alpha = 50 maxUDPLen = 3000 ) const calDir = "/ctl/cal" var calGlob = store.MustCompileGlob(calDir + "/*") type proposer struct { seqns chan int64 props chan *consensus.Prop st *store.Store } func (p *proposer) Propose(v []byte) (e store.Event) { for e.Mut != string(v) { n := <-p.seqns w, err := p.st.Wait(store.Any, n) if err != nil { panic(err) // can't happen } p.props <- &consensus.Prop{n, v}