| package graphdriver // import "github.com/docker/docker/daemon/graphdriver" |
| |
| import "sync" |
| |
| type minfo struct { |
| check bool |
| count int |
| } |
| |
| // RefCounter is a generic counter for use by graphdriver Get/Put calls |
| type RefCounter struct { |
| counts map[string]*minfo |
| mu sync.Mutex |
| checker Checker |
| } |
| |
| // NewRefCounter returns a new RefCounter |
| func NewRefCounter(c Checker) *RefCounter { |
| return &RefCounter{ |
| checker: c, |
| counts: make(map[string]*minfo), |
| } |
| } |
| |
| // Increment increases the ref count for the given id and returns the current count |
| func (c *RefCounter) Increment(path string) int { |
| return c.incdec(path, func(minfo *minfo) { |
| minfo.count++ |
| }) |
| } |
| |
| // Decrement decreases the ref count for the given id and returns the current count |
| func (c *RefCounter) Decrement(path string) int { |
| return c.incdec(path, func(minfo *minfo) { |
| minfo.count-- |
| }) |
| } |
| |
| func (c *RefCounter) incdec(path string, infoOp func(minfo *minfo)) int { |
| c.mu.Lock() |
| m := c.counts[path] |
| if m == nil { |
| m = &minfo{} |
| c.counts[path] = m |
| } |
| // if we are checking this path for the first time check to make sure |
| // if it was already mounted on the system and make sure we have a correct ref |
| // count if it is mounted as it is in use. |
| if !m.check { |
| m.check = true |
| if c.checker.IsMounted(path) { |
| m.count++ |
| } |
| } |
| infoOp(m) |
| count := m.count |
| if count <= 0 { |
| delete(c.counts, path) |
| } |
| c.mu.Unlock() |
| return count |
| } |