-
Notifications
You must be signed in to change notification settings - Fork 3.8k
/
Copy pathversion_guard.go
94 lines (85 loc) · 3.29 KB
/
version_guard.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Copyright 2023 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
package settingswatcher
import (
"context"
"github.com/cockroachdb/cockroach/pkg/clusterversion"
"github.com/cockroachdb/cockroach/pkg/kv"
"github.com/cockroachdb/cockroach/pkg/util/log"
"github.com/cockroachdb/errors"
)
// VersionGuard is a utility for checking the cluster version in a transaction.
// VersionGuard is optimized to avoid the extra kv read overhead once the
// cluster is finalized.
//
// Example Usage:
//
// guard, err := watcher.MakeVersionGuard(ctx, txn, version.MaxVersionGateToCheck)
// if err != nil {
// return err // unable to read version
// }
// if guard.IsActive(version.SomeVersionLessThanMax) {
// ...
// } else if guard.IsActive(version.MaxVersionGateToCheck) {
// ...
// }
type VersionGuard struct {
activeVersion clusterversion.ClusterVersion
}
// MakeVersionGuard constructs a version guard for the transaction.
func (s *SettingsWatcher) MakeVersionGuard(
ctx context.Context, txn *kv.Txn, maxGate clusterversion.Key,
) (VersionGuard, error) {
activeVersion := s.settings.Version.ActiveVersion(ctx)
if activeVersion.IsActive(maxGate) {
return VersionGuard{activeVersion: activeVersion}, nil
}
txnVersion, err := s.GetClusterVersionFromStorage(ctx, txn)
if errors.Is(err, errVersionSettingNotFound) {
// The version setting is set via the upgrade job. Since there are some
// permanent upgrades that run unconditionally when a cluster is
// created, the version setting is populated during the cluster boot
// strap process.
//
// The case where a setting is old and the version is missing is
// uncommon and mostly shows up during tests. Usually clusters are
// bootstrapped at the binary version, so a new cluster will hit the
// fast path of the version guard since the active version is the most
// recent version gate.
//
// However, during testing the sql server may be bootstrapped at an old
// cluster version and hits the slow path because the cluster version
// is behind the maxGate version. In this case we treat the in-memory
// version as the active setting.
//
// Using the in-memory version is safe from race conditions because the
// transaction did read the missing value from the system.settings
// table and will get retried if the setting changes.
log.Ops.Warningf(ctx, "the 'version' setting was not found in the system.setting table using in-memory settings %v", activeVersion)
return VersionGuard{
activeVersion: activeVersion,
}, nil
}
if err != nil {
return VersionGuard{}, err
}
return VersionGuard{
activeVersion: txnVersion,
}, nil
}
// IsActive returns true if the transaction should treat the version guard as
// active.
func (v *VersionGuard) IsActive(version clusterversion.Key) bool {
return v.activeVersion.IsActive(version)
}
// TestMakeVersionGuard initializes a version guard at specific version.
func TestMakeVersionGuard(activeVersion clusterversion.ClusterVersion) VersionGuard {
return VersionGuard{activeVersion: activeVersion}
}