Skip to content
This repository was archived by the owner on Jul 15, 2018. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
BREAKING:

- [cli] WriteDemoConfig -> WriteConfigValues
- [common] added Quit method to Service interface, which returns a channel
which is closed once a service is stopped

## 0.6.1 (TBD)

Expand Down
54 changes: 28 additions & 26 deletions common/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@ type Service interface {
// Return true if the service is running
IsRunning() bool

// Quit returns a channel, which is closed once service is stopped.
Quit() <-chan struct{}

// String representation of the service
String() string

// SetLogger sets a logger.
SetLogger(log.Logger)
}

Expand Down Expand Up @@ -88,12 +92,13 @@ type BaseService struct {
name string
started uint32 // atomic
stopped uint32 // atomic
Quit chan struct{}
quit chan struct{}

// The "subclass" of BaseService
impl Service
}

// NewBaseService creates a new BaseService.
func NewBaseService(logger log.Logger, name string, impl Service) *BaseService {
if logger == nil {
logger = log.NewNopLogger()
Expand All @@ -102,16 +107,19 @@ func NewBaseService(logger log.Logger, name string, impl Service) *BaseService {
return &BaseService{
Logger: logger,
name: name,
Quit: make(chan struct{}),
quit: make(chan struct{}),
impl: impl,
}
}

// SetLogger implements Service by setting a logger.
func (bs *BaseService) SetLogger(l log.Logger) {
bs.Logger = l
}

// Implements Servce
// Start implements Service by calling OnStart (if defined). An error will be
// returned if the service is already running or stopped. Not to start the
// stopped service, you need to call Reset.
func (bs *BaseService) Start() error {
if atomic.CompareAndSwapUint32(&bs.started, 0, 1) {
if atomic.LoadUint32(&bs.stopped) == 1 {
Expand All @@ -133,30 +141,32 @@ func (bs *BaseService) Start() error {
}
}

// Implements Service
// OnStart implements Service by doing nothing.
// NOTE: Do not put anything in here,
// that way users don't need to call BaseService.OnStart()
func (bs *BaseService) OnStart() error { return nil }

// Implements Service
// Stop implements Service by calling OnStop (if defined) and closing quit
// channel. An error will be returned if the service is already stopped.
func (bs *BaseService) Stop() error {
if atomic.CompareAndSwapUint32(&bs.stopped, 0, 1) {
bs.Logger.Info(Fmt("Stopping %v", bs.name), "impl", bs.impl)
bs.impl.OnStop()
close(bs.Quit)
close(bs.quit)
return nil
} else {
bs.Logger.Debug(Fmt("Stopping %v (ignoring: already stopped)", bs.name), "impl", bs.impl)
return ErrAlreadyStopped
}
}

// Implements Service
// OnStop implements Service by doing nothing.
// NOTE: Do not put anything in here,
// that way users don't need to call BaseService.OnStop()
func (bs *BaseService) OnStop() {}

// Implements Service
// Reset implements Service by calling OnReset callback (if defined). An error
// will be returned if the service is running.
func (bs *BaseService) Reset() error {
if !atomic.CompareAndSwapUint32(&bs.stopped, 1, 0) {
bs.Logger.Debug(Fmt("Can't reset %v. Not stopped", bs.name), "impl", bs.impl)
Expand All @@ -166,41 +176,33 @@ func (bs *BaseService) Reset() error {
// whether or not we've started, we can reset
atomic.CompareAndSwapUint32(&bs.started, 1, 0)

bs.Quit = make(chan struct{})
bs.quit = make(chan struct{})
return bs.impl.OnReset()
}

// Implements Service
// OnReset implements Service by panicking.
func (bs *BaseService) OnReset() error {
PanicSanity("The service cannot be reset")
return nil
}

// Implements Service
// IsRunning implements Service by returning true or false depending on the
// service's state.
func (bs *BaseService) IsRunning() bool {
return atomic.LoadUint32(&bs.started) == 1 && atomic.LoadUint32(&bs.stopped) == 0
}

// Wait blocks until the service is stopped.
func (bs *BaseService) Wait() {
<-bs.Quit
<-bs.quit
}

// Implements Servce
// String implements Servce by returning a string representation of the service.
func (bs *BaseService) String() string {
return bs.name
}

//----------------------------------------

type QuitService struct {
BaseService
}

func NewQuitService(logger log.Logger, name string, impl Service) *QuitService {
if logger != nil {
logger.Info("QuitService is deprecated, use BaseService instead")
}
return &QuitService{
BaseService: *NewBaseService(logger, name, impl),
}
// Quit Implements Service by returning a quit channel.
func (bs *BaseService) Quit() <-chan struct{} {
return bs.quit
}