github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/watcher.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state
     5  
     6  import (
     7  	"fmt"
     8  	"reflect"
     9  	"regexp"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/juju/errors"
    14  	"github.com/juju/loggo"
    15  	"github.com/juju/utils/set"
    16  	"gopkg.in/juju/names.v2"
    17  	"gopkg.in/mgo.v2"
    18  	"gopkg.in/mgo.v2/bson"
    19  	"gopkg.in/tomb.v1"
    20  
    21  	"github.com/juju/juju/instance"
    22  	"github.com/juju/juju/mongo"
    23  	"github.com/juju/juju/state/watcher"
    24  	"github.com/juju/juju/state/workers"
    25  
    26  	// TODO(fwereade): 2015-11-18 lp:1517428
    27  	//
    28  	// This gets an import block of its own because it's such staggeringly bad
    29  	// practice. It's here because (1) it always has been, just not quite so
    30  	// explicitly and (2) even if we had the state watchers implemented as
    31  	// juju/watcher~s rather than juju/state/watcher~s -- which we don't, so
    32  	// it's misleading to use those *Chan types etc -- we don't yet have any
    33  	// ability to transform watcher output in the apiserver layer, so we're
    34  	// kinda stuck producing what we always have.
    35  	//
    36  	// See RelationUnitsWatcher below.
    37  	"github.com/juju/juju/apiserver/params"
    38  )
    39  
    40  var watchLogger = loggo.GetLogger("juju.state.watch")
    41  
    42  // Watcher is implemented by all watchers; the actual
    43  // changes channel is returned by a watcher-specific
    44  // Changes method.
    45  type Watcher interface {
    46  	// Kill asks the watcher to stop without waiting for it do so.
    47  	Kill()
    48  	// Wait waits for the watcher to die and returns any
    49  	// error encountered when it was running.
    50  	Wait() error
    51  	// Stop kills the watcher, then waits for it to die.
    52  	Stop() error
    53  	// Err returns any error encountered while the watcher
    54  	// has been running.
    55  	Err() error
    56  }
    57  
    58  // NotifyWatcher generates signals when something changes, but it does not
    59  // return any content for those changes
    60  type NotifyWatcher interface {
    61  	Watcher
    62  	Changes() <-chan struct{}
    63  }
    64  
    65  // StringsWatcher generates signals when something changes, returning
    66  // the changes as a list of strings.
    67  type StringsWatcher interface {
    68  	Watcher
    69  	Changes() <-chan []string
    70  }
    71  
    72  // RelationUnitsWatcher generates signals when units enter or leave
    73  // the scope of a RelationUnit, and changes to the settings of those
    74  // units known to have entered.
    75  type RelationUnitsWatcher interface {
    76  	Watcher
    77  
    78  	// Note that it's not very nice exposing a params type directly here. This
    79  	// is a continuation of existing bad behaviour and not good practice; do
    80  	// not use this as a model. (FWIW, it used to be in multiwatcher; which is
    81  	// also api-ey; and the multiwatcher type was used directly in params
    82  	// anyway.)
    83  	Changes() <-chan params.RelationUnitsChange
    84  }
    85  
    86  // newCommonWatcher exists so that all embedders have a place from which
    87  // to get a single TxnLogWatcher that will not be replaced in the lifetime
    88  // of the embedder (and also to restrict the width of the interface by
    89  // which they can access the rest of State, by storing st as a
    90  // modelBackend).
    91  func newCommonWatcher(st *State) commonWatcher {
    92  	return commonWatcher{
    93  		st:      st,
    94  		watcher: st.workers.TxnLogWatcher(),
    95  	}
    96  }
    97  
    98  // commonWatcher is part of all client watchers.
    99  type commonWatcher struct {
   100  	st      modelBackend
   101  	watcher workers.TxnLogWatcher
   102  	tomb    tomb.Tomb
   103  }
   104  
   105  // Stop stops the watcher, and returns any error encountered while running
   106  // or shutting down.
   107  func (w *commonWatcher) Stop() error {
   108  	w.Kill()
   109  	return w.Wait()
   110  }
   111  
   112  // Kill kills the watcher without waiting for it to shut down.
   113  func (w *commonWatcher) Kill() {
   114  	w.tomb.Kill(nil)
   115  }
   116  
   117  // Wait waits for the watcher to die and returns any
   118  // error encountered when it was running.
   119  func (w *commonWatcher) Wait() error {
   120  	return w.tomb.Wait()
   121  }
   122  
   123  // Err returns any error encountered while running or shutting down, or
   124  // tomb.ErrStillAlive if the watcher is still running.
   125  func (w *commonWatcher) Err() error {
   126  	return w.tomb.Err()
   127  }
   128  
   129  // collect combines the effects of the one change, and any further changes read
   130  // from more in the next 10ms. The result map describes the existence, or not,
   131  // of every id observed to have changed. If a value is read from the supplied
   132  // stop chan, collect returns false immediately.
   133  func collect(one watcher.Change, more <-chan watcher.Change, stop <-chan struct{}) (map[interface{}]bool, bool) {
   134  	var count int
   135  	result := map[interface{}]bool{}
   136  	handle := func(ch watcher.Change) {
   137  		count++
   138  		result[ch.Id] = ch.Revno != -1
   139  	}
   140  	handle(one)
   141  	// TODO(fwereade): 2016-03-17 lp:1558657
   142  	timeout := time.After(10 * time.Millisecond)
   143  	for done := false; !done; {
   144  		select {
   145  		case <-stop:
   146  			return nil, false
   147  		case another := <-more:
   148  			handle(another)
   149  		case <-timeout:
   150  			done = true
   151  		}
   152  	}
   153  	watchLogger.Tracef("read %d events for %d documents", count, len(result))
   154  	return result, true
   155  }
   156  
   157  func hasString(changes []string, name string) bool {
   158  	for _, v := range changes {
   159  		if v == name {
   160  			return true
   161  		}
   162  	}
   163  	return false
   164  }
   165  
   166  var _ Watcher = (*lifecycleWatcher)(nil)
   167  
   168  // lifecycleWatcher notifies about lifecycle changes for a set of entities of
   169  // the same kind. The first event emitted will contain the ids of all
   170  // entities; subsequent events are emitted whenever one or more entities are
   171  // added, or change their lifecycle state. After an entity is found to be
   172  // Dead, no further event will include it.
   173  type lifecycleWatcher struct {
   174  	commonWatcher
   175  	out chan []string
   176  
   177  	// coll is a function returning the mongo.Collection holding all
   178  	// interesting entities
   179  	coll     func() (mongo.Collection, func())
   180  	collName string
   181  
   182  	// members is used to select the initial set of interesting entities.
   183  	members bson.D
   184  	// filter is used to exclude events not affecting interesting entities.
   185  	filter func(interface{}) bool
   186  	// transform, if non-nil, is used to transform a document ID immediately
   187  	// prior to emitting to the out channel.
   188  	transform func(string) string
   189  	// life holds the most recent known life states of interesting entities.
   190  	life map[string]Life
   191  }
   192  
   193  func collFactory(st *State, collName string) func() (mongo.Collection, func()) {
   194  	return func() (mongo.Collection, func()) {
   195  		return st.getCollection(collName)
   196  	}
   197  }
   198  
   199  // WatchModels returns a StringsWatcher that notifies of changes
   200  // to the lifecycles of all models.
   201  func (st *State) WatchModels() StringsWatcher {
   202  	return newLifecycleWatcher(st, modelsC, nil, nil, nil)
   203  }
   204  
   205  // WatchModelVolumes returns a StringsWatcher that notifies of changes to
   206  // the lifecycles of all model-scoped volumes.
   207  func (st *State) WatchModelVolumes() StringsWatcher {
   208  	return st.watchModelMachinestorage(volumesC)
   209  }
   210  
   211  // WatchModelFilesystems returns a StringsWatcher that notifies of changes
   212  // to the lifecycles of all model-scoped filesystems.
   213  func (st *State) WatchModelFilesystems() StringsWatcher {
   214  	return st.watchModelMachinestorage(filesystemsC)
   215  }
   216  
   217  func (st *State) watchModelMachinestorage(collection string) StringsWatcher {
   218  	pattern := fmt.Sprintf("^%s$", st.docID(names.NumberSnippet))
   219  	members := bson.D{{"_id", bson.D{{"$regex", pattern}}}}
   220  	filter := func(id interface{}) bool {
   221  		k, err := st.strictLocalID(id.(string))
   222  		if err != nil {
   223  			return false
   224  		}
   225  		return !strings.Contains(k, "/")
   226  	}
   227  	return newLifecycleWatcher(st, collection, members, filter, nil)
   228  }
   229  
   230  // WatchMachineVolumes returns a StringsWatcher that notifies of changes to
   231  // the lifecycles of all volumes scoped to the specified machine.
   232  func (st *State) WatchMachineVolumes(m names.MachineTag) StringsWatcher {
   233  	return st.watchMachineStorage(m, volumesC)
   234  }
   235  
   236  // WatchMachineFilesystems returns a StringsWatcher that notifies of changes
   237  // to the lifecycles of all filesystems scoped to the specified machine.
   238  func (st *State) WatchMachineFilesystems(m names.MachineTag) StringsWatcher {
   239  	return st.watchMachineStorage(m, filesystemsC)
   240  }
   241  
   242  func (st *State) watchMachineStorage(m names.MachineTag, collection string) StringsWatcher {
   243  	pattern := fmt.Sprintf("^%s/%s$", st.docID(m.Id()), names.NumberSnippet)
   244  	members := bson.D{{"_id", bson.D{{"$regex", pattern}}}}
   245  	prefix := m.Id() + "/"
   246  	filter := func(id interface{}) bool {
   247  		k, err := st.strictLocalID(id.(string))
   248  		if err != nil {
   249  			return false
   250  		}
   251  		return strings.HasPrefix(k, prefix)
   252  	}
   253  	return newLifecycleWatcher(st, collection, members, filter, nil)
   254  }
   255  
   256  // WatchEnvironVolumeAttachments returns a StringsWatcher that notifies of
   257  // changes to the lifecycles of all volume attachments related to environ-
   258  // scoped volumes.
   259  func (st *State) WatchEnvironVolumeAttachments() StringsWatcher {
   260  	return st.watchModelMachinestorageAttachments(volumeAttachmentsC)
   261  }
   262  
   263  // WatchEnvironFilesystemAttachments returns a StringsWatcher that notifies
   264  // of changes to the lifecycles of all filesystem attachments related to
   265  // environ-scoped filesystems.
   266  func (st *State) WatchEnvironFilesystemAttachments() StringsWatcher {
   267  	return st.watchModelMachinestorageAttachments(filesystemAttachmentsC)
   268  }
   269  
   270  func (st *State) watchModelMachinestorageAttachments(collection string) StringsWatcher {
   271  	pattern := fmt.Sprintf("^%s.*:%s$", st.docID(""), names.NumberSnippet)
   272  	members := bson.D{{"_id", bson.D{{"$regex", pattern}}}}
   273  	filter := func(id interface{}) bool {
   274  		k, err := st.strictLocalID(id.(string))
   275  		if err != nil {
   276  			return false
   277  		}
   278  		colon := strings.IndexRune(k, ':')
   279  		if colon == -1 {
   280  			return false
   281  		}
   282  		return !strings.Contains(k[colon+1:], "/")
   283  	}
   284  	return newLifecycleWatcher(st, collection, members, filter, nil)
   285  }
   286  
   287  // WatchMachineVolumeAttachments returns a StringsWatcher that notifies of
   288  // changes to the lifecycles of all volume attachments related to the specified
   289  // machine, for volumes scoped to the machine.
   290  func (st *State) WatchMachineVolumeAttachments(m names.MachineTag) StringsWatcher {
   291  	return st.watchMachineStorageAttachments(m, volumeAttachmentsC)
   292  }
   293  
   294  // WatchMachineFilesystemAttachments returns a StringsWatcher that notifies of
   295  // changes to the lifecycles of all filesystem attachments related to the specified
   296  // machine, for filesystems scoped to the machine.
   297  func (st *State) WatchMachineFilesystemAttachments(m names.MachineTag) StringsWatcher {
   298  	return st.watchMachineStorageAttachments(m, filesystemAttachmentsC)
   299  }
   300  
   301  func (st *State) watchMachineStorageAttachments(m names.MachineTag, collection string) StringsWatcher {
   302  	pattern := fmt.Sprintf("^%s:%s/.*", st.docID(m.Id()), m.Id())
   303  	members := bson.D{{"_id", bson.D{{"$regex", pattern}}}}
   304  	prefix := m.Id() + fmt.Sprintf(":%s/", m.Id())
   305  	filter := func(id interface{}) bool {
   306  		k, err := st.strictLocalID(id.(string))
   307  		if err != nil {
   308  			return false
   309  		}
   310  		return strings.HasPrefix(k, prefix)
   311  	}
   312  	return newLifecycleWatcher(st, collection, members, filter, nil)
   313  }
   314  
   315  // WatchServices returns a StringsWatcher that notifies of changes to
   316  // the lifecycles of the services in the model.
   317  func (st *State) WatchServices() StringsWatcher {
   318  	return newLifecycleWatcher(st, applicationsC, nil, isLocalID(st), nil)
   319  }
   320  
   321  // WatchStorageAttachments returns a StringsWatcher that notifies of
   322  // changes to the lifecycles of all storage instances attached to the
   323  // specified unit.
   324  func (st *State) WatchStorageAttachments(unit names.UnitTag) StringsWatcher {
   325  	members := bson.D{{"unitid", unit.Id()}}
   326  	prefix := unitGlobalKey(unit.Id()) + "#"
   327  	filter := func(id interface{}) bool {
   328  		k, err := st.strictLocalID(id.(string))
   329  		if err != nil {
   330  			return false
   331  		}
   332  		return strings.HasPrefix(k, prefix)
   333  	}
   334  	tr := func(id string) string {
   335  		// Transform storage attachment document ID to storage ID.
   336  		return id[len(prefix):]
   337  	}
   338  	return newLifecycleWatcher(st, storageAttachmentsC, members, filter, tr)
   339  }
   340  
   341  // WatchUnits returns a StringsWatcher that notifies of changes to the
   342  // lifecycles of units of s.
   343  func (s *Application) WatchUnits() StringsWatcher {
   344  	members := bson.D{{"application", s.doc.Name}}
   345  	prefix := s.doc.Name + "/"
   346  	filter := func(unitDocID interface{}) bool {
   347  		unitName, err := s.st.strictLocalID(unitDocID.(string))
   348  		if err != nil {
   349  			return false
   350  		}
   351  		return strings.HasPrefix(unitName, prefix)
   352  	}
   353  	return newLifecycleWatcher(s.st, unitsC, members, filter, nil)
   354  }
   355  
   356  // WatchRelations returns a StringsWatcher that notifies of changes to the
   357  // lifecycles of relations involving s.
   358  func (s *Application) WatchRelations() StringsWatcher {
   359  	prefix := s.doc.Name + ":"
   360  	infix := " " + prefix
   361  	filter := func(id interface{}) bool {
   362  		k, err := s.st.strictLocalID(id.(string))
   363  		if err != nil {
   364  			return false
   365  		}
   366  		out := strings.HasPrefix(k, prefix) || strings.Contains(k, infix)
   367  		return out
   368  	}
   369  
   370  	members := bson.D{{"endpoints.applicationname", s.doc.Name}}
   371  	return newLifecycleWatcher(s.st, relationsC, members, filter, nil)
   372  }
   373  
   374  // WatchModelMachines returns a StringsWatcher that notifies of changes to
   375  // the lifecycles of the machines (but not containers) in the model.
   376  func (st *State) WatchModelMachines() StringsWatcher {
   377  	members := bson.D{{"$or", []bson.D{
   378  		{{"containertype", ""}},
   379  		{{"containertype", bson.D{{"$exists", false}}}},
   380  	}}}
   381  	filter := func(id interface{}) bool {
   382  		k, err := st.strictLocalID(id.(string))
   383  		if err != nil {
   384  			return false
   385  		}
   386  		return !strings.Contains(k, "/")
   387  	}
   388  	return newLifecycleWatcher(st, machinesC, members, filter, nil)
   389  }
   390  
   391  // WatchContainers returns a StringsWatcher that notifies of changes to the
   392  // lifecycles of containers of the specified type on a machine.
   393  func (m *Machine) WatchContainers(ctype instance.ContainerType) StringsWatcher {
   394  	isChild := fmt.Sprintf("^%s/%s/%s$", m.doc.DocID, ctype, names.NumberSnippet)
   395  	return m.containersWatcher(isChild)
   396  }
   397  
   398  // WatchAllContainers returns a StringsWatcher that notifies of changes to the
   399  // lifecycles of all containers on a machine.
   400  func (m *Machine) WatchAllContainers() StringsWatcher {
   401  	isChild := fmt.Sprintf("^%s/%s/%s$", m.doc.DocID, names.ContainerTypeSnippet, names.NumberSnippet)
   402  	return m.containersWatcher(isChild)
   403  }
   404  
   405  func (m *Machine) containersWatcher(isChildRegexp string) StringsWatcher {
   406  	members := bson.D{{"_id", bson.D{{"$regex", isChildRegexp}}}}
   407  	compiled := regexp.MustCompile(isChildRegexp)
   408  	filter := func(key interface{}) bool {
   409  		k := key.(string)
   410  		_, err := m.st.strictLocalID(k)
   411  		if err != nil {
   412  			return false
   413  		}
   414  		return compiled.MatchString(k)
   415  	}
   416  	return newLifecycleWatcher(m.st, machinesC, members, filter, nil)
   417  }
   418  
   419  func newLifecycleWatcher(
   420  	st *State,
   421  	collName string,
   422  	members bson.D,
   423  	filter func(key interface{}) bool,
   424  	transform func(id string) string,
   425  ) StringsWatcher {
   426  	w := &lifecycleWatcher{
   427  		commonWatcher: newCommonWatcher(st),
   428  		coll:          collFactory(st, collName),
   429  		collName:      collName,
   430  		members:       members,
   431  		filter:        filter,
   432  		transform:     transform,
   433  		life:          make(map[string]Life),
   434  		out:           make(chan []string),
   435  	}
   436  	go func() {
   437  		defer w.tomb.Done()
   438  		defer close(w.out)
   439  		w.tomb.Kill(w.loop())
   440  	}()
   441  	return w
   442  }
   443  
   444  type lifeDoc struct {
   445  	Id   string `bson:"_id"`
   446  	Life Life
   447  }
   448  
   449  var lifeFields = bson.D{{"_id", 1}, {"life", 1}}
   450  
   451  // Changes returns the event channel for the LifecycleWatcher.
   452  func (w *lifecycleWatcher) Changes() <-chan []string {
   453  	return w.out
   454  }
   455  
   456  func (w *lifecycleWatcher) initial() (set.Strings, error) {
   457  	coll, closer := w.coll()
   458  	defer closer()
   459  
   460  	ids := make(set.Strings)
   461  	var doc lifeDoc
   462  	iter := coll.Find(w.members).Select(lifeFields).Iter()
   463  	for iter.Next(&doc) {
   464  		id := w.st.localID(doc.Id)
   465  		ids.Add(id)
   466  		if doc.Life != Dead {
   467  			w.life[id] = doc.Life
   468  		}
   469  	}
   470  	return ids, iter.Close()
   471  }
   472  
   473  func (w *lifecycleWatcher) merge(ids set.Strings, updates map[interface{}]bool) error {
   474  	coll, closer := w.coll()
   475  	defer closer()
   476  
   477  	// Separate ids into those thought to exist and those known to be removed.
   478  	var changed []string
   479  	latest := make(map[string]Life)
   480  	for docID, exists := range updates {
   481  		switch docID := docID.(type) {
   482  		case string:
   483  			if exists {
   484  				changed = append(changed, docID)
   485  			} else {
   486  				latest[w.st.localID(docID)] = Dead
   487  			}
   488  		default:
   489  			return errors.Errorf("id is not of type string, got %T", docID)
   490  		}
   491  	}
   492  
   493  	// Collect life states from ids thought to exist. Any that don't actually
   494  	// exist are ignored (we'll hear about them in the next set of updates --
   495  	// all that's actually happened in that situation is that the watcher
   496  	// events have lagged a little behind reality).
   497  	iter := coll.Find(bson.D{{"_id", bson.D{{"$in", changed}}}}).Select(lifeFields).Iter()
   498  	var doc lifeDoc
   499  	for iter.Next(&doc) {
   500  		latest[w.st.localID(doc.Id)] = doc.Life
   501  	}
   502  	if err := iter.Close(); err != nil {
   503  		return err
   504  	}
   505  
   506  	// Add to ids any whose life state is known to have changed.
   507  	for id, newLife := range latest {
   508  		gone := newLife == Dead
   509  		oldLife, known := w.life[id]
   510  		switch {
   511  		case known && gone:
   512  			delete(w.life, id)
   513  		case !known && !gone:
   514  			w.life[id] = newLife
   515  		case known && newLife != oldLife:
   516  			w.life[id] = newLife
   517  		default:
   518  			continue
   519  		}
   520  		ids.Add(id)
   521  	}
   522  	return nil
   523  }
   524  
   525  // ErrStateClosed is returned from watchers if their underlying
   526  // state connection has been closed.
   527  var ErrStateClosed = fmt.Errorf("state has been closed")
   528  
   529  // stateWatcherDeadError processes the error received when the watcher
   530  // inside a state connection dies. If the State has been closed, the
   531  // watcher will have been stopped and error will be nil, so we ensure
   532  // that higher level watchers return a non-nil error in that case, as
   533  // watchers are not expected to die unexpectedly without an error.
   534  func stateWatcherDeadError(err error) error {
   535  	if err != nil {
   536  		return err
   537  	}
   538  	return ErrStateClosed
   539  }
   540  
   541  func (w *lifecycleWatcher) loop() error {
   542  	in := make(chan watcher.Change)
   543  	w.watcher.WatchCollectionWithFilter(w.collName, in, w.filter)
   544  	defer w.watcher.UnwatchCollection(w.collName, in)
   545  	ids, err := w.initial()
   546  	if err != nil {
   547  		return err
   548  	}
   549  	out := w.out
   550  	for {
   551  		values := ids.Values()
   552  		if w.transform != nil {
   553  			for i, v := range values {
   554  				values[i] = w.transform(v)
   555  			}
   556  		}
   557  		select {
   558  		case <-w.tomb.Dying():
   559  			return tomb.ErrDying
   560  		case <-w.watcher.Dead():
   561  			return stateWatcherDeadError(w.watcher.Err())
   562  		case ch := <-in:
   563  			updates, ok := collect(ch, in, w.tomb.Dying())
   564  			if !ok {
   565  				return tomb.ErrDying
   566  			}
   567  			if err := w.merge(ids, updates); err != nil {
   568  				return err
   569  			}
   570  			if !ids.IsEmpty() {
   571  				out = w.out
   572  			}
   573  		case out <- values:
   574  			ids = make(set.Strings)
   575  			out = nil
   576  		}
   577  	}
   578  }
   579  
   580  // minUnitsWatcher notifies about MinUnits changes of the services requiring
   581  // a minimum number of units to be alive. The first event returned by the
   582  // watcher is the set of application names requiring a minimum number of units.
   583  // Subsequent events are generated when a service increases MinUnits, or when
   584  // one or more units belonging to a service are destroyed.
   585  type minUnitsWatcher struct {
   586  	commonWatcher
   587  	known map[string]int
   588  	out   chan []string
   589  }
   590  
   591  var _ Watcher = (*minUnitsWatcher)(nil)
   592  
   593  func newMinUnitsWatcher(st *State) StringsWatcher {
   594  	w := &minUnitsWatcher{
   595  		commonWatcher: newCommonWatcher(st),
   596  		known:         make(map[string]int),
   597  		out:           make(chan []string),
   598  	}
   599  	go func() {
   600  		defer w.tomb.Done()
   601  		defer close(w.out)
   602  		w.tomb.Kill(w.loop())
   603  	}()
   604  	return w
   605  }
   606  
   607  // WatchMinUnits returns a StringsWatcher for the minUnits collection
   608  func (st *State) WatchMinUnits() StringsWatcher {
   609  	return newMinUnitsWatcher(st)
   610  }
   611  
   612  func (w *minUnitsWatcher) initial() (set.Strings, error) {
   613  	applicationnames := make(set.Strings)
   614  	var doc minUnitsDoc
   615  	newMinUnits, closer := w.st.getCollection(minUnitsC)
   616  	defer closer()
   617  
   618  	iter := newMinUnits.Find(nil).Iter()
   619  	for iter.Next(&doc) {
   620  		w.known[doc.ApplicationName] = doc.Revno
   621  		applicationnames.Add(doc.ApplicationName)
   622  	}
   623  	return applicationnames, iter.Close()
   624  }
   625  
   626  func (w *minUnitsWatcher) merge(applicationnames set.Strings, change watcher.Change) error {
   627  	applicationname := w.st.localID(change.Id.(string))
   628  	if change.Revno == -1 {
   629  		delete(w.known, applicationname)
   630  		applicationnames.Remove(applicationname)
   631  		return nil
   632  	}
   633  	doc := minUnitsDoc{}
   634  	newMinUnits, closer := w.st.getCollection(minUnitsC)
   635  	defer closer()
   636  	if err := newMinUnits.FindId(change.Id).One(&doc); err != nil {
   637  		return err
   638  	}
   639  	revno, known := w.known[applicationname]
   640  	w.known[applicationname] = doc.Revno
   641  	if !known || doc.Revno > revno {
   642  		applicationnames.Add(applicationname)
   643  	}
   644  	return nil
   645  }
   646  
   647  func (w *minUnitsWatcher) loop() (err error) {
   648  	ch := make(chan watcher.Change)
   649  	w.watcher.WatchCollectionWithFilter(minUnitsC, ch, isLocalID(w.st))
   650  	defer w.watcher.UnwatchCollection(minUnitsC, ch)
   651  	applicationnames, err := w.initial()
   652  	if err != nil {
   653  		return err
   654  	}
   655  	out := w.out
   656  	for {
   657  		select {
   658  		case <-w.tomb.Dying():
   659  			return tomb.ErrDying
   660  		case <-w.watcher.Dead():
   661  			return stateWatcherDeadError(w.watcher.Err())
   662  		case change := <-ch:
   663  			if err = w.merge(applicationnames, change); err != nil {
   664  				return err
   665  			}
   666  			if !applicationnames.IsEmpty() {
   667  				out = w.out
   668  			}
   669  		case out <- applicationnames.Values():
   670  			out = nil
   671  			applicationnames = set.NewStrings()
   672  		}
   673  	}
   674  }
   675  
   676  func (w *minUnitsWatcher) Changes() <-chan []string {
   677  	return w.out
   678  }
   679  
   680  // scopeInfo holds a RelationScopeWatcher's last-delivered state, and any
   681  // known but undelivered changes thereto.
   682  type scopeInfo struct {
   683  	base map[string]bool
   684  	diff map[string]bool
   685  }
   686  
   687  func (info *scopeInfo) add(name string) {
   688  	if info.base[name] {
   689  		delete(info.diff, name)
   690  	} else {
   691  		info.diff[name] = true
   692  	}
   693  }
   694  
   695  func (info *scopeInfo) remove(name string) {
   696  	if info.base[name] {
   697  		info.diff[name] = false
   698  	} else {
   699  		delete(info.diff, name)
   700  	}
   701  }
   702  
   703  func (info *scopeInfo) commit() {
   704  	for name, change := range info.diff {
   705  		if change {
   706  			info.base[name] = true
   707  		} else {
   708  			delete(info.base, name)
   709  		}
   710  	}
   711  	info.diff = map[string]bool{}
   712  }
   713  
   714  func (info *scopeInfo) hasChanges() bool {
   715  	return len(info.diff) > 0
   716  }
   717  
   718  func (info *scopeInfo) changes() *RelationScopeChange {
   719  	ch := &RelationScopeChange{}
   720  	for name, change := range info.diff {
   721  		if change {
   722  			ch.Entered = append(ch.Entered, name)
   723  		} else {
   724  			ch.Left = append(ch.Left, name)
   725  		}
   726  	}
   727  	return ch
   728  }
   729  
   730  var _ Watcher = (*RelationScopeWatcher)(nil)
   731  
   732  // RelationScopeChange contains information about units that have
   733  // entered or left a particular scope.
   734  type RelationScopeChange struct {
   735  	Entered []string
   736  	Left    []string
   737  }
   738  
   739  // RelationScopeWatcher observes changes to the set of units
   740  // in a particular relation scope.
   741  type RelationScopeWatcher struct {
   742  	commonWatcher
   743  	prefix string
   744  	ignore string
   745  	out    chan *RelationScopeChange
   746  }
   747  
   748  func newRelationScopeWatcher(st *State, scope, ignore string) *RelationScopeWatcher {
   749  	w := &RelationScopeWatcher{
   750  		commonWatcher: newCommonWatcher(st),
   751  		prefix:        scope + "#",
   752  		ignore:        ignore,
   753  		out:           make(chan *RelationScopeChange),
   754  	}
   755  	go func() {
   756  		defer w.tomb.Done()
   757  		defer close(w.out)
   758  		w.tomb.Kill(w.loop())
   759  	}()
   760  	return w
   761  }
   762  
   763  // Changes returns a channel that will receive changes when units enter and
   764  // leave a relation scope. The Entered field in the first event on the channel
   765  // holds the initial state.
   766  func (w *RelationScopeWatcher) Changes() <-chan *RelationScopeChange {
   767  	return w.out
   768  }
   769  
   770  // initialInfo returns an uncommitted scopeInfo with the current set of units.
   771  func (w *RelationScopeWatcher) initialInfo() (info *scopeInfo, err error) {
   772  	relationScopes, closer := w.st.getCollection(relationScopesC)
   773  	defer closer()
   774  
   775  	docs := []relationScopeDoc{}
   776  	sel := bson.D{
   777  		{"key", bson.D{{"$regex", "^" + w.prefix}}},
   778  		{"departing", bson.D{{"$ne", true}}},
   779  	}
   780  	if err = relationScopes.Find(sel).All(&docs); err != nil {
   781  		return nil, err
   782  	}
   783  	info = &scopeInfo{
   784  		base: map[string]bool{},
   785  		diff: map[string]bool{},
   786  	}
   787  	for _, doc := range docs {
   788  		if name := doc.unitName(); name != w.ignore {
   789  			info.add(name)
   790  		}
   791  	}
   792  	return info, nil
   793  }
   794  
   795  // mergeChanges updates info with the contents of the changes in ids. False
   796  // values are always treated as removed; true values cause the associated
   797  // document to be read, and whether it's treated as added or removed depends
   798  // on the value of the document's Departing field.
   799  func (w *RelationScopeWatcher) mergeChanges(info *scopeInfo, ids map[interface{}]bool) error {
   800  	relationScopes, closer := w.st.getCollection(relationScopesC)
   801  	defer closer()
   802  
   803  	var existIds []string
   804  	for id, exists := range ids {
   805  		switch id := id.(type) {
   806  		case string:
   807  			if exists {
   808  				existIds = append(existIds, id)
   809  			} else {
   810  				key, err := w.st.strictLocalID(id)
   811  				if err != nil {
   812  					return errors.Trace(err)
   813  				}
   814  				info.remove(unitNameFromScopeKey(key))
   815  			}
   816  		default:
   817  			logger.Warningf("ignoring bad relation scope id: %#v", id)
   818  		}
   819  	}
   820  	var docs []relationScopeDoc
   821  	sel := bson.D{{"_id", bson.D{{"$in", existIds}}}}
   822  	if err := relationScopes.Find(sel).All(&docs); err != nil {
   823  		return err
   824  	}
   825  	for _, doc := range docs {
   826  		name := doc.unitName()
   827  		if doc.Departing {
   828  			info.remove(name)
   829  		} else if name != w.ignore {
   830  			info.add(name)
   831  		}
   832  	}
   833  	return nil
   834  }
   835  
   836  func (w *RelationScopeWatcher) loop() error {
   837  	in := make(chan watcher.Change)
   838  	fullPrefix := w.st.docID(w.prefix)
   839  	filter := func(id interface{}) bool {
   840  		return strings.HasPrefix(id.(string), fullPrefix)
   841  	}
   842  	w.watcher.WatchCollectionWithFilter(relationScopesC, in, filter)
   843  	defer w.watcher.UnwatchCollection(relationScopesC, in)
   844  	info, err := w.initialInfo()
   845  	if err != nil {
   846  		return err
   847  	}
   848  	sent := false
   849  	out := w.out
   850  	for {
   851  		select {
   852  		case <-w.watcher.Dead():
   853  			return stateWatcherDeadError(w.watcher.Err())
   854  		case <-w.tomb.Dying():
   855  			return tomb.ErrDying
   856  		case ch := <-in:
   857  			latest, ok := collect(ch, in, w.tomb.Dying())
   858  			if !ok {
   859  				return tomb.ErrDying
   860  			}
   861  			if err := w.mergeChanges(info, latest); err != nil {
   862  				return err
   863  			}
   864  			if info.hasChanges() {
   865  				out = w.out
   866  			} else if sent {
   867  				out = nil
   868  			}
   869  		case out <- info.changes():
   870  			info.commit()
   871  			sent = true
   872  			out = nil
   873  		}
   874  	}
   875  }
   876  
   877  // relationUnitsWatcher sends notifications of units entering and leaving the
   878  // scope of a RelationUnit, and changes to the settings of those units known
   879  // to have entered.
   880  type relationUnitsWatcher struct {
   881  	commonWatcher
   882  	sw       *RelationScopeWatcher
   883  	watching set.Strings
   884  	updates  chan watcher.Change
   885  	out      chan params.RelationUnitsChange
   886  }
   887  
   888  // Watch returns a watcher that notifies of changes to conterpart units in
   889  // the relation.
   890  func (ru *RelationUnit) Watch() RelationUnitsWatcher {
   891  	return newRelationUnitsWatcher(ru)
   892  }
   893  
   894  func newRelationUnitsWatcher(ru *RelationUnit) RelationUnitsWatcher {
   895  	w := &relationUnitsWatcher{
   896  		commonWatcher: newCommonWatcher(ru.st),
   897  		sw:            ru.WatchScope(),
   898  		watching:      make(set.Strings),
   899  		updates:       make(chan watcher.Change),
   900  		out:           make(chan params.RelationUnitsChange),
   901  	}
   902  	go func() {
   903  		defer w.finish()
   904  		w.tomb.Kill(w.loop())
   905  	}()
   906  	return w
   907  }
   908  
   909  // Changes returns a channel that will receive the changes to
   910  // counterpart units in a relation. The first event on the
   911  // channel holds the initial state of the relation in its
   912  // Changed field.
   913  func (w *relationUnitsWatcher) Changes() <-chan params.RelationUnitsChange {
   914  	return w.out
   915  }
   916  
   917  func emptyRelationUnitsChanges(changes *params.RelationUnitsChange) bool {
   918  	return len(changes.Changed)+len(changes.Departed) == 0
   919  }
   920  
   921  func setRelationUnitChangeVersion(changes *params.RelationUnitsChange, key string, version int64) {
   922  	name := unitNameFromScopeKey(key)
   923  	settings := params.UnitSettings{Version: version}
   924  	if changes.Changed == nil {
   925  		changes.Changed = map[string]params.UnitSettings{}
   926  	}
   927  	changes.Changed[name] = settings
   928  }
   929  
   930  // mergeSettings reads the relation settings node for the unit with the
   931  // supplied key, and sets a value in the Changed field keyed on the unit's
   932  // name. It returns the mgo/txn revision number of the settings node.
   933  func (w *relationUnitsWatcher) mergeSettings(changes *params.RelationUnitsChange, key string) (int64, error) {
   934  	var doc struct {
   935  		TxnRevno int64 `bson:"txn-revno"`
   936  		Version  int64 `bson:"version"`
   937  	}
   938  	if err := readSettingsDocInto(w.st, settingsC, key, &doc); err != nil {
   939  		return -1, err
   940  	}
   941  	setRelationUnitChangeVersion(changes, key, doc.Version)
   942  	return doc.TxnRevno, nil
   943  }
   944  
   945  // mergeScope starts and stops settings watches on the units entering and
   946  // leaving the scope in the supplied RelationScopeChange event, and applies
   947  // the expressed changes to the supplied RelationUnitsChange event.
   948  func (w *relationUnitsWatcher) mergeScope(changes *params.RelationUnitsChange, c *RelationScopeChange) error {
   949  	for _, name := range c.Entered {
   950  		key := w.sw.prefix + name
   951  		docID := w.st.docID(key)
   952  		revno, err := w.mergeSettings(changes, key)
   953  		if err != nil {
   954  			return err
   955  		}
   956  		changes.Departed = remove(changes.Departed, name)
   957  		w.watcher.Watch(settingsC, docID, revno, w.updates)
   958  		w.watching.Add(docID)
   959  	}
   960  	for _, name := range c.Left {
   961  		key := w.sw.prefix + name
   962  		docID := w.st.docID(key)
   963  		changes.Departed = append(changes.Departed, name)
   964  		if changes.Changed != nil {
   965  			delete(changes.Changed, name)
   966  		}
   967  		w.watcher.Unwatch(settingsC, docID, w.updates)
   968  		w.watching.Remove(docID)
   969  	}
   970  	return nil
   971  }
   972  
   973  // remove removes s from strs and returns the modified slice.
   974  func remove(strs []string, s string) []string {
   975  	for i, v := range strs {
   976  		if s == v {
   977  			strs[i] = strs[len(strs)-1]
   978  			return strs[:len(strs)-1]
   979  		}
   980  	}
   981  	return strs
   982  }
   983  
   984  func (w *relationUnitsWatcher) finish() {
   985  	watcher.Stop(w.sw, &w.tomb)
   986  	for _, watchedValue := range w.watching.Values() {
   987  		w.watcher.Unwatch(settingsC, watchedValue, w.updates)
   988  	}
   989  	close(w.updates)
   990  	close(w.out)
   991  	w.tomb.Done()
   992  }
   993  
   994  func (w *relationUnitsWatcher) loop() (err error) {
   995  	var (
   996  		sentInitial bool
   997  		changes     params.RelationUnitsChange
   998  		out         chan<- params.RelationUnitsChange
   999  	)
  1000  	for {
  1001  		select {
  1002  		case <-w.watcher.Dead():
  1003  			return stateWatcherDeadError(w.watcher.Err())
  1004  		case <-w.tomb.Dying():
  1005  			return tomb.ErrDying
  1006  		case c, ok := <-w.sw.Changes():
  1007  			if !ok {
  1008  				return watcher.EnsureErr(w.sw)
  1009  			}
  1010  			if err = w.mergeScope(&changes, c); err != nil {
  1011  				return err
  1012  			}
  1013  			if !sentInitial || !emptyRelationUnitsChanges(&changes) {
  1014  				out = w.out
  1015  			} else {
  1016  				out = nil
  1017  			}
  1018  		case c := <-w.updates:
  1019  			id, ok := c.Id.(string)
  1020  			if !ok {
  1021  				logger.Warningf("ignoring bad relation scope id: %#v", c.Id)
  1022  			}
  1023  			if _, err := w.mergeSettings(&changes, id); err != nil {
  1024  				return err
  1025  			}
  1026  			out = w.out
  1027  		case out <- changes:
  1028  			sentInitial = true
  1029  			changes = params.RelationUnitsChange{}
  1030  			out = nil
  1031  		}
  1032  	}
  1033  }
  1034  
  1035  // unitsWatcher notifies of changes to a set of units. Notifications will be
  1036  // sent when units enter or leave the set, and when units in the set change
  1037  // their lifecycle status. The initial event contains all units in the set,
  1038  // regardless of lifecycle status; once a unit observed to be Dead or removed
  1039  // has been reported, it will not be reported again.
  1040  type unitsWatcher struct {
  1041  	commonWatcher
  1042  	tag      string
  1043  	getUnits func() ([]string, error)
  1044  	life     map[string]Life
  1045  	in       chan watcher.Change
  1046  	out      chan []string
  1047  }
  1048  
  1049  var _ Watcher = (*unitsWatcher)(nil)
  1050  
  1051  // WatchSubordinateUnits returns a StringsWatcher tracking the unit's subordinate units.
  1052  func (u *Unit) WatchSubordinateUnits() StringsWatcher {
  1053  	u = &Unit{st: u.st, doc: u.doc}
  1054  	coll := unitsC
  1055  	getUnits := func() ([]string, error) {
  1056  		if err := u.Refresh(); err != nil {
  1057  			return nil, err
  1058  		}
  1059  		return u.doc.Subordinates, nil
  1060  	}
  1061  	return newUnitsWatcher(u.st, u.Tag(), getUnits, coll, u.doc.DocID)
  1062  }
  1063  
  1064  // WatchPrincipalUnits returns a StringsWatcher tracking the machine's principal
  1065  // units.
  1066  func (m *Machine) WatchPrincipalUnits() StringsWatcher {
  1067  	m = &Machine{st: m.st, doc: m.doc}
  1068  	coll := machinesC
  1069  	getUnits := func() ([]string, error) {
  1070  		if err := m.Refresh(); err != nil {
  1071  			return nil, err
  1072  		}
  1073  		return m.doc.Principals, nil
  1074  	}
  1075  	return newUnitsWatcher(m.st, m.Tag(), getUnits, coll, m.doc.DocID)
  1076  }
  1077  
  1078  func newUnitsWatcher(st *State, tag names.Tag, getUnits func() ([]string, error), coll, id string) StringsWatcher {
  1079  	w := &unitsWatcher{
  1080  		commonWatcher: newCommonWatcher(st),
  1081  		tag:           tag.String(),
  1082  		getUnits:      getUnits,
  1083  		life:          map[string]Life{},
  1084  		in:            make(chan watcher.Change),
  1085  		out:           make(chan []string),
  1086  	}
  1087  	go func() {
  1088  		defer w.tomb.Done()
  1089  		defer close(w.out)
  1090  		w.tomb.Kill(w.loop(coll, id))
  1091  	}()
  1092  	return w
  1093  }
  1094  
  1095  // Tag returns the tag of the entity whose units are being watched.
  1096  func (w *unitsWatcher) Tag() string {
  1097  	return w.tag
  1098  }
  1099  
  1100  // Changes returns the UnitsWatcher's output channel.
  1101  func (w *unitsWatcher) Changes() <-chan []string {
  1102  	return w.out
  1103  }
  1104  
  1105  // lifeWatchDoc holds the fields used in starting and maintaining a watch
  1106  // on a entity's lifecycle.
  1107  type lifeWatchDoc struct {
  1108  	Id       string `bson:"_id"`
  1109  	Life     Life
  1110  	TxnRevno int64 `bson:"txn-revno"`
  1111  }
  1112  
  1113  // lifeWatchFields specifies the fields of a lifeWatchDoc.
  1114  var lifeWatchFields = bson.D{{"_id", 1}, {"life", 1}, {"txn-revno", 1}}
  1115  
  1116  // initial returns every member of the tracked set.
  1117  func (w *unitsWatcher) initial() ([]string, error) {
  1118  	initialNames, err := w.getUnits()
  1119  	if err != nil {
  1120  		return nil, err
  1121  	}
  1122  	newUnits, closer := w.st.getCollection(unitsC)
  1123  	defer closer()
  1124  	query := bson.D{{"name", bson.D{{"$in", initialNames}}}}
  1125  	docs := []lifeWatchDoc{}
  1126  	if err := newUnits.Find(query).Select(lifeWatchFields).All(&docs); err != nil {
  1127  		return nil, err
  1128  	}
  1129  	changes := []string{}
  1130  	for _, doc := range docs {
  1131  		unitName, err := w.st.strictLocalID(doc.Id)
  1132  		if err != nil {
  1133  			return nil, errors.Trace(err)
  1134  		}
  1135  		changes = append(changes, unitName)
  1136  		if doc.Life != Dead {
  1137  			w.life[unitName] = doc.Life
  1138  			w.watcher.Watch(unitsC, doc.Id, doc.TxnRevno, w.in)
  1139  		}
  1140  	}
  1141  	return changes, nil
  1142  }
  1143  
  1144  // update adds to and returns changes, such that it contains the names of any
  1145  // non-Dead units to have entered or left the tracked set.
  1146  func (w *unitsWatcher) update(changes []string) ([]string, error) {
  1147  	latest, err := w.getUnits()
  1148  	if err != nil {
  1149  		return nil, err
  1150  	}
  1151  	for _, name := range latest {
  1152  		if _, known := w.life[name]; !known {
  1153  			changes, err = w.merge(changes, name)
  1154  			if err != nil {
  1155  				return nil, err
  1156  			}
  1157  		}
  1158  	}
  1159  	for name := range w.life {
  1160  		if hasString(latest, name) {
  1161  			continue
  1162  		}
  1163  		if !hasString(changes, name) {
  1164  			changes = append(changes, name)
  1165  		}
  1166  		delete(w.life, name)
  1167  		w.watcher.Unwatch(unitsC, w.st.docID(name), w.in)
  1168  	}
  1169  	return changes, nil
  1170  }
  1171  
  1172  // merge adds to and returns changes, such that it contains the supplied unit
  1173  // name if that unit is unknown and non-Dead, or has changed lifecycle status.
  1174  func (w *unitsWatcher) merge(changes []string, name string) ([]string, error) {
  1175  	units, closer := w.st.getCollection(unitsC)
  1176  	defer closer()
  1177  
  1178  	unitDocID := w.st.docID(name)
  1179  	doc := lifeWatchDoc{}
  1180  	err := units.FindId(unitDocID).Select(lifeWatchFields).One(&doc)
  1181  	gone := false
  1182  	if err == mgo.ErrNotFound {
  1183  		gone = true
  1184  	} else if err != nil {
  1185  		return nil, err
  1186  	} else if doc.Life == Dead {
  1187  		gone = true
  1188  	}
  1189  	life, known := w.life[name]
  1190  	switch {
  1191  	case known && gone:
  1192  		delete(w.life, name)
  1193  		w.watcher.Unwatch(unitsC, unitDocID, w.in)
  1194  	case !known && !gone:
  1195  		w.watcher.Watch(unitsC, unitDocID, doc.TxnRevno, w.in)
  1196  		w.life[name] = doc.Life
  1197  	case known && life != doc.Life:
  1198  		w.life[name] = doc.Life
  1199  	default:
  1200  		return changes, nil
  1201  	}
  1202  	if !hasString(changes, name) {
  1203  		changes = append(changes, name)
  1204  	}
  1205  	return changes, nil
  1206  }
  1207  
  1208  func (w *unitsWatcher) loop(coll, id string) error {
  1209  	collection, closer := w.st.getCollection(coll)
  1210  	revno, err := getTxnRevno(collection, id)
  1211  	closer()
  1212  	if err != nil {
  1213  		return err
  1214  	}
  1215  
  1216  	w.watcher.Watch(coll, id, revno, w.in)
  1217  	defer func() {
  1218  		w.watcher.Unwatch(coll, id, w.in)
  1219  		for name := range w.life {
  1220  			w.watcher.Unwatch(unitsC, w.st.docID(name), w.in)
  1221  		}
  1222  	}()
  1223  	changes, err := w.initial()
  1224  	if err != nil {
  1225  		return err
  1226  	}
  1227  	rootLocalID := w.st.localID(id)
  1228  	out := w.out
  1229  	for {
  1230  		select {
  1231  		case <-w.watcher.Dead():
  1232  			return stateWatcherDeadError(w.watcher.Err())
  1233  		case <-w.tomb.Dying():
  1234  			return tomb.ErrDying
  1235  		case c := <-w.in:
  1236  			localID := w.st.localID(c.Id.(string))
  1237  			if localID == rootLocalID {
  1238  				changes, err = w.update(changes)
  1239  			} else {
  1240  				changes, err = w.merge(changes, localID)
  1241  			}
  1242  			if err != nil {
  1243  				return err
  1244  			}
  1245  			if len(changes) > 0 {
  1246  				out = w.out
  1247  			}
  1248  		case out <- changes:
  1249  			out = nil
  1250  			changes = nil
  1251  		}
  1252  	}
  1253  }
  1254  
  1255  // WatchHardwareCharacteristics returns a watcher for observing changes to a machine's hardware characteristics.
  1256  func (m *Machine) WatchHardwareCharacteristics() NotifyWatcher {
  1257  	return newEntityWatcher(m.st, instanceDataC, m.doc.DocID)
  1258  }
  1259  
  1260  // WatchControllerInfo returns a NotifyWatcher for the controllers collection
  1261  func (st *State) WatchControllerInfo() NotifyWatcher {
  1262  	return newEntityWatcher(st, controllersC, modelGlobalKey)
  1263  }
  1264  
  1265  // Watch returns a watcher for observing changes to a machine.
  1266  func (m *Machine) Watch() NotifyWatcher {
  1267  	return newEntityWatcher(m.st, machinesC, m.doc.DocID)
  1268  }
  1269  
  1270  // Watch returns a watcher for observing changes to a service.
  1271  func (s *Application) Watch() NotifyWatcher {
  1272  	return newEntityWatcher(s.st, applicationsC, s.doc.DocID)
  1273  }
  1274  
  1275  // WatchLeaderSettings returns a watcher for observing changed to a service's
  1276  // leader settings.
  1277  func (s *Application) WatchLeaderSettings() NotifyWatcher {
  1278  	docId := s.st.docID(leadershipSettingsKey(s.Name()))
  1279  	return newEntityWatcher(s.st, settingsC, docId)
  1280  }
  1281  
  1282  // Watch returns a watcher for observing changes to a unit.
  1283  func (u *Unit) Watch() NotifyWatcher {
  1284  	return newEntityWatcher(u.st, unitsC, u.doc.DocID)
  1285  }
  1286  
  1287  // Watch returns a watcher for observing changes to an model.
  1288  func (e *Model) Watch() NotifyWatcher {
  1289  	return newEntityWatcher(e.st, modelsC, e.doc.UUID)
  1290  }
  1291  
  1292  // WatchUpgradeInfo returns a watcher for observing changes to upgrade
  1293  // synchronisation state.
  1294  func (st *State) WatchUpgradeInfo() NotifyWatcher {
  1295  	return newEntityWatcher(st, upgradeInfoC, currentUpgradeId)
  1296  }
  1297  
  1298  // WatchRestoreInfoChanges returns a NotifyWatcher that will inform
  1299  // when the restore status changes.
  1300  func (st *State) WatchRestoreInfoChanges() NotifyWatcher {
  1301  	return newEntityWatcher(st, restoreInfoC, currentRestoreId)
  1302  }
  1303  
  1304  // WatchForModelConfigChanges returns a NotifyWatcher waiting for the Model
  1305  // Config to change.
  1306  func (st *State) WatchForModelConfigChanges() NotifyWatcher {
  1307  	return newEntityWatcher(st, settingsC, st.docID(modelGlobalKey))
  1308  }
  1309  
  1310  // WatchForUnitAssignment watches for new services that request units to be
  1311  // assigned to machines.
  1312  func (st *State) WatchForUnitAssignment() StringsWatcher {
  1313  	return newcollectionWatcher(st, colWCfg{col: assignUnitC})
  1314  }
  1315  
  1316  // WatchAPIHostPorts returns a NotifyWatcher that notifies
  1317  // when the set of API addresses changes.
  1318  func (st *State) WatchAPIHostPorts() NotifyWatcher {
  1319  	return newEntityWatcher(st, controllersC, apiHostPortsKey)
  1320  }
  1321  
  1322  // WatchStorageAttachment returns a watcher for observing changes
  1323  // to a storage attachment.
  1324  func (st *State) WatchStorageAttachment(s names.StorageTag, u names.UnitTag) NotifyWatcher {
  1325  	id := storageAttachmentId(u.Id(), s.Id())
  1326  	return newEntityWatcher(st, storageAttachmentsC, st.docID(id))
  1327  }
  1328  
  1329  // WatchVolumeAttachment returns a watcher for observing changes
  1330  // to a volume attachment.
  1331  func (st *State) WatchVolumeAttachment(m names.MachineTag, v names.VolumeTag) NotifyWatcher {
  1332  	id := volumeAttachmentId(m.Id(), v.Id())
  1333  	return newEntityWatcher(st, volumeAttachmentsC, st.docID(id))
  1334  }
  1335  
  1336  // WatchFilesystemAttachment returns a watcher for observing changes
  1337  // to a filesystem attachment.
  1338  func (st *State) WatchFilesystemAttachment(m names.MachineTag, f names.FilesystemTag) NotifyWatcher {
  1339  	id := filesystemAttachmentId(m.Id(), f.Id())
  1340  	return newEntityWatcher(st, filesystemAttachmentsC, st.docID(id))
  1341  }
  1342  
  1343  // WatchConfigSettings returns a watcher for observing changes to the
  1344  // unit's service configuration settings. The unit must have a charm URL
  1345  // set before this method is called, and the returned watcher will be
  1346  // valid only while the unit's charm URL is not changed.
  1347  // TODO(fwereade): this could be much smarter; if it were, uniter.Filter
  1348  // could be somewhat simpler.
  1349  func (u *Unit) WatchConfigSettings() (NotifyWatcher, error) {
  1350  	if u.doc.CharmURL == nil {
  1351  		return nil, fmt.Errorf("unit charm not set")
  1352  	}
  1353  	settingsKey := applicationSettingsKey(u.doc.Application, u.doc.CharmURL)
  1354  	return newEntityWatcher(u.st, settingsC, u.st.docID(settingsKey)), nil
  1355  }
  1356  
  1357  // WatchMeterStatus returns a watcher observing changes that affect the meter status
  1358  // of a unit.
  1359  func (u *Unit) WatchMeterStatus() NotifyWatcher {
  1360  	return newDocWatcher(u.st, []docKey{
  1361  		{
  1362  			meterStatusC,
  1363  			u.st.docID(u.globalMeterStatusKey()),
  1364  		}, {
  1365  			metricsManagerC,
  1366  			metricsManagerKey,
  1367  		},
  1368  	})
  1369  }
  1370  
  1371  func newEntityWatcher(st *State, collName string, key interface{}) NotifyWatcher {
  1372  	return newDocWatcher(st, []docKey{{collName, key}})
  1373  }
  1374  
  1375  // docWatcher watches for changes in 1 or more mongo documents
  1376  // across collections.
  1377  type docWatcher struct {
  1378  	commonWatcher
  1379  	out chan struct{}
  1380  }
  1381  
  1382  var _ Watcher = (*docWatcher)(nil)
  1383  
  1384  // docKey identifies a single item in a single collection.
  1385  // It's used as a parameter to newDocWatcher to specify
  1386  // which documents should be watched.
  1387  type docKey struct {
  1388  	coll  string
  1389  	docId interface{}
  1390  }
  1391  
  1392  // newDocWatcher returns a new docWatcher.
  1393  // docKeys identifies the documents that should be watched (their id and which collection they are in)
  1394  func newDocWatcher(st *State, docKeys []docKey) NotifyWatcher {
  1395  	w := &docWatcher{
  1396  		commonWatcher: newCommonWatcher(st),
  1397  		out:           make(chan struct{}),
  1398  	}
  1399  	go func() {
  1400  		defer w.tomb.Done()
  1401  		defer close(w.out)
  1402  		w.tomb.Kill(w.loop(docKeys))
  1403  	}()
  1404  	return w
  1405  }
  1406  
  1407  // Changes returns the event channel for the docWatcher.
  1408  func (w *docWatcher) Changes() <-chan struct{} {
  1409  	return w.out
  1410  }
  1411  
  1412  // getTxnRevno returns the transaction revision number of the
  1413  // given document id in the given collection. It is useful to enable
  1414  // a watcher.Watcher to be primed with the correct revision
  1415  // id.
  1416  func getTxnRevno(coll mongo.Collection, id interface{}) (int64, error) {
  1417  	doc := struct {
  1418  		TxnRevno int64 `bson:"txn-revno"`
  1419  	}{}
  1420  	fields := bson.D{{"txn-revno", 1}}
  1421  	if err := coll.FindId(id).Select(fields).One(&doc); err == mgo.ErrNotFound {
  1422  		return -1, nil
  1423  	} else if err != nil {
  1424  		return 0, err
  1425  	}
  1426  	return doc.TxnRevno, nil
  1427  }
  1428  
  1429  func (w *docWatcher) loop(docKeys []docKey) error {
  1430  	in := make(chan watcher.Change)
  1431  	for _, k := range docKeys {
  1432  		coll, closer := w.st.getCollection(k.coll)
  1433  		txnRevno, err := getTxnRevno(coll, k.docId)
  1434  		closer()
  1435  		if err != nil {
  1436  			return err
  1437  		}
  1438  		w.watcher.Watch(coll.Name(), k.docId, txnRevno, in)
  1439  		defer w.watcher.Unwatch(coll.Name(), k.docId, in)
  1440  	}
  1441  	out := w.out
  1442  	for {
  1443  		select {
  1444  		case <-w.tomb.Dying():
  1445  			return tomb.ErrDying
  1446  		case <-w.watcher.Dead():
  1447  			return stateWatcherDeadError(w.watcher.Err())
  1448  		case ch := <-in:
  1449  			if _, ok := collect(ch, in, w.tomb.Dying()); !ok {
  1450  				return tomb.ErrDying
  1451  			}
  1452  			out = w.out
  1453  		case out <- struct{}{}:
  1454  			out = nil
  1455  		}
  1456  	}
  1457  }
  1458  
  1459  // machineUnitsWatcher notifies about assignments and lifecycle changes
  1460  // for all units of a machine.
  1461  //
  1462  // The first event emitted contains the unit names of all units currently
  1463  // assigned to the machine, irrespective of their life state. From then on,
  1464  // a new event is emitted whenever a unit is assigned to or unassigned from
  1465  // the machine, or the lifecycle of a unit that is currently assigned to
  1466  // the machine changes.
  1467  //
  1468  // After a unit is found to be Dead, no further event will include it.
  1469  type machineUnitsWatcher struct {
  1470  	commonWatcher
  1471  	machine *Machine
  1472  	out     chan []string
  1473  	in      chan watcher.Change
  1474  	known   map[string]Life
  1475  }
  1476  
  1477  var _ Watcher = (*machineUnitsWatcher)(nil)
  1478  
  1479  // WatchUnits returns a new StringsWatcher watching m's units.
  1480  func (m *Machine) WatchUnits() StringsWatcher {
  1481  	return newMachineUnitsWatcher(m)
  1482  }
  1483  
  1484  func newMachineUnitsWatcher(m *Machine) StringsWatcher {
  1485  	w := &machineUnitsWatcher{
  1486  		commonWatcher: newCommonWatcher(m.st),
  1487  		out:           make(chan []string),
  1488  		in:            make(chan watcher.Change),
  1489  		known:         make(map[string]Life),
  1490  		machine:       &Machine{st: m.st, doc: m.doc}, // Copy so it may be freely refreshed
  1491  	}
  1492  	go func() {
  1493  		defer w.tomb.Done()
  1494  		defer close(w.out)
  1495  		w.tomb.Kill(w.loop())
  1496  	}()
  1497  	return w
  1498  }
  1499  
  1500  // Changes returns the event channel for w.
  1501  func (w *machineUnitsWatcher) Changes() <-chan []string {
  1502  	return w.out
  1503  }
  1504  
  1505  func (w *machineUnitsWatcher) updateMachine(pending []string) (new []string, err error) {
  1506  	err = w.machine.Refresh()
  1507  	if err != nil {
  1508  		return nil, err
  1509  	}
  1510  	for _, unitName := range w.machine.doc.Principals {
  1511  		if _, ok := w.known[unitName]; !ok {
  1512  			pending, err = w.merge(pending, unitName)
  1513  			if err != nil {
  1514  				return nil, err
  1515  			}
  1516  		}
  1517  	}
  1518  	return pending, nil
  1519  }
  1520  
  1521  func (w *machineUnitsWatcher) merge(pending []string, unitName string) (new []string, err error) {
  1522  	doc := unitDoc{}
  1523  	newUnits, closer := w.st.getCollection(unitsC)
  1524  	defer closer()
  1525  	err = newUnits.FindId(unitName).One(&doc)
  1526  	if err != nil && err != mgo.ErrNotFound {
  1527  		return nil, err
  1528  	}
  1529  	life, known := w.known[unitName]
  1530  	if err == mgo.ErrNotFound || doc.Principal == "" && (doc.MachineId == "" || doc.MachineId != w.machine.doc.Id) {
  1531  		// Unit was removed or unassigned from w.machine.
  1532  		if known {
  1533  			delete(w.known, unitName)
  1534  			w.watcher.Unwatch(unitsC, w.st.docID(unitName), w.in)
  1535  			if life != Dead && !hasString(pending, unitName) {
  1536  				pending = append(pending, unitName)
  1537  			}
  1538  			for _, subunitName := range doc.Subordinates {
  1539  				if sublife, subknown := w.known[subunitName]; subknown {
  1540  					delete(w.known, subunitName)
  1541  					w.watcher.Unwatch(unitsC, w.st.docID(subunitName), w.in)
  1542  					if sublife != Dead && !hasString(pending, subunitName) {
  1543  						pending = append(pending, subunitName)
  1544  					}
  1545  				}
  1546  			}
  1547  		}
  1548  		return pending, nil
  1549  	}
  1550  	if !known {
  1551  		w.watcher.Watch(unitsC, doc.DocID, doc.TxnRevno, w.in)
  1552  		pending = append(pending, unitName)
  1553  	} else if life != doc.Life && !hasString(pending, unitName) {
  1554  		pending = append(pending, unitName)
  1555  	}
  1556  	w.known[unitName] = doc.Life
  1557  	for _, subunitName := range doc.Subordinates {
  1558  		if _, ok := w.known[subunitName]; !ok {
  1559  			pending, err = w.merge(pending, subunitName)
  1560  			if err != nil {
  1561  				return nil, err
  1562  			}
  1563  		}
  1564  	}
  1565  	return pending, nil
  1566  }
  1567  
  1568  func (w *machineUnitsWatcher) loop() error {
  1569  	defer func() {
  1570  		for unit := range w.known {
  1571  			w.watcher.Unwatch(unitsC, w.st.docID(unit), w.in)
  1572  		}
  1573  	}()
  1574  
  1575  	machines, closer := w.st.getCollection(machinesC)
  1576  	revno, err := getTxnRevno(machines, w.machine.doc.DocID)
  1577  	closer()
  1578  	if err != nil {
  1579  		return err
  1580  	}
  1581  	machineCh := make(chan watcher.Change)
  1582  	w.watcher.Watch(machinesC, w.machine.doc.DocID, revno, machineCh)
  1583  	defer w.watcher.Unwatch(machinesC, w.machine.doc.DocID, machineCh)
  1584  	changes, err := w.updateMachine([]string(nil))
  1585  	if err != nil {
  1586  		return err
  1587  	}
  1588  	out := w.out
  1589  	for {
  1590  		select {
  1591  		case <-w.watcher.Dead():
  1592  			return stateWatcherDeadError(w.watcher.Err())
  1593  		case <-w.tomb.Dying():
  1594  			return tomb.ErrDying
  1595  		case <-machineCh:
  1596  			changes, err = w.updateMachine(changes)
  1597  			if err != nil {
  1598  				return err
  1599  			}
  1600  			if len(changes) > 0 {
  1601  				out = w.out
  1602  			}
  1603  		case c := <-w.in:
  1604  			changes, err = w.merge(changes, w.st.localID(c.Id.(string)))
  1605  			if err != nil {
  1606  				return err
  1607  			}
  1608  			if len(changes) > 0 {
  1609  				out = w.out
  1610  			}
  1611  		case out <- changes:
  1612  			out = nil
  1613  			changes = nil
  1614  		}
  1615  	}
  1616  }
  1617  
  1618  // machineAddressesWatcher notifies about changes to a machine's addresses.
  1619  //
  1620  // The first event emitted contains the addresses currently assigned to the
  1621  // machine. From then on, a new event is emitted whenever the machine's
  1622  // addresses change.
  1623  type machineAddressesWatcher struct {
  1624  	commonWatcher
  1625  	machine *Machine
  1626  	out     chan struct{}
  1627  }
  1628  
  1629  var _ Watcher = (*machineAddressesWatcher)(nil)
  1630  
  1631  // WatchAddresses returns a new NotifyWatcher watching m's addresses.
  1632  func (m *Machine) WatchAddresses() NotifyWatcher {
  1633  	return newMachineAddressesWatcher(m)
  1634  }
  1635  
  1636  func newMachineAddressesWatcher(m *Machine) NotifyWatcher {
  1637  	w := &machineAddressesWatcher{
  1638  		commonWatcher: newCommonWatcher(m.st),
  1639  		out:           make(chan struct{}),
  1640  		machine:       &Machine{st: m.st, doc: m.doc}, // Copy so it may be freely refreshed
  1641  	}
  1642  	go func() {
  1643  		defer w.tomb.Done()
  1644  		defer close(w.out)
  1645  		w.tomb.Kill(w.loop())
  1646  	}()
  1647  	return w
  1648  }
  1649  
  1650  // Changes returns the event channel for w.
  1651  func (w *machineAddressesWatcher) Changes() <-chan struct{} {
  1652  	return w.out
  1653  }
  1654  
  1655  func (w *machineAddressesWatcher) loop() error {
  1656  	machines, closer := w.st.getCollection(machinesC)
  1657  	revno, err := getTxnRevno(machines, w.machine.doc.DocID)
  1658  	closer()
  1659  	if err != nil {
  1660  		return err
  1661  	}
  1662  	machineCh := make(chan watcher.Change)
  1663  	w.watcher.Watch(machinesC, w.machine.doc.DocID, revno, machineCh)
  1664  	defer w.watcher.Unwatch(machinesC, w.machine.doc.DocID, machineCh)
  1665  	addresses := w.machine.Addresses()
  1666  	out := w.out
  1667  	for {
  1668  		select {
  1669  		case <-w.watcher.Dead():
  1670  			return stateWatcherDeadError(w.watcher.Err())
  1671  		case <-w.tomb.Dying():
  1672  			return tomb.ErrDying
  1673  		case <-machineCh:
  1674  			if err := w.machine.Refresh(); err != nil {
  1675  				return err
  1676  			}
  1677  			newAddresses := w.machine.Addresses()
  1678  			if !addressesEqual(newAddresses, addresses) {
  1679  				addresses = newAddresses
  1680  				out = w.out
  1681  			}
  1682  		case out <- struct{}{}:
  1683  			out = nil
  1684  		}
  1685  	}
  1686  }
  1687  
  1688  // WatchCleanups starts and returns a CleanupWatcher.
  1689  func (st *State) WatchCleanups() NotifyWatcher {
  1690  	return newNotifyCollWatcher(st, cleanupsC, isLocalID(st))
  1691  }
  1692  
  1693  // actionStatusWatcher is a StringsWatcher that filters notifications
  1694  // to Action Id's that match the ActionReceiver and ActionStatus set
  1695  // provided.
  1696  type actionStatusWatcher struct {
  1697  	commonWatcher
  1698  	source         chan watcher.Change
  1699  	sink           chan []string
  1700  	receiverFilter bson.D
  1701  	statusFilter   bson.D
  1702  }
  1703  
  1704  var _ StringsWatcher = (*actionStatusWatcher)(nil)
  1705  
  1706  // newActionStatusWatcher returns the StringsWatcher that will notify
  1707  // on changes to Actions with the given ActionReceiver and ActionStatus
  1708  // filters.
  1709  func newActionStatusWatcher(st *State, receivers []ActionReceiver, statusSet ...ActionStatus) StringsWatcher {
  1710  	watchLogger.Debugf("newActionStatusWatcher receivers:'%+v', statuses'%+v'", receivers, statusSet)
  1711  	w := &actionStatusWatcher{
  1712  		commonWatcher:  newCommonWatcher(st),
  1713  		source:         make(chan watcher.Change),
  1714  		sink:           make(chan []string),
  1715  		receiverFilter: actionReceiverInCollectionOp(receivers...),
  1716  		statusFilter:   statusInCollectionOp(statusSet...),
  1717  	}
  1718  
  1719  	go func() {
  1720  		defer w.tomb.Done()
  1721  		defer close(w.sink)
  1722  		w.tomb.Kill(w.loop())
  1723  	}()
  1724  
  1725  	return w
  1726  }
  1727  
  1728  // Changes returns the channel that sends the ids of any
  1729  // Actions that change in the actionsC collection, if they
  1730  // match the ActionReceiver and ActionStatus filters on the
  1731  // watcher.
  1732  func (w *actionStatusWatcher) Changes() <-chan []string {
  1733  	watchLogger.Tracef("actionStatusWatcher Changes()")
  1734  	return w.sink
  1735  }
  1736  
  1737  // loop performs the main event loop cycle, polling for changes and
  1738  // responding to Changes requests
  1739  func (w *actionStatusWatcher) loop() error {
  1740  	watchLogger.Tracef("actionStatusWatcher loop()")
  1741  	var (
  1742  		changes []string
  1743  		in      <-chan watcher.Change = w.source
  1744  		out     chan<- []string       = w.sink
  1745  	)
  1746  	w.watcher.WatchCollectionWithFilter(actionsC, w.source, isLocalID(w.st))
  1747  	defer w.watcher.UnwatchCollection(actionsC, w.source)
  1748  
  1749  	changes, err := w.initial()
  1750  	if err != nil {
  1751  		return err
  1752  	}
  1753  
  1754  	for {
  1755  		select {
  1756  		case <-w.tomb.Dying():
  1757  			return tomb.ErrDying
  1758  		case <-w.watcher.Dead():
  1759  			return stateWatcherDeadError(w.watcher.Err())
  1760  		case ch := <-in:
  1761  			updates, ok := collect(ch, in, w.tomb.Dying())
  1762  			if !ok {
  1763  				return tomb.ErrDying
  1764  			}
  1765  			if err := w.filterAndMergeIds(&changes, updates); err != nil {
  1766  				return err
  1767  			}
  1768  			if len(changes) > 0 {
  1769  				out = w.sink
  1770  			}
  1771  		case out <- changes:
  1772  			changes = nil
  1773  			out = nil
  1774  		}
  1775  	}
  1776  }
  1777  
  1778  // initial pre-loads the id's that have already been added to the
  1779  // collection that would otherwise not normally trigger the watcher
  1780  func (w *actionStatusWatcher) initial() ([]string, error) {
  1781  	watchLogger.Tracef("actionStatusWatcher initial()")
  1782  	return w.matchingIds()
  1783  }
  1784  
  1785  // matchingIds is a helper function that filters the actionsC collection
  1786  // on the ActionReceivers and ActionStatus set defined on the watcher.
  1787  // If ids are passed in the collection is further filtered to only
  1788  // Actions that also have one of the supplied _id's.
  1789  func (w *actionStatusWatcher) matchingIds(ids ...string) ([]string, error) {
  1790  	watchLogger.Tracef("actionStatusWatcher matchingIds() ids:'%+v'", ids)
  1791  
  1792  	coll, closer := w.st.getCollection(actionsC)
  1793  	defer closer()
  1794  
  1795  	idFilter := localIdInCollectionOp(w.st, ids...)
  1796  	query := bson.D{{"$and", []bson.D{idFilter, w.receiverFilter, w.statusFilter}}}
  1797  	iter := coll.Find(query).Iter()
  1798  	var found []string
  1799  	var doc actionDoc
  1800  	for iter.Next(&doc) {
  1801  		found = append(found, w.st.localID(doc.DocId))
  1802  	}
  1803  	watchLogger.Debugf("actionStatusWatcher matchingIds() ids:'%+v', found:'%+v'", ids, found)
  1804  	return found, iter.Close()
  1805  }
  1806  
  1807  // filterAndMergeIds combines existing pending changes along with
  1808  // updates from the upstream watcher, and updates the changes set.
  1809  // If the upstream changes do not match the ActionReceivers and
  1810  // ActionStatus set filters defined on the watcher, they are silently
  1811  // dropped.
  1812  func (w *actionStatusWatcher) filterAndMergeIds(changes *[]string, updates map[interface{}]bool) error {
  1813  	watchLogger.Tracef("actionStatusWatcher filterAndMergeIds(changes:'%+v', updates:'%+v')", changes, updates)
  1814  	var adds []string
  1815  	for id, exists := range updates {
  1816  		switch id := id.(type) {
  1817  		case string:
  1818  			localId := w.st.localID(id)
  1819  			chIx, idAlreadyInChangeset := indexOf(localId, *changes)
  1820  			if exists {
  1821  				if !idAlreadyInChangeset {
  1822  					adds = append(adds, localId)
  1823  				}
  1824  			} else {
  1825  				if idAlreadyInChangeset {
  1826  					// remove id from changes
  1827  					*changes = append([]string(*changes)[:chIx], []string(*changes)[chIx+1:]...)
  1828  				}
  1829  			}
  1830  		default:
  1831  			return errors.Errorf("id is not of type string, got %T", id)
  1832  		}
  1833  	}
  1834  	if len(adds) > 0 {
  1835  		ids, err := w.matchingIds(adds...)
  1836  		if err != nil {
  1837  			return errors.Trace(err)
  1838  		}
  1839  		*changes = append(*changes, ids...)
  1840  	}
  1841  	return nil
  1842  }
  1843  
  1844  // inCollectionOp takes a key name and a list of potential values and
  1845  // returns a bson.D Op that will match on the supplied key and values.
  1846  func inCollectionOp(key string, ids ...string) bson.D {
  1847  	ret := bson.D{}
  1848  	switch len(ids) {
  1849  	case 0:
  1850  	case 1:
  1851  		ret = append(ret, bson.DocElem{key, ids[0]})
  1852  	default:
  1853  		ret = append(ret, bson.DocElem{key, bson.D{{"$in", ids}}})
  1854  	}
  1855  	return ret
  1856  }
  1857  
  1858  // localIdInCollectionOp is a special form of inCollectionOp that just
  1859  // converts id's to their model-uuid prefixed form.
  1860  func localIdInCollectionOp(st modelBackend, localIds ...string) bson.D {
  1861  	ids := make([]string, len(localIds))
  1862  	for i, id := range localIds {
  1863  		ids[i] = st.docID(id)
  1864  	}
  1865  	return inCollectionOp("_id", ids...)
  1866  }
  1867  
  1868  // actionReceiverInCollectionOp is a special form of inCollectionOp
  1869  // that just converts []ActionReceiver to a []string containing the
  1870  // ActionReceiver Name() values.
  1871  func actionReceiverInCollectionOp(receivers ...ActionReceiver) bson.D {
  1872  	ids := make([]string, len(receivers))
  1873  	for i, r := range receivers {
  1874  		ids[i] = r.Tag().Id()
  1875  	}
  1876  	return inCollectionOp("receiver", ids...)
  1877  }
  1878  
  1879  // statusInCollectionOp is a special form of inCollectionOp that just
  1880  // converts []ActionStatus to a []string with the same values.
  1881  func statusInCollectionOp(statusSet ...ActionStatus) bson.D {
  1882  	ids := make([]string, len(statusSet))
  1883  	for i, s := range statusSet {
  1884  		ids[i] = string(s)
  1885  	}
  1886  	return inCollectionOp("status", ids...)
  1887  }
  1888  
  1889  // collectionWatcher is a StringsWatcher that watches for changes on the
  1890  // specified collection that match a filter on the id.
  1891  type collectionWatcher struct {
  1892  	commonWatcher
  1893  	colWCfg
  1894  	source chan watcher.Change
  1895  	sink   chan []string
  1896  }
  1897  
  1898  // colWCfg contains the parameters for watching a collection.
  1899  type colWCfg struct {
  1900  	col    string
  1901  	filter func(interface{}) bool
  1902  	idconv func(string) string
  1903  }
  1904  
  1905  // newcollectionWatcher starts and returns a new StringsWatcher configured
  1906  // with the given collection and filter function
  1907  func newcollectionWatcher(st *State, cfg colWCfg) StringsWatcher {
  1908  	// Always ensure that there is at least filtering on the
  1909  	// model in place.
  1910  	backstop := isLocalID(st)
  1911  	if cfg.filter == nil {
  1912  		cfg.filter = backstop
  1913  	} else {
  1914  		innerFilter := cfg.filter
  1915  		cfg.filter = func(id interface{}) bool {
  1916  			if !backstop(id) {
  1917  				return false
  1918  			}
  1919  			return innerFilter(id)
  1920  		}
  1921  	}
  1922  
  1923  	w := &collectionWatcher{
  1924  		colWCfg:       cfg,
  1925  		commonWatcher: newCommonWatcher(st),
  1926  		source:        make(chan watcher.Change),
  1927  		sink:          make(chan []string),
  1928  	}
  1929  
  1930  	go func() {
  1931  		defer w.tomb.Done()
  1932  		defer close(w.sink)
  1933  		defer close(w.source)
  1934  		w.tomb.Kill(w.loop())
  1935  	}()
  1936  
  1937  	return w
  1938  }
  1939  
  1940  // Changes returns the event channel for this watcher
  1941  func (w *collectionWatcher) Changes() <-chan []string {
  1942  	return w.sink
  1943  }
  1944  
  1945  // loop performs the main event loop cycle, polling for changes and
  1946  // responding to Changes requests
  1947  func (w *collectionWatcher) loop() error {
  1948  	var (
  1949  		changes []string
  1950  		in      = (<-chan watcher.Change)(w.source)
  1951  		out     = (chan<- []string)(w.sink)
  1952  	)
  1953  
  1954  	w.watcher.WatchCollectionWithFilter(w.col, w.source, w.filter)
  1955  	defer w.watcher.UnwatchCollection(w.col, w.source)
  1956  
  1957  	changes, err := w.initial()
  1958  	if err != nil {
  1959  		return err
  1960  	}
  1961  
  1962  	for {
  1963  		select {
  1964  		case <-w.tomb.Dying():
  1965  			return tomb.ErrDying
  1966  		case <-w.watcher.Dead():
  1967  			return stateWatcherDeadError(w.watcher.Err())
  1968  		case ch := <-in:
  1969  			updates, ok := collect(ch, in, w.tomb.Dying())
  1970  			if !ok {
  1971  				return tomb.ErrDying
  1972  			}
  1973  			if err := w.mergeIds(&changes, updates); err != nil {
  1974  				return err
  1975  			}
  1976  			if len(changes) > 0 {
  1977  				out = w.sink
  1978  			}
  1979  		case out <- changes:
  1980  			changes = []string{}
  1981  			out = nil
  1982  		}
  1983  	}
  1984  }
  1985  
  1986  // makeIdFilter constructs a predicate to filter keys that have the
  1987  // prefix matching one of the passed in ActionReceivers, or returns nil
  1988  // if tags is empty
  1989  func makeIdFilter(st *State, marker string, receivers ...ActionReceiver) func(interface{}) bool {
  1990  	if len(receivers) == 0 {
  1991  		return nil
  1992  	}
  1993  	ensureMarkerFn := ensureSuffixFn(marker)
  1994  	prefixes := make([]string, len(receivers))
  1995  	for ix, receiver := range receivers {
  1996  		prefixes[ix] = st.docID(ensureMarkerFn(receiver.Tag().Id()))
  1997  	}
  1998  
  1999  	return func(key interface{}) bool {
  2000  		switch key.(type) {
  2001  		case string:
  2002  			for _, prefix := range prefixes {
  2003  				if strings.HasPrefix(key.(string), prefix) {
  2004  					return true
  2005  				}
  2006  			}
  2007  		default:
  2008  			watchLogger.Errorf("key is not type string, got %T", key)
  2009  		}
  2010  		return false
  2011  	}
  2012  }
  2013  
  2014  // initial pre-loads the id's that have already been added to the
  2015  // collection that would otherwise not normally trigger the watcher
  2016  func (w *collectionWatcher) initial() ([]string, error) {
  2017  	var ids []string
  2018  	var doc struct {
  2019  		DocId string `bson:"_id"`
  2020  	}
  2021  	coll, closer := w.st.getCollection(w.col)
  2022  	defer closer()
  2023  	iter := coll.Find(nil).Iter()
  2024  	for iter.Next(&doc) {
  2025  		if w.filter == nil || w.filter(doc.DocId) {
  2026  			id := w.st.localID(doc.DocId)
  2027  			if w.idconv != nil {
  2028  				id = w.idconv(id)
  2029  			}
  2030  			ids = append(ids, id)
  2031  		}
  2032  	}
  2033  	return ids, iter.Close()
  2034  }
  2035  
  2036  // mergeIds is used for merging actionId's and actionResultId's that
  2037  // come in via the updates map. It cleans up the pending changes to
  2038  // account for id's being removed before the watcher consumes them,
  2039  // and to account for the potential overlap between the id's that were
  2040  // pending before the watcher started, and the new id's detected by the
  2041  // watcher.
  2042  // Additionally, mergeIds strips the model UUID prefix from the id
  2043  // before emitting it through the watcher.
  2044  func (w *collectionWatcher) mergeIds(changes *[]string, updates map[interface{}]bool) error {
  2045  	return mergeIds(w.st, changes, updates, w.idconv)
  2046  }
  2047  
  2048  func mergeIds(st modelBackend, changes *[]string, updates map[interface{}]bool, idconv func(string) string) error {
  2049  	for val, idExists := range updates {
  2050  		id, ok := val.(string)
  2051  		if !ok {
  2052  			return errors.Errorf("id is not of type string, got %T", val)
  2053  		}
  2054  
  2055  		// Strip off the env UUID prefix. We only expect ids for a
  2056  		// single model.
  2057  		id, err := st.strictLocalID(id)
  2058  		if err != nil {
  2059  			return errors.Annotatef(err, "collection watcher")
  2060  		}
  2061  
  2062  		if idconv != nil {
  2063  			id = idconv(id)
  2064  		}
  2065  
  2066  		chIx, idAlreadyInChangeset := indexOf(id, *changes)
  2067  		if idExists {
  2068  			if !idAlreadyInChangeset {
  2069  				*changes = append(*changes, id)
  2070  			}
  2071  		} else {
  2072  			if idAlreadyInChangeset {
  2073  				// remove id from changes
  2074  				*changes = append([]string(*changes)[:chIx], []string(*changes)[chIx+1:]...)
  2075  			}
  2076  		}
  2077  	}
  2078  	return nil
  2079  }
  2080  
  2081  func actionNotificationIdToActionId(id string) string {
  2082  	ix := strings.Index(id, actionMarker)
  2083  	if ix == -1 {
  2084  		return id
  2085  	}
  2086  	return id[ix+len(actionMarker):]
  2087  }
  2088  
  2089  func indexOf(find string, in []string) (int, bool) {
  2090  	for ix, cur := range in {
  2091  		if cur == find {
  2092  			return ix, true
  2093  		}
  2094  	}
  2095  	return -1, false
  2096  }
  2097  
  2098  // ensureSuffixFn returns a function that will make sure the passed in
  2099  // string has the marker token at the end of it
  2100  func ensureSuffixFn(marker string) func(string) string {
  2101  	return func(p string) string {
  2102  		if !strings.HasSuffix(p, marker) {
  2103  			p = p + marker
  2104  		}
  2105  		return p
  2106  	}
  2107  }
  2108  
  2109  // watchEnqueuedActionsFilteredBy starts and returns a StringsWatcher
  2110  // that notifies on new Actions being enqueued on the ActionRecevers
  2111  // being watched.
  2112  func (st *State) watchEnqueuedActionsFilteredBy(receivers ...ActionReceiver) StringsWatcher {
  2113  	return newcollectionWatcher(st, colWCfg{
  2114  		col:    actionNotificationsC,
  2115  		filter: makeIdFilter(st, actionMarker, receivers...),
  2116  		idconv: actionNotificationIdToActionId,
  2117  	})
  2118  }
  2119  
  2120  // WatchControllerStatusChanges starts and returns a StringsWatcher that
  2121  // notifies when the status of a controller machine changes.
  2122  // TODO(cherylj) Add unit tests for this, as per bug 1543408.
  2123  func (st *State) WatchControllerStatusChanges() StringsWatcher {
  2124  	return newcollectionWatcher(st, colWCfg{
  2125  		col:    statusesC,
  2126  		filter: makeControllerIdFilter(st),
  2127  	})
  2128  }
  2129  
  2130  func makeControllerIdFilter(st *State) func(interface{}) bool {
  2131  	initialInfo, err := st.ControllerInfo()
  2132  	if err != nil {
  2133  		return nil
  2134  	}
  2135  	machines := initialInfo.MachineIds
  2136  	return func(key interface{}) bool {
  2137  		switch key.(type) {
  2138  		case string:
  2139  			info, err := st.ControllerInfo()
  2140  			if err != nil {
  2141  				// Most likely, things will be killed and
  2142  				// restarted if we hit this error.  Just use
  2143  				// the machine list we knew about last time.
  2144  				logger.Debugf("unable to get controller info: %v", err)
  2145  			} else {
  2146  				machines = info.MachineIds
  2147  			}
  2148  			for _, machine := range machines {
  2149  				if strings.HasSuffix(key.(string), fmt.Sprintf("m#%s", machine)) {
  2150  					return true
  2151  				}
  2152  			}
  2153  		default:
  2154  			watchLogger.Errorf("key is not type string, got %T", key)
  2155  		}
  2156  		return false
  2157  	}
  2158  
  2159  }
  2160  
  2161  // WatchActionResults starts and returns a StringsWatcher that
  2162  // notifies on new ActionResults being added.
  2163  func (st *State) WatchActionResults() StringsWatcher {
  2164  	return st.WatchActionResultsFilteredBy()
  2165  }
  2166  
  2167  // WatchActionResultsFilteredBy starts and returns a StringsWatcher
  2168  // that notifies on new ActionResults being added for the ActionRecevers
  2169  // being watched.
  2170  func (st *State) WatchActionResultsFilteredBy(receivers ...ActionReceiver) StringsWatcher {
  2171  	return newActionStatusWatcher(st, receivers, []ActionStatus{ActionCompleted, ActionCancelled, ActionFailed}...)
  2172  }
  2173  
  2174  // openedPortsWatcher notifies of changes in the openedPorts
  2175  // collection
  2176  type openedPortsWatcher struct {
  2177  	commonWatcher
  2178  	known map[string]int64
  2179  	out   chan []string
  2180  }
  2181  
  2182  var _ Watcher = (*openedPortsWatcher)(nil)
  2183  
  2184  // WatchOpenedPorts starts and returns a StringsWatcher notifying of changes to
  2185  // the openedPorts collection. Reported changes have the following format:
  2186  // "<machine-id>:[<subnet-CIDR>]", i.e. "0:10.20.0.0/16" or "1:" (empty subnet
  2187  // ID is allowed for backwards-compatibility).
  2188  func (st *State) WatchOpenedPorts() StringsWatcher {
  2189  	return newOpenedPortsWatcher(st)
  2190  }
  2191  
  2192  func newOpenedPortsWatcher(st *State) StringsWatcher {
  2193  	w := &openedPortsWatcher{
  2194  		commonWatcher: newCommonWatcher(st),
  2195  		known:         make(map[string]int64),
  2196  		out:           make(chan []string),
  2197  	}
  2198  	go func() {
  2199  		defer w.tomb.Done()
  2200  		defer close(w.out)
  2201  		w.tomb.Kill(w.loop())
  2202  	}()
  2203  
  2204  	return w
  2205  }
  2206  
  2207  // Changes returns the event channel for w
  2208  func (w *openedPortsWatcher) Changes() <-chan []string {
  2209  	return w.out
  2210  }
  2211  
  2212  // transformId converts a global key for a ports document (e.g.
  2213  // "m#42#0.1.2.0/24") into a colon-separated string with the machine and subnet
  2214  // IDs (e.g. "42:0.1.2.0/24"). Subnet ID (a.k.a. CIDR) can be empty for
  2215  // backwards-compatibility.
  2216  func (w *openedPortsWatcher) transformID(globalKey string) (string, error) {
  2217  	parts, err := extractPortsIDParts(globalKey)
  2218  	if err != nil {
  2219  		return "", errors.Trace(err)
  2220  	}
  2221  	return fmt.Sprintf("%s:%s", parts[machineIDPart], parts[subnetIDPart]), nil
  2222  }
  2223  
  2224  func (w *openedPortsWatcher) initial() (set.Strings, error) {
  2225  	ports, closer := w.st.getCollection(openedPortsC)
  2226  	defer closer()
  2227  
  2228  	portDocs := set.NewStrings()
  2229  	var doc portsDoc
  2230  	iter := ports.Find(nil).Select(bson.D{{"_id", 1}, {"txn-revno", 1}}).Iter()
  2231  	for iter.Next(&doc) {
  2232  		id, err := w.st.strictLocalID(doc.DocID)
  2233  		if err != nil {
  2234  			return nil, errors.Trace(err)
  2235  		}
  2236  		if doc.TxnRevno != -1 {
  2237  			w.known[id] = doc.TxnRevno
  2238  		}
  2239  		if changeID, err := w.transformID(id); err != nil {
  2240  			logger.Errorf(err.Error())
  2241  		} else {
  2242  			portDocs.Add(changeID)
  2243  		}
  2244  	}
  2245  	return portDocs, errors.Trace(iter.Close())
  2246  }
  2247  
  2248  func (w *openedPortsWatcher) loop() error {
  2249  	in := make(chan watcher.Change)
  2250  	changes, err := w.initial()
  2251  	if err != nil {
  2252  		return errors.Trace(err)
  2253  	}
  2254  	w.watcher.WatchCollectionWithFilter(openedPortsC, in, isLocalID(w.st))
  2255  	defer w.watcher.UnwatchCollection(openedPortsC, in)
  2256  
  2257  	out := w.out
  2258  	for {
  2259  		select {
  2260  		case <-w.tomb.Dying():
  2261  			return tomb.ErrDying
  2262  		case <-w.watcher.Dead():
  2263  			return stateWatcherDeadError(w.watcher.Err())
  2264  		case ch := <-in:
  2265  			if err = w.merge(changes, ch); err != nil {
  2266  				return errors.Trace(err)
  2267  			}
  2268  			if !changes.IsEmpty() {
  2269  				out = w.out
  2270  			}
  2271  		case out <- changes.Values():
  2272  			out = nil
  2273  			changes = set.NewStrings()
  2274  		}
  2275  	}
  2276  }
  2277  
  2278  func (w *openedPortsWatcher) merge(ids set.Strings, change watcher.Change) error {
  2279  	id, ok := change.Id.(string)
  2280  	if !ok {
  2281  		return errors.Errorf("id %v is not of type string, got %T", id, id)
  2282  	}
  2283  	localID, err := w.st.strictLocalID(id)
  2284  	if err != nil {
  2285  		return errors.Trace(err)
  2286  	}
  2287  	if change.Revno == -1 {
  2288  		delete(w.known, localID)
  2289  		if changeID, err := w.transformID(localID); err != nil {
  2290  			logger.Errorf(err.Error())
  2291  		} else {
  2292  			// Report the removed id.
  2293  			ids.Add(changeID)
  2294  		}
  2295  		return nil
  2296  	}
  2297  	openedPorts, closer := w.st.getCollection(openedPortsC)
  2298  	currentRevno, err := getTxnRevno(openedPorts, id)
  2299  	closer()
  2300  	if err != nil {
  2301  		return err
  2302  	}
  2303  	knownRevno, isKnown := w.known[localID]
  2304  	w.known[localID] = currentRevno
  2305  	if !isKnown || currentRevno > knownRevno {
  2306  		if changeID, err := w.transformID(localID); err != nil {
  2307  			logger.Errorf(err.Error())
  2308  		} else {
  2309  			// Report the unknown-so-far id.
  2310  			ids.Add(changeID)
  2311  		}
  2312  	}
  2313  	return nil
  2314  }
  2315  
  2316  // WatchForRebootEvent returns a notify watcher that will trigger an event
  2317  // when the reboot flag is set on our machine agent, our parent machine agent
  2318  // or grandparent machine agent
  2319  func (m *Machine) WatchForRebootEvent() NotifyWatcher {
  2320  	machineIds := m.machinesToCareAboutRebootsFor()
  2321  	machines := set.NewStrings(machineIds...)
  2322  
  2323  	filter := func(key interface{}) bool {
  2324  		if id, ok := key.(string); ok {
  2325  			if id, err := m.st.strictLocalID(id); err == nil {
  2326  				return machines.Contains(id)
  2327  			} else {
  2328  				return false
  2329  			}
  2330  		}
  2331  		return false
  2332  	}
  2333  	return newNotifyCollWatcher(m.st, rebootC, filter)
  2334  }
  2335  
  2336  // blockDevicesWatcher notifies about changes to all block devices
  2337  // associated with a machine.
  2338  type blockDevicesWatcher struct {
  2339  	commonWatcher
  2340  	machineId string
  2341  	out       chan struct{}
  2342  }
  2343  
  2344  var _ NotifyWatcher = (*blockDevicesWatcher)(nil)
  2345  
  2346  func newBlockDevicesWatcher(st *State, machineId string) NotifyWatcher {
  2347  	w := &blockDevicesWatcher{
  2348  		commonWatcher: newCommonWatcher(st),
  2349  		machineId:     machineId,
  2350  		out:           make(chan struct{}),
  2351  	}
  2352  	go func() {
  2353  		defer w.tomb.Done()
  2354  		defer close(w.out)
  2355  		w.tomb.Kill(w.loop())
  2356  	}()
  2357  	return w
  2358  }
  2359  
  2360  // Changes returns the event channel for w.
  2361  func (w *blockDevicesWatcher) Changes() <-chan struct{} {
  2362  	return w.out
  2363  }
  2364  
  2365  func (w *blockDevicesWatcher) loop() error {
  2366  	docID := w.st.docID(w.machineId)
  2367  	coll, closer := w.st.getCollection(blockDevicesC)
  2368  	revno, err := getTxnRevno(coll, docID)
  2369  	closer()
  2370  	if err != nil {
  2371  		return errors.Trace(err)
  2372  	}
  2373  	changes := make(chan watcher.Change)
  2374  	w.watcher.Watch(blockDevicesC, docID, revno, changes)
  2375  	defer w.watcher.Unwatch(blockDevicesC, docID, changes)
  2376  	blockDevices, err := getBlockDevices(w.st, w.machineId)
  2377  	if err != nil {
  2378  		return errors.Trace(err)
  2379  	}
  2380  	out := w.out
  2381  	for {
  2382  		select {
  2383  		case <-w.watcher.Dead():
  2384  			return stateWatcherDeadError(w.watcher.Err())
  2385  		case <-w.tomb.Dying():
  2386  			return tomb.ErrDying
  2387  		case <-changes:
  2388  			newBlockDevices, err := getBlockDevices(w.st, w.machineId)
  2389  			if err != nil {
  2390  				return errors.Trace(err)
  2391  			}
  2392  			if !reflect.DeepEqual(newBlockDevices, blockDevices) {
  2393  				blockDevices = newBlockDevices
  2394  				out = w.out
  2395  			}
  2396  		case out <- struct{}{}:
  2397  			out = nil
  2398  		}
  2399  	}
  2400  }
  2401  
  2402  // WatchForMigration returns a notify watcher which reports when
  2403  // a migration is in progress for the model associated with the
  2404  // State.
  2405  func (st *State) WatchForMigration() NotifyWatcher {
  2406  	return newMigrationActiveWatcher(st)
  2407  }
  2408  
  2409  type migrationActiveWatcher struct {
  2410  	commonWatcher
  2411  	collName string
  2412  	id       string
  2413  	sink     chan struct{}
  2414  }
  2415  
  2416  func newMigrationActiveWatcher(st *State) NotifyWatcher {
  2417  	w := &migrationActiveWatcher{
  2418  		commonWatcher: newCommonWatcher(st),
  2419  		collName:      migrationsActiveC,
  2420  		id:            st.ModelUUID(),
  2421  		sink:          make(chan struct{}),
  2422  	}
  2423  	go func() {
  2424  		defer w.tomb.Done()
  2425  		defer close(w.sink)
  2426  		w.tomb.Kill(w.loop())
  2427  	}()
  2428  	return w
  2429  }
  2430  
  2431  // Changes returns the event channel for this watcher.
  2432  func (w *migrationActiveWatcher) Changes() <-chan struct{} {
  2433  	return w.sink
  2434  }
  2435  
  2436  func (w *migrationActiveWatcher) loop() error {
  2437  	collection, closer := w.st.getCollection(w.collName)
  2438  	revno, err := getTxnRevno(collection, w.id)
  2439  	closer()
  2440  	if err != nil {
  2441  		return errors.Trace(err)
  2442  	}
  2443  
  2444  	in := make(chan watcher.Change)
  2445  	w.watcher.Watch(w.collName, w.id, revno, in)
  2446  	defer w.watcher.Unwatch(w.collName, w.id, in)
  2447  
  2448  	out := w.sink
  2449  	for {
  2450  		select {
  2451  		case <-w.tomb.Dying():
  2452  			return tomb.ErrDying
  2453  		case <-w.watcher.Dead():
  2454  			return stateWatcherDeadError(w.watcher.Err())
  2455  		case change := <-in:
  2456  			if _, ok := collect(change, in, w.tomb.Dying()); !ok {
  2457  				return tomb.ErrDying
  2458  			}
  2459  			out = w.sink
  2460  		case out <- struct{}{}:
  2461  			out = nil
  2462  		}
  2463  	}
  2464  }
  2465  
  2466  // WatchMigrationStatus returns a NotifyWatcher which triggers
  2467  // whenever the status of latest migration for the State's model
  2468  // changes. One instance can be used across migrations. The watcher
  2469  // will report changes when one migration finishes and another one
  2470  // begins.
  2471  //
  2472  // Note that this watcher does not produce an initial event if there's
  2473  // never been a migration attempt for the model.
  2474  func (st *State) WatchMigrationStatus() NotifyWatcher {
  2475  	// Watch the entire migrationsStatusC collection for migration
  2476  	// status updates related to the State's model. This is more
  2477  	// efficient and simpler than tracking the current active
  2478  	// migration (and changing watchers when one migration finishes
  2479  	// and another starts.
  2480  	//
  2481  	// This approach is safe because there are strong guarantees that
  2482  	// there will only be one active migration per model. The watcher
  2483  	// will only see changes for one migration status document at a
  2484  	// time for the model.
  2485  	return newNotifyCollWatcher(st, migrationsStatusC, isLocalID(st))
  2486  }
  2487  
  2488  // WatchMachineRemovals returns a NotifyWatcher which triggers
  2489  // whenever machine removal records are added or removed.
  2490  func (st *State) WatchMachineRemovals() NotifyWatcher {
  2491  	return newNotifyCollWatcher(st, machineRemovalsC, isLocalID(st))
  2492  }
  2493  
  2494  // notifyCollWatcher implements NotifyWatcher, triggering when a
  2495  // change is seen in a specific collection matching the provided
  2496  // filter function.
  2497  type notifyCollWatcher struct {
  2498  	commonWatcher
  2499  	collName string
  2500  	filter   func(interface{}) bool
  2501  	sink     chan struct{}
  2502  }
  2503  
  2504  func newNotifyCollWatcher(st *State, collName string, filter func(interface{}) bool) NotifyWatcher {
  2505  	w := &notifyCollWatcher{
  2506  		commonWatcher: newCommonWatcher(st),
  2507  		collName:      collName,
  2508  		filter:        filter,
  2509  		sink:          make(chan struct{}),
  2510  	}
  2511  	go func() {
  2512  		defer w.tomb.Done()
  2513  		defer close(w.sink)
  2514  		w.tomb.Kill(w.loop())
  2515  	}()
  2516  	return w
  2517  }
  2518  
  2519  // Changes returns the event channel for this watcher.
  2520  func (w *notifyCollWatcher) Changes() <-chan struct{} {
  2521  	return w.sink
  2522  }
  2523  
  2524  func (w *notifyCollWatcher) loop() error {
  2525  	in := make(chan watcher.Change)
  2526  
  2527  	w.watcher.WatchCollectionWithFilter(w.collName, in, w.filter)
  2528  	defer w.watcher.UnwatchCollection(w.collName, in)
  2529  
  2530  	out := w.sink // out set so that initial event is sent.
  2531  	for {
  2532  		select {
  2533  		case <-w.tomb.Dying():
  2534  			return tomb.ErrDying
  2535  		case <-w.watcher.Dead():
  2536  			return stateWatcherDeadError(w.watcher.Err())
  2537  		case change := <-in:
  2538  			if _, ok := collect(change, in, w.tomb.Dying()); !ok {
  2539  				return tomb.ErrDying
  2540  			}
  2541  			out = w.sink
  2542  		case out <- struct{}{}:
  2543  			out = nil
  2544  		}
  2545  	}
  2546  }