您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // Copyright (c) 2012-2014 Jeremy Latt
  2. // Copyright (c) 2016 Daniel Oaks <daniel@danieloaks.net>
  3. // released under the MIT license
  4. package irc
  5. import (
  6. "sync"
  7. )
  8. // WhoWasList holds our list of prior clients (for use with the WHOWAS command).
  9. type WhoWasList struct {
  10. buffer []*WhoWas
  11. start int
  12. end int
  13. accessMutex sync.RWMutex // tier 2
  14. }
  15. // WhoWas is an entry in the WhoWasList.
  16. type WhoWas struct {
  17. nicknameCasefolded string
  18. nickname string
  19. username string
  20. hostname string
  21. realname string
  22. }
  23. // NewWhoWasList returns a new WhoWasList
  24. func NewWhoWasList(size uint) *WhoWasList {
  25. return &WhoWasList{
  26. buffer: make([]*WhoWas, size+1),
  27. }
  28. }
  29. // Append adds an entry to the WhoWasList.
  30. func (list *WhoWasList) Append(client *Client) {
  31. list.accessMutex.Lock()
  32. defer list.accessMutex.Unlock()
  33. list.buffer[list.end] = &WhoWas{
  34. nicknameCasefolded: client.nickCasefolded,
  35. nickname: client.nick,
  36. username: client.username,
  37. hostname: client.hostname,
  38. realname: client.realname,
  39. }
  40. list.end = (list.end + 1) % len(list.buffer)
  41. if list.end == list.start {
  42. list.start = (list.end + 1) % len(list.buffer)
  43. }
  44. }
  45. // Find tries to find an entry in our WhoWasList with the given details.
  46. func (list *WhoWasList) Find(nickname string, limit int64) []*WhoWas {
  47. list.accessMutex.RLock()
  48. defer list.accessMutex.RUnlock()
  49. results := make([]*WhoWas, 0)
  50. casefoldedNickname, err := CasefoldName(nickname)
  51. if err != nil {
  52. return results
  53. }
  54. for whoWas := range list.Each() {
  55. if casefoldedNickname != whoWas.nicknameCasefolded {
  56. continue
  57. }
  58. results = append(results, whoWas)
  59. if int64(len(results)) >= limit {
  60. break
  61. }
  62. }
  63. return results
  64. }
  65. func (list *WhoWasList) prev(index int) int {
  66. list.accessMutex.RLock()
  67. defer list.accessMutex.RUnlock()
  68. index--
  69. if index < 0 {
  70. index += len(list.buffer)
  71. }
  72. return index
  73. }
  74. // Each iterates the WhoWasList in reverse.
  75. func (list *WhoWasList) Each() <-chan *WhoWas {
  76. ch := make(chan *WhoWas)
  77. go func() {
  78. defer close(ch)
  79. if list.start == list.end {
  80. return
  81. }
  82. start := list.prev(list.end)
  83. end := list.prev(list.start)
  84. for start != end {
  85. ch <- list.buffer[start]
  86. start = list.prev(start)
  87. }
  88. }()
  89. return ch
  90. }