github.com/tompao/docker@v1.9.1/daemon/events/events.go (about) 1 package events 2 3 import ( 4 "sync" 5 "time" 6 7 "github.com/docker/docker/pkg/jsonmessage" 8 "github.com/docker/docker/pkg/pubsub" 9 ) 10 11 const eventsLimit = 64 12 13 // Events is pubsub channel for *jsonmessage.JSONMessage 14 type Events struct { 15 mu sync.Mutex 16 events []*jsonmessage.JSONMessage 17 pub *pubsub.Publisher 18 } 19 20 // New returns new *Events instance 21 func New() *Events { 22 return &Events{ 23 events: make([]*jsonmessage.JSONMessage, 0, eventsLimit), 24 pub: pubsub.NewPublisher(100*time.Millisecond, 1024), 25 } 26 } 27 28 // Subscribe adds new listener to events, returns slice of 64 stored last events 29 // channel in which you can expect new events in form of interface{}, so you 30 // need type assertion. 31 func (e *Events) Subscribe() ([]*jsonmessage.JSONMessage, chan interface{}) { 32 e.mu.Lock() 33 current := make([]*jsonmessage.JSONMessage, len(e.events)) 34 copy(current, e.events) 35 l := e.pub.Subscribe() 36 e.mu.Unlock() 37 return current, l 38 } 39 40 // Evict evicts listener from pubsub 41 func (e *Events) Evict(l chan interface{}) { 42 e.pub.Evict(l) 43 } 44 45 // Log broadcasts event to listeners. Each listener has 100 millisecond for 46 // receiving event or it will be skipped. 47 func (e *Events) Log(action, id, from string) { 48 now := time.Now().UTC() 49 jm := &jsonmessage.JSONMessage{Status: action, ID: id, From: from, Time: now.Unix(), TimeNano: now.UnixNano()} 50 e.mu.Lock() 51 if len(e.events) == cap(e.events) { 52 // discard oldest event 53 copy(e.events, e.events[1:]) 54 e.events[len(e.events)-1] = jm 55 } else { 56 e.events = append(e.events, jm) 57 } 58 e.mu.Unlock() 59 e.pub.Publish(jm) 60 } 61 62 // SubscribersCount returns number of event listeners 63 func (e *Events) SubscribersCount() int { 64 return e.pub.Len() 65 }