summaryrefslogtreecommitdiffhomepage
path: root/server/watcher.go
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-03-20 00:09:44 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-03-20 00:09:44 +0900
commit731f4fa3ea2ea58b1dccdb62eb14a407594c81d8 (patch)
tree4aa29c89ab7824a66475674b0db9377695ebe812 /server/watcher.go
parent66ac5a1051267c5d915461a2556ef33e8ac9e670 (diff)
server: support mrt dump rotation like Quagga
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Diffstat (limited to 'server/watcher.go')
-rw-r--r--server/watcher.go92
1 files changed, 55 insertions, 37 deletions
diff --git a/server/watcher.go b/server/watcher.go
index 591d5d89..ce86203d 100644
--- a/server/watcher.go
+++ b/server/watcher.go
@@ -16,7 +16,6 @@
package server
import (
- "fmt"
log "github.com/Sirupsen/logrus"
"github.com/osrg/gobgp/packet"
"github.com/osrg/gobgp/table"
@@ -94,17 +93,12 @@ type watcher interface {
watchingEventTypes() []watcherEventType
}
-type mrtWatcherOp struct {
- filename string //used for rotate
- result chan error
-}
-
type mrtWatcher struct {
t tomb.Tomb
filename string
file *os.File
ch chan watcherEvent
- opCh chan *mrtWatcherOp
+ interval uint64
}
func (w *mrtWatcher) notify(t watcherEventType) chan watcherEvent {
@@ -119,20 +113,26 @@ func (w *mrtWatcher) stop() {
}
func (w *mrtWatcher) restart(filename string) error {
- adminOp := &mrtWatcherOp{
- filename: filename,
- result: make(chan error),
- }
- select {
- case w.opCh <- adminOp:
- default:
- return fmt.Errorf("already an admin operaiton in progress")
- }
- return <-adminOp.result
+ return nil
}
func (w *mrtWatcher) loop() error {
- defer w.file.Close()
+ c := func() *time.Ticker {
+ if w.interval == 0 {
+ return &time.Ticker{}
+ }
+ return time.NewTicker(time.Second * time.Duration(w.interval))
+ }()
+
+ defer func() {
+ if w.file != nil {
+ w.file.Close()
+ }
+ if w.interval != 0 {
+ c.Stop()
+ }
+ }()
+
for {
write := func(ev watcherEvent) {
m := ev.(*watcherEventUpdateMsg)
@@ -152,9 +152,10 @@ func (w *mrtWatcher) loop() error {
}
buf, err := bm.Serialize()
if err == nil {
- _, err = w.file.Write(buf)
+ if _, err = w.file.Write(buf); err == nil {
+ err = w.file.Sync()
+ }
}
-
if err != nil {
log.WithFields(log.Fields{
"Topic": "mrt",
@@ -176,20 +177,14 @@ func (w *mrtWatcher) loop() error {
return nil
case m := <-w.ch:
write(m)
- case adminOp := <-w.opCh:
- var err error
- if adminOp.filename != "" {
- err = os.Rename(w.file.Name(), adminOp.filename)
- }
+ case <-c.C:
+ w.file.Close()
+ file, err := mrtFileOpen(w.filename, w.interval)
if err == nil {
- var file *os.File
- file, err = mrtFileOpen(w.file.Name())
- if err == nil {
- w.file.Close()
- w.file = file
- }
+ w.file = file
+ } else {
+ log.Info("can't rotate mrt file", err)
}
- adminOp.result <- err
}
}
}
@@ -198,16 +193,39 @@ func (w *mrtWatcher) watchingEventTypes() []watcherEventType {
return []watcherEventType{WATCHER_EVENT_UPDATE_MSG}
}
-func mrtFileOpen(filename string) (*os.File, error) {
- file, err := os.OpenFile(filename, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0644)
+func mrtFileOpen(filename string, interval uint64) (*os.File, error) {
+ realname := filename
+ if interval != 0 {
+ realname = time.Now().Format(filename)
+ }
+
+ i := len(realname)
+ for i > 0 && os.IsPathSeparator(realname[i-1]) {
+ // skip trailing path separators
+ i--
+ }
+ j := i
+
+ for j > 0 && !os.IsPathSeparator(realname[j-1]) {
+ j--
+ }
+
+ if j > 0 {
+ if err := os.MkdirAll(realname[0:j-1], 0755); err != nil {
+ log.Warn(err)
+ return nil, err
+ }
+ }
+
+ file, err := os.OpenFile(realname, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0644)
if err != nil {
log.Warn(err)
}
return file, err
}
-func newMrtWatcher(filename string) (*mrtWatcher, error) {
- file, err := mrtFileOpen(filename)
+func newMrtWatcher(dumpType int32, filename string, interval uint64) (*mrtWatcher, error) {
+ file, err := mrtFileOpen(filename, interval)
if err != nil {
return nil, err
}
@@ -215,7 +233,7 @@ func newMrtWatcher(filename string) (*mrtWatcher, error) {
filename: filename,
file: file,
ch: make(chan watcherEvent),
- opCh: make(chan *mrtWatcherOp, 1),
+ interval: interval,
}
w.t.Go(w.loop)
return &w, nil