| package libcontainerd |
| |
| import ( |
| "fmt" |
| "sync" |
| |
| "github.com/Sirupsen/logrus" |
| ) |
| |
| // clientCommon contains the platform agnostic fields used in the client structure |
| type clientCommon struct { |
| backend Backend |
| containers map[string]*container |
| containerMutexes map[string]*sync.Mutex // lock by container ID |
| mapMutex sync.RWMutex // protects read/write oprations from containers map |
| sync.Mutex // lock for containerMutexes map access |
| } |
| |
| func (clnt *client) lock(containerID string) { |
| clnt.Lock() |
| if _, ok := clnt.containerMutexes[containerID]; !ok { |
| clnt.containerMutexes[containerID] = &sync.Mutex{} |
| } |
| clnt.Unlock() |
| clnt.containerMutexes[containerID].Lock() |
| } |
| |
| func (clnt *client) unlock(containerID string) { |
| clnt.Lock() |
| if l, ok := clnt.containerMutexes[containerID]; ok { |
| l.Unlock() |
| } else { |
| logrus.Warnf("unlock of non-existing mutex: %s", containerID) |
| } |
| clnt.Unlock() |
| } |
| |
| // must hold a lock for cont.containerID |
| func (clnt *client) appendContainer(cont *container) { |
| clnt.mapMutex.Lock() |
| clnt.containers[cont.containerID] = cont |
| clnt.mapMutex.Unlock() |
| } |
| func (clnt *client) deleteContainer(friendlyName string) { |
| clnt.mapMutex.Lock() |
| delete(clnt.containers, friendlyName) |
| clnt.mapMutex.Unlock() |
| } |
| |
| func (clnt *client) getContainer(containerID string) (*container, error) { |
| clnt.mapMutex.RLock() |
| container, ok := clnt.containers[containerID] |
| defer clnt.mapMutex.RUnlock() |
| if !ok { |
| return nil, fmt.Errorf("invalid container: %s", containerID) // fixme: typed error |
| } |
| return container, nil |
| } |