package dex
import (
"sync"
"github.com/dexon-foundation/dexon/event"
"github.com/dexon-foundation/dexon/log"
"github.com/dexon-foundation/dexon/p2p/enode"
"github.com/dexon-foundation/dexon/p2p/enr"
)
type newRecordsEvent struct{ Records []*enr.Record }
type nodeTable struct {
mu sync.RWMutex
entry map[enode.ID]*enode.Node
feed event.Feed
}
func newNodeTable() *nodeTable {
return &nodeTable{
entry: make(map[enode.ID]*enode.Node),
}
}
func (t *nodeTable) GetNode(id enode.ID) *enode.Node {
t.mu.RLock()
defer t.mu.RUnlock()
return t.entry[id]
}
func (t *nodeTable) AddRecords(records []*enr.Record) {
t.mu.Lock()
defer t.mu.Unlock()
var newRecords []*enr.Record
for _, record := range records {
node, err := enode.New(enode.ValidSchemes, record)
if err != nil {
log.Error("invalid node record", "err", err)
return
}
if n, ok := t.entry[node.ID()]; ok && n.Seq() >= node.Seq() {
log.Debug("Ignore new record, already exists", "id", node.ID().String(),
"ip", node.IP().String(), "udp", node.UDP(), "tcp", node.TCP())
continue
}
t.entry[node.ID()] = node
newRecords = append(newRecords, record)
log.Debug("Add new record to node table", "id", node.ID().String(),
"ip", node.IP().String(), "udp", node.UDP(), "tcp", node.TCP())
}
if len(newRecords) > 0 {
go t.feed.Send(newRecordsEvent{newRecords})
}
}
func (t *nodeTable) Records() []*enr.Record {
t.mu.RLock()
defer t.mu.RUnlock()
records := make([]*enr.Record, 0, len(t.entry))
for _, node := range t.entry {
records = append(records, node.Record())
}
return records
}
func (t *nodeTable) SubscribeNewRecordsEvent(
ch chan<- newRecordsEvent) event.Subscription {
return t.feed.Subscribe(ch)
}