This helps ensure that only one thing is trying to intialize a plugin at
once while also keeping the global lock free during initialization.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
| ... | ... |
@@ -6,6 +6,7 @@ import ( |
| 6 | 6 |
"fmt" |
| 7 | 7 |
"sync" |
| 8 | 8 |
|
| 9 |
+ "github.com/docker/docker/pkg/locker" |
|
| 9 | 10 |
"github.com/docker/docker/pkg/plugins" |
| 10 | 11 |
"github.com/docker/docker/volume" |
| 11 | 12 |
) |
| ... | ... |
@@ -13,7 +14,7 @@ import ( |
| 13 | 13 |
// currently created by hand. generation tool would generate this like: |
| 14 | 14 |
// $ extpoint-gen Driver > volume/extpoint.go |
| 15 | 15 |
|
| 16 |
-var drivers = &driverExtpoint{extensions: make(map[string]volume.Driver)}
|
|
| 16 |
+var drivers = &driverExtpoint{extensions: make(map[string]volume.Driver), driverLock: &locker.Locker{}}
|
|
| 17 | 17 |
|
| 18 | 18 |
const extName = "VolumeDriver" |
| 19 | 19 |
|
| ... | ... |
@@ -49,16 +50,19 @@ type volumeDriver interface {
|
| 49 | 49 |
type driverExtpoint struct {
|
| 50 | 50 |
extensions map[string]volume.Driver |
| 51 | 51 |
sync.Mutex |
| 52 |
+ driverLock *locker.Locker |
|
| 52 | 53 |
} |
| 53 | 54 |
|
| 54 | 55 |
// Register associates the given driver to the given name, checking if |
| 55 | 56 |
// the name is already associated |
| 56 | 57 |
func Register(extension volume.Driver, name string) bool {
|
| 57 |
- drivers.Lock() |
|
| 58 |
- defer drivers.Unlock() |
|
| 59 | 58 |
if name == "" {
|
| 60 | 59 |
return false |
| 61 | 60 |
} |
| 61 |
+ |
|
| 62 |
+ drivers.Lock() |
|
| 63 |
+ defer drivers.Unlock() |
|
| 64 |
+ |
|
| 62 | 65 |
_, exists := drivers.extensions[name] |
| 63 | 66 |
if exists {
|
| 64 | 67 |
return false |
| ... | ... |
@@ -71,6 +75,7 @@ func Register(extension volume.Driver, name string) bool {
|
| 71 | 71 |
func Unregister(name string) bool {
|
| 72 | 72 |
drivers.Lock() |
| 73 | 73 |
defer drivers.Unlock() |
| 74 |
+ |
|
| 74 | 75 |
_, exists := drivers.extensions[name] |
| 75 | 76 |
if !exists {
|
| 76 | 77 |
return false |
| ... | ... |
@@ -83,12 +88,16 @@ func Unregister(name string) bool {
|
| 83 | 83 |
// driver with the given name has not been registered it checks if |
| 84 | 84 |
// there is a VolumeDriver plugin available with the given name. |
| 85 | 85 |
func Lookup(name string) (volume.Driver, error) {
|
| 86 |
+ drivers.driverLock.Lock(name) |
|
| 87 |
+ defer drivers.driverLock.Unlock(name) |
|
| 88 |
+ |
|
| 86 | 89 |
drivers.Lock() |
| 87 | 90 |
ext, ok := drivers.extensions[name] |
| 88 | 91 |
drivers.Unlock() |
| 89 | 92 |
if ok {
|
| 90 | 93 |
return ext, nil |
| 91 | 94 |
} |
| 95 |
+ |
|
| 92 | 96 |
pl, err := plugins.Get(name, extName) |
| 93 | 97 |
if err != nil {
|
| 94 | 98 |
return nil, fmt.Errorf("Error looking up volume plugin %s: %v", name, err)
|
| ... | ... |
@@ -118,9 +127,11 @@ func GetDriver(name string) (volume.Driver, error) {
|
| 118 | 118 |
// If no driver is registered, empty string list will be returned. |
| 119 | 119 |
func GetDriverList() []string {
|
| 120 | 120 |
var driverList []string |
| 121 |
+ drivers.Lock() |
|
| 121 | 122 |
for driverName := range drivers.extensions {
|
| 122 | 123 |
driverList = append(driverList, driverName) |
| 123 | 124 |
} |
| 125 |
+ drivers.Unlock() |
|
| 124 | 126 |
return driverList |
| 125 | 127 |
} |
| 126 | 128 |
|
| ... | ... |
@@ -144,6 +155,7 @@ func GetAllDrivers() ([]volume.Driver, error) {
|
| 144 | 144 |
if ok {
|
| 145 | 145 |
continue |
| 146 | 146 |
} |
| 147 |
+ |
|
| 147 | 148 |
ext = NewVolumeDriver(p.Name, p.Client) |
| 148 | 149 |
drivers.extensions[p.Name] = ext |
| 149 | 150 |
ds = append(ds, ext) |