Example #1
0
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", "X", "", nil, u, l, nil, 1e9, 1e8, 3e9)
	go Main("a", "Y", "", doozer.New("a", a), u1, l1, nil, 1e9, 1e8, 3e9)
	go Main("a", "Z", "", doozer.New("a", a), u2, l2, nil, 1e9, 1e8, 3e9)
	go Main("a", "V", "", doozer.New("a", a), u3, l3, nil, 1e9, 1e8, 3e9)
	go Main("a", "W", "", doozer.New("a", a), u4, l4, nil, 1e9, 1e8, 3e9)

	cl := doozer.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 := []*doozer.Client{
		cl,
		doozer.New("foo", l1.Addr().String()),
		doozer.New("foo", l2.Addr().String()),
		doozer.New("foo", l3.Addr().String()),
		doozer.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
	}
}
Example #2
0
func TestDoozerWaitSimple(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())
	var rev int64 = 1

	cl.Set("/test/foo", store.Clobber, []byte("bar"))
	ev, err := cl.Wait("/test/**", rev)
	assert.Equal(t, nil, err)
	assert.Equal(t, "/test/foo", ev.Path)
	assert.Equal(t, []byte("bar"), ev.Body)
	assert.T(t, ev.IsSet())
	rev = ev.Rev + 1

	cl.Set("/test/fun", store.Clobber, []byte("house"))
	ev, err = cl.Wait("/test/**", rev)
	assert.Equal(t, nil, err)
	assert.Equal(t, "/test/fun", ev.Path)
	assert.Equal(t, []byte("house"), ev.Body)
	assert.T(t, ev.IsSet())
	rev = ev.Rev + 1

	cl.Del("/test/foo", store.Clobber)
	ev, err = cl.Wait("/test/**", rev)
	assert.Equal(t, nil, err)
	assert.Equal(t, "/test/foo", ev.Path)
	assert.T(t, ev.IsDel())
}
Example #3
0
func TestDoozerWalk(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	cl.Set("/test/foo", store.Clobber, []byte("bar"))
	cl.Set("/test/fun", store.Clobber, []byte("house"))

	info, err := cl.Walk("/test/**", nil, 0, -1)
	assert.Equal(t, nil, err)
	assert.Equal(t, 2, len(info))

	assert.Equal(t, "/test/foo", info[0].Path)
	assert.Equal(t, "bar", string(info[0].Body))
	assert.T(t, info[0].IsSet())

	assert.Equal(t, "/test/fun", info[1].Path)
	assert.Equal(t, "house", string(info[1].Body))
	assert.T(t, info[1].IsSet())
}
Example #4
0
func TestDoozerWalkWithRev(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	rev, _ := cl.Set("/test/foo", store.Clobber, []byte("bar"))
	cl.Set("/test/fun", store.Clobber, []byte("house"))
	cl.Set("/test/fab", store.Clobber, []byte("ulous"))

	w, err := cl.Walk("/test/**", &rev, nil, nil)
	assert.Equal(t, nil, err, err)

	ls := []string{}
	for e := range w.C {
		ls = append(ls, e.Path)
	}

	sort.SortStrings(ls)
	assert.Equal(t, []string{"/test/foo"}, ls)
}
Example #5
0
File: boot.go Project: kr/doozerd
// IsCal checks if addr is a CAL in the cluster named name.
// Returns a client if so, nil if not.
func isCal(name, addr string) *doozer.Client {
	c := doozer.New(name, addr)
	v, _, _ := c.Get("/ctl/name", nil)
	if string(v) != name {
		return nil
	}

	var cals []string
	names, err := c.Getdir("/ctl/cal", nil, 0, -1)
	if err != nil {
		panic(err)
	}
	for _, name := range names {
		cals = append(cals, name)
	}

	for _, cal := range cals {
		body, _, err := c.Get("/ctl/cal/"+cal, nil)
		if err != nil || len(body) == 0 {
			continue
		}

		id := string(body)

		v, _, err := c.Get("/ctl/node/"+id+"/addr", nil)
		if err != nil {
			panic(err)
		}
		if string(v) == addr {
			return c
		}
	}

	return nil
}
Example #6
0
func TestDoozerGetdirOffsetLimit(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())
	cl.Set("/test/a", store.Clobber, []byte("1"))
	cl.Set("/test/b", store.Clobber, []byte("2"))
	cl.Set("/test/c", store.Clobber, []byte("3"))
	cl.Set("/test/d", store.Clobber, []byte("4"))

	// The order is arbitrary.  We need to collect them
	// because it's not safe to assume the order.
	w, _ := cl.Getdir("/test", 0, 0, nil)
	ents := make([]string, 0)
	for e := range w.C {
		ents = append(ents, e.Path)
	}

	w, _ = cl.Getdir("/test", 1, 2, nil)
	assert.Equal(t, ents[1], (<-w.C).Path)
	assert.Equal(t, ents[2], (<-w.C).Path)
	assert.Equal(t, (*doozer.Event)(nil), <-w.C)
	assert.T(t, closed(w.C))
}
Example #7
0
func TestDoozerWalkWithOffsetAndLimit(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	cl.Set("/test/a", store.Clobber, []byte("abc"))
	cl.Set("/test/b", store.Clobber, []byte("def"))
	cl.Set("/test/c", store.Clobber, []byte("ghi"))
	cl.Set("/test/d", store.Clobber, []byte("jkl"))

	info, err := cl.Walk("/test/**", nil, 1, 2)
	assert.Equal(t, nil, err)
	assert.Equal(t, 2, len(info))

	assert.Equal(t, "/test/b", info[0].Path)
	assert.Equal(t, "def", string(info[0].Body))
	assert.T(t, info[0].IsSet())

	assert.Equal(t, "/test/c", info[1].Path)
	assert.Equal(t, "ghi", string(info[1].Body))
	assert.T(t, info[1].IsSet())
}
Example #8
0
func TestDoozerWalk(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	cl.Set("/test/foo", store.Clobber, []byte("bar"))
	cl.Set("/test/fun", store.Clobber, []byte("house"))

	w, err := cl.Walk("/test/**", nil, nil, nil)
	assert.Equal(t, nil, err, err)

	ev := <-w.C
	assert.NotEqual(t, (*doozer.Event)(nil), ev)
	assert.Equal(t, "/test/foo", ev.Path)
	assert.Equal(t, "bar", string(ev.Body))
	assert.T(t, ev.IsSet())

	ev = <-w.C
	assert.NotEqual(t, (*doozer.Event)(nil), ev)
	assert.Equal(t, "/test/fun", ev.Path)
	assert.Equal(t, "house", string(ev.Body))
	assert.T(t, ev.IsSet())

	ev = <-w.C
	assert.Tf(t, closed(w.C), "got %v", ev)
}
Example #9
0
func TestDoozerGetWithRev(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	rev1, err := cl.Set("/x", store.Missing, []byte{'a'})
	assert.Equal(t, nil, err)

	v, rev, err := cl.Get("/x", &rev1) // Use the snapshot.
	assert.Equal(t, nil, err)
	assert.Equal(t, rev1, rev)
	assert.Equal(t, []byte{'a'}, v)

	rev2, err := cl.Set("/x", rev, []byte{'b'})
	assert.Equal(t, nil, err)

	v, rev, err = cl.Get("/x", nil) // Read the new value.
	assert.Equal(t, nil, err)
	assert.Equal(t, rev2, rev)
	assert.Equal(t, []byte{'b'}, v)

	v, rev, err = cl.Get("/x", &rev1) // Read the saved value again.
	assert.Equal(t, nil, err)
	assert.Equal(t, rev1, rev)
	assert.Equal(t, []byte{'a'}, v)
}
Example #10
0
func TestDoozerWatchSimple(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	w, err := cl.Watch("/test/**", 0)
	assert.Equal(t, nil, err, err)
	defer w.Cancel()

	cl.Set("/test/foo", store.Clobber, []byte("bar"))
	ev := <-w.C
	assert.Equal(t, "/test/foo", ev.Path)
	assert.Equal(t, []byte("bar"), ev.Body)
	assert.T(t, ev.IsSet())

	cl.Set("/test/fun", store.Clobber, []byte("house"))
	ev = <-w.C
	assert.Equal(t, "/test/fun", ev.Path)
	assert.Equal(t, []byte("house"), ev.Body)
	assert.T(t, ev.IsSet())

	cl.Del("/test/foo", store.Clobber)
	ev = <-w.C
	assert.Equal(t, "/test/foo", ev.Path)
	assert.T(t, ev.IsDel())

	w.Cancel()
	ev = <-w.C
	assert.Tf(t, closed(w.C), "got %v", ev)
}
Example #11
0
func TestDoozerWatchWithRev(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	// Create some history
	cl.Set("/test/foo", store.Clobber, []byte("bar"))
	cl.Set("/test/fun", store.Clobber, []byte("house"))

	// Ask doozer for the history
	w, err := cl.Watch("/test/**", 1)
	assert.Equal(t, nil, err, err)
	defer w.Cancel()

	ev := <-w.C
	assert.Equal(t, "/test/foo", ev.Path)
	assert.Equal(t, []byte("bar"), ev.Body)
	assert.T(t, ev.IsSet())

	ev = <-w.C
	assert.Equal(t, "/test/fun", ev.Path)
	assert.Equal(t, []byte("house"), ev.Body)
	assert.T(t, ev.IsSet())
}
Example #12
0
func TestDoozerGet(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	_, err := cl.Set("/x", store.Missing, []byte{'a'})
	assert.Equal(t, nil, err)

	ents, rev, err := cl.Get("/x", nil)
	assert.Equal(t, nil, err)
	assert.NotEqual(t, store.Dir, rev)
	assert.Equal(t, []byte{'a'}, ents)

	//cl.Set("/test/a", store.Missing, []byte{'1'})
	//cl.Set("/test/b", store.Missing, []byte{'2'})
	//cl.Set("/test/c", store.Missing, []byte{'3'})

	//ents, rev, err = cl.Get("/test", 0)
	//sort.SortStrings(ents)
	//assert.Equal(t, store.Dir, rev)
	//assert.Equal(t, nil, err)
	//assert.Equal(t, []string{"a", "b", "c"}, ents)
}
Example #13
0
func TestDoozerGetdirOnDir(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	cl.Set("/test/a", store.Clobber, []byte("1"))
	cl.Set("/test/b", store.Clobber, []byte("2"))
	cl.Set("/test/c", store.Clobber, []byte("3"))

	w, err := cl.Getdir("/test", 0, 0, nil)
	assert.Equal(t, nil, err)

	got := make([]string, 0)
	for e := range w.C {
		got = append(got, e.Path)
	}

	sort.SortStrings(got)
	assert.Equal(t, []string{"a", "b", "c"}, got)
}
Example #14
0
func TestDoozerReconnect(t *testing.T) {
	l := mustListen()
	defer l.Close()
	a := l.Addr().String()
	u := mustListenPacket(a)
	defer u.Close()
	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	l1 := mustListen()
	go Main("a", "Y", "", doozer.New("a", a), mustListenPacket(l1.Addr().String()), l1, nil, 1e9, 2e9, 3e9)

	l2 := mustListen()
	go Main("a", "Z", "", doozer.New("a", a), mustListenPacket(l2.Addr().String()), l2, nil, 1e9, 2e9, 3e9)

	c0 := doozer.New("foo", a)

	_, err := c0.Set("/ctl/cal/2", 0, []byte{})
	assert.Equal(t, nil, err)

	_, err = c0.Set("/ctl/cal/3", 0, []byte{})
	assert.Equal(t, nil, err)

	// Wait for the other nodes to become CALs.
	for <-c0.Len < 3 {
		time.Sleep(5e8)
	}

	rev, err := c0.Set("/x", -1, []byte{'a'})
	assert.Equal(t, nil, err, err)

	rev, err = c0.Set("/x", -1, []byte{'b'})
	assert.Equal(t, nil, err)

	l1.Close()

	ents, rev, err := c0.Get("/x", nil)
	assert.Equal(t, nil, err, err)
	assert.NotEqual(t, store.Dir, rev)
	assert.Equal(t, []byte{'b'}, ents)

	rev, err = c0.Set("/x", -1, []byte{'c'})
	assert.Equal(t, nil, err, err)

	rev, err = c0.Set("/x", -1, []byte{'d'})
	assert.Equal(t, nil, err)
}
Example #15
0
File: boot.go Project: kr/doozerd
func boot(name, id, laddr, baddr string) *doozer.Client {
	b := doozer.New("<boot>", baddr)
	cl := lookupAndAttach(b, name)
	if cl == nil {
		return elect(name, id, laddr, b)
	}

	return cl
}
Example #16
0
func TestDoozerNop(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())
	err := cl.Nop()
	assert.Equal(t, nil, err)
}
Example #17
0
func TestDoozerGetdirMissing(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	names, err := cl.Getdir("/not/here", nil, 0, -1)
	assert.Equal(t, os.ENOENT, err)
	assert.Equal(t, []string{}, names)
}
Example #18
0
func TestDoozerSet(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	for i := byte(0); i < 10; i++ {
		_, err := cl.Set("/x", store.Clobber, []byte{'0' + i})
		assert.Equal(t, nil, err)
	}
}
Example #19
0
func TestDoozerGetdirOnFile(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	cl.Set("/test/a", store.Clobber, []byte("1"))

	names, err := cl.Getdir("/test/a", nil, 0, -1)
	assert.Equal(t, os.ENOTDIR, err)
	assert.Equal(t, []string{}, names)
}
Example #20
0
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", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		cl.Set("/test", store.Clobber, nil)
	}
}
Example #21
0
func TestDoozerGetdirOffsetLimit(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())
	cl.Set("/test/a", store.Clobber, []byte("1"))
	cl.Set("/test/b", store.Clobber, []byte("2"))
	cl.Set("/test/c", store.Clobber, []byte("3"))
	cl.Set("/test/d", store.Clobber, []byte("4"))

	names, err := cl.Getdir("/test", nil, 1, 2)
	assert.Equal(t, nil, err)
	assert.Equal(t, []string{"b", "c"}, names)
}
Example #22
0
func TestDoozerWalkWithRev(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	rev, _ := cl.Set("/test/foo", store.Clobber, []byte("bar"))
	cl.Set("/test/fun", store.Clobber, []byte("house"))
	cl.Set("/test/fab", store.Clobber, []byte("ulous"))

	info, err := cl.Walk("/test/**", &rev, 0, -1)
	assert.Equal(t, nil, err)
	assert.Equal(t, 1, len(info))
	assert.Equal(t, "/test/foo", info[0].Path)
}
Example #23
0
func TestDoozerGetdirOffsetLimitBounds(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())
	cl.Set("/test/a", store.Clobber, []byte("1"))
	cl.Set("/test/b", store.Clobber, []byte("2"))
	cl.Set("/test/c", store.Clobber, []byte("3"))
	cl.Set("/test/d", store.Clobber, []byte("4"))

	w, _ := cl.Getdir("/test", 1, 5, nil)
	assert.NotEqual(t, (*doozer.Event)(nil), <-w.C)
	assert.NotEqual(t, (*doozer.Event)(nil), <-w.C)
	assert.NotEqual(t, (*doozer.Event)(nil), <-w.C)
	assert.Equal(t, (*doozer.Event)(nil), <-w.C)
	assert.T(t, closed(w.C))
}
Example #24
0
func TestDoozerStat(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	cl.Set("/test/foo", store.Clobber, []byte("bar"))
	setRev, _ := cl.Set("/test/fun", store.Clobber, []byte("house"))

	ln, rev, err := cl.Stat("/test", nil)
	assert.Equal(t, nil, err)
	assert.Equal(t, store.Dir, rev)
	assert.Equal(t, int32(2), ln)

	ln, rev, err = cl.Stat("/test/fun", nil)
	assert.Equal(t, nil, err)
	assert.Equal(t, setRev, rev)
	assert.Equal(t, int32(5), ln)
}
Example #25
0
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", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.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
	}
}
Example #26
0
func TestDoozerWalkWithOffsetAndLimit(t *testing.T) {
	l := mustListen()
	defer l.Close()
	u := mustListenPacket(l.Addr().String())
	defer u.Close()

	go Main("a", "X", "", nil, u, l, nil, 1e9, 2e9, 3e9)

	cl := doozer.New("foo", l.Addr().String())

	cl.Set("/test/a", store.Clobber, []byte("abc"))
	cl.Set("/test/b", store.Clobber, []byte("def"))
	cl.Set("/test/c", store.Clobber, []byte("ghi"))
	cl.Set("/test/d", store.Clobber, []byte("jkl"))

	offset := int32(1)
	limit := int32(2)

	w, err := cl.Walk("/test/**", nil, &offset, &limit)
	assert.Equal(t, nil, err, err)

	ev := <-w.C
	assert.NotEqual(t, (*doozer.Event)(nil), ev)
	assert.Equal(t, "/test/b", ev.Path)
	assert.Equal(t, "def", string(ev.Body))
	assert.T(t, ev.IsSet())

	ev = <-w.C
	assert.NotEqual(t, (*doozer.Event)(nil), ev)
	assert.Equal(t, "/test/c", ev.Path)
	assert.Equal(t, "ghi", string(ev.Body))
	assert.T(t, ev.IsSet())

	ev = <-w.C
	assert.Tf(t, closed(w.C), "got %v", ev)
}
Example #27
0
func Main(clusterName, self, baddr string, cl *doozer.Client, udpConn net.PacketConn, listener, webListener net.Listener, pulseInterval, fillDelay, kickTimeout int64) {
	listenAddr := listener.Addr().String()

	var activateSeqn int64
	useSelf := make(chan bool, 1)

	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 cl == nil { // we are the only node in a new cluster
		set(st, "/ctl/name", clusterName, store.Missing)
		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 {
		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)
			if baddr != "" {
				b := doozer.New("<boot>", baddr)
				setC(
					b,
					"/ctl/ns/"+clusterName+"/"+self,
					listenAddr,
					store.Missing,
				)
			}
		}()
	}

	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 cl == nil {
		// 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}
	}
}