cosmos-sdk/iavl/internal/node_pointer.go

46 lines
1.5 KiB
Go

package internal
import (
"fmt"
"sync/atomic"
)
// NodePointer is a pointer to a Node, which may be either in-memory, on-disk or both.
type NodePointer struct {
mem atomic.Pointer[MemNode]
// changeset *Changeset // commented to satisfy linter, will uncomment in a future PR when we wire it up
fileIdx uint32 // absolute index in file, 1-based, zero means we don't have an offset
id NodeID
}
// NewNodePointer creates a new NodePointer pointing to the given in-memory node.
func NewNodePointer(memNode *MemNode) *NodePointer {
n := &NodePointer{}
n.mem.Store(memNode)
return n
}
// Resolve resolves the NodePointer to a Node, loading from memory or disk as necessary
// as well as a Pin which MUST be unpinned after the caller is done using the node.
// Resolve will ALWAYS return a valid Pin even if there is an error. For clarity and
// consistency it is recommended to introduce a defer pin.Unpin() immediately after
// calling Resolve and BEFORE checking the error return value like this:
//
// node, pin, err := nodePointer.Resolve()
// defer pin.Unpin()
// if err != nil {
// // handle error
// }
func (p *NodePointer) Resolve() (Node, Pin, error) {
mem := p.mem.Load()
if mem != nil {
return mem, NoopPin{}, nil
}
return nil, NoopPin{}, fmt.Errorf("node not in memory and on-disk loading will be implemented in a future PR")
}
// String implements the fmt.Stringer interface.
func (p *NodePointer) String() string {
return fmt.Sprintf("NodePointer{id: %s, fileIdx: %d}", p.id.String(), p.fileIdx)
}