You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
1.8 KiB

  1. package mempool
  2. import (
  3. "fmt"
  4. "sync"
  5. "github.com/tendermint/tendermint/types"
  6. )
  7. type IDs struct {
  8. mtx sync.RWMutex
  9. peerMap map[types.NodeID]uint16
  10. nextID uint16 // assumes that a node will never have over 65536 active peers
  11. activeIDs map[uint16]struct{} // used to check if a given peerID key is used
  12. }
  13. func NewMempoolIDs() *IDs {
  14. return &IDs{
  15. peerMap: make(map[types.NodeID]uint16),
  16. // reserve UnknownPeerID for mempoolReactor.BroadcastTx
  17. activeIDs: map[uint16]struct{}{UnknownPeerID: {}},
  18. nextID: 1,
  19. }
  20. }
  21. // ReserveForPeer searches for the next unused ID and assigns it to the provided
  22. // peer.
  23. func (ids *IDs) ReserveForPeer(peerID types.NodeID) {
  24. ids.mtx.Lock()
  25. defer ids.mtx.Unlock()
  26. if _, ok := ids.peerMap[peerID]; ok {
  27. // the peer has been reserved
  28. return
  29. }
  30. curID := ids.nextPeerID()
  31. ids.peerMap[peerID] = curID
  32. ids.activeIDs[curID] = struct{}{}
  33. }
  34. // Reclaim returns the ID reserved for the peer back to unused pool.
  35. func (ids *IDs) Reclaim(peerID types.NodeID) {
  36. ids.mtx.Lock()
  37. defer ids.mtx.Unlock()
  38. removedID, ok := ids.peerMap[peerID]
  39. if ok {
  40. delete(ids.activeIDs, removedID)
  41. delete(ids.peerMap, peerID)
  42. if removedID < ids.nextID {
  43. ids.nextID = removedID
  44. }
  45. }
  46. }
  47. // GetForPeer returns an ID reserved for the peer.
  48. func (ids *IDs) GetForPeer(peerID types.NodeID) uint16 {
  49. ids.mtx.RLock()
  50. defer ids.mtx.RUnlock()
  51. return ids.peerMap[peerID]
  52. }
  53. // nextPeerID returns the next unused peer ID to use. We assume that the mutex
  54. // is already held.
  55. func (ids *IDs) nextPeerID() uint16 {
  56. if len(ids.activeIDs) == MaxActiveIDs {
  57. panic(fmt.Sprintf("node has maximum %d active IDs and wanted to get one more", MaxActiveIDs))
  58. }
  59. _, idExists := ids.activeIDs[ids.nextID]
  60. for idExists {
  61. ids.nextID++
  62. _, idExists = ids.activeIDs[ids.nextID]
  63. }
  64. curID := ids.nextID
  65. ids.nextID++
  66. return curID
  67. }