From c824f0f55cb46885e479fd4a59dcb03dc0ce5b78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Weber?= Date: Tue, 2 Jul 2019 14:42:19 +1000 Subject: [PATCH 1/4] fix sort, with a helper so the sort is done 'naturally' --- pkg/backup/backup_manager.go | 61 +++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/pkg/backup/backup_manager.go b/pkg/backup/backup_manager.go index a82ae32eb..a6f03d771 100644 --- a/pkg/backup/backup_manager.go +++ b/pkg/backup/backup_manager.go @@ -19,7 +19,10 @@ import ( "crypto/tls" "fmt" "sort" + "strconv" + "strings" "time" + "unicode" "github.com/coreos/etcd-operator/pkg/backup/writer" "github.com/coreos/etcd-operator/pkg/util/constants" @@ -83,13 +86,69 @@ func (bm *BackupManager) SaveSnap(ctx context.Context, s3Path string, isPeriodic } // EnsureMaxBackup to ensure the number of snapshot is under maxcount +// We need to naturally sort it, help functions below: +type Compare func(str1, str2 string) bool + +func (cmp Compare) Sort(strs []string) { + strSort := &strSorter{ + strs: strs, + cmp: cmp, + } + sort.Sort(strSort) +} + +type strSorter struct { + strs []string + cmp func(str1, str2 string) bool +} + +func extractNumberFromString(str string, size int) (num int) { + + strSlice := make([]string, 0) + for _, v := range str { + if unicode.IsDigit(v) { + strSlice = append(strSlice, string(v)) + } + } + + if size == 0 { // default + num, err := strconv.Atoi(strings.Join(strSlice, "")) + if err != nil { + return fmt.Errorf("failed: %v", err) + } + + return num + } else { + num, err := strconv.Atoi(strSlice[size-1]) + if err != nil { + return fmt.Errorf("failed: %v", err) + } + + return num + } +} + +func (s *strSorter) Len() int { return len(s.strs) } + +func (s *strSorter) Swap(i, j int) { s.strs[i], s.strs[j] = s.strs[j], s.strs[i] } + +func (s *strSorter) Less(i, j int) bool { return s.cmp(s.strs[i], s.strs[j]) } + // if the number of snapshot exceeded than maxcount, delete oldest snapshot func (bm *BackupManager) EnsureMaxBackup(ctx context.Context, basePath string, maxCount int) error { savedSnapShots, err := bm.bw.List(ctx, basePath) if err != nil { return fmt.Errorf("failed to get exisiting snapshots: %v", err) } - sort.Sort(sort.Reverse(sort.StringSlice(savedSnapShots))) + + // closure order for natural string number sorting + compareStringNumber := func(str1, str2 string) bool { + // switch this <> around to change the order (asc vs des) + return extractNumberFromString(str1, 0) < extractNumberFromString(str2, 0) + } + // this is sorted on the etcd revision number, the smaller the number the older it is + Compare(compareStringNumber).Sort(savedSnapShots) + for i, snapshotPath := range savedSnapShots { if i < maxCount { continue From d037bbce3ddfcac3154258e006c4520d96b1fadc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Weber?= Date: Tue, 2 Jul 2019 15:29:31 +1000 Subject: [PATCH 2/4] do not return, just fail --- pkg/backup/backup_manager.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/backup/backup_manager.go b/pkg/backup/backup_manager.go index a6f03d771..1375e7b9e 100644 --- a/pkg/backup/backup_manager.go +++ b/pkg/backup/backup_manager.go @@ -114,14 +114,14 @@ func extractNumberFromString(str string, size int) (num int) { if size == 0 { // default num, err := strconv.Atoi(strings.Join(strSlice, "")) if err != nil { - return fmt.Errorf("failed: %v", err) + fmt.Errorf("failed: %v", err) } return num } else { num, err := strconv.Atoi(strSlice[size-1]) if err != nil { - return fmt.Errorf("failed: %v", err) + fmt.Errorf("failed: %v", err) } return num From f832e12513783df8edb434c7752abe80bf973917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Weber?= Date: Thu, 4 Jul 2019 08:36:00 +1000 Subject: [PATCH 3/4] give kudo's to the blog where the solution was sourced from --- pkg/backup/backup_manager.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/backup/backup_manager.go b/pkg/backup/backup_manager.go index 1375e7b9e..6929dceb1 100644 --- a/pkg/backup/backup_manager.go +++ b/pkg/backup/backup_manager.go @@ -102,6 +102,7 @@ type strSorter struct { cmp func(str1, str2 string) bool } +// Thanks to https://www.socketloop.com/tutorials/golang-natural-string-sorting-example func extractNumberFromString(str string, size int) (num int) { strSlice := make([]string, 0) From 2e12cd4be040a8135382ea9c51a0d394bec29c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Weber?= Date: Wed, 10 Jul 2019 12:40:40 +1000 Subject: [PATCH 4/4] ordering the incorrect way, handle numbers greater than int --- pkg/backup/backup_manager.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/backup/backup_manager.go b/pkg/backup/backup_manager.go index 6929dceb1..99ec3ab48 100644 --- a/pkg/backup/backup_manager.go +++ b/pkg/backup/backup_manager.go @@ -103,7 +103,7 @@ type strSorter struct { } // Thanks to https://www.socketloop.com/tutorials/golang-natural-string-sorting-example -func extractNumberFromString(str string, size int) (num int) { +func extractNumberFromString(str string, size int) (num float64) { strSlice := make([]string, 0) for _, v := range str { @@ -113,14 +113,14 @@ func extractNumberFromString(str string, size int) (num int) { } if size == 0 { // default - num, err := strconv.Atoi(strings.Join(strSlice, "")) + num, err := strconv.ParseFloat(strings.Join(strSlice, ""), 64) if err != nil { fmt.Errorf("failed: %v", err) } return num } else { - num, err := strconv.Atoi(strSlice[size-1]) + num, err := strconv.ParseFloat(strSlice[size-1], 64) if err != nil { fmt.Errorf("failed: %v", err) } @@ -145,7 +145,7 @@ func (bm *BackupManager) EnsureMaxBackup(ctx context.Context, basePath string, m // closure order for natural string number sorting compareStringNumber := func(str1, str2 string) bool { // switch this <> around to change the order (asc vs des) - return extractNumberFromString(str1, 0) < extractNumberFromString(str2, 0) + return extractNumberFromString(str1, 0) > extractNumberFromString(str2, 0) } // this is sorted on the etcd revision number, the smaller the number the older it is Compare(compareStringNumber).Sort(savedSnapShots)