Don't flock snapshot files

Signed-off-by: Marek Siarkowicz <siarkowicz@google.com>
This commit is contained in:
Marek Siarkowicz 2024-01-04 14:53:40 +01:00
parent c7eab9d4fa
commit 73814a46f9
3 changed files with 32 additions and 21 deletions

View File

@ -837,8 +837,8 @@ func (s *EtcdServer) purgeFile() {
var dberrc, serrc, werrc <-chan error var dberrc, serrc, werrc <-chan error
var dbdonec, sdonec, wdonec <-chan struct{} var dbdonec, sdonec, wdonec <-chan struct{}
if s.Cfg.MaxSnapFiles > 0 { if s.Cfg.MaxSnapFiles > 0 {
dbdonec, dberrc = fileutil.PurgeFileWithDoneNotify(s.getLogger(), s.Cfg.SnapDir(), "snap.db", s.Cfg.MaxSnapFiles, purgeFileInterval, s.stopping) dbdonec, dberrc = fileutil.PurgeFileWithoutFlock(s.getLogger(), s.Cfg.SnapDir(), "snap.db", s.Cfg.MaxSnapFiles, purgeFileInterval, s.stopping)
sdonec, serrc = fileutil.PurgeFileWithDoneNotify(s.getLogger(), s.Cfg.SnapDir(), "snap", s.Cfg.MaxSnapFiles, purgeFileInterval, s.stopping) sdonec, serrc = fileutil.PurgeFileWithoutFlock(s.getLogger(), s.Cfg.SnapDir(), "snap", s.Cfg.MaxSnapFiles, purgeFileInterval, s.stopping)
} }
if s.Cfg.MaxWALFiles > 0 { if s.Cfg.MaxWALFiles > 0 {
wdonec, werrc = fileutil.PurgeFileWithDoneNotify(s.getLogger(), s.Cfg.WALDir(), "wal", s.Cfg.MaxWALFiles, purgeFileInterval, s.stopping) wdonec, werrc = fileutil.PurgeFileWithDoneNotify(s.getLogger(), s.Cfg.WALDir(), "wal", s.Cfg.MaxWALFiles, purgeFileInterval, s.stopping)

View File

@ -25,18 +25,24 @@ import (
) )
func PurgeFile(lg *zap.Logger, dirname string, suffix string, max uint, interval time.Duration, stop <-chan struct{}) <-chan error { func PurgeFile(lg *zap.Logger, dirname string, suffix string, max uint, interval time.Duration, stop <-chan struct{}) <-chan error {
return purgeFile(lg, dirname, suffix, max, interval, stop, nil, nil) return purgeFile(lg, dirname, suffix, max, interval, stop, nil, nil, true)
} }
func PurgeFileWithDoneNotify(lg *zap.Logger, dirname string, suffix string, max uint, interval time.Duration, stop <-chan struct{}) (<-chan struct{}, <-chan error) { func PurgeFileWithDoneNotify(lg *zap.Logger, dirname string, suffix string, max uint, interval time.Duration, stop <-chan struct{}) (<-chan struct{}, <-chan error) {
doneC := make(chan struct{}) doneC := make(chan struct{})
errC := purgeFile(lg, dirname, suffix, max, interval, stop, nil, doneC) errC := purgeFile(lg, dirname, suffix, max, interval, stop, nil, doneC, true)
return doneC, errC
}
func PurgeFileWithoutFlock(lg *zap.Logger, dirname string, suffix string, max uint, interval time.Duration, stop <-chan struct{}) (<-chan struct{}, <-chan error) {
doneC := make(chan struct{})
errC := purgeFile(lg, dirname, suffix, max, interval, stop, nil, doneC, false)
return doneC, errC return doneC, errC
} }
// purgeFile is the internal implementation for PurgeFile which can post purged files to purgec if non-nil. // purgeFile is the internal implementation for PurgeFile which can post purged files to purgec if non-nil.
// if donec is non-nil, the function closes it to notify its exit. // if donec is non-nil, the function closes it to notify its exit.
func purgeFile(lg *zap.Logger, dirname string, suffix string, max uint, interval time.Duration, stop <-chan struct{}, purgec chan<- string, donec chan<- struct{}) <-chan error { func purgeFile(lg *zap.Logger, dirname string, suffix string, max uint, interval time.Duration, stop <-chan struct{}, purgec chan<- string, donec chan<- struct{}, flock bool) <-chan error {
errC := make(chan error, 1) errC := make(chan error, 1)
if lg != nil { if lg != nil {
lg.Info("started to purge file", lg.Info("started to purge file",
@ -73,7 +79,9 @@ func purgeFile(lg *zap.Logger, dirname string, suffix string, max uint, interval
fnames = newfnames fnames = newfnames
for len(newfnames) > int(max) { for len(newfnames) > int(max) {
f := filepath.Join(dirname, newfnames[0]) f := filepath.Join(dirname, newfnames[0])
l, err := TryLockFile(f, os.O_WRONLY, PrivateFileMode) var l *LockedFile
if flock {
l, err = TryLockFile(f, os.O_WRONLY, PrivateFileMode)
if err != nil { if err != nil {
if lg != nil { if lg != nil {
lg.Warn("failed to lock file", zap.String("path", f), zap.Error(err)) lg.Warn("failed to lock file", zap.String("path", f), zap.Error(err))
@ -82,6 +90,7 @@ func purgeFile(lg *zap.Logger, dirname string, suffix string, max uint, interval
} }
break break
} }
}
if err = os.Remove(f); err != nil { if err = os.Remove(f); err != nil {
if lg != nil { if lg != nil {
lg.Error("failed to remove file", zap.String("path", f), zap.Error(err)) lg.Error("failed to remove file", zap.String("path", f), zap.Error(err))
@ -91,6 +100,7 @@ func purgeFile(lg *zap.Logger, dirname string, suffix string, max uint, interval
errC <- err errC <- err
return return
} }
if flock {
if err = l.Close(); err != nil { if err = l.Close(); err != nil {
if lg != nil { if lg != nil {
lg.Error("failed to unlock/close", zap.String("path", l.Name()), zap.Error(err)) lg.Error("failed to unlock/close", zap.String("path", l.Name()), zap.Error(err))
@ -100,6 +110,7 @@ func purgeFile(lg *zap.Logger, dirname string, suffix string, max uint, interval
errC <- err errC <- err
return return
} }
}
if lg != nil { if lg != nil {
lg.Info("purged", zap.String("path", f)) lg.Info("purged", zap.String("path", f))
} else { } else {

View File

@ -45,7 +45,7 @@ func TestPurgeFile(t *testing.T) {
stop, purgec := make(chan struct{}), make(chan string, 10) stop, purgec := make(chan struct{}), make(chan string, 10)
// keep 3 most recent files // keep 3 most recent files
errch := purgeFile(zap.NewExample(), dir, "test", 3, time.Millisecond, stop, purgec, nil) errch := purgeFile(zap.NewExample(), dir, "test", 3, time.Millisecond, stop, purgec, nil, false)
select { select {
case f := <-purgec: case f := <-purgec:
t.Errorf("unexpected purge on %q", f) t.Errorf("unexpected purge on %q", f)
@ -116,7 +116,7 @@ func TestPurgeFileHoldingLockFile(t *testing.T) {
} }
stop, purgec := make(chan struct{}), make(chan string, 10) stop, purgec := make(chan struct{}), make(chan string, 10)
errch := purgeFile(zap.NewExample(), dir, "test", 3, time.Millisecond, stop, purgec, nil) errch := purgeFile(zap.NewExample(), dir, "test", 3, time.Millisecond, stop, purgec, nil, true)
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
select { select {