github.com/jonasnick/go-ethereum@v0.7.12-0.20150216215225-22176f05d387/event/filter/eth_filter.go (about)

     1  package filter
     2  
     3  // TODO make use of the generic filtering system
     4  
     5  import (
     6  	"sync"
     7  
     8  	"github.com/jonasnick/go-ethereum/core"
     9  	"github.com/jonasnick/go-ethereum/event"
    10  	"github.com/jonasnick/go-ethereum/state"
    11  )
    12  
    13  type FilterManager struct {
    14  	eventMux *event.TypeMux
    15  
    16  	filterMu sync.RWMutex
    17  	filterId int
    18  	filters  map[int]*core.Filter
    19  
    20  	quit chan struct{}
    21  }
    22  
    23  func NewFilterManager(mux *event.TypeMux) *FilterManager {
    24  	return &FilterManager{
    25  		eventMux: mux,
    26  		filters:  make(map[int]*core.Filter),
    27  	}
    28  }
    29  
    30  func (self *FilterManager) Start() {
    31  	go self.filterLoop()
    32  }
    33  
    34  func (self *FilterManager) Stop() {
    35  	close(self.quit)
    36  }
    37  
    38  func (self *FilterManager) InstallFilter(filter *core.Filter) (id int) {
    39  	self.filterMu.Lock()
    40  	id = self.filterId
    41  	self.filters[id] = filter
    42  	self.filterId++
    43  	self.filterMu.Unlock()
    44  	return id
    45  }
    46  
    47  func (self *FilterManager) UninstallFilter(id int) {
    48  	self.filterMu.Lock()
    49  	delete(self.filters, id)
    50  	self.filterMu.Unlock()
    51  }
    52  
    53  // GetFilter retrieves a filter installed using InstallFilter.
    54  // The filter may not be modified.
    55  func (self *FilterManager) GetFilter(id int) *core.Filter {
    56  	self.filterMu.RLock()
    57  	defer self.filterMu.RUnlock()
    58  	return self.filters[id]
    59  }
    60  
    61  func (self *FilterManager) filterLoop() {
    62  	// Subscribe to events
    63  	events := self.eventMux.Subscribe(core.PendingBlockEvent{}, core.NewBlockEvent{}, state.Logs(nil))
    64  
    65  out:
    66  	for {
    67  		select {
    68  		case <-self.quit:
    69  			break out
    70  		case event := <-events.Chan():
    71  			switch event := event.(type) {
    72  			case core.NewBlockEvent:
    73  				self.filterMu.RLock()
    74  				for _, filter := range self.filters {
    75  					if filter.BlockCallback != nil {
    76  						filter.BlockCallback(event.Block)
    77  					}
    78  				}
    79  				self.filterMu.RUnlock()
    80  
    81  			case core.PendingBlockEvent:
    82  				self.filterMu.RLock()
    83  				for _, filter := range self.filters {
    84  					if filter.PendingCallback != nil {
    85  						filter.PendingCallback(event.Block)
    86  					}
    87  				}
    88  				self.filterMu.RUnlock()
    89  
    90  			case state.Logs:
    91  				self.filterMu.RLock()
    92  				for _, filter := range self.filters {
    93  					if filter.LogsCallback != nil {
    94  						msgs := filter.FilterLogs(event)
    95  						if len(msgs) > 0 {
    96  							filter.LogsCallback(msgs)
    97  						}
    98  					}
    99  				}
   100  				self.filterMu.RUnlock()
   101  			}
   102  		}
   103  	}
   104  }