func TestMemberSimple(t *testing.T) { st := store.New() 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 := fp.Watch(store.MustCompileGlob("/ctl/cal/0")) nodeCh := fp.Watch(store.MustCompileGlob("/ctl/node/a/?")) // 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])) ev = <-nodeCh assert.T(t, ev.IsDel()) cs = append(cs, int(ev.Path[len(ev.Path)-1])) sort.SortInts(cs) assert.Equal(t, []int{'x', 'y'}, cs) }
func TestLockSimple(t *testing.T) { st := store.New() defer close(st.Ops) fp := &test.FakeProposer{Store: st} go Clean(fp, st.Watch(SessGlob)) // start our session fp.Propose([]byte(store.MustEncodeSet("/ctl/sess/a", "1.2.3.4:55", store.Clobber))) // lock something for a fp.Propose([]byte(store.MustEncodeSet("/lock/x", "a", store.Missing))) fp.Propose([]byte(store.MustEncodeSet("/lock/y", "b", store.Missing))) fp.Propose([]byte(store.MustEncodeSet("/lock/z", "a", store.Missing))) // watch the locks to be deleted ch := fp.Watch(store.MustCompileGlob("/lock/*")) // end the session fp.Propose([]byte(store.MustEncodeDel("/ctl/sess/a", store.Clobber))) // now that the session has ended, check all locks it owned are released assert.Equal(t, "/lock/x", (<-ch).Path) assert.Equal(t, "/lock/z", (<-ch).Path) }
func errResponse(e os.Error) *R { return &R{ ErrCode: newResponse_Err(response_OTHER), ErrDetail: pb.String(e.String()), } } // response flags const ( Valid = 1 << iota Done Set Del ) var calGlob = store.MustCompileGlob("/ctl/cal/*") type T request type R response type OpError struct { Detail string } type Manager interface { consensus.Proposer } type Server struct { Addr string St *store.Store
"doozer/web" "github.com/ha/doozer" "log" "net" "os" "time" ) 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}
package lock import ( "doozer/consensus" "doozer/store" ) const SessDir = "/ctl/sess" var ( SessGlob = store.MustCompileGlob(SessDir + "/*") locks = store.MustCompileGlob("/lock/**") ) func Clean(p consensus.Proposer, ch <-chan store.Event) { for ev := range ch { if ev.IsDel() { name := ev.Path[len(SessDir)+1:] store.Walk(ev, locks, func(path, body string, rev int64) bool { if body == name { go consensus.Del(p, path, rev) } return false }) } } }