Documentation
¶
Overview ¶
Package reads implements chain read-handles.
These protect read results. The actual reads may still be disturbed, but the handle can be inspected at any time, to abort if needed. And the final result can inspect the read-handle, to determine if the combined reading result is valid.
Append-only writes to the state do not need any invalidation. And updates have parent-hash checks, and thus do not require any rewind-locking on the parent either.
But rewinds, replacements, etc. that do not append do need invalidation, to make sure other reads are not affected.
This approach was chosen over simpler global read-write ChainsDB locking for two main reasons: 1. Fine-grained invalidation: Only operations depending on rewound blocks are affected 2. Non-blocking reads: Rewinds don't block unrelated read operations
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Acquirer ¶
type Acquirer interface { // AcquireHandle creates a new read handle. // Once the handle is no longer used, it must be released with readHandle.Release, or memory leaks. AcquireHandle() Handle }
Acquirer creates read handles
type DerivedInvalidation ¶
type DerivedInvalidation struct {
Timestamp uint64
}
func (DerivedInvalidation) Apply ¶
func (s DerivedInvalidation) Apply(h invalidationTarget)
type Handle ¶
type Handle interface { // DependOnDerivedTime registers the given derived block timestamp as a dependency, // updating the current range if needed. DependOnDerivedTime(timestamp uint64) // DependOnSourceBlock registers the given derived block number as a dependency, // updating the current range if needed. DependOnSourceBlock(blockNum uint64) // Err is a convenience method to return a types.ErrInvalidatedRead whenever the read handle is not valid Err() error // IsValid inspects the dependencies we have seen so far, and the invalidations we have seen, // and determines if the reads thus far are still valid. // Once a Handle is invalid, it never becomes valid again. IsValid() bool // Release releases the read-handle: once released we no longer apply updates to the read handle. // rangeHandles must be released, otherwise they are tracked forever. Release() // contains filtered or unexported methods }
Handle represents a read handle, to detect chain rewinds during multi-operation reads.
type InvalidHandle ¶
type InvalidHandle struct{}
InvalidHandle is a test-util, to present a read-handle that is always invalid, to mock an inconsistency.
func (InvalidHandle) DependOnDerivedTime ¶
func (i InvalidHandle) DependOnDerivedTime(timestamp uint64)
func (InvalidHandle) DependOnSourceBlock ¶
func (i InvalidHandle) DependOnSourceBlock(blockNum uint64)
func (InvalidHandle) Err ¶
func (i InvalidHandle) Err() error
func (InvalidHandle) IsValid ¶
func (i InvalidHandle) IsValid() bool
func (InvalidHandle) Release ¶
func (i InvalidHandle) Release()
type InvalidationRule ¶
type InvalidationRule interface {
Apply(h invalidationTarget)
}
type InvalidationRules ¶
type InvalidationRules []InvalidationRule
func (InvalidationRules) Apply ¶
func (rules InvalidationRules) Apply(h invalidationTarget)
type Invalidator ¶
type Invalidator interface {
TryInvalidate(rule InvalidationRule) (release func(), err error)
}
Invalidator invalidates read handles
type NoopHandle ¶
type NoopHandle struct{}
NoopHandle implements Handle without offering actual protection. This can be used when access is known to be synchronous and safe.
func (NoopHandle) DependOnDerivedTime ¶
func (n NoopHandle) DependOnDerivedTime(timestamp uint64)
func (NoopHandle) DependOnSourceBlock ¶
func (n NoopHandle) DependOnSourceBlock(blockNum uint64)
func (NoopHandle) Err ¶
func (n NoopHandle) Err() error
func (NoopHandle) IsValid ¶
func (n NoopHandle) IsValid() bool
func (NoopHandle) Release ¶
func (n NoopHandle) Release()
type NoopRegistry ¶
type NoopRegistry struct{}
NoopRegistry implements Acquirer and Invalidator without offering actual protection. This can be used when access is known to be synchronous and safe.
func (NoopRegistry) AcquireHandle ¶
func (n NoopRegistry) AcquireHandle() Handle
func (NoopRegistry) TryInvalidate ¶
func (n NoopRegistry) TryInvalidate(rule InvalidationRule) (release func(), err error)
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry maintains a set of read handles (readHandle). Whenever the chain reorgs, the active handles are updated, to track what has been reorged. Any handles that have an overlapping usage and invalidation range are invalid and return an error.
func NewRegistry ¶
func (*Registry) AcquireHandle ¶
AcquireHandle creates a new read handle. Once the handle is no longer used, it must be released with readHandle.Release, or memory leaks.
func (*Registry) TryInvalidate ¶
func (r *Registry) TryInvalidate(rule InvalidationRule) (release func(), err error)
TryInvalidate invalidates all handles that depend on blocks with numbers >= blockNum. Any new read-handles will automatically be invalidated if they depend on blockNum or later. The invalidation of new reads (starting at the given number) will stop once it has been released by calling release.
type SourceInvalidation ¶
type SourceInvalidation struct {
Number uint64
}
func (SourceInvalidation) Apply ¶
func (s SourceInvalidation) Apply(h invalidationTarget)
type TestInvalidator ¶
type TestInvalidator struct { Invalidated bool InvalidatedDerivedTimestamp uint64 InvalidatedSourceNum uint64 }
func (*TestInvalidator) TryInvalidate ¶
func (t *TestInvalidator) TryInvalidate(rule InvalidationRule) (release func(), err error)