whisper: add pool to matched

This commit is contained in:
b00ris 2018-02-21 18:51:55 +03:00
parent 376e7953df
commit 41353474f7
2 changed files with 55 additions and 55 deletions

View file

@ -104,11 +104,14 @@ func (fs *Filters) Get(id string) *Filter {
func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) { func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
var msg *ReceivedMessage var msg *ReceivedMessage
matchedTopics := fs.topicMatcher.take()
defer fs.topicMatcher.resolve(matchedTopics)
fs.mutex.RLock() fs.mutex.RLock()
defer fs.mutex.RUnlock() defer fs.mutex.RUnlock()
for watcherID := range fs.topicMatcher.matchedTopics(env.Topic) { fs.topicMatcher.matchedTopics(env.Topic, &matchedTopics)
for _, watcherID := range matchedTopics {
watcher, ok := fs.watchers[watcherID] watcher, ok := fs.watchers[watcherID]
if !ok { if !ok {
log.Trace(fmt.Sprintf("msg [%x], filter [%s]: filter not exists", env.Hash(), watcherID)) log.Trace(fmt.Sprintf("msg [%x], filter [%s]: filter not exists", env.Hash(), watcherID))
@ -224,16 +227,30 @@ func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool {
return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0 return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0
} }
type topicMatcher struct {
mapper map[string]map[string]struct{}
mx sync.RWMutex
pool sync.Pool
}
func newTopicMatcher() *topicMatcher { func newTopicMatcher() *topicMatcher {
tm := new(topicMatcher) tm := new(topicMatcher)
tm.mapper = make(map[string]map[string]struct{}) tm.mapper = make(map[string]map[string]struct{})
tm.mapper[ALL_TOPICS] = make(map[string]struct{}) tm.mapper[ALL_TOPICS] = make(map[string]struct{})
tm.pool.New = func() interface{} {
return []string{}
}
return tm return tm
} }
type topicMatcher struct { func (fs *topicMatcher) take() []string {
mapper map[string]map[string]struct{} return fs.pool.Get().([]string)
mx sync.RWMutex }
func (fs *topicMatcher) resolve(s []string) {
if cap(s) > 1000 {
return
}
fs.pool.Put(s[:0])
} }
func (fs *topicMatcher) addFilterToTopicsMapping(watcher *Filter, id string) { func (fs *topicMatcher) addFilterToTopicsMapping(watcher *Filter, id string) {
@ -259,8 +276,6 @@ func (fs *topicMatcher) removeTopicFromTopicMapping(id string) {
} }
func (fs *topicMatcher) prepareTopicsMapping(watcher *Filter) map[string]struct{} { func (fs *topicMatcher) prepareTopicsMapping(watcher *Filter) map[string]struct{} {
fs.mx.RLock()
defer fs.mx.RUnlock()
topics := make(map[string]struct{}, len(watcher.Topics)) topics := make(map[string]struct{}, len(watcher.Topics))
if len(watcher.Topics) == 0 { if len(watcher.Topics) == 0 {
@ -275,18 +290,15 @@ func (fs *topicMatcher) prepareTopicsMapping(watcher *Filter) map[string]struct{
return topics return topics
} }
func (fs *topicMatcher) matchedTopics(topic TopicType) map[string]struct{} { func (fs *topicMatcher) matchedTopics(topic TopicType, matched *[]string) {
fs.mx.RLock() fs.mx.RLock()
defer fs.mx.RUnlock() defer fs.mx.RUnlock()
m := make(map[string]struct{}, len(fs.mapper[ALL_TOPICS])+len(fs.mapper[topic.String()]))
for i := range fs.mapper[ALL_TOPICS] { for i := range fs.mapper[ALL_TOPICS] {
m[i] = struct{}{} *matched = append(*matched, i)
} }
for i := range fs.mapper[topic.String()] { for i := range fs.mapper[topic.String()] {
m[i] = struct{}{} *matched = append(*matched, i)
} }
return m
} }

View file

@ -489,33 +489,6 @@ func TestMatchMessageAsym(t *testing.T) {
t.Fatalf("failed MatchEnvelope(sufficient PoW) with seed %d.", seed) t.Fatalf("failed MatchEnvelope(sufficient PoW) with seed %d.", seed)
} }
fs := generateFilters()
filterID, err := fs.Install(f)
if err != nil {
t.Fatalf("failed filter install with seed %d: %s.", seed, err)
}
m := fs.topicMatcher.matchedTopics(env.Topic)
_, matchedTopic := m[filterID]
if !matchedTopic {
t.Fatalf("failed MatchEnvelope(topic mismatch) with seed %d.", seed)
}
// topic mismatch
if !fs.Uninstall(filterID) {
t.Fatal("failed to uninstall filter")
}
f.Topics[index][0]++
filterID, err = fs.Install(f)
m = fs.topicMatcher.matchedTopics(env.Topic)
_, matchedTopic = m[filterID]
if matchedTopic {
t.Fatalf("failed MatchEnvelope(topic mismatch) with seed %d.", seed)
}
f.Topics[index][0]--
// key mismatch // key mismatch
prev := *f.KeyAsym.PublicKey.X prev := *f.KeyAsym.PublicKey.X
zero := *big.NewInt(0) zero := *big.NewInt(0)
@ -761,10 +734,10 @@ func TestVariableTopics(t *testing.T) {
env.Topic = BytesToTopic(f.Topics[i]) env.Topic = BytesToTopic(f.Topics[i])
//test match //test match
m := fs.topicMatcher.matchedTopics(env.Topic) matched := []string{}
_, ok := m[filterID] fs.topicMatcher.matchedTopics(env.Topic, &matched)
match = f.MatchEnvelope(env) match = f.MatchEnvelope(env)
if !(match && ok) { if !(match && hasFilterID(matched, filterID)) {
t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed, i) t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed, i)
} }
@ -773,9 +746,10 @@ func TestVariableTopics(t *testing.T) {
//false positive test //false positive test
match = f.MatchEnvelope(env) match = f.MatchEnvelope(env)
m = fs.topicMatcher.matchedTopics(env.Topic)
_, ok = m[filterID] matched = matched[:0]
if match && ok { fs.topicMatcher.matchedTopics(env.Topic, &matched)
if match && hasFilterID(matched, filterID) {
t.Fatalf("MatchEnvelope symmetric with seed %d, step %d: false positive.", seed, i) t.Fatalf("MatchEnvelope symmetric with seed %d, step %d: false positive.", seed, i)
} }
} }
@ -812,8 +786,9 @@ func TestTopicsMapping(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
m := fs.topicMatcher.matchedTopics(env.Topic) matched := []string{}
if _, matchTopic := m[filterID]; !matchTopic { fs.topicMatcher.matchedTopics(env.Topic, &matched)
if !hasFilterID(matched, filterID) {
t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed, i) t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed, i)
} }
@ -821,8 +796,9 @@ func TestTopicsMapping(t *testing.T) {
if !fs.Uninstall(filterID) { if !fs.Uninstall(filterID) {
t.Fatal("Failed to uninstall filter") t.Fatal("Failed to uninstall filter")
} }
m = fs.topicMatcher.matchedTopics(env.Topic) matched = matched[:0]
if _, matchTopic := m[filterID]; matchTopic { fs.topicMatcher.matchedTopics(env.Topic, &matched)
if hasFilterID(matched, filterID) {
t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed, i) t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed, i)
} }
@ -832,8 +808,9 @@ func TestTopicsMapping(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
m = fs.topicMatcher.matchedTopics(env.Topic) matched = matched[:0]
if _, matchTopic := m[filterID]; matchTopic { fs.topicMatcher.matchedTopics(env.Topic, &matched)
if hasFilterID(matched, filterID) {
t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed, i) t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed, i)
} }
if !fs.Uninstall(filterID) { if !fs.Uninstall(filterID) {
@ -862,8 +839,9 @@ func TestTopicsMapping_MatchAllTopics_Success(t *testing.T) {
topic := TopicType{} topic := TopicType{}
mrand.Read(topic[:]) mrand.Read(topic[:])
m := fs.topicMatcher.matchedTopics(topic) matched := []string{}
if _, matchTopic := m[filterID]; !matchTopic { fs.topicMatcher.matchedTopics(topic, &matched)
if !hasFilterID(matched, filterID) {
t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed) t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed)
} }
if _, ok := fs.topicMatcher.mapper[ALL_TOPICS][filterID]; !ok { if _, ok := fs.topicMatcher.mapper[ALL_TOPICS][filterID]; !ok {
@ -874,8 +852,9 @@ func TestTopicsMapping_MatchAllTopics_Success(t *testing.T) {
if !fs.Uninstall(filterID) { if !fs.Uninstall(filterID) {
t.Fatal("Failed to uninstall filter") t.Fatal("Failed to uninstall filter")
} }
m = fs.topicMatcher.matchedTopics(topic) matched = matched[:0]
if _, matchTopic := m[filterID]; matchTopic { fs.topicMatcher.matchedTopics(topic, &matched)
if hasFilterID(matched, filterID) {
t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed) t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed)
} }
@ -883,3 +862,12 @@ func TestTopicsMapping_MatchAllTopics_Success(t *testing.T) {
t.Fatal("watcher mapping incorrect") t.Fatal("watcher mapping incorrect")
} }
} }
func hasFilterID(matched []string, filterID string) bool {
for i := range matched {
if matched[i] == filterID {
return true
}
}
return false
}