mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
49aa66b597
Truncating the current log file while a reader is still reading through it results in log lines getting missed. In contrast, rotating the file allows readers who have the file open can continue to read from it undisturbed. Rotating frees up the file name for the logger to create a new file in its place. This remains true even when max-file=1; the current log file is "rotated" from its name without giving it a new one. On POSIXy filesystem APIs, rotating the last file is straightforward: unlink()ing a file name immediately deletes the name from the filesystem and makes it available for reuse, even if processes have the file open at the time. Windows on the other hand only makes the name available for reuse once the file itself is deleted, which only happens when no processes have it open. To reuse the file name while the file is still in use, the file needs to be renamed. So that's what we have to do: rotate the file to a temporary name before marking it for deletion. Signed-off-by: Cory Snider <csnider@mirantis.com>
59 lines
1.4 KiB
Go
59 lines
1.4 KiB
Go
package loggerutils
|
|
|
|
import (
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"gotest.tools/v3/assert"
|
|
)
|
|
|
|
func TestOpenFileDelete(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
f, err := openFile(filepath.Join(tmpDir, "test.txt"), os.O_CREATE|os.O_RDWR, 644)
|
|
assert.NilError(t, err)
|
|
defer f.Close()
|
|
|
|
assert.NilError(t, os.RemoveAll(f.Name()))
|
|
}
|
|
|
|
func TestOpenFileRename(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
f, err := openFile(filepath.Join(tmpDir, "test.txt"), os.O_CREATE|os.O_RDWR, 0644)
|
|
assert.NilError(t, err)
|
|
defer f.Close()
|
|
|
|
assert.NilError(t, os.Rename(f.Name(), f.Name()+"renamed"))
|
|
}
|
|
|
|
func TestUnlinkOpenFile(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
name := filepath.Join(tmpDir, "test.txt")
|
|
f, err := openFile(name, os.O_CREATE|os.O_RDWR, 0644)
|
|
assert.NilError(t, err)
|
|
defer func() { assert.NilError(t, f.Close()) }()
|
|
|
|
_, err = io.WriteString(f, "first")
|
|
assert.NilError(t, err)
|
|
|
|
assert.NilError(t, unlink(name))
|
|
f2, err := openFile(name, os.O_CREATE|os.O_RDWR, 0644)
|
|
assert.NilError(t, err)
|
|
defer func() { assert.NilError(t, f2.Close()) }()
|
|
|
|
_, err = io.WriteString(f2, "second")
|
|
assert.NilError(t, err)
|
|
|
|
_, err = f.Seek(0, io.SeekStart)
|
|
assert.NilError(t, err)
|
|
fdata, err := io.ReadAll(f)
|
|
assert.NilError(t, err)
|
|
assert.Check(t, "first" == string(fdata))
|
|
|
|
_, err = f2.Seek(0, io.SeekStart)
|
|
assert.NilError(t, err)
|
|
f2data, err := io.ReadAll(f2)
|
|
assert.NilError(t, err)
|
|
assert.Check(t, "second" == string(f2data))
|
|
}
|