You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
go-log/fixed_size_file_writer.go

114 lines
1.9 KiB
Go

package log
import (
"fmt"
"math"
"os"
"path"
)
// FixedSizeFileWriter create new log if log size exceed
type FixedSizeFileWriter struct {
Name string
MaxSize int64
MaxCount int
file *os.File
currentSize int64
}
// Write implements io.Writer
func (w *FixedSizeFileWriter) Write(p []byte) (n int, err error) {
if w.file == nil {
if err = w.openCurrentFile(); err != nil {
return
}
}
if w.currentSize > w.MaxSize {
w.file.Close()
if err = w.openNextFile(); err != nil {
return
}
}
w.currentSize += int64(len(p))
return w.file.Write(p)
}
func (w *FixedSizeFileWriter) openCurrentFile() error {
name, err := os.Readlink(w.Name)
if err != nil {
name = w.getAvailableFileName()
// create a symlink
err = os.Symlink(path.Base(name), w.Name)
if err != nil {
return err
}
} else {
// convert to abs path
name = path.Join(path.Dir(w.Name), name)
}
w.file, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
return err
}
stat, err := w.file.Stat()
if err != nil {
return err
}
w.currentSize = stat.Size()
return nil
}
func (w *FixedSizeFileWriter) openNextFile() (err error) {
name := w.getAvailableFileName()
// remove symbol link
err = os.Remove(w.Name)
if err != nil {
return err
}
// create symbol
err = os.Symlink(path.Base(name), w.Name)
if err != nil {
return err
}
w.file, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return err
}
w.currentSize = 0
return nil
}
// get available file or oldest file
func (w *FixedSizeFileWriter) getAvailableFileName() string {
var oldestTime int64 = math.MaxInt64
var oldestName string
for i := 0; i < w.MaxCount; i++ {
name := fmt.Sprintf("%s.%d", w.Name, i)
stat, err := os.Stat(name)
if err != nil {
return name
}
if fTime := stat.ModTime().Unix(); fTime < oldestTime {
oldestTime = fTime
oldestName = name
}
}
return oldestName
}