github.com/bcskill/bcschain/v3@v3.4.9-beta2/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  	"reflect"
    22  	"sync"
    23  	"time"
    24  
    25  	"github.com/bcskill/bcschain/v3/common"
    26  	"github.com/bcskill/bcschain/v3/core/types"
    27  	"github.com/bcskill/bcschain/v3/log"
    28  )
    29  
    30  const timeout = 500 * time.Millisecond
    31  
    32  // NewTxsEvent is posted when a batch of transactions enter the transaction pool.
    33  type NewTxsEvent struct{ Txs []*types.Transaction }
    34  
    35  // PendingLogsEvent is posted pre mining and notifies of pending logs.
    36  type PendingLogsEvent struct {
    37  	Logs []*types.Log
    38  }
    39  
    40  // PendingStateEvent is posted pre mining and notifies of pending state changes.
    41  type PendingStateEvent struct{}
    42  
    43  // NewMinedBlockEvent is posted when a block has been imported.
    44  type NewMinedBlockEvent struct{ Block *types.Block }
    45  
    46  // RemovedLogsEvent is posted when a reorg happens
    47  type RemovedLogsEvent struct{ Logs []*types.Log }
    48  
    49  type ChainEvent struct {
    50  	Block *types.Block
    51  	Hash  common.Hash
    52  	Logs  []*types.Log
    53  }
    54  
    55  type ChainSideEvent struct {
    56  	Block *types.Block
    57  }
    58  
    59  type ChainHeadEvent struct{ Block *types.Block }
    60  
    61  type NewTxsFeed struct {
    62  	mu   sync.RWMutex
    63  	subs map[chan<- NewTxsEvent]string
    64  }
    65  
    66  func (f *NewTxsFeed) Close() {
    67  	f.mu.Lock()
    68  	defer f.mu.Unlock()
    69  	for sub := range f.subs {
    70  		close(sub)
    71  	}
    72  	f.subs = nil
    73  }
    74  
    75  func (f *NewTxsFeed) Subscribe(ch chan<- NewTxsEvent, name string) {
    76  	f.mu.Lock()
    77  	defer f.mu.Unlock()
    78  	if f.subs == nil {
    79  		f.subs = make(map[chan<- NewTxsEvent]string)
    80  	}
    81  	f.subs[ch] = name
    82  }
    83  
    84  func (f *NewTxsFeed) Unsubscribe(ch chan<- NewTxsEvent) {
    85  	f.mu.Lock()
    86  	defer f.mu.Unlock()
    87  	if _, ok := f.subs[ch]; ok {
    88  		delete(f.subs, ch)
    89  		close(ch)
    90  	}
    91  }
    92  
    93  func (f *NewTxsFeed) Send(ev NewTxsEvent) {
    94  	f.mu.RLock()
    95  	defer f.mu.RUnlock()
    96  	for sub, name := range f.subs {
    97  		select {
    98  		case sub <- ev:
    99  		default:
   100  			start := time.Now()
   101  			var action string
   102  			select {
   103  			case sub <- ev:
   104  				action = "delayed"
   105  			case <-time.After(timeout):
   106  				action = "dropped"
   107  			}
   108  			dur := time.Since(start)
   109  			log.Warn(fmt.Sprintf("NewTxsFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "txs", len(ev.Txs))
   110  		}
   111  	}
   112  }
   113  
   114  type ChainFeed struct {
   115  	mu   sync.RWMutex
   116  	subs map[chan<- ChainEvent]string
   117  }
   118  
   119  func (f *ChainFeed) Close() {
   120  	f.mu.Lock()
   121  	defer f.mu.Unlock()
   122  	for sub := range f.subs {
   123  		close(sub)
   124  	}
   125  	f.subs = nil
   126  }
   127  
   128  func (f *ChainFeed) Subscribe(ch chan<- ChainEvent, name string) {
   129  	f.mu.Lock()
   130  	defer f.mu.Unlock()
   131  	if f.subs == nil {
   132  		f.subs = make(map[chan<- ChainEvent]string)
   133  	}
   134  	f.subs[ch] = name
   135  }
   136  
   137  func (f *ChainFeed) Unsubscribe(ch chan<- ChainEvent) {
   138  	f.mu.Lock()
   139  	defer f.mu.Unlock()
   140  	if _, ok := f.subs[ch]; ok {
   141  		delete(f.subs, ch)
   142  		close(ch)
   143  	}
   144  }
   145  
   146  func (f *ChainFeed) Send(ev ChainEvent) {
   147  	f.mu.RLock()
   148  	defer f.mu.RUnlock()
   149  	for sub, name := range f.subs {
   150  		select {
   151  		case sub <- ev:
   152  		default:
   153  			start := time.Now()
   154  			var action string
   155  			select {
   156  			case sub <- ev:
   157  				action = "delayed"
   158  			case <-time.After(timeout):
   159  				action = "dropped"
   160  			}
   161  			dur := time.Since(start)
   162  			log.Warn(fmt.Sprintf("ChainFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "block", ev.Block.NumberU64(), "hash", ev.Hash)
   163  		}
   164  	}
   165  }
   166  
   167  type ChainHeadFeed struct {
   168  	mu   sync.RWMutex
   169  	subs map[chan<- ChainHeadEvent]string
   170  }
   171  
   172  func (f *ChainHeadFeed) Close() {
   173  	f.mu.Lock()
   174  	defer f.mu.Unlock()
   175  	for sub := range f.subs {
   176  		close(sub)
   177  	}
   178  	f.subs = nil
   179  }
   180  
   181  func (f *ChainHeadFeed) Subscribe(ch chan<- ChainHeadEvent, name string) {
   182  	f.mu.Lock()
   183  	defer f.mu.Unlock()
   184  	if f.subs == nil {
   185  		f.subs = make(map[chan<- ChainHeadEvent]string)
   186  	}
   187  	f.subs[ch] = name
   188  }
   189  
   190  func (f *ChainHeadFeed) Unsubscribe(ch chan<- ChainHeadEvent) {
   191  	f.mu.Lock()
   192  	defer f.mu.Unlock()
   193  	if _, ok := f.subs[ch]; ok {
   194  		delete(f.subs, ch)
   195  		close(ch)
   196  	}
   197  }
   198  
   199  func (f *ChainHeadFeed) Send(ev ChainHeadEvent) {
   200  	f.mu.RLock()
   201  	defer f.mu.RUnlock()
   202  	for sub, name := range f.subs {
   203  		select {
   204  		case sub <- ev:
   205  		default:
   206  			start := time.Now()
   207  			var action string
   208  			select {
   209  			case sub <- ev:
   210  				action = "delayed"
   211  			case <-time.After(timeout):
   212  				action = "dropped"
   213  			}
   214  			dur := time.Since(start)
   215  			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())
   216  		}
   217  	}
   218  }
   219  
   220  type ChainSideFeed struct {
   221  	mu   sync.RWMutex
   222  	subs map[chan<- ChainSideEvent]string
   223  }
   224  
   225  func (f *ChainSideFeed) Close() {
   226  	f.mu.Lock()
   227  	defer f.mu.Unlock()
   228  	for sub := range f.subs {
   229  		close(sub)
   230  	}
   231  	f.subs = nil
   232  }
   233  
   234  func (f *ChainSideFeed) Subscribe(ch chan<- ChainSideEvent, name string) {
   235  	f.mu.Lock()
   236  	defer f.mu.Unlock()
   237  	if f.subs == nil {
   238  		f.subs = make(map[chan<- ChainSideEvent]string)
   239  	}
   240  	f.subs[ch] = name
   241  }
   242  
   243  func (f *ChainSideFeed) Unsubscribe(ch chan<- ChainSideEvent) {
   244  	f.mu.Lock()
   245  	defer f.mu.Unlock()
   246  	if _, ok := f.subs[ch]; ok {
   247  		delete(f.subs, ch)
   248  		close(ch)
   249  	}
   250  }
   251  
   252  func (f *ChainSideFeed) Send(ev ChainSideEvent) {
   253  	f.mu.RLock()
   254  	defer f.mu.RUnlock()
   255  	for sub, name := range f.subs {
   256  		select {
   257  		case sub <- ev:
   258  		default:
   259  			start := time.Now()
   260  			var action string
   261  			select {
   262  			case sub <- ev:
   263  				action = "delayed"
   264  			case <-time.After(timeout):
   265  				action = "dropped"
   266  			}
   267  			dur := time.Since(start)
   268  			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())
   269  		}
   270  	}
   271  }
   272  
   273  type PendingLogsFeed struct {
   274  	mu   sync.RWMutex
   275  	subs map[chan<- PendingLogsEvent]string
   276  }
   277  
   278  func (f *PendingLogsFeed) Close() {
   279  	f.mu.Lock()
   280  	defer f.mu.Unlock()
   281  	for sub := range f.subs {
   282  		close(sub)
   283  	}
   284  	f.subs = nil
   285  }
   286  
   287  func (f *PendingLogsFeed) Subscribe(ch chan<- PendingLogsEvent, name string) {
   288  	f.mu.Lock()
   289  	defer f.mu.Unlock()
   290  	if f.subs == nil {
   291  		f.subs = make(map[chan<- PendingLogsEvent]string)
   292  	}
   293  	f.subs[ch] = name
   294  }
   295  
   296  func (f *PendingLogsFeed) Unsubscribe(ch chan<- PendingLogsEvent) {
   297  	f.mu.Lock()
   298  	defer f.mu.Unlock()
   299  	if _, ok := f.subs[ch]; ok {
   300  		delete(f.subs, ch)
   301  		close(ch)
   302  	}
   303  }
   304  
   305  func (f *PendingLogsFeed) Send(ev PendingLogsEvent) {
   306  	f.mu.RLock()
   307  	defer f.mu.RUnlock()
   308  	for sub, name := range f.subs {
   309  		select {
   310  		case sub <- ev:
   311  		default:
   312  			start := time.Now()
   313  			var action string
   314  			select {
   315  			case sub <- ev:
   316  				action = "delayed"
   317  			case <-time.After(timeout):
   318  				action = "dropped"
   319  			}
   320  			dur := time.Since(start)
   321  			log.Warn(fmt.Sprintf("PendingLogsFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "len", len(ev.Logs))
   322  		}
   323  	}
   324  }
   325  
   326  type RemovedLogsFeed struct {
   327  	mu   sync.RWMutex
   328  	subs map[chan<- RemovedLogsEvent]string
   329  }
   330  
   331  func (f *RemovedLogsFeed) Close() {
   332  	f.mu.Lock()
   333  	defer f.mu.Unlock()
   334  	for sub := range f.subs {
   335  		close(sub)
   336  	}
   337  	f.subs = nil
   338  }
   339  
   340  func (f *RemovedLogsFeed) Subscribe(ch chan<- RemovedLogsEvent, name string) {
   341  	f.mu.Lock()
   342  	defer f.mu.Unlock()
   343  	if f.subs == nil {
   344  		f.subs = make(map[chan<- RemovedLogsEvent]string)
   345  	}
   346  	f.subs[ch] = name
   347  }
   348  
   349  func (f *RemovedLogsFeed) Unsubscribe(ch chan<- RemovedLogsEvent) {
   350  	f.mu.Lock()
   351  	defer f.mu.Unlock()
   352  	if _, ok := f.subs[ch]; ok {
   353  		delete(f.subs, ch)
   354  		close(ch)
   355  	}
   356  }
   357  
   358  func (f *RemovedLogsFeed) Send(ev RemovedLogsEvent) {
   359  	f.mu.RLock()
   360  	defer f.mu.RUnlock()
   361  	for sub, name := range f.subs {
   362  		select {
   363  		case sub <- ev:
   364  		default:
   365  			start := time.Now()
   366  			var action string
   367  			select {
   368  			case sub <- ev:
   369  				action = "delayed"
   370  			case <-time.After(timeout):
   371  				action = "dropped"
   372  			}
   373  			dur := time.Since(start)
   374  			log.Warn(fmt.Sprintf("RemovedLogsFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "len", len(ev.Logs))
   375  		}
   376  	}
   377  }
   378  
   379  type LogsFeed struct {
   380  	mu   sync.RWMutex
   381  	subs map[chan<- []*types.Log]string
   382  }
   383  
   384  func (f *LogsFeed) Close() {
   385  	f.mu.Lock()
   386  	defer f.mu.Unlock()
   387  	for sub := range f.subs {
   388  		close(sub)
   389  	}
   390  	f.subs = nil
   391  }
   392  
   393  func (f *LogsFeed) Len() int {
   394  	f.mu.RLock()
   395  	defer f.mu.RUnlock()
   396  	return len(f.subs)
   397  }
   398  
   399  func (f *LogsFeed) Subscribe(ch chan<- []*types.Log, name string) {
   400  	f.mu.Lock()
   401  	defer f.mu.Unlock()
   402  	if f.subs == nil {
   403  		f.subs = make(map[chan<- []*types.Log]string)
   404  	}
   405  	f.subs[ch] = name
   406  }
   407  
   408  func (f *LogsFeed) Unsubscribe(ch chan<- []*types.Log) {
   409  	f.mu.Lock()
   410  	defer f.mu.Unlock()
   411  	if _, ok := f.subs[ch]; ok {
   412  		delete(f.subs, ch)
   413  		close(ch)
   414  	}
   415  }
   416  
   417  func (f *LogsFeed) Send(logs []*types.Log) {
   418  	f.mu.RLock()
   419  	defer f.mu.RUnlock()
   420  	for sub, name := range f.subs {
   421  		select {
   422  		case sub <- logs:
   423  		default:
   424  			start := time.Now()
   425  			var action string
   426  			select {
   427  			case sub <- logs:
   428  				action = "delayed"
   429  			case <-time.After(timeout):
   430  				action = "dropped"
   431  			}
   432  			dur := time.Since(start)
   433  			log.Warn(fmt.Sprintf("LogsFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "len", len(logs))
   434  		}
   435  	}
   436  }
   437  
   438  type BlockProcFeed struct {
   439  	mu   sync.RWMutex
   440  	subs map[chan<- bool]string
   441  }
   442  
   443  func (f *BlockProcFeed) Close() {
   444  	f.mu.Lock()
   445  	defer f.mu.Unlock()
   446  	for sub := range f.subs {
   447  		close(sub)
   448  	}
   449  	f.subs = nil
   450  }
   451  
   452  func (f *BlockProcFeed) Subscribe(ch chan<- bool, name string) {
   453  	f.mu.Lock()
   454  	defer f.mu.Unlock()
   455  	if f.subs == nil {
   456  		f.subs = make(map[chan<- bool]string)
   457  	}
   458  	f.subs[ch] = name
   459  }
   460  
   461  func (f *BlockProcFeed) Unsubscribe(ch chan<- bool) {
   462  	f.mu.Lock()
   463  	defer f.mu.Unlock()
   464  	if _, ok := f.subs[ch]; ok {
   465  		delete(f.subs, ch)
   466  		close(ch)
   467  	}
   468  }
   469  
   470  func (f *BlockProcFeed) Send(b bool) {
   471  	f.mu.RLock()
   472  	defer f.mu.RUnlock()
   473  	for sub, name := range f.subs {
   474  		select {
   475  		case sub <- b:
   476  		default:
   477  			start := time.Now()
   478  			var action string
   479  			select {
   480  			case sub <- b:
   481  				action = "delayed"
   482  			case <-time.After(timeout):
   483  				action = "dropped"
   484  			}
   485  			dur := time.Since(start)
   486  			log.Warn(fmt.Sprintf("BlockProcFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "val", b)
   487  		}
   488  	}
   489  }
   490  
   491  type Int64Feed struct {
   492  	mu   sync.RWMutex
   493  	subs map[chan<- int64]string
   494  }
   495  
   496  func (f *Int64Feed) Close() {
   497  	f.mu.Lock()
   498  	defer f.mu.Unlock()
   499  	for sub := range f.subs {
   500  		close(sub)
   501  	}
   502  	f.subs = nil
   503  }
   504  
   505  func (f *Int64Feed) Subscribe(ch chan<- int64, name string) {
   506  	f.mu.Lock()
   507  	defer f.mu.Unlock()
   508  	if f.subs == nil {
   509  		f.subs = make(map[chan<- int64]string)
   510  	}
   511  	f.subs[ch] = name
   512  }
   513  
   514  func (f *Int64Feed) Unsubscribe(ch chan<- int64) {
   515  	f.mu.Lock()
   516  	defer f.mu.Unlock()
   517  	if _, ok := f.subs[ch]; ok {
   518  		delete(f.subs, ch)
   519  		close(ch)
   520  	}
   521  }
   522  
   523  func (f *Int64Feed) Send(e int64) {
   524  	f.mu.RLock()
   525  	defer f.mu.RUnlock()
   526  	for sub, name := range f.subs {
   527  		select {
   528  		case sub <- e:
   529  		default:
   530  			start := time.Now()
   531  			var action string
   532  			select {
   533  			case sub <- e:
   534  				action = "delayed"
   535  			case <-time.After(timeout):
   536  				action = "dropped"
   537  			}
   538  			dur := time.Since(start)
   539  			log.Warn(fmt.Sprintf("Int64Feed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "val", e)
   540  		}
   541  	}
   542  }
   543  
   544  type IntFeed struct {
   545  	mu   sync.RWMutex
   546  	subs map[chan<- int]string
   547  }
   548  
   549  func (f *IntFeed) Close() {
   550  	f.mu.Lock()
   551  	defer f.mu.Unlock()
   552  	for sub := range f.subs {
   553  		close(sub)
   554  	}
   555  	f.subs = nil
   556  }
   557  
   558  func (f *IntFeed) Subscribe(ch chan<- int, name string) {
   559  	f.mu.Lock()
   560  	defer f.mu.Unlock()
   561  	if f.subs == nil {
   562  		f.subs = make(map[chan<- int]string)
   563  	}
   564  	f.subs[ch] = name
   565  }
   566  
   567  func (f *IntFeed) Unsubscribe(ch chan<- int) {
   568  	f.mu.Lock()
   569  	defer f.mu.Unlock()
   570  	if _, ok := f.subs[ch]; ok {
   571  		delete(f.subs, ch)
   572  		close(ch)
   573  	}
   574  }
   575  
   576  func (f *IntFeed) Send(e int) {
   577  	f.mu.RLock()
   578  	defer f.mu.RUnlock()
   579  	for sub, name := range f.subs {
   580  		select {
   581  		case sub <- e:
   582  		default:
   583  			start := time.Now()
   584  			var action string
   585  			select {
   586  			case sub <- e:
   587  				action = "delayed"
   588  			case <-time.After(timeout):
   589  				action = "dropped"
   590  			}
   591  			dur := time.Since(start)
   592  			log.Warn(fmt.Sprintf("IntFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "val", e)
   593  		}
   594  	}
   595  }
   596  
   597  type InterfaceFeed struct {
   598  	mu   sync.RWMutex
   599  	subs map[chan<- interface{}]string
   600  }
   601  
   602  func (f *InterfaceFeed) Close() {
   603  	f.mu.Lock()
   604  	defer f.mu.Unlock()
   605  	for sub := range f.subs {
   606  		close(sub)
   607  	}
   608  	f.subs = nil
   609  }
   610  
   611  func (f *InterfaceFeed) Subscribe(ch chan<- interface{}, name string) {
   612  	f.mu.Lock()
   613  	defer f.mu.Unlock()
   614  	if f.subs == nil {
   615  		f.subs = make(map[chan<- interface{}]string)
   616  	}
   617  	f.subs[ch] = name
   618  }
   619  
   620  func (f *InterfaceFeed) Unsubscribe(ch chan<- interface{}) {
   621  	f.mu.Lock()
   622  	defer f.mu.Unlock()
   623  	if _, ok := f.subs[ch]; ok {
   624  		delete(f.subs, ch)
   625  		close(ch)
   626  	}
   627  }
   628  
   629  func (f *InterfaceFeed) Send(e interface{}) {
   630  	f.mu.RLock()
   631  	defer f.mu.RUnlock()
   632  	for sub, name := range f.subs {
   633  		select {
   634  		case sub <- e:
   635  		default:
   636  			start := time.Now()
   637  			var action string
   638  			select {
   639  			case sub <- e:
   640  				action = "delayed"
   641  			case <-time.After(timeout):
   642  				action = "dropped"
   643  			}
   644  			dur := time.Since(start)
   645  			log.Warn(fmt.Sprintf("InterfaceFeed send %s: channel full", action), "name", name, "cap", cap(sub), "time", dur, "type", reflect.TypeOf(e))
   646  		}
   647  	}
   648  }