table.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. package dht
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/anacrolix/dht/v2/int160"
  6. )
  7. // Node table, with indexes on distance from root ID to bucket, and node addr.
  8. type table struct {
  9. rootID int160.T
  10. k int
  11. buckets [160]bucket
  12. addrs map[string]map[int160.T]struct{}
  13. }
  14. func (tbl *table) K() int {
  15. return tbl.k
  16. }
  17. func (tbl *table) randomIdForBucket(bucketIndex int) int160.T {
  18. randomId := randomIdInBucket(tbl.rootID, bucketIndex)
  19. if randomIdBucketIndex := tbl.bucketIndex(randomId); randomIdBucketIndex != bucketIndex {
  20. panic(fmt.Sprintf("bucket index for random id %v == %v not %v", randomId, randomIdBucketIndex, bucketIndex))
  21. }
  22. return randomId
  23. }
  24. func (tbl *table) addrNodes(addr Addr) []*node {
  25. a := tbl.addrs[addr.String()]
  26. ret := make([]*node, 0, len(a))
  27. for id := range a {
  28. ret = append(ret, tbl.getNode(addr, id))
  29. }
  30. return ret
  31. }
  32. func (tbl *table) dropNode(n *node) {
  33. as := n.Addr.String()
  34. if _, ok := tbl.addrs[as][n.Id]; !ok {
  35. panic("missing id for addr")
  36. }
  37. delete(tbl.addrs[as], n.Id)
  38. if len(tbl.addrs[as]) == 0 {
  39. delete(tbl.addrs, as)
  40. }
  41. b := tbl.bucketForID(n.Id)
  42. if _, ok := b.nodes[n]; !ok {
  43. panic("expected node in bucket")
  44. }
  45. delete(b.nodes, n)
  46. }
  47. func (tbl *table) bucketForID(id int160.T) *bucket {
  48. return &tbl.buckets[tbl.bucketIndex(id)]
  49. }
  50. func (tbl *table) numNodes() (num int) {
  51. for _, b := range tbl.buckets {
  52. num += b.Len()
  53. }
  54. return
  55. }
  56. func (tbl *table) bucketIndex(id int160.T) int {
  57. if id == tbl.rootID {
  58. panic("nobody puts the root ID in a bucket")
  59. }
  60. var a int160.T
  61. a.Xor(&tbl.rootID, &id)
  62. index := 160 - a.BitLen()
  63. return index
  64. }
  65. func (tbl *table) forNodes(f func(*node) bool) bool {
  66. for _, b := range tbl.buckets {
  67. if !b.EachNode(f) {
  68. return false
  69. }
  70. }
  71. return true
  72. }
  73. func (tbl *table) getNode(addr Addr, id int160.T) *node {
  74. if id == tbl.rootID {
  75. return nil
  76. }
  77. return tbl.buckets[tbl.bucketIndex(id)].GetNode(addr, id)
  78. }
  79. func (tbl *table) closestNodes(k int, target int160.T, filter func(*node) bool) (ret []*node) {
  80. for bi := func() int {
  81. if target == tbl.rootID {
  82. return len(tbl.buckets) - 1
  83. } else {
  84. return tbl.bucketIndex(target)
  85. }
  86. }(); bi >= 0 && len(ret) < k; bi-- {
  87. for n := range tbl.buckets[bi].nodes {
  88. if filter(n) {
  89. ret = append(ret, n)
  90. }
  91. }
  92. }
  93. // TODO: Keep only the closest.
  94. if len(ret) > k {
  95. ret = ret[:k]
  96. }
  97. return
  98. }
  99. func (tbl *table) addNode(n *node) error {
  100. if n.Id == tbl.rootID {
  101. return errors.New("is root id")
  102. }
  103. b := &tbl.buckets[tbl.bucketIndex(n.Id)]
  104. if b.GetNode(n.Addr, n.Id) != nil {
  105. return errors.New("already present")
  106. }
  107. if b.Len() >= tbl.k {
  108. return errors.New("bucket is full")
  109. }
  110. b.AddNode(n, tbl.k)
  111. if tbl.addrs == nil {
  112. tbl.addrs = make(map[string]map[int160.T]struct{}, 160*tbl.k)
  113. }
  114. as := n.Addr.String()
  115. if tbl.addrs[as] == nil {
  116. tbl.addrs[as] = make(map[int160.T]struct{}, 1)
  117. }
  118. tbl.addrs[as][n.Id] = struct{}{}
  119. return nil
  120. }