erigon-pulse/erigon-lib/state/gc_test.go

176 lines
5.2 KiB
Go
Raw Permalink Normal View History

package state
import (
"context"
"testing"
2023-03-15 06:47:48 +00:00
"time"
2023-03-15 06:47:48 +00:00
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/log/v3"
"github.com/stretchr/testify/require"
)
func TestGCReadAfterRemoveFile(t *testing.T) {
logger := log.New()
2023-03-15 06:47:48 +00:00
logEvery := time.NewTicker(30 * time.Second)
defer logEvery.Stop()
ctx := context.Background()
2023-03-15 06:47:48 +00:00
test := func(t *testing.T, h *History, db kv.RwDB, txs uint64) {
t.Helper()
require := require.New(t)
collateAndMergeHistory(t, db, h, txs)
2023-03-15 06:47:48 +00:00
t.Run("read after: remove when have reader", func(t *testing.T) {
tx, err := db.BeginRo(ctx)
require.NoError(err)
defer tx.Rollback()
2023-03-15 06:47:48 +00:00
// - create immutable view
// - del cold file
// - read from canDelete file
// - close view
// - open new view
// - make sure there is no canDelete file
hc := h.MakeContext()
_ = hc
lastOnFs, _ := h.files.Max()
require.False(lastOnFs.frozen) // prepared dataset must have some non-frozen files. or it's bad dataset.
h.integrateMergedFiles(nil, []*filesItem{lastOnFs}, nil, nil)
require.NotNil(lastOnFs.decompressor)
2023-03-15 06:47:48 +00:00
lastInView := hc.files[len(hc.files)-1]
g := lastInView.src.decompressor.MakeGetter()
require.Equal(lastInView.startTxNum, lastOnFs.startTxNum)
require.Equal(lastInView.endTxNum, lastOnFs.endTxNum)
if g.HasNext() {
k, _ := g.Next(nil)
require.Equal(8, len(k))
v, _ := g.Next(nil)
require.Equal(8, len(v))
}
2023-03-15 06:47:48 +00:00
require.NotNil(lastOnFs.decompressor)
loc := hc.ic.loc // replace of locality index must not affect current HistoryContext, but expect to be closed after last reader
h.localityIndex.integrateFiles(LocalityIndexFiles{}, 0, 0)
require.NotNil(loc.file)
hc.Close()
require.Nil(lastOnFs.decompressor)
require.NotNil(loc.file)
2023-03-15 06:47:48 +00:00
nonDeletedOnFs, _ := h.files.Max()
require.False(nonDeletedOnFs.frozen)
require.NotNil(nonDeletedOnFs.decompressor) // non-canDelete files are not closed
2023-03-15 06:47:48 +00:00
hc = h.MakeContext()
newLastInView := hc.files[len(hc.files)-1]
require.False(lastOnFs.frozen)
require.False(lastInView.startTxNum == newLastInView.startTxNum && lastInView.endTxNum == newLastInView.endTxNum)
2023-03-15 06:47:48 +00:00
hc.Close()
})
2023-03-15 06:47:48 +00:00
t.Run("read after: remove when no readers", func(t *testing.T) {
tx, err := db.BeginRo(ctx)
require.NoError(err)
defer tx.Rollback()
2023-03-15 06:47:48 +00:00
// - del cold file
// - new reader must not see canDelete file
hc := h.MakeContext()
lastOnFs, _ := h.files.Max()
require.False(lastOnFs.frozen) // prepared dataset must have some non-frozen files. or it's bad dataset.
h.integrateMergedFiles(nil, []*filesItem{lastOnFs}, nil, nil)
2023-03-15 06:47:48 +00:00
require.NotNil(lastOnFs.decompressor)
hc.Close()
require.Nil(lastOnFs.decompressor)
})
}
t.Run("large_values", func(t *testing.T) {
_, db, h, txs := filledHistory(t, true, logger)
2023-03-15 06:47:48 +00:00
test(t, h, db, txs)
})
t.Run("small_values", func(t *testing.T) {
_, db, h, txs := filledHistory(t, false, logger)
2023-03-15 06:47:48 +00:00
test(t, h, db, txs)
})
}
2023-03-22 03:42:32 +00:00
func TestDomainGCReadAfterRemoveFile(t *testing.T) {
logEvery := time.NewTicker(30 * time.Second)
defer logEvery.Stop()
ctx := context.Background()
test := func(t *testing.T, h *Domain, db kv.RwDB, txs uint64) {
t.Helper()
require := require.New(t)
collateAndMerge(t, db, nil, h, txs)
t.Run("read after: remove when have reader", func(t *testing.T) {
tx, err := db.BeginRo(ctx)
require.NoError(err)
defer tx.Rollback()
// - create immutable view
// - del cold file
// - read from canDelete file
// - close view
// - open new view
// - make sure there is no canDelete file
hc := h.MakeContext()
_ = hc
lastOnFs, _ := h.files.Max()
require.False(lastOnFs.frozen) // prepared dataset must have some non-frozen files. or it's bad dataset.
h.integrateMergedFiles([]*filesItem{lastOnFs}, nil, nil, nil, nil, nil)
require.NotNil(lastOnFs.decompressor)
lastInView := hc.files[len(hc.files)-1]
g := lastInView.src.decompressor.MakeGetter()
require.Equal(lastInView.startTxNum, lastOnFs.startTxNum)
require.Equal(lastInView.endTxNum, lastOnFs.endTxNum)
if g.HasNext() {
k, _ := g.Next(nil)
require.Equal(8, len(k))
v, _ := g.Next(nil)
require.Equal(8, len(v))
}
require.NotNil(lastOnFs.decompressor)
hc.Close()
require.Nil(lastOnFs.decompressor)
nonDeletedOnFs, _ := h.files.Max()
require.False(nonDeletedOnFs.frozen)
require.NotNil(nonDeletedOnFs.decompressor) // non-canDelete files are not closed
hc = h.MakeContext()
newLastInView := hc.files[len(hc.files)-1]
require.False(lastOnFs.frozen)
require.False(lastInView.startTxNum == newLastInView.startTxNum && lastInView.endTxNum == newLastInView.endTxNum)
hc.Close()
})
t.Run("read after: remove when no readers", func(t *testing.T) {
tx, err := db.BeginRo(ctx)
require.NoError(err)
defer tx.Rollback()
// - del cold file
// - new reader must not see canDelete file
hc := h.MakeContext()
lastOnFs, _ := h.files.Max()
require.False(lastOnFs.frozen) // prepared dataset must have some non-frozen files. or it's bad dataset.
2023-03-23 03:18:00 +00:00
h.integrateMergedFiles([]*filesItem{lastOnFs}, nil, nil, nil, nil, nil)
2023-03-22 03:42:32 +00:00
require.NotNil(lastOnFs.decompressor)
hc.Close()
require.Nil(lastOnFs.decompressor)
})
}
logger := log.New()
_, db, d, txs := filledDomain(t, logger)
2023-03-22 03:42:32 +00:00
test(t, d, db, txs)
}