File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 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+ }
Original file line number Diff line number Diff line change 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+ }
Original file line number Diff line number Diff line change 11package openstack
22
33import (
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)
Original file line number Diff line number Diff 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)
You can’t perform that action at this time.
0 commit comments