func (bs *BaseService) Reset() error {
	if !atomic.CompareAndSwapUint32(&bs.stopped, 1, 0) {
		bs.Logger.Debug("cannot reset service; not stopped", "service", bs.name, "impl", bs.impl.String())
		return fmt.Errorf("can't reset running %s", bs.name)
	}
	atomic.CompareAndSwapUint32(&bs.started, 1, 0)
	bs.quit = make(chan struct{})
	return bs.impl.OnReset()
}
Reset implements Service by calling OnReset callback (if defined). An error
will be returned if the service is running.
package service
import (
	"errors"
	"fmt"
	"sync/atomic"
	"github.com/tendermint/tendermint/libs/log"
)
var (
	ErrAlreadyStarted = errors.New("already started")
	ErrAlreadyStopped = errors.New("already stopped")
	ErrNotStarted = errors.New("not started")
)
type Service interface {
	Start() error
	OnStart() error
	Stop() error
	OnStop()
	Reset() error
	OnReset() error
	IsRunning() bool
	Quit() <-chan struct{}
	String() string
	SetLogger(log.Logger)
	Wait()
}
type BaseService struct {
	Logger  log.Logger
	name    string
	started uint32  
	stopped uint32  
	quit    chan struct{}
	impl Service
}
func NewBaseService(logger log.Logger, name string, impl Service) *BaseService {
	if logger == nil {
		logger = log.NewNopLogger()
	}
	return &BaseService{
		Logger: logger,
		name:   name,
		quit:   make(chan struct{}),
		impl:   impl,
	}
}
func (bs *BaseService) SetLogger(l log.Logger) {
	bs.Logger = l
}
func (bs *BaseService) Start() error {
	if atomic.CompareAndSwapUint32(&bs.started, 0, 1) {
		if atomic.LoadUint32(&bs.stopped) == 1 {
			bs.Logger.Error("not starting service; already stopped", "service", bs.name, "impl", bs.impl.String())
			atomic.StoreUint32(&bs.started, 0)
			return ErrAlreadyStopped
		}
		bs.Logger.Info("starting service", "service", bs.name, "impl", bs.impl.String())
		if err := bs.impl.OnStart(); err != nil {
			atomic.StoreUint32(&bs.started, 0)
			return err
		}
		return nil
	}
	bs.Logger.Debug("not starting service; already started", "service", bs.name, "impl", bs.impl.String())
	return ErrAlreadyStarted
}
func (bs *BaseService) OnStart() error { return nil }
func (bs *BaseService) Stop() error {
	if atomic.CompareAndSwapUint32(&bs.stopped, 0, 1) {
		if atomic.LoadUint32(&bs.started) == 0 {
			bs.Logger.Error("not stopping service; not started yet", "service", bs.name, "impl", bs.impl.String())
			atomic.StoreUint32(&bs.stopped, 0)
			return ErrNotStarted
		}
		bs.Logger.Info("stopping service", "service", bs.name, "impl", bs.impl.String())
		bs.impl.OnStop()
		close(bs.quit)
		return nil
	}
	bs.Logger.Debug("not stopping service; already stopped", "service", bs.name, "impl", bs.impl.String())
	return ErrAlreadyStopped
}
func (bs *BaseService) OnStop() {}