github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/daemon/events/events.go (about)

     1  package events // import "github.com/demonoid81/moby/daemon/events"
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  
     7  	eventtypes "github.com/demonoid81/moby/api/types/events"
     8  	"github.com/demonoid81/moby/pkg/pubsub"
     9  )
    10  
    11  const (
    12  	eventsLimit = 256
    13  	bufferSize  = 1024
    14  )
    15  
    16  // Events is pubsub channel for events generated by the engine.
    17  type Events struct {
    18  	mu     sync.Mutex
    19  	events []eventtypes.Message
    20  	pub    *pubsub.Publisher
    21  }
    22  
    23  // New returns new *Events instance
    24  func New() *Events {
    25  	return &Events{
    26  		events: make([]eventtypes.Message, 0, eventsLimit),
    27  		pub:    pubsub.NewPublisher(100*time.Millisecond, bufferSize),
    28  	}
    29  }
    30  
    31  // Subscribe adds new listener to events, returns slice of 256 stored
    32  // last events, a channel in which you can expect new events (in form
    33  // of interface{}, so you need type assertion), and a function to call
    34  // to stop the stream of events.
    35  func (e *Events) Subscribe() ([]eventtypes.Message, chan interface{}, func()) {
    36  	eventSubscribers.Inc()
    37  	e.mu.Lock()
    38  	current := make([]eventtypes.Message, len(e.events))
    39  	copy(current, e.events)
    40  	l := e.pub.Subscribe()
    41  	e.mu.Unlock()
    42  
    43  	cancel := func() {
    44  		e.Evict(l)
    45  	}
    46  	return current, l, cancel
    47  }
    48  
    49  // SubscribeTopic adds new listener to events, returns slice of 256 stored
    50  // last events, a channel in which you can expect new events (in form
    51  // of interface{}, so you need type assertion).
    52  func (e *Events) SubscribeTopic(since, until time.Time, ef *Filter) ([]eventtypes.Message, chan interface{}) {
    53  	eventSubscribers.Inc()
    54  	e.mu.Lock()
    55  
    56  	var topic func(m interface{}) bool
    57  	if ef != nil && ef.filter.Len() > 0 {
    58  		topic = func(m interface{}) bool { return ef.Include(m.(eventtypes.Message)) }
    59  	}
    60  
    61  	buffered := e.loadBufferedEvents(since, until, topic)
    62  
    63  	var ch chan interface{}
    64  	if topic != nil {
    65  		ch = e.pub.SubscribeTopic(topic)
    66  	} else {
    67  		// Subscribe to all events if there are no filters
    68  		ch = e.pub.Subscribe()
    69  	}
    70  
    71  	e.mu.Unlock()
    72  	return buffered, ch
    73  }
    74  
    75  // Evict evicts listener from pubsub
    76  func (e *Events) Evict(l chan interface{}) {
    77  	eventSubscribers.Dec()
    78  	e.pub.Evict(l)
    79  }
    80  
    81  // Log creates a local scope message and publishes it
    82  func (e *Events) Log(action, eventType string, actor eventtypes.Actor) {
    83  	now := time.Now().UTC()
    84  	jm := eventtypes.Message{
    85  		Action:   action,
    86  		Type:     eventType,
    87  		Actor:    actor,
    88  		Scope:    "local",
    89  		Time:     now.Unix(),
    90  		TimeNano: now.UnixNano(),
    91  	}
    92  
    93  	// fill deprecated fields for container and images
    94  	switch eventType {
    95  	case eventtypes.ContainerEventType:
    96  		jm.ID = actor.ID
    97  		jm.Status = action
    98  		jm.From = actor.Attributes["image"]
    99  	case eventtypes.ImageEventType:
   100  		jm.ID = actor.ID
   101  		jm.Status = action
   102  	}
   103  
   104  	e.PublishMessage(jm)
   105  }
   106  
   107  // PublishMessage broadcasts event to listeners. Each listener has 100 milliseconds to
   108  // receive the event or it will be skipped.
   109  func (e *Events) PublishMessage(jm eventtypes.Message) {
   110  	eventsCounter.Inc()
   111  
   112  	e.mu.Lock()
   113  	if len(e.events) == cap(e.events) {
   114  		// discard oldest event
   115  		copy(e.events, e.events[1:])
   116  		e.events[len(e.events)-1] = jm
   117  	} else {
   118  		e.events = append(e.events, jm)
   119  	}
   120  	e.mu.Unlock()
   121  	e.pub.Publish(jm)
   122  }
   123  
   124  // SubscribersCount returns number of event listeners
   125  func (e *Events) SubscribersCount() int {
   126  	return e.pub.Len()
   127  }
   128  
   129  // loadBufferedEvents iterates over the cached events in the buffer
   130  // and returns those that were emitted between two specific dates.
   131  // It uses `time.Unix(seconds, nanoseconds)` to generate valid dates with those arguments.
   132  // It filters those buffered messages with a topic function if it's not nil, otherwise it adds all messages.
   133  func (e *Events) loadBufferedEvents(since, until time.Time, topic func(interface{}) bool) []eventtypes.Message {
   134  	var buffered []eventtypes.Message
   135  	if since.IsZero() && until.IsZero() {
   136  		return buffered
   137  	}
   138  
   139  	var sinceNanoUnix int64
   140  	if !since.IsZero() {
   141  		sinceNanoUnix = since.UnixNano()
   142  	}
   143  
   144  	var untilNanoUnix int64
   145  	if !until.IsZero() {
   146  		untilNanoUnix = until.UnixNano()
   147  	}
   148  
   149  	for i := len(e.events) - 1; i >= 0; i-- {
   150  		ev := e.events[i]
   151  
   152  		if ev.TimeNano < sinceNanoUnix {
   153  			break
   154  		}
   155  
   156  		if untilNanoUnix > 0 && ev.TimeNano > untilNanoUnix {
   157  			continue
   158  		}
   159  
   160  		if topic == nil || topic(ev) {
   161  			buffered = append([]eventtypes.Message{ev}, buffered...)
   162  		}
   163  	}
   164  	return buffered
   165  }