// WatchUnitLXDProfileUpgradeNotifications returns a StringsWatcher for observing
// changes to the lxd profile changes for one unit.
509677
func (u *LXDProfileAPI) WatchUnitLXDProfileUpgradeNotifications(args params.Entities) (params.StringsWatchResults, error) {
	u.logger.Tracef("Starting WatchUnitLXDProfileUpgradeNotifications with %+v", args)
	result := params.StringsWatchResults{
		Results: make([]params.StringsWatchResult, len(args.Entities)),
	}
	canAccess, err := u.accessUnit()
	if err != nil {
		return params.StringsWatchResults{}, err
	}
	for i, entity := range args.Entities {
		tag, err := names.ParseTag(entity.Tag)
		if err != nil {
			result.Results[i].Error = common.ServerError(common.ErrPerm)
			continue
		}

		if !canAccess(tag) {
			result.Results[i].Error = common.ServerError(common.ErrPerm)
			continue
		}
		unit, err := u.getLXDProfileUnit(tag)
		if err != nil {
			result.Results[i].Error = common.ServerError(err)
			continue
		}
		watcherId, initial, err := u.watchOneChangeUnitLXDProfileUpgradeNotifications(unit)
		if err != nil {
			result.Results[i].Error = common.ServerError(err)
			continue
		}

		result.Results[i].StringsWatcherId = watcherId
		result.Results[i].Changes = initial
	}
	return result, nil
}
559147
func (m *Machine) WatchUpgradeSeriesNotifications() (NotifyWatcher, error) {
	watch := newEntityWatcher(m.st, machineUpgradeSeriesLocksC, m.doc.DocID)
	if _, ok := <-watch.Changes(); ok {
		return watch, nil
	}

	return nil, watcher.EnsureErr(watch)
}
98118
func (st *state) WatchForRebootEvent() (watcher.NotifyWatcher, error) {
	var result params.NotifyWatchResult

	if err := st.facade.FacadeCall("WatchForRebootEvent", nil, &result); err != nil {
		return nil, err
	}
	if result.Error != nil {
		return nil, result.Error
	}

	w := apiwatcher.NewNotifyWatcher(st.facade.RawAPICaller(), result)
	return w, nil
}
182100
func (_m *DBClient) UpdateProvisionWatcher(pw models.ProvisionWatcher) error {
	ret := _m.Called(pw)

	var r0 error
	if rf, ok := ret.Get(0).(func(models.ProvisionWatcher) error); ok {
		r0 = rf(pw)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}
710944
func (c *Client) WatchUnits(application string) (watcher.StringsWatcher, error) {
	applicationTag, err := applicationTag(application)
	if err != nil {
		return nil, errors.Trace(err)
	}
	args := entities(applicationTag)

	var results params.StringsWatchResults
	if err := c.facade.FacadeCall("WatchUnits", args, &results); err != nil {
		return nil, err
	}
	if n := len(results.Results); n != 1 {
		return nil, errors.Errorf("expected 1 result, got %d", n)
	}
	if err := results.Results[0].Error; err != nil {
		return nil, errors.Trace(err)
	}
	w := apiwatcher.NewStringsWatcher(c.facade.RawAPICaller(), results.Results[0])
	return w, nil
}
996579
func (w *MachineLXDProfileWatcher) addUnit(topic string, value interface{}) {
	// We don't want to respond to any events until we have been fully initialized.
	select {
	case <-w.initialized:
	case <-w.tomb.Dying():
		return
	}
	var notify bool
	defer func(notify *bool) {
		if *notify {
			logger.Tracef("notifying due to add unit requires lxd profile change machine-%s", w.machineId)
			w.notify()
			w.metrics.LXDProfileChangeHit.Inc()
		} else {
			w.metrics.LXDProfileChangeMiss.Inc()
		}
	}(&notify)

	unit, okUnit := value.(*Unit)
	if !okUnit {
		w.logError("programming error, value not of type *Unit")
		return
	}
	isSubordinate := unit.Subordinate()
	unitMachineId := unit.MachineId()
	unitName := unit.Name()

	switch {
	case unitMachineId == "" && !isSubordinate:
		logger.Tracef("%s has no machineId and not a sub", unitName)
		return
	case isSubordinate:
		principal, err := w.modeler.Unit(unit.Principal())
		if err != nil {
			logger.Tracef("unit %s is subordinate, principal %s not found", unitName, unit.Principal())
			return
		}
		if w.machineId != principal.MachineId() {
			logger.Tracef("watching unit changes on machine-%s not machine-%s", w.machineId, unitMachineId)
			return
		}
	case w.machineId != unitMachineId:
		logger.Tracef("watching unit changes on machine-%s not machine-%s", w.machineId, unitMachineId)
		return
	}
	logger.Tracef("start watching %q on machine-%s", unitName, w.machineId)
	notify = w.add(unit)

	logger.Debugf("end of unit change %#v", w.applications)
}
649989
func (u *UpgradeSeriesAPI) WatchUpgradeSeriesNotifications() (watcher.NotifyWatcher, error) {
	var results params.NotifyWatchResults
	args := params.Entities{
		Entities: []params.Entity{{Tag: u.tag.String()}},
	}
	err := u.facade.FacadeCall("WatchUpgradeSeriesNotifications", args, &results)
	if err != nil {
		return nil, err
	}
	if len(results.Results) != 1 {
		return nil, errors.Errorf("expected 1 result, got %d", len(results.Results))
	}
	result := results.Results[0]
	if result.Error != nil {
		return nil, result.Error
	}
	w := apiwatcher.NewNotifyWatcher(u.facade.RawAPICaller(), result)
	return w, nil
}
1229986
func (client *Client) WatchUpgradeSeriesNotifications(machineName string) (watcher.NotifyWatcher, string, error) {
	if client.BestAPIVersion() < 5 {
		return nil, "", errors.NotSupportedf("WatchUpgradeSeriesNotifications")
	}
	var results params.NotifyWatchResults
	args := params.Entities{
		Entities: []params.Entity{{Tag: names.NewMachineTag(machineName).String()}},
	}
	err := client.facade.FacadeCall("WatchUpgradeSeriesNotifications", args, &results)
	if err != nil {
		return nil, "", errors.Trace(err)
	}
	if len(results.Results) != 1 {
		return nil, "", errors.Errorf("expected 1 result, got %d", len(results.Results))
	}
	result := results.Results[0]
	if result.Error != nil {
		return nil, "", result.Error
	}
	w := apiwatcher.NewNotifyWatcher(client.facade.RawAPICaller(), result)
	return w, result.NotifyWatcherId, nil
}
453154
func notifyProvisionWatcherAssociates(pw models.ProvisionWatcher, action string) error {
	// Get the device service for the provision watcher
	ds, err := dbClient.GetDeviceServiceById(pw.Service.Id)
	if err != nil {
		return err
	}

	// Notify the service
	if err = notifyAssociates([]models.DeviceService{ds}, pw.Id, action, models.PROVISIONWATCHER); err != nil {
		return err
	}

	return nil
}
831731
func (r *Relation) WatchLifeSuspendedStatus() StringsWatcher {
	filter := func(id interface{}) bool {
		k, err := r.st.strictLocalID(id.(string))
		if err != nil {
			return false
		}
		return k == r.Tag().Id()
	}
	members := bson.D{{"id", r.Id()}}
	return newRelationLifeSuspendedWatcher(r.st, members, filter, nil)
}
145131
func (facade *Facade) Watch(uuid string) (watcher.NotifyWatcher, error) {
	results := params.NotifyWatchResults{}
	err := facade.call("Watch", uuid, &results)
	if err != nil {
		return nil, errors.Trace(err)
	}
	if count := len(results.Results); count != 1 {
		return nil, countError(count)
	}
	result := results.Results[0]
	if result.Error != nil {
		return nil, errors.Trace(result.Error)
	}
	apiCaller := facade.caller.RawAPICaller()
	watcher := facade.newWatcher(apiCaller, result)
	return watcher, nil
}
828833
func (p lxdStateCharmProfiler) LXDProfile() lxdprofile.LXDProfile {
	if p.Charm == nil {
		return nil
	}
	return p.Charm.LXDProfile()
}
1211866
func (sb *storageBackend) WatchUnitFilesystemAttachments(app names.ApplicationTag) StringsWatcher {
	return sb.watchHostStorageAttachments(app, filesystemAttachmentsC)
}
190422
func restUpdateProvisionWatcher(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()
	var from models.ProvisionWatcher
	if err := json.NewDecoder(r.Body).Decode(&from); err != nil {
		LoggingClient.Error(err.Error())
		http.Error(w, err.Error(), http.StatusServiceUnavailable)
		return
	}

	// Check if the provision watcher exists
	// Try by ID
	to, err := dbClient.GetProvisionWatcherById(from.Id)
	if err != nil {
		// Try by name
		if to, err = dbClient.GetProvisionWatcherByName(from.Name); err != nil {
			if err == db.ErrNotFound {
				http.Error(w, "Provision watcher not found", http.StatusNotFound)
				LoggingClient.Error("Provision watcher not found: " + err.Error())
			} else {
				LoggingClient.Error("Problem getting provision watcher: " + err.Error())
				http.Error(w, err.Error(), http.StatusServiceUnavailable)
			}
			return
		}
	}

	if err := updateProvisionWatcherFields(from, &to, w); err != nil {
		LoggingClient.Error("Problem updating provision watcher: " + err.Error())
		return
	}

	if err := dbClient.UpdateProvisionWatcher(to); err != nil {
		LoggingClient.Error("Problem updating provision watcher: " + err.Error())
		http.Error(w, err.Error(), http.StatusServiceUnavailable)
		return
	}

	// Notify Associates
	if err := notifyProvisionWatcherAssociates(to, http.MethodPut); err != nil {
		LoggingClient.Error("Problem notifying associated device services for provision watcher: " + err.Error())
	}
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write([]byte("true"))
}
1115266
func (st *State) watchEnqueuedActionsFilteredBy(receivers ...ActionReceiver) StringsWatcher {
	return newCollectionWatcher(st, colWCfg{
		col:    actionNotificationsC,
		filter: makeIdFilter(st, actionMarker, receivers...),
		idconv: actionNotificationIdToActionId,
	})
}
548010
func (f *Facade) WatchActionNotifications(args params.Entities) params.StringsWatchResults {
	tagToActionReceiver := f.backend.TagToActionReceiverFn(f.backend.FindEntity)
	watchOne := common.WatchOneActionReceiverNotifications(tagToActionReceiver, f.resources.Register)
	return common.WatchActionNotifications(args, f.accessMachine, watchOne)
}
1054840
func (fw Watchers) WatchUnitManagedFilesystems(app names.ApplicationTag) state.StringsWatcher {
	w := &hostFilesystemsWatcher{
		stringsWatcherBase:     stringsWatcherBase{out: make(chan []string)},
		backend:                fw.Backend,
		changes:                set.NewStrings(),
		hostFilesystems:        fw.Backend.WatchUnitFilesystems(app),
		modelFilesystems:       fw.Backend.WatchModelFilesystems(),
		modelVolumeAttachments: fw.Backend.WatchModelVolumeAttachments(),
		modelVolumesAttached:   names.NewSet(),
		modelVolumeFilesystems: make(map[names.VolumeTag]names.FilesystemTag),
		hostMatch: func(tag names.Tag) (bool, error) {
			entity, err := names.UnitApplication(tag.Id())
			if err != nil {
				return false, errors.Trace(err)
			}
			return app.Id() == entity, nil
		},
	}
	w.tomb.Go(func() error {
		defer watcher.Stop(w.hostFilesystems, &w.tomb)
		defer watcher.Stop(w.modelFilesystems, &w.tomb)
		defer watcher.Stop(w.modelVolumeAttachments, &w.tomb)
		return w.loop()
	})
	return w
}