Moves ACL ID sorting interface onto the iterator.

This commit is contained in:
James Phillips 2016-08-09 11:08:26 -07:00
parent ae1cd5b47d
commit 17537a0f10
No known key found for this signature in database
GPG Key ID: 77183E682AC5FC11
2 changed files with 23 additions and 27 deletions

View File

@ -10,30 +10,11 @@ import (
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib"
) )
// aclIDSorter is used to make sure a given list of ACLs is sorted by token ID.
// This should always be true, but since this is crucial for correctness and we
// are accepting input from another server, we sort to make sure.
type aclIDSorter struct {
acls structs.ACLs
}
// See sort.Interface.
func (a *aclIDSorter) Len() int {
return len(a.acls)
}
// See sort.Interface.
func (a *aclIDSorter) Swap(i, j int) {
a.acls[i], a.acls[j] = a.acls[j], a.acls[i]
}
// See sort.Interface.
func (a *aclIDSorter) Less(i, j int) bool {
return a.acls[i].ID < a.acls[j].ID
}
// aclIterator simplifies the algorithm below by providing a basic iterator that // aclIterator simplifies the algorithm below by providing a basic iterator that
// moves through a list of ACLs and returns nil when it's exhausted. // moves through a list of ACLs and returns nil when it's exhausted. It also has
// methods for pre-sorting the ACLs being iterated over by ID, which should
// already be true, but since this is crucial for correctness and we are taking
// input from other servers, we sort to make sure.
type aclIterator struct { type aclIterator struct {
acls structs.ACLs acls structs.ACLs
@ -46,6 +27,21 @@ func newACLIterator(acls structs.ACLs) *aclIterator {
return &aclIterator{acls: acls} return &aclIterator{acls: acls}
} }
// See sort.Interface.
func (a *aclIterator) Len() int {
return len(a.acls)
}
// See sort.Interface.
func (a *aclIterator) Swap(i, j int) {
a.acls[i], a.acls[j] = a.acls[j], a.acls[i]
}
// See sort.Interface.
func (a *aclIterator) Less(i, j int) bool {
return a.acls[i].ID < a.acls[j].ID
}
// Front returns the item at index position, or nil if the list is exhausted. // Front returns the item at index position, or nil if the list is exhausted.
func (a *aclIterator) Front() *structs.ACL { func (a *aclIterator) Front() *structs.ACL {
if a.index < len(a.acls) { if a.index < len(a.acls) {
@ -72,12 +68,12 @@ func reconcileACLs(local, remote structs.ACLs, lastRemoteIndex uint64) structs.A
// version of Consul, and sorted-ness is kind of a subtle property of // version of Consul, and sorted-ness is kind of a subtle property of
// the state store indexing, it's prudent to make sure things are sorted // the state store indexing, it's prudent to make sure things are sorted
// before we begin. // before we begin.
sort.Sort(&aclIDSorter{local}) localIter, remoteIter := newACLIterator(local), newACLIterator(remote)
sort.Sort(&aclIDSorter{remote}) sort.Sort(localIter)
sort.Sort(remoteIter)
// Run through both lists and reconcile them. // Run through both lists and reconcile them.
var changes structs.ACLRequests var changes structs.ACLRequests
localIter, remoteIter := newACLIterator(local), newACLIterator(remote)
for localIter.Front() != nil || remoteIter.Front() != nil { for localIter.Front() != nil || remoteIter.Front() != nil {
// If the local list is exhausted, then process this as a remote // If the local list is exhausted, then process this as a remote
// add. We know from the loop condition that there's something // add. We know from the loop condition that there's something

View File

@ -21,7 +21,7 @@ func TestACLReplication_Sorter(t *testing.T) {
&structs.ACL{ID: "c"}, &structs.ACL{ID: "c"},
} }
sorter := &aclIDSorter{acls} sorter := &aclIterator{acls, 0}
if len := sorter.Len(); len != 3 { if len := sorter.Len(); len != 3 {
t.Fatalf("bad: %d", len) t.Fatalf("bad: %d", len)
} }