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  }