From fcfebd0e69026e65437690024b5270e283a2050f Mon Sep 17 00:00:00 2001 From: Sebastiaan Mannem Date: Mon, 21 Feb 2022 12:17:49 +0100 Subject: [PATCH] With this change we also move the wal to new location if --wal-dir location is changed --- internal/postgresql/postgresql.go | 79 +++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/internal/postgresql/postgresql.go b/internal/postgresql/postgresql.go index 48b007bb0..3e4559dca 100644 --- a/internal/postgresql/postgresql.go +++ b/internal/postgresql/postgresql.go @@ -299,10 +299,89 @@ func (p *Manager) StartTmpMerged() error { return p.start("-c", fmt.Sprintf("config_file=%s", tmpPostgresConfPath)) } +func (p *Manager) moveWal() (err error) { + var curPath string + var desiredPath string + var tmpPath string + symlinkPath := filepath.Join(p.dataDir, "pg_wal") + if curPath, err = filepath.EvalSymlinks(symlinkPath); err != nil { + log.Errorf("could not evaluate symlink %s: %e", symlinkPath, err) + return err + } + if p.walDir == "" { + desiredPath = symlinkPath + tmpPath = filepath.Join(p.dataDir, "pg_wal_new") + } else { + desiredPath = p.walDir + tmpPath = p.walDir + } + if curPath == desiredPath { + return nil + } + if p.walDir == "" { + log.Infof("moving wal from %s to %s first and then to %s", curPath, tmpPath, desiredPath) + } else { + log.Infof("moving wal from PGDATA/pg_wal (%s) to new location %s", curPath, desiredPath) + } + // We use tmpPath here first and (if needed) mv tmpPath to desiredPath when all is copied. + // This allows stolon-keeper to re-read symlink dest and continue should stolon-keeper be restarted while copying. + log.Debugf("creating %s", tmpPath) + if err = os.MkdirAll(tmpPath, 0700); err != nil && ! os.IsExist(err) { + log.Errorf("could not create new dest folder %s: %e", tmpPath, err) + return err + } + log.Debugf("moving wal from %s to %s", curPath, tmpPath) + if entries, err := ioutil.ReadDir(curPath); err != nil { + log.Errorf("could not read contents of folder %s: %e", curPath, err) + return err + } else { + for _, entry := range entries { + srcEntry := filepath.Join(curPath, entry.Name()) + dstEntry := filepath.Join(tmpPath, entry.Name()) + log.Infof("moving %s to %s", srcEntry, dstEntry) + os.Rename(srcEntry, dstEntry) + } + } + + if symlinkStat, err := os.Lstat(symlinkPath); err != nil { + log.Errorf("could not get info on current pg_wal folder/symlink %s: %e", symlinkPath, err) + return err + } else if symlinkStat.Mode() & os.ModeSymlink != 0 { + if err = os.Remove(symlinkPath); err != nil { + log.Errorf("could not remove current pg_wal symlink %s: %e", symlinkPath, err) + return err + } + } else if symlinkStat.IsDir() { + if err := syscall.Rmdir(symlinkPath); err != nil { + log.Errorf("could not remove current folder %s: %e", symlinkPath, err) + return err + } + } else { + err := fmt.Errorf("location %s is no symlink and no dir, so please check and resolve by hand", symlinkPath) + log.Error(err) + return err + } + if p.walDir == "" { + // So we were moving wal files back into PGDATA. Let's rename the tmpDir now holding all wal files and use that + // as PGDATA/pg_wal + os.Rename(tmpPath, desiredPath) + // Ah, so we were copying WAL files from PGDATA (or another location) to a location outside of PGDATA. + // Then we need to point the symlink in the right direction. + } else if err = os.Symlink(desiredPath, symlinkPath); err != nil { + log.Errorf("could not create symlink %s to %s: %e", symlinkPath, desiredPath, err) + return err + } + log.Debugf("finished moving pg_wal from %s to %s", curPath, desiredPath) + return nil +} + func (p *Manager) Start() error { if err := p.writeConfs(false); err != nil { return err } + if err := p.moveWal(); err != nil { + return err + } return p.start() }