cmd/bootnode, eth, p2p, p2p/discover: use a fancier db design
This commit is contained in:
@ -27,7 +27,7 @@ type Table struct {
|
||||
mutex sync.Mutex // protects buckets, their content, and nursery
|
||||
buckets [nBuckets]*bucket // index of known nodes by distance
|
||||
nursery []*Node // bootstrap nodes
|
||||
cache *Cache // cache of known nodes
|
||||
db *nodeDB // database of known nodes
|
||||
|
||||
bondmu sync.Mutex
|
||||
bonding map[NodeID]*bondproc
|
||||
@ -61,15 +61,17 @@ type bucket struct {
|
||||
entries []*Node
|
||||
}
|
||||
|
||||
func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr, seeder *Cache) *Table {
|
||||
func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr, nodeDBPath string) *Table {
|
||||
// If no seed cache was given, use an in-memory one
|
||||
if seeder == nil {
|
||||
seeder, _ = NewMemoryCache()
|
||||
db, err := newNodeDB(nodeDBPath)
|
||||
if err != nil {
|
||||
glog.V(logger.Warn).Infoln("Failed to open node database:", err)
|
||||
db, _ = newNodeDB("")
|
||||
}
|
||||
// Create the bootstrap table
|
||||
tab := &Table{
|
||||
net: t,
|
||||
cache: seeder,
|
||||
db: db,
|
||||
self: newNode(ourID, ourAddr),
|
||||
bonding: make(map[NodeID]*bondproc),
|
||||
bondslots: make(chan struct{}, maxBondingPingPongs),
|
||||
@ -91,6 +93,7 @@ func (tab *Table) Self() *Node {
|
||||
// Close terminates the network listener and flushes the seed cache.
|
||||
func (tab *Table) Close() {
|
||||
tab.net.close()
|
||||
tab.db.close()
|
||||
}
|
||||
|
||||
// Bootstrap sets the bootstrap nodes. These nodes are used to connect
|
||||
@ -174,11 +177,10 @@ func (tab *Table) refresh() {
|
||||
|
||||
result := tab.Lookup(randomID(tab.self.ID, ld))
|
||||
if len(result) == 0 {
|
||||
// Pick a batch of previously know seeds to lookup with and discard them (will come back if they are still live)
|
||||
seeds := tab.cache.list(10)
|
||||
// Pick a batch of previously know seeds to lookup with
|
||||
seeds := tab.db.querySeeds(10)
|
||||
for _, seed := range seeds {
|
||||
glog.V(logger.Debug).Infoln("Seeding network with:", seed)
|
||||
tab.cache.delete(seed.ID)
|
||||
glog.V(logger.Debug).Infoln("Seeding network with", seed)
|
||||
}
|
||||
// Bootstrap the table with a self lookup
|
||||
all := tab.bondall(append(tab.nursery, seeds...))
|
||||
@ -249,7 +251,7 @@ func (tab *Table) bondall(nodes []*Node) (result []*Node) {
|
||||
// of the process can be skipped.
|
||||
func (tab *Table) bond(pinged bool, id NodeID, addr *net.UDPAddr, tcpPort uint16) (*Node, error) {
|
||||
var n *Node
|
||||
if n = tab.cache.get(id); n == nil {
|
||||
if n = tab.db.node(id); n == nil {
|
||||
tab.bondmu.Lock()
|
||||
w := tab.bonding[id]
|
||||
if w != nil {
|
||||
@ -282,8 +284,12 @@ func (tab *Table) bond(pinged bool, id NodeID, addr *net.UDPAddr, tcpPort uint16
|
||||
}
|
||||
|
||||
func (tab *Table) pingpong(w *bondproc, pinged bool, id NodeID, addr *net.UDPAddr, tcpPort uint16) {
|
||||
// Request a bonding slot to limit network usage
|
||||
<-tab.bondslots
|
||||
defer func() { tab.bondslots <- struct{}{} }()
|
||||
|
||||
// Ping the remote side and wait for a pong
|
||||
tab.db.updateLastPing(id, time.Now())
|
||||
if w.err = tab.net.ping(id, addr); w.err != nil {
|
||||
close(w.done)
|
||||
return
|
||||
@ -294,7 +300,15 @@ func (tab *Table) pingpong(w *bondproc, pinged bool, id NodeID, addr *net.UDPAdd
|
||||
// waitping will simply time out.
|
||||
tab.net.waitping(id)
|
||||
}
|
||||
w.n = tab.cache.add(id, addr, tcpPort)
|
||||
// Bonding succeeded, update the node database
|
||||
w.n = &Node{
|
||||
ID: id,
|
||||
IP: addr.IP,
|
||||
DiscPort: addr.Port,
|
||||
TCPPort: int(tcpPort),
|
||||
}
|
||||
tab.db.updateNode(w.n)
|
||||
tab.db.updateLastBond(id, time.Now())
|
||||
close(w.done)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user