-
Notifications
You must be signed in to change notification settings - Fork 779
Remove version db from merkle db #1534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d62807b
b8035d5
e0dfd71
191d739
a0af586
44695a3
03248f1
66275e8
96ac861
05f51b9
10112cf
ef7fc97
a8fa299
6f03b55
9a129a2
416c96f
295fac0
765dead
dc3815c
08ebccd
61d8ee1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,6 @@ import ( | |
|
||
"github.com/ava-labs/avalanchego/database" | ||
"github.com/ava-labs/avalanchego/database/prefixdb" | ||
"github.com/ava-labs/avalanchego/database/versiondb" | ||
"github.com/ava-labs/avalanchego/ids" | ||
"github.com/ava-labs/avalanchego/trace" | ||
"github.com/ava-labs/avalanchego/utils" | ||
|
@@ -29,8 +28,8 @@ import ( | |
) | ||
|
||
const ( | ||
RootPath = EmptyPath | ||
|
||
RootPath = EmptyPath | ||
evictionBatchSize = 100 | ||
// TODO: name better | ||
rebuildViewSizeFractionOfCacheSize = 50 | ||
minRebuildViewSizePerCommit = 1000 | ||
|
@@ -139,9 +138,7 @@ type merkleDB struct { | |
// Should be held before taking [db.lock] | ||
commitLock sync.RWMutex | ||
|
||
// versiondb that the other dbs are built on. | ||
// Allows the changes made to the snapshot and [nodeDB] to be atomic. | ||
nodeDB *versiondb.Database | ||
nodeDB database.Database | ||
|
||
// Stores data about the database's current state. | ||
metadataDB database.Database | ||
|
@@ -176,7 +173,7 @@ func newDatabase( | |
) (*merkleDB, error) { | ||
trieDB := &merkleDB{ | ||
metrics: metrics, | ||
nodeDB: versiondb.New(prefixdb.New(nodePrefix, db)), | ||
nodeDB: prefixdb.New(nodePrefix, db), | ||
metadataDB: prefixdb.New(metadataPrefix, db), | ||
history: newTrieHistory(config.HistoryLength), | ||
tracer: config.Tracer, | ||
|
@@ -265,8 +262,7 @@ func (db *merkleDB) rebuild(ctx context.Context) error { | |
return err | ||
} | ||
currentViewSize++ | ||
} | ||
if err := db.nodeDB.Delete(key); err != nil { | ||
} else if err := db.nodeDB.Delete(key); err != nil { | ||
return err | ||
} | ||
} | ||
|
@@ -354,10 +350,6 @@ func (db *merkleDB) Close() error { | |
return err | ||
} | ||
|
||
if err := db.nodeDB.Commit(); err != nil { | ||
return err | ||
} | ||
|
||
// Successfully wrote intermediate nodes. | ||
return db.metadataDB.Put(cleanShutdownKey, hadCleanShutdown) | ||
} | ||
|
@@ -749,23 +741,42 @@ func (db *merkleDB) NewIteratorWithStartAndPrefix(start, prefix []byte) database | |
// the movement of [node] from [db.nodeCache] to [db.nodeDB] is atomic. | ||
// As soon as [db.nodeCache] no longer has [node], [db.nodeDB] does. | ||
// Non-nil error is fatal -- causes [db] to close. | ||
func (db *merkleDB) onEviction(node *node) error { | ||
if node == nil || node.hasValue() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if it makes sense to keep this check as an early return so eviction of non-intermediary nodes remains a no-op and doesn't cause a batch write to disk. Not sure it really matters, but wanted to point this out. |
||
// only persist intermediary nodes | ||
func (db *merkleDB) onEviction(n *node) error { | ||
// the evicted node isn't an intermediary node, so skip writing. | ||
if n == nil || n.hasValue() { | ||
return nil | ||
} | ||
|
||
nodeBytes, err := node.marshal() | ||
if err != nil { | ||
db.onEvictionErr.Set(err) | ||
// Prevent reads/writes from/to [db.nodeDB] to avoid inconsistent state. | ||
_ = db.nodeDB.Close() | ||
// This is a fatal error. | ||
go db.Close() | ||
batch := db.nodeDB.NewBatch() | ||
if err := writeNodeToBatch(batch, n); err != nil { | ||
return err | ||
} | ||
|
||
if err := db.nodeDB.Put(node.key.Bytes(), nodeBytes); err != nil { | ||
// Evict the oldest [evictionBatchSize] nodes from the cache | ||
// and write them to disk. We write a batch of them, rather than | ||
// just [n], so that we don't immediately evict and write another | ||
// node, because each time this method is called we do a disk write. | ||
var err error | ||
for removedCount := 0; removedCount < evictionBatchSize; removedCount++ { | ||
_, n, exists := db.nodeCache.removeOldest() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't love this solution to batching the evictions, but it works. |
||
if !exists { | ||
// The cache is empty. | ||
break | ||
} | ||
if n == nil || n.hasValue() { | ||
// only persist intermediary nodes | ||
continue | ||
} | ||
// Note this must be = not := since we check | ||
// [err] outside the loop. | ||
if err = writeNodeToBatch(batch, n); err != nil { | ||
break | ||
} | ||
} | ||
if err == nil { | ||
err = batch.Write() | ||
} | ||
if err != nil { | ||
db.onEvictionErr.Set(err) | ||
_ = db.nodeDB.Close() | ||
go db.Close() | ||
|
@@ -774,6 +785,16 @@ func (db *merkleDB) onEviction(node *node) error { | |
return nil | ||
} | ||
|
||
// Writes [n] to [batch]. Assumes [n] is non-nil. | ||
func writeNodeToBatch(batch database.Batch, n *node) error { | ||
nodeBytes, err := n.marshal() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return batch.Put(n.key.Bytes(), nodeBytes) | ||
} | ||
|
||
// Put upserts the key/value pair into the db. | ||
func (db *merkleDB) Put(k, v []byte) error { | ||
return db.Insert(context.Background(), k, v) | ||
|
@@ -859,19 +880,13 @@ func (db *merkleDB) commitChanges(ctx context.Context, trieToCommit *trieView) e | |
return errNoNewRoot | ||
} | ||
|
||
// commit any outstanding cache evicted nodes. | ||
// Note that we do this here because below we may Abort | ||
// [db.nodeDB], which would cause us to lose these changes. | ||
if err := db.nodeDB.Commit(); err != nil { | ||
darioush marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return err | ||
} | ||
batch := db.nodeDB.NewBatch() | ||
|
||
_, nodesSpan := db.tracer.Start(ctx, "MerkleDB.commitChanges.writeNodes") | ||
for key, nodeChange := range changes.nodes { | ||
if nodeChange.after == nil { | ||
db.metrics.IOKeyWrite() | ||
if err := db.nodeDB.Delete(key.Bytes()); err != nil { | ||
db.nodeDB.Abort() | ||
if err := batch.Delete(key.Bytes()); err != nil { | ||
nodesSpan.End() | ||
return err | ||
} | ||
|
@@ -883,15 +898,7 @@ func (db *merkleDB) commitChanges(ctx context.Context, trieToCommit *trieView) e | |
// Otherwise, intermediary nodes are persisted on cache eviction or | ||
// shutdown. | ||
db.metrics.IOKeyWrite() | ||
nodeBytes, err := nodeChange.after.marshal() | ||
if err != nil { | ||
db.nodeDB.Abort() | ||
nodesSpan.End() | ||
return err | ||
} | ||
|
||
if err := db.nodeDB.Put(key.Bytes(), nodeBytes); err != nil { | ||
db.nodeDB.Abort() | ||
if err := writeNodeToBatch(batch, nodeChange.after); err != nil { | ||
nodesSpan.End() | ||
return err | ||
} | ||
|
@@ -900,10 +907,9 @@ func (db *merkleDB) commitChanges(ctx context.Context, trieToCommit *trieView) e | |
nodesSpan.End() | ||
|
||
_, commitSpan := db.tracer.Start(ctx, "MerkleDB.commitChanges.dbCommit") | ||
err := db.nodeDB.Commit() | ||
err := batch.Write() | ||
commitSpan.End() | ||
if err != nil { | ||
db.nodeDB.Abort() | ||
return err | ||
} | ||
|
||
|
@@ -1122,11 +1128,13 @@ func (db *merkleDB) initializeRootIfNeeded() (ids.ID, error) { | |
if err != nil { | ||
return ids.Empty, err | ||
} | ||
if err := db.nodeDB.Put(rootKey, rootBytes); err != nil { | ||
|
||
batch := db.nodeDB.NewBatch() | ||
if err := batch.Put(rootKey, rootBytes); err != nil { | ||
return ids.Empty, err | ||
} | ||
|
||
return db.root.id, db.nodeDB.Commit() | ||
return db.root.id, batch.Write() | ||
} | ||
|
||
// Returns a view of the trie as it was when it had root [rootID] for keys within range [start, end]. | ||
|
Uh oh!
There was an error while loading. Please reload this page.