client-go/kv/keyflags.go

261 lines
9.4 KiB
Go

// Copyright 2021 TiKV Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// NOTE: The code in this file is based on code from the
// TiDB project, licensed under the Apache License v 2.0
//
// https://github.com/pingcap/tidb/tree/cc5e161ac06827589c4966674597c137cc9e809c/store/tikv/kv/keyflags.go
//
// Copyright 2021 PingCAP, Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package kv
// KeyFlags are metadata associated with key.
// Notice that the highest bit is used by red black tree, do not set flags on it.
type KeyFlags uint16
// FlagBytes is the byte size of type KeyFlags
const FlagBytes = 2
const (
flagPresumeKNE KeyFlags = 1 << iota
flagKeyLocked
flagNeedLocked
flagKeyLockedValExist
flagNeedCheckExists
flagPrewriteOnly
flagIgnoredIn2PC
flagReadable
flagNewlyInserted
// The following are assertion related flags.
// There are four choices of the two bits:
// * 0: Assertion is not set and can be set later.
// * flagAssertExists: We assert the key exists.
// * flagAssertNotExists: We assert the key doesn't exist.
// * flagAssertExists | flagAssertNotExists: Assertion cannot be made on this key (unknown).
// Once either (or both) of the two flags is set, we say assertion is set (`HasAssertionFlags` becomes true), and
// it's expected to be unchangeable within the current transaction.
flagAssertExist
flagAssertNotExist
// It marks the conflict check of the key is postponed to prewrite. This is only used in pessimistic transactions.
// When the key gets locked (and the existence is checked), the flag should be removed.
// It should only be applied to keys with PresumeNotExist, so that an in-place constraint check becomes
// (a conflict check + a constraint check) in prewrite.
flagNeedConstraintCheckInPrewrite
// A PresumeKNE that should not be unset. It's used by lazy uniqueness checks. So that PresumeKNE flags in previous
// statement should not be mistakenly unset.
// It's only set when a stmt that sets PresumeKNE finishes.
// It's only read together with PresumeKNE
// It doesn't have to be persistent, since the only place where it is used is in statement retry where it helps set
// the correct assert_not_exist option. The life of the flag begins after stmt which sets the PresumeKNE flag, and
// ends when the lock is acquired.
flagPreviousPresumeKNE
persistentFlags = flagKeyLocked | flagKeyLockedValExist | flagNeedConstraintCheckInPrewrite
)
// HasAssertExist returns whether the key need ensure exists in 2pc.
func (f KeyFlags) HasAssertExist() bool {
return f&flagAssertExist != 0 && f&flagAssertNotExist == 0
}
// HasAssertNotExist returns whether the key need ensure non-exists in 2pc.
func (f KeyFlags) HasAssertNotExist() bool {
return f&flagAssertNotExist != 0 && f&flagAssertExist == 0
}
// HasAssertUnknown returns whether the key is marked unable to do any assertion.
func (f KeyFlags) HasAssertUnknown() bool {
return f&flagAssertExist != 0 && f&flagAssertNotExist != 0
}
// HasAssertionFlags returns whether the key's assertion is set.
func (f KeyFlags) HasAssertionFlags() bool {
return f&flagAssertExist != 0 || f&flagAssertNotExist != 0
}
// HasPresumeKeyNotExists returns whether the associated key use lazy check.
func (f KeyFlags) HasPresumeKeyNotExists() bool {
return f&(flagPresumeKNE|flagPreviousPresumeKNE) != 0
}
// HasLocked returns whether the associated key has acquired pessimistic lock.
func (f KeyFlags) HasLocked() bool {
return f&flagKeyLocked != 0
}
// HasNeedLocked return whether the key needed to be locked
func (f KeyFlags) HasNeedLocked() bool {
return f&flagNeedLocked != 0
}
// HasLockedValueExists returns whether the value exists when key locked.
func (f KeyFlags) HasLockedValueExists() bool {
return f&flagKeyLockedValExist != 0
}
// HasNeedCheckExists returns whether the key need to check existence when it has been locked.
func (f KeyFlags) HasNeedCheckExists() bool {
return f&flagNeedCheckExists != 0
}
// HasPrewriteOnly returns whether the key should be used in 2pc commit phase.
func (f KeyFlags) HasPrewriteOnly() bool {
return f&flagPrewriteOnly != 0
}
// HasIgnoredIn2PC returns whether the key will be ignored in 2pc.
func (f KeyFlags) HasIgnoredIn2PC() bool {
return f&flagIgnoredIn2PC != 0
}
// HasReadable returns whether the in-transaction operations is able to read the key.
func (f KeyFlags) HasReadable() bool {
return f&flagReadable != 0
}
// HasNeedConstraintCheckInPrewrite returns whether the key needs to check conflict in prewrite.
func (f KeyFlags) HasNeedConstraintCheckInPrewrite() bool {
return f&flagNeedConstraintCheckInPrewrite != 0
}
// AndPersistent returns the value of current flags&persistentFlags
func (f KeyFlags) AndPersistent() KeyFlags {
return f & persistentFlags
}
// HasNewlyInserted returns whether the in-transaction key is generated by an "insert" operation.
func (f KeyFlags) HasNewlyInserted() bool {
return f&flagNewlyInserted != 0
}
// ApplyFlagsOps applys flagspos to origin.
func ApplyFlagsOps(origin KeyFlags, ops ...FlagsOp) KeyFlags {
for _, op := range ops {
switch op {
case SetPresumeKeyNotExists:
origin |= flagPresumeKNE | flagNeedCheckExists
case DelPresumeKeyNotExists:
origin &= ^(flagPresumeKNE | flagNeedCheckExists)
case SetKeyLocked:
origin |= flagKeyLocked
case DelKeyLocked:
origin &= ^flagKeyLocked
case SetNeedLocked:
origin |= flagNeedLocked
case DelNeedLocked:
origin &= ^flagNeedLocked
case SetKeyLockedValueExists:
origin |= flagKeyLockedValExist
origin &= ^flagNeedConstraintCheckInPrewrite
case DelNeedCheckExists:
origin &= ^flagNeedCheckExists
case SetKeyLockedValueNotExists:
origin &= ^flagKeyLockedValExist
origin &= ^flagNeedConstraintCheckInPrewrite
case SetPrewriteOnly:
origin |= flagPrewriteOnly
case SetIgnoredIn2PC:
origin |= flagIgnoredIn2PC
case SetReadable:
origin |= flagReadable
case SetNewlyInserted:
origin |= flagNewlyInserted
case SetAssertExist:
origin &= ^flagAssertNotExist
origin |= flagAssertExist
case SetAssertNotExist:
origin &= ^flagAssertExist
origin |= flagAssertNotExist
case SetAssertUnknown:
origin |= flagAssertNotExist
origin |= flagAssertExist
case SetAssertNone:
origin &= ^flagAssertExist
origin &= ^flagAssertNotExist
case SetNeedConstraintCheckInPrewrite:
origin |= flagNeedConstraintCheckInPrewrite
case DelNeedConstraintCheckInPrewrite:
origin &= ^flagNeedConstraintCheckInPrewrite
case SetPreviousPresumeKNE:
origin |= flagPreviousPresumeKNE
}
}
return origin
}
// FlagsOp describes KeyFlags modify operation.
type FlagsOp uint32
const (
// SetPresumeKeyNotExists marks the existence of the associated key is checked lazily.
// Implies KeyFlags.HasNeedCheckExists() == true.
SetPresumeKeyNotExists FlagsOp = 1 << iota
// DelPresumeKeyNotExists reverts SetPresumeKeyNotExists.
DelPresumeKeyNotExists
// SetKeyLocked marks the associated key has acquired lock.
SetKeyLocked
// DelKeyLocked reverts SetKeyLocked.
DelKeyLocked
// SetNeedLocked marks the associated key need to be acquired lock.
SetNeedLocked
// DelNeedLocked reverts SetKeyNeedLocked.
DelNeedLocked
// SetKeyLockedValueExists marks the value exists when key has been locked in Transaction.LockKeys.
SetKeyLockedValueExists
// SetKeyLockedValueNotExists marks the value doesn't exists when key has been locked in Transaction.LockKeys.
SetKeyLockedValueNotExists
// DelNeedCheckExists marks the key no need to be checked in Transaction.LockKeys.
DelNeedCheckExists
// SetPrewriteOnly marks the key shouldn't be used in 2pc commit phase.
SetPrewriteOnly
// SetIgnoredIn2PC marks the key will be ignored in 2pc.
SetIgnoredIn2PC
// SetReadable marks the key is readable by in-transaction read.
SetReadable
// SetNewlyInserted marks the key is newly inserted with value length greater than zero.
SetNewlyInserted
// SetAssertExist marks the key must exist.
SetAssertExist
// SetAssertNotExist marks the key must not exist.
SetAssertNotExist
// SetAssertUnknown mark the key maybe exists or not exists.
SetAssertUnknown
// SetAssertNone cleans up the key's assert.
SetAssertNone
// SetNeedConstraintCheckInPrewrite marks the key needs to check conflict in prewrite.
SetNeedConstraintCheckInPrewrite
// DelNeedConstraintCheckInPrewrite reverts SetNeedConstraintCheckInPrewrite. This is required when we decide to
// make up the pessimistic lock.
DelNeedConstraintCheckInPrewrite
// SetPreviousPresumeKNE sets flagPreviousPresumeKNE.
SetPreviousPresumeKNE
)