89 lines
1.7 KiB
Go
89 lines
1.7 KiB
Go
package driver
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type LogRotator struct {
|
|
maxFiles int
|
|
fileSize int64
|
|
path string
|
|
fileName string
|
|
logFileIdx int
|
|
}
|
|
|
|
func NewLogRotator(path string, fileName string, maxFiles int, fileSize int64) (*LogRotator, error) {
|
|
files, err := ioutil.ReadDir(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
logFileIdx := 0
|
|
for _, f := range files {
|
|
if strings.HasPrefix(f.Name(), fileName) {
|
|
fileIdx := strings.TrimPrefix(f.Name(), fmt.Sprintf("%s.", fileName))
|
|
n, err := strconv.Atoi(fileIdx)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if n > logFileIdx {
|
|
logFileIdx = n
|
|
}
|
|
}
|
|
}
|
|
|
|
return &LogRotator{
|
|
maxFiles: maxFiles,
|
|
fileSize: fileSize,
|
|
path: path,
|
|
fileName: fileName,
|
|
logFileIdx: logFileIdx,
|
|
}, nil
|
|
}
|
|
|
|
func (l *LogRotator) Start(r io.Reader) error {
|
|
buf := make([]byte, 32 * 1024)
|
|
for {
|
|
logFileName := filepath.Join(l.path, fmt.Sprintf("%s.%d", l.fileName, l.logFileIdx))
|
|
f, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0066)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
remainingSize := l.fileSize
|
|
if finfo, err := os.Stat(logFileName); err == nil {
|
|
remainingSize -= finfo.Size()
|
|
}
|
|
if remainingSize < 1 {
|
|
l.logFileIdx = l.logFileIdx + 1
|
|
f.Close()
|
|
continue
|
|
}
|
|
|
|
for {
|
|
nr, err := io.LimitReader(r, remainingSize).Read(buf)
|
|
if err != nil {
|
|
f.Close()
|
|
return err
|
|
}
|
|
nw, err := f.Write(buf[:nr])
|
|
if err != nil {
|
|
f.Close()
|
|
return err
|
|
}
|
|
if nr != nw {
|
|
f.Close()
|
|
return fmt.Errorf("Failed to write data R: %d W: %d", nr, nw)
|
|
}
|
|
remainingSize -= int64(nr)
|
|
}
|
|
l.logFileIdx = l.logFileIdx + 1
|
|
}
|
|
return nil
|
|
}
|