| package local |
| |
| import ( |
| "errors" |
| "fmt" |
| "io/ioutil" |
| "os" |
| "path/filepath" |
| "sync" |
| |
| "github.com/docker/docker/volume" |
| ) |
| |
| func New(rootDirectory string) (*Root, error) { |
| if err := os.MkdirAll(rootDirectory, 0700); err != nil { |
| return nil, err |
| } |
| r := &Root{ |
| path: rootDirectory, |
| volumes: make(map[string]*Volume), |
| } |
| dirs, err := ioutil.ReadDir(rootDirectory) |
| if err != nil { |
| return nil, err |
| } |
| for _, d := range dirs { |
| name := filepath.Base(d.Name()) |
| r.volumes[name] = &Volume{ |
| driverName: r.Name(), |
| name: name, |
| path: filepath.Join(rootDirectory, name), |
| } |
| } |
| return r, nil |
| } |
| |
| type Root struct { |
| m sync.Mutex |
| path string |
| volumes map[string]*Volume |
| } |
| |
| func (r *Root) Name() string { |
| return "local" |
| } |
| |
| func (r *Root) Create(name string) (volume.Volume, error) { |
| r.m.Lock() |
| defer r.m.Unlock() |
| v, exists := r.volumes[name] |
| if !exists { |
| path := filepath.Join(r.path, name) |
| if err := os.Mkdir(path, 0755); err != nil { |
| if os.IsExist(err) { |
| return nil, fmt.Errorf("volume already exists under %s", path) |
| } |
| return nil, err |
| } |
| v = &Volume{ |
| driverName: r.Name(), |
| name: name, |
| path: path, |
| } |
| r.volumes[name] = v |
| } |
| v.use() |
| return v, nil |
| } |
| |
| func (r *Root) Remove(v volume.Volume) error { |
| r.m.Lock() |
| defer r.m.Unlock() |
| lv, ok := v.(*Volume) |
| if !ok { |
| return errors.New("unknown volume type") |
| } |
| lv.release() |
| if lv.usedCount == 0 { |
| delete(r.volumes, lv.name) |
| return os.RemoveAll(lv.path) |
| } |
| return nil |
| } |
| |
| type Volume struct { |
| m sync.Mutex |
| usedCount int |
| // unique name of the volume |
| name string |
| // path is the path on the host where the data lives |
| path string |
| // driverName is the name of the driver that created the volume. |
| driverName string |
| } |
| |
| func (v *Volume) Name() string { |
| return v.name |
| } |
| |
| func (v *Volume) DriverName() string { |
| return v.driverName |
| } |
| |
| func (v *Volume) Path() string { |
| return v.path |
| } |
| |
| func (v *Volume) Mount() (string, error) { |
| return v.path, nil |
| } |
| |
| func (v *Volume) Unmount() error { |
| return nil |
| } |
| |
| func (v *Volume) use() { |
| v.m.Lock() |
| v.usedCount++ |
| v.m.Unlock() |
| } |
| |
| func (v *Volume) release() { |
| v.m.Lock() |
| v.usedCount-- |
| v.m.Unlock() |
| } |