You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
3.7 KiB
86 lines
3.7 KiB
package shell
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func computeRequirementsFromDirectory(previousSnapshots []string, homeDirectory string, snapshotPath string, count int, durationDays int, targetDate time.Time) (snapshotsToRemove []string, snapshotsToGenerate []time.Time, levelDbBootstrapPath string, err error) {
|
|
levelDbBootstrapPath = previousSnapshots[len(previousSnapshots)-1]
|
|
lastSnapshotDate, err := time.Parse(DateFormat, levelDbBootstrapPath[:len(DateFormat)])
|
|
if err != nil {
|
|
return
|
|
}
|
|
if err != nil {
|
|
return
|
|
}
|
|
// the snapshots cover the last nanosecond of the current date
|
|
lastSnapshotDate = lastSnapshotDate.AddDate(0, 0, 1).Add(-1 * time.Nanosecond)
|
|
gapDuration := targetDate.Sub(lastSnapshotDate)
|
|
oneSnapshotInterval := 24 * time.Hour * time.Duration(durationDays)
|
|
totalSnapshotsInterval := 24 * time.Hour * time.Duration(durationDays*count)
|
|
// gap too small no snapshot will be generated
|
|
if gapDuration < oneSnapshotInterval {
|
|
return snapshotsToRemove, snapshotsToGenerate, levelDbBootstrapPath, errors.New(fmt.Sprintf("last snapshot was generated at %v no need to generate new snapshots", lastSnapshotDate.Format(DateFormat)))
|
|
} else if gapDuration > totalSnapshotsInterval {
|
|
// gap too large generate from targetDate
|
|
// and remove all previous snapshots
|
|
_, snapshotsToGenerate, _, err = computeRequirementsFromEmpty(count, durationDays, targetDate)
|
|
for _, file := range previousSnapshots {
|
|
snapshotsToRemove = append(snapshotsToRemove, filepath.Join(homeDirectory, snapshotPath, file))
|
|
}
|
|
return
|
|
}
|
|
snapshotDate := lastSnapshotDate.AddDate(0, 0, durationDays)
|
|
for snapshotDate.Before(targetDate) || snapshotDate.Equal(targetDate) {
|
|
snapshotsToGenerate = append(snapshotsToGenerate, snapshotDate)
|
|
snapshotDate = snapshotDate.AddDate(0, 0, durationDays)
|
|
}
|
|
totalCount := len(previousSnapshots) + len(snapshotsToGenerate)
|
|
toRemoveIdx := 0
|
|
for toRemoveIdx < len(previousSnapshots) && totalCount-toRemoveIdx > count {
|
|
snapshotsToRemove = append(snapshotsToRemove, filepath.Join(homeDirectory, snapshotPath, previousSnapshots[toRemoveIdx]))
|
|
toRemoveIdx += 1
|
|
}
|
|
return
|
|
}
|
|
|
|
func computeRequirementsFromEmpty(count int, durationDays int, targetDate time.Time) (snapshotsToRemove []string, snapshotsToGenerate []time.Time, levelDbBootstrapPath string, err error) {
|
|
snapshotDate := targetDate
|
|
for i := 0; i < count; i++ {
|
|
snapshotsToGenerate = append(snapshotsToGenerate, snapshotDate)
|
|
snapshotDate = snapshotDate.AddDate(0, 0, -1*durationDays)
|
|
}
|
|
return snapshotsToRemove, snapshotsToGenerate, "", nil
|
|
}
|
|
|
|
// compute number of snapshot need to be generated and number of snapshots to remove from give directory.
|
|
func computeRequirements(homeDirectory string, snapshotPath string, count int, durationDays int) (snapshotsToRemove []string, snapshotsToGenerate []time.Time, levelDbBootstrapPath string, err error) {
|
|
snapshotDirectory := filepath.Join(homeDirectory, snapshotPath)
|
|
files, _ := os.ReadDir(snapshotDirectory)
|
|
// sort files by name
|
|
sort.Slice(files, func(i, j int) bool {
|
|
return files[i].Name() < files[j].Name()
|
|
})
|
|
// filter for snapshots file name only
|
|
var prevSnapshotFiles []string
|
|
for _, file := range files {
|
|
if strings.HasSuffix(file.Name(), SnapshotDirPostFix) {
|
|
prevSnapshotFiles = append(prevSnapshotFiles, file.Name())
|
|
}
|
|
}
|
|
curDate := time.Now()
|
|
curDateStr := curDate.Format(DateFormat)
|
|
// ensure snapshot start at today 00:00 - 1ns
|
|
today, err := time.Parse(DateFormat, curDateStr)
|
|
targetDate := today.Add(-1 * time.Nanosecond)
|
|
if len(prevSnapshotFiles) == 0 {
|
|
return computeRequirementsFromEmpty(count, durationDays, targetDate)
|
|
}
|
|
return computeRequirementsFromDirectory(prevSnapshotFiles, homeDirectory, snapshotPath, count, durationDays, targetDate)
|
|
}
|