ava-labs / firewood

Compaction-Less Database Optimized for Efficiently Storing Recent Merkleized Blockchain State
https://ava-labs.github.io/firewood/
Other
117 stars 10 forks source link

Implement reparenting (depends on 701) #706

Closed rkuris closed 2 months ago

rkuris commented 2 months ago

In this diff, I added the arc_swap crate to allow for efficient committing of proposals. The reason to use this crate is that for a nested proposal, we need to traverse the parents. One of the parents might have just been committed, and so the list of modified nodes changes. These nodes are duplicated in the new member of ImmutableProposal so we don't need to use the general node cache to read them, but we could if the transaction has been committed.

Since it doesn't actually matter which we use (the ImmutableProposal or the Committed state) we can safely ArcSwap from one to the other during commit, avoiding any locking of the parent field. This is important since these proposals are in-memory and are immutable anyway.

To properly implement the parenting, NodeStore has to now use Arc<ImmutableProposal> as the kind since this Arc is also used as a NodeStoreParent and you could have multiple proposals pointing at the same parent.

The challenging part of this was constructing new ImmutableProposals since the parent is now in an Arc. Currently, the code creates an ImmutableProposal and allocates the nodes into a separate list, then construct a new ImmutableProposal once we have all the parts. There might be a better way to do this. One idea is a new NodeStore.kind, maybe PendingProposal, to use as an intermediate when the proposal is still mutating, but this seemed like more work.

Still TODO is to add tests at the revision manager layer; we only test the reparent function itself here.