diff --git a/core/api/src/main/java/org/opennms/core/network/IPAddress.java b/core/api/src/main/java/org/opennms/core/network/IPAddress.java index 452b6970d2a5..d19aefff352a 100644 --- a/core/api/src/main/java/org/opennms/core/network/IPAddress.java +++ b/core/api/src/main/java/org/opennms/core/network/IPAddress.java @@ -33,22 +33,27 @@ public class IPAddress implements Comparable { private static final Pattern LEADING_ZEROS = Pattern.compile("^0:[0:]+"); protected final InetAddress m_inetAddress; + private final byte[] m_addressBytes; public IPAddress(final IPAddress addr) { m_inetAddress = addr.m_inetAddress; + m_addressBytes = addr.m_addressBytes; } public IPAddress(final String dottedNotation) { m_inetAddress = getInetAddress(dottedNotation); + m_addressBytes = extractAddressBytes(m_inetAddress); } public IPAddress(final InetAddress inetAddress) { m_inetAddress = inetAddress; + m_addressBytes = extractAddressBytes(m_inetAddress); } public IPAddress(final byte[] ipAddrOctets) { try { - m_inetAddress = InetAddress.getByAddress(ipAddrOctets); + m_addressBytes = Arrays.copyOf(ipAddrOctets, ipAddrOctets.length); + m_inetAddress = InetAddress.getByAddress(m_addressBytes); } catch (final UnknownHostException e) { throw new IllegalArgumentException("Cannot convert bytes to an InetAddress.", e); } @@ -63,14 +68,14 @@ public InetAddress toInetAddress() { } public byte[] toOctets() { - return m_inetAddress.getAddress(); + return Arrays.copyOf(m_addressBytes, m_addressBytes.length); } @Override public boolean equals(final Object obj) { if (obj == null) return false; if (obj instanceof IPAddress) { - return Arrays.equals(m_inetAddress.getAddress(), ((IPAddress) obj).m_inetAddress.getAddress()); + return Arrays.equals(m_addressBytes, ((IPAddress) obj).m_addressBytes); } return false; } @@ -82,17 +87,17 @@ public int hashCode() { @Override public int compareTo(final IPAddress o) { - return compare(m_inetAddress.getAddress(), o.m_inetAddress.getAddress()); + return compare(m_addressBytes, o.m_addressBytes); } public String toUserString() { if (m_inetAddress instanceof Inet4Address) { - return toIpAddrString(m_inetAddress); + return toIpAddrString(m_addressBytes); } else if (m_inetAddress instanceof Inet6Address) { /* *

From: Guava.

*/ - final byte[] bytes = m_inetAddress.getAddress(); + final byte[] bytes = m_addressBytes; final int[] hextets = new int[8]; for (int i = 0; i < hextets.length; i++) { hextets[i] = fromBytes( @@ -116,12 +121,12 @@ public String toString() { } public String toDbString() { - return toIpAddrString(m_inetAddress); + return toIpAddrString(m_addressBytes); } /** {@inheritDoc} */ public BigInteger toBigInteger() { - return new BigInteger(1, m_inetAddress.getAddress()); + return new BigInteger(1, m_addressBytes); } /** @@ -130,7 +135,7 @@ public BigInteger toBigInteger() { * @return a {@link org.opennms.core.network.IPAddress} object. */ public IPAddress incr() { - final byte[] current = m_inetAddress.getAddress(); + final byte[] current = m_addressBytes; final byte[] b = new byte[current.length]; int carry = 1; @@ -154,7 +159,7 @@ public IPAddress incr() { * @return a {@link org.opennms.core.network.IPAddress} object. */ public IPAddress decr() { - final byte[] current = m_inetAddress.getAddress(); + final byte[] current = m_addressBytes; final byte[] b = new byte[current.length]; int borrow = 1; @@ -180,7 +185,7 @@ public IPAddress decr() { * @return a boolean. */ public boolean isPredecessorOf(final IPAddress other) { - return other.decr().equals(this); + return isImmediateSuccessor(other.m_addressBytes, m_addressBytes); } /** @@ -190,7 +195,7 @@ public boolean isPredecessorOf(final IPAddress other) { * @return a boolean. */ public boolean isSuccessorOf(final IPAddress other) { - return other.incr().equals(this); + return isImmediateSuccessor(m_addressBytes, other.m_addressBytes); } /** @@ -272,7 +277,7 @@ protected String toIpAddrString(final InetAddress addr) { protected String toIpAddrString(final byte[] addr) { if (addr.length == 4) { - return getInetAddress(addr).getHostAddress(); + return formatIpv4(addr); } else if (addr.length == 16) { return String.format("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", addr[0], @@ -311,8 +316,15 @@ private InetAddress getInetAddress(final byte[] ipAddrOctets) { } private InetAddress getInetAddress(final String dottedNotation) { + if (dottedNotation == null) { + return null; + } + final byte[] ipv4Bytes = tryParseIpv4Bytes(dottedNotation); + if (ipv4Bytes != null) { + return getInetAddress(ipv4Bytes); + } try { - return dottedNotation == null? null : InetAddress.getByName(dottedNotation); + return InetAddress.getByName(dottedNotation); } catch (final UnknownHostException e) { throw new IllegalArgumentException("Invalid IPAddress " + dottedNotation); } @@ -326,28 +338,87 @@ private int compare(final byte[] a, final byte[] b) { } else if (b == null) { return 1; } else { - // Make shorter byte arrays "less than" longer arrays - if (a.length < b.length) { - return -1; - } else if (a.length > b.length) { - return 1; - } else { - // Compare byte-by-byte - for (int i = 0; i < a.length; i++) { - final int aInt = unsignedByteToInt(a[i]); - final int bInt = unsignedByteToInt(b[i]); - if (aInt < bInt) { - return -1; - } else if (aInt > bInt) { - return 1; - } + final int lengthCmp = Integer.compare(a.length, b.length); + if (lengthCmp != 0) { + return lengthCmp; + } + for (int i = 0; i < a.length; i++) { + final int byteCmp = Integer.compare(a[i] & 0xFF, b[i] & 0xFF); + if (byteCmp != 0) { + return byteCmp; } - // OK both arrays are the same length and every byte is identical so they are equal - return 0; } + return 0; } } + private static boolean isImmediateSuccessor(final byte[] successor, final byte[] base) { + if (successor.length != base.length) { + return false; + } + int carry = 1; + for (int i = base.length - 1; i >= 0; i--) { + final int sum = (base[i] & 0xFF) + carry; + if ((successor[i] & 0xFF) != (sum & 0xFF)) { + return false; + } + carry = sum >> 8; + } + return carry == 0; + } + + private static String formatIpv4(final byte[] addr) { + return new StringBuilder(15) + .append(addr[0] & 0xFF).append('.') + .append(addr[1] & 0xFF).append('.') + .append(addr[2] & 0xFF).append('.') + .append(addr[3] & 0xFF) + .toString(); + } + + /** + * Parse a dotted-decimal IPv4 literal without invoking the JDK name service. + * + * @return four address octets, or {@code null} if the input is not a strict + * decimal IPv4 literal (caller should fall back to {@link InetAddress#getByName(String)}). + */ + private static byte[] tryParseIpv4Bytes(final String s) { + if (s == null || s.isEmpty()) { + return null; + } + final byte[] result = new byte[4]; + int part = 0; + int value = 0; + boolean hasDigit = false; + for (int i = 0; i < s.length(); i++) { + final char c = s.charAt(i); + if (c == '.') { + if (!hasDigit || value > 255 || part >= 3) { + return null; + } + result[part++] = (byte) value; + value = 0; + hasDigit = false; + } else if (c >= '0' && c <= '9') { + if (!hasDigit && c == '0' && i + 1 < s.length() && s.charAt(i + 1) != '.') { + return null; + } + hasDigit = true; + value = value * 10 + (c - '0'); + if (value > 255) { + return null; + } + } else { + return null; + } + } + if (!hasDigit || value > 255 || part != 3) { + return null; + } + result[3] = (byte) value; + return result; + } + /** * Returns the {@code int} value whose byte representation is the given 4 * bytes, in big-endian order; equivalent to {@code Ints.fromByteArray(new @@ -430,7 +501,14 @@ private static String hextetsToIPv6String(final int[] hextets) { return matcher.replaceAll(":"); } - private int unsignedByteToInt(final byte b) { - return b < 0 ? ((int)b)+256 : ((int)b); + private static byte[] extractAddressBytes(final InetAddress addr) { + if (addr == null) { + throw new IllegalArgumentException("Cannot convert null InetAddress to a byte array"); + } + final byte[] address = addr.getAddress(); + if (address == null) { + throw new IllegalArgumentException("InetAddress instance violates contract by returning a null address from getAddress()"); + } + return address; } } \ No newline at end of file diff --git a/core/api/src/test/java/org/opennms/core/network/IPAddressTest.java b/core/api/src/test/java/org/opennms/core/network/IPAddressTest.java new file mode 100644 index 000000000000..2af9841a3a8e --- /dev/null +++ b/core/api/src/test/java/org/opennms/core/network/IPAddressTest.java @@ -0,0 +1,93 @@ +/* + * Licensed to The OpenNMS Group, Inc (TOG) under one or more + * contributor license agreements. See the LICENSE.md file + * distributed with this work for additional information + * regarding copyright ownership. + * + * TOG licenses this file to You under the GNU Affero General + * Public License Version 3 (the "License") or (at your option) + * any later version. You may not use this file except in + * compliance with the License. You may obtain a copy of the + * License at: + * + * https://www.gnu.org/licenses/agpl-3.0.txt + * + * 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 org.opennms.core.network; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.net.InetAddress; + +import org.junit.Test; + +public class IPAddressTest { + + @Test + public void shouldReturnDefensiveCopyFromToOctets() { + final IPAddress ipAddress = new IPAddress("192.0.2.10"); + final byte[] octets = ipAddress.toOctets(); + octets[0] = 0; + + // Mutating the returned array must not alter internal state. + assertEquals("192.0.2.10", ipAddress.toDbString()); + assertTrue(ipAddress.equals(new IPAddress("192.0.2.10"))); + } + + @Test + public void shouldIncrementAndDecrementUsingCachedBytes() { + final IPAddress ipAddress = new IPAddress("192.0.2.10"); + + final IPAddress incremented = ipAddress.incr(); + final IPAddress decremented = incremented.decr(); + + assertEquals(ipAddress, decremented); + assertArrayEquals(new byte[] {(byte) 192, 0, 2, 11}, incremented.toOctets()); + } + + @Test + public void shouldFormatIpv4FromBytesWithoutInetAddressRoundTrip() { + final IPAddress ipAddress = new IPAddress(new byte[] {(byte) 192, 0, 2, 10}); + assertEquals("192.0.2.10", ipAddress.toDbString()); + assertEquals("192.0.2.10", ipAddress.toUserString()); + } + + @Test + public void shouldParseIpv4LiteralsWithoutNameService() throws Exception { + final IPAddress fast = new IPAddress("10.20.30.40"); + final IPAddress jdk = new IPAddress(InetAddress.getByName("10.20.30.40")); + assertEquals(jdk, fast); + assertEquals("10.20.30.40", fast.toDbString()); + } + + @Test + public void shouldFallBackToNameServiceForNonDecimalIpv4Literals() throws Exception { + final IPAddress ipv6 = new IPAddress("::1"); + assertTrue(ipv6.toInetAddress() instanceof java.net.Inet6Address); + } + + @Test + public void shouldDetectImmediatePredecessorAndSuccessorWithoutAllocating() { + final IPAddress zero = new IPAddress("0.0.0.0"); + final IPAddress one = new IPAddress("0.0.0.1"); + final IPAddress two = new IPAddress("0.0.0.2"); + + assertTrue(zero.isPredecessorOf(one)); + assertTrue(one.isSuccessorOf(zero)); + assertTrue(one.isPredecessorOf(two)); + assertTrue(two.isSuccessorOf(one)); + + assertFalse(one.isPredecessorOf(one)); + assertFalse(one.isSuccessorOf(one)); + assertFalse(zero.isSuccessorOf(two)); + } +} diff --git a/core/lib/src/main/java/org/opennms/core/utils/ByteArrayComparator.java b/core/lib/src/main/java/org/opennms/core/utils/ByteArrayComparator.java index 6e10f778f872..ee50cdaf9388 100644 --- a/core/lib/src/main/java/org/opennms/core/utils/ByteArrayComparator.java +++ b/core/lib/src/main/java/org/opennms/core/utils/ByteArrayComparator.java @@ -42,13 +42,13 @@ public int compare(byte[] a, byte[] b) { return 1; } else { // Make shorter byte arrays "less than" longer arrays - int comparison = Integer.valueOf(a.length).compareTo(Integer.valueOf(b.length)); + int comparison = Integer.compare(a.length, b.length); if (comparison != 0) { return comparison; } else { // Compare byte-by-byte for (int i = 0; i < a.length; i++) { - int byteComparison = Integer.valueOf(unsignedByteToInt(a[i])).compareTo(Integer.valueOf(unsignedByteToInt(b[i]))); + int byteComparison = Integer.compare(unsignedByteToInt(a[i]), unsignedByteToInt(b[i])); if (byteComparison != 0) { return byteComparison; } diff --git a/core/lib/src/main/java/org/opennms/core/utils/InetAddressUtils.java b/core/lib/src/main/java/org/opennms/core/utils/InetAddressUtils.java index af69602a35f3..6e243af89a9e 100644 --- a/core/lib/src/main/java/org/opennms/core/utils/InetAddressUtils.java +++ b/core/lib/src/main/java/org/opennms/core/utils/InetAddressUtils.java @@ -190,7 +190,7 @@ public static byte[] decr(final byte[] address) throws UnknownHostException { public static InetAddress getInetAddress(final int[] octets, final int offset, final int length) { final byte[] addressBytes = new byte[length]; for (int i = 0; i < addressBytes.length; i++) { - addressBytes[i] = Integer.valueOf(octets[i + offset]).byteValue(); + addressBytes[i] = (byte) octets[i + offset]; } return getInetAddress(addressBytes); } @@ -296,12 +296,13 @@ public static boolean isInetAddressInRange(final byte[] laddr, final String begi public static boolean isInetAddressInRange(final String addrString, final String beginString, final String endString) { final byte[] addr = InetAddressUtils.toIpAddrBytes(addrString); final byte[] begin = InetAddressUtils.toIpAddrBytes(beginString); - if (s_BYTE_ARRAY_COMPARATOR.compare(addr, begin) > 0) { + final int beginCmp = s_BYTE_ARRAY_COMPARATOR.compare(addr, begin); + if (beginCmp > 0) { final byte[] end = InetAddressUtils.toIpAddrBytes(endString); return (s_BYTE_ARRAY_COMPARATOR.compare(addr, end) <= 0); - } else if (s_BYTE_ARRAY_COMPARATOR.compare(addr, begin) == 0) { + } else if (beginCmp == 0) { return true; - } else { + } else { return false; } } @@ -318,7 +319,7 @@ public static boolean inSameScope(final InetAddress addr1, final InetAddress add return false; } else { // Compare the IPv6 scope IDs - return Integer.valueOf(((Inet6Address)addr1).getScopeId()).compareTo(((Inet6Address)addr2).getScopeId()) == 0; + return ((Inet6Address) addr1).getScopeId() == ((Inet6Address) addr2).getScopeId(); } } } @@ -329,7 +330,7 @@ public static InetAddress getIpv4Network(InetAddress ipaddress, InetAddress netm final byte[] netWork = new byte[4]; for (int i=0;i< 4; i++) { - netWork[i] = Integer.valueOf(ipAddress[i] & netMask[i]).byteValue(); + netWork[i] = (byte) (ipAddress[i] & netMask[i]); } return InetAddressUtils.getInetAddress(netWork); @@ -341,7 +342,7 @@ public static InetAddress getIpv6Network(InetAddress ipaddress, InetAddress netm final byte[] netWork = new byte[16]; for (int i=0;i< 16; i++) { - netWork[i] = Integer.valueOf(ipAddress[i] & netMask[i]).byteValue(); + netWork[i] = (byte) (ipAddress[i] & netMask[i]); } return InetAddressUtils.getInetAddress(netWork); @@ -358,16 +359,13 @@ public static InetAddress getNetwork(InetAddress ipaddress, InetAddress netmask) } public static boolean inSameIpv4Network(final InetAddress addr1, final InetAddress addr2, final InetAddress mask) { - final byte[] ipAddress1 = addr1.getAddress(); - final byte[] ipAddress2 = addr2.getAddress(); - final byte[] netMask = mask.getAddress(); - - for (int i=0;i< 4; i++) { - if ((ipAddress1[i] & netMask[i]) != (ipAddress2[i] & netMask[i])) - return false; - + if (!(addr1 instanceof Inet4Address) || !(addr2 instanceof Inet4Address) || !(mask instanceof Inet4Address)) { + throw new IllegalArgumentException("inSameIpv4Network requires IPv4 addresses and mask"); } - return true; + // Inet4Address.hashCode() returns the 32-bit address value, which lets us + // do network-prefix comparisons without allocating byte[] via getAddress(). + final int netMask = mask.hashCode(); + return (addr1.hashCode() & netMask) == (addr2.hashCode() & netMask); } public static boolean inSameIpv6Network(final InetAddress addr1, final InetAddress addr2, final InetAddress mask) { diff --git a/core/lib/src/test/java/org/opennms/core/utils/ByteArrayComparatorTest.java b/core/lib/src/test/java/org/opennms/core/utils/ByteArrayComparatorTest.java new file mode 100644 index 000000000000..5fe0313770f4 --- /dev/null +++ b/core/lib/src/test/java/org/opennms/core/utils/ByteArrayComparatorTest.java @@ -0,0 +1,39 @@ +/* + * Licensed to The OpenNMS Group, Inc (TOG) under one or more + * contributor license agreements. See the LICENSE.md file + * distributed with this work for additional information + * regarding copyright ownership. + * + * TOG licenses this file to You under the GNU Affero General + * Public License Version 3 (the "License") or (at your option) + * any later version. You may not use this file except in + * compliance with the License. You may obtain a copy of the + * License at: + * + * https://www.gnu.org/licenses/agpl-3.0.txt + * + * 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 org.opennms.core.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class ByteArrayComparatorTest { + + private static final ByteArrayComparator COMPARATOR = new ByteArrayComparator(); + + @Test + public void shouldOrderByLengthThenUnsignedByteValue() { + assertTrue(COMPARATOR.compare(new byte[] {1}, new byte[] {1, 0}) < 0); + assertTrue(COMPARATOR.compare(new byte[] {(byte) 255}, new byte[] {0}) > 0); + assertEquals(0, COMPARATOR.compare(new byte[] {10, 20}, new byte[] {10, 20})); + } +} diff --git a/core/lib/src/test/java/org/opennms/core/utils/InetAddressUtilsTest.java b/core/lib/src/test/java/org/opennms/core/utils/InetAddressUtilsTest.java index caceea9b0e12..892f74bf2e7d 100644 --- a/core/lib/src/test/java/org/opennms/core/utils/InetAddressUtilsTest.java +++ b/core/lib/src/test/java/org/opennms/core/utils/InetAddressUtilsTest.java @@ -131,5 +131,18 @@ public void shouldRejectNotValidMaskValue() { InetAddressUtils.convertInetAddressMaskToCidr(InetAddressUtils.addr("255.255.251.0")); } + @Test + public void shouldMatchIpv4NetworksWithoutAddressArrayExtraction() { + Assert.assertTrue(InetAddressUtils.inSameNetwork( + InetAddressUtils.addr("192.168.1.10"), + InetAddressUtils.addr("192.168.1.99"), + InetAddressUtils.addr("255.255.255.0"))); + + Assert.assertFalse(InetAddressUtils.inSameNetwork( + InetAddressUtils.addr("192.168.1.10"), + InetAddressUtils.addr("192.168.2.99"), + InetAddressUtils.addr("255.255.255.0"))); + } + } diff --git a/opennms-config-jaxb/src/main/java/org/opennms/netmgt/config/collectd/Package.java b/opennms-config-jaxb/src/main/java/org/opennms/netmgt/config/collectd/Package.java index 7a2a6cb63885..d85c44c4e6d7 100644 --- a/opennms-config-jaxb/src/main/java/org/opennms/netmgt/config/collectd/Package.java +++ b/opennms-config-jaxb/src/main/java/org/opennms/netmgt/config/collectd/Package.java @@ -34,6 +34,8 @@ import org.opennms.core.network.IPAddress; import org.opennms.core.network.IpListFromUrl; +import org.opennms.core.utils.ByteArrayComparator; +import org.opennms.core.utils.InetAddressUtils; /** * Package encapsulating addresses eligible to have SNMP @@ -215,15 +217,25 @@ public boolean removeSpecific(final String specific) { } public boolean hasSpecific(final byte[] addr) { - final IPAddress ipAddr = new IPAddress(addr); + if (addr == null) { + return false; + } + // Compare bytes directly to avoid allocating an InetAddress / IPAddress per spec. for (final String espec : getSpecifics()) { - if (ipAddr.equals(new IPAddress(espec))) { + final byte[] specBytes = InetAddressUtils.toIpAddrBytes(espec); + if (specBytes != null && BYTE_ARRAY_COMPARATOR.compare(addr, specBytes) == 0) { return true; } } return false; } + /** + * Stateless and thread-safe; reuse one instance to avoid per-comparison + * allocation in {@link #hasSpecific(byte[])} / range checks. + */ + private static final ByteArrayComparator BYTE_ARRAY_COMPARATOR = new ByteArrayComparator(); + public List getIncludeRanges() { if (m_includeRanges == null) { return Collections.emptyList(); @@ -249,12 +261,14 @@ public boolean hasIncludeRange(final String addr) { return true; } - final IPAddress ipAddr = new IPAddress(addr); + // Parse range bounds as bytes; reuse a single comparator instance. + final byte[] addrBytes = InetAddressUtils.toIpAddrBytes(addr); for (final IncludeRange rng : getIncludeRanges()) { - final IPAddress begin = rng.getBeginAsAddress(); - final IPAddress end = rng.getEndAsAddress(); - if (ipAddr.isGreaterThanOrEqualTo(begin) && ipAddr.isLessThanOrEqualTo(end)) { + final byte[] beginBytes = InetAddressUtils.toIpAddrBytes(rng.getBegin()); + final byte[] endBytes = InetAddressUtils.toIpAddrBytes(rng.getEnd()); + if (BYTE_ARRAY_COMPARATOR.compare(addrBytes, beginBytes) >= 0 + && BYTE_ARRAY_COMPARATOR.compare(addrBytes, endBytes) <= 0) { return true; } } @@ -282,13 +296,14 @@ public boolean removeExcludeRange(final ExcludeRange range) { } public boolean hasExcludeRange(final String addr) { - final IPAddress ipAddr = new IPAddress(addr); + final byte[] addrBytes = InetAddressUtils.toIpAddrBytes(addr); for (final ExcludeRange rng : getExcludeRanges()) { - final IPAddress begin = rng.getBeginAsAddress(); - final IPAddress end = rng.getEndAsAddress(); + final byte[] beginBytes = InetAddressUtils.toIpAddrBytes(rng.getBegin()); + final byte[] endBytes = InetAddressUtils.toIpAddrBytes(rng.getEnd()); - if (ipAddr.isGreaterThanOrEqualTo(begin) && ipAddr.isLessThanOrEqualTo(end)) { + if (BYTE_ARRAY_COMPARATOR.compare(addrBytes, beginBytes) >= 0 + && BYTE_ARRAY_COMPARATOR.compare(addrBytes, endBytes) <= 0) { return true; } } diff --git a/opennms-config-jaxb/src/main/java/org/opennms/netmgt/config/snmp/AddressSnmpConfigVisitor.java b/opennms-config-jaxb/src/main/java/org/opennms/netmgt/config/snmp/AddressSnmpConfigVisitor.java index ed334c808455..5b17be760c09 100644 --- a/opennms-config-jaxb/src/main/java/org/opennms/netmgt/config/snmp/AddressSnmpConfigVisitor.java +++ b/opennms-config-jaxb/src/main/java/org/opennms/netmgt/config/snmp/AddressSnmpConfigVisitor.java @@ -42,6 +42,7 @@ import static org.opennms.netmgt.snmp.SnmpConfiguration.versionToString; import java.net.InetAddress; +import java.util.Arrays; import java.util.List; import org.opennms.core.utils.ByteArrayComparator; @@ -58,6 +59,12 @@ public class AddressSnmpConfigVisitor extends AbstractSnmpConfigVisitor implemen private static final ByteArrayComparator BYTE_ARRAY_COMPARATOR = new ByteArrayComparator(); private final InetAddress m_address; + /** + * Cached network-byte-order representation of {@link #m_address}; computed + * once per visitor so the per-range / per-specific match loops do not + * allocate a fresh byte[] for every comparison. + */ + private final byte[] m_addressBytes; private final String m_location; private SnmpConfig m_currentConfig; @@ -80,6 +87,7 @@ public AddressSnmpConfigVisitor(final InetAddress addr) { public AddressSnmpConfigVisitor(final InetAddress addr, final String location) { m_address = addr; + m_addressBytes = addr == null ? null : addr.getAddress(); m_location = LocationUtils.getEffectiveLocationName(location); } @@ -141,9 +149,9 @@ public void visitSpecifics(final List specifics) { for (final String saddr : specifics) { try { - final InetAddress addr = InetAddressUtils.addr(saddr); - if (addr != null && addr.equals(m_address)) { - //LOG.debug("{} == {}", addr, m_address); + // Cached-once per visitor; safe because m_address is final. + final byte[] specBytes = InetAddressUtils.toIpAddrBytes(saddr); + if (specBytes != null && Arrays.equals(specBytes, m_addressBytes)) { handleMatch(); return; } @@ -158,11 +166,12 @@ public void visitRanges(List ranges) { // if we've already matched a specific, don't bother with the ranges if (!shouldTryToMatch()) return; + // Cached-once per visitor; safe because m_address is final. + final byte[] addr = m_addressBytes; for (final Range range : ranges) { - final byte[] addr = m_address.getAddress(); final byte[] begin = InetAddressUtils.toIpAddrBytes(range.getBegin()); final byte[] end = InetAddressUtils.toIpAddrBytes(range.getEnd()); - + final boolean inRange; if (BYTE_ARRAY_COMPARATOR.compare(begin, end) <= 0) { inRange = InetAddressUtils.isInetAddressInRange(addr, begin, end); diff --git a/opennms-config/src/main/java/org/opennms/netmgt/config/PollerConfigManager.java b/opennms-config/src/main/java/org/opennms/netmgt/config/PollerConfigManager.java index 4e3b32fbb8aa..72fa6c8375ec 100644 --- a/opennms-config/src/main/java/org/opennms/netmgt/config/PollerConfigManager.java +++ b/opennms-config/src/main/java/org/opennms/netmgt/config/PollerConfigManager.java @@ -235,6 +235,11 @@ public void setDefaultCriticalPathRetries(Integer retries) { private static final Logger LOG = LoggerFactory.getLogger(PollerConfigManager.class); + /** + * Stateless and thread-safe; reuse one instance to avoid per-comparison + * allocation in {@link #isInterfaceInPackage(String, Package)}. + */ + private static final ByteArrayComparator BYTE_ARRAY_COMPARATOR = new ByteArrayComparator(); private final ReadWriteLock m_globalLock = new ReentrantReadWriteLock(); private final Lock m_readLock = m_globalLock.readLock(); private final Lock m_writeLock = m_globalLock.writeLock(); @@ -691,9 +696,9 @@ public boolean isInterfaceInPackage(final String iface, final Package pkg) { final byte[] addr = toIpAddrBytes(iface); for (final IncludeRange rng : pkg.getIncludeRanges()) { - int comparison = new ByteArrayComparator().compare(addr, toIpAddrBytes(rng.getBegin())); + int comparison = BYTE_ARRAY_COMPARATOR.compare(addr, toIpAddrBytes(rng.getBegin())); if (comparison > 0) { - int endComparison = new ByteArrayComparator().compare(addr, toIpAddrBytes(rng.getEnd())); + int endComparison = BYTE_ARRAY_COMPARATOR.compare(addr, toIpAddrBytes(rng.getEnd())); if (endComparison <= 0) { has_range_include = true; break; @@ -705,7 +710,7 @@ public boolean isInterfaceInPackage(final String iface, final Package pkg) { } for (final String spec : pkg.getSpecifics()) { - if (new ByteArrayComparator().compare(addr, toIpAddrBytes(spec)) == 0) { + if (BYTE_ARRAY_COMPARATOR.compare(addr, toIpAddrBytes(spec)) == 0) { has_specific = true; LOG.debug("interfaceInPackage: Interface {} defined as 'specific'", iface); break; @@ -722,9 +727,9 @@ public boolean isInterfaceInPackage(final String iface, final Package pkg) { if (!has_specific) { for (final ExcludeRange rng : pkg.getExcludeRanges()) { - int comparison = new ByteArrayComparator().compare(addr, toIpAddrBytes(rng.getBegin())); + int comparison = BYTE_ARRAY_COMPARATOR.compare(addr, toIpAddrBytes(rng.getBegin())); if (comparison > 0) { - int endComparison = new ByteArrayComparator().compare(addr, toIpAddrBytes(rng.getEnd())); + int endComparison = BYTE_ARRAY_COMPARATOR.compare(addr, toIpAddrBytes(rng.getEnd())); if (endComparison <= 0) { LOG.debug("interfaceInPackage: Interface {} matches an exclude range", iface); has_range_exclude = true; diff --git a/opennms-config/src/main/java/org/opennms/netmgt/config/SnmpInterfacePollerConfigManager.java b/opennms-config/src/main/java/org/opennms/netmgt/config/SnmpInterfacePollerConfigManager.java index 9756ccdf4b0a..5162c5546dfe 100644 --- a/opennms-config/src/main/java/org/opennms/netmgt/config/SnmpInterfacePollerConfigManager.java +++ b/opennms-config/src/main/java/org/opennms/netmgt/config/SnmpInterfacePollerConfigManager.java @@ -65,6 +65,11 @@ */ abstract public class SnmpInterfacePollerConfigManager implements SnmpInterfacePollerConfig { private static final Logger LOG = LoggerFactory.getLogger(SnmpInterfacePollerConfigManager.class); + /** + * Stateless and thread-safe; reuse one instance to avoid per-comparison + * allocation in {@link #interfaceInPackage(String, Package)}. + */ + private static final ByteArrayComparator BYTE_ARRAY_COMPARATOR = new ByteArrayComparator(); /** *

Constructor for SnmpInterfacePollerConfigManager.

@@ -366,7 +371,7 @@ public synchronized boolean interfaceInPackage(String iface, Package pkg) { for (String spec : pkg.getSpecifics()) { byte[] speca = toIpAddrBytes(spec); - if (new ByteArrayComparator().compare(speca, addr) == 0) { + if (BYTE_ARRAY_COMPARATOR.compare(speca, addr) == 0) { has_specific = true; break; }