Skip to content

Commit b54a1c9

Browse files
move lockmap to util package (#7714)
1 parent a8e6cd2 commit b54a1c9

9 files changed

+156
-111
lines changed

Diff for: pkg/provider/azure.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ import (
7777
"sigs.k8s.io/cloud-provider-azure/pkg/consts"
7878
azureconfig "sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
7979
"sigs.k8s.io/cloud-provider-azure/pkg/retry"
80+
"sigs.k8s.io/cloud-provider-azure/pkg/util/lockmap"
8081
utilsets "sigs.k8s.io/cloud-provider-azure/pkg/util/sets"
8182
"sigs.k8s.io/cloud-provider-azure/pkg/util/taints"
8283
)
@@ -190,7 +191,7 @@ type Cloud struct {
190191
// node-sync-loop routine and service-reconcile routine should not update LoadBalancer at the same time
191192
serviceReconcileLock sync.Mutex
192193

193-
lockMap *LockMap
194+
lockMap *lockmap.LockMap
194195
// multipleStandardLoadBalancerConfigurationsSynced make sure the `reconcileMultipleStandardLoadBalancerConfigurations`
195196
// runs only once every time the cloud provide restarts.
196197
multipleStandardLoadBalancerConfigurationsSynced bool
@@ -224,7 +225,7 @@ func NewCloud(ctx context.Context, clientBuilder cloudprovider.ControllerClientB
224225

225226
az.ipv6DualStackEnabled = true
226227
if az.lockMap == nil {
227-
az.lockMap = newLockMap()
228+
az.lockMap = lockmap.NewLockMap()
228229
}
229230

230231
if clientBuilder != nil {
@@ -386,7 +387,7 @@ func (az *Cloud) InitializeCloudFromConfig(ctx context.Context, config *config.C
386387
return err
387388
}
388389

389-
az.lockMap = newLockMap()
390+
az.lockMap = lockmap.NewLockMap()
390391
az.Config = *config
391392
az.Environment = *env
392393
az.ResourceRequestBackoff = resourceRequestBackoff

Diff for: pkg/provider/azure_fakes.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import (
4747
"sigs.k8s.io/cloud-provider-azure/pkg/provider/routetable"
4848
"sigs.k8s.io/cloud-provider-azure/pkg/provider/securitygroup"
4949
"sigs.k8s.io/cloud-provider-azure/pkg/provider/subnet"
50+
"sigs.k8s.io/cloud-provider-azure/pkg/util/lockmap"
5051
utilsets "sigs.k8s.io/cloud-provider-azure/pkg/util/sets"
5152
)
5253

@@ -110,7 +111,7 @@ func GetTestCloud(ctrl *gomock.Controller) (az *Cloud) {
110111
nodePrivateIPs: map[string]*utilsets.IgnoreCaseSet{},
111112
routeCIDRs: map[string]string{},
112113
eventRecorder: &record.FakeRecorder{},
113-
lockMap: newLockMap(),
114+
lockMap: lockmap.NewLockMap(),
114115
}
115116
az.DisksClient = mockdiskclient.NewMockInterface(ctrl)
116117
az.InterfacesClient = mockinterfaceclient.NewMockInterface(ctrl)

Diff for: pkg/provider/azure_storageaccount_test.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import (
4545
"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/subnetclient/mocksubnetclient"
4646
"sigs.k8s.io/cloud-provider-azure/pkg/cache"
4747
"sigs.k8s.io/cloud-provider-azure/pkg/retry"
48+
"sigs.k8s.io/cloud-provider-azure/pkg/util/lockmap"
4849
)
4950

5051
const TestLocation = "testLocation"
@@ -702,7 +703,7 @@ func TestAddStorageAccountTags(t *testing.T) {
702703
defer cancel()
703704

704705
cloud := &Cloud{}
705-
cloud.lockMap = newLockMap()
706+
cloud.lockMap = lockmap.NewLockMap()
706707
tests := []struct {
707708
name string
708709
subsID string
@@ -806,7 +807,7 @@ func TestRemoveStorageAccountTags(t *testing.T) {
806807

807808
getter := func(_ context.Context, _ string) (interface{}, error) { return nil, nil }
808809
cloud.storageAccountCache, _ = cache.NewTimedCache(time.Minute, getter, false)
809-
cloud.lockMap = newLockMap()
810+
cloud.lockMap = lockmap.NewLockMap()
810811
for _, test := range tests {
811812
mockStorageAccountsClient := mockstorageaccountclient.NewMockInterface(ctrl)
812813
cloud.StorageAccountClient = mockStorageAccountsClient

Diff for: pkg/provider/azure_utils.go

-38
Original file line numberDiff line numberDiff line change
@@ -47,44 +47,6 @@ var strToExtendedLocationType = map[string]armnetwork.ExtendedLocationTypes{
4747
"edgezone": armnetwork.ExtendedLocationTypesEdgeZone,
4848
}
4949

50-
// LockMap used to lock on entries
51-
type LockMap struct {
52-
sync.Mutex
53-
mutexMap map[string]*sync.Mutex
54-
}
55-
56-
// NewLockMap returns a new lock map
57-
func newLockMap() *LockMap {
58-
return &LockMap{
59-
mutexMap: make(map[string]*sync.Mutex),
60-
}
61-
}
62-
63-
// LockEntry acquires a lock associated with the specific entry
64-
func (lm *LockMap) LockEntry(entry string) {
65-
lm.Lock()
66-
// check if entry does not exists, then add entry
67-
mutex, exists := lm.mutexMap[entry]
68-
if !exists {
69-
mutex = &sync.Mutex{}
70-
lm.mutexMap[entry] = mutex
71-
}
72-
lm.Unlock()
73-
mutex.Lock()
74-
}
75-
76-
// UnlockEntry release the lock associated with the specific entry
77-
func (lm *LockMap) UnlockEntry(entry string) {
78-
lm.Lock()
79-
defer lm.Unlock()
80-
81-
mutex, exists := lm.mutexMap[entry]
82-
if !exists {
83-
return
84-
}
85-
mutex.Unlock()
86-
}
87-
8850
func getContextWithCancel() (context.Context, context.CancelFunc) {
8951
return context.WithCancel(context.Background())
9052
}

Diff for: pkg/provider/azure_utils_test.go

-62
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"reflect"
2222
"sync"
2323
"testing"
24-
"time"
2524

2625
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6"
2726
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6"
@@ -39,67 +38,6 @@ import (
3938
"sigs.k8s.io/cloud-provider-azure/pkg/consts"
4039
)
4140

42-
func TestSimpleLockEntry(t *testing.T) {
43-
testLockMap := newLockMap()
44-
45-
callbackChan1 := make(chan interface{})
46-
go testLockMap.lockAndCallback(t, "entry1", callbackChan1)
47-
ensureCallbackHappens(t, callbackChan1)
48-
}
49-
50-
func TestSimpleLockUnlockEntry(t *testing.T) {
51-
testLockMap := newLockMap()
52-
53-
callbackChan1 := make(chan interface{})
54-
go testLockMap.lockAndCallback(t, "entry1", callbackChan1)
55-
ensureCallbackHappens(t, callbackChan1)
56-
testLockMap.UnlockEntry("entry1")
57-
}
58-
59-
func TestConcurrentLockEntry(t *testing.T) {
60-
testLockMap := newLockMap()
61-
62-
callbackChan1 := make(chan interface{})
63-
callbackChan2 := make(chan interface{})
64-
65-
go testLockMap.lockAndCallback(t, "entry1", callbackChan1)
66-
ensureCallbackHappens(t, callbackChan1)
67-
68-
go testLockMap.lockAndCallback(t, "entry1", callbackChan2)
69-
ensureNoCallback(t, callbackChan2)
70-
71-
testLockMap.UnlockEntry("entry1")
72-
ensureCallbackHappens(t, callbackChan2)
73-
testLockMap.UnlockEntry("entry1")
74-
}
75-
76-
func (lm *LockMap) lockAndCallback(_ *testing.T, entry string, callbackChan chan<- interface{}) {
77-
lm.LockEntry(entry)
78-
callbackChan <- true
79-
}
80-
81-
var callbackTimeout = 2 * time.Second
82-
83-
func ensureCallbackHappens(t *testing.T, callbackChan <-chan interface{}) bool {
84-
select {
85-
case <-callbackChan:
86-
return true
87-
case <-time.After(callbackTimeout):
88-
t.Fatalf("timed out waiting for callback")
89-
return false
90-
}
91-
}
92-
93-
func ensureNoCallback(t *testing.T, callbackChan <-chan interface{}) bool {
94-
select {
95-
case <-callbackChan:
96-
t.Fatalf("unexpected callback")
97-
return false
98-
case <-time.After(callbackTimeout):
99-
return true
100-
}
101-
}
102-
10341
func TestReconcileTags(t *testing.T) {
10442
for _, testCase := range []struct {
10543
description, systemTags string

Diff for: pkg/provider/azure_vmss.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import (
4040
"sigs.k8s.io/cloud-provider-azure/pkg/consts"
4141
"sigs.k8s.io/cloud-provider-azure/pkg/metrics"
4242
"sigs.k8s.io/cloud-provider-azure/pkg/provider/virtualmachine"
43+
"sigs.k8s.io/cloud-provider-azure/pkg/util/lockmap"
4344
vmutil "sigs.k8s.io/cloud-provider-azure/pkg/util/vm"
4445
)
4546

@@ -102,7 +103,7 @@ type ScaleSet struct {
102103
nonVmssUniformNodesCache azcache.Resource
103104

104105
// lockMap in cache refresh
105-
lockMap *LockMap
106+
lockMap *lockmap.LockMap
106107
}
107108

108109
// RefreshCaches invalidates and renew all related caches.
@@ -153,14 +154,14 @@ func newScaleSet(az *Cloud) (VMSet, error) {
153154
Cloud: az,
154155
availabilitySet: as,
155156
flexScaleSet: fs,
156-
lockMap: newLockMap(),
157+
lockMap: lockmap.NewLockMap(),
157158
}
158159

159160
if err := ss.RefreshCaches(); err != nil {
160161
return nil, err
161162
}
162163

163-
ss.lockMap = newLockMap()
164+
ss.lockMap = lockmap.NewLockMap()
164165
return ss, nil
165166
}
166167

Diff for: pkg/provider/azure_vmssflex.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
azcache "sigs.k8s.io/cloud-provider-azure/pkg/cache"
3939
"sigs.k8s.io/cloud-provider-azure/pkg/consts"
4040
"sigs.k8s.io/cloud-provider-azure/pkg/metrics"
41+
"sigs.k8s.io/cloud-provider-azure/pkg/util/lockmap"
4142
vmutil "sigs.k8s.io/cloud-provider-azure/pkg/util/vm"
4243
)
4344

@@ -54,7 +55,7 @@ type FlexScaleSet struct {
5455
vmssFlexVMCache azcache.Resource
5556

5657
// lockMap in cache refresh
57-
lockMap *LockMap
58+
lockMap *lockmap.LockMap
5859
}
5960

6061
// RefreshCaches invalidates and renew all related caches.
@@ -79,7 +80,7 @@ func newFlexScaleSet(az *Cloud) (VMSet, error) {
7980
Cloud: az,
8081
vmssFlexVMNameToVmssID: &sync.Map{},
8182
vmssFlexVMNameToNodeName: &sync.Map{},
82-
lockMap: newLockMap(),
83+
lockMap: lockmap.NewLockMap(),
8384
}
8485

8586
if err := fs.RefreshCaches(); err != nil {

Diff for: pkg/util/lockmap/lockmap.go

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package lockmap
18+
19+
import "sync"
20+
21+
// LockMap used to lock on entries
22+
type LockMap struct {
23+
sync.Mutex
24+
mutexMap map[string]*sync.Mutex
25+
}
26+
27+
// NewLockMap returns a new lock map
28+
func NewLockMap() *LockMap {
29+
return &LockMap{
30+
mutexMap: make(map[string]*sync.Mutex),
31+
}
32+
}
33+
34+
// LockEntry acquires a lock associated with the specific entry
35+
func (lm *LockMap) LockEntry(entry string) {
36+
lm.Lock()
37+
// check if entry does not exists, then add entry
38+
mutex, exists := lm.mutexMap[entry]
39+
if !exists {
40+
mutex = &sync.Mutex{}
41+
lm.mutexMap[entry] = mutex
42+
}
43+
lm.Unlock()
44+
mutex.Lock()
45+
}
46+
47+
// UnlockEntry release the lock associated with the specific entry
48+
func (lm *LockMap) UnlockEntry(entry string) {
49+
lm.Lock()
50+
defer lm.Unlock()
51+
52+
mutex, exists := lm.mutexMap[entry]
53+
if !exists {
54+
return
55+
}
56+
mutex.Unlock()
57+
}

0 commit comments

Comments
 (0)