This patch makes it such that plugin initialization is synchronized
based on the plugin name and not globally
Signed-off-by: Darren Shepherd <darren@rancher.com>
| ... | ... |
@@ -63,6 +63,9 @@ type Plugin struct {
|
| 63 | 63 |
Client *Client `json:"-"` |
| 64 | 64 |
// Manifest of the plugin (see above) |
| 65 | 65 |
Manifest *Manifest `json:"-"` |
| 66 |
+ |
|
| 67 |
+ activatErr error |
|
| 68 |
+ activateOnce sync.Once |
|
| 66 | 69 |
} |
| 67 | 70 |
|
| 68 | 71 |
func newLocalPlugin(name, addr string) *Plugin {
|
| ... | ... |
@@ -74,6 +77,13 @@ func newLocalPlugin(name, addr string) *Plugin {
|
| 74 | 74 |
} |
| 75 | 75 |
|
| 76 | 76 |
func (p *Plugin) activate() error {
|
| 77 |
+ p.activateOnce.Do(func() {
|
|
| 78 |
+ p.activatErr = p.activateWithLock() |
|
| 79 |
+ }) |
|
| 80 |
+ return p.activatErr |
|
| 81 |
+} |
|
| 82 |
+ |
|
| 83 |
+func (p *Plugin) activateWithLock() error {
|
|
| 77 | 84 |
c, err := NewClient(p.Addr, p.TLSConfig) |
| 78 | 85 |
if err != nil {
|
| 79 | 86 |
return err |
| ... | ... |
@@ -99,32 +109,37 @@ func (p *Plugin) activate() error {
|
| 99 | 99 |
} |
| 100 | 100 |
|
| 101 | 101 |
func load(name string) (*Plugin, error) {
|
| 102 |
+ storage.Lock() |
|
| 102 | 103 |
registry := newLocalRegistry() |
| 103 | 104 |
pl, err := registry.Plugin(name) |
| 105 |
+ if err == nil {
|
|
| 106 |
+ storage.plugins[name] = pl |
|
| 107 |
+ } |
|
| 108 |
+ storage.Unlock() |
|
| 109 |
+ |
|
| 104 | 110 |
if err != nil {
|
| 105 | 111 |
return nil, err |
| 106 | 112 |
} |
| 107 |
- if err := pl.activate(); err != nil {
|
|
| 108 |
- return nil, err |
|
| 113 |
+ |
|
| 114 |
+ err = pl.activate() |
|
| 115 |
+ |
|
| 116 |
+ if err != nil {
|
|
| 117 |
+ storage.Lock() |
|
| 118 |
+ delete(storage.plugins, name) |
|
| 119 |
+ storage.Unlock() |
|
| 109 | 120 |
} |
| 110 |
- return pl, nil |
|
| 121 |
+ |
|
| 122 |
+ return pl, err |
|
| 111 | 123 |
} |
| 112 | 124 |
|
| 113 | 125 |
func get(name string) (*Plugin, error) {
|
| 114 | 126 |
storage.Lock() |
| 115 |
- defer storage.Unlock() |
|
| 116 | 127 |
pl, ok := storage.plugins[name] |
| 128 |
+ storage.Unlock() |
|
| 117 | 129 |
if ok {
|
| 118 |
- return pl, nil |
|
| 130 |
+ return pl, pl.activate() |
|
| 119 | 131 |
} |
| 120 |
- pl, err := load(name) |
|
| 121 |
- if err != nil {
|
|
| 122 |
- return nil, err |
|
| 123 |
- } |
|
| 124 |
- |
|
| 125 |
- logrus.Debugf("Plugin: %v", pl)
|
|
| 126 |
- storage.plugins[name] = pl |
|
| 127 |
- return pl, nil |
|
| 132 |
+ return load(name) |
|
| 128 | 133 |
} |
| 129 | 134 |
|
| 130 | 135 |
// Get returns the plugin given the specified name and requested implementation. |
| ... | ... |
@@ -51,8 +51,8 @@ func Unregister(name string) bool {
|
| 51 | 51 |
// there is a VolumeDriver plugin available with the given name. |
| 52 | 52 |
func Lookup(name string) (volume.Driver, error) {
|
| 53 | 53 |
drivers.Lock() |
| 54 |
- defer drivers.Unlock() |
|
| 55 | 54 |
ext, ok := drivers.extensions[name] |
| 55 |
+ drivers.Unlock() |
|
| 56 | 56 |
if ok {
|
| 57 | 57 |
return ext, nil |
| 58 | 58 |
} |
| ... | ... |
@@ -61,6 +61,12 @@ func Lookup(name string) (volume.Driver, error) {
|
| 61 | 61 |
return nil, fmt.Errorf("Error looking up volume plugin %s: %v", name, err)
|
| 62 | 62 |
} |
| 63 | 63 |
|
| 64 |
+ drivers.Lock() |
|
| 65 |
+ defer drivers.Unlock() |
|
| 66 |
+ if ext, ok := drivers.extensions[name]; ok {
|
|
| 67 |
+ return ext, nil |
|
| 68 |
+ } |
|
| 69 |
+ |
|
| 64 | 70 |
d := NewVolumeDriver(name, pl.Client) |
| 65 | 71 |
drivers.extensions[name] = d |
| 66 | 72 |
return d, nil |