From 44f2818a3d6c0174da7c16c97387cb97fe6c63af Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 26 Oct 2016 21:50:28 -0700 Subject: [PATCH 1/5] Remove AutoFile; Use go-autofile instead --- os.go | 154 ---------------------------------------------------------- 1 file changed, 154 deletions(-) diff --git a/os.go b/os.go index a273bec4..9f38027f 100644 --- a/os.go +++ b/os.go @@ -7,19 +7,12 @@ 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) @@ -112,153 +105,6 @@ 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 { From 2781df39e576c4258b7d10d1404eaf3c029d92f8 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 28 Oct 2016 12:09:22 -0700 Subject: [PATCH 2/5] QuitService->BaseService --- service.go | 29 ++++++++++++++--------------- service_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 15 deletions(-) create mode 100644 service_test.go diff --git a/service.go b/service.go index 86ef20ea..7336446f 100644 --- a/service.go +++ b/service.go @@ -65,6 +65,7 @@ type BaseService struct { name string started uint32 // atomic stopped uint32 // atomic + Quit chan struct{} // The "subclass" of BaseService impl Service @@ -74,6 +75,7 @@ func NewBaseService(log log15.Logger, name string, impl Service) *BaseService { return &BaseService{ log: log, name: name, + Quit: make(chan struct{}), impl: impl, } } @@ -102,6 +104,8 @@ 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 @@ -111,6 +115,7 @@ 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 { @@ -121,6 +126,8 @@ 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 @@ -151,6 +158,10 @@ func (bs *BaseService) IsRunning() bool { return atomic.LoadUint32(&bs.started) == 1 && atomic.LoadUint32(&bs.stopped) == 0 } +func (bs *QuitService) Wait() { + <-bs.Quit +} + // Implements Servce func (bs *BaseService) String() string { return bs.name @@ -160,25 +171,13 @@ 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) } } diff --git a/service_test.go b/service_test.go new file mode 100644 index 00000000..6e24dad6 --- /dev/null +++ b/service_test.go @@ -0,0 +1,24 @@ +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() + } + +} From fa3daa7abc253264c916c12fecce3effa01a1287 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 28 Oct 2016 12:09:34 -0700 Subject: [PATCH 3/5] Remove AutoFile tests --- os_test.go | 64 ------------------------------------------------------ service.go | 2 +- 2 files changed, 1 insertion(+), 65 deletions(-) delete mode 100644 os_test.go diff --git a/os_test.go b/os_test.go deleted file mode 100644 index c0effdc2..00000000 --- a/os_test.go +++ /dev/null @@ -1,64 +0,0 @@ -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) - } - -} diff --git a/service.go b/service.go index 7336446f..e2d31925 100644 --- a/service.go +++ b/service.go @@ -158,7 +158,7 @@ func (bs *BaseService) IsRunning() bool { return atomic.LoadUint32(&bs.started) == 1 && atomic.LoadUint32(&bs.stopped) == 0 } -func (bs *QuitService) Wait() { +func (bs *BaseService) Wait() { <-bs.Quit } From 6b4160f2a57487f277c42bf06fd280195dfdb278 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 21 Nov 2016 20:01:11 -0800 Subject: [PATCH 4/5] Add Tempdir --- os.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/os.go b/os.go index 9f38027f..e8943c0c 100644 --- a/os.go +++ b/os.go @@ -113,6 +113,19 @@ 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) { From 70e694ee76f09058ea38c9ba81b4aa621bd54df1 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 6 Dec 2016 01:39:04 -0800 Subject: [PATCH 5/5] Fix ThrottleTimer null-pointer error / race condition --- throttle_timer.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/throttle_timer.go b/throttle_timer.go index 0966e913..38ef4e9a 100644 --- a/throttle_timer.go +++ b/throttle_timer.go @@ -26,7 +26,9 @@ func NewThrottleTimer(name string, dur time.Duration) *ThrottleTimer { var ch = make(chan struct{}) var quit = make(chan struct{}) var t = &ThrottleTimer{Name: name, Ch: ch, dur: dur, quit: quit} + t.mtx.Lock() t.timer = time.AfterFunc(dur, t.fireRoutine) + t.mtx.Unlock() t.timer.Stop() return t }