forked from TrueCloudLab/frostfs-node
[#1208] innerring: Disallow to tick timer twice on the same height
Provide current heights as an argument to ticker. Zero height disables any checks, thus corresponding to the old behaviour. If non-zero height is used, ignore the tick if the height is less than the timer tick state. Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
c0e65dadaf
commit
4770cb8bf6
4 changed files with 68 additions and 8 deletions
|
@ -66,9 +66,9 @@ func (s *Server) startBlockTimers() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) tickTimers() {
|
||||
func (s *Server) tickTimers(h uint32) {
|
||||
for i := range s.blockTimers {
|
||||
s.blockTimers[i].Tick()
|
||||
s.blockTimers[i].Tick(h)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -241,7 +241,7 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) {
|
|||
zap.Uint32("block_index", b.Index))
|
||||
}
|
||||
|
||||
s.tickTimers()
|
||||
s.tickTimers(b.Index)
|
||||
})
|
||||
|
||||
if !s.withoutMainNet {
|
||||
|
|
|
@ -27,6 +27,8 @@ type BlockTimer struct {
|
|||
|
||||
cur, tgt uint32
|
||||
|
||||
last uint32
|
||||
|
||||
h BlockTickHandler
|
||||
|
||||
ps []BlockTimer
|
||||
|
@ -159,13 +161,18 @@ func (t *BlockTimer) reset() {
|
|||
// Tick ticks one block in the BlockTimer.
|
||||
//
|
||||
// Executes all callbacks which are awaiting execution at the new block.
|
||||
func (t *BlockTimer) Tick() {
|
||||
func (t *BlockTimer) Tick(h uint32) {
|
||||
t.mtx.Lock()
|
||||
t.tick()
|
||||
t.tick(h)
|
||||
t.mtx.Unlock()
|
||||
}
|
||||
|
||||
func (t *BlockTimer) tick() {
|
||||
func (t *BlockTimer) tick(h uint32) {
|
||||
if h != 0 && t.last == h {
|
||||
return
|
||||
}
|
||||
|
||||
t.last = h
|
||||
t.cur++
|
||||
|
||||
if t.cur == t.tgt {
|
||||
|
@ -182,6 +189,6 @@ func (t *BlockTimer) tick() {
|
|||
}
|
||||
|
||||
for i := range t.ps {
|
||||
t.ps[i].tick()
|
||||
t.ps[i].tick(h)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
func tickN(t *timer.BlockTimer, n uint32) {
|
||||
for i := uint32(0); i < n; i++ {
|
||||
t.Tick()
|
||||
t.Tick(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,3 +159,56 @@ func TestNewOneTickTimer(t *testing.T) {
|
|||
require.Equal(t, 1, detlaCallCounter)
|
||||
})
|
||||
}
|
||||
|
||||
func TestBlockTimer_TickSameHeight(t *testing.T) {
|
||||
var baseCounter, deltaCounter int
|
||||
|
||||
blockDur := uint32(2)
|
||||
bt := timer.NewBlockTimer(
|
||||
func() (uint32, error) { return blockDur, nil },
|
||||
func() { baseCounter++ })
|
||||
bt.OnDelta(2, 1, func() {
|
||||
deltaCounter++
|
||||
})
|
||||
require.NoError(t, bt.Reset())
|
||||
|
||||
check := func(t *testing.T, h uint32, base, delta int) {
|
||||
for i := 0; i < 2*int(blockDur); i++ {
|
||||
bt.Tick(h)
|
||||
require.Equal(t, base, baseCounter)
|
||||
require.Equal(t, delta, deltaCounter)
|
||||
}
|
||||
}
|
||||
|
||||
check(t, 1, 0, 0)
|
||||
check(t, 2, 1, 0)
|
||||
check(t, 3, 1, 0)
|
||||
check(t, 4, 2, 1)
|
||||
|
||||
t.Run("works the same way after `Reset()`", func(t *testing.T) {
|
||||
t.Run("same block duration", func(t *testing.T) {
|
||||
require.NoError(t, bt.Reset())
|
||||
baseCounter = 0
|
||||
deltaCounter = 0
|
||||
|
||||
check(t, 1, 0, 0)
|
||||
check(t, 2, 1, 0)
|
||||
check(t, 3, 1, 0)
|
||||
check(t, 4, 2, 1)
|
||||
})
|
||||
t.Run("different block duration", func(t *testing.T) {
|
||||
blockDur = 3
|
||||
|
||||
require.NoError(t, bt.Reset())
|
||||
baseCounter = 0
|
||||
deltaCounter = 0
|
||||
|
||||
check(t, 1, 0, 0)
|
||||
check(t, 2, 0, 0)
|
||||
check(t, 3, 1, 0)
|
||||
check(t, 4, 1, 0)
|
||||
check(t, 5, 1, 0)
|
||||
check(t, 6, 2, 1)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue