Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
756b6298
Commit
756b6298
authored
May 09, 2016
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2523 from fjl/shutdown
core, eth, miner: improve shutdown synchronisation
parents
dc7f202e
56ed6152
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
101 additions
and
70 deletions
+101
-70
tx_pool.go
core/tx_pool.go
+7
-4
backend.go
eth/backend.go
+1
-0
handler.go
eth/handler.go
+38
-22
helper_test.go
eth/helper_test.go
+7
-7
peer.go
eth/peer.go
+19
-2
sync.go
eth/sync.go
+1
-1
worker.go
miner/worker.go
+28
-34
No files found.
core/tx_pool.go
View file @
756b6298
...
@@ -60,8 +60,7 @@ type stateFn func() (*state.StateDB, error)
...
@@ -60,8 +60,7 @@ type stateFn func() (*state.StateDB, error)
// two states over time as they are received and processed.
// two states over time as they are received and processed.
type
TxPool
struct
{
type
TxPool
struct
{
config
*
ChainConfig
config
*
ChainConfig
quit
chan
bool
// Quitting channel
currentState
stateFn
// The state function which will allow us to do some pre checks
currentState
stateFn
// The state function which will allow us to do some pre checks
pendingState
*
state
.
ManagedState
pendingState
*
state
.
ManagedState
gasLimit
func
()
*
big
.
Int
// The current gas limit function callback
gasLimit
func
()
*
big
.
Int
// The current gas limit function callback
minGasPrice
*
big
.
Int
minGasPrice
*
big
.
Int
...
@@ -72,6 +71,8 @@ type TxPool struct {
...
@@ -72,6 +71,8 @@ type TxPool struct {
pending
map
[
common
.
Hash
]
*
types
.
Transaction
// processable transactions
pending
map
[
common
.
Hash
]
*
types
.
Transaction
// processable transactions
queue
map
[
common
.
Address
]
map
[
common
.
Hash
]
*
types
.
Transaction
queue
map
[
common
.
Address
]
map
[
common
.
Hash
]
*
types
.
Transaction
wg
sync
.
WaitGroup
// for shutdown sync
homestead
bool
homestead
bool
}
}
...
@@ -80,7 +81,6 @@ func NewTxPool(config *ChainConfig, eventMux *event.TypeMux, currentStateFn stat
...
@@ -80,7 +81,6 @@ func NewTxPool(config *ChainConfig, eventMux *event.TypeMux, currentStateFn stat
config
:
config
,
config
:
config
,
pending
:
make
(
map
[
common
.
Hash
]
*
types
.
Transaction
),
pending
:
make
(
map
[
common
.
Hash
]
*
types
.
Transaction
),
queue
:
make
(
map
[
common
.
Address
]
map
[
common
.
Hash
]
*
types
.
Transaction
),
queue
:
make
(
map
[
common
.
Address
]
map
[
common
.
Hash
]
*
types
.
Transaction
),
quit
:
make
(
chan
bool
),
eventMux
:
eventMux
,
eventMux
:
eventMux
,
currentState
:
currentStateFn
,
currentState
:
currentStateFn
,
gasLimit
:
gasLimitFn
,
gasLimit
:
gasLimitFn
,
...
@@ -90,12 +90,15 @@ func NewTxPool(config *ChainConfig, eventMux *event.TypeMux, currentStateFn stat
...
@@ -90,12 +90,15 @@ func NewTxPool(config *ChainConfig, eventMux *event.TypeMux, currentStateFn stat
events
:
eventMux
.
Subscribe
(
ChainHeadEvent
{},
GasPriceChanged
{},
RemovedTransactionEvent
{}),
events
:
eventMux
.
Subscribe
(
ChainHeadEvent
{},
GasPriceChanged
{},
RemovedTransactionEvent
{}),
}
}
pool
.
wg
.
Add
(
1
)
go
pool
.
eventLoop
()
go
pool
.
eventLoop
()
return
pool
return
pool
}
}
func
(
pool
*
TxPool
)
eventLoop
()
{
func
(
pool
*
TxPool
)
eventLoop
()
{
defer
pool
.
wg
.
Done
()
// Track chain events. When a chain events occurs (new chain canon block)
// Track chain events. When a chain events occurs (new chain canon block)
// we need to know the new state. The new state will help us determine
// we need to know the new state. The new state will help us determine
// the nonces in the managed state
// the nonces in the managed state
...
@@ -155,8 +158,8 @@ func (pool *TxPool) resetState() {
...
@@ -155,8 +158,8 @@ func (pool *TxPool) resetState() {
}
}
func
(
pool
*
TxPool
)
Stop
()
{
func
(
pool
*
TxPool
)
Stop
()
{
close
(
pool
.
quit
)
pool
.
events
.
Unsubscribe
()
pool
.
events
.
Unsubscribe
()
pool
.
wg
.
Wait
()
glog
.
V
(
logger
.
Info
)
.
Infoln
(
"Transaction pool stopped"
)
glog
.
V
(
logger
.
Info
)
.
Infoln
(
"Transaction pool stopped"
)
}
}
...
...
eth/backend.go
View file @
756b6298
...
@@ -416,6 +416,7 @@ func (s *Ethereum) Stop() error {
...
@@ -416,6 +416,7 @@ func (s *Ethereum) Stop() error {
s
.
blockchain
.
Stop
()
s
.
blockchain
.
Stop
()
s
.
protocolManager
.
Stop
()
s
.
protocolManager
.
Stop
()
s
.
txPool
.
Stop
()
s
.
txPool
.
Stop
()
s
.
miner
.
Stop
()
s
.
eventMux
.
Stop
()
s
.
eventMux
.
Stop
()
s
.
StopAutoDAG
()
s
.
StopAutoDAG
()
...
...
eth/handler.go
View file @
756b6298
...
@@ -74,14 +74,14 @@ type ProtocolManager struct {
...
@@ -74,14 +74,14 @@ type ProtocolManager struct {
minedBlockSub
event
.
Subscription
minedBlockSub
event
.
Subscription
// channels for fetcher, syncer, txsyncLoop
// channels for fetcher, syncer, txsyncLoop
newPeerCh
chan
*
peer
newPeerCh
chan
*
peer
txsyncCh
chan
*
txsync
txsyncCh
chan
*
txsync
quitSync
chan
struct
{}
quitSync
chan
struct
{}
noMorePeers
chan
struct
{}
// wait group is used for graceful shutdowns during downloading
// wait group is used for graceful shutdowns during downloading
// and processing
// and processing
wg
sync
.
WaitGroup
wg
sync
.
WaitGroup
quit
bool
}
}
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
...
@@ -94,16 +94,17 @@ func NewProtocolManager(config *core.ChainConfig, fastSync bool, networkId int,
...
@@ -94,16 +94,17 @@ func NewProtocolManager(config *core.ChainConfig, fastSync bool, networkId int,
}
}
// Create the protocol manager with the base fields
// Create the protocol manager with the base fields
manager
:=
&
ProtocolManager
{
manager
:=
&
ProtocolManager
{
networkId
:
networkId
,
networkId
:
networkId
,
fastSync
:
fastSync
,
fastSync
:
fastSync
,
eventMux
:
mux
,
eventMux
:
mux
,
txpool
:
txpool
,
txpool
:
txpool
,
blockchain
:
blockchain
,
blockchain
:
blockchain
,
chaindb
:
chaindb
,
chaindb
:
chaindb
,
peers
:
newPeerSet
(),
peers
:
newPeerSet
(),
newPeerCh
:
make
(
chan
*
peer
,
1
),
newPeerCh
:
make
(
chan
*
peer
),
txsyncCh
:
make
(
chan
*
txsync
),
noMorePeers
:
make
(
chan
struct
{}),
quitSync
:
make
(
chan
struct
{}),
txsyncCh
:
make
(
chan
*
txsync
),
quitSync
:
make
(
chan
struct
{}),
}
}
// Initiate a sub-protocol for every implemented version we can handle
// Initiate a sub-protocol for every implemented version we can handle
manager
.
SubProtocols
=
make
([]
p2p
.
Protocol
,
0
,
len
(
ProtocolVersions
))
manager
.
SubProtocols
=
make
([]
p2p
.
Protocol
,
0
,
len
(
ProtocolVersions
))
...
@@ -120,8 +121,14 @@ func NewProtocolManager(config *core.ChainConfig, fastSync bool, networkId int,
...
@@ -120,8 +121,14 @@ func NewProtocolManager(config *core.ChainConfig, fastSync bool, networkId int,
Length
:
ProtocolLengths
[
i
],
Length
:
ProtocolLengths
[
i
],
Run
:
func
(
p
*
p2p
.
Peer
,
rw
p2p
.
MsgReadWriter
)
error
{
Run
:
func
(
p
*
p2p
.
Peer
,
rw
p2p
.
MsgReadWriter
)
error
{
peer
:=
manager
.
newPeer
(
int
(
version
),
p
,
rw
)
peer
:=
manager
.
newPeer
(
int
(
version
),
p
,
rw
)
manager
.
newPeerCh
<-
peer
select
{
return
manager
.
handle
(
peer
)
case
manager
.
newPeerCh
<-
peer
:
manager
.
wg
.
Add
(
1
)
defer
manager
.
wg
.
Done
()
return
manager
.
handle
(
peer
)
case
<-
manager
.
quitSync
:
return
p2p
.
DiscQuitting
}
},
},
NodeInfo
:
func
()
interface
{}
{
NodeInfo
:
func
()
interface
{}
{
return
manager
.
NodeInfo
()
return
manager
.
NodeInfo
()
...
@@ -187,16 +194,25 @@ func (pm *ProtocolManager) Start() {
...
@@ -187,16 +194,25 @@ func (pm *ProtocolManager) Start() {
}
}
func
(
pm
*
ProtocolManager
)
Stop
()
{
func
(
pm
*
ProtocolManager
)
Stop
()
{
// Showing a log message. During download / process this could actually
// take between 5 to 10 seconds and therefor feedback is required.
glog
.
V
(
logger
.
Info
)
.
Infoln
(
"Stopping ethereum protocol handler..."
)
glog
.
V
(
logger
.
Info
)
.
Infoln
(
"Stopping ethereum protocol handler..."
)
pm
.
quit
=
true
pm
.
txSub
.
Unsubscribe
()
// quits txBroadcastLoop
pm
.
txSub
.
Unsubscribe
()
// quits txBroadcastLoop
pm
.
minedBlockSub
.
Unsubscribe
()
// quits blockBroadcastLoop
pm
.
minedBlockSub
.
Unsubscribe
()
// quits blockBroadcastLoop
close
(
pm
.
quitSync
)
// quits syncer, fetcher, txsyncLoop
// Wait for any process action
// Quit the sync loop.
// After this send has completed, no new peers will be accepted.
pm
.
noMorePeers
<-
struct
{}{}
// Quit fetcher, txsyncLoop.
close
(
pm
.
quitSync
)
// Disconnect existing sessions.
// This also closes the gate for any new registrations on the peer set.
// sessions which are already established but not added to pm.peers yet
// will exit when they try to register.
pm
.
peers
.
Close
()
// Wait for all peer handler goroutines and the loops to come down.
pm
.
wg
.
Wait
()
pm
.
wg
.
Wait
()
glog
.
V
(
logger
.
Info
)
.
Infoln
(
"Ethereum protocol handler stopped"
)
glog
.
V
(
logger
.
Info
)
.
Infoln
(
"Ethereum protocol handler stopped"
)
...
...
eth/helper_test.go
View file @
756b6298
...
@@ -140,14 +140,14 @@ func newTestPeer(name string, version int, pm *ProtocolManager, shake bool) (*te
...
@@ -140,14 +140,14 @@ func newTestPeer(name string, version int, pm *ProtocolManager, shake bool) (*te
// Start the peer on a new thread
// Start the peer on a new thread
errc
:=
make
(
chan
error
,
1
)
errc
:=
make
(
chan
error
,
1
)
go
func
()
{
go
func
()
{
pm
.
newPeerCh
<-
peer
select
{
errc
<-
pm
.
handle
(
peer
)
case
pm
.
newPeerCh
<-
peer
:
errc
<-
pm
.
handle
(
peer
)
case
<-
pm
.
quitSync
:
errc
<-
p2p
.
DiscQuitting
}
}()
}()
tp
:=
&
testPeer
{
tp
:=
&
testPeer
{
app
:
app
,
net
:
net
,
peer
:
peer
}
app
:
app
,
net
:
net
,
peer
:
peer
,
}
// Execute any implicitly requested handshakes and return
// Execute any implicitly requested handshakes and return
if
shake
{
if
shake
{
td
,
head
,
genesis
:=
pm
.
blockchain
.
Status
()
td
,
head
,
genesis
:=
pm
.
blockchain
.
Status
()
...
...
eth/peer.go
View file @
756b6298
...
@@ -34,6 +34,7 @@ import (
...
@@ -34,6 +34,7 @@ import (
)
)
var
(
var
(
errClosed
=
errors
.
New
(
"peer set is closed"
)
errAlreadyRegistered
=
errors
.
New
(
"peer is already registered"
)
errAlreadyRegistered
=
errors
.
New
(
"peer is already registered"
)
errNotRegistered
=
errors
.
New
(
"peer is not registered"
)
errNotRegistered
=
errors
.
New
(
"peer is not registered"
)
)
)
...
@@ -351,8 +352,9 @@ func (p *peer) String() string {
...
@@ -351,8 +352,9 @@ func (p *peer) String() string {
// peerSet represents the collection of active peers currently participating in
// peerSet represents the collection of active peers currently participating in
// the Ethereum sub-protocol.
// the Ethereum sub-protocol.
type
peerSet
struct
{
type
peerSet
struct
{
peers
map
[
string
]
*
peer
peers
map
[
string
]
*
peer
lock
sync
.
RWMutex
lock
sync
.
RWMutex
closed
bool
}
}
// newPeerSet creates a new peer set to track the active participants.
// newPeerSet creates a new peer set to track the active participants.
...
@@ -368,6 +370,9 @@ func (ps *peerSet) Register(p *peer) error {
...
@@ -368,6 +370,9 @@ func (ps *peerSet) Register(p *peer) error {
ps
.
lock
.
Lock
()
ps
.
lock
.
Lock
()
defer
ps
.
lock
.
Unlock
()
defer
ps
.
lock
.
Unlock
()
if
ps
.
closed
{
return
errClosed
}
if
_
,
ok
:=
ps
.
peers
[
p
.
id
];
ok
{
if
_
,
ok
:=
ps
.
peers
[
p
.
id
];
ok
{
return
errAlreadyRegistered
return
errAlreadyRegistered
}
}
...
@@ -450,3 +455,15 @@ func (ps *peerSet) BestPeer() *peer {
...
@@ -450,3 +455,15 @@ func (ps *peerSet) BestPeer() *peer {
}
}
return
bestPeer
return
bestPeer
}
}
// Close disconnects all peers.
// No new peers can be registered after Close has returned.
func
(
ps
*
peerSet
)
Close
()
{
ps
.
lock
.
Lock
()
defer
ps
.
lock
.
Unlock
()
for
_
,
p
:=
range
ps
.
peers
{
p
.
Disconnect
(
p2p
.
DiscQuitting
)
}
ps
.
closed
=
true
}
eth/sync.go
View file @
756b6298
...
@@ -148,7 +148,7 @@ func (pm *ProtocolManager) syncer() {
...
@@ -148,7 +148,7 @@ func (pm *ProtocolManager) syncer() {
// Force a sync even if not enough peers are present
// Force a sync even if not enough peers are present
go
pm
.
synchronise
(
pm
.
peers
.
BestPeer
())
go
pm
.
synchronise
(
pm
.
peers
.
BestPeer
())
case
<-
pm
.
quitSync
:
case
<-
pm
.
noMorePeers
:
return
return
}
}
}
}
...
...
miner/worker.go
View file @
756b6298
...
@@ -94,10 +94,13 @@ type worker struct {
...
@@ -94,10 +94,13 @@ type worker struct {
mu
sync
.
Mutex
mu
sync
.
Mutex
// update loop
mux
*
event
.
TypeMux
events
event
.
Subscription
wg
sync
.
WaitGroup
agents
map
[
Agent
]
struct
{}
agents
map
[
Agent
]
struct
{}
recv
chan
*
Result
recv
chan
*
Result
mux
*
event
.
TypeMux
quit
chan
struct
{}
pow
pow
.
PoW
pow
pow
.
PoW
eth
core
.
Backend
eth
core
.
Backend
...
@@ -138,13 +141,14 @@ func newWorker(config *core.ChainConfig, coinbase common.Address, eth core.Backe
...
@@ -138,13 +141,14 @@ func newWorker(config *core.ChainConfig, coinbase common.Address, eth core.Backe
possibleUncles
:
make
(
map
[
common
.
Hash
]
*
types
.
Block
),
possibleUncles
:
make
(
map
[
common
.
Hash
]
*
types
.
Block
),
coinbase
:
coinbase
,
coinbase
:
coinbase
,
txQueue
:
make
(
map
[
common
.
Hash
]
*
types
.
Transaction
),
txQueue
:
make
(
map
[
common
.
Hash
]
*
types
.
Transaction
),
quit
:
make
(
chan
struct
{}),
agents
:
make
(
map
[
Agent
]
struct
{}),
agents
:
make
(
map
[
Agent
]
struct
{}),
fullValidation
:
false
,
fullValidation
:
false
,
}
}
worker
.
events
=
worker
.
mux
.
Subscribe
(
core
.
ChainHeadEvent
{},
core
.
ChainSideEvent
{},
core
.
TxPreEvent
{})
worker
.
wg
.
Add
(
1
)
go
worker
.
update
()
go
worker
.
update
()
go
worker
.
wait
()
go
worker
.
wait
()
worker
.
commitNewWork
()
worker
.
commitNewWork
()
return
worker
return
worker
...
@@ -184,9 +188,12 @@ func (self *worker) start() {
...
@@ -184,9 +188,12 @@ func (self *worker) start() {
}
}
func
(
self
*
worker
)
stop
()
{
func
(
self
*
worker
)
stop
()
{
// Quit update.
self
.
events
.
Unsubscribe
()
self
.
wg
.
Wait
()
self
.
mu
.
Lock
()
self
.
mu
.
Lock
()
defer
self
.
mu
.
Unlock
()
defer
self
.
mu
.
Unlock
()
if
atomic
.
LoadInt32
(
&
self
.
mining
)
==
1
{
if
atomic
.
LoadInt32
(
&
self
.
mining
)
==
1
{
// Stop all agents.
// Stop all agents.
for
agent
:=
range
self
.
agents
{
for
agent
:=
range
self
.
agents
{
...
@@ -217,36 +224,23 @@ func (self *worker) unregister(agent Agent) {
...
@@ -217,36 +224,23 @@ func (self *worker) unregister(agent Agent) {
}
}
func
(
self
*
worker
)
update
()
{
func
(
self
*
worker
)
update
()
{
eventSub
:=
self
.
mux
.
Subscribe
(
core
.
ChainHeadEvent
{},
core
.
ChainSideEvent
{},
core
.
TxPreEvent
{})
defer
self
.
wg
.
Done
()
defer
eventSub
.
Unsubscribe
()
for
event
:=
range
self
.
events
.
Chan
()
{
// A real event arrived, process interesting content
eventCh
:=
eventSub
.
Chan
()
switch
ev
:=
event
.
Data
.
(
type
)
{
for
{
case
core
.
ChainHeadEvent
:
select
{
self
.
commitNewWork
()
case
event
,
ok
:=
<-
eventCh
:
case
core
.
ChainSideEvent
:
if
!
ok
{
self
.
uncleMu
.
Lock
()
// Event subscription closed, set the channel to nil to stop spinning
self
.
possibleUncles
[
ev
.
Block
.
Hash
()]
=
ev
.
Block
eventCh
=
nil
self
.
uncleMu
.
Unlock
()
continue
case
core
.
TxPreEvent
:
}
// Apply transaction to the pending state if we're not mining
// A real event arrived, process interesting content
if
atomic
.
LoadInt32
(
&
self
.
mining
)
==
0
{
switch
ev
:=
event
.
Data
.
(
type
)
{
self
.
currentMu
.
Lock
()
case
core
.
ChainHeadEvent
:
self
.
current
.
commitTransactions
(
self
.
mux
,
types
.
Transactions
{
ev
.
Tx
},
self
.
gasPrice
,
self
.
chain
)
self
.
commitNewWork
()
self
.
currentMu
.
Unlock
()
case
core
.
ChainSideEvent
:
self
.
uncleMu
.
Lock
()
self
.
possibleUncles
[
ev
.
Block
.
Hash
()]
=
ev
.
Block
self
.
uncleMu
.
Unlock
()
case
core
.
TxPreEvent
:
// Apply transaction to the pending state if we're not mining
if
atomic
.
LoadInt32
(
&
self
.
mining
)
==
0
{
self
.
currentMu
.
Lock
()
self
.
current
.
commitTransactions
(
self
.
mux
,
types
.
Transactions
{
ev
.
Tx
},
self
.
gasPrice
,
self
.
chain
)
self
.
currentMu
.
Unlock
()
}
}
}
case
<-
self
.
quit
:
return
}
}
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment