Documentation ¶
Overview ¶
Package lock is the API for POSIX-style advisory regional file locks and BSD-style full file locks.
Callers needing to enforce these types of locks, like sys_fcntl, can call LockRegion and UnlockRegion on a thread-safe set of Locks. Locks are specific to a unique file (unique device/inode pair) and for this reason should not be shared between files.
A Lock has a set of holders identified by UniqueID. Normally this is the pid of the thread attempting to acquire the lock.
Since these are advisory locks, they do not need to be integrated into Reads/Writes and for this reason there is no way to *check* if a lock is held. One can only attempt to take a lock or unlock an existing lock.
A Lock in a set of Locks is typed: it is either a read lock with any number of readers and no writer, or a write lock with no readers.
As expected from POSIX, any attempt to acquire a write lock on a file region when there already exits a write lock held by a different uid will fail. Any attempt to acquire a write lock on a file region when there is more than one reader will fail. Any attempt to acquire a read lock on a file region when there is already a writer will fail.
In special cases, a read lock may be upgraded to a write lock and a write lock can be downgraded to a read lock. This can only happen if:
read lock upgrade to write lock: There can be only one reader and the reader must be the same as the requested write lock holder.
write lock downgrade to read lock: The writer must be the same as the requested read lock holder.
UnlockRegion always succeeds. If LockRegion fails the caller should normally interpret this as "try again later".
Index ¶
- Constants
- func LockzeroNodeSlice(slice []*Locknode)
- func LockzeroValueSlice(slice []Lock)
- type Lock
- type LockFlatSegment
- type LockGapIterator
- func (gap LockGapIterator) End() uint64
- func (gap LockGapIterator) IsEmpty() bool
- func (gap LockGapIterator) NextGap() LockGapIterator
- func (gap LockGapIterator) NextLargeEnoughGap(minSize uint64) LockGapIterator
- func (gap LockGapIterator) NextSegment() LockIterator
- func (gap LockGapIterator) Ok() bool
- func (gap LockGapIterator) PrevGap() LockGapIterator
- func (gap LockGapIterator) PrevLargeEnoughGap(minSize uint64) LockGapIterator
- func (gap LockGapIterator) PrevSegment() LockIterator
- func (gap LockGapIterator) Range() LockRange
- func (gap LockGapIterator) Start() uint64
- type LockIterator
- func (seg LockIterator) End() uint64
- func (seg LockIterator) NextGap() LockGapIterator
- func (seg LockIterator) NextNonEmpty() (LockIterator, LockGapIterator)
- func (seg LockIterator) NextSegment() LockIterator
- func (seg LockIterator) Ok() bool
- func (seg LockIterator) PrevGap() LockGapIterator
- func (seg LockIterator) PrevNonEmpty() (LockIterator, LockGapIterator)
- func (seg LockIterator) PrevSegment() LockIterator
- func (seg LockIterator) Range() LockRange
- func (seg LockIterator) SetEnd(end uint64)
- func (seg LockIterator) SetEndUnchecked(end uint64)
- func (seg LockIterator) SetRange(r LockRange)
- func (seg LockIterator) SetRangeUnchecked(r LockRange)
- func (seg LockIterator) SetStart(start uint64)
- func (seg LockIterator) SetStartUnchecked(start uint64)
- func (seg LockIterator) SetValue(val Lock)
- func (seg LockIterator) Start() uint64
- func (seg LockIterator) Value() Lock
- func (seg LockIterator) ValuePtr() *Lock
- type LockRange
- func (r LockRange) CanSplitAt(x uint64) bool
- func (r LockRange) Contains(x uint64) bool
- func (r LockRange) Intersect(r2 LockRange) LockRange
- func (r LockRange) IsSupersetOf(r2 LockRange) bool
- func (r LockRange) Length() uint64
- func (r LockRange) Overlaps(r2 LockRange) bool
- func (r *LockRange) StateFields() []string
- func (r *LockRange) StateLoad(ctx context.Context, stateSourceObject state.Source)
- func (r *LockRange) StateSave(stateSinkObject state.Sink)
- func (r *LockRange) StateTypeName() string
- func (r LockRange) WellFormed() bool
- type LockSet
- func (s *LockSet) ExportSlice() []LockFlatSegment
- func (s *LockSet) Find(key uint64) (LockIterator, LockGapIterator)
- func (s *LockSet) FindGap(key uint64) LockGapIterator
- func (s *LockSet) FindSegment(key uint64) LockIterator
- func (s *LockSet) FirstGap() LockGapIterator
- func (s *LockSet) FirstLargeEnoughGap(minSize uint64) LockGapIterator
- func (s *LockSet) FirstSegment() LockIterator
- func (s *LockSet) ImportSlice(fs []LockFlatSegment) error
- func (s *LockSet) Insert(gap LockGapIterator, r LockRange, val Lock) LockIterator
- func (s *LockSet) InsertRange(r LockRange, val Lock) LockIterator
- func (s *LockSet) InsertWithoutMerging(gap LockGapIterator, r LockRange, val Lock) LockIterator
- func (s *LockSet) InsertWithoutMergingRange(r LockRange, val Lock) LockIterator
- func (s *LockSet) InsertWithoutMergingUnchecked(gap LockGapIterator, r LockRange, val Lock) LockIterator
- func (s *LockSet) IsEmpty() bool
- func (s *LockSet) IsEmptyRange(r LockRange) bool
- func (s *LockSet) Isolate(seg LockIterator, r LockRange) LockIterator
- func (s *LockSet) LastGap() LockGapIterator
- func (s *LockSet) LastLargeEnoughGap(minSize uint64) LockGapIterator
- func (s *LockSet) LastSegment() LockIterator
- func (s *LockSet) LowerBoundGap(min uint64) LockGapIterator
- func (s *LockSet) LowerBoundLargeEnoughGap(min, minSize uint64) LockGapIterator
- func (s *LockSet) LowerBoundSegment(min uint64) LockIterator
- func (s *LockSet) LowerBoundSegmentSplitBefore(min uint64) LockIterator
- func (s *LockSet) Merge(first, second LockIterator) LockIterator
- func (s *LockSet) MergeAll()
- func (s *LockSet) MergeInsideRange(r LockRange)
- func (s *LockSet) MergeNext(seg LockIterator) LockIterator
- func (s *LockSet) MergeOutsideRange(r LockRange)
- func (s *LockSet) MergePrev(seg LockIterator) LockIterator
- func (s *LockSet) MergeUnchecked(first, second LockIterator) LockIterator
- func (s *LockSet) MutateFullRange(r LockRange, f func(seg LockIterator) bool)
- func (s *LockSet) MutateRange(r LockRange, f func(seg LockIterator) bool)
- func (s *LockSet) Remove(seg LockIterator) LockGapIterator
- func (s *LockSet) RemoveAll()
- func (s *LockSet) RemoveFullRange(r LockRange) LockGapIterator
- func (s *LockSet) RemoveFullRangeWith(r LockRange, f func(seg LockIterator)) LockGapIterator
- func (s *LockSet) RemoveRange(r LockRange) LockGapIterator
- func (s *LockSet) RemoveRangeWith(r LockRange, f func(seg LockIterator)) LockGapIterator
- func (s *LockSet) Span() uint64
- func (s *LockSet) SpanRange(r LockRange) uint64
- func (s *LockSet) Split(seg LockIterator, split uint64) (LockIterator, LockIterator)
- func (s *LockSet) SplitAfter(seg LockIterator, end uint64) LockIterator
- func (s *LockSet) SplitBefore(seg LockIterator, start uint64) LockIterator
- func (s *LockSet) SplitUnchecked(seg LockIterator, split uint64) (LockIterator, LockIterator)
- func (s *LockSet) StateFields() []string
- func (s *LockSet) StateLoad(ctx context.Context, stateSourceObject state.Source)
- func (s *LockSet) StateSave(stateSinkObject state.Sink)
- func (s *LockSet) StateTypeName() string
- func (s *LockSet) String() string
- func (s *LockSet) TryInsertRange(r LockRange, val Lock) LockIterator
- func (s *LockSet) TryInsertWithoutMergingRange(r LockRange, val Lock) LockIterator
- func (s *LockSet) Unisolate(seg LockIterator) LockIterator
- func (s *LockSet) UpperBoundGap(max uint64) LockGapIterator
- func (s *LockSet) UpperBoundLargeEnoughGap(max, minSize uint64) LockGapIterator
- func (s *LockSet) UpperBoundSegment(max uint64) LockIterator
- func (s *LockSet) UpperBoundSegmentSplitAfter(max uint64) LockIterator
- func (s *LockSet) VisitFullRange(r LockRange, f func(seg LockIterator) bool)
- func (s *LockSet) VisitRange(r LockRange, f func(seg LockIterator) bool)
- type LockType
- type LockdynamicGap
- type Locknode
- type Locks
- func (l *Locks) EventRegister(e *waiter.Entry) error
- func (l *Locks) EventUnregister(e *waiter.Entry)
- func (l *Locks) LockRegion(ctx context.Context, uid UniqueID, ownerPID int32, t LockType, r LockRange, ...) error
- func (l *Locks) Readiness(waiter.EventMask) waiter.EventMask
- func (l *Locks) StateFields() []string
- func (l *Locks) StateLoad(ctx context.Context, stateSourceObject state.Source)
- func (l *Locks) StateSave(stateSinkObject state.Sink)
- func (l *Locks) StateTypeName() string
- func (l *Locks) TestRegion(ctx context.Context, uid UniqueID, t LockType, r LockRange, ofd bool) linux.Flock
- func (l *Locks) UnlockRegion(uid UniqueID, r LockRange)
- type OwnerInfo
- type UniqueID
Constants ¶
const ( // minDegree is the minimum degree of an internal node in a Set B-tree. // // - Any non-root node has at least minDegree-1 segments. // // - Any non-root internal (non-leaf) node has at least minDegree children. // // - The root node may have fewer than minDegree-1 segments, but it may // only have 0 segments if the tree is empty. // // Our implementation requires minDegree >= 3. Higher values of minDegree // usually improve performance, but increase memory usage for small sets. LockminDegree = 3 LockmaxDegree = 2 * LockminDegree )
const LockEOF = math.MaxInt64
LockEOF is the maximal possible end of a regional file lock.
A BSD-style full file lock can be represented as a regional file lock from offset 0 to LockEOF.
const LocktrackGaps = 0
trackGaps is an optional parameter.
If trackGaps is 1, the Set will track maximum gap size recursively, enabling the GapIterator.{Prev,Next}LargeEnoughGap functions. In this case, Key must be an unsigned integer.
trackGaps must be 0 or 1.
Variables ¶
This section is empty.
Functions ¶
func LockzeroNodeSlice ¶
func LockzeroNodeSlice(slice []*Locknode)
func LockzeroValueSlice ¶
func LockzeroValueSlice(slice []Lock)
Types ¶
type Lock ¶
type Lock struct { // Readers are the set of read lock holders identified by UniqueID. // If len(Readers) > 0 then Writer must be nil. Readers map[UniqueID]OwnerInfo // Writer holds the writer unique ID. It's nil if there are no writers. Writer UniqueID // WriterInfo describes the writer. It is only meaningful if Writer != nil. WriterInfo OwnerInfo }
Lock is a regional file lock. It consists of either a single writer or a set of readers.
A Lock may be upgraded from a read lock to a write lock only if there is a single reader and that reader has the same uid as the write lock.
A Lock may be downgraded from a write lock to a read lock only if the write lock's uid is the same as the read lock.
Accesses to Lock are synchronized through the Locks object to which it belongs.
+stateify savable
func (*Lock) StateFields ¶
func (*Lock) StateTypeName ¶
type LockFlatSegment ¶
FlatSegment represents a segment as a single object. FlatSegment is used as an intermediate representation for save/restore and tests.
+stateify savable
func (*LockFlatSegment) StateFields ¶
func (l *LockFlatSegment) StateFields() []string
func (*LockFlatSegment) StateLoad ¶
func (l *LockFlatSegment) StateLoad(ctx context.Context, stateSourceObject state.Source)
+checklocksignore
func (*LockFlatSegment) StateSave ¶
func (l *LockFlatSegment) StateSave(stateSinkObject state.Sink)
+checklocksignore
func (*LockFlatSegment) StateTypeName ¶
func (l *LockFlatSegment) StateTypeName() string
type LockGapIterator ¶
type LockGapIterator struct {
// contains filtered or unexported fields
}
A GapIterator is conceptually one of:
A pointer to a position between two segments, before the first segment, or after the last segment in a set, called a *gap*; or
A terminal iterator, which is a sentinel indicating that the end of iteration has been reached.
Note that the gap between two adjacent segments exists (iterators to it are non-terminal), but has a length of zero. GapIterator.IsEmpty returns true for such gaps. An empty set contains a single gap, spanning the entire range of the set's keys.
GapIterators are copyable values and are meaningfully equality-comparable. The zero value of GapIterator is a terminal iterator.
Unless otherwise specified, any mutation of a set invalidates all existing iterators into the set.
func (LockGapIterator) End ¶
func (gap LockGapIterator) End() uint64
End is equivalent to Range().End, but should be preferred if only the end of the range is needed.
func (LockGapIterator) IsEmpty ¶
func (gap LockGapIterator) IsEmpty() bool
IsEmpty returns true if the iterated gap is empty (that is, the "gap" is between two adjacent segments.)
func (LockGapIterator) NextGap ¶
func (gap LockGapIterator) NextGap() LockGapIterator
NextGap returns the iterated gap's successor. If no such gap exists, NextGap returns a terminal iterator.
func (LockGapIterator) NextLargeEnoughGap ¶
func (gap LockGapIterator) NextLargeEnoughGap(minSize uint64) LockGapIterator
NextLargeEnoughGap returns the iterated gap's first next gap with larger length than minSize. If not found, return a terminal gap iterator (does NOT include this gap itself).
Precondition: trackGaps must be 1.
func (LockGapIterator) NextSegment ¶
func (gap LockGapIterator) NextSegment() LockIterator
NextSegment returns the segment immediately after the iterated gap. If no such segment exists, NextSegment returns a terminal iterator.
func (LockGapIterator) Ok ¶
func (gap LockGapIterator) Ok() bool
Ok returns true if the iterator is not terminal. All other methods are only valid for non-terminal iterators.
func (LockGapIterator) PrevGap ¶
func (gap LockGapIterator) PrevGap() LockGapIterator
PrevGap returns the iterated gap's predecessor. If no such gap exists, PrevGap returns a terminal iterator.
func (LockGapIterator) PrevLargeEnoughGap ¶
func (gap LockGapIterator) PrevLargeEnoughGap(minSize uint64) LockGapIterator
PrevLargeEnoughGap returns the iterated gap's first prev gap with larger or equal length than minSize. If not found, return a terminal gap iterator (does NOT include this gap itself).
Precondition: trackGaps must be 1.
func (LockGapIterator) PrevSegment ¶
func (gap LockGapIterator) PrevSegment() LockIterator
PrevSegment returns the segment immediately before the iterated gap. If no such segment exists, PrevSegment returns a terminal iterator.
func (LockGapIterator) Range ¶
func (gap LockGapIterator) Range() LockRange
Range returns the range spanned by the iterated gap.
func (LockGapIterator) Start ¶
func (gap LockGapIterator) Start() uint64
Start is equivalent to Range().Start, but should be preferred if only the start of the range is needed.
type LockIterator ¶
type LockIterator struct {
// contains filtered or unexported fields
}
A Iterator is conceptually one of:
A pointer to a segment in a set; or
A terminal iterator, which is a sentinel indicating that the end of iteration has been reached.
Iterators are copyable values and are meaningfully equality-comparable. The zero value of Iterator is a terminal iterator.
Unless otherwise specified, any mutation of a set invalidates all existing iterators into the set.
func LocksegmentAfterPosition ¶
func LocksegmentAfterPosition(n *Locknode, i int) LockIterator
segmentAfterPosition returns the successor segment of the position given by n.children[i], which may or may not contain a child. If no such segment exists, segmentAfterPosition returns a terminal iterator.
func LocksegmentBeforePosition ¶
func LocksegmentBeforePosition(n *Locknode, i int) LockIterator
segmentBeforePosition returns the predecessor segment of the position given by n.children[i], which may or may not contain a child. If no such segment exists, segmentBeforePosition returns a terminal iterator.
func (LockIterator) End ¶
func (seg LockIterator) End() uint64
End is equivalent to Range().End, but should be preferred if only the end of the range is needed.
func (LockIterator) NextGap ¶
func (seg LockIterator) NextGap() LockGapIterator
NextGap returns the gap immediately after the iterated segment.
func (LockIterator) NextNonEmpty ¶
func (seg LockIterator) NextNonEmpty() (LockIterator, LockGapIterator)
NextNonEmpty returns the iterated segment's successor if it is adjacent, or the gap after the iterated segment otherwise. If seg.End() == Functions.MaxKey(), NextNonEmpty will return two terminal iterators. Otherwise, exactly one of the iterators returned by NextNonEmpty will be non-terminal.
func (LockIterator) NextSegment ¶
func (seg LockIterator) NextSegment() LockIterator
NextSegment returns the iterated segment's successor. If there is no succeeding segment, NextSegment returns a terminal iterator.
func (LockIterator) Ok ¶
func (seg LockIterator) Ok() bool
Ok returns true if the iterator is not terminal. All other methods are only valid for non-terminal iterators.
func (LockIterator) PrevGap ¶
func (seg LockIterator) PrevGap() LockGapIterator
PrevGap returns the gap immediately before the iterated segment.
func (LockIterator) PrevNonEmpty ¶
func (seg LockIterator) PrevNonEmpty() (LockIterator, LockGapIterator)
PrevNonEmpty returns the iterated segment's predecessor if it is adjacent, or the gap before the iterated segment otherwise. If seg.Start() == Functions.MinKey(), PrevNonEmpty will return two terminal iterators. Otherwise, exactly one of the iterators returned by PrevNonEmpty will be non-terminal.
func (LockIterator) PrevSegment ¶
func (seg LockIterator) PrevSegment() LockIterator
PrevSegment returns the iterated segment's predecessor. If there is no preceding segment, PrevSegment returns a terminal iterator.
func (LockIterator) Range ¶
func (seg LockIterator) Range() LockRange
Range returns the iterated segment's range key.
func (LockIterator) SetEnd ¶
func (seg LockIterator) SetEnd(end uint64)
SetEnd mutates the iterated segment's end. If the new end value would cause the iterated segment to overlap another segment, or would result in an invalid range, SetEnd panics. This operation does not invalidate any iterators.
func (LockIterator) SetEndUnchecked ¶
func (seg LockIterator) SetEndUnchecked(end uint64)
SetEndUnchecked mutates the iterated segment's end. This operation does not invalidate any iterators.
Preconditions: The new end must be valid:
- end > seg.Start().
- If seg.NextSegment().Ok(), then end <= seg.NextSegment().Start().
func (LockIterator) SetRange ¶
func (seg LockIterator) SetRange(r LockRange)
SetRange mutates the iterated segment's range key. If the new range would cause the iterated segment to overlap another segment, or if the new range is invalid, SetRange panics. This operation does not invalidate any iterators.
func (LockIterator) SetRangeUnchecked ¶
func (seg LockIterator) SetRangeUnchecked(r LockRange)
SetRangeUnchecked mutates the iterated segment's range key. This operation does not invalidate any iterators.
Preconditions: - r.Length() > 0. - The new range must not overlap an existing one:
- If seg.NextSegment().Ok(), then r.end <= seg.NextSegment().Start().
- If seg.PrevSegment().Ok(), then r.start >= seg.PrevSegment().End().
func (LockIterator) SetStart ¶
func (seg LockIterator) SetStart(start uint64)
SetStart mutates the iterated segment's start. If the new start value would cause the iterated segment to overlap another segment, or would result in an invalid range, SetStart panics. This operation does not invalidate any iterators.
func (LockIterator) SetStartUnchecked ¶
func (seg LockIterator) SetStartUnchecked(start uint64)
SetStartUnchecked mutates the iterated segment's start. This operation does not invalidate any iterators.
Preconditions: The new start must be valid:
- start < seg.End()
- If seg.PrevSegment().Ok(), then start >= seg.PrevSegment().End().
func (LockIterator) SetValue ¶
func (seg LockIterator) SetValue(val Lock)
SetValue mutates the iterated segment's value. This operation does not invalidate any iterators.
func (LockIterator) Start ¶
func (seg LockIterator) Start() uint64
Start is equivalent to Range().Start, but should be preferred if only the start of the range is needed.
func (LockIterator) Value ¶
func (seg LockIterator) Value() Lock
Value returns a copy of the iterated segment's value.
func (LockIterator) ValuePtr ¶
func (seg LockIterator) ValuePtr() *Lock
ValuePtr returns a pointer to the iterated segment's value. The pointer is invalidated if the iterator is invalidated. This operation does not invalidate any iterators.
type LockRange ¶
type LockRange struct { // Start is the inclusive start of the range. Start uint64 // End is the exclusive end of the range. End uint64 }
A Range represents a contiguous range of T.
+stateify savable
func ComputeRange ¶
ComputeRange takes a positive file offset and computes the start of a LockRange using start (relative to offset) and the end of the LockRange using length. The values of start and length may be negative but the resulting LockRange must preserve that LockRange.Start < LockRange.End and LockRange.Start > 0.
func (LockRange) CanSplitAt ¶
CanSplitAt returns true if it is legal to split a segment spanning the range r at x; that is, splitting at x would produce two ranges, both of which have non-zero length.
func (LockRange) Intersect ¶
Intersect returns a range consisting of the intersection between r and r2. If r and r2 do not overlap, Intersect returns a range with unspecified bounds, but for which Length() == 0.
func (LockRange) IsSupersetOf ¶
IsSupersetOf returns true if r is a superset of r2; that is, the range r2 is contained within r.
func (*LockRange) StateFields ¶
func (*LockRange) StateTypeName ¶
func (LockRange) WellFormed ¶
WellFormed returns true if r.Start <= r.End. All other methods on a Range require that the Range is well-formed.
type LockSet ¶
type LockSet struct {
// contains filtered or unexported fields
}
A Set is a mapping of segments with non-overlapping Range keys. The zero value for a Set is an empty set. Set values are not safely movable nor copyable. Set is thread-compatible.
+stateify savable
func (*LockSet) ExportSlice ¶
func (s *LockSet) ExportSlice() []LockFlatSegment
ExportSlice returns a copy of all segments in the given set, in ascending key order.
func (*LockSet) Find ¶
func (s *LockSet) Find(key uint64) (LockIterator, LockGapIterator)
Find returns the segment or gap whose range contains the given key. If a segment is found, the returned Iterator is non-terminal and the returned GapIterator is terminal. Otherwise, the returned Iterator is terminal and the returned GapIterator is non-terminal.
func (*LockSet) FindGap ¶
func (s *LockSet) FindGap(key uint64) LockGapIterator
FindGap returns the gap containing the given key. If no such gap exists (i.e. the set contains a segment containing that key), FindGap returns a terminal iterator.
func (*LockSet) FindSegment ¶
func (s *LockSet) FindSegment(key uint64) LockIterator
FindSegment returns the segment whose range contains the given key. If no such segment exists, FindSegment returns a terminal iterator.
func (*LockSet) FirstGap ¶
func (s *LockSet) FirstGap() LockGapIterator
FirstGap returns the first gap in the set.
func (*LockSet) FirstLargeEnoughGap ¶
func (s *LockSet) FirstLargeEnoughGap(minSize uint64) LockGapIterator
FirstLargeEnoughGap returns the first gap in the set with at least the given length. If no such gap exists, FirstLargeEnoughGap returns a terminal iterator.
Precondition: trackGaps must be 1.
func (*LockSet) FirstSegment ¶
func (s *LockSet) FirstSegment() LockIterator
FirstSegment returns the first segment in the set. If the set is empty, FirstSegment returns a terminal iterator.
func (*LockSet) ImportSlice ¶
func (s *LockSet) ImportSlice(fs []LockFlatSegment) error
ImportSlice initializes the given set from the given slice.
Preconditions:
- s must be empty.
- fs must represent a valid set (the segments in fs must have valid lengths that do not overlap).
- The segments in fs must be sorted in ascending key order.
func (*LockSet) Insert ¶
func (s *LockSet) Insert(gap LockGapIterator, r LockRange, val Lock) LockIterator
Insert inserts the given segment into the given gap. If the new segment can be merged with adjacent segments, Insert will do so. Insert returns an iterator to the segment containing the inserted value (which may have been merged with other values). All existing iterators (including gap, but not including the returned iterator) are invalidated.
If the gap cannot accommodate the segment, or if r is invalid, Insert panics.
Insert is semantically equivalent to a InsertWithoutMerging followed by a Merge, but may be more efficient. Note that there is no unchecked variant of Insert since Insert must retrieve and inspect gap's predecessor and successor segments regardless.
func (*LockSet) InsertRange ¶
func (s *LockSet) InsertRange(r LockRange, val Lock) LockIterator
InsertRange inserts the given segment into the set. If the new segment can be merged with adjacent segments, InsertRange will do so. InsertRange returns an iterator to the segment containing the inserted value (which may have been merged with other values). All existing iterators (excluding the returned iterator) are invalidated.
If the new segment would overlap an existing segment, or if r is invalid, InsertRange panics.
InsertRange searches the set to find the gap to insert into. If the caller already has the appropriate GapIterator, or if the caller needs to do additional work between finding the gap and insertion, use Insert instead.
func (*LockSet) InsertWithoutMerging ¶
func (s *LockSet) InsertWithoutMerging(gap LockGapIterator, r LockRange, val Lock) LockIterator
InsertWithoutMerging inserts the given segment into the given gap and returns an iterator to the inserted segment. All existing iterators (including gap, but not including the returned iterator) are invalidated.
If the gap cannot accommodate the segment, or if r is invalid, InsertWithoutMerging panics.
func (*LockSet) InsertWithoutMergingRange ¶
func (s *LockSet) InsertWithoutMergingRange(r LockRange, val Lock) LockIterator
InsertWithoutMergingRange inserts the given segment into the set and returns an iterator to the inserted segment. All existing iterators (excluding the returned iterator) are invalidated.
If the new segment would overlap an existing segment, or if r is invalid, InsertWithoutMergingRange panics.
InsertWithoutMergingRange searches the set to find the gap to insert into. If the caller already has the appropriate GapIterator, or if the caller needs to do additional work between finding the gap and insertion, use InsertWithoutMerging instead.
func (*LockSet) InsertWithoutMergingUnchecked ¶
func (s *LockSet) InsertWithoutMergingUnchecked(gap LockGapIterator, r LockRange, val Lock) LockIterator
InsertWithoutMergingUnchecked inserts the given segment into the given gap and returns an iterator to the inserted segment. All existing iterators (including gap, but not including the returned iterator) are invalidated.
Preconditions:
- r.Start >= gap.Start().
- r.End <= gap.End().
func (*LockSet) IsEmptyRange ¶
IsEmptyRange returns true iff no segments in the set overlap the given range. This is semantically equivalent to s.SpanRange(r) == 0, but may be more efficient.
func (*LockSet) Isolate ¶
func (s *LockSet) Isolate(seg LockIterator, r LockRange) LockIterator
Isolate ensures that the given segment's range is a subset of r by splitting at r.Start and r.End if necessary, and returns an updated iterator to the bounded segment. All existing iterators (including seg, but not including the returned iterators) are invalidated.
Isolate is usually used when mutating part of a single segment, or when mutating segments in a range where the first segment is not necessarily split, making use of SplitBefore/SplitAfter complex.
Preconditions: seg.Range().Overlaps(r).
func (*LockSet) LastGap ¶
func (s *LockSet) LastGap() LockGapIterator
LastGap returns the last gap in the set.
func (*LockSet) LastLargeEnoughGap ¶
func (s *LockSet) LastLargeEnoughGap(minSize uint64) LockGapIterator
LastLargeEnoughGap returns the last gap in the set with at least the given length. If no such gap exists, LastLargeEnoughGap returns a terminal iterator.
Precondition: trackGaps must be 1.
func (*LockSet) LastSegment ¶
func (s *LockSet) LastSegment() LockIterator
LastSegment returns the last segment in the set. If the set is empty, LastSegment returns a terminal iterator.
func (*LockSet) LowerBoundGap ¶
func (s *LockSet) LowerBoundGap(min uint64) LockGapIterator
LowerBoundGap returns the gap with the lowest range that is greater than or equal to min.
func (*LockSet) LowerBoundLargeEnoughGap ¶
func (s *LockSet) LowerBoundLargeEnoughGap(min, minSize uint64) LockGapIterator
LowerBoundLargeEnoughGap returns the first gap in the set with at least the given length and whose range contains a key greater than or equal to min. If no such gap exists, LowerBoundLargeEnoughGap returns a terminal iterator.
Precondition: trackGaps must be 1.
func (*LockSet) LowerBoundSegment ¶
func (s *LockSet) LowerBoundSegment(min uint64) LockIterator
LowerBoundSegment returns the segment with the lowest range that contains a key greater than or equal to min. If no such segment exists, LowerBoundSegment returns a terminal iterator.
func (*LockSet) LowerBoundSegmentSplitBefore ¶
func (s *LockSet) LowerBoundSegmentSplitBefore(min uint64) LockIterator
LowerBoundSegmentSplitBefore combines LowerBoundSegment and SplitBefore.
LowerBoundSegmentSplitBefore is usually used when mutating segments in a range while iterating them in order of increasing keys. In such cases, LowerBoundSegmentSplitBefore provides an iterator to the first segment to be mutated, suitable as the initial value for a loop variable.
func (*LockSet) Merge ¶
func (s *LockSet) Merge(first, second LockIterator) LockIterator
Merge attempts to merge two neighboring segments. If successful, Merge returns an iterator to the merged segment, and all existing iterators are invalidated. Otherwise, Merge returns a terminal iterator.
If first is not the predecessor of second, Merge panics.
func (*LockSet) MergeAll ¶
func (s *LockSet) MergeAll()
MergeAll merges all mergeable adjacent segments in the set. All existing iterators are invalidated.
func (*LockSet) MergeInsideRange ¶
MergeInsideRange attempts to merge all adjacent segments that contain a key in the specific range. All existing iterators are invalidated.
MergeInsideRange only makes sense after mutating the set in a way that may change the mergeability of modified segments; callers should prefer to use MergePrev or MergeNext during the mutating loop instead (depending on the direction of iteration), in order to avoid a redundant search.
func (*LockSet) MergeNext ¶
func (s *LockSet) MergeNext(seg LockIterator) LockIterator
MergeNext attempts to merge the given segment with its successor if possible, and returns an updated iterator to the extended segment. All existing iterators (including seg, but not including the returned iterator) are invalidated.
MergeNext is usually used when mutating segments while iterating them in order of decreasing keys, to attempt merging of each mutated segment with its previously-mutated successor. In such cases, merging a mutated segment with its unmutated predecessor would incorrectly cause the latter to be skipped.
func (*LockSet) MergeOutsideRange ¶
MergeOutsideRange attempts to merge the segment containing r.Start with its predecessor, and the segment containing r.End-1 with its successor.
MergeOutsideRange only makes sense after mutating the set in a way that may change the mergeability of modified segments; callers should prefer to use MergePrev or MergeNext during the mutating loop instead (depending on the direction of iteration), in order to avoid two redundant searches.
func (*LockSet) MergePrev ¶
func (s *LockSet) MergePrev(seg LockIterator) LockIterator
MergePrev attempts to merge the given segment with its predecessor if possible, and returns an updated iterator to the extended segment. All existing iterators (including seg, but not including the returned iterator) are invalidated.
MergePrev is usually used when mutating segments while iterating them in order of increasing keys, to attempt merging of each mutated segment with its previously-mutated predecessor. In such cases, merging a mutated segment with its unmutated successor would incorrectly cause the latter to be skipped.
func (*LockSet) MergeUnchecked ¶
func (s *LockSet) MergeUnchecked(first, second LockIterator) LockIterator
MergeUnchecked attempts to merge two neighboring segments. If successful, MergeUnchecked returns an iterator to the merged segment, and all existing iterators are invalidated. Otherwise, MergeUnchecked returns a terminal iterator.
Precondition: first is the predecessor of second: first.NextSegment() == second, first == second.PrevSegment().
func (*LockSet) MutateFullRange ¶
func (s *LockSet) MutateFullRange(r LockRange, f func(seg LockIterator) bool)
MutateFullRange is equivalent to MutateRange, except that if any key in r that is visited before f returns false does not correspond to a segment, MutateFullRange panics.
func (*LockSet) MutateRange ¶
func (s *LockSet) MutateRange(r LockRange, f func(seg LockIterator) bool)
MutateRange applies the function f to all segments intersecting the range r, in order of ascending keys. Segments that lie partially outside r are split before f is called, such that f only observes segments entirely within r. Iterated segments are merged again after f is called. Non-empty gaps between segments are skipped. If a call to f returns false, MutateRange stops iteration immediately.
MutateRange invalidates all existing iterators.
N.B. f must not invalidate iterators into s.
func (*LockSet) Remove ¶
func (s *LockSet) Remove(seg LockIterator) LockGapIterator
Remove removes the given segment and returns an iterator to the vacated gap. All existing iterators (including seg, but not including the returned iterator) are invalidated.
func (*LockSet) RemoveAll ¶
func (s *LockSet) RemoveAll()
RemoveAll removes all segments from the set. All existing iterators are invalidated.
func (*LockSet) RemoveFullRange ¶
func (s *LockSet) RemoveFullRange(r LockRange) LockGapIterator
RemoveFullRange is equivalent to RemoveRange, except that if any key in the given range does not correspond to a segment, RemoveFullRange panics.
func (*LockSet) RemoveFullRangeWith ¶
func (s *LockSet) RemoveFullRangeWith(r LockRange, f func(seg LockIterator)) LockGapIterator
RemoveFullRangeWith is equivalent to RemoveRangeWith, except that if any key in the given range does not correspond to a segment, RemoveFullRangeWith panics.
func (*LockSet) RemoveRange ¶
func (s *LockSet) RemoveRange(r LockRange) LockGapIterator
RemoveRange removes all segments in the given range. An iterator to the newly formed gap is returned, and all existing iterators are invalidated.
RemoveRange searches the set to find segments to remove. If the caller already has an iterator to either end of the range of segments to remove, or if the caller needs to do additional work before removing each segment, iterate segments and call Remove in a loop instead.
func (*LockSet) RemoveRangeWith ¶
func (s *LockSet) RemoveRangeWith(r LockRange, f func(seg LockIterator)) LockGapIterator
RemoveRangeWith removes all segments in the given range. An iterator to the newly formed gap is returned, and all existing iterators are invalidated.
The function f is applied to each segment immediately before it is removed, in order of ascending keys. Segments that lie partially outside r are split before f is called, such that f only observes segments entirely within r. Non-empty gaps between segments are skipped.
RemoveRangeWith searches the set to find segments to remove. If the caller already has an iterator to either end of the range of segments to remove, or if the caller needs to do additional work before removing each segment, iterate segments and call Remove in a loop instead.
N.B. f must not invalidate iterators into s.
func (*LockSet) SpanRange ¶
SpanRange returns the total size of the intersection of segments in the set with the given range.
func (*LockSet) Split ¶
func (s *LockSet) Split(seg LockIterator, split uint64) (LockIterator, LockIterator)
Split splits the given segment at the given key and returns iterators to the two resulting segments. All existing iterators (including seg, but not including the returned iterators) are invalidated.
If the segment cannot be split at split (because split is at the start or end of the segment's range, so splitting would produce a segment with zero length, or because split falls outside the segment's range altogether), Split panics.
func (*LockSet) SplitAfter ¶
func (s *LockSet) SplitAfter(seg LockIterator, end uint64) LockIterator
SplitAfter ensures that the given segment's end is at most end by splitting at end if necessary, and returns an updated iterator to the bounded segment. All existing iterators (including seg, but not including the returned iterator) are invalidated.
SplitAfter is usually used when mutating segments in a range. In such cases, when iterating segments in order of increasing keys, each iterated segment may extend beyond the end of the range to be mutated, and needs to be SplitAfter to ensure that only the part of the segment within the range is mutated. When iterating segments in order of decreasing keys, SplitBefore and SplitAfter exchange roles; i.e. SplitBefore needs to be invoked on each segment, while SplitAfter only needs to be invoked on the first.
Preconditions: seg.Start() < end.
func (*LockSet) SplitBefore ¶
func (s *LockSet) SplitBefore(seg LockIterator, start uint64) LockIterator
SplitBefore ensures that the given segment's start is at least start by splitting at start if necessary, and returns an updated iterator to the bounded segment. All existing iterators (including seg, but not including the returned iterator) are invalidated.
SplitBefore is usually when mutating segments in a range. In such cases, when iterating segments in order of increasing keys, the first segment may extend beyond the start of the range to be mutated, and needs to be SplitBefore to ensure that only the part of the segment within the range is mutated. When iterating segments in order of decreasing keys, SplitBefore and SplitAfter; i.e. SplitBefore needs to be invoked on each segment, while SplitAfter only needs to be invoked on the first.
Preconditions: start < seg.End().
func (*LockSet) SplitUnchecked ¶
func (s *LockSet) SplitUnchecked(seg LockIterator, split uint64) (LockIterator, LockIterator)
SplitUnchecked splits the given segment at the given key and returns iterators to the two resulting segments. All existing iterators (including seg, but not including the returned iterators) are invalidated.
Preconditions: seg.Start() < key < seg.End().
func (*LockSet) StateFields ¶
func (*LockSet) StateTypeName ¶
func (*LockSet) TryInsertRange ¶
func (s *LockSet) TryInsertRange(r LockRange, val Lock) LockIterator
TryInsertRange attempts to insert the given segment into the set. If the new segment can be merged with adjacent segments, TryInsertRange will do so. TryInsertRange returns an iterator to the segment containing the inserted value (which may have been merged with other values). All existing iterators (excluding the returned iterator) are invalidated.
If the new segment would overlap an existing segment, TryInsertRange does nothing and returns a terminal iterator.
TryInsertRange searches the set to find the gap to insert into. If the caller already has the appropriate GapIterator, or if the caller needs to do additional work between finding the gap and insertion, use Insert instead.
func (*LockSet) TryInsertWithoutMergingRange ¶
func (s *LockSet) TryInsertWithoutMergingRange(r LockRange, val Lock) LockIterator
TryInsertWithoutMergingRange attempts to insert the given segment into the set. If successful, it returns an iterator to the inserted segment; all existing iterators (excluding the returned iterator) are invalidated. If the new segment would overlap an existing segment, TryInsertWithoutMergingRange does nothing and returns a terminal iterator.
TryInsertWithoutMergingRange searches the set to find the gap to insert into. If the caller already has the appropriate GapIterator, or if the caller needs to do additional work between finding the gap and insertion, use InsertWithoutMerging instead.
func (*LockSet) Unisolate ¶
func (s *LockSet) Unisolate(seg LockIterator) LockIterator
Unisolate attempts to merge the given segment with its predecessor and successor if possible, and returns an updated iterator to the extended segment. All existing iterators (including seg, but not including the returned iterator) are invalidated.
Unisolate is usually used in conjunction with Isolate when mutating part of a single segment in a way that may affect its mergeability. For the reasons described by MergePrev and MergeNext, it is usually incorrect to use the return value of Unisolate in a loop variable.
func (*LockSet) UpperBoundGap ¶
func (s *LockSet) UpperBoundGap(max uint64) LockGapIterator
UpperBoundGap returns the gap with the highest range that is less than or equal to max.
func (*LockSet) UpperBoundLargeEnoughGap ¶
func (s *LockSet) UpperBoundLargeEnoughGap(max, minSize uint64) LockGapIterator
UpperBoundLargeEnoughGap returns the last gap in the set with at least the given length and whose range contains a key less than or equal to max. If no such gap exists, UpperBoundLargeEnoughGap returns a terminal iterator.
Precondition: trackGaps must be 1.
func (*LockSet) UpperBoundSegment ¶
func (s *LockSet) UpperBoundSegment(max uint64) LockIterator
UpperBoundSegment returns the segment with the highest range that contains a key less than or equal to max. If no such segment exists, UpperBoundSegment returns a terminal iterator.
func (*LockSet) UpperBoundSegmentSplitAfter ¶
func (s *LockSet) UpperBoundSegmentSplitAfter(max uint64) LockIterator
UpperBoundSegmentSplitAfter combines UpperBoundSegment and SplitAfter.
UpperBoundSegmentSplitAfter is usually used when mutating segments in a range while iterating them in order of decreasing keys. In such cases, UpperBoundSegmentSplitAfter provides an iterator to the first segment to be mutated, suitable as the initial value for a loop variable.
func (*LockSet) VisitFullRange ¶
func (s *LockSet) VisitFullRange(r LockRange, f func(seg LockIterator) bool)
VisitFullRange is equivalent to VisitRange, except that if any key in r that is visited before f returns false does not correspond to a segment, VisitFullRange panics.
func (*LockSet) VisitRange ¶
func (s *LockSet) VisitRange(r LockRange, f func(seg LockIterator) bool)
VisitRange applies the function f to all segments intersecting the range r, in order of ascending keys. Segments will not be split, so f may be called on segments lying partially outside r. Non-empty gaps between segments are skipped. If a call to f returns false, VisitRange stops iteration immediately.
N.B. f must not invalidate iterators into s.
type LockType ¶
type LockType int
LockType is a type of regional file lock.
const ( // ReadLock describes a POSIX regional file lock to be taken // read only. There may be multiple of these locks on a single // file region as long as there is no writer lock on the same // region. ReadLock LockType = iota // WriteLock describes a POSIX regional file lock to be taken // write only. There may be only a single holder of this lock // and no read locks. WriteLock )
type LockdynamicGap ¶
type LockdynamicGap [LocktrackGaps]uint64
dynamicGap is a type that disappears if trackGaps is 0.
func (*LockdynamicGap) Get ¶
func (d *LockdynamicGap) Get() uint64
Get returns the value of the gap.
Precondition: trackGaps must be non-zero.
func (*LockdynamicGap) Set ¶
func (d *LockdynamicGap) Set(v uint64)
Set sets the value of the gap.
Precondition: trackGaps must be non-zero.
type Locknode ¶
type Locknode struct {
// contains filtered or unexported fields
}
+stateify savable
func (*Locknode) StateFields ¶
func (*Locknode) StateTypeName ¶
type Locks ¶
type Locks struct {
// contains filtered or unexported fields
}
Locks is a thread-safe wrapper around a LockSet.
+stateify savable
func (*Locks) EventRegister ¶
EventRegister implements waiter.Waitable.EventRegister.
func (*Locks) EventUnregister ¶
EventUnregister implements waiter.Waitable.EventUnregister.
func (*Locks) LockRegion ¶
func (l *Locks) LockRegion(ctx context.Context, uid UniqueID, ownerPID int32, t LockType, r LockRange, ofd bool, block bool) error
LockRegion attempts to acquire a typed lock for the uid on a region of a file. Returns nil if successful in locking the region, otherwise an appropriate error is returned.
func (*Locks) StateFields ¶
func (*Locks) StateTypeName ¶
func (*Locks) TestRegion ¶
func (l *Locks) TestRegion(ctx context.Context, uid UniqueID, t LockType, r LockRange, ofd bool) linux.Flock
TestRegion checks whether the lock holder identified by uid can hold a lock of type t on range r. It returns a Flock struct representing this information as the F_GETLK fcntl does.
Note that the PID returned in the flock structure is relative to the root PID namespace. It needs to be converted to the caller's PID namespace before returning to userspace.
func (*Locks) UnlockRegion ¶
UnlockRegion attempts to release a lock for the uid on a region of a file. This operation is always successful, even if there did not exist a lock on the requested region held by uid in the first place.
type OwnerInfo ¶
type OwnerInfo struct { // PID is the process ID of the lock owner. PID int32 // OFD is whether this is an open file descriptor lock. OFD bool }
OwnerInfo describes the owner of a lock.
+stateify savable