Skip to content

Commit 7fe2cfe

Browse files
authored
Copy MutexKV to internal package (terraform-provider-openstack#1080)
Because MutexKV will be removed from terraform-plugin-sdk package copy it to local internal/mutexkv package.
1 parent bbce811 commit 7fe2cfe

4 files changed

Lines changed: 120 additions & 2 deletions

File tree

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package mutexkv
2+
3+
import (
4+
"log"
5+
"sync"
6+
)
7+
8+
// MutexKV is a simple key/value store for arbitrary mutexes. It can be used to
9+
// serialize changes across arbitrary collaborators that share knowledge of the
10+
// keys they must serialize on.
11+
//
12+
// The initial use case is to let aws_security_group_rule resources serialize
13+
// their access to individual security groups based on SG ID.
14+
type MutexKV struct {
15+
lock sync.Mutex
16+
store map[string]*sync.Mutex
17+
}
18+
19+
// Locks the mutex for the given key. Caller is responsible for calling Unlock
20+
// for the same key.
21+
func (m *MutexKV) Lock(key string) {
22+
log.Printf("[DEBUG] Locking %q", key)
23+
m.get(key).Lock()
24+
log.Printf("[DEBUG] Locked %q", key)
25+
}
26+
27+
// Unlock the mutex for the given key. Caller must have called Lock for the same key first.
28+
func (m *MutexKV) Unlock(key string) {
29+
log.Printf("[DEBUG] Unlocking %q", key)
30+
m.get(key).Unlock()
31+
log.Printf("[DEBUG] Unlocked %q", key)
32+
}
33+
34+
// Returns a mutex for the given key, no guarantee of its lock status.
35+
func (m *MutexKV) get(key string) *sync.Mutex {
36+
m.lock.Lock()
37+
defer m.lock.Unlock()
38+
mutex, ok := m.store[key]
39+
if !ok {
40+
mutex = &sync.Mutex{}
41+
m.store[key] = mutex
42+
}
43+
return mutex
44+
}
45+
46+
// Returns a properly initialized MutexKV.
47+
func NewMutexKV() *MutexKV {
48+
return &MutexKV{
49+
store: make(map[string]*sync.Mutex),
50+
}
51+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package mutexkv
2+
3+
import (
4+
"testing"
5+
"time"
6+
)
7+
8+
func TestMutexKVLock(t *testing.T) {
9+
mkv := NewMutexKV()
10+
11+
mkv.Lock("foo")
12+
13+
doneCh := make(chan struct{})
14+
15+
go func() {
16+
mkv.Lock("foo")
17+
close(doneCh)
18+
}()
19+
20+
select {
21+
case <-doneCh:
22+
t.Fatal("Second lock was able to be taken. This shouldn't happen.")
23+
case <-time.After(50 * time.Millisecond):
24+
// pass
25+
}
26+
}
27+
28+
func TestMutexKVUnlock(t *testing.T) {
29+
mkv := NewMutexKV()
30+
31+
mkv.Lock("foo")
32+
mkv.Unlock("foo")
33+
34+
doneCh := make(chan struct{})
35+
36+
go func() {
37+
mkv.Lock("foo")
38+
close(doneCh)
39+
}()
40+
41+
select {
42+
case <-doneCh:
43+
// pass
44+
case <-time.After(50 * time.Millisecond):
45+
t.Fatal("Second lock blocked after unlock. This shouldn't happen.")
46+
}
47+
}
48+
49+
func TestMutexKVDifferentKeys(t *testing.T) {
50+
mkv := NewMutexKV()
51+
52+
mkv.Lock("foo")
53+
54+
doneCh := make(chan struct{})
55+
56+
go func() {
57+
mkv.Lock("bar")
58+
close(doneCh)
59+
}()
60+
61+
select {
62+
case <-doneCh:
63+
// pass
64+
case <-time.After(50 * time.Millisecond):
65+
t.Fatal("Second lock on a different key blocked. This shouldn't happen.")
66+
}
67+
}

‎openstack/provider.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package openstack
22

33
import (
4-
"github.com/hashicorp/terraform-plugin-sdk/helper/mutexkv"
54
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
65
"github.com/hashicorp/terraform-plugin-sdk/meta"
76
"github.com/hashicorp/terraform-plugin-sdk/terraform"
7+
"github.com/terraform-provider-openstack/terraform-provider-openstack/openstack/internal/mutexkv"
88

99
"github.com/gophercloud/utils/terraform/auth"
1010
)

‎openstack/provider_test.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import (
66
"os"
77
"testing"
88

9-
"github.com/hashicorp/terraform-plugin-sdk/helper/mutexkv"
109
"github.com/hashicorp/terraform-plugin-sdk/helper/pathorcontents"
1110
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
1211
"github.com/hashicorp/terraform-plugin-sdk/terraform"
12+
"github.com/terraform-provider-openstack/terraform-provider-openstack/openstack/internal/mutexkv"
1313

1414
"github.com/gophercloud/utils/terraform/auth"
1515
)

0 commit comments

Comments
 (0)