diff --git a/triedb/pathdb/history_index.go b/triedb/pathdb/history_index.go index 5b4c91d7e61..6c9668847d8 100644 --- a/triedb/pathdb/history_index.go +++ b/triedb/pathdb/history_index.go @@ -107,9 +107,7 @@ func (r *indexReader) refresh() error { // may have been modified by additional elements written to the disk. if len(r.descList) != 0 { last := r.descList[len(r.descList)-1] - if !last.full() { - delete(r.readers, last.id) - } + delete(r.readers, last.id) } descList, err := loadIndexData(r.db, r.state) if err != nil { @@ -158,19 +156,23 @@ type indexWriter struct { lastID uint64 // The ID of the latest tracked history state stateIdent db ethdb.KeyValueReader + + // configs + blockCap uint16 // Maximum number of entries grouped into a single index block } // newIndexWriter constructs the index writer for the specified state. -func newIndexWriter(db ethdb.KeyValueReader, state stateIdent) (*indexWriter, error) { +func newIndexWriter(db ethdb.KeyValueReader, state stateIdent, blockCap uint16) (*indexWriter, error) { blob := readStateIndex(state, db) if len(blob) == 0 { desc := newIndexBlockDesc(0) - bw, _ := newBlockWriter(nil, desc) + bw, _ := newBlockWriter(nil, desc, blockCap) return &indexWriter{ descList: []*indexBlockDesc{desc}, bw: bw, state: state, db: db, + blockCap: blockCap, }, nil } descList, err := parseIndex(blob) @@ -179,7 +181,7 @@ func newIndexWriter(db ethdb.KeyValueReader, state stateIdent) (*indexWriter, er } lastDesc := descList[len(descList)-1] indexBlock := readStateIndexBlock(state, db, lastDesc.id) - bw, err := newBlockWriter(indexBlock, lastDesc) + bw, err := newBlockWriter(indexBlock, lastDesc, blockCap) if err != nil { return nil, err } @@ -189,6 +191,7 @@ func newIndexWriter(db ethdb.KeyValueReader, state stateIdent) (*indexWriter, er bw: bw, state: state, db: db, + blockCap: blockCap, }, nil } @@ -218,7 +221,7 @@ func (w *indexWriter) rotate() error { desc = newIndexBlockDesc(w.bw.desc.id + 1) ) w.frozen = append(w.frozen, w.bw) - w.bw, err = newBlockWriter(nil, desc) + w.bw, err = newBlockWriter(nil, desc, w.blockCap) if err != nil { return err } @@ -265,21 +268,25 @@ type indexDeleter struct { lastID uint64 // The ID of the latest tracked history state stateIdent db ethdb.KeyValueReader + + // configs + blockCap uint16 // Maximum number of entries grouped into a single index block } // newIndexDeleter constructs the index deleter for the specified state. -func newIndexDeleter(db ethdb.KeyValueReader, state stateIdent) (*indexDeleter, error) { +func newIndexDeleter(db ethdb.KeyValueReader, state stateIdent, blockCap uint16) (*indexDeleter, error) { blob := readStateIndex(state, db) if len(blob) == 0 { // TODO(rjl493456442) we can probably return an error here, // deleter with no data is meaningless. desc := newIndexBlockDesc(0) - bw, _ := newBlockWriter(nil, desc) + bw, _ := newBlockWriter(nil, desc, blockCap) return &indexDeleter{ descList: []*indexBlockDesc{desc}, bw: bw, state: state, db: db, + blockCap: blockCap, }, nil } descList, err := parseIndex(blob) @@ -288,7 +295,7 @@ func newIndexDeleter(db ethdb.KeyValueReader, state stateIdent) (*indexDeleter, } lastDesc := descList[len(descList)-1] indexBlock := readStateIndexBlock(state, db, lastDesc.id) - bw, err := newBlockWriter(indexBlock, lastDesc) + bw, err := newBlockWriter(indexBlock, lastDesc, blockCap) if err != nil { return nil, err } @@ -334,7 +341,7 @@ func (d *indexDeleter) pop(id uint64) error { // Open the previous block writer for deleting lastDesc := d.descList[len(d.descList)-1] indexBlock := readStateIndexBlock(d.state, d.db, lastDesc.id) - bw, err := newBlockWriter(indexBlock, lastDesc) + bw, err := newBlockWriter(indexBlock, lastDesc, d.blockCap) if err != nil { return err } diff --git a/triedb/pathdb/history_index_block.go b/triedb/pathdb/history_index_block.go index 7648b99226c..51bde8d6853 100644 --- a/triedb/pathdb/history_index_block.go +++ b/triedb/pathdb/history_index_block.go @@ -25,10 +25,8 @@ import ( ) const ( - indexBlockDescSize = 14 // The size of index block descriptor - indexBlockEntriesCap = 4096 // The maximum number of entries can be grouped in a block - indexBlockRestartLen = 256 // The restart interval length of index block - historyIndexBatch = 1_000_000 // The number of state history indexes for constructing or deleting as batch + indexBlockDescSize = 14 // The size of index block descriptor + indexBlockRestartLen = 256 // The restart interval length of index block ) // indexBlockDesc represents a descriptor for an index block, which contains a @@ -51,8 +49,8 @@ func (d *indexBlockDesc) empty() bool { // full indicates whether the number of elements in the block exceeds the // preconfigured limit. -func (d *indexBlockDesc) full() bool { - return d.entries >= indexBlockEntriesCap +func (d *indexBlockDesc) full(capacity uint16) bool { + return d.entries >= capacity } // encode packs index block descriptor into byte stream. @@ -222,13 +220,15 @@ type blockWriter struct { desc *indexBlockDesc // Descriptor of the block restarts []uint16 // Offsets into the data slice, marking the start of each section data []byte // Aggregated encoded data slice + capacity uint16 // Maximum number of entries grouped into a single block } -func newBlockWriter(blob []byte, desc *indexBlockDesc) (*blockWriter, error) { +func newBlockWriter(blob []byte, desc *indexBlockDesc, capacity uint16) (*blockWriter, error) { if len(blob) == 0 { return &blockWriter{ - desc: desc, - data: make([]byte, 0, 1024), + desc: desc, + data: make([]byte, 0, 1024), + capacity: capacity, }, nil } restarts, data, err := parseIndexBlock(blob) @@ -239,6 +239,7 @@ func newBlockWriter(blob []byte, desc *indexBlockDesc) (*blockWriter, error) { desc: desc, restarts: restarts, data: data, // safe to own the slice + capacity: capacity, }, nil } @@ -372,7 +373,7 @@ func (b *blockWriter) empty() bool { } func (b *blockWriter) full() bool { - return b.desc.full() + return b.desc.full(b.capacity) } // finish finalizes the index block encoding by appending the encoded restart points diff --git a/triedb/pathdb/history_index_block_test.go b/triedb/pathdb/history_index_block_test.go index c251cea2ecb..70362c9020c 100644 --- a/triedb/pathdb/history_index_block_test.go +++ b/triedb/pathdb/history_index_block_test.go @@ -25,10 +25,11 @@ import ( ) func TestBlockReaderBasic(t *testing.T) { + blockCap := uint16(4096) elements := []uint64{ 1, 5, 10, 11, 20, } - bw, _ := newBlockWriter(nil, newIndexBlockDesc(0)) + bw, _ := newBlockWriter(nil, newIndexBlockDesc(0), blockCap) for i := 0; i < len(elements); i++ { bw.append(elements[i]) } @@ -60,13 +61,14 @@ func TestBlockReaderBasic(t *testing.T) { } func TestBlockReaderLarge(t *testing.T) { + blockCap := uint16(4096) var elements []uint64 for i := 0; i < 1000; i++ { elements = append(elements, rand.Uint64()) } slices.Sort(elements) - bw, _ := newBlockWriter(nil, newIndexBlockDesc(0)) + bw, _ := newBlockWriter(nil, newIndexBlockDesc(0), blockCap) for i := 0; i < len(elements); i++ { bw.append(elements[i]) } @@ -95,7 +97,8 @@ func TestBlockReaderLarge(t *testing.T) { } func TestBlockWriterBasic(t *testing.T) { - bw, _ := newBlockWriter(nil, newIndexBlockDesc(0)) + blockCap := uint16(4096) + bw, _ := newBlockWriter(nil, newIndexBlockDesc(0), blockCap) if !bw.empty() { t.Fatal("expected empty block") } @@ -107,7 +110,7 @@ func TestBlockWriterBasic(t *testing.T) { bw.append(uint64(i + 3)) } - bw, err := newBlockWriter(bw.finish(), newIndexBlockDesc(0)) + bw, err := newBlockWriter(bw.finish(), newIndexBlockDesc(0), blockCap) if err != nil { t.Fatalf("Failed to construct the block writer, %v", err) } @@ -120,7 +123,8 @@ func TestBlockWriterBasic(t *testing.T) { } func TestBlockWriterDelete(t *testing.T) { - bw, _ := newBlockWriter(nil, newIndexBlockDesc(0)) + blockCap := uint16(4096) + bw, _ := newBlockWriter(nil, newIndexBlockDesc(0), blockCap) for i := 0; i < 10; i++ { bw.append(uint64(i + 1)) } @@ -144,10 +148,11 @@ func TestBlockWriterDelete(t *testing.T) { } func TestBlcokWriterDeleteWithData(t *testing.T) { + blockCap := uint16(4096) elements := []uint64{ 1, 5, 10, 11, 20, } - bw, _ := newBlockWriter(nil, newIndexBlockDesc(0)) + bw, _ := newBlockWriter(nil, newIndexBlockDesc(0), blockCap) for i := 0; i < len(elements); i++ { bw.append(elements[i]) } @@ -158,7 +163,7 @@ func TestBlcokWriterDeleteWithData(t *testing.T) { max: 20, entries: 5, } - bw, err := newBlockWriter(bw.finish(), desc) + bw, err := newBlockWriter(bw.finish(), desc, blockCap) if err != nil { t.Fatalf("Failed to construct block writer %v", err) } @@ -201,7 +206,8 @@ func TestBlcokWriterDeleteWithData(t *testing.T) { } func TestCorruptedIndexBlock(t *testing.T) { - bw, _ := newBlockWriter(nil, newIndexBlockDesc(0)) + blockCap := uint16(4096) + bw, _ := newBlockWriter(nil, newIndexBlockDesc(0), blockCap) for i := 0; i < 10; i++ { bw.append(uint64(i + 1)) } @@ -209,7 +215,7 @@ func TestCorruptedIndexBlock(t *testing.T) { // Mutate the buffer manually buf[len(buf)-1]++ - _, err := newBlockWriter(buf, newIndexBlockDesc(0)) + _, err := newBlockWriter(buf, newIndexBlockDesc(0), blockCap) if err == nil { t.Fatal("Corrupted index block data is not detected") } @@ -218,8 +224,9 @@ func TestCorruptedIndexBlock(t *testing.T) { // BenchmarkParseIndexBlock benchmarks the performance of parseIndexBlock. func BenchmarkParseIndexBlock(b *testing.B) { // Generate a realistic index block blob - bw, _ := newBlockWriter(nil, newIndexBlockDesc(0)) - for i := 0; i < 4096; i++ { + blockCap := uint16(4096) + bw, _ := newBlockWriter(nil, newIndexBlockDesc(0), blockCap) + for i := 0; i < int(blockCap); i++ { bw.append(uint64(i * 2)) } blob := bw.finish() @@ -238,13 +245,14 @@ func BenchmarkBlockWriterAppend(b *testing.B) { b.ReportAllocs() b.ResetTimer() + blockCap := uint16(4096) desc := newIndexBlockDesc(0) - writer, _ := newBlockWriter(nil, desc) + writer, _ := newBlockWriter(nil, desc, blockCap) for i := 0; i < b.N; i++ { if writer.full() { desc = newIndexBlockDesc(0) - writer, _ = newBlockWriter(nil, desc) + writer, _ = newBlockWriter(nil, desc, blockCap) } if err := writer.append(writer.desc.max + 1); err != nil { b.Error(err) diff --git a/triedb/pathdb/history_index_test.go b/triedb/pathdb/history_index_test.go index be9b7c40491..170525ffa05 100644 --- a/triedb/pathdb/history_index_test.go +++ b/triedb/pathdb/history_index_test.go @@ -29,11 +29,12 @@ import ( ) func TestIndexReaderBasic(t *testing.T) { + blockCap := uint16(4096) elements := []uint64{ 1, 5, 10, 11, 20, } db := rawdb.NewMemoryDatabase() - bw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa})) + bw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa}), blockCap) for i := 0; i < len(elements); i++ { bw.append(elements[i]) } @@ -68,14 +69,15 @@ func TestIndexReaderBasic(t *testing.T) { } func TestIndexReaderLarge(t *testing.T) { + blockCap := uint16(4096) var elements []uint64 - for i := 0; i < 10*indexBlockEntriesCap; i++ { + for i := 0; i < 10*int(blockCap); i++ { elements = append(elements, rand.Uint64()) } slices.Sort(elements) db := rawdb.NewMemoryDatabase() - bw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa})) + bw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa}), blockCap) for i := 0; i < len(elements); i++ { bw.append(elements[i]) } @@ -121,8 +123,9 @@ func TestEmptyIndexReader(t *testing.T) { } func TestIndexWriterBasic(t *testing.T) { + blockCap := uint16(4096) db := rawdb.NewMemoryDatabase() - iw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa})) + iw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa}), blockCap) iw.append(2) if err := iw.append(1); err == nil { t.Fatal("out-of-order insertion is not expected") @@ -134,7 +137,7 @@ func TestIndexWriterBasic(t *testing.T) { iw.finish(batch) batch.Write() - iw, err := newIndexWriter(db, newAccountIdent(common.Hash{0xa})) + iw, err := newIndexWriter(db, newAccountIdent(common.Hash{0xa}), blockCap) if err != nil { t.Fatalf("Failed to construct the block writer, %v", err) } @@ -147,9 +150,10 @@ func TestIndexWriterBasic(t *testing.T) { } func TestIndexWriterDelete(t *testing.T) { + blockCap := uint16(4096) db := rawdb.NewMemoryDatabase() - iw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa})) - for i := 0; i < indexBlockEntriesCap*4; i++ { + iw, _ := newIndexWriter(db, newAccountIdent(common.Hash{0xa}), blockCap) + for i := 0; i < int(blockCap)*4; i++ { iw.append(uint64(i + 1)) } batch := db.NewBatch() @@ -157,11 +161,11 @@ func TestIndexWriterDelete(t *testing.T) { batch.Write() // Delete unknown id, the request should be rejected - id, _ := newIndexDeleter(db, newAccountIdent(common.Hash{0xa})) - if err := id.pop(indexBlockEntriesCap * 5); err == nil { + id, _ := newIndexDeleter(db, newAccountIdent(common.Hash{0xa}), blockCap) + if err := id.pop(uint64(blockCap) * 5); err == nil { t.Fatal("Expect error to occur for unknown id") } - for i := indexBlockEntriesCap * 4; i >= 1; i-- { + for i := int(blockCap) * 4; i >= 1; i-- { if err := id.pop(uint64(i)); err != nil { t.Fatalf("Unexpected error for element popping, %v", err) } @@ -179,7 +183,7 @@ func TestIndexWriterDelete(t *testing.T) { func TestBatchIndexerWrite(t *testing.T) { var ( db = rawdb.NewMemoryDatabase() - batch = newBatchIndexer(db, false, typeStateHistory) + batch = newBatchIndexer(indexerConfigs[typeStateHistory], db, false, typeStateHistory) histories = makeStateHistories(10) ) for i, h := range histories { @@ -256,7 +260,7 @@ func TestBatchIndexerWrite(t *testing.T) { func TestBatchIndexerDelete(t *testing.T) { var ( db = rawdb.NewMemoryDatabase() - bw = newBatchIndexer(db, false, typeStateHistory) + bw = newBatchIndexer(indexerConfigs[typeStateHistory], db, false, typeStateHistory) histories = makeStateHistories(10) ) // Index histories @@ -270,7 +274,7 @@ func TestBatchIndexerDelete(t *testing.T) { } // Unindex histories - bd := newBatchIndexer(db, true, typeStateHistory) + bd := newBatchIndexer(indexerConfigs[typeStateHistory], db, true, typeStateHistory) for i := len(histories) - 1; i >= 0; i-- { if err := bd.process(histories[i], uint64(i+1)); err != nil { t.Fatalf("Failed to process history, %v", err) diff --git a/triedb/pathdb/history_indexer.go b/triedb/pathdb/history_indexer.go index 368ff78d415..38db8cbf5c4 100644 --- a/triedb/pathdb/history_indexer.go +++ b/triedb/pathdb/history_indexer.go @@ -40,6 +40,11 @@ const ( stateHistoryIndexVersion = stateHistoryIndexV0 // the current state index version trienodeHistoryIndexV0 = uint8(0) // initial version of trienode index structure trienodeHistoryIndexVersion = trienodeHistoryIndexV0 // the current trienode index version + + // estimations for calculating the batch size for atomic database commit + estimatedStateHistoryIndexSize = 2 // The average size of each state history index entry is approximately 1–2 bytes + estimatedTrienodeHistoryIndexSize = 3 // The average size of each trienode history index entry is approximately 2-3 bytes + estimatedIndexBatchSizeFactor = 32 // The factor counts for the write amplification for each entry ) // indexVersion returns the latest index version for the given history type. @@ -120,6 +125,7 @@ func deleteIndexMetadata(db ethdb.KeyValueWriter, typ historyType) { // batchIndexer is responsible for performing batch indexing or unindexing // of historical data (e.g., state or trie node changes) atomically. type batchIndexer struct { + config historyIndexerConfig // Configs for history index index map[stateIdent][]uint64 // List of history IDs for tracked state entry pending int // Number of entries processed in the current batch. delete bool // Operation mode: true for unindex, false for index. @@ -129,8 +135,9 @@ type batchIndexer struct { } // newBatchIndexer constructs the batch indexer with the supplied mode. -func newBatchIndexer(db ethdb.KeyValueStore, delete bool, typ historyType) *batchIndexer { +func newBatchIndexer(config historyIndexerConfig, db ethdb.KeyValueStore, delete bool, typ historyType) *batchIndexer { return &batchIndexer{ + config: config, index: make(map[stateIdent][]uint64), delete: delete, typ: typ, @@ -150,17 +157,31 @@ func (b *batchIndexer) process(h history, id uint64) error { return b.finish(false) } +// makeBatch constructs a database batch based on the number of pending entries. +// The batch size is roughly estimated to minimize repeated resizing rounds, +// as accurately predicting the exact size is technically challenging. +func (b *batchIndexer) makeBatch() ethdb.Batch { + var size int + switch b.typ { + case typeStateHistory: + size = estimatedStateHistoryIndexSize + case typeTrienodeHistory: + size = estimatedTrienodeHistoryIndexSize + } + return b.db.NewBatchWithSize(size * estimatedIndexBatchSizeFactor * b.pending) +} + // finish writes the accumulated state indexes into the disk if either the // memory limitation is reached or it's requested forcibly. func (b *batchIndexer) finish(force bool) error { if b.pending == 0 { return nil } - if !force && b.pending < historyIndexBatch { + if !force && b.pending < b.config.indexBatchSize { return nil } var ( - batch = b.db.NewBatch() + batch = b.makeBatch() batchMu sync.RWMutex start = time.Now() eg errgroup.Group @@ -170,7 +191,7 @@ func (b *batchIndexer) finish(force bool) error { for ident, list := range b.index { eg.Go(func() error { if !b.delete { - iw, err := newIndexWriter(b.db, ident) + iw, err := newIndexWriter(b.db, ident, b.config.maxEntriesPerBlock) if err != nil { return err } @@ -183,7 +204,7 @@ func (b *batchIndexer) finish(force bool) error { iw.finish(batch) batchMu.Unlock() } else { - id, err := newIndexDeleter(b.db, ident) + id, err := newIndexDeleter(b.db, ident, b.config.maxEntriesPerBlock) if err != nil { return err } @@ -222,7 +243,7 @@ func (b *batchIndexer) finish(force bool) error { } // indexSingle processes the state history with the specified ID for indexing. -func indexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.AncientReader, typ historyType) error { +func indexSingle(config historyIndexerConfig, historyID uint64, db ethdb.KeyValueStore, freezer ethdb.AncientReader, typ historyType) error { start := time.Now() defer func() { if typ == typeStateHistory { @@ -243,7 +264,7 @@ func indexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.Ancient var ( err error h history - b = newBatchIndexer(db, false, typ) + b = newBatchIndexer(config, db, false, typ) ) if typ == typeStateHistory { h, err = readStateHistory(freezer, historyID) @@ -264,7 +285,7 @@ func indexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.Ancient } // unindexSingle processes the state history with the specified ID for unindexing. -func unindexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.AncientReader, typ historyType) error { +func unindexSingle(config historyIndexerConfig, historyID uint64, db ethdb.KeyValueStore, freezer ethdb.AncientReader, typ historyType) error { start := time.Now() defer func() { if typ == typeStateHistory { @@ -286,7 +307,7 @@ func unindexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.Ancie err error h history ) - b := newBatchIndexer(db, true, typ) + b := newBatchIndexer(config, db, true, typ) if typ == typeStateHistory { h, err = readStateHistory(freezer, historyID) } else { @@ -319,6 +340,7 @@ type interruptSignal struct { // If a state history is removed due to a rollback, the associated indexes should // be unmarked accordingly. type indexIniter struct { + config historyIndexerConfig disk ethdb.KeyValueStore freezer ethdb.AncientStore interrupt chan *interruptSignal @@ -334,8 +356,9 @@ type indexIniter struct { wg sync.WaitGroup } -func newIndexIniter(disk ethdb.KeyValueStore, freezer ethdb.AncientStore, typ historyType, lastID uint64) *indexIniter { +func newIndexIniter(config historyIndexerConfig, disk ethdb.KeyValueStore, freezer ethdb.AncientStore, typ historyType, lastID uint64) *indexIniter { initer := &indexIniter{ + config: config, disk: disk, freezer: freezer, interrupt: make(chan *interruptSignal), @@ -446,7 +469,7 @@ func (i *indexIniter) run(lastID uint64) { // been fully indexed, unindex it here and shut down the initializer. if checkDone() { i.log.Info("Truncate the extra history", "id", lastID) - if err := unindexSingle(lastID, i.disk, i.freezer, i.typ); err != nil { + if err := unindexSingle(i.config, lastID, i.disk, i.freezer, i.typ); err != nil { signal.result <- err return } @@ -547,7 +570,7 @@ func (i *indexIniter) index(done chan struct{}, interrupt *atomic.Int32, lastID current = beginID start = time.Now() logged = time.Now() - batch = newBatchIndexer(i.disk, false, i.typ) + batch = newBatchIndexer(i.config, i.disk, false, i.typ) ) for current <= lastID { count := lastID - current + 1 @@ -653,6 +676,37 @@ func (i *indexIniter) recover(lastID uint64) { } } +// historyIndexerConfig defines the configuration parameters used for building +// history indexes. +// +// Each state index maintains a set of index blocks, each grouping multiple history +// entries. The configuration below controls how these entries are organized, +// batched, and stored for different types of history data. +type historyIndexerConfig struct { + maxEntriesPerBlock uint16 // Maximum number of entries grouped into a single index block + indexBatchSize int // Number of history entries processed in a single operation +} + +// indexerConfigs defines the configs for various history indexer. +var indexerConfigs = map[historyType]historyIndexerConfig{ + typeStateHistory: { + // The average size of each entry is approximately 1–2 bytes. Therefore, a block + // size of 2K entries is chosen to roughly limit the storage size to around 4KB. + // + // Note, this block size was chosen as 4K previously. Changing the block size + // won't break the backward compatibility. + maxEntriesPerBlock: 2048, + indexBatchSize: 512 * 1024, + }, + typeTrienodeHistory: { + // The average size of each entry is approximately 1–2 bytes, with an additional + // byte reserved for extension. Therefore, a block size of 1K entries is chosen + // to roughly limit the storage size to around 4KB. + maxEntriesPerBlock: 1024, + indexBatchSize: 512 * 1024, + }, +} + // historyIndexer manages the indexing and unindexing of state histories, // providing access to historical states. // @@ -664,6 +718,7 @@ func (i *indexIniter) recover(lastID uint64) { // the history index is created or removed along with the corresponding // state history. type historyIndexer struct { + config historyIndexerConfig initer *indexIniter typ historyType disk ethdb.KeyValueStore @@ -718,8 +773,14 @@ func checkVersion(disk ethdb.KeyValueStore, typ historyType) { // initer to complete the indexing of any remaining state histories. func newHistoryIndexer(disk ethdb.KeyValueStore, freezer ethdb.AncientStore, lastHistoryID uint64, typ historyType) *historyIndexer { checkVersion(disk, typ) + + config, exists := indexerConfigs[typ] + if !exists { + panic(fmt.Errorf("unknown history type: %v", typ)) + } return &historyIndexer{ - initer: newIndexIniter(disk, freezer, typ, lastHistoryID), + config: config, + initer: newIndexIniter(config, disk, freezer, typ, lastHistoryID), typ: typ, disk: disk, freezer: freezer, @@ -748,7 +809,7 @@ func (i *historyIndexer) extend(historyID uint64) error { case <-i.initer.closed: return errors.New("indexer is closed") case <-i.initer.done: - return indexSingle(historyID, i.disk, i.freezer, i.typ) + return indexSingle(i.config, historyID, i.disk, i.freezer, i.typ) case i.initer.interrupt <- signal: return <-signal.result } @@ -765,7 +826,7 @@ func (i *historyIndexer) shorten(historyID uint64) error { case <-i.initer.closed: return errors.New("indexer is closed") case <-i.initer.done: - return unindexSingle(historyID, i.disk, i.freezer, i.typ) + return unindexSingle(i.config, historyID, i.disk, i.freezer, i.typ) case i.initer.interrupt <- signal: return <-signal.result }