mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #6997 from gyuho/range
auth: improve 'removeSubsetRangePerms' to O(n)
This commit is contained in:
commit
cdde0368ad
@ -49,38 +49,30 @@ func isRangeEqual(a, b *rangePerm) bool {
|
|||||||
|
|
||||||
// removeSubsetRangePerms removes any rangePerms that are subsets of other rangePerms.
|
// removeSubsetRangePerms removes any rangePerms that are subsets of other rangePerms.
|
||||||
// If there are equal ranges, removeSubsetRangePerms only keeps one of them.
|
// If there are equal ranges, removeSubsetRangePerms only keeps one of them.
|
||||||
func removeSubsetRangePerms(perms []*rangePerm) []*rangePerm {
|
// It returns a sorted rangePerm slice.
|
||||||
// TODO(mitake): currently it is O(n^2), we need a better algorithm
|
func removeSubsetRangePerms(perms []*rangePerm) (newp []*rangePerm) {
|
||||||
var newp []*rangePerm
|
sort.Sort(RangePermSliceByBegin(perms))
|
||||||
|
var prev *rangePerm
|
||||||
for i := range perms {
|
for i := range perms {
|
||||||
skip := false
|
if i == 0 {
|
||||||
|
prev = perms[i]
|
||||||
for j := range perms {
|
newp = append(newp, perms[i])
|
||||||
if i == j {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if isRangeEqual(perms[i], prev) {
|
||||||
if isRangeEqual(perms[i], perms[j]) {
|
|
||||||
// if ranges are equal, we only keep the first range.
|
|
||||||
if i > j {
|
|
||||||
skip = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} else if isSubset(perms[i], perms[j]) {
|
|
||||||
// if a range is a strict subset of the other one, we skip the subset.
|
|
||||||
skip = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if skip {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if isSubset(perms[i], prev) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if isSubset(prev, perms[i]) {
|
||||||
|
prev = perms[i]
|
||||||
|
newp[len(newp)-1] = perms[i]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
prev = perms[i]
|
||||||
newp = append(newp, perms[i])
|
newp = append(newp, perms[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
return newp
|
return newp
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +80,6 @@ func removeSubsetRangePerms(perms []*rangePerm) []*rangePerm {
|
|||||||
func mergeRangePerms(perms []*rangePerm) []*rangePerm {
|
func mergeRangePerms(perms []*rangePerm) []*rangePerm {
|
||||||
var merged []*rangePerm
|
var merged []*rangePerm
|
||||||
perms = removeSubsetRangePerms(perms)
|
perms = removeSubsetRangePerms(perms)
|
||||||
sort.Sort(RangePermSliceByBegin(perms))
|
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
for i < len(perms) {
|
for i < len(perms) {
|
||||||
|
@ -16,6 +16,8 @@ package auth
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -131,3 +133,47 @@ func TestGetMergedPerms(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRemoveSubsetRangePerms(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
perms []*rangePerm
|
||||||
|
expect []*rangePerm
|
||||||
|
}{
|
||||||
|
{ // subsets converge
|
||||||
|
[]*rangePerm{{[]byte{2}, []byte{3}}, {[]byte{2}, []byte{5}}, {[]byte{1}, []byte{4}}},
|
||||||
|
[]*rangePerm{{[]byte{1}, []byte{4}}, {[]byte{2}, []byte{5}}},
|
||||||
|
},
|
||||||
|
{ // subsets converge
|
||||||
|
[]*rangePerm{{[]byte{0}, []byte{3}}, {[]byte{0}, []byte{1}}, {[]byte{2}, []byte{4}}, {[]byte{0}, []byte{2}}},
|
||||||
|
[]*rangePerm{{[]byte{0}, []byte{3}}, {[]byte{2}, []byte{4}}},
|
||||||
|
},
|
||||||
|
{ // biggest range at the end
|
||||||
|
[]*rangePerm{{[]byte{2}, []byte{3}}, {[]byte{0}, []byte{2}}, {[]byte{1}, []byte{4}}, {[]byte{0}, []byte{5}}},
|
||||||
|
[]*rangePerm{{[]byte{0}, []byte{5}}},
|
||||||
|
},
|
||||||
|
{ // biggest range at the beginning
|
||||||
|
[]*rangePerm{{[]byte{0}, []byte{5}}, {[]byte{2}, []byte{3}}, {[]byte{0}, []byte{2}}, {[]byte{1}, []byte{4}}},
|
||||||
|
[]*rangePerm{{[]byte{0}, []byte{5}}},
|
||||||
|
},
|
||||||
|
{ // no overlapping ranges
|
||||||
|
[]*rangePerm{{[]byte{2}, []byte{3}}, {[]byte{0}, []byte{1}}, {[]byte{4}, []byte{7}}, {[]byte{8}, []byte{15}}},
|
||||||
|
[]*rangePerm{{[]byte{0}, []byte{1}}, {[]byte{2}, []byte{3}}, {[]byte{4}, []byte{7}}, {[]byte{8}, []byte{15}}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i, tt := range tests {
|
||||||
|
rs := removeSubsetRangePerms(tt.perms)
|
||||||
|
if !reflect.DeepEqual(rs, tt.expect) {
|
||||||
|
t.Fatalf("#%d: unexpected rangePerms %q, got %q", i, printPerms(rs), printPerms(tt.expect))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printPerms(rs []*rangePerm) (txt string) {
|
||||||
|
for i, p := range rs {
|
||||||
|
if i != 0 {
|
||||||
|
txt += ","
|
||||||
|
}
|
||||||
|
txt += fmt.Sprintf("%+v", *p)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user