diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/helper/shadow')
5 files changed, 504 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/helper/shadow/closer.go b/vendor/github.com/hashicorp/terraform/helper/shadow/closer.go new file mode 100644 index 0000000..7edd5e7 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/helper/shadow/closer.go | |||
@@ -0,0 +1,80 @@ | |||
1 | package shadow | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "io" | ||
6 | "reflect" | ||
7 | |||
8 | "github.com/hashicorp/go-multierror" | ||
9 | "github.com/mitchellh/reflectwalk" | ||
10 | ) | ||
11 | |||
12 | // Close will close all shadow values within the given structure. | ||
13 | // | ||
14 | // This uses reflection to walk the structure, find all shadow elements, | ||
15 | // and close them. Currently this will only find struct fields that are | ||
16 | // shadow values, and not slice elements, etc. | ||
17 | func Close(v interface{}) error { | ||
18 | // We require a pointer so we can address the internal fields | ||
19 | val := reflect.ValueOf(v) | ||
20 | if val.Kind() != reflect.Ptr { | ||
21 | return fmt.Errorf("value must be a pointer") | ||
22 | } | ||
23 | |||
24 | // Walk and close | ||
25 | var w closeWalker | ||
26 | if err := reflectwalk.Walk(v, &w); err != nil { | ||
27 | return err | ||
28 | } | ||
29 | |||
30 | return w.Err | ||
31 | } | ||
32 | |||
33 | type closeWalker struct { | ||
34 | Err error | ||
35 | } | ||
36 | |||
37 | func (w *closeWalker) Struct(reflect.Value) error { | ||
38 | // Do nothing. We implement this for reflectwalk.StructWalker | ||
39 | return nil | ||
40 | } | ||
41 | |||
42 | func (w *closeWalker) StructField(f reflect.StructField, v reflect.Value) error { | ||
43 | // Not sure why this would be but lets avoid some panics | ||
44 | if !v.IsValid() { | ||
45 | return nil | ||
46 | } | ||
47 | |||
48 | // Empty for exported, so don't check unexported fields | ||
49 | if f.PkgPath != "" { | ||
50 | return nil | ||
51 | } | ||
52 | |||
53 | // Verify the io.Closer is in this package | ||
54 | typ := v.Type() | ||
55 | if typ.PkgPath() != "github.com/hashicorp/terraform/helper/shadow" { | ||
56 | return nil | ||
57 | } | ||
58 | |||
59 | // We're looking for an io.Closer | ||
60 | raw := v.Interface() | ||
61 | if raw == nil { | ||
62 | return nil | ||
63 | } | ||
64 | |||
65 | closer, ok := raw.(io.Closer) | ||
66 | if !ok && v.CanAddr() { | ||
67 | closer, ok = v.Addr().Interface().(io.Closer) | ||
68 | } | ||
69 | if !ok { | ||
70 | return reflectwalk.SkipEntry | ||
71 | } | ||
72 | |||
73 | // Close it | ||
74 | if err := closer.Close(); err != nil { | ||
75 | w.Err = multierror.Append(w.Err, err) | ||
76 | } | ||
77 | |||
78 | // Don't go into the struct field | ||
79 | return reflectwalk.SkipEntry | ||
80 | } | ||
diff --git a/vendor/github.com/hashicorp/terraform/helper/shadow/compared_value.go b/vendor/github.com/hashicorp/terraform/helper/shadow/compared_value.go new file mode 100644 index 0000000..4223e92 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/helper/shadow/compared_value.go | |||
@@ -0,0 +1,128 @@ | |||
1 | package shadow | ||
2 | |||
3 | import ( | ||
4 | "sync" | ||
5 | ) | ||
6 | |||
7 | // ComparedValue is a struct that finds a value by comparing some key | ||
8 | // to the list of stored values. This is useful when there is no easy | ||
9 | // uniquely identifying key that works in a map (for that, use KeyedValue). | ||
10 | // | ||
11 | // ComparedValue is very expensive, relative to other Value types. Try to | ||
12 | // limit the number of values stored in a ComparedValue by potentially | ||
13 | // nesting it within a KeyedValue (a keyed value points to a compared value, | ||
14 | // for example). | ||
15 | type ComparedValue struct { | ||
16 | // Func is a function that is given the lookup key and a single | ||
17 | // stored value. If it matches, it returns true. | ||
18 | Func func(k, v interface{}) bool | ||
19 | |||
20 | lock sync.Mutex | ||
21 | once sync.Once | ||
22 | closed bool | ||
23 | values []interface{} | ||
24 | waiters map[interface{}]*Value | ||
25 | } | ||
26 | |||
27 | // Close closes the value. This can never fail. For a definition of | ||
28 | // "close" see the ErrClosed docs. | ||
29 | func (w *ComparedValue) Close() error { | ||
30 | w.lock.Lock() | ||
31 | defer w.lock.Unlock() | ||
32 | |||
33 | // Set closed to true always | ||
34 | w.closed = true | ||
35 | |||
36 | // For all waiters, complete with ErrClosed | ||
37 | for k, val := range w.waiters { | ||
38 | val.SetValue(ErrClosed) | ||
39 | delete(w.waiters, k) | ||
40 | } | ||
41 | |||
42 | return nil | ||
43 | } | ||
44 | |||
45 | // Value returns the value that was set for the given key, or blocks | ||
46 | // until one is available. | ||
47 | func (w *ComparedValue) Value(k interface{}) interface{} { | ||
48 | v, val := w.valueWaiter(k) | ||
49 | if val == nil { | ||
50 | return v | ||
51 | } | ||
52 | |||
53 | return val.Value() | ||
54 | } | ||
55 | |||
56 | // ValueOk gets the value for the given key, returning immediately if the | ||
57 | // value doesn't exist. The second return argument is true if the value exists. | ||
58 | func (w *ComparedValue) ValueOk(k interface{}) (interface{}, bool) { | ||
59 | v, val := w.valueWaiter(k) | ||
60 | return v, val == nil | ||
61 | } | ||
62 | |||
63 | func (w *ComparedValue) SetValue(v interface{}) { | ||
64 | w.lock.Lock() | ||
65 | defer w.lock.Unlock() | ||
66 | w.once.Do(w.init) | ||
67 | |||
68 | // Check if we already have this exact value (by simply comparing | ||
69 | // with == directly). If we do, then we don't insert it again. | ||
70 | found := false | ||
71 | for _, v2 := range w.values { | ||
72 | if v == v2 { | ||
73 | found = true | ||
74 | break | ||
75 | } | ||
76 | } | ||
77 | |||
78 | if !found { | ||
79 | // Set the value, always | ||
80 | w.values = append(w.values, v) | ||
81 | } | ||
82 | |||
83 | // Go through the waiters | ||
84 | for k, val := range w.waiters { | ||
85 | if w.Func(k, v) { | ||
86 | val.SetValue(v) | ||
87 | delete(w.waiters, k) | ||
88 | } | ||
89 | } | ||
90 | } | ||
91 | |||
92 | func (w *ComparedValue) valueWaiter(k interface{}) (interface{}, *Value) { | ||
93 | w.lock.Lock() | ||
94 | w.once.Do(w.init) | ||
95 | |||
96 | // Look for a pre-existing value | ||
97 | for _, v := range w.values { | ||
98 | if w.Func(k, v) { | ||
99 | w.lock.Unlock() | ||
100 | return v, nil | ||
101 | } | ||
102 | } | ||
103 | |||
104 | // If we're closed, return that | ||
105 | if w.closed { | ||
106 | w.lock.Unlock() | ||
107 | return ErrClosed, nil | ||
108 | } | ||
109 | |||
110 | // Pre-existing value doesn't exist, create a waiter | ||
111 | val := w.waiters[k] | ||
112 | if val == nil { | ||
113 | val = new(Value) | ||
114 | w.waiters[k] = val | ||
115 | } | ||
116 | w.lock.Unlock() | ||
117 | |||
118 | // Return the waiter | ||
119 | return nil, val | ||
120 | } | ||
121 | |||
122 | // Must be called with w.lock held. | ||
123 | func (w *ComparedValue) init() { | ||
124 | w.waiters = make(map[interface{}]*Value) | ||
125 | if w.Func == nil { | ||
126 | w.Func = func(k, v interface{}) bool { return k == v } | ||
127 | } | ||
128 | } | ||
diff --git a/vendor/github.com/hashicorp/terraform/helper/shadow/keyed_value.go b/vendor/github.com/hashicorp/terraform/helper/shadow/keyed_value.go new file mode 100644 index 0000000..432b036 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/helper/shadow/keyed_value.go | |||
@@ -0,0 +1,151 @@ | |||
1 | package shadow | ||
2 | |||
3 | import ( | ||
4 | "sync" | ||
5 | ) | ||
6 | |||
7 | // KeyedValue is a struct that coordinates a value by key. If a value is | ||
8 | // not available for a give key, it'll block until it is available. | ||
9 | type KeyedValue struct { | ||
10 | lock sync.Mutex | ||
11 | once sync.Once | ||
12 | values map[string]interface{} | ||
13 | waiters map[string]*Value | ||
14 | closed bool | ||
15 | } | ||
16 | |||
17 | // Close closes the value. This can never fail. For a definition of | ||
18 | // "close" see the ErrClosed docs. | ||
19 | func (w *KeyedValue) Close() error { | ||
20 | w.lock.Lock() | ||
21 | defer w.lock.Unlock() | ||
22 | |||
23 | // Set closed to true always | ||
24 | w.closed = true | ||
25 | |||
26 | // For all waiters, complete with ErrClosed | ||
27 | for k, val := range w.waiters { | ||
28 | val.SetValue(ErrClosed) | ||
29 | delete(w.waiters, k) | ||
30 | } | ||
31 | |||
32 | return nil | ||
33 | } | ||
34 | |||
35 | // Value returns the value that was set for the given key, or blocks | ||
36 | // until one is available. | ||
37 | func (w *KeyedValue) Value(k string) interface{} { | ||
38 | w.lock.Lock() | ||
39 | v, val := w.valueWaiter(k) | ||
40 | w.lock.Unlock() | ||
41 | |||
42 | // If we have no waiter, then return the value | ||
43 | if val == nil { | ||
44 | return v | ||
45 | } | ||
46 | |||
47 | // We have a waiter, so wait | ||
48 | return val.Value() | ||
49 | } | ||
50 | |||
51 | // WaitForChange waits for the value with the given key to be set again. | ||
52 | // If the key isn't set, it'll wait for an initial value. Note that while | ||
53 | // it is called "WaitForChange", the value isn't guaranteed to _change_; | ||
54 | // this will return when a SetValue is called for the given k. | ||
55 | func (w *KeyedValue) WaitForChange(k string) interface{} { | ||
56 | w.lock.Lock() | ||
57 | w.once.Do(w.init) | ||
58 | |||
59 | // If we're closed, we're closed | ||
60 | if w.closed { | ||
61 | w.lock.Unlock() | ||
62 | return ErrClosed | ||
63 | } | ||
64 | |||
65 | // Check for an active waiter. If there isn't one, make it | ||
66 | val := w.waiters[k] | ||
67 | if val == nil { | ||
68 | val = new(Value) | ||
69 | w.waiters[k] = val | ||
70 | } | ||
71 | w.lock.Unlock() | ||
72 | |||
73 | // And wait | ||
74 | return val.Value() | ||
75 | } | ||
76 | |||
77 | // ValueOk gets the value for the given key, returning immediately if the | ||
78 | // value doesn't exist. The second return argument is true if the value exists. | ||
79 | func (w *KeyedValue) ValueOk(k string) (interface{}, bool) { | ||
80 | w.lock.Lock() | ||
81 | defer w.lock.Unlock() | ||
82 | |||
83 | v, val := w.valueWaiter(k) | ||
84 | return v, val == nil | ||
85 | } | ||
86 | |||
87 | func (w *KeyedValue) SetValue(k string, v interface{}) { | ||
88 | w.lock.Lock() | ||
89 | defer w.lock.Unlock() | ||
90 | w.setValue(k, v) | ||
91 | } | ||
92 | |||
93 | // Init will initialize the key to a given value only if the key has | ||
94 | // not been set before. This is safe to call multiple times and in parallel. | ||
95 | func (w *KeyedValue) Init(k string, v interface{}) { | ||
96 | w.lock.Lock() | ||
97 | defer w.lock.Unlock() | ||
98 | |||
99 | // If we have a waiter, set the value. | ||
100 | _, val := w.valueWaiter(k) | ||
101 | if val != nil { | ||
102 | w.setValue(k, v) | ||
103 | } | ||
104 | } | ||
105 | |||
106 | // Must be called with w.lock held. | ||
107 | func (w *KeyedValue) init() { | ||
108 | w.values = make(map[string]interface{}) | ||
109 | w.waiters = make(map[string]*Value) | ||
110 | } | ||
111 | |||
112 | // setValue is like SetValue but assumes the lock is held. | ||
113 | func (w *KeyedValue) setValue(k string, v interface{}) { | ||
114 | w.once.Do(w.init) | ||
115 | |||
116 | // Set the value, always | ||
117 | w.values[k] = v | ||
118 | |||
119 | // If we have a waiter, set it | ||
120 | if val, ok := w.waiters[k]; ok { | ||
121 | val.SetValue(v) | ||
122 | delete(w.waiters, k) | ||
123 | } | ||
124 | } | ||
125 | |||
126 | // valueWaiter gets the value or the Value waiter for a given key. | ||
127 | // | ||
128 | // This must be called with lock held. | ||
129 | func (w *KeyedValue) valueWaiter(k string) (interface{}, *Value) { | ||
130 | w.once.Do(w.init) | ||
131 | |||
132 | // If we have this value already, return it | ||
133 | if v, ok := w.values[k]; ok { | ||
134 | return v, nil | ||
135 | } | ||
136 | |||
137 | // If we're closed, return that | ||
138 | if w.closed { | ||
139 | return ErrClosed, nil | ||
140 | } | ||
141 | |||
142 | // No pending value, check for a waiter | ||
143 | val := w.waiters[k] | ||
144 | if val == nil { | ||
145 | val = new(Value) | ||
146 | w.waiters[k] = val | ||
147 | } | ||
148 | |||
149 | // Return the waiter | ||
150 | return nil, val | ||
151 | } | ||
diff --git a/vendor/github.com/hashicorp/terraform/helper/shadow/ordered_value.go b/vendor/github.com/hashicorp/terraform/helper/shadow/ordered_value.go new file mode 100644 index 0000000..0a43d4d --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/helper/shadow/ordered_value.go | |||
@@ -0,0 +1,66 @@ | |||
1 | package shadow | ||
2 | |||
3 | import ( | ||
4 | "container/list" | ||
5 | "sync" | ||
6 | ) | ||
7 | |||
8 | // OrderedValue is a struct that keeps track of a value in the order | ||
9 | // it is set. Each time Value() is called, it will return the most recent | ||
10 | // calls value then discard it. | ||
11 | // | ||
12 | // This is unlike Value that returns the same value once it is set. | ||
13 | type OrderedValue struct { | ||
14 | lock sync.Mutex | ||
15 | values *list.List | ||
16 | waiters *list.List | ||
17 | } | ||
18 | |||
19 | // Value returns the last value that was set, or blocks until one | ||
20 | // is received. | ||
21 | func (w *OrderedValue) Value() interface{} { | ||
22 | w.lock.Lock() | ||
23 | |||
24 | // If we have a pending value already, use it | ||
25 | if w.values != nil && w.values.Len() > 0 { | ||
26 | front := w.values.Front() | ||
27 | w.values.Remove(front) | ||
28 | w.lock.Unlock() | ||
29 | return front.Value | ||
30 | } | ||
31 | |||
32 | // No pending value, create a waiter | ||
33 | if w.waiters == nil { | ||
34 | w.waiters = list.New() | ||
35 | } | ||
36 | |||
37 | var val Value | ||
38 | w.waiters.PushBack(&val) | ||
39 | w.lock.Unlock() | ||
40 | |||
41 | // Return the value once we have it | ||
42 | return val.Value() | ||
43 | } | ||
44 | |||
45 | // SetValue sets the latest value. | ||
46 | func (w *OrderedValue) SetValue(v interface{}) { | ||
47 | w.lock.Lock() | ||
48 | defer w.lock.Unlock() | ||
49 | |||
50 | // If we have a waiter, notify it | ||
51 | if w.waiters != nil && w.waiters.Len() > 0 { | ||
52 | front := w.waiters.Front() | ||
53 | w.waiters.Remove(front) | ||
54 | |||
55 | val := front.Value.(*Value) | ||
56 | val.SetValue(v) | ||
57 | return | ||
58 | } | ||
59 | |||
60 | // Add it to the list of values | ||
61 | if w.values == nil { | ||
62 | w.values = list.New() | ||
63 | } | ||
64 | |||
65 | w.values.PushBack(v) | ||
66 | } | ||
diff --git a/vendor/github.com/hashicorp/terraform/helper/shadow/value.go b/vendor/github.com/hashicorp/terraform/helper/shadow/value.go new file mode 100644 index 0000000..2413335 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/helper/shadow/value.go | |||
@@ -0,0 +1,79 @@ | |||
1 | package shadow | ||
2 | |||
3 | import ( | ||
4 | "errors" | ||
5 | "sync" | ||
6 | ) | ||
7 | |||
8 | // ErrClosed is returned by any closed values. | ||
9 | // | ||
10 | // A "closed value" is when the shadow has been notified that the real | ||
11 | // side is complete and any blocking values will _never_ be satisfied | ||
12 | // in the future. In this case, this error is returned. If a value is already | ||
13 | // available, that is still returned. | ||
14 | var ErrClosed = errors.New("shadow closed") | ||
15 | |||
16 | // Value is a struct that coordinates a value between two | ||
17 | // parallel routines. It is similar to atomic.Value except that when | ||
18 | // Value is called if it isn't set it will wait for it. | ||
19 | // | ||
20 | // The Value can be closed with Close, which will cause any future | ||
21 | // blocking operations to return immediately with ErrClosed. | ||
22 | type Value struct { | ||
23 | lock sync.Mutex | ||
24 | cond *sync.Cond | ||
25 | value interface{} | ||
26 | valueSet bool | ||
27 | } | ||
28 | |||
29 | // Close closes the value. This can never fail. For a definition of | ||
30 | // "close" see the struct docs. | ||
31 | func (w *Value) Close() error { | ||
32 | w.lock.Lock() | ||
33 | set := w.valueSet | ||
34 | w.lock.Unlock() | ||
35 | |||
36 | // If we haven't set the value, set it | ||
37 | if !set { | ||
38 | w.SetValue(ErrClosed) | ||
39 | } | ||
40 | |||
41 | // Done | ||
42 | return nil | ||
43 | } | ||
44 | |||
45 | // Value returns the value that was set. | ||
46 | func (w *Value) Value() interface{} { | ||
47 | w.lock.Lock() | ||
48 | defer w.lock.Unlock() | ||
49 | |||
50 | // If we already have a value just return | ||
51 | for !w.valueSet { | ||
52 | // No value, setup the condition variable if we have to | ||
53 | if w.cond == nil { | ||
54 | w.cond = sync.NewCond(&w.lock) | ||
55 | } | ||
56 | |||
57 | // Wait on it | ||
58 | w.cond.Wait() | ||
59 | } | ||
60 | |||
61 | // Return the value | ||
62 | return w.value | ||
63 | } | ||
64 | |||
65 | // SetValue sets the value. | ||
66 | func (w *Value) SetValue(v interface{}) { | ||
67 | w.lock.Lock() | ||
68 | defer w.lock.Unlock() | ||
69 | |||
70 | // Set the value | ||
71 | w.valueSet = true | ||
72 | w.value = v | ||
73 | |||
74 | // If we have a condition, clear it | ||
75 | if w.cond != nil { | ||
76 | w.cond.Broadcast() | ||
77 | w.cond = nil | ||
78 | } | ||
79 | } | ||