github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/kv/kvserver/concurrency/isolation/levels.go (about)

     1  // Copyright 2023 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  // Package isolation provides type definitions for isolation level-related
    12  // concepts used by concurrency control in the key-value layer.
    13  package isolation
    14  
    15  import "github.com/gogo/protobuf/proto"
    16  
    17  // WeakerThan returns true if the receiver's strength is weaker than the
    18  // parameter's strength. It returns false if the two isolation levels are
    19  // equivalent or if the parameter's strength is weaker than the receiver's.
    20  //
    21  // WARNING: Because isolation levels are defined from strongest to weakest in
    22  // their enumeration (which is important for backwards compatability), their
    23  // value comparison semantics do not represent a comparison of strength. The
    24  // equality operators (==, !=) may be used to match a specific isolation level,
    25  // but ordering operators (<, <=, >, >=) must not be used. Use this method
    26  // instead.
    27  func (l Level) WeakerThan(l2 Level) bool {
    28  	// Internally, we exploit the fact that the enum's value comparison semantics
    29  	// represent a comparison of the inverse of strength. Users of isolation level
    30  	// outside this package should not rely on this.
    31  	return l > l2
    32  }
    33  
    34  // ToleratesWriteSkew returns whether the isolation level permits write skew. In
    35  // an MVCC system, this property can be expressed as whether the isolation level
    36  // allows transactions to write and commit at an MVCC timestamp above the MVCC
    37  // timestamp of its read snapshot(s).
    38  func (l Level) ToleratesWriteSkew() bool {
    39  	return l.WeakerThan(Serializable)
    40  }
    41  
    42  // PerStatementReadSnapshot returns whether the isolation level establishes a
    43  // new read snapshot for each statement. If not, a single read snapshot is used
    44  // for the entire transaction.
    45  func (l Level) PerStatementReadSnapshot() bool {
    46  	return l == ReadCommitted
    47  }
    48  
    49  var levelNameLower = map[int32]string{
    50  	int32(Serializable):  "serializable",
    51  	int32(Snapshot):      "snapshot",
    52  	int32(ReadCommitted): "read committed",
    53  }
    54  
    55  func init() {
    56  	if len(levelNameLower) != len(Level_name) {
    57  		panic("missing lower-case name for isolation level")
    58  	}
    59  }
    60  
    61  // StringLower returns the lower-case name of the isolation level.
    62  func (l Level) StringLower() string {
    63  	return proto.EnumName(levelNameLower, int32(l))
    64  }
    65  
    66  // SafeValue implements the redact.SafeValue interface.
    67  func (Level) SafeValue() {}
    68  
    69  // Levels returns a list of all isolation levels, ordered from strongest to
    70  // weakest.
    71  func Levels() []Level { return []Level{Serializable, Snapshot, ReadCommitted} }
    72  
    73  // RunEachLevel calls f in a subtest for each isolation level.
    74  func RunEachLevel[T testingTB[T]](t T, f func(T, Level)) {
    75  	for _, l := range Levels() {
    76  		t.Run(l.String(), func(t T) { f(t, l) })
    77  	}
    78  }
    79  
    80  // testingTB is an interface that matches *testing.T and *testing.B, without
    81  // incurring the package dependency.
    82  type testingTB[T any] interface {
    83  	Run(name string, f func(t T)) bool
    84  }