func (d send) check(c *gc.C, in chan params.RelationUnitsChange, out chan hook.Info) { ruc := params.RelationUnitsChange{Changed: map[string]params.UnitSettings{}} for name, version := range d.changed { ruc.Changed[name] = params.UnitSettings{Version: version} } for _, name := range d.departed { ruc.Departed = append(ruc.Departed, name) } in <- ruc }
func (q *AliveHookQueue) loop(initial *State) { defer q.tomb.Done() defer watcher.Stop(q.w, &q.tomb) // Consume initial event, and reconcile with initial state, by inserting // a new RelationUnitsChange before the initial event, which schedules // every missing unit for immediate departure before anything else happens // (apart from a single potential required post-joined changed event). ch1, ok := <-q.w.Changes() if !ok { q.tomb.Kill(watcher.MustErr(q.w)) return } if len(ch1.Departed) != 0 { panic("AliveHookQueue must be started with a fresh RelationUnitsWatcher") } q.changedPending = initial.ChangedPending ch0 := params.RelationUnitsChange{} for unit, version := range initial.Members { q.info[unit] = &unitInfo{ unit: unit, version: version, joined: true, } if _, found := ch1.Changed[unit]; !found { ch0.Departed = append(ch0.Departed, unit) } } q.update(ch0) q.update(ch1) var next hook.Info var out chan<- hook.Info for { if q.empty() { out = nil } else { out = q.out next = q.next() } select { case <-q.tomb.Dying(): return case ch, ok := <-q.w.Changes(): if !ok { q.tomb.Kill(watcher.MustErr(q.w)) return } q.update(ch) case out <- next: q.pop() } } }
// mergeScope starts and stops settings watches on the units entering and // leaving the scope in the supplied RelationScopeChange event, and applies // the expressed changes to the supplied RelationUnitsChange event. func (w *relationUnitsWatcher) mergeScope(changes *params.RelationUnitsChange, c *RelationScopeChange) error { for _, name := range c.Entered { key := w.sw.prefix + name revno, err := w.mergeSettings(changes, key) if err != nil { return err } changes.Departed = remove(changes.Departed, name) w.st.watcher.Watch(w.st.settings.Name, key, revno, w.updates) w.watching.Add(key) } for _, name := range c.Left { key := w.sw.prefix + name changes.Departed = append(changes.Departed, name) if changes.Changed != nil { delete(changes.Changed, name) } w.st.watcher.Unwatch(w.st.settings.Name, key, w.updates) w.watching.Remove(key) } return nil }
// mergeSettings reads the relation settings node for the unit with the // supplied id, and sets a value in the Changed field keyed on the unit's // name. It returns the mgo/txn revision number of the settings node. func (w *relationUnitsWatcher) mergeSettings(changes *params.RelationUnitsChange, key string) (int64, error) { node, err := readSettings(w.st, key) if err != nil { return -1, err } name := (&relationScopeDoc{key}).unitName() settings := params.UnitSettings{Version: node.txnRevno} if changes.Changed == nil { changes.Changed = map[string]params.UnitSettings{name: settings} } else { changes.Changed[name] = settings } return node.txnRevno, nil }