Merge pull request #729 from vmarmol/watches

Report the last cgroup destroy event.
This commit is contained in:
Rohit Jnagal 2015-05-21 11:24:05 -06:00
commit a6c31d4074
2 changed files with 34 additions and 27 deletions

View File

@ -473,18 +473,18 @@ func (self *rawContainerHandler) processEvent(event *inotify.Event, events chan
} }
// Only report container creation once. // Only report container creation once.
if !alreadyWatched { if alreadyWatched {
return nil return nil
} }
case eventType == container.SubcontainerDelete: case eventType == container.SubcontainerDelete:
// Container was deleted, stop watching for it. // Container was deleted, stop watching for it.
wasWatched, err := self.watcher.RemoveWatch(containerName, event.Name) lastWatched, err := self.watcher.RemoveWatch(containerName, event.Name)
if err != nil { if err != nil {
return err return err
} }
// Only report container deletion once. // Only report container deletion once.
if wasWatched { if !lastWatched {
return nil return nil
} }
default: default:

View File

@ -27,11 +27,8 @@ type InotifyWatcher struct {
// Underlying inotify watcher. // Underlying inotify watcher.
watcher *inotify.Watcher watcher *inotify.Watcher
// Containers being watched. // Map of containers being watched to cgroup paths watched for that container.
containersWatched map[string]bool containersWatched map[string]map[string]bool
// Full cgroup paths being watched.
cgroupsWatched map[string]bool
// Lock for all datastructure access. // Lock for all datastructure access.
lock sync.Mutex lock sync.Mutex
@ -45,8 +42,7 @@ func NewInotifyWatcher() (*InotifyWatcher, error) {
return &InotifyWatcher{ return &InotifyWatcher{
watcher: w, watcher: w,
containersWatched: make(map[string]bool), containersWatched: make(map[string]map[string]bool),
cgroupsWatched: make(map[string]bool),
}, nil }, nil
} }
@ -55,46 +51,55 @@ func (iw *InotifyWatcher) AddWatch(containerName, dir string) (bool, error) {
iw.lock.Lock() iw.lock.Lock()
defer iw.lock.Unlock() defer iw.lock.Unlock()
alreadyWatched := iw.containersWatched[containerName] cgroupsWatched, alreadyWatched := iw.containersWatched[containerName]
// Register an inotify notification. // Register an inotify notification.
if !iw.cgroupsWatched[dir] { if !cgroupsWatched[dir] {
err := iw.watcher.AddWatch(dir, inotify.IN_CREATE|inotify.IN_DELETE|inotify.IN_MOVE) err := iw.watcher.AddWatch(dir, inotify.IN_CREATE|inotify.IN_DELETE|inotify.IN_MOVE)
if err != nil { if err != nil {
return alreadyWatched, err return alreadyWatched, err
} }
iw.cgroupsWatched[dir] = true
if cgroupsWatched == nil {
cgroupsWatched = make(map[string]bool)
}
cgroupsWatched[dir] = true
} }
// Record our watching of the container. // Record our watching of the container.
if !alreadyWatched { if !alreadyWatched {
iw.containersWatched[containerName] = true iw.containersWatched[containerName] = cgroupsWatched
} }
return alreadyWatched, nil return alreadyWatched, nil
} }
// Remove watch from the specified directory. Returns if the container was already being watched. // Remove watch from the specified directory. Returns if this was the last watch on the specified container.
func (iw *InotifyWatcher) RemoveWatch(containerName, dir string) (bool, error) { func (iw *InotifyWatcher) RemoveWatch(containerName, dir string) (bool, error) {
iw.lock.Lock() iw.lock.Lock()
defer iw.lock.Unlock() defer iw.lock.Unlock()
alreadyWatched := iw.containersWatched[containerName] // If we don't have a watch registed for this, just return.
cgroupsWatched, ok := iw.containersWatched[containerName]
if !ok {
return false, nil
}
// Remove the inotify watch if it exists. // Remove the inotify watch if it exists.
if iw.cgroupsWatched[dir] { if cgroupsWatched[dir] {
err := iw.watcher.RemoveWatch(dir) err := iw.watcher.RemoveWatch(dir)
if err != nil { if err != nil {
return alreadyWatched, nil return false, nil
} }
delete(iw.cgroupsWatched, dir) delete(cgroupsWatched, dir)
} }
// Record the container as no longer being watched. // Remove the record if this is the last watch.
if alreadyWatched { if len(cgroupsWatched) == 0 {
delete(iw.containersWatched, containerName) delete(iw.containersWatched, containerName)
return true, nil
} }
return alreadyWatched, nil return false, nil
} }
// Errors are returned on this channel. // Errors are returned on this channel.
@ -112,11 +117,13 @@ func (iw *InotifyWatcher) Close() error {
return iw.watcher.Close() return iw.watcher.Close()
} }
// Returns a list of: // Returns a map of containers to the cgroup paths being watched.
// - Containers being watched. func (iw *InotifyWatcher) GetWatches() map[string][]string {
// - Cgroup paths being watched. out := make(map[string][]string, len(iw.containersWatched))
func (iw *InotifyWatcher) GetWatches() ([]string, []string) { for k, v := range iw.containersWatched {
return mapToSlice(iw.containersWatched), mapToSlice(iw.cgroupsWatched) out[k] = mapToSlice(v)
}
return out
} }
func mapToSlice(m map[string]bool) []string { func mapToSlice(m map[string]bool) []string {