mirror of https://github.com/grpc/grpc-java.git
xds: replace PriorityHeap with simpler logic that keeps track of top matches (#8225)
This commit is contained in:
parent
1cd925c3dd
commit
54b4e93927
|
|
@ -40,10 +40,8 @@ import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.PriorityQueue;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
|
@ -307,26 +305,19 @@ public final class XdsClientWrapperForServerSds {
|
||||||
return cidrInt.equals(addrInt);
|
return cidrInt.equals(addrInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class QueueElement {
|
private static int getMatchingPrefixLength(
|
||||||
FilterChain filterChain;
|
FilterChainMatch filterChainMatch, InetAddress address, boolean forDestination) {
|
||||||
int indexOfMatchingPrefixRange;
|
|
||||||
int matchingPrefixLength;
|
|
||||||
|
|
||||||
public QueueElement(FilterChain filterChain, InetAddress address, boolean forDestination) {
|
|
||||||
this.filterChain = filterChain;
|
|
||||||
FilterChainMatch filterChainMatch = filterChain.getFilterChainMatch();
|
|
||||||
byte[] addressBytes = address.getAddress();
|
byte[] addressBytes = address.getAddress();
|
||||||
boolean isIPv6 = address instanceof Inet6Address;
|
boolean isIPv6 = address instanceof Inet6Address;
|
||||||
List<CidrRange> cidrRanges =
|
List<CidrRange> cidrRanges =
|
||||||
forDestination
|
forDestination
|
||||||
? filterChainMatch.getPrefixRanges()
|
? filterChainMatch.getPrefixRanges()
|
||||||
: filterChainMatch.getSourcePrefixRanges();
|
: filterChainMatch.getSourcePrefixRanges();
|
||||||
indexOfMatchingPrefixRange = -1;
|
int matchingPrefixLength;
|
||||||
if (cidrRanges.isEmpty()) { // if there is no CidrRange assume 0-length match
|
if (cidrRanges.isEmpty()) { // if there is no CidrRange assume 0-length match
|
||||||
matchingPrefixLength = 0;
|
matchingPrefixLength = 0;
|
||||||
} else {
|
} else {
|
||||||
matchingPrefixLength = -1;
|
matchingPrefixLength = -1;
|
||||||
int index = 0;
|
|
||||||
for (CidrRange cidrRange : cidrRanges) {
|
for (CidrRange cidrRange : cidrRanges) {
|
||||||
InetAddress cidrAddr = cidrRange.getAddressPrefix();
|
InetAddress cidrAddr = cidrRange.getAddressPrefix();
|
||||||
boolean cidrIsIpv6 = cidrAddr instanceof Inet6Address;
|
boolean cidrIsIpv6 = cidrAddr instanceof Inet6Address;
|
||||||
|
|
@ -336,59 +327,33 @@ public final class XdsClientWrapperForServerSds {
|
||||||
if (isCidrMatching(cidrBytes, addressBytes, prefixLen)
|
if (isCidrMatching(cidrBytes, addressBytes, prefixLen)
|
||||||
&& prefixLen > matchingPrefixLength) {
|
&& prefixLen > matchingPrefixLength) {
|
||||||
matchingPrefixLength = prefixLen;
|
matchingPrefixLength = prefixLen;
|
||||||
indexOfMatchingPrefixRange = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return matchingPrefixLength;
|
||||||
private static final class QueueElementComparator implements Comparator<QueueElement> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(QueueElement o1, QueueElement o2) {
|
|
||||||
// descending order for max heap
|
|
||||||
return o2.matchingPrefixLength - o1.matchingPrefixLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
return obj instanceof QueueElementComparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return super.hashCode();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// use prefix_ranges (CIDR) and get the most specific matches
|
// use prefix_ranges (CIDR) and get the most specific matches
|
||||||
private static List<FilterChain> filterOnIpAddress(
|
private static List<FilterChain> filterOnIpAddress(
|
||||||
List<FilterChain> filterChains, InetAddress address, boolean forDestination) {
|
List<FilterChain> filterChains, InetAddress address, boolean forDestination) {
|
||||||
PriorityQueue<QueueElement> heap = new PriorityQueue<>(10, new QueueElementComparator());
|
// curent list of top ones
|
||||||
|
ArrayList<FilterChain> topOnes = new ArrayList<>(filterChains.size());
|
||||||
for (FilterChain filterChain : filterChains) {
|
|
||||||
QueueElement element = new QueueElement(filterChain, address, forDestination);
|
|
||||||
|
|
||||||
if (element.matchingPrefixLength >= 0) {
|
|
||||||
heap.add(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// get the top ones
|
|
||||||
ArrayList<FilterChain> topOnes = new ArrayList<>(heap.size());
|
|
||||||
int topMatchingPrefixLen = -1;
|
int topMatchingPrefixLen = -1;
|
||||||
while (!heap.isEmpty()) {
|
for (FilterChain filterChain : filterChains) {
|
||||||
QueueElement element = heap.remove();
|
int currentMatchingPrefixLen =
|
||||||
if (topMatchingPrefixLen == -1) {
|
getMatchingPrefixLength(filterChain.getFilterChainMatch(), address, forDestination);
|
||||||
topMatchingPrefixLen = element.matchingPrefixLength;
|
|
||||||
} else {
|
if (currentMatchingPrefixLen >= 0) {
|
||||||
if (element.matchingPrefixLength < topMatchingPrefixLen) {
|
if (currentMatchingPrefixLen < topMatchingPrefixLen) {
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (currentMatchingPrefixLen > topMatchingPrefixLen) {
|
||||||
|
topMatchingPrefixLen = currentMatchingPrefixLen;
|
||||||
|
topOnes.clear();
|
||||||
|
}
|
||||||
|
topOnes.add(filterChain);
|
||||||
}
|
}
|
||||||
topOnes.add(element.filterChain);
|
|
||||||
}
|
}
|
||||||
return topOnes;
|
return topOnes;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue