github.com/zhyoulun/cilium@v1.6.12/pkg/kvstore/events.go (about)

     1  // Copyright 2016-2018 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package kvstore
    16  
    17  import (
    18  	"sync"
    19  )
    20  
    21  // EventType defines the type of watch event that occurred
    22  type EventType int
    23  
    24  const (
    25  	// EventTypeCreate represents a newly created key
    26  	EventTypeCreate EventType = iota
    27  	// EventTypeModify represents a modified key
    28  	EventTypeModify
    29  	// EventTypeDelete represents a deleted key
    30  	EventTypeDelete
    31  	//EventTypeListDone signals that the initial list operation has completed
    32  	EventTypeListDone
    33  )
    34  
    35  // String() returns the human readable format of an event type
    36  func (t EventType) String() string {
    37  	switch t {
    38  	case EventTypeCreate:
    39  		return "create"
    40  	case EventTypeModify:
    41  		return "modify"
    42  	case EventTypeDelete:
    43  		return "delete"
    44  	case EventTypeListDone:
    45  		return "listDone"
    46  	default:
    47  		return "unknown"
    48  	}
    49  }
    50  
    51  // KeyValueEvent is a change event for a Key/Value pair
    52  type KeyValueEvent struct {
    53  	// Typ is the type of event { EventTypeCreate | EventTypeModify | EventTypeDelete | EventTypeListDone }
    54  	Typ EventType
    55  
    56  	// Key is the kvstore key that changed
    57  	Key string
    58  
    59  	// Value is the kvstore value associated with the key
    60  	Value []byte
    61  }
    62  
    63  // EventChan is a channel to receive events on
    64  type EventChan chan KeyValueEvent
    65  
    66  // stopChan is the channel used to indicate stopping of the watcher
    67  type stopChan chan struct{}
    68  
    69  // Watcher represents a KVstore watcher
    70  type Watcher struct {
    71  	// Events is the channel to which change notifications will be sent to
    72  	Events EventChan
    73  
    74  	name      string
    75  	prefix    string
    76  	stopWatch stopChan
    77  
    78  	// stopOnce guarantees that Stop() is only called once
    79  	stopOnce sync.Once
    80  
    81  	// stopWait is the wait group to wait for watchers to exit gracefully
    82  	stopWait sync.WaitGroup
    83  }
    84  
    85  func newWatcher(name, prefix string, chanSize int) *Watcher {
    86  	w := &Watcher{
    87  		name:      name,
    88  		prefix:    prefix,
    89  		Events:    make(EventChan, chanSize),
    90  		stopWatch: make(stopChan),
    91  	}
    92  
    93  	w.stopWait.Add(1)
    94  
    95  	return w
    96  }
    97  
    98  // String returns the name of the wather
    99  func (w *Watcher) String() string {
   100  	return w.name
   101  }
   102  
   103  // ListAndWatch creates a new watcher which will watch the specified prefix for
   104  // changes. Before doing this, it will list the current keys matching the
   105  // prefix and report them as new keys. Name can be set to anything and is used
   106  // for logging messages. The Events channel is created with the specified
   107  // sizes. Upon every change observed, a KeyValueEvent will be sent to the
   108  // Events channel
   109  //
   110  // Returns a watcher structure plus a channel that is closed when the initial
   111  // list operation has been completed
   112  func ListAndWatch(name, prefix string, chanSize int) *Watcher {
   113  	return Client().ListAndWatch(name, prefix, chanSize)
   114  }
   115  
   116  // Stop stops a watcher previously created and started with Watch()
   117  func (w *Watcher) Stop() {
   118  	w.stopOnce.Do(func() {
   119  		close(w.stopWatch)
   120  		log.WithField(fieldWatcher, w).Debug("Stopped watcher")
   121  		w.stopWait.Wait()
   122  	})
   123  }