mirror of
https://github.com/minio/minio.git
synced 2025-01-11 15:03:22 -05:00
dataDir needs maxima calculation to be correct (#13715)
there is a corner case where the new check doesn't work where dataDir has changed, especially when xl.json -> xl.meta healing happens, if some healing is partial this can make certain backend files unreadable. This PR fixes and updates unit-tests
This commit is contained in:
parent
1e72e9b1cd
commit
36b5426f6e
@ -30,12 +30,14 @@ func commonTime(modTimes []time.Time, dataDirs []string) (modTime time.Time, dat
|
|||||||
var maxima int // Counter for remembering max occurrence of elements.
|
var maxima int // Counter for remembering max occurrence of elements.
|
||||||
|
|
||||||
timeOccurenceMap := make(map[int64]int, len(modTimes))
|
timeOccurenceMap := make(map[int64]int, len(modTimes))
|
||||||
|
dataDirMap := make(map[int64]string, len(modTimes))
|
||||||
// Ignore the uuid sentinel and count the rest.
|
// Ignore the uuid sentinel and count the rest.
|
||||||
for _, time := range modTimes {
|
for i, t := range modTimes {
|
||||||
if time.Equal(timeSentinel) {
|
if t.Equal(timeSentinel) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
timeOccurenceMap[time.UnixNano()]++
|
dataDirMap[t.UnixNano()] = dataDirs[i]
|
||||||
|
timeOccurenceMap[t.UnixNano()]++
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the common cardinality from previously collected
|
// Find the common cardinality from previously collected
|
||||||
@ -44,18 +46,11 @@ func commonTime(modTimes []time.Time, dataDirs []string) (modTime time.Time, dat
|
|||||||
t := time.Unix(0, nano).UTC()
|
t := time.Unix(0, nano).UTC()
|
||||||
if count > maxima || (count == maxima && t.After(modTime)) {
|
if count > maxima || (count == maxima && t.After(modTime)) {
|
||||||
maxima = count
|
maxima = count
|
||||||
|
dataDir = dataDirMap[nano]
|
||||||
modTime = t
|
modTime = t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, ddataDir := range dataDirs {
|
|
||||||
if modTimes[i].Equal(modTime) {
|
|
||||||
// Return the data-dir that matches modTime.
|
|
||||||
dataDir = ddataDir
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the collected common uuid.
|
// Return the collected common uuid.
|
||||||
return modTime, dataDir
|
return modTime, dataDir
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,10 @@ import (
|
|||||||
func TestCommonTime(t *testing.T) {
|
func TestCommonTime(t *testing.T) {
|
||||||
// List of test cases for common modTime.
|
// List of test cases for common modTime.
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
times []time.Time
|
times []time.Time
|
||||||
time time.Time
|
dataDirs []string
|
||||||
|
time time.Time
|
||||||
|
dataDir string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
// 1. Tests common times when slice has varying time elements.
|
// 1. Tests common times when slice has varying time elements.
|
||||||
@ -47,7 +49,17 @@ func TestCommonTime(t *testing.T) {
|
|||||||
time.Unix(0, 2).UTC(),
|
time.Unix(0, 2).UTC(),
|
||||||
time.Unix(0, 3).UTC(),
|
time.Unix(0, 3).UTC(),
|
||||||
time.Unix(0, 1).UTC(),
|
time.Unix(0, 1).UTC(),
|
||||||
}, time.Unix(0, 3).UTC(),
|
}, []string{
|
||||||
|
errorDir,
|
||||||
|
delMarkerDir,
|
||||||
|
"cd3b36c0-49e6-11ec-8087-73a2b2fd4016",
|
||||||
|
"cd3b36c0-49e6-11ec-8087-73a2b2fd4016",
|
||||||
|
"cd3b36c0-49e6-11ec-8087-73a2b2fd4016",
|
||||||
|
"cd3b36c0-49e6-11ec-8087-73a2b2fd4016",
|
||||||
|
"cd3b36c0-49e6-11ec-8087-73a2b2fd4016",
|
||||||
|
},
|
||||||
|
time.Unix(0, 3).UTC(),
|
||||||
|
"cd3b36c0-49e6-11ec-8087-73a2b2fd4016",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// 2. Tests common time obtained when all elements are equal.
|
// 2. Tests common time obtained when all elements are equal.
|
||||||
@ -59,7 +71,17 @@ func TestCommonTime(t *testing.T) {
|
|||||||
time.Unix(0, 3).UTC(),
|
time.Unix(0, 3).UTC(),
|
||||||
time.Unix(0, 3).UTC(),
|
time.Unix(0, 3).UTC(),
|
||||||
time.Unix(0, 3).UTC(),
|
time.Unix(0, 3).UTC(),
|
||||||
}, time.Unix(0, 3).UTC(),
|
}, []string{
|
||||||
|
errorDir,
|
||||||
|
delMarkerDir,
|
||||||
|
delMarkerDir,
|
||||||
|
delMarkerDir,
|
||||||
|
delMarkerDir,
|
||||||
|
delMarkerDir,
|
||||||
|
delMarkerDir,
|
||||||
|
},
|
||||||
|
time.Unix(0, 3).UTC(),
|
||||||
|
delMarkerDir,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// 3. Tests common time obtained when elements have a mixture
|
// 3. Tests common time obtained when elements have a mixture
|
||||||
@ -75,7 +97,17 @@ func TestCommonTime(t *testing.T) {
|
|||||||
timeSentinel,
|
timeSentinel,
|
||||||
timeSentinel,
|
timeSentinel,
|
||||||
timeSentinel,
|
timeSentinel,
|
||||||
}, time.Unix(0, 3).UTC(),
|
}, []string{
|
||||||
|
errorDir,
|
||||||
|
delMarkerDir,
|
||||||
|
delMarkerDir,
|
||||||
|
delMarkerDir,
|
||||||
|
delMarkerDir,
|
||||||
|
delMarkerDir,
|
||||||
|
delMarkerDir,
|
||||||
|
},
|
||||||
|
time.Unix(0, 3).UTC(),
|
||||||
|
delMarkerDir,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,9 +115,13 @@ func TestCommonTime(t *testing.T) {
|
|||||||
// common modtime. Tests fail if modtime does not match.
|
// common modtime. Tests fail if modtime does not match.
|
||||||
for i, testCase := range testCases {
|
for i, testCase := range testCases {
|
||||||
// Obtain a common mod time from modTimes slice.
|
// Obtain a common mod time from modTimes slice.
|
||||||
ctime, _ := commonTime(testCase.times, nil)
|
ctime, dataDir := commonTime(testCase.times, testCase.dataDirs)
|
||||||
if !testCase.time.Equal(ctime) {
|
if !testCase.time.Equal(ctime) {
|
||||||
t.Fatalf("Test case %d, expect to pass but failed. Wanted modTime: %s, got modTime: %s\n", i+1, testCase.time, ctime)
|
t.Errorf("Test case %d, expect to pass but failed. Wanted modTime: %s, got modTime: %s\n", i+1, testCase.time, ctime)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if dataDir != testCase.dataDir {
|
||||||
|
t.Errorf("Test case %d, expect to pass but failed. Wanted dataDir: %s, got dataDir: %s\n", i+1, testCase.dataDir, dataDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user