|
|
@@ -31,30 +31,32 @@ import (
|
|
|
// block, transaction and log events. The Filtering system can be used to listen
|
|
|
// for specific LOG events fired by the EVM (Ethereum Virtual Machine).
|
|
|
type FilterSystem struct {
|
|
|
- eventMux *event.TypeMux
|
|
|
-
|
|
|
filterMu sync.RWMutex
|
|
|
filterId int
|
|
|
filters map[int]*Filter
|
|
|
created map[int]time.Time
|
|
|
-
|
|
|
- quit chan struct{}
|
|
|
+ sub event.Subscription
|
|
|
}
|
|
|
|
|
|
// NewFilterSystem returns a newly allocated filter manager
|
|
|
func NewFilterSystem(mux *event.TypeMux) *FilterSystem {
|
|
|
fs := &FilterSystem{
|
|
|
- eventMux: mux,
|
|
|
- filters: make(map[int]*Filter),
|
|
|
- created: make(map[int]time.Time),
|
|
|
+ filters: make(map[int]*Filter),
|
|
|
+ created: make(map[int]time.Time),
|
|
|
}
|
|
|
+ fs.sub = mux.Subscribe(
|
|
|
+ //core.PendingBlockEvent{},
|
|
|
+ core.ChainEvent{},
|
|
|
+ core.TxPreEvent{},
|
|
|
+ vm.Logs(nil),
|
|
|
+ )
|
|
|
go fs.filterLoop()
|
|
|
return fs
|
|
|
}
|
|
|
|
|
|
// Stop quits the filter loop required for polling events
|
|
|
func (fs *FilterSystem) Stop() {
|
|
|
- close(fs.quit)
|
|
|
+ fs.sub.Unsubscribe()
|
|
|
}
|
|
|
|
|
|
// Add adds a filter to the filter manager
|
|
|
@@ -89,57 +91,37 @@ func (fs *FilterSystem) Get(id int) *Filter {
|
|
|
// filterLoop waits for specific events from ethereum and fires their handlers
|
|
|
// when the filter matches the requirements.
|
|
|
func (fs *FilterSystem) filterLoop() {
|
|
|
- // Subscribe to events
|
|
|
- eventCh := fs.eventMux.Subscribe(
|
|
|
- //core.PendingBlockEvent{},
|
|
|
- core.ChainEvent{},
|
|
|
- core.TxPreEvent{},
|
|
|
- vm.Logs(nil),
|
|
|
- ).Chan()
|
|
|
-
|
|
|
-out:
|
|
|
- for {
|
|
|
- select {
|
|
|
- case <-fs.quit:
|
|
|
- break out
|
|
|
- case event, ok := <-eventCh:
|
|
|
- if !ok {
|
|
|
- // Event subscription closed, set the channel to nil to stop spinning
|
|
|
- eventCh = nil
|
|
|
- continue
|
|
|
- }
|
|
|
- // A real event arrived, notify the registered filters
|
|
|
- switch ev := event.Data.(type) {
|
|
|
- case core.ChainEvent:
|
|
|
- fs.filterMu.RLock()
|
|
|
- for id, filter := range fs.filters {
|
|
|
- if filter.BlockCallback != nil && fs.created[id].Before(event.Time) {
|
|
|
- filter.BlockCallback(ev.Block, ev.Logs)
|
|
|
- }
|
|
|
+ for event := range fs.sub.Chan() {
|
|
|
+ switch ev := event.Data.(type) {
|
|
|
+ case core.ChainEvent:
|
|
|
+ fs.filterMu.RLock()
|
|
|
+ for id, filter := range fs.filters {
|
|
|
+ if filter.BlockCallback != nil && fs.created[id].Before(event.Time) {
|
|
|
+ filter.BlockCallback(ev.Block, ev.Logs)
|
|
|
}
|
|
|
- fs.filterMu.RUnlock()
|
|
|
+ }
|
|
|
+ fs.filterMu.RUnlock()
|
|
|
|
|
|
- case core.TxPreEvent:
|
|
|
- fs.filterMu.RLock()
|
|
|
- for id, filter := range fs.filters {
|
|
|
- if filter.TransactionCallback != nil && fs.created[id].Before(event.Time) {
|
|
|
- filter.TransactionCallback(ev.Tx)
|
|
|
- }
|
|
|
+ case core.TxPreEvent:
|
|
|
+ fs.filterMu.RLock()
|
|
|
+ for id, filter := range fs.filters {
|
|
|
+ if filter.TransactionCallback != nil && fs.created[id].Before(event.Time) {
|
|
|
+ filter.TransactionCallback(ev.Tx)
|
|
|
}
|
|
|
- fs.filterMu.RUnlock()
|
|
|
-
|
|
|
- case vm.Logs:
|
|
|
- fs.filterMu.RLock()
|
|
|
- for id, filter := range fs.filters {
|
|
|
- if filter.LogsCallback != nil && fs.created[id].Before(event.Time) {
|
|
|
- msgs := filter.FilterLogs(ev)
|
|
|
- if len(msgs) > 0 {
|
|
|
- filter.LogsCallback(msgs)
|
|
|
- }
|
|
|
+ }
|
|
|
+ fs.filterMu.RUnlock()
|
|
|
+
|
|
|
+ case vm.Logs:
|
|
|
+ fs.filterMu.RLock()
|
|
|
+ for id, filter := range fs.filters {
|
|
|
+ if filter.LogsCallback != nil && fs.created[id].Before(event.Time) {
|
|
|
+ msgs := filter.FilterLogs(ev)
|
|
|
+ if len(msgs) > 0 {
|
|
|
+ filter.LogsCallback(msgs)
|
|
|
}
|
|
|
}
|
|
|
- fs.filterMu.RUnlock()
|
|
|
}
|
|
|
+ fs.filterMu.RUnlock()
|
|
|
}
|
|
|
}
|
|
|
}
|