dotcloud/docker

View on GitHub
daemon/internal/mountref/counter.go

Summary

Maintainability
A
0 mins
Test Coverage
package mountref

import "sync"

type minfo struct {
    check bool
    count int
}

// Counter is a generic counter for use by graphdriver Get/Put calls
type Counter struct {
    counts    map[string]*minfo
    mu        sync.Mutex
    isMounted Checker
}

// Checker checks whether the provided path is mounted.
type Checker func(path string) bool

// NewCounter returns a new Counter. It accepts a [Checker] to
// determine whether a path is mounted.
func NewCounter(c Checker) *Counter {
    return &Counter{
        isMounted: c,
        counts:    make(map[string]*minfo),
    }
}

// Increment increases the ref count for the given id and returns the current count
func (c *Counter) 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 *Counter) Decrement(path string) int {
    return c.incdec(path, func(minfo *minfo) {
        minfo.count--
    })
}

func (c *Counter) 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.isMounted(path) {
            m.count++
        }
    }
    infoOp(m)
    count := m.count
    if count <= 0 {
        delete(c.counts, path)
    }
    c.mu.Unlock()
    return count
}