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

2 years ago
  1. package shell
  2. import (
  3. "errors"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "sort"
  8. "strings"
  9. "time"
  10. )
  11. func computeRequirementsFromDirectory(previousSnapshots []string, homeDirectory string, snapshotPath string, count int, durationDays int, targetDate time.Time) (snapshotsToRemove []string, snapshotsToGenerate []time.Time, levelDbBootstrapPath string, err error) {
  12. levelDbBootstrapPath = previousSnapshots[len(previousSnapshots)-1]
  13. lastSnapshotDate, err := time.Parse(DateFormat, levelDbBootstrapPath[:len(DateFormat)])
  14. if err != nil {
  15. return
  16. }
  17. if err != nil {
  18. return
  19. }
  20. // the snapshots cover the last nanosecond of the current date
  21. lastSnapshotDate = lastSnapshotDate.AddDate(0, 0, 1).Add(-1 * time.Nanosecond)
  22. gapDuration := targetDate.Sub(lastSnapshotDate)
  23. oneSnapshotInterval := 24 * time.Hour * time.Duration(durationDays)
  24. totalSnapshotsInterval := 24 * time.Hour * time.Duration(durationDays*count)
  25. // gap too small no snapshot will be generated
  26. if gapDuration < oneSnapshotInterval {
  27. return snapshotsToRemove, snapshotsToGenerate, levelDbBootstrapPath, errors.New(fmt.Sprintf("last snapshot was generated at %v no need to generate new snapshots", lastSnapshotDate.Format(DateFormat)))
  28. } else if gapDuration > totalSnapshotsInterval {
  29. // gap too large generate from targetDate
  30. // and remove all previous snapshots
  31. _, snapshotsToGenerate, _, err = computeRequirementsFromEmpty(count, durationDays, targetDate)
  32. for _, file := range previousSnapshots {
  33. snapshotsToRemove = append(snapshotsToRemove, filepath.Join(homeDirectory, snapshotPath, file))
  34. }
  35. return
  36. }
  37. snapshotDate := lastSnapshotDate.AddDate(0, 0, durationDays)
  38. for snapshotDate.Before(targetDate) || snapshotDate.Equal(targetDate) {
  39. snapshotsToGenerate = append(snapshotsToGenerate, snapshotDate)
  40. snapshotDate = snapshotDate.AddDate(0, 0, durationDays)
  41. }
  42. totalCount := len(previousSnapshots) + len(snapshotsToGenerate)
  43. toRemoveIdx := 0
  44. for toRemoveIdx < len(previousSnapshots) && totalCount-toRemoveIdx > count {
  45. snapshotsToRemove = append(snapshotsToRemove, filepath.Join(homeDirectory, snapshotPath, previousSnapshots[toRemoveIdx]))
  46. toRemoveIdx += 1
  47. }
  48. return
  49. }
  50. func computeRequirementsFromEmpty(count int, durationDays int, targetDate time.Time) (snapshotsToRemove []string, snapshotsToGenerate []time.Time, levelDbBootstrapPath string, err error) {
  51. snapshotDate := targetDate
  52. for i := 0; i < count; i++ {
  53. snapshotsToGenerate = append(snapshotsToGenerate, snapshotDate)
  54. snapshotDate = snapshotDate.AddDate(0, 0, -1*durationDays)
  55. }
  56. return snapshotsToRemove, snapshotsToGenerate, "", nil
  57. }
  58. // compute number of snapshot need to be generated and number of snapshots to remove from give directory.
  59. func computeRequirements(homeDirectory string, snapshotPath string, count int, durationDays int) (snapshotsToRemove []string, snapshotsToGenerate []time.Time, levelDbBootstrapPath string, err error) {
  60. snapshotDirectory := filepath.Join(homeDirectory, snapshotPath)
  61. files, _ := os.ReadDir(snapshotDirectory)
  62. // sort files by name
  63. sort.Slice(files, func(i, j int) bool {
  64. return files[i].Name() < files[j].Name()
  65. })
  66. // filter for snapshots file name only
  67. var prevSnapshotFiles []string
  68. for _, file := range files {
  69. if strings.HasSuffix(file.Name(), SnapshotDirPostFix) {
  70. prevSnapshotFiles = append(prevSnapshotFiles, file.Name())
  71. }
  72. }
  73. curDate := time.Now()
  74. curDateStr := curDate.Format(DateFormat)
  75. // ensure snapshot start at today 00:00 - 1ns
  76. today, err := time.Parse(DateFormat, curDateStr)
  77. targetDate := today.Add(-1 * time.Nanosecond)
  78. if len(prevSnapshotFiles) == 0 {
  79. return computeRequirementsFromEmpty(count, durationDays, targetDate)
  80. }
  81. return computeRequirementsFromDirectory(prevSnapshotFiles, homeDirectory, snapshotPath, count, durationDays, targetDate)
  82. }