func (w *commonWatcher) commonLoop() {
	defer close(w.in)
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		// When the watcher has been stopped, we send a Stop request
		// to the server, which will remove the watcher and return a
		// CodeStopped error to any currently outstanding call to
		// Next. If a call to Next happens just after the watcher has
		// been stopped, we'll get a CodeNotFound error; Either way
		// we'll return, wait for the stop request to complete, and
		// the watcher will die with all resources cleaned up.
		defer wg.Done()
		<-w.tomb.Dying()
		if err := w.call("Stop", nil); err != nil {
			// Don't log an error if a watcher is stopped due to an agent restart,
			// or if the entity being watched is already removed.
			if err.Error() != worker.ErrRestartAgent.Error() &&
				err.Error() != rpc.ErrShutdown.Error() && !params.IsCodeNotFound(err) {
				logger.Errorf("error trying to stop watcher: %v", err)
			}
		}
	}()
	wg.Add(1)
	go func() {
		// Because Next blocks until there are changes, we need to
		// call it in a separate goroutine, so the watcher can be
		// stopped normally.
		defer wg.Done()
		for {
			result := w.newResult()
			err := w.call("Next", &result)
			if err != nil {
				if params.IsCodeStopped(err) || params.IsCodeNotFound(err) {
					if w.tomb.Err() != tomb.ErrStillAlive {
						// The watcher has been stopped at the client end, so we're
						// expecting one of the above two kinds of error.
						// We might see the same errors if the server itself
						// has been shut down, in which case we leave them
						// untouched.
						err = tomb.ErrDying
					}
				}
				// Something went wrong, just report the error and bail out.
				w.tomb.Kill(err)
				return
			}
			select {
			case <-w.tomb.Dying():
				return
			case w.in <- result:
				// Report back the result we just got.
			}
		}
	}()
	wg.Wait()
}
// commonLoop implements the loop structure common to the client
// watchers. It should be started in a separate goroutine by any
// watcher that embeds commonWatcher. It kills the commonWatcher's
// tomb when an error occurs.
commonLoop implements the loop structure common to the client
watchers. It should be started in a separate goroutine by any
watcher that embeds commonWatcher. It kills the commonWatcher's
tomb when an error occurs.
// commonLoop implements the loop structure common to the client // watchers . It should be started in a separate goroutine by any // watcher that embeds commonWatcher . It kills the commonWatcher ' s // tomb when an error occurs .
func (w *commonWatcher) commonLoop() {
	defer close(w.in)
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		<-w.tomb.Dying()
		if err := w.call("Stop", nil); err != nil {
			if err.Error() != worker.ErrRestartAgent.Error() &&
				err.Error() != rpc.ErrShutdown.Error() && !params.IsCodeNotFound(err) {
				logger.Errorf("error trying to stop watcher: %v", err)
			}
		}
	}()
	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			result := w.newResult()
			err := w.call("Next", &result)
			if err != nil {
				if params.IsCodeStopped(err) || params.IsCodeNotFound(err) {
					if w.tomb.Err() != tomb.ErrStillAlive {
						err = tomb.ErrDying
					}
				}
				w.tomb.Kill(err)
				return
			}
			select {
			case <-w.tomb.Dying():
				return
			case w.in <- result:
			}
		}
	}()
	wg.Wait()
}
func ( w * commonWatcher ) commonLoop ( ) { defer close ( w . in ) var wg sync . WaitGroup wg . Add ( 1 ) go func ( ) { defer wg . Done ( ) <- w . tomb . Dying ( ) if err := w . call ( " " , nil ) ; err != nil { if err . Error ( ) != worker . ErrRestartAgent . Error ( ) && err . Error ( ) != rpc . ErrShutdown . Error ( ) && ! params . IsCodeNotFound ( err ) { logger . Errorf ( " " , err ) } } } ( ) wg . Add ( 1 ) go func ( ) { defer wg . Done ( ) for { result := w . newResult ( ) err := w . call ( " " , & result ) if err != nil { if params . IsCodeStopped ( err ) || params . IsCodeNotFound ( err ) { if w . tomb . Err ( ) != tomb . ErrStillAlive { err = tomb . ErrDying } } w . tomb . Kill ( err ) return } select { case <- w . tomb . Dying ( ) : return case w . in <- result : } } } ( ) wg . Wait ( ) }
commonLoop implements the loop structure common to the client
watchers.
commonLoop implements the loop structure common to the client watchers .
// When the watcher has been stopped, we send a Stop request // to the server, which will remove the watcher and return a // CodeStopped error to any currently outstanding call to // Next. If a call to Next happens just after the watcher has // been stopped, we'll get a CodeNotFound error; Either way // we'll return, wait for the stop request to complete, and // the watcher will die with all resources cleaned up. // Don't log an error if a watcher is stopped due to an agent restart, // or if the entity being watched is already removed. // Because Next blocks until there are changes, we need to // call it in a separate goroutine, so the watcher can be // stopped normally. // The watcher has been stopped at the client end, so we're // expecting one of the above two kinds of error. // We might see the same errors if the server itself // has been shut down, in which case we leave them // untouched. // Something went wrong, just report the error and bail out. // Report back the result we just got.