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/signal"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
GoPath = os.Getenv("GOPATH")
|
||||
)
|
||||
|
||||
func init() {
|
||||
initAFSIGHUPWatcher()
|
||||
}
|
||||
|
||||
func TrapSignal(cb func()) {
|
||||
c := make(chan os.Signal, 1)
|
||||
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) {
|
||||
file, err := ioutil.TempFile("", prefix)
|
||||
if err != nil {
|
||||
@ -113,19 +267,6 @@ func Tempfile(prefix string) (*os.File, string) {
|
||||
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) {
|
||||
|
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
|
||||
started uint32 // atomic
|
||||
stopped uint32 // atomic
|
||||
Quit chan struct{}
|
||||
|
||||
// The "subclass" of BaseService
|
||||
impl Service
|
||||
@ -75,7 +74,6 @@ func NewBaseService(log log15.Logger, name string, impl Service) *BaseService {
|
||||
return &BaseService{
|
||||
log: log,
|
||||
name: name,
|
||||
Quit: make(chan struct{}),
|
||||
impl: impl,
|
||||
}
|
||||
}
|
||||
@ -104,8 +102,6 @@ func (bs *BaseService) Start() (bool, error) {
|
||||
}
|
||||
|
||||
// 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 }
|
||||
|
||||
// Implements Service
|
||||
@ -115,7 +111,6 @@ func (bs *BaseService) Stop() bool {
|
||||
bs.log.Info(Fmt("Stopping %v", bs.name), "impl", bs.impl)
|
||||
}
|
||||
bs.impl.OnStop()
|
||||
close(bs.Quit)
|
||||
return true
|
||||
} else {
|
||||
if bs.log != nil {
|
||||
@ -126,8 +121,6 @@ func (bs *BaseService) Stop() bool {
|
||||
}
|
||||
|
||||
// Implements Service
|
||||
// NOTE: Do not put anything in here,
|
||||
// that way users don't need to call BaseService.OnStop()
|
||||
func (bs *BaseService) OnStop() {}
|
||||
|
||||
// Implements Service
|
||||
@ -158,10 +151,6 @@ func (bs *BaseService) IsRunning() bool {
|
||||
return atomic.LoadUint32(&bs.started) == 1 && atomic.LoadUint32(&bs.stopped) == 0
|
||||
}
|
||||
|
||||
func (bs *BaseService) Wait() {
|
||||
<-bs.Quit
|
||||
}
|
||||
|
||||
// Implements Servce
|
||||
func (bs *BaseService) String() string {
|
||||
return bs.name
|
||||
@ -171,13 +160,25 @@ func (bs *BaseService) String() string {
|
||||
|
||||
type QuitService struct {
|
||||
BaseService
|
||||
Quit chan struct{}
|
||||
}
|
||||
|
||||
func NewQuitService(log log15.Logger, name string, impl Service) *QuitService {
|
||||
if log != nil {
|
||||
log.Warn("QuitService is deprecated, use BaseService instead")
|
||||
}
|
||||
return &QuitService{
|
||||
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