Exemple #1
0
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())
					}
				}
			}
		}
	}
}
Exemple #2
0
func (self *Node) migrate() {
	lastAllowedChange := time.Now().Add(-1 * migrateWaitFactor * syncInterval).UnixNano()
	if lastAllowedChange > common.Max64(atomic.LoadInt64(&self.lastSync), atomic.LoadInt64(&self.lastReroute), atomic.LoadInt64(&self.lastMigrate)) {
		var succSize int
		succ := self.node.GetSuccessor()
		if err := succ.Call("DHash.Owned", 0, &succSize); err != nil {
			self.node.RemoveNode(succ)
		} else {
			mySize := self.Owned()
			if mySize > 10 && float64(mySize) > float64(succSize)*migrateHysteresis {
				wantedDelta := (mySize - succSize) / 2
				var existed bool
				var wantedPos []byte
				pred := self.node.GetPredecessor()
				if bytes.Compare(pred.Pos, self.node.GetPosition()) < 1 {
					if wantedPos, existed = self.tree.NextMarkerIndex(self.tree.RealSizeBetween(nil, self.node.GetPosition(), true, false) - wantedDelta); !existed {
						return
					}
				} else {
					ownedAfterNil := self.tree.RealSizeBetween(nil, succ.Pos, true, false)
					if ownedAfterNil > wantedDelta {
						if wantedPos, existed = self.tree.NextMarkerIndex(ownedAfterNil - wantedDelta); !existed {
							return
						}
					} else {
						if wantedPos, existed = self.tree.NextMarkerIndex(self.tree.RealSize() + ownedAfterNil - wantedDelta); !existed {
							return
						}
					}
				}
				if common.BetweenIE(wantedPos, self.node.GetPredecessor().Pos, self.node.GetPosition()) {
					self.changePosition(wantedPos)
				}
			}
		}
	}
}
Exemple #3
0
// GetSuccessorFor will return the successor for the provided key.
// If the successor is not this Node, it will assert that the provided key is between the found successor and the predecessor it claims to have.
func (self *Node) GetSuccessorFor(key []byte) common.Remote {
	// Guess according to our route cache
	predecessor, match, successor := self.ring.Remotes(key)
	if match != nil {
		predecessor = match
	}
	// If we consider ourselves successors, just return us
	if successor.Addr != self.GetBroadcastAddr() {
		// Double check by asking the successor we found what predecessor it has
		if err := successor.Call("Discord.GetPredecessor", 0, predecessor); err != nil {
			self.RemoveNode(*successor)
			return self.GetSuccessorFor(key)
		}
		// If the key we are looking for is between them, just return the successor
		if !common.BetweenIE(key, predecessor.Pos, successor.Pos) {
			// Otherwise, ask the predecessor we actually found about who is the successor of the key
			if err := predecessor.Call("Discord.GetSuccessorFor", key, successor); err != nil {
				self.RemoveNode(*predecessor)
				return self.GetSuccessorFor(key)
			}
		}
	}
	return *successor
}
Exemple #4
0
// withinLimits will check i the given key is actually between the from and to Nibbles for this Sync.
func (self *Sync) withinLimits(key []Nibble) bool {
	if self.from == nil || self.to == nil {
		return true
	}
	return common.BetweenIE(toBytes(key), toBytes(self.from), toBytes(self.to))
}