mirror of
https://github.com/fluencelabs/tendermint
synced 2025-05-28 21:51:22 +00:00
Reverts commit f40b1b to a6a67e
This commit is contained in:
parent
f40b1b65f8
commit
a552e49b50
167
os.go
167
os.go
@ -7,12 +7,19 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
GoPath = os.Getenv("GOPATH")
|
GoPath = os.Getenv("GOPATH")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
initAFSIGHUPWatcher()
|
||||||
|
}
|
||||||
|
|
||||||
func TrapSignal(cb func()) {
|
func TrapSignal(cb func()) {
|
||||||
c := make(chan os.Signal, 1)
|
c := make(chan os.Signal, 1)
|
||||||
signal.Notify(c, os.Interrupt)
|
signal.Notify(c, os.Interrupt)
|
||||||
@ -105,6 +112,153 @@ func WriteFileAtomic(filePath string, newBytes []byte, mode os.FileMode) error {
|
|||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* AutoFile usage
|
||||||
|
|
||||||
|
// Create/Append to ./autofile_test
|
||||||
|
af, err := OpenAutoFile("autofile_test")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stream of writes.
|
||||||
|
// During this time, the file may be moved e.g. by logRotate.
|
||||||
|
for i := 0; i < 60; i++ {
|
||||||
|
af.Write([]byte(Fmt("LOOP(%v)", i)))
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the AutoFile
|
||||||
|
err = af.Close()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const autoFileOpenDuration = 1000 * time.Millisecond
|
||||||
|
|
||||||
|
// Automatically closes and re-opens file for writing.
|
||||||
|
// This is useful for using a log file with the logrotate tool.
|
||||||
|
type AutoFile struct {
|
||||||
|
ID string
|
||||||
|
Path string
|
||||||
|
ticker *time.Ticker
|
||||||
|
mtx sync.Mutex
|
||||||
|
file *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func OpenAutoFile(path string) (af *AutoFile, err error) {
|
||||||
|
af = &AutoFile{
|
||||||
|
ID: RandStr(12) + ":" + path,
|
||||||
|
Path: path,
|
||||||
|
ticker: time.NewTicker(autoFileOpenDuration),
|
||||||
|
}
|
||||||
|
if err = af.openFile(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go af.processTicks()
|
||||||
|
autoFileWatchers.addAutoFile(af)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (af *AutoFile) Close() error {
|
||||||
|
af.ticker.Stop()
|
||||||
|
err := af.closeFile()
|
||||||
|
autoFileWatchers.removeAutoFile(af)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (af *AutoFile) processTicks() {
|
||||||
|
for {
|
||||||
|
_, ok := <-af.ticker.C
|
||||||
|
if !ok {
|
||||||
|
return // Done.
|
||||||
|
}
|
||||||
|
af.closeFile()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (af *AutoFile) closeFile() (err error) {
|
||||||
|
af.mtx.Lock()
|
||||||
|
defer af.mtx.Unlock()
|
||||||
|
|
||||||
|
file := af.file
|
||||||
|
if file == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
af.file = nil
|
||||||
|
return file.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (af *AutoFile) Write(b []byte) (n int, err error) {
|
||||||
|
af.mtx.Lock()
|
||||||
|
defer af.mtx.Unlock()
|
||||||
|
if af.file == nil {
|
||||||
|
if err = af.openFile(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return af.file.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (af *AutoFile) openFile() error {
|
||||||
|
file, err := os.OpenFile(af.Path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
af.file = file
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
var autoFileWatchers *afSIGHUPWatcher
|
||||||
|
|
||||||
|
func initAFSIGHUPWatcher() {
|
||||||
|
autoFileWatchers = newAFSIGHUPWatcher()
|
||||||
|
|
||||||
|
c := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(c, syscall.SIGHUP)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for _ = range c {
|
||||||
|
autoFileWatchers.closeAll()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
type afSIGHUPWatcher struct {
|
||||||
|
mtx sync.Mutex
|
||||||
|
autoFiles map[string]*AutoFile
|
||||||
|
}
|
||||||
|
|
||||||
|
func newAFSIGHUPWatcher() *afSIGHUPWatcher {
|
||||||
|
return &afSIGHUPWatcher{
|
||||||
|
autoFiles: make(map[string]*AutoFile, 10),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (afw *afSIGHUPWatcher) addAutoFile(af *AutoFile) {
|
||||||
|
afw.mtx.Lock()
|
||||||
|
afw.autoFiles[af.ID] = af
|
||||||
|
afw.mtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (afw *afSIGHUPWatcher) removeAutoFile(af *AutoFile) {
|
||||||
|
afw.mtx.Lock()
|
||||||
|
delete(afw.autoFiles, af.ID)
|
||||||
|
afw.mtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (afw *afSIGHUPWatcher) closeAll() {
|
||||||
|
afw.mtx.Lock()
|
||||||
|
for _, af := range afw.autoFiles {
|
||||||
|
af.closeFile()
|
||||||
|
}
|
||||||
|
afw.mtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
func Tempfile(prefix string) (*os.File, string) {
|
func Tempfile(prefix string) (*os.File, string) {
|
||||||
file, err := ioutil.TempFile("", prefix)
|
file, err := ioutil.TempFile("", prefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -113,19 +267,6 @@ func Tempfile(prefix string) (*os.File, string) {
|
|||||||
return file, file.Name()
|
return file, file.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Tempdir(prefix string) (*os.File, string) {
|
|
||||||
tempDir := os.TempDir() + "/" + prefix + RandStr(12)
|
|
||||||
err := EnsureDir(tempDir, 0700)
|
|
||||||
if err != nil {
|
|
||||||
panic(Fmt("Error creating temp dir: %v", err))
|
|
||||||
}
|
|
||||||
dir, err := os.Open(tempDir)
|
|
||||||
if err != nil {
|
|
||||||
panic(Fmt("Error opening temp dir: %v", err))
|
|
||||||
}
|
|
||||||
return dir, tempDir
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
func Prompt(prompt string, defaultValue string) (string, error) {
|
func Prompt(prompt string, defaultValue string) (string, error) {
|
||||||
|
64
os_test.go
Normal file
64
os_test.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSIGHUP(t *testing.T) {
|
||||||
|
|
||||||
|
// First, create an AutoFile writing to a tempfile dir
|
||||||
|
file, name := Tempfile("sighup_test")
|
||||||
|
err := file.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error creating tempfile: %v", err)
|
||||||
|
}
|
||||||
|
// Here is the actual AutoFile
|
||||||
|
af, err := OpenAutoFile(name)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error creating autofile: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to the file.
|
||||||
|
_, err = af.Write([]byte("Line 1\n"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error writing to autofile: %v", err)
|
||||||
|
}
|
||||||
|
_, err = af.Write([]byte("Line 2\n"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error writing to autofile: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send SIGHUP to self.
|
||||||
|
syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
|
||||||
|
|
||||||
|
// Move the file over
|
||||||
|
err = os.Rename(name, name+"_old")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error moving autofile: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write more to the file.
|
||||||
|
_, err = af.Write([]byte("Line 3\n"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error writing to autofile: %v", err)
|
||||||
|
}
|
||||||
|
_, err = af.Write([]byte("Line 4\n"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error writing to autofile: %v", err)
|
||||||
|
}
|
||||||
|
err = af.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error closing autofile")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both files should exist
|
||||||
|
if body := MustReadFile(name + "_old"); string(body) != "Line 1\nLine 2\n" {
|
||||||
|
t.Errorf("Unexpected body %s", body)
|
||||||
|
}
|
||||||
|
if body := MustReadFile(name); string(body) != "Line 3\nLine 4\n" {
|
||||||
|
t.Errorf("Unexpected body %s", body)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
29
service.go
29
service.go
@ -65,7 +65,6 @@ type BaseService struct {
|
|||||||
name string
|
name string
|
||||||
started uint32 // atomic
|
started uint32 // atomic
|
||||||
stopped uint32 // atomic
|
stopped uint32 // atomic
|
||||||
Quit chan struct{}
|
|
||||||
|
|
||||||
// The "subclass" of BaseService
|
// The "subclass" of BaseService
|
||||||
impl Service
|
impl Service
|
||||||
@ -75,7 +74,6 @@ func NewBaseService(log log15.Logger, name string, impl Service) *BaseService {
|
|||||||
return &BaseService{
|
return &BaseService{
|
||||||
log: log,
|
log: log,
|
||||||
name: name,
|
name: name,
|
||||||
Quit: make(chan struct{}),
|
|
||||||
impl: impl,
|
impl: impl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,8 +102,6 @@ func (bs *BaseService) Start() (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implements Service
|
// Implements Service
|
||||||
// NOTE: Do not put anything in here,
|
|
||||||
// that way users don't need to call BaseService.OnStart()
|
|
||||||
func (bs *BaseService) OnStart() error { return nil }
|
func (bs *BaseService) OnStart() error { return nil }
|
||||||
|
|
||||||
// Implements Service
|
// Implements Service
|
||||||
@ -115,7 +111,6 @@ func (bs *BaseService) Stop() bool {
|
|||||||
bs.log.Info(Fmt("Stopping %v", bs.name), "impl", bs.impl)
|
bs.log.Info(Fmt("Stopping %v", bs.name), "impl", bs.impl)
|
||||||
}
|
}
|
||||||
bs.impl.OnStop()
|
bs.impl.OnStop()
|
||||||
close(bs.Quit)
|
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
if bs.log != nil {
|
if bs.log != nil {
|
||||||
@ -126,8 +121,6 @@ func (bs *BaseService) Stop() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implements Service
|
// Implements Service
|
||||||
// NOTE: Do not put anything in here,
|
|
||||||
// that way users don't need to call BaseService.OnStop()
|
|
||||||
func (bs *BaseService) OnStop() {}
|
func (bs *BaseService) OnStop() {}
|
||||||
|
|
||||||
// Implements Service
|
// Implements Service
|
||||||
@ -158,10 +151,6 @@ func (bs *BaseService) IsRunning() bool {
|
|||||||
return atomic.LoadUint32(&bs.started) == 1 && atomic.LoadUint32(&bs.stopped) == 0
|
return atomic.LoadUint32(&bs.started) == 1 && atomic.LoadUint32(&bs.stopped) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bs *BaseService) Wait() {
|
|
||||||
<-bs.Quit
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements Servce
|
// Implements Servce
|
||||||
func (bs *BaseService) String() string {
|
func (bs *BaseService) String() string {
|
||||||
return bs.name
|
return bs.name
|
||||||
@ -171,13 +160,25 @@ func (bs *BaseService) String() string {
|
|||||||
|
|
||||||
type QuitService struct {
|
type QuitService struct {
|
||||||
BaseService
|
BaseService
|
||||||
|
Quit chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewQuitService(log log15.Logger, name string, impl Service) *QuitService {
|
func NewQuitService(log log15.Logger, name string, impl Service) *QuitService {
|
||||||
if log != nil {
|
|
||||||
log.Warn("QuitService is deprecated, use BaseService instead")
|
|
||||||
}
|
|
||||||
return &QuitService{
|
return &QuitService{
|
||||||
BaseService: *NewBaseService(log, name, impl),
|
BaseService: *NewBaseService(log, name, impl),
|
||||||
|
Quit: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: when overriding OnStart, must call .QuitService.OnStart().
|
||||||
|
func (qs *QuitService) OnStart() error {
|
||||||
|
qs.Quit = make(chan struct{})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: when overriding OnStop, must call .QuitService.OnStop().
|
||||||
|
func (qs *QuitService) OnStop() {
|
||||||
|
if qs.Quit != nil {
|
||||||
|
close(qs.Quit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
package common
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBaseServiceWait(t *testing.T) {
|
|
||||||
|
|
||||||
type TestService struct {
|
|
||||||
BaseService
|
|
||||||
}
|
|
||||||
ts := &TestService{}
|
|
||||||
ts.BaseService = *NewBaseService(nil, "TestService", ts)
|
|
||||||
ts.Start()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
ts.Stop()
|
|
||||||
}()
|
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
ts.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user