ergo/irc/whowas.go

106 lines
2.2 KiB
Go
Raw Normal View History

// Copyright (c) 2012-2014 Jeremy Latt
2017-03-27 14:15:02 +02:00
// Copyright (c) 2016 Daniel Oaks <daniel@danieloaks.net>
// released under the MIT license
package irc
2017-04-18 14:26:01 +02:00
import (
"sync"
)
// WhoWasList holds our list of prior clients (for use with the WHOWAS command).
type WhoWasList struct {
buffer []*WhoWas
2014-04-10 20:53:34 +02:00
start int
end int
2017-04-18 14:26:01 +02:00
accessMutex sync.RWMutex
}
// WhoWas is an entry in the WhoWasList.
type WhoWas struct {
nicknameCasefolded string
nickname string
username string
hostname string
realname string
}
// NewWhoWasList returns a new WhoWasList
func NewWhoWasList(size uint) *WhoWasList {
return &WhoWasList{
buffer: make([]*WhoWas, size+1),
}
}
// Append adds an entry to the WhoWasList.
func (list *WhoWasList) Append(client *Client) {
2017-04-18 14:26:01 +02:00
list.accessMutex.Lock()
defer list.accessMutex.Unlock()
list.buffer[list.end] = &WhoWas{
nicknameCasefolded: client.nickCasefolded,
nickname: client.nick,
username: client.username,
hostname: client.hostname,
realname: client.realname,
}
2014-04-10 20:53:34 +02:00
list.end = (list.end + 1) % len(list.buffer)
if list.end == list.start {
2014-04-10 20:53:34 +02:00
list.start = (list.end + 1) % len(list.buffer)
}
}
// Find tries to find an entry in our WhoWasList with the given details.
func (list *WhoWasList) Find(nickname string, limit int64) []*WhoWas {
2017-04-18 14:26:01 +02:00
list.accessMutex.RLock()
defer list.accessMutex.RUnlock()
results := make([]*WhoWas, 0)
casefoldedNickname, err := CasefoldName(nickname)
if err != nil {
return results
}
for whoWas := range list.Each() {
if casefoldedNickname != whoWas.nicknameCasefolded {
continue
}
results = append(results, whoWas)
if int64(len(results)) >= limit {
break
}
}
return results
}
2014-04-10 20:53:34 +02:00
func (list *WhoWasList) prev(index int) int {
2017-04-18 14:26:01 +02:00
list.accessMutex.RLock()
defer list.accessMutex.RUnlock()
2017-04-16 03:31:33 +02:00
index--
if index < 0 {
2014-04-10 20:53:34 +02:00
index += len(list.buffer)
}
return index
}
// Each iterates the WhoWasList in reverse.
func (list *WhoWasList) Each() <-chan *WhoWas {
ch := make(chan *WhoWas)
go func() {
defer close(ch)
if list.start == list.end {
return
}
start := list.prev(list.end)
end := list.prev(list.start)
for start != end {
ch <- list.buffer[start]
start = list.prev(start)
}
}()
return ch
}