github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/xeth/whisper_filter.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Contains the external API side message filter for watching, pooling and polling 18 // matched whisper messages, also serializing data access to avoid duplications. 19 20 package xeth 21 22 import ( 23 "sync" 24 "time" 25 26 "github.com/ethereum/go-ethereum/common" 27 ) 28 29 // whisperFilter is the message cache matching a specific filter, accumulating 30 // inbound messages until the are requested by the client. 31 type whisperFilter struct { 32 id int // Filter identifier for old message retrieval 33 ref *Whisper // Whisper reference for old message retrieval 34 35 cache []WhisperMessage // Cache of messages not yet polled 36 skip map[common.Hash]struct{} // List of retrieved messages to avoid duplication 37 update time.Time // Time of the last message query 38 39 lock sync.RWMutex // Lock protecting the filter internals 40 } 41 42 // newWhisperFilter creates a new serialized, poll based whisper topic filter. 43 func newWhisperFilter(id int, ref *Whisper) *whisperFilter { 44 return &whisperFilter{ 45 id: id, 46 ref: ref, 47 48 update: time.Now(), 49 skip: make(map[common.Hash]struct{}), 50 } 51 } 52 53 // messages retrieves all the cached messages from the entire pool matching the 54 // filter, resetting the filter's change buffer. 55 func (w *whisperFilter) messages() []WhisperMessage { 56 w.lock.Lock() 57 defer w.lock.Unlock() 58 59 w.cache = nil 60 w.update = time.Now() 61 62 w.skip = make(map[common.Hash]struct{}) 63 messages := w.ref.Messages(w.id) 64 for _, message := range messages { 65 w.skip[message.ref.Hash] = struct{}{} 66 } 67 return messages 68 } 69 70 // insert injects a new batch of messages into the filter cache. 71 func (w *whisperFilter) insert(messages ...WhisperMessage) { 72 w.lock.Lock() 73 defer w.lock.Unlock() 74 75 for _, message := range messages { 76 if _, ok := w.skip[message.ref.Hash]; !ok { 77 w.cache = append(w.cache, messages...) 78 } 79 } 80 } 81 82 // retrieve fetches all the cached messages from the filter. 83 func (w *whisperFilter) retrieve() (messages []WhisperMessage) { 84 w.lock.Lock() 85 defer w.lock.Unlock() 86 87 messages, w.cache = w.cache, nil 88 w.update = time.Now() 89 90 return 91 } 92 93 // activity returns the last time instance when client requests were executed on 94 // the filter. 95 func (w *whisperFilter) activity() time.Time { 96 w.lock.RLock() 97 defer w.lock.RUnlock() 98 99 return w.update 100 }