mirror of
https://github.com/bcicen/ctop.git
synced 2025-12-06 15:16:41 +08:00
further containermap refactoring
This commit is contained in:
@@ -2,12 +2,16 @@ package main
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/bcicen/ctop/config"
|
||||
"github.com/bcicen/ctop/metrics"
|
||||
"github.com/fsouza/go-dockerclient"
|
||||
)
|
||||
|
||||
var lock = sync.RWMutex{}
|
||||
|
||||
type ContainerMap struct {
|
||||
client *docker.Client
|
||||
containers Containers
|
||||
@@ -27,32 +31,29 @@ func NewContainerMap() *ContainerMap {
|
||||
needsRefresh: make(map[string]int),
|
||||
}
|
||||
cm.refreshAll()
|
||||
go cm.watch()
|
||||
go cm.UpdateLoop()
|
||||
go cm.watchEvents()
|
||||
return cm
|
||||
}
|
||||
|
||||
// Docker events watcher
|
||||
func (cm *ContainerMap) watch() {
|
||||
func (cm *ContainerMap) watchEvents() {
|
||||
log.Info("docker event listener starting")
|
||||
events := make(chan *docker.APIEvents)
|
||||
cm.client.AddEventListener(events)
|
||||
|
||||
for e := range events {
|
||||
cm.handleEvent(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Docker event handler
|
||||
func (cm *ContainerMap) handleEvent(e *docker.APIEvents) {
|
||||
// only process container events
|
||||
if e.Type != "container" {
|
||||
return
|
||||
}
|
||||
switch e.Action {
|
||||
case "start", "die", "pause", "unpause":
|
||||
cm.needsRefresh[e.ID] = 1
|
||||
case "destroy":
|
||||
cm.DelByID(e.ID)
|
||||
if e.Type != "container" {
|
||||
continue
|
||||
}
|
||||
switch e.Action {
|
||||
case "start", "die", "pause", "unpause":
|
||||
log.Debugf("handling docker event: action=%s id=%s", e.Action, e.ID)
|
||||
cm.needsRefresh[e.ID] = 1
|
||||
case "destroy":
|
||||
log.Debugf("handling docker event: action=%s id=%s", e.Action, e.ID)
|
||||
cm.DelByID(e.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,12 +68,10 @@ func (cm *ContainerMap) refresh(id string) {
|
||||
c, ok := cm.Get(id)
|
||||
// append container struct for new containers
|
||||
if !ok {
|
||||
c = &Container{
|
||||
id: id,
|
||||
name: insp.Name,
|
||||
}
|
||||
c.Collapse()
|
||||
c = NewContainer(id, insp.Name)
|
||||
lock.Lock()
|
||||
cm.containers = append(cm.containers, c)
|
||||
lock.Unlock()
|
||||
// create collector
|
||||
if _, ok := cm.collectors[id]; ok == false {
|
||||
cm.collectors[id] = metrics.NewDocker(cm.client, id)
|
||||
@@ -86,6 +85,10 @@ func (cm *ContainerMap) refresh(id string) {
|
||||
cm.collectors[c.id].Start()
|
||||
c.Read(cm.collectors[c.id].Stream())
|
||||
}
|
||||
// stop collector if needed
|
||||
if c.state != "running" && cm.collectors[c.id].Running() {
|
||||
cm.collectors[c.id].Stop()
|
||||
}
|
||||
}
|
||||
|
||||
func (cm *ContainerMap) inspect(id string) *docker.Container {
|
||||
@@ -108,29 +111,26 @@ func (cm *ContainerMap) refreshAll() {
|
||||
for _, c := range allContainers {
|
||||
cm.needsRefresh[c.ID] = 1
|
||||
}
|
||||
cm.Update()
|
||||
}
|
||||
|
||||
func (cm *ContainerMap) Update() {
|
||||
var ids []string
|
||||
for id, _ := range cm.needsRefresh {
|
||||
cm.refresh(id)
|
||||
ids = append(ids, id)
|
||||
}
|
||||
for _, id := range ids {
|
||||
delete(cm.needsRefresh, id)
|
||||
func (cm *ContainerMap) UpdateLoop() {
|
||||
for {
|
||||
switch {
|
||||
case len(cm.needsRefresh) > 0:
|
||||
processed := []string{}
|
||||
for id, _ := range cm.needsRefresh {
|
||||
cm.refresh(id)
|
||||
processed = append(processed, id)
|
||||
}
|
||||
for _, id := range processed {
|
||||
delete(cm.needsRefresh, id)
|
||||
}
|
||||
default:
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Kill a container by ID
|
||||
//func (cm *ContainerMap) Kill(id string, sig docker.Signal) error {
|
||||
//opts := docker.KillContainerOptions{
|
||||
//ID: id,
|
||||
//Signal: sig,
|
||||
//}
|
||||
//return cm.client.KillContainer(opts)
|
||||
//}
|
||||
|
||||
// Return number of containers/rows
|
||||
func (cm *ContainerMap) Len() uint {
|
||||
return uint(len(cm.containers))
|
||||
@@ -158,9 +158,12 @@ func (cm *ContainerMap) DelByID(id string) {
|
||||
|
||||
// Remove one or more containers by index
|
||||
func (cm *ContainerMap) Del(idx ...int) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
for _, i := range idx {
|
||||
cm.containers = append(cm.containers[:i], cm.containers[i+1:]...)
|
||||
}
|
||||
log.Infof("removed %d dead containers", len(idx))
|
||||
}
|
||||
|
||||
// Return array of all containers, sorted by field
|
||||
|
||||
Reference in New Issue
Block a user