func main() { runtime.GOMAXPROCS(runtime.NumCPU()) flag.Parse() if *dir == address { *dir = fmt.Sprintf("%v_%v", *broadcastIp, *port) } s := dhash.NewNodeDir(fmt.Sprintf("%v:%v", *listenIp, *port), fmt.Sprintf("%v:%v", *broadcastIp, *port), *dir) if *verbose { s.AddChangeListener(func(ring *common.Ring) bool { fmt.Println(s.Describe()) return true }) s.AddMigrateListener(func(dhash *dhash.Node, source, destination []byte) bool { fmt.Printf("Migrated from %v to %v\n", common.HexEncode(source), common.HexEncode(destination)) return true }) s.AddSyncListener(func(source, dest common.Remote, pulled, pushed int) bool { fmt.Printf("%v pulled %v and pushed %v keys synchronizing with %v\n", source.Addr, pulled, pushed, dest.Addr) return true }) s.AddCleanListener(func(source, dest common.Remote, cleaned, pushed int) bool { fmt.Printf("%v cleaned %v and pushed %v keys to %v\n", source.Addr, cleaned, pushed, dest.Addr) return true }) } s.MustStart() if *joinIp != "" { s.MustJoin(fmt.Sprintf("%v:%v", *joinIp, *joinPort)) } select {} }
// Describe returns a humanly readable string describing the broadcast address, position and ring of this Node. func (self *Node) Describe() string { self.metaLock.RLock() buffer := bytes.NewBufferString(fmt.Sprintf("%v@%v\n", common.HexEncode(self.position), self.broadcastAddr)) self.metaLock.RUnlock() fmt.Fprint(buffer, self.ring.Describe()) return string(buffer.Bytes()) }
func testMigrate(t *testing.T, dhashes []*Node) { for _, d := range dhashes { d.Clear() } var item common.Item for i := 0; i < 1000; i++ { item.Key = []byte(fmt.Sprint(i)) item.Value = []byte(fmt.Sprint(i)) item.Timestamp = 1 dhashes[0].Put(item) } common.AssertWithin(t, func() (string, bool) { sum := 0 status := new(bytes.Buffer) ordered := dhashAry(dhashes) sort.Sort(ordered) lastOwned := ordered[len(ordered)-1].Owned() ok := true for _, d := range ordered { sum += d.Owned() fmt.Fprintf(status, "%v %v %v\n", d.node.GetBroadcastAddr(), common.HexEncode(d.node.GetPosition()), d.Owned()) if float64(lastOwned)/float64(d.Owned()) > migrateHysteresis { ok = false } if d.Owned() == 0 { ok = false } lastOwned = d.Owned() } return string(status.Bytes()), ok && sum == 1000 }, time.Second*100) }
func assertDelSuccess(t *testing.T, tree *Tree, k, old string) { assertExistance(t, tree, k, old) if value, existed := tree.Del([]byte(k)); !existed || string(value) != old { t.Errorf("%v should contain %v => %v, got %v, %v", tree.Describe(), common.HexEncode([]byte(k)), old, value, existed) } assertNonExistance(t, tree, k) }
// DescribeNode will return the description structure of the node at pos. func (self *Conn) DescribeNode(pos []byte) (result common.DHashDescription, err error) { _, match, _ := self.ring.Remotes(pos) if match == nil { err = fmt.Errorf("No node with position %v found", common.HexEncode(pos)) return } err = match.Call("DHash.Describe", 0, &result) return }
func TestTreeIndexOf(t *testing.T) { tree := NewTree() for i := 100; i < 200; i += 2 { tree.Put([]byte(fmt.Sprint(i)), []byte(fmt.Sprint(i)), 1) } for i := 100; i < 200; i++ { shouldExist := i%2 == 0 wantedIndex := (i - 99) / 2 if ind, e := tree.IndexOf([]byte(fmt.Sprint(i))); ind != wantedIndex || e != shouldExist { t.Errorf("%v.IndexOf(%v) => %v, %v should be %v, %v", tree.Describe(), common.HexEncode([]byte(fmt.Sprint(i))), ind, e, wantedIndex, shouldExist) } } if ind, e := tree.IndexOf([]byte("1991")); ind != 50 || e { t.Errorf("%v.IndexOf(%v) => %v, %v should be %v, %v", tree.Describe(), "1991", ind, e, 50, false) } if ind, e := tree.IndexOf([]byte("099")); ind != 0 || e { t.Errorf("%v.IndexOf(%v) => %v, %v should be %v, %v", tree.Describe(), "099", ind, e, 0, false) } }
func (self *Node) String() string { return fmt.Sprintf("<%v@%v>", common.HexEncode(self.GetPosition()), self.GetBroadcastAddr()) }
func TestSyncRandomLimits(t *testing.T) { tree1 := NewTree() n := 10 var k []byte var v []byte for i := 0; i < n; i++ { k = murmur.HashString(fmt.Sprint(i)) v = []byte(fmt.Sprint(i)) tree1.Put(k, v, 1) } var keys [][]byte tree1.Each(func(key []byte, byteValue []byte, timestamp int64) bool { keys = append(keys, key) return true }) var fromKey []byte var toKey []byte var tree2 *Tree var tree3 *Tree var s *Sync for fromIndex, _ := range keys { for toIndex, _ := range keys { if fromIndex != toIndex { fromKey = keys[fromIndex] toKey = keys[toIndex] if bytes.Compare(fromKey, toKey) < 0 { tree2 = NewTree() tree1.Each(func(key []byte, byteValue []byte, timestamp int64) bool { if common.BetweenIE(key, fromKey, toKey) { tree2.Put(key, byteValue, 1) } return true }) tree3 = NewTree() s = NewSync(tree1, tree3).From(fromKey).To(toKey) s.Run() if !tree3.deepEqual(tree2) { t.Errorf("when syncing from %v to %v, %v and %v have hashes\n%v\n%v\nand they should be equal!", common.HexEncode(fromKey), common.HexEncode(toKey), tree3.Describe(), tree2.Describe(), tree3.Hash(), tree2.Hash()) } } } } } }
func TestTreeSizeBetween(t *testing.T) { tree := NewTree() for i := 11; i < 20; i++ { tree.Put([]byte(fmt.Sprint(i)), []byte(fmt.Sprint(i)), 1) } for i := 10; i < 21; i++ { for j := i; j < 21; j++ { expected := common.Max(0, common.Min(j+1, 20)-common.Max(11, i)) val := tree.SizeBetween([]byte(fmt.Sprint(i)), []byte(fmt.Sprint(j)), true, true) if val != expected { t.Errorf("%v.SizeBetween(%v, %v, true, true) should be %v but was %v", tree.Describe(), common.HexEncode([]byte(fmt.Sprint(i))), common.HexEncode([]byte(fmt.Sprint(j))), expected, val) } expected = common.Max(0, common.Min(j+1, 20)-common.Max(11, i+1)) val = tree.SizeBetween([]byte(fmt.Sprint(i)), []byte(fmt.Sprint(j)), false, true) if val != expected { t.Errorf("%v.SizeBetween(%v, %v, false, true) should be %v but was %v", tree.Describe(), common.HexEncode([]byte(fmt.Sprint(i))), common.HexEncode([]byte(fmt.Sprint(j))), expected, val) } expected = common.Max(0, common.Min(j, 20)-common.Max(11, i)) val = tree.SizeBetween([]byte(fmt.Sprint(i)), []byte(fmt.Sprint(j)), true, false) if val != expected { t.Errorf("%v.SizeBetween(%v, %v, true, false) should be %v but was %v", tree.Describe(), common.HexEncode([]byte(fmt.Sprint(i))), common.HexEncode([]byte(fmt.Sprint(j))), expected, val) } expected = common.Max(0, common.Min(j, 20)-common.Max(11, i+1)) val = tree.SizeBetween([]byte(fmt.Sprint(i)), []byte(fmt.Sprint(j)), false, false) if val != expected { t.Errorf("%v.SizeBetween(%v, %v, false, false) should be %v but was %v", tree.Describe(), common.HexEncode([]byte(fmt.Sprint(i))), common.HexEncode([]byte(fmt.Sprint(j))), expected, val) } } } for i := 0; i < 10; i++ { tree.SubPut([]byte{50}, []byte{byte(i)}, []byte{byte(i)}, 1) } ary := []byte{50} if s := tree.SizeBetween(ary, ary, true, true); s != 10 { t.Errorf("wrong size calculated for %v\nbetween %v and %v\nwanted %v but got %v", tree.Describe(), common.HexEncode(ary), common.HexEncode(ary), 10, s) } }