yet more debugging

This commit is contained in:
Arceliar 2018-10-21 17:40:43 -05:00
parent f0bd40ff68
commit 5e3959f1d0
4 changed files with 72 additions and 73 deletions

View File

@ -437,7 +437,7 @@ func main() {
pingNodes(kstore)
//pingBench(kstore) // Only after disabling debug output
//stressTest(kstore)
//time.Sleep(120*time.Second)
time.Sleep(120 * time.Second)
dumpDHTSize(kstore) // note that this uses racey functions to read things...
if false {
// This connects the sim to the local network

View File

@ -11,7 +11,7 @@ import (
"time"
)
const dht_lookup_size = 16
const dht_lookup_size = 4
// dhtInfo represents everything we know about a node in the DHT.
// This includes its key, a cache of it's NodeID, coords, and timing/ping related info for deciding who/when to ping nodes for maintenance.
@ -57,18 +57,6 @@ type dht struct {
table map[NodeID]*dhtInfo
peers chan *dhtInfo // other goroutines put incoming dht updates here
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
@ -76,19 +64,6 @@ func (t *dht) init(c *Core) {
t.core = c
t.nodeID = *t.core.GetNodeID()
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()
}
@ -103,11 +78,15 @@ func (t *dht) reset() {
// If allowWorse = true, begins with best know predecessor for ID and works backwards, even if these nodes are worse predecessors than we are, to be used when intializing searches
// If allowWorse = false, begins with the best known successor for ID and works backwards (next is predecessor, etc, inclusive of the ID if it's a known node)
func (t *dht) lookup(nodeID *NodeID, everything bool) []*dhtInfo {
var results []*dhtInfo
for infoID, info := range t.table {
if everything || t.isImportant(&infoID) {
results := make([]*dhtInfo, 0, len(t.table))
for _, info := range t.table {
results = append(results, info)
}
sort.SliceStable(results, func(i, j int) bool {
return dht_ordered(results[j].getNodeID(), results[i].getNodeID(), nodeID)
})
if len(results) > dht_lookup_size {
//results = results[:dht_lookup_size] //FIXME debug
}
return results
}
@ -277,6 +256,7 @@ func (t *dht) handleRes(res *dhtRes) {
if len(res.Infos) > dht_lookup_size {
//res.Infos = res.Infos[:dht_lookup_size] //FIXME debug
}
imp := t.getImportant()
for _, info := range res.Infos {
if *info.getNodeID() == t.nodeID {
continue
@ -285,7 +265,7 @@ func (t *dht) handleRes(res *dhtRes) {
// TODO? don't skip if coords are different?
continue
}
if t.isImportant(info.getNodeID()) {
if t.isImportant(info, imp) {
t.ping(info, nil)
}
}
@ -336,30 +316,18 @@ func (t *dht) ping(info *dhtInfo, target *NodeID) {
func (t *dht) doMaintenance() {
toPing := make(map[NodeID]*dhtInfo)
now := time.Now()
imp := t.getImportant()
good := make(map[NodeID]*dhtInfo)
for _, info := range imp {
good[*info.getNodeID()] = info
}
for infoID, info := range t.table {
if now.Sub(info.recv) > time.Minute || info.pings > 3 {
delete(t.table, infoID)
} else if t.isImportant(info.getNodeID()) {
} else if t.isImportant(info, imp) {
toPing[infoID] = info
}
}
//////////////////////////////////////////////////////////////////////////////
t.core.switchTable.mutex.RLock()
parentPort := t.core.switchTable.parent
parentInfo := t.core.switchTable.data.peers[parentPort]
t.core.switchTable.mutex.RUnlock()
ports := t.core.peers.getPorts()
if parent, isIn := ports[parentPort]; isIn {
loc := parentInfo.locator.clone()
end := len(loc.coords)
if end > 0 {
end -= 1
}
loc.coords = loc.coords[:end]
pinfo := dhtInfo{key: parent.box, coords: loc.getCoords()}
t.insert(&pinfo)
}
//////////////////////////////////////////////////////////////////////////////
for _, info := range toPing {
if now.Sub(info.recv) > info.throttle {
t.ping(info, info.getNodeID())
@ -368,28 +336,52 @@ func (t *dht) doMaintenance() {
if info.throttle > 30*time.Second {
info.throttle = 30 * time.Second
}
//continue
continue
fmt.Println("DEBUG self:", t.nodeID[:8], "throttle:", info.throttle, "nodeID:", info.getNodeID()[:8], "coords:", info.coords)
}
}
}
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
func (t *dht) getImportant() []*dhtInfo {
// Get a list of all known nodes
infos := make([]*dhtInfo, 0, len(t.table))
for _, info := range t.table {
if best == nil || dht_ordered(best.getNodeID(), info.getNodeID(), &target) {
best = info
infos = append(infos, info)
}
// Sort them by increasing order in distance along the ring
sort.SliceStable(infos, func(i, j int) bool {
// Sort in order of successors
return dht_ordered(&t.nodeID, infos[i].getNodeID(), infos[j].getNodeID())
})
// Keep the ones that are no further than the closest seen so far
minDist := ^uint64(0)
loc := t.core.switchTable.getLocator()
important := infos[:0]
for _, info := range infos {
dist := uint64(loc.dist(info.coords))
if dist < minDist {
minDist = dist
important = append(important, 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 important
}
func (t *dht) isImportant(ninfo *dhtInfo, important []*dhtInfo) bool {
// Check if ninfo is of equal or greater importance to what we already know
loc := t.core.switchTable.getLocator()
ndist := uint64(loc.dist(ninfo.coords))
minDist := ^uint64(0)
for _, info := range important {
dist := uint64(loc.dist(info.coords))
if dist < minDist {
minDist = dist
}
if dht_ordered(&t.nodeID, ninfo.getNodeID(), info.getNodeID()) && ndist <= minDist {
// This node is at least as close in both key space and tree space
return true
}
}
// We didn't find anything where this is better, so it must be worse
// We didn't find any important node that ninfo is better than
return false
}

View File

@ -183,7 +183,7 @@ func (p *peer) linkLoop() {
}
p.sendSwitchMsg()
case _ = <-tick.C:
break // FIXME disabled the below completely to test something
//break // FIXME disabled the below completely to test something
pdinfo := p.dinfo // FIXME this is a bad workarond NPE on the next line
if pdinfo != nil {
dinfo := *pdinfo

View File

@ -12,6 +12,7 @@ package yggdrasil
// A new search packet is sent periodically, once per second, in case a packet was dropped (this slowly causes the search to become parallel if the search doesn't timeout but also doesn't finish within 1 second for whatever reason)
import (
"fmt"
"sort"
"time"
)
@ -73,6 +74,9 @@ func (s *searches) handleDHTRes(res *dhtRes) {
sinfo, isIn := s.searches[res.Dest]
if !isIn || s.checkDHTRes(sinfo, res) {
// Either we don't recognize this search, or we just finished it
if isIn {
fmt.Println("DEBUG: search finished, length:", len(sinfo.visited))
}
return
} else {
// Add to the search and continue
@ -92,7 +96,7 @@ func (s *searches) addToSearch(sinfo *searchInfo, res *dhtRes) {
if *info.getNodeID() == s.core.dht.nodeID || sinfo.visited[*info.getNodeID()] {
continue
}
if dht_ordered(from.getNodeID(), info.getNodeID(), &res.Dest) {
if true || dht_ordered(from.getNodeID(), info.getNodeID(), &res.Dest) {
sinfo.toVisit = append(sinfo.toVisit, info)
}
}
@ -107,11 +111,13 @@ func (s *searches) addToSearch(sinfo *searchInfo, res *dhtRes) {
}
// Sort
sort.SliceStable(sinfo.toVisit, func(i, j int) bool {
// Should return true if i is closer to the destination than j
// FIXME for some reason it works better backwards, why?!
return dht_ordered(sinfo.toVisit[j].getNodeID(), sinfo.toVisit[i].getNodeID(), &res.Dest)
})
// Truncate to some maximum size
if len(sinfo.toVisit) > search_MAX_SEARCH_SIZE {
sinfo.toVisit = sinfo.toVisit[:search_MAX_SEARCH_SIZE]
//sinfo.toVisit = sinfo.toVisit[:search_MAX_SEARCH_SIZE]
}
}
@ -121,6 +127,7 @@ func (s *searches) doSearchStep(sinfo *searchInfo) {
if len(sinfo.toVisit) == 0 {
// Dead end, do cleanup
delete(s.searches, sinfo.dest)
fmt.Println("DEBUG: search abandoned, length:", len(sinfo.visited))
return
} else {
// Send to the next search target