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