server: Sort disk arguments for consistent ordering (#3469)
This is important in a distributed setup, where the server hosting the first disk formats a fresh setup. Sorting ensures that all servers arrive at the same 'first' server. Note: This change doesn't protect against different disk arguments with some disks being same across servers.master
parent
5404dddcea
commit
85c6bb9809
@ -0,0 +1,34 @@ |
|||||||
|
/* |
||||||
|
* Minio Cloud Storage, (C) 2016 Minio, Inc. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package cmd |
||||||
|
|
||||||
|
import "net/url" |
||||||
|
|
||||||
|
type byHostPath []*url.URL |
||||||
|
|
||||||
|
func (s byHostPath) Swap(i, j int) { |
||||||
|
s[i], s[j] = s[j], s[i] |
||||||
|
} |
||||||
|
|
||||||
|
func (s byHostPath) Len() int { |
||||||
|
return len(s) |
||||||
|
} |
||||||
|
|
||||||
|
// Note: Host in url.URL includes the port too.
|
||||||
|
func (s byHostPath) Less(i, j int) bool { |
||||||
|
return (s[i].Host + s[i].Path) < (s[j].Host + s[j].Path) |
||||||
|
} |
@ -0,0 +1,99 @@ |
|||||||
|
/* |
||||||
|
* Minio Cloud Storage, (C) 2016 Minio, Inc. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package cmd |
||||||
|
|
||||||
|
import ( |
||||||
|
"net/url" |
||||||
|
"reflect" |
||||||
|
"sort" |
||||||
|
"testing" |
||||||
|
) |
||||||
|
|
||||||
|
// TestSortByHostPath - tests if ordering of urls are based on
|
||||||
|
// host+path concatenated.
|
||||||
|
func TestSortByHostPath(t *testing.T) { |
||||||
|
testCases := []struct { |
||||||
|
given []string |
||||||
|
expected []*url.URL |
||||||
|
}{ |
||||||
|
{ |
||||||
|
given: []string{ |
||||||
|
"http://abcd.com/a/b/d", |
||||||
|
"http://abcd.com/a/b/c", |
||||||
|
"http://abcd.com/a/b/e", |
||||||
|
}, |
||||||
|
expected: []*url.URL{ |
||||||
|
{ |
||||||
|
Scheme: "http", |
||||||
|
Host: "abcd.com:9000", |
||||||
|
Path: "/a/b/c", |
||||||
|
}, |
||||||
|
{ |
||||||
|
Scheme: "http", |
||||||
|
Host: "abcd.com:9000", |
||||||
|
Path: "/a/b/d", |
||||||
|
}, |
||||||
|
{ |
||||||
|
Scheme: "http", |
||||||
|
Host: "abcd.com:9000", |
||||||
|
Path: "/a/b/e", |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
given: []string{ |
||||||
|
"http://defg.com/a/b/c", |
||||||
|
"http://abcd.com/a/b/c", |
||||||
|
"http://hijk.com/a/b/c", |
||||||
|
}, |
||||||
|
expected: []*url.URL{ |
||||||
|
{ |
||||||
|
Scheme: "http", |
||||||
|
Host: "abcd.com:9000", |
||||||
|
Path: "/a/b/c", |
||||||
|
}, |
||||||
|
{ |
||||||
|
Scheme: "http", |
||||||
|
Host: "defg.com:9000", |
||||||
|
Path: "/a/b/c", |
||||||
|
}, |
||||||
|
{ |
||||||
|
Scheme: "http", |
||||||
|
Host: "hijk.com:9000", |
||||||
|
Path: "/a/b/c", |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
saveGlobalPort := globalMinioPort |
||||||
|
globalMinioPort = "9000" |
||||||
|
for i, test := range testCases { |
||||||
|
eps, err := parseStorageEndpoints(test.given) |
||||||
|
if err != nil { |
||||||
|
t.Fatalf("Test %d - Failed to parse storage endpoint %v", i+1, err) |
||||||
|
} |
||||||
|
sort.Sort(byHostPath(eps)) |
||||||
|
if !sort.IsSorted(byHostPath(eps)) { |
||||||
|
t.Errorf("Test %d - Expected order %v but got %v", i+1, test.expected, eps) |
||||||
|
} |
||||||
|
if !reflect.DeepEqual(eps, test.expected) { |
||||||
|
t.Errorf("Test %d - Expected order %v but got %v", i+1, test.expected, eps) |
||||||
|
} |
||||||
|
} |
||||||
|
globalMinioPort = saveGlobalPort |
||||||
|
} |
Loading…
Reference in new issue