mirror of https://github.com/k3s-io/k3s
clean pkg/util/keymutex
parent
1add6b0cfa
commit
df7e4f3d49
|
@ -32,7 +32,6 @@ filegroup(
|
||||||
"//pkg/util/ipset:all-srcs",
|
"//pkg/util/ipset:all-srcs",
|
||||||
"//pkg/util/iptables:all-srcs",
|
"//pkg/util/iptables:all-srcs",
|
||||||
"//pkg/util/ipvs:all-srcs",
|
"//pkg/util/ipvs:all-srcs",
|
||||||
"//pkg/util/keymutex:all-srcs",
|
|
||||||
"//pkg/util/labels:all-srcs",
|
"//pkg/util/labels:all-srcs",
|
||||||
"//pkg/util/maps:all-srcs",
|
"//pkg/util/maps:all-srcs",
|
||||||
"//pkg/util/metrics:all-srcs",
|
"//pkg/util/metrics:all-srcs",
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
package(default_visibility = ["//visibility:public"])
|
|
||||||
|
|
||||||
load(
|
|
||||||
"@io_bazel_rules_go//go:def.bzl",
|
|
||||||
"go_library",
|
|
||||||
"go_test",
|
|
||||||
)
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = [
|
|
||||||
"hashed.go",
|
|
||||||
"keymutex.go",
|
|
||||||
],
|
|
||||||
importpath = "k8s.io/kubernetes/pkg/util/keymutex",
|
|
||||||
deps = ["//vendor/k8s.io/klog:go_default_library"],
|
|
||||||
)
|
|
||||||
|
|
||||||
go_test(
|
|
||||||
name = "go_default_test",
|
|
||||||
srcs = ["keymutex_test.go"],
|
|
||||||
embed = [":go_default_library"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
)
|
|
|
@ -1,64 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2018 The Kubernetes 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package keymutex
|
|
||||||
|
|
||||||
import (
|
|
||||||
"hash/fnv"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"k8s.io/klog"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewHashed returns a new instance of KeyMutex which hashes arbitrary keys to
|
|
||||||
// a fixed set of locks. `n` specifies number of locks, if n <= 0, we use
|
|
||||||
// number of cpus.
|
|
||||||
// Note that because it uses fixed set of locks, different keys may share same
|
|
||||||
// lock, so it's possible to wait on same lock.
|
|
||||||
func NewHashed(n int) KeyMutex {
|
|
||||||
if n <= 0 {
|
|
||||||
n = runtime.NumCPU()
|
|
||||||
}
|
|
||||||
return &hashedKeyMutex{
|
|
||||||
mutexes: make([]sync.Mutex, n),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type hashedKeyMutex struct {
|
|
||||||
mutexes []sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// Acquires a lock associated with the specified ID.
|
|
||||||
func (km *hashedKeyMutex) LockKey(id string) {
|
|
||||||
klog.V(5).Infof("hashedKeyMutex.LockKey(...) called for id %q\r\n", id)
|
|
||||||
km.mutexes[km.hash(id)%len(km.mutexes)].Lock()
|
|
||||||
klog.V(5).Infof("hashedKeyMutex.LockKey(...) for id %q completed.\r\n", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Releases the lock associated with the specified ID.
|
|
||||||
func (km *hashedKeyMutex) UnlockKey(id string) error {
|
|
||||||
klog.V(5).Infof("hashedKeyMutex.UnlockKey(...) called for id %q\r\n", id)
|
|
||||||
km.mutexes[km.hash(id)%len(km.mutexes)].Unlock()
|
|
||||||
klog.V(5).Infof("hashedKeyMutex.UnlockKey(...) for id %q completed.\r\n", id)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (km *hashedKeyMutex) hash(id string) int {
|
|
||||||
h := fnv.New32a()
|
|
||||||
h.Write([]byte(id))
|
|
||||||
return int(h.Sum32())
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package keymutex
|
|
||||||
|
|
||||||
// KeyMutex is a thread-safe interface for acquiring locks on arbitrary strings.
|
|
||||||
type KeyMutex interface {
|
|
||||||
// Acquires a lock associated with the specified ID, creates the lock if one doesn't already exist.
|
|
||||||
LockKey(id string)
|
|
||||||
|
|
||||||
// Releases the lock associated with the specified ID.
|
|
||||||
// Returns an error if the specified ID doesn't exist.
|
|
||||||
UnlockKey(id string) error
|
|
||||||
}
|
|
|
@ -1,105 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015 The Kubernetes 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package keymutex
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
callbackTimeout = 1 * time.Second
|
|
||||||
)
|
|
||||||
|
|
||||||
func newKeyMutexes() []KeyMutex {
|
|
||||||
return []KeyMutex{
|
|
||||||
NewHashed(0),
|
|
||||||
NewHashed(1),
|
|
||||||
NewHashed(2),
|
|
||||||
NewHashed(4),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_SingleLock_NoUnlock(t *testing.T) {
|
|
||||||
for _, km := range newKeyMutexes() {
|
|
||||||
// Arrange
|
|
||||||
key := "fakeid"
|
|
||||||
callbackCh := make(chan interface{})
|
|
||||||
|
|
||||||
// Act
|
|
||||||
go lockAndCallback(km, key, callbackCh)
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
verifyCallbackHappens(t, callbackCh)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_SingleLock_SingleUnlock(t *testing.T) {
|
|
||||||
for _, km := range newKeyMutexes() {
|
|
||||||
// Arrange
|
|
||||||
key := "fakeid"
|
|
||||||
callbackCh := make(chan interface{})
|
|
||||||
|
|
||||||
// Act & Assert
|
|
||||||
go lockAndCallback(km, key, callbackCh)
|
|
||||||
verifyCallbackHappens(t, callbackCh)
|
|
||||||
km.UnlockKey(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_DoubleLock_DoubleUnlock(t *testing.T) {
|
|
||||||
for _, km := range newKeyMutexes() {
|
|
||||||
// Arrange
|
|
||||||
key := "fakeid"
|
|
||||||
callbackCh1stLock := make(chan interface{})
|
|
||||||
callbackCh2ndLock := make(chan interface{})
|
|
||||||
|
|
||||||
// Act & Assert
|
|
||||||
go lockAndCallback(km, key, callbackCh1stLock)
|
|
||||||
verifyCallbackHappens(t, callbackCh1stLock)
|
|
||||||
go lockAndCallback(km, key, callbackCh2ndLock)
|
|
||||||
verifyCallbackDoesntHappens(t, callbackCh2ndLock)
|
|
||||||
km.UnlockKey(key)
|
|
||||||
verifyCallbackHappens(t, callbackCh2ndLock)
|
|
||||||
km.UnlockKey(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func lockAndCallback(km KeyMutex, id string, callbackCh chan<- interface{}) {
|
|
||||||
km.LockKey(id)
|
|
||||||
callbackCh <- true
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyCallbackHappens(t *testing.T, callbackCh <-chan interface{}) bool {
|
|
||||||
select {
|
|
||||||
case <-callbackCh:
|
|
||||||
return true
|
|
||||||
case <-time.After(callbackTimeout):
|
|
||||||
t.Fatalf("Timed out waiting for callback.")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyCallbackDoesntHappens(t *testing.T, callbackCh <-chan interface{}) bool {
|
|
||||||
select {
|
|
||||||
case <-callbackCh:
|
|
||||||
t.Fatalf("Unexpected callback.")
|
|
||||||
return false
|
|
||||||
case <-time.After(callbackTimeout):
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -793,7 +793,6 @@ k8s.io/kubernetes/pkg/util/hash,timothysc,1,
|
||||||
k8s.io/kubernetes/pkg/util/i18n,brendandburns,0,
|
k8s.io/kubernetes/pkg/util/i18n,brendandburns,0,
|
||||||
k8s.io/kubernetes/pkg/util/io,mtaufen,1,
|
k8s.io/kubernetes/pkg/util/io,mtaufen,1,
|
||||||
k8s.io/kubernetes/pkg/util/iptables,rrati,0,
|
k8s.io/kubernetes/pkg/util/iptables,rrati,0,
|
||||||
k8s.io/kubernetes/pkg/util/keymutex,saad-ali,0,
|
|
||||||
k8s.io/kubernetes/pkg/util/labels,rmmh,1,
|
k8s.io/kubernetes/pkg/util/labels,rmmh,1,
|
||||||
k8s.io/kubernetes/pkg/util/limitwriter,deads2k,1,
|
k8s.io/kubernetes/pkg/util/limitwriter,deads2k,1,
|
||||||
k8s.io/kubernetes/pkg/util/mount,xiang90,1,
|
k8s.io/kubernetes/pkg/util/mount,xiang90,1,
|
||||||
|
|
|
Loading…
Reference in New Issue