user_validator.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package protocol
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. const (
  7. updateIntervalSec = 10
  8. cacheDurationSec = 120
  9. )
  10. type idEntry struct {
  11. id *ID
  12. userIdx int
  13. lastSec Timestamp
  14. lastSecRemoval Timestamp
  15. }
  16. type UserValidator interface {
  17. Add(user *User) error
  18. Get(timeHash []byte) (*User, Timestamp, bool)
  19. }
  20. type TimedUserValidator struct {
  21. validUsers []*User
  22. userHash map[[16]byte]*indexTimePair
  23. ids []*idEntry
  24. access sync.RWMutex
  25. hasher IDHash
  26. }
  27. type indexTimePair struct {
  28. index int
  29. timeSec Timestamp
  30. }
  31. func NewTimedUserValidator(hasher IDHash) UserValidator {
  32. tus := &TimedUserValidator{
  33. validUsers: make([]*User, 0, 16),
  34. userHash: make(map[[16]byte]*indexTimePair, 512),
  35. access: sync.RWMutex{},
  36. ids: make([]*idEntry, 0, 512),
  37. hasher: hasher,
  38. }
  39. go tus.updateUserHash(time.Tick(updateIntervalSec * time.Second))
  40. return tus
  41. }
  42. func (this *TimedUserValidator) generateNewHashes(nowSec Timestamp, idx int, entry *idEntry) {
  43. var hashValue [16]byte
  44. var hashValueRemoval [16]byte
  45. idHash := this.hasher(entry.id.Bytes())
  46. for entry.lastSec <= nowSec {
  47. idHash.Write(entry.lastSec.Bytes())
  48. idHash.Sum(hashValue[:0])
  49. idHash.Reset()
  50. idHash.Write(entry.lastSecRemoval.Bytes())
  51. idHash.Sum(hashValueRemoval[:0])
  52. idHash.Reset()
  53. this.access.Lock()
  54. this.userHash[hashValue] = &indexTimePair{idx, entry.lastSec}
  55. delete(this.userHash, hashValueRemoval)
  56. this.access.Unlock()
  57. entry.lastSec++
  58. entry.lastSecRemoval++
  59. }
  60. }
  61. func (this *TimedUserValidator) updateUserHash(tick <-chan time.Time) {
  62. for now := range tick {
  63. nowSec := Timestamp(now.Unix() + cacheDurationSec)
  64. for _, entry := range this.ids {
  65. this.generateNewHashes(nowSec, entry.userIdx, entry)
  66. }
  67. }
  68. }
  69. func (this *TimedUserValidator) Add(user *User) error {
  70. idx := len(this.validUsers)
  71. this.validUsers = append(this.validUsers, user)
  72. nowSec := time.Now().Unix()
  73. entry := &idEntry{
  74. id: user.ID,
  75. userIdx: idx,
  76. lastSec: Timestamp(nowSec - cacheDurationSec),
  77. lastSecRemoval: Timestamp(nowSec - cacheDurationSec*3),
  78. }
  79. this.generateNewHashes(Timestamp(nowSec+cacheDurationSec), idx, entry)
  80. this.ids = append(this.ids, entry)
  81. for _, alterid := range user.AlterIDs {
  82. entry := &idEntry{
  83. id: alterid,
  84. userIdx: idx,
  85. lastSec: Timestamp(nowSec - cacheDurationSec),
  86. lastSecRemoval: Timestamp(nowSec - cacheDurationSec*3),
  87. }
  88. this.generateNewHashes(Timestamp(nowSec+cacheDurationSec), idx, entry)
  89. this.ids = append(this.ids, entry)
  90. }
  91. return nil
  92. }
  93. func (this *TimedUserValidator) Get(userHash []byte) (*User, Timestamp, bool) {
  94. defer this.access.RUnlock()
  95. this.access.RLock()
  96. var fixedSizeHash [16]byte
  97. copy(fixedSizeHash[:], userHash)
  98. pair, found := this.userHash[fixedSizeHash]
  99. if found {
  100. return this.validUsers[pair.index], pair.timeSec, true
  101. }
  102. return nil, 0, false
  103. }