mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2024-11-30 13:35:19 +00:00
keep track of all keys we're supposed to care about in the dht, don't give special treatment to successors/predecessors
This commit is contained in:
parent
efe6cec11a
commit
bcbd24120d
@ -57,6 +57,18 @@ type dht struct {
|
|||||||
table map[NodeID]*dhtInfo
|
table map[NodeID]*dhtInfo
|
||||||
peers chan *dhtInfo // other goroutines put incoming dht updates here
|
peers chan *dhtInfo // other goroutines put incoming dht updates here
|
||||||
reqs map[boxPubKey]map[NodeID]time.Time
|
reqs map[boxPubKey]map[NodeID]time.Time
|
||||||
|
targets [NodeIDLen*8 + 1]NodeID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nodeID NodeID) add(toAdd *NodeID) NodeID {
|
||||||
|
var accumulator uint16
|
||||||
|
for idx := len(nodeID) - 1; idx >= 0; idx-- {
|
||||||
|
accumulator += uint16(nodeID[idx])
|
||||||
|
accumulator += uint16(toAdd[idx])
|
||||||
|
nodeID[idx] = byte(accumulator)
|
||||||
|
accumulator >>= 8
|
||||||
|
}
|
||||||
|
return nodeID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes the DHT
|
// Initializes the DHT
|
||||||
@ -64,32 +76,27 @@ func (t *dht) init(c *Core) {
|
|||||||
t.core = c
|
t.core = c
|
||||||
t.nodeID = *t.core.GetNodeID()
|
t.nodeID = *t.core.GetNodeID()
|
||||||
t.peers = make(chan *dhtInfo, 1024)
|
t.peers = make(chan *dhtInfo, 1024)
|
||||||
|
getDist := func(bit int) *NodeID {
|
||||||
|
nBits := NodeIDLen * 8
|
||||||
|
theByte := (nBits - bit) / 8
|
||||||
|
theBitmask := uint8(0x80) >> uint8(nBits-bit)
|
||||||
|
var nid NodeID
|
||||||
|
//fmt.Println("DEBUG: bit", bit, "theByte", theByte)
|
||||||
|
nid[theByte] = theBitmask
|
||||||
|
return &nid
|
||||||
|
}
|
||||||
|
for idx := range t.targets {
|
||||||
|
t.targets[idx] = t.nodeID.add(getDist(idx + 1))
|
||||||
|
}
|
||||||
|
t.targets[len(t.targets)-1] = t.nodeID // Last one wraps around to self
|
||||||
t.reset()
|
t.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resets the DHT in response to coord changes
|
// Resets the DHT in response to coord changes
|
||||||
// This empties all info from the DHT and drops outstanding requests
|
// This empties all info from the DHT and drops outstanding requests
|
||||||
// It sends a ping to the old successor and predecessor, in case they're still around
|
|
||||||
func (t *dht) reset() {
|
func (t *dht) reset() {
|
||||||
var successor *dhtInfo
|
|
||||||
var predecessor *dhtInfo
|
|
||||||
for infoID, info := range t.table {
|
|
||||||
// Get current successor and predecessor
|
|
||||||
if successor == nil || dht_ordered(&t.nodeID, &infoID, successor.getNodeID()) {
|
|
||||||
successor = info
|
|
||||||
}
|
|
||||||
if predecessor == nil || dht_ordered(predecessor.getNodeID(), &infoID, &t.nodeID) {
|
|
||||||
predecessor = info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t.reqs = make(map[boxPubKey]map[NodeID]time.Time)
|
t.reqs = make(map[boxPubKey]map[NodeID]time.Time)
|
||||||
t.table = make(map[NodeID]*dhtInfo)
|
t.table = make(map[NodeID]*dhtInfo)
|
||||||
if successor != nil {
|
|
||||||
t.ping(successor, nil)
|
|
||||||
}
|
|
||||||
if predecessor != nil {
|
|
||||||
t.ping(predecessor, nil)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does a DHT lookup and returns up to dht_lookup_size results
|
// Does a DHT lookup and returns up to dht_lookup_size results
|
||||||
@ -197,24 +204,7 @@ func (t *dht) handleReq(req *dhtReq) {
|
|||||||
coords: req.Coords,
|
coords: req.Coords,
|
||||||
}
|
}
|
||||||
// For bootstrapping to work, we need to add these nodes to the table
|
// For bootstrapping to work, we need to add these nodes to the table
|
||||||
//t.insert(&info)
|
|
||||||
// FIXME? DEBUG testing what happens if we only add better predecessors/successors
|
|
||||||
var successor *dhtInfo
|
|
||||||
var predecessor *dhtInfo
|
|
||||||
for infoID, v := range t.table {
|
|
||||||
// Get current successor and predecessor
|
|
||||||
if successor == nil || dht_ordered(&t.nodeID, &infoID, successor.getNodeID()) {
|
|
||||||
successor = v
|
|
||||||
}
|
|
||||||
if predecessor == nil || dht_ordered(predecessor.getNodeID(), &infoID, &t.nodeID) {
|
|
||||||
predecessor = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if successor != nil && dht_ordered(&t.nodeID, info.getNodeID(), successor.getNodeID()) {
|
|
||||||
t.insert(&info)
|
t.insert(&info)
|
||||||
} else if predecessor != nil && dht_ordered(predecessor.getNodeID(), info.getNodeID(), &t.nodeID) {
|
|
||||||
t.insert(&info)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends a lookup response to the specified node.
|
// Sends a lookup response to the specified node.
|
||||||
@ -274,17 +264,6 @@ func (t *dht) handleRes(res *dhtRes) {
|
|||||||
coords: res.Coords,
|
coords: res.Coords,
|
||||||
}
|
}
|
||||||
t.insert(&rinfo) // Or at the end, after checking successor/predecessor?
|
t.insert(&rinfo) // Or at the end, after checking successor/predecessor?
|
||||||
var successor *dhtInfo
|
|
||||||
var predecessor *dhtInfo
|
|
||||||
for infoID, info := range t.table {
|
|
||||||
// Get current successor and predecessor
|
|
||||||
if successor != nil && dht_ordered(&t.nodeID, &infoID, successor.getNodeID()) {
|
|
||||||
successor = info
|
|
||||||
}
|
|
||||||
if predecessor != nil && dht_ordered(predecessor.getNodeID(), &infoID, &t.nodeID) {
|
|
||||||
predecessor = info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(res.Infos) > dht_lookup_size {
|
if len(res.Infos) > dht_lookup_size {
|
||||||
res.Infos = res.Infos[:dht_lookup_size]
|
res.Infos = res.Infos[:dht_lookup_size]
|
||||||
}
|
}
|
||||||
@ -296,11 +275,7 @@ func (t *dht) handleRes(res *dhtRes) {
|
|||||||
// TODO? don't skip if coords are different?
|
// TODO? don't skip if coords are different?
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Send a request to all better successors or predecessors
|
if t.isImportant(info.getNodeID()) {
|
||||||
// We could try sending to only the best, but then packet loss matters more
|
|
||||||
if successor == nil || dht_ordered(&t.nodeID, info.getNodeID(), successor.getNodeID()) {
|
|
||||||
t.ping(info, nil)
|
|
||||||
} else if predecessor == nil || dht_ordered(predecessor.getNodeID(), info.getNodeID(), &t.nodeID) {
|
|
||||||
t.ping(info, nil)
|
t.ping(info, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,18 +324,13 @@ func (t *dht) ping(info *dhtInfo, target *NodeID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *dht) doMaintenance() {
|
func (t *dht) doMaintenance() {
|
||||||
// Ping successor, asking for their predecessor, and clean up old/expired info
|
|
||||||
var successor *dhtInfo
|
|
||||||
var predecessor *dhtInfo
|
|
||||||
toPing := make(map[NodeID]*dhtInfo)
|
toPing := make(map[NodeID]*dhtInfo)
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
for infoID, info := range t.table {
|
for infoID, info := range t.table {
|
||||||
if now.Sub(info.recv) > time.Minute || info.pings > 3 {
|
if now.Sub(info.recv) > time.Minute || info.pings > 3 {
|
||||||
delete(t.table, infoID)
|
delete(t.table, infoID)
|
||||||
} else if successor == nil || dht_ordered(&t.nodeID, &infoID, successor.getNodeID()) {
|
} else if t.isImportant(info.getNodeID()) {
|
||||||
successor = info
|
toPing[infoID] = info
|
||||||
} else if predecessor == nil || dht_ordered(predecessor.getNodeID(), &infoID, &t.nodeID) {
|
|
||||||
predecessor = info
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@ -380,38 +350,36 @@ func (t *dht) doMaintenance() {
|
|||||||
t.insert(&pinfo)
|
t.insert(&pinfo)
|
||||||
}
|
}
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
if successor != nil {
|
|
||||||
toPing[*successor.getNodeID()] = successor
|
|
||||||
}
|
|
||||||
if predecessor != nil {
|
|
||||||
toPing[*predecessor.getNodeID()] = predecessor
|
|
||||||
}
|
|
||||||
for _, info := range toPing {
|
for _, info := range toPing {
|
||||||
if now.Sub(info.recv) > info.throttle {
|
if now.Sub(info.recv) > info.throttle {
|
||||||
t.ping(info, nil)
|
t.ping(info, info.getNodeID())
|
||||||
info.pings++
|
info.pings++
|
||||||
info.throttle += time.Second
|
info.throttle += time.Second
|
||||||
if info.throttle > 30*time.Second {
|
if info.throttle > 30*time.Second {
|
||||||
info.throttle = 30 * time.Second
|
info.throttle = 30 * time.Second
|
||||||
}
|
}
|
||||||
//fmt.Println("DEBUG self:", t.nodeID[:8], "throttle:", info.throttle, "nodeID:", info.getNodeID()[:8], "coords:", info.coords)
|
//continue
|
||||||
|
fmt.Println("DEBUG self:", t.nodeID[:8], "throttle:", info.throttle, "nodeID:", info.getNodeID()[:8], "coords:", info.coords)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
if successor != nil &&
|
|
||||||
now.Sub(successor.recv) > successor.throttle {
|
|
||||||
t.ping(successor, nil)
|
|
||||||
successor.pings++
|
|
||||||
successor.throttle += time.Second
|
|
||||||
//return
|
|
||||||
fmt.Println("DEBUG self:", t.nodeID[:8], "throttle:", successor.throttle, "nodeID:", successor.getNodeID()[:8], "coords:", successor.coords)
|
|
||||||
//for infoID := range t.table {
|
|
||||||
// fmt.Println("DEBUG other info:", infoID[:8], "ordered", dht_ordered(&t.nodeID, &infoID, successor.getNodeID()), "swapped:", dht_ordered(&t.nodeID, successor.getNodeID(), &infoID))
|
|
||||||
//}
|
|
||||||
if successor.throttle > 30*time.Second {
|
|
||||||
successor.throttle = 30 * time.Second
|
|
||||||
}
|
}
|
||||||
//fmt.Println("Table size:", len(t.table))
|
|
||||||
|
func (t *dht) isImportant(nodeID *NodeID) bool {
|
||||||
|
// TODO persistently store stuff about best nodes, so we don't need to keep doing this
|
||||||
|
// Ideally switch to a better data structure... linked list?
|
||||||
|
for _, target := range t.targets {
|
||||||
|
// Get the best known node for this target
|
||||||
|
var best *dhtInfo
|
||||||
|
for _, info := range t.table {
|
||||||
|
if best == nil || dht_ordered(best.getNodeID(), info.getNodeID(), &target) {
|
||||||
|
best = info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if best != nil && dht_ordered(best.getNodeID(), nodeID, &target) {
|
||||||
|
// This is an equal or better finger table entry than what we currently have
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We didn't find anything where this is better, so it must be worse
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user