Browse code

Don't globally lock on driver initialization

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>

Darren Shepherd authored on 2015/08/19 14:04:22
Showing 2 changed files
... ...
@@ -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