github.com/m3shine/gochain@v2.2.26+incompatible/core/events.go (about)

     1  // Copyright 2014 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  package core
    18  
    19  import (
    20  	"fmt"
    21  	"sync"
    22  	"time"
    23  
    24  	"github.com/gochain-io/gochain/common"
    25  	"github.com/gochain-io/gochain/core/types"
    26  	"github.com/gochain-io/gochain/log"
    27  )
    28  
    29  const timeout = 500 * time.Millisecond
    30  
    31  // NewTxsEvent is posted when a batch of transactions enter the transaction pool.
    32  type NewTxsEvent struct{ Txs []*types.Transaction }
    33  
    34  // PendingLogsEvent is posted pre mining and notifies of pending logs.
    35  type PendingLogsEvent struct {
    36  	Logs []*types.Log
    37  }
    38  
    39  // PendingStateEvent is posted pre mining and notifies of pending state changes.
    40  type PendingStateEvent struct{}
    41  
    42  // NewMinedBlockEvent is posted when a block has been imported.
    43  type NewMinedBlockEvent struct{ Block *types.Block }
    44  
    45  // RemovedLogsEvent is posted when a reorg happens
    46  type RemovedLogsEvent struct{ Logs []*types.Log }
    47  
    48  type ChainEvent struct {
    49  	Block *types.Block
    50  	Hash  common.Hash
    51  	Logs  []*types.Log
    52  }
    53  
    54  type ChainSideEvent struct {
    55  	Block *types.Block
    56  }
    57  
    58  type ChainHeadEvent struct{ Block *types.Block }
    59  
    60  type NewTxsFeed struct {
    61  	mu   sync.RWMutex
    62  	subs map[chan<- NewTxsEvent]string
    63  }
    64  
    65  func (f *NewTxsFeed) Close() {
    66  	f.mu.Lock()
    67  	defer f.mu.Unlock()
    68  	for sub := range f.subs {
    69  		close(sub)
    70  	}
    71  	f.subs = nil
    72  }
    73  
    74  func (f *NewTxsFeed) Subscribe(ch chan<- NewTxsEvent, name string) {
    75  	f.mu.Lock()
    76  	defer f.mu.Unlock()
    77  	if f.subs == nil {
    78  		f.subs = make(map[chan<- NewTxsEvent]string)
    79  	}
    80  	f.subs[ch] = name
    81  }
    82  
    83  func (f *NewTxsFeed) Unsubscribe(ch chan<- NewTxsEvent) {
    84  	f.mu.Lock()
    85  	defer f.mu.Unlock()
    86  	if _, ok := f.subs[ch]; ok {
    87  		delete(f.subs, ch)
    88  		close(ch)
    89  	}
    90  }
    91  
    92  func (f *NewTxsFeed) Send(ev NewTxsEvent) {
    93  	f.mu.RLock()
    94  	defer f.mu.RUnlock()
    95  	for sub, name := range f.subs {
    96  		select {
    97  		case sub <- ev:
    98  		default:
    99  			start := time.Now()
   100  			var action string
   101  			select {
   102  			case sub <- ev:
   103  				action = "delayed"
   104  			case <-time.After(timeout):
   105  				action = "dropped"
   106  			}
   107  			dur := time.Since(start)
   108  			log.Warn(fmt.Sprintf("NewTxsFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "txs", len(ev.Txs))
   109  		}
   110  	}
   111  }
   112  
   113  type ChainFeed struct {
   114  	mu   sync.RWMutex
   115  	subs map[chan<- ChainEvent]string
   116  }
   117  
   118  func (f *ChainFeed) Close() {
   119  	f.mu.Lock()
   120  	defer f.mu.Unlock()
   121  	for sub := range f.subs {
   122  		close(sub)
   123  	}
   124  	f.subs = nil
   125  }
   126  
   127  func (f *ChainFeed) Subscribe(ch chan<- ChainEvent, name string) {
   128  	f.mu.Lock()
   129  	defer f.mu.Unlock()
   130  	if f.subs == nil {
   131  		f.subs = make(map[chan<- ChainEvent]string)
   132  	}
   133  	f.subs[ch] = name
   134  }
   135  
   136  func (f *ChainFeed) Unsubscribe(ch chan<- ChainEvent) {
   137  	f.mu.Lock()
   138  	defer f.mu.Unlock()
   139  	if _, ok := f.subs[ch]; ok {
   140  		delete(f.subs, ch)
   141  		close(ch)
   142  	}
   143  }
   144  
   145  func (f *ChainFeed) Send(ev ChainEvent) {
   146  	f.mu.RLock()
   147  	defer f.mu.RUnlock()
   148  	for sub, name := range f.subs {
   149  		select {
   150  		case sub <- ev:
   151  		default:
   152  			start := time.Now()
   153  			var action string
   154  			select {
   155  			case sub <- ev:
   156  				action = "delayed"
   157  			case <-time.After(timeout):
   158  				action = "dropped"
   159  			}
   160  			dur := time.Since(start)
   161  			log.Warn(fmt.Sprintf("ChainFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "block", ev.Block.NumberU64(), "hash", ev.Hash)
   162  		}
   163  	}
   164  }
   165  
   166  type ChainHeadFeed struct {
   167  	mu   sync.RWMutex
   168  	subs map[chan<- ChainHeadEvent]string
   169  }
   170  
   171  func (f *ChainHeadFeed) Close() {
   172  	f.mu.Lock()
   173  	defer f.mu.Unlock()
   174  	for sub := range f.subs {
   175  		close(sub)
   176  	}
   177  	f.subs = nil
   178  }
   179  
   180  func (f *ChainHeadFeed) Subscribe(ch chan<- ChainHeadEvent, name string) {
   181  	f.mu.Lock()
   182  	defer f.mu.Unlock()
   183  	if f.subs == nil {
   184  		f.subs = make(map[chan<- ChainHeadEvent]string)
   185  	}
   186  	f.subs[ch] = name
   187  }
   188  
   189  func (f *ChainHeadFeed) Unsubscribe(ch chan<- ChainHeadEvent) {
   190  	f.mu.Lock()
   191  	defer f.mu.Unlock()
   192  	if _, ok := f.subs[ch]; ok {
   193  		delete(f.subs, ch)
   194  		close(ch)
   195  	}
   196  }
   197  
   198  func (f *ChainHeadFeed) Send(ev ChainHeadEvent) {
   199  	f.mu.RLock()
   200  	defer f.mu.RUnlock()
   201  	for sub, name := range f.subs {
   202  		select {
   203  		case sub <- ev:
   204  		default:
   205  			start := time.Now()
   206  			var action string
   207  			select {
   208  			case sub <- ev:
   209  				action = "delayed"
   210  			case <-time.After(timeout):
   211  				action = "dropped"
   212  			}
   213  			dur := time.Since(start)
   214  			log.Warn(fmt.Sprintf("ChainHeadFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "block", ev.Block.NumberU64(), "hash", ev.Block.Hash())
   215  		}
   216  	}
   217  }
   218  
   219  type ChainSideFeed struct {
   220  	mu   sync.RWMutex
   221  	subs map[chan<- ChainSideEvent]string
   222  }
   223  
   224  func (f *ChainSideFeed) Close() {
   225  	f.mu.Lock()
   226  	defer f.mu.Unlock()
   227  	for sub := range f.subs {
   228  		close(sub)
   229  	}
   230  	f.subs = nil
   231  }
   232  
   233  func (f *ChainSideFeed) Subscribe(ch chan<- ChainSideEvent, name string) {
   234  	f.mu.Lock()
   235  	defer f.mu.Unlock()
   236  	if f.subs == nil {
   237  		f.subs = make(map[chan<- ChainSideEvent]string)
   238  	}
   239  	f.subs[ch] = name
   240  }
   241  
   242  func (f *ChainSideFeed) Unsubscribe(ch chan<- ChainSideEvent) {
   243  	f.mu.Lock()
   244  	defer f.mu.Unlock()
   245  	if _, ok := f.subs[ch]; ok {
   246  		delete(f.subs, ch)
   247  		close(ch)
   248  	}
   249  }
   250  
   251  func (f *ChainSideFeed) Send(ev ChainSideEvent) {
   252  	f.mu.RLock()
   253  	defer f.mu.RUnlock()
   254  	for sub, name := range f.subs {
   255  		select {
   256  		case sub <- ev:
   257  		default:
   258  			start := time.Now()
   259  			var action string
   260  			select {
   261  			case sub <- ev:
   262  				action = "delayed"
   263  			case <-time.After(timeout):
   264  				action = "dropped"
   265  			}
   266  			dur := time.Since(start)
   267  			log.Warn(fmt.Sprintf("ChainSideFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "block", ev.Block.NumberU64(), "hash", ev.Block.Hash())
   268  		}
   269  	}
   270  }
   271  
   272  type PendingLogsFeed struct {
   273  	mu   sync.RWMutex
   274  	subs map[chan<- PendingLogsEvent]string
   275  }
   276  
   277  func (f *PendingLogsFeed) Close() {
   278  	f.mu.Lock()
   279  	defer f.mu.Unlock()
   280  	for sub := range f.subs {
   281  		close(sub)
   282  	}
   283  	f.subs = nil
   284  }
   285  
   286  func (f *PendingLogsFeed) Subscribe(ch chan<- PendingLogsEvent, name string) {
   287  	f.mu.Lock()
   288  	defer f.mu.Unlock()
   289  	if f.subs == nil {
   290  		f.subs = make(map[chan<- PendingLogsEvent]string)
   291  	}
   292  	f.subs[ch] = name
   293  }
   294  
   295  func (f *PendingLogsFeed) Unsubscribe(ch chan<- PendingLogsEvent) {
   296  	f.mu.Lock()
   297  	defer f.mu.Unlock()
   298  	if _, ok := f.subs[ch]; ok {
   299  		delete(f.subs, ch)
   300  		close(ch)
   301  	}
   302  }
   303  
   304  func (f *PendingLogsFeed) Send(ev PendingLogsEvent) {
   305  	f.mu.RLock()
   306  	defer f.mu.RUnlock()
   307  	for sub, name := range f.subs {
   308  		select {
   309  		case sub <- ev:
   310  		default:
   311  			start := time.Now()
   312  			var action string
   313  			select {
   314  			case sub <- ev:
   315  				action = "delayed"
   316  			case <-time.After(timeout):
   317  				action = "dropped"
   318  			}
   319  			dur := time.Since(start)
   320  			log.Warn(fmt.Sprintf("PendingLogsFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "len", len(ev.Logs))
   321  		}
   322  	}
   323  }
   324  
   325  type RemovedLogsFeed struct {
   326  	mu   sync.RWMutex
   327  	subs map[chan<- RemovedLogsEvent]string
   328  }
   329  
   330  func (f *RemovedLogsFeed) Close() {
   331  	f.mu.Lock()
   332  	defer f.mu.Unlock()
   333  	for sub := range f.subs {
   334  		close(sub)
   335  	}
   336  	f.subs = nil
   337  }
   338  
   339  func (f *RemovedLogsFeed) Subscribe(ch chan<- RemovedLogsEvent, name string) {
   340  	f.mu.Lock()
   341  	defer f.mu.Unlock()
   342  	if f.subs == nil {
   343  		f.subs = make(map[chan<- RemovedLogsEvent]string)
   344  	}
   345  	f.subs[ch] = name
   346  }
   347  
   348  func (f *RemovedLogsFeed) Unsubscribe(ch chan<- RemovedLogsEvent) {
   349  	f.mu.Lock()
   350  	defer f.mu.Unlock()
   351  	if _, ok := f.subs[ch]; ok {
   352  		delete(f.subs, ch)
   353  		close(ch)
   354  	}
   355  }
   356  
   357  func (f *RemovedLogsFeed) Send(ev RemovedLogsEvent) {
   358  	f.mu.RLock()
   359  	defer f.mu.RUnlock()
   360  	for sub, name := range f.subs {
   361  		select {
   362  		case sub <- ev:
   363  		default:
   364  			start := time.Now()
   365  			var action string
   366  			select {
   367  			case sub <- ev:
   368  				action = "delayed"
   369  			case <-time.After(timeout):
   370  				action = "dropped"
   371  			}
   372  			dur := time.Since(start)
   373  			log.Warn(fmt.Sprintf("RemovedLogsFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "len", len(ev.Logs))
   374  		}
   375  	}
   376  }
   377  
   378  type LogsFeed struct {
   379  	mu   sync.RWMutex
   380  	subs map[chan<- []*types.Log]string
   381  }
   382  
   383  func (f *LogsFeed) Close() {
   384  	f.mu.Lock()
   385  	defer f.mu.Unlock()
   386  	for sub := range f.subs {
   387  		close(sub)
   388  	}
   389  	f.subs = nil
   390  }
   391  
   392  func (f *LogsFeed) Len() int {
   393  	f.mu.RLock()
   394  	defer f.mu.RUnlock()
   395  	return len(f.subs)
   396  }
   397  
   398  func (f *LogsFeed) Subscribe(ch chan<- []*types.Log, name string) {
   399  	f.mu.Lock()
   400  	defer f.mu.Unlock()
   401  	if f.subs == nil {
   402  		f.subs = make(map[chan<- []*types.Log]string)
   403  	}
   404  	f.subs[ch] = name
   405  }
   406  
   407  func (f *LogsFeed) Unsubscribe(ch chan<- []*types.Log) {
   408  	f.mu.Lock()
   409  	defer f.mu.Unlock()
   410  	if _, ok := f.subs[ch]; ok {
   411  		delete(f.subs, ch)
   412  		close(ch)
   413  	}
   414  }
   415  
   416  func (f *LogsFeed) Send(logs []*types.Log) {
   417  	f.mu.RLock()
   418  	defer f.mu.RUnlock()
   419  	for sub, name := range f.subs {
   420  		select {
   421  		case sub <- logs:
   422  		default:
   423  			start := time.Now()
   424  			var action string
   425  			select {
   426  			case sub <- logs:
   427  				action = "delayed"
   428  			case <-time.After(timeout):
   429  				action = "dropped"
   430  			}
   431  			dur := time.Since(start)
   432  			log.Warn(fmt.Sprintf("LogsFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "len", len(logs))
   433  		}
   434  	}
   435  }