Skip to content

Commit cf35473

Browse files
committed
refactor: rename store to database
1 parent 64ca7f1 commit cf35473

File tree

8 files changed

+57
-59
lines changed

8 files changed

+57
-59
lines changed

x/blockdb/README.md

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,14 @@
22

33
BlockDB is a specialized storage system designed for blockchain blocks. It provides O(1) write performance with support for parallel operations. Unlike general-purpose key-value stores like LevelDB that require periodic compaction, BlockDB's append-only design ensures consistently fast writes without the overhead of background maintenance operations.
44

5-
## Key Functionalities (Needs Review)
5+
## Key Functionalities
66

77
- **O(1) Performance**: Both reads and writes complete in constant time
88
- **Parallel Operations**: Multiple threads can read and write blocks concurrently without blocking
9-
- **Flexible Write Ordering**: Supports out-of-order block writes for efficient synchronization
10-
- **Configurable Durability**: Optional `syncToDisk` mode guarantees immediate recoverability at the cost of performance
9+
- **Flexible Write Ordering**: Supports out-of-order block writes for bootstrapping
10+
- **Configurable Durability**: Optional `syncToDisk` mode guarantees immediate recoverability
1111
- **Automatic Recovery**: Detects and recovers unindexed blocks after unclean shutdowns
12-
- **Data Integrity**: Checksums verify block data on every read
13-
- **No Maintenance Required**: Append-only design eliminates the need for compaction or reorganization
14-
- **Progress Tracking**: Maintains maximum contiguous height for sync status
12+
- **Data Integrity**: Checksums verify block data on reads
1513

1614
## Architecture
1715

@@ -27,6 +25,7 @@ BlockDB uses two file types: index files and data files. The index file maps blo
2725
│ - Min Height │ │ │ - Data │
2826
│ - MCH │ │ ├─────────────────┤
2927
│ - Data Size │ │ │ Block 2 │
28+
│ - ... │ │ │ │
3029
├─────────────────┤ │ ┌──>│ - Header │
3130
│ Entry[0] │ │ │ │ - Data │
3231
│ - Offset ───────┼──┘ │ ├─────────────────┤
@@ -101,7 +100,7 @@ BlockDB is strictly append-only with no support for deletions. This aligns with
101100
- Straightforward recovery logic
102101
- No compaction overhead
103102

104-
**Trade-off**: Overwriting a block leaves the old data as unreferenced "dead" space. However, since blockchain blocks are immutable and rarely overwritten (only during reorgs), this trade-off has minimal impact in practice.
103+
**Trade-off**: Overwriting a block leaves the old data as unreferenced "dead" space. However, since blocks are immutable and rarely overwritten (only during reorgs), this trade-off has minimal impact in practice.
105104

106105
#### Fixed-Size Index Entries
107106

@@ -164,26 +163,26 @@ BlockDB uses a reader-writer lock for overall thread safety, with atomic operati
164163

165164
## Usage
166165

167-
### Creating a Store
166+
### Creating a Database
168167

169168
```go
170169
import "github.com/ava-labs/avalanchego/x/blockdb"
171170

172-
opts := blockdb.DefaultStoreOptions()
173-
opts.MinimumHeight = 1
171+
config := blockdb.DefaultDatabaseOptions()
172+
config.MinimumHeight = 1
174173

175-
store, err := blockdb.NewStore(
174+
db, err := blockdb.New(
176175
"/path/to/index", // Index directory
177176
"/path/to/data", // Data directory
178177
true, // Sync to disk
179178
false, // Don't truncate existing data
180-
opts,
179+
config,
181180
logger,
182181
)
183182
if err != nil {
184183
return err
185184
}
186-
defer store.Close()
185+
defer db.Close()
187186
```
188187

189188
### Writing and Reading Blocks
@@ -192,17 +191,17 @@ defer store.Close()
192191
// Write a block
193192
height := uint64(100)
194193
blockData := []byte("block data...")
195-
err := store.WriteBlock(height, blockData)
194+
err := db.WriteBlock(height, blockData)
196195

197196
// Read a block
198-
blockData, err := store.ReadBlock(height)
197+
blockData, err := db.ReadBlock(height)
199198
if err == blockdb.ErrBlockNotFound {
200199
// Block doesn't exist at this height
201200
}
202201

203-
// Query store state
204-
maxContiguous := store.MaxContiguousHeight()
205-
minHeight := store.MinHeight()
202+
// Query database state
203+
maxContiguous := db.MaxContiguousHeight()
204+
minHeight := db.MinHeight()
206205
```
207206

208207
## TODO

x/blockdb/block.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ var (
2121

2222
// blockHeader is prepended to each block in the data file.
2323
type blockHeader struct {
24-
Height uint64
24+
Height uint64 // todo: can this be omitted? currently only used for verification
2525
// Size of the raw block data (excluding this blockHeader).
2626
Size uint64
2727
Checksum uint64
@@ -49,12 +49,12 @@ func (bh *blockHeader) UnmarshalBinary(data []byte) error {
4949

5050
// WriteBlock inserts a block into the store at the given height.
5151
// Returns an error if the store is closed, the block is empty, or the write fails.
52-
func (s *Store) WriteBlock(height BlockHeight, block Block) error {
52+
func (s *Database) WriteBlock(height BlockHeight, block Block) error {
5353
s.mu.RLock()
5454
defer s.mu.RUnlock()
5555

5656
if s.closed {
57-
return ErrStoreClosed
57+
return ErrDatabaseClosed
5858
}
5959

6060
if len(block) == 0 {
@@ -95,12 +95,12 @@ func (s *Store) WriteBlock(height BlockHeight, block Block) error {
9595

9696
// ReadBlock retrieves a block by its height.
9797
// Returns the block data or an error if not found or block data is corrupted.
98-
func (s *Store) ReadBlock(height BlockHeight) (Block, error) {
98+
func (s *Database) ReadBlock(height BlockHeight) (Block, error) {
9999
s.mu.RLock()
100100
defer s.mu.RUnlock()
101101

102102
if s.closed {
103-
return nil, ErrStoreClosed
103+
return nil, ErrDatabaseClosed
104104
}
105105

106106
indexEntry, err := s.readIndexEntry(height)
@@ -122,7 +122,7 @@ func (s *Store) ReadBlock(height BlockHeight) (Block, error) {
122122
return s.readAndVerifyBlockData(indexEntry, bh)
123123
}
124124

125-
func (s *Store) readAndVerifyBlockHeader(indexEntry IndexEntry, expectedHeight BlockHeight) (blockHeader, error) {
125+
func (s *Database) readAndVerifyBlockHeader(indexEntry IndexEntry, expectedHeight BlockHeight) (blockHeader, error) {
126126
var bh blockHeader
127127
dataHeaderBuf := make([]byte, sizeOfBlockHeader)
128128
_, err := s.dataFile.ReadAt(dataHeaderBuf, int64(indexEntry.Offset))
@@ -143,7 +143,7 @@ func (s *Store) readAndVerifyBlockHeader(indexEntry IndexEntry, expectedHeight B
143143
return bh, nil
144144
}
145145

146-
func (s *Store) readAndVerifyBlockData(indexEntry IndexEntry, bh blockHeader) (Block, error) {
146+
func (s *Database) readAndVerifyBlockData(indexEntry IndexEntry, bh blockHeader) (Block, error) {
147147
blockData := make(Block, bh.Size)
148148
actualDataOffset := indexEntry.Offset + sizeOfBlockHeader
149149
if actualDataOffset < indexEntry.Offset {
@@ -167,7 +167,7 @@ func calculateChecksum(data []byte) uint64 {
167167
return xxhash.Sum64(data)
168168
}
169169

170-
func (s *Store) writeBlockAtOffset(offset uint64, bh blockHeader, block Block) error {
170+
func (s *Database) writeBlockAtOffset(offset uint64, bh blockHeader, block Block) error {
171171
headerBytes, err := bh.MarshalBinary()
172172
if err != nil {
173173
return fmt.Errorf("failed to serialize block header: %w", err)
@@ -192,7 +192,7 @@ func (s *Store) writeBlockAtOffset(offset uint64, bh blockHeader, block Block) e
192192
return nil
193193
}
194194

195-
func (s *Store) updateBlockHeights(writtenBlockHeight uint64) error {
195+
func (s *Database) updateBlockHeights(writtenBlockHeight uint64) error {
196196
// update max contiguous height
197197
var prevContiguousCandidate uint64
198198
if writtenBlockHeight == s.header.MinBlockHeight {
@@ -244,7 +244,7 @@ func (s *Store) updateBlockHeights(writtenBlockHeight uint64) error {
244244
return nil
245245
}
246246

247-
func (s *Store) allocateBlockSpace(sizeWithDataHeader uint64) (writeDataOffset uint64, err error) {
247+
func (s *Database) allocateBlockSpace(sizeWithDataHeader uint64) (writeDataOffset uint64, err error) {
248248
maxDataFileSize := s.header.MaxDataFileSize
249249

250250
for {

x/blockdb/blockdb.go

Lines changed: 0 additions & 1 deletion
This file was deleted.

x/blockdb/config.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import (
44
"fmt"
55
)
66

7-
// StoreOptions contains optional configuration parameters for BlockDB.
8-
type StoreOptions struct {
7+
// DatabaseConfig contains configuration parameters for BlockDB.
8+
type DatabaseConfig struct {
99
// MinimumHeight is the lowest block height the store will track (must be >= 1).
1010
MinimumHeight uint64
1111

@@ -16,17 +16,17 @@ type StoreOptions struct {
1616
CheckpointInterval uint64
1717
}
1818

19-
// DefaultStoreOptions returns the default options for BlockDB.
20-
func DefaultStoreOptions() StoreOptions {
21-
return StoreOptions{
19+
// DefaultDatabaseConfig returns the default options for BlockDB.
20+
func DefaultDatabaseConfig() DatabaseConfig {
21+
return DatabaseConfig{
2222
MinimumHeight: 1,
2323
MaxDataFileSize: 1 << 31, // Default to 2GB
2424
CheckpointInterval: 1024,
2525
}
2626
}
2727

2828
// Validate checks if the store options are valid.
29-
func (opts StoreOptions) Validate() error {
29+
func (opts DatabaseConfig) Validate() error {
3030
if opts.MinimumHeight == 0 {
3131
return fmt.Errorf("%w: MinimumHeight cannot be 0, must be >= 1", ErrInvalidBlockHeight)
3232
}

x/blockdb/store.go renamed to x/blockdb/database.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ type BlockHeight = uint64
2323
// Block defines the type for block data.
2424
type Block = []byte
2525

26-
// Store is a collection of blockchain blocks. It provides methods to read, write, and manage blocks on disk.
27-
type Store struct {
26+
// Database is a collection of blockchain blocks. It provides methods to read, write, and manage blocks on disk.
27+
type Database struct {
2828
indexFile *os.File
2929
dataFile *os.File
30-
options StoreOptions
30+
options DatabaseConfig
3131
header IndexFileHeader
3232
log logging.Logger
3333

@@ -45,7 +45,7 @@ type Store struct {
4545
maxContiguousHeight atomic.Uint64
4646
}
4747

48-
func (s *Store) openOrCreateFiles(indexDir, dataDir string, truncate bool) error {
48+
func (s *Database) openOrCreateFiles(indexDir, dataDir string, truncate bool) error {
4949
indexPath := filepath.Join(indexDir, indexFileName)
5050
dataPath := filepath.Join(dataDir, dataFileName)
5151

@@ -75,7 +75,7 @@ func (s *Store) openOrCreateFiles(indexDir, dataDir string, truncate bool) error
7575
return nil
7676
}
7777

78-
func (s *Store) loadOrInitializeHeader(truncate bool) error {
78+
func (s *Database) loadOrInitializeHeader(truncate bool) error {
7979
if truncate {
8080
initialMCH := uint64(0)
8181
if s.options.MinimumHeight > 1 {
@@ -125,25 +125,25 @@ func (s *Store) loadOrInitializeHeader(truncate bool) error {
125125
return nil
126126
}
127127

128-
// NewStore creates or opens a block store.
128+
// New creates a block database.
129129
// Parameters:
130130
// - indexDir: Directory for the index file
131131
// - dataDir: Directory for the data file(s)
132132
// - syncToDisk: If true, forces fsync after writes for guaranteed recoverability
133133
// - truncate: If true, truncates existing store files
134-
// - opts: Optional configuration parameters
134+
// - config: Optional configuration parameters
135135
// - log: Logger instance for structured logging
136-
func NewStore(indexDir, dataDir string, syncToDisk bool, truncate bool, opts StoreOptions, log logging.Logger) (*Store, error) {
136+
func New(indexDir, dataDir string, syncToDisk bool, truncate bool, config DatabaseConfig, log logging.Logger) (*Database, error) {
137137
if indexDir == "" || dataDir == "" {
138138
return nil, fmt.Errorf("both indexDir and dataDir must be provided")
139139
}
140140

141-
if err := opts.Validate(); err != nil {
141+
if err := config.Validate(); err != nil {
142142
return nil, err
143143
}
144144

145-
s := &Store{
146-
options: opts,
145+
s := &Database{
146+
options: config,
147147
syncToDisk: syncToDisk,
148148
log: log,
149149
}
@@ -166,7 +166,7 @@ func NewStore(indexDir, dataDir string, syncToDisk bool, truncate bool, opts Sto
166166
return s, nil
167167
}
168168

169-
func (s *Store) closeFiles() {
169+
func (s *Database) closeFiles() {
170170
if s.indexFile != nil {
171171
s.indexFile.Close()
172172
}
@@ -176,22 +176,22 @@ func (s *Store) closeFiles() {
176176
}
177177

178178
// MaxContiguousHeight returns the highest block height known to be contiguously stored.
179-
func (s *Store) MaxContiguousHeight() BlockHeight {
179+
func (s *Database) MaxContiguousHeight() BlockHeight {
180180
return s.maxContiguousHeight.Load()
181181
}
182182

183183
// MinHeight returns the minimum block height configured for this store.
184-
func (s *Store) MinHeight() uint64 {
184+
func (s *Database) MinHeight() uint64 {
185185
return s.header.MinBlockHeight
186186
}
187187

188-
func (s *Store) MaxBlockHeight() BlockHeight {
188+
func (s *Database) MaxBlockHeight() BlockHeight {
189189
return s.maxBlockHeight.Load()
190190
}
191191

192192
// Close flushes pending writes and closes the store files.
193193
// It is safe to call Close multiple times.
194-
func (s *Store) Close() error {
194+
func (s *Database) Close() error {
195195
s.mu.Lock()
196196
defer s.mu.Unlock()
197197

x/blockdb/errors.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ var (
88
ErrBlockEmpty = fmt.Errorf("blockdb: block is empty")
99
ErrBlockSizeMismatch = fmt.Errorf("blockdb: block size in index file does not match data header")
1010
ErrChecksumMismatch = fmt.Errorf("blockdb: checksum mismatch")
11-
ErrStoreClosed = fmt.Errorf("blockdb: store is closed")
11+
ErrDatabaseClosed = fmt.Errorf("blockdb: database is closed")
1212
ErrInvalidCheckpointInterval = fmt.Errorf("blockdb: invalid checkpoint interval")
1313
ErrCorrupted = fmt.Errorf("blockdb: unrecoverable corruption detected")
1414
ErrBlockTooLarge = fmt.Errorf("blockdb: block size exceeds maximum allowed size of %d bytes", MaxBlockDataSize)

x/blockdb/index.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ func (h *IndexFileHeader) UnmarshalBinary(data []byte) error {
9191
return nil
9292
}
9393

94-
func (s *Store) indexEntryOffset(height BlockHeight) (uint64, error) {
94+
func (s *Database) indexEntryOffset(height BlockHeight) (uint64, error) {
9595
if height < s.header.MinBlockHeight {
9696
return 0, fmt.Errorf("%w: height %d is less than minimum block height %d", ErrInvalidBlockHeight, height, s.header.MinBlockHeight)
9797
}
@@ -107,7 +107,7 @@ func (s *Store) indexEntryOffset(height BlockHeight) (uint64, error) {
107107
return finalOffset, nil
108108
}
109109

110-
func (s *Store) readIndexEntry(height BlockHeight) (IndexEntry, error) {
110+
func (s *Database) readIndexEntry(height BlockHeight) (IndexEntry, error) {
111111
offset, err := s.indexEntryOffset(height)
112112
if err != nil {
113113
return IndexEntry{}, err
@@ -128,7 +128,7 @@ func (s *Store) readIndexEntry(height BlockHeight) (IndexEntry, error) {
128128
return entry, nil
129129
}
130130

131-
func (s *Store) writeIndexEntryAt(indexFileOffset, dataFileBlockOffset, blockDataLen uint64) error {
131+
func (s *Database) writeIndexEntryAt(indexFileOffset, dataFileBlockOffset, blockDataLen uint64) error {
132132
indexEntry := IndexEntry{
133133
Offset: dataFileBlockOffset,
134134
Size: blockDataLen,
@@ -145,7 +145,7 @@ func (s *Store) writeIndexEntryAt(indexFileOffset, dataFileBlockOffset, blockDat
145145
return nil
146146
}
147147

148-
func (s *Store) persistIndexHeader(syncToDisk bool) error {
148+
func (s *Database) persistIndexHeader(syncToDisk bool) error {
149149
// Why fsync indexFile before writing its header?
150150
// To prevent a critical inconsistency: the header must not describe a state
151151
// more advanced than what's durably stored in the index entries.

x/blockdb/recovery.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const (
1515
// recover attempts to restore the store to a consistent state by scanning the data file
1616
// for blocks that may not be correctly indexed, usually after an unclean shutdown.
1717
// It reconciles the data file with the index file header and entries.
18-
func (s *Store) recover() error {
18+
func (s *Database) recover() error {
1919
dataFileInfo, err := s.dataFile.Stat()
2020
if err != nil {
2121
return fmt.Errorf("failed to get data file stats for recovery: %w", err)
@@ -94,7 +94,7 @@ func (s *Store) recover() error {
9494

9595
// recoverBlockAtOffset attempts to read, validate, and index a block at the given offset.
9696
// Returns the blockHeader and an error if the block is invalid or incomplete.
97-
func (s *Store) recoverBlockAtOffset(offset, dataFileActualSize uint64) (blockHeader, error) {
97+
func (s *Database) recoverBlockAtOffset(offset, dataFileActualSize uint64) (blockHeader, error) {
9898
var bh blockHeader
9999
if dataFileActualSize-offset < sizeOfBlockHeader {
100100
return bh, fmt.Errorf("not enough data for block header at offset %d", offset)
@@ -143,7 +143,7 @@ func (s *Store) recoverBlockAtOffset(offset, dataFileActualSize uint64) (blockHe
143143

144144
// updateMaxContiguousHeightOnRecovery extends the max contiguous height from the value in the header,
145145
// incrementing as long as contiguous blocks exist.
146-
func (s *Store) updateMaxContiguousHeightOnRecovery() {
146+
func (s *Database) updateMaxContiguousHeightOnRecovery() {
147147
currentMCH := s.header.MaxContiguousBlockHeight
148148
highestKnown := s.maxBlockHeight.Load()
149149

0 commit comments

Comments
 (0)