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 }