From 37c70f58211c42409cf88b7f49272b805a7685b3 Mon Sep 17 00:00:00 2001 From: Srijeet Chatterjee Date: Wed, 29 Nov 2023 16:53:55 -0700 Subject: [PATCH 1/5] Replace synchronization in Zone with locks --- src/main/java/org/xbill/DNS/Zone.java | 214 +++++++++++++--------- src/test/java/org/xbill/DNS/ZoneTest.java | 105 +++++++++++ 2 files changed, 234 insertions(+), 85 deletions(-) diff --git a/src/main/java/org/xbill/DNS/Zone.java b/src/main/java/org/xbill/DNS/Zone.java index 644b3430..7971bf04 100644 --- a/src/main/java/org/xbill/DNS/Zone.java +++ b/src/main/java/org/xbill/DNS/Zone.java @@ -11,6 +11,7 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.TreeMap; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * A DNS Zone. This encapsulates all data related to a Zone, and provides convenient lookup methods. @@ -19,6 +20,9 @@ */ public class Zone implements Serializable { + private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + private ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock(); + private ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock(); private static final long serialVersionUID = -9220510891189510942L; /** A primary zone */ @@ -41,21 +45,24 @@ class ZoneIterator implements Iterator { private boolean wantLastSOA; ZoneIterator(boolean axfr) { - synchronized (Zone.this) { + try { + readLock.lock(); zentries = data.entrySet().iterator(); - } - wantLastSOA = axfr; - RRset[] sets = allRRsets(originNode); - current = new RRset[sets.length]; - for (int i = 0, j = 2; i < sets.length; i++) { - int type = sets[i].getType(); - if (type == Type.SOA) { - current[0] = sets[i]; - } else if (type == Type.NS) { - current[1] = sets[i]; - } else { - current[j++] = sets[i]; + wantLastSOA = axfr; + RRset[] sets = allRRsets(originNode); + current = new RRset[sets.length]; + for (int i = 0, j = 2; i < sets.length; i++) { + int type = sets[i].getType(); + if (type == Type.SOA) { + current[0] = sets[i]; + } else if (type == Type.NS) { + current[1] = sets[i]; + } else { + current[j++] = sets[i]; + } } + } finally { + readLock.unlock(); } } @@ -99,6 +106,14 @@ public void remove() { } } + public void setLock(ReentrantReadWriteLock.ReadLock lock) { + readLock = lock; + } + + public ReentrantReadWriteLock getLock() { + return readWriteLock; + } + private void validate() throws IOException { originNode = exactName(origin); if (originNode == null) { @@ -167,15 +182,23 @@ public Zone(Name zone, Record[] records) throws IOException { throw new IllegalArgumentException("no zone name specified"); } origin = zone; - for (Record record : records) { - maybeAddRecord(record); + try { + writeLock.lock(); + for (Record record : records) { + maybeAddRecord(record); + } + validate(); + } finally { + writeLock.unlock(); } - validate(); } private void fromXFR(ZoneTransferIn xfrin) throws IOException, ZoneTransferException { - synchronized (this) { + try { + writeLock.lock(); data = new TreeMap<>(); + } finally { + writeLock.unlock(); } origin = xfrin.getName(); @@ -231,43 +254,58 @@ public int getDClass() { return DClass.IN; } - private synchronized Object exactName(Name name) { - return data.get(name); + private Object exactName(Name name) { + try { + readLock.lock(); + return data.get(name); + } finally { + readLock.unlock(); + } } - private synchronized RRset[] allRRsets(Object types) { + private RRset[] allRRsets(Object types) { if (types instanceof List) { - @SuppressWarnings("unchecked") - List typelist = (List) types; - return typelist.toArray(new RRset[0]); + try { + readLock.lock(); + @SuppressWarnings("unchecked") + List typelist = (List) types; + return typelist.toArray(new RRset[0]); + } finally { + readLock.unlock(); + } } else { RRset set = (RRset) types; return new RRset[] {set}; } } - private synchronized RRset oneRRset(Object types, int type) { - if (type == Type.ANY) { - throw new IllegalArgumentException("oneRRset(ANY)"); - } - if (types instanceof List) { - @SuppressWarnings("unchecked") - List list = (List) types; - for (RRset set : list) { + private RRset oneRRset(Object types, int type) { + try { + readLock.lock(); + if (type == Type.ANY) { + throw new IllegalArgumentException("oneRRset(ANY)"); + } + if (types instanceof List) { + @SuppressWarnings("unchecked") + List list = (List) types; + for (RRset set : list) { + if (set.getType() == type) { + return set; + } + } + } else { + RRset set = (RRset) types; if (set.getType() == type) { return set; } } - } else { - RRset set = (RRset) types; - if (set.getType() == type) { - return set; - } + return null; + } finally { + readLock.unlock(); } - return null; } - private synchronized RRset findRRset(Name name, int type) { + private RRset findRRset(Name name, int type) { Object types = exactName(name); if (types == null) { return null; @@ -275,7 +313,7 @@ private synchronized RRset findRRset(Name name, int type) { return oneRRset(types, type); } - private synchronized void addRRset(Name name, RRset rrset) { + private void addRRset(Name name, RRset rrset) { if (!hasWild && name.isWild()) { hasWild = true; } @@ -309,34 +347,39 @@ private synchronized void addRRset(Name name, RRset rrset) { } } - private synchronized void removeRRset(Name name, int type) { - Object types = data.get(name); - if (types == null) { - return; - } - if (types instanceof List) { - @SuppressWarnings("unchecked") - List list = (List) types; - for (int i = 0; i < list.size(); i++) { - RRset set = list.get(i); - if (set.getType() == type) { - list.remove(i); - if (list.isEmpty()) { - data.remove(name); + private void removeRRset(Name name, int type) { + try { + writeLock.lock(); + Object types = data.get(name); + if (types == null) { + return; + } + if (types instanceof List) { + @SuppressWarnings("unchecked") + List list = (List) types; + for (int i = 0; i < list.size(); i++) { + RRset set = list.get(i); + if (set.getType() == type) { + list.remove(i); + if (list.isEmpty()) { + data.remove(name); + } + return; } + } + } else { + RRset set = (RRset) types; + if (set.getType() != type) { return; } + data.remove(name); } - } else { - RRset set = (RRset) types; - if (set.getType() != type) { - return; - } - data.remove(name); + } finally { + writeLock.unlock(); } } - private synchronized SetResponse lookup(Name name, int type) { + private SetResponse lookup(Name name, int type) { if (!name.subdomain(origin)) { return SetResponse.ofType(SetResponse.NXDOMAIN); } @@ -491,14 +534,12 @@ public void addRRset(RRset rrset) { public void addRecord(T r) { Name name = r.getName(); int rtype = r.getRRsetType(); - synchronized (this) { - RRset rrset = findRRset(name, rtype); - if (rrset == null) { - rrset = new RRset(r); - addRRset(name, rrset); - } else { - rrset.addRR(r); - } + RRset rrset = findRRset(name, rtype); + if (rrset == null) { + rrset = new RRset(r); + addRRset(name, rrset); + } else { + rrset.addRR(r); } } @@ -511,16 +552,14 @@ public void addRecord(T r) { public void removeRecord(Record r) { Name name = r.getName(); int rtype = r.getRRsetType(); - synchronized (this) { - RRset rrset = findRRset(name, rtype); - if (rrset == null) { - return; - } - if (rrset.size() == 1 && rrset.first().equals(r)) { - removeRRset(name, rtype); - } else { - rrset.deleteRR(r); - } + RRset rrset = findRRset(name, rtype); + if (rrset == null) { + return; + } + if (rrset.size() == 1 && rrset.first().equals(r)) { + removeRRset(name, rtype); + } else { + rrset.deleteRR(r); } } @@ -547,15 +586,20 @@ private void nodeToString(StringBuffer sb, Object node) { } /** Returns the contents of the Zone in master file format. */ - public synchronized String toMasterFile() { - StringBuffer sb = new StringBuffer(); - nodeToString(sb, originNode); - for (Map.Entry entry : data.entrySet()) { - if (!origin.equals(entry.getKey())) { - nodeToString(sb, entry.getValue()); + public String toMasterFile() { + try { + readLock.lock(); + StringBuffer sb = new StringBuffer(); + nodeToString(sb, originNode); + for (Map.Entry entry : data.entrySet()) { + if (!origin.equals(entry.getKey())) { + nodeToString(sb, entry.getValue()); + } } + return sb.toString(); + } finally { + readLock.unlock(); } - return sb.toString(); } /** Returns the contents of the Zone as a string (in master file format). */ diff --git a/src/test/java/org/xbill/DNS/ZoneTest.java b/src/test/java/org/xbill/DNS/ZoneTest.java index bd39e903..9f932565 100644 --- a/src/test/java/org/xbill/DNS/ZoneTest.java +++ b/src/test/java/org/xbill/DNS/ZoneTest.java @@ -3,16 +3,22 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import java.io.IOException; import java.net.InetAddress; import java.util.Collections; import java.util.List; +import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.Test; class ZoneTest { + int answers = 0; + Zone zone = null; private static final ARecord A_TEST; private static final AAAARecord AAAA_1_TEST; private static final AAAARecord AAAA_2_TEST; @@ -110,6 +116,105 @@ void wildNameAnyLookup() { resp.answers()); } + @Test + void testReadLocksAreAcquiredAndReleasedCorrectNumberOfTimes() { + Name testName = Name.fromConstantString("test.example."); + ReentrantReadWriteLock.ReadLock readLock = mock(ReentrantReadWriteLock.ReadLock.class); + ZONE.setLock(readLock); + SetResponse resp = ZONE.findRecords(testName, Type.ANY); + verify(readLock, times(5)).lock(); + verify(readLock, times(5)).unlock(); + } + + @Test + void testReadsWaitForWrites() throws Exception { + final AAAARecord AAAA_1_TEST_RECORD; + final AAAARecord AAAA_2_TEST_RECORD; + final ARecord A_WILD_RECORD; + final TXTRecord TXT_WILD_RECORD; + + Name testNameZone = new Name("example."); + InetAddress localhost4 = InetAddress.getByName("127.0.0.1"); + InetAddress localhost6a = InetAddress.getByName("::1"); + InetAddress localhost6b = InetAddress.getByName("::2"); + AAAA_1_TEST_RECORD = + new AAAARecord(new Name("test", testNameZone), DClass.IN, 3600, localhost6a); + AAAA_2_TEST_RECORD = + new AAAARecord(new Name("test", testNameZone), DClass.IN, 3600, localhost6b); + A_WILD_RECORD = new ARecord(new Name("*", testNameZone), DClass.IN, 3600, localhost4); + TXT_WILD_RECORD = new TXTRecord(new Name("*", testNameZone), DClass.IN, 3600, "sometext"); + + Record[] zoneRecordElements = new Record[100]; + zoneRecordElements[0] = + new SOARecord( + testNameZone, + DClass.IN, + 3600L, + Name.fromConstantString("nameserver."), + new Name("hostmaster", testNameZone), + 1, + 21600L, + 7200L, + 2160000L, + 3600L); + + zoneRecordElements[1] = + new NSRecord(testNameZone, DClass.IN, 300L, Name.fromConstantString("nameserver.")); + zoneRecordElements[96] = AAAA_1_TEST_RECORD; + zoneRecordElements[97] = AAAA_2_TEST_RECORD; + zoneRecordElements[98] = A_WILD_RECORD; + zoneRecordElements[99] = TXT_WILD_RECORD; + + int start = 1; + for (int i = 2; i <= 95; i++) { + zoneRecordElements[i] = + new ARecord( + new Name("test", testNameZone), + DClass.IN, + 3600, + InetAddress.getByName("127.0.0." + start)); + start++; + } + + Thread t1 = + new Thread( + new Runnable() { + @Override + public void run() { + try { + zone = new Zone(testNameZone, zoneRecordElements); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + + Thread t2 = + new Thread( + new Runnable() { + @Override + public void run() { + Name testName = Name.fromConstantString("test.example."); + while (zone == null) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + SetResponse resp = zone.findRecords(testName, Type.ANY); + answers = resp.answers().get(0).size(); + } + }); + + t1.start(); + t2.start(); + + t1.join(); + t2.join(); + assertEquals(94, answers); + } + private static List listOf(RRset... rrsets) { return Stream.of(rrsets).collect(Collectors.toList()); } From 9d5939518cf56b49498abd6be61630e837dabd90 Mon Sep 17 00:00:00 2001 From: Srijeet Chatterjee Date: Mon, 4 Dec 2023 15:31:01 -0700 Subject: [PATCH 2/5] code review --- pom.xml | 5 + src/main/java/org/xbill/DNS/Zone.java | 231 +++++++++++----------- src/main/java11/module-info.java | 1 + src/test/java/org/xbill/DNS/ZoneTest.java | 9 +- 4 files changed, 118 insertions(+), 128 deletions(-) diff --git a/pom.xml b/pom.xml index dd9fce8b..44c538de 100644 --- a/pom.xml +++ b/pom.xml @@ -535,6 +535,11 @@ 2.15.0 test + + com.google.guava + guava + 32.0.0-jre + diff --git a/src/main/java/org/xbill/DNS/Zone.java b/src/main/java/org/xbill/DNS/Zone.java index 7971bf04..2c7d3fb6 100644 --- a/src/main/java/org/xbill/DNS/Zone.java +++ b/src/main/java/org/xbill/DNS/Zone.java @@ -3,6 +3,7 @@ package org.xbill.DNS; +import com.google.common.annotations.VisibleForTesting; import java.io.IOException; import java.io.Serializable; import java.util.Iterator; @@ -20,10 +21,9 @@ */ public class Zone implements Serializable { - private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); - private ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock(); - private ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock(); - private static final long serialVersionUID = -9220510891189510942L; + private transient ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + private transient ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock(); + private transient ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock(); /** A primary zone */ public static final int PRIMARY = 1; @@ -44,26 +44,23 @@ class ZoneIterator implements Iterator { private int count; private boolean wantLastSOA; - ZoneIterator(boolean axfr) { - try { - readLock.lock(); - zentries = data.entrySet().iterator(); - wantLastSOA = axfr; - RRset[] sets = allRRsets(originNode); - current = new RRset[sets.length]; - for (int i = 0, j = 2; i < sets.length; i++) { - int type = sets[i].getType(); - if (type == Type.SOA) { - current[0] = sets[i]; - } else if (type == Type.NS) { - current[1] = sets[i]; - } else { - current[j++] = sets[i]; - } + ZoneIterator(boolean axfr) throws IllegalMonitorStateException { + readLock.lock(); + zentries = data.entrySet().iterator(); + wantLastSOA = axfr; + RRset[] sets = allRRsets(originNode); + current = new RRset[sets.length]; + for (int i = 0, j = 2; i < sets.length; i++) { + int type = sets[i].getType(); + if (type == Type.SOA) { + current[0] = sets[i]; + } else if (type == Type.NS) { + current[1] = sets[i]; + } else { + current[j++] = sets[i]; } - } finally { - readLock.unlock(); } + readLock.unlock(); } @Override @@ -106,14 +103,11 @@ public void remove() { } } - public void setLock(ReentrantReadWriteLock.ReadLock lock) { + @VisibleForTesting + void setLock(ReentrantReadWriteLock.ReadLock lock) { readLock = lock; } - public ReentrantReadWriteLock getLock() { - return readWriteLock; - } - private void validate() throws IOException { originNode = exactName(origin); if (originNode == null) { @@ -132,7 +126,7 @@ private void validate() throws IOException { } } - private void maybeAddRecord(Record record) throws IOException { + private void maybeAddRecord(Record record) throws IOException, IllegalMonitorStateException { int rtype = record.getType(); Name name = record.getName(); @@ -151,7 +145,8 @@ private void maybeAddRecord(Record record) throws IOException { * @param file The master file to read from. * @see Master */ - public Zone(Name zone, String file) throws IOException { + public Zone(Name zone, String file) throws IOException, IllegalMonitorStateException { + writeLock.lock(); data = new TreeMap<>(); if (zone == null) { @@ -166,6 +161,7 @@ public Zone(Name zone, String file) throws IOException { } } validate(); + writeLock.unlock(); } /** @@ -175,35 +171,30 @@ public Zone(Name zone, String file) throws IOException { * @param records The records to add to the zone. * @see Master */ - public Zone(Name zone, Record[] records) throws IOException { + public Zone(Name zone, Record[] records) throws IOException, IllegalMonitorStateException { + writeLock.lock(); data = new TreeMap<>(); if (zone == null) { throw new IllegalArgumentException("no zone name specified"); } origin = zone; - try { - writeLock.lock(); - for (Record record : records) { - maybeAddRecord(record); - } - validate(); - } finally { - writeLock.unlock(); + for (Record record : records) { + maybeAddRecord(record); } + validate(); + writeLock.unlock(); } - private void fromXFR(ZoneTransferIn xfrin) throws IOException, ZoneTransferException { - try { - writeLock.lock(); - data = new TreeMap<>(); - } finally { - writeLock.unlock(); - } + private void fromXFR(ZoneTransferIn xfrin) + throws IOException, ZoneTransferException, IllegalMonitorStateException { + writeLock.lock(); + data = new TreeMap<>(); origin = xfrin.getName(); xfrin.run(); if (!xfrin.isAXFR()) { + writeLock.unlock(); throw new IllegalArgumentException("zones can only be created from AXFRs"); } @@ -211,6 +202,7 @@ private void fromXFR(ZoneTransferIn xfrin) throws IOException, ZoneTransferExcep maybeAddRecord(record); } validate(); + writeLock.unlock(); } /** @@ -254,55 +246,49 @@ public int getDClass() { return DClass.IN; } - private Object exactName(Name name) { - try { - readLock.lock(); - return data.get(name); - } finally { - readLock.unlock(); - } + private Object exactName(Name name) throws IllegalMonitorStateException { + readLock.lock(); + Object val = data.get(name); + readLock.unlock(); + return val; } - private RRset[] allRRsets(Object types) { + private RRset[] allRRsets(Object types) throws IllegalMonitorStateException { if (types instanceof List) { - try { - readLock.lock(); - @SuppressWarnings("unchecked") - List typelist = (List) types; - return typelist.toArray(new RRset[0]); - } finally { - readLock.unlock(); - } + readLock.lock(); + @SuppressWarnings("unchecked") + List typelist = (List) types; + readLock.unlock(); + return typelist.toArray(new RRset[0]); } else { RRset set = (RRset) types; return new RRset[] {set}; } } - private RRset oneRRset(Object types, int type) { - try { - readLock.lock(); - if (type == Type.ANY) { - throw new IllegalArgumentException("oneRRset(ANY)"); - } - if (types instanceof List) { - @SuppressWarnings("unchecked") - List list = (List) types; - for (RRset set : list) { - if (set.getType() == type) { - return set; - } - } - } else { - RRset set = (RRset) types; + private RRset oneRRset(Object types, int type) throws IllegalMonitorStateException { + if (type == Type.ANY) { + throw new IllegalArgumentException("oneRRset(ANY)"); + } + readLock.lock(); + RRset resultSet = null; + if (types instanceof List) { + @SuppressWarnings("unchecked") + List list = (List) types; + for (RRset set : list) { if (set.getType() == type) { - return set; + resultSet = set; + break; } } - return null; - } finally { - readLock.unlock(); + } else { + RRset set = (RRset) types; + if (set.getType() == type) { + resultSet = set; + } } + readLock.unlock(); + return resultSet; } private RRset findRRset(Name name, int type) { @@ -347,36 +333,36 @@ private void addRRset(Name name, RRset rrset) { } } - private void removeRRset(Name name, int type) { - try { - writeLock.lock(); - Object types = data.get(name); - if (types == null) { - return; - } - if (types instanceof List) { - @SuppressWarnings("unchecked") - List list = (List) types; - for (int i = 0; i < list.size(); i++) { - RRset set = list.get(i); - if (set.getType() == type) { - list.remove(i); - if (list.isEmpty()) { - data.remove(name); - } - return; + private void removeRRset(Name name, int type) throws IllegalMonitorStateException { + writeLock.lock(); + Object types = data.get(name); + if (types == null) { + writeLock.unlock(); + return; + } + if (types instanceof List) { + @SuppressWarnings("unchecked") + List list = (List) types; + for (int i = 0; i < list.size(); i++) { + RRset set = list.get(i); + if (set.getType() == type) { + list.remove(i); + if (list.isEmpty()) { + data.remove(name); } - } - } else { - RRset set = (RRset) types; - if (set.getType() != type) { + writeLock.unlock(); return; } - data.remove(name); } - } finally { - writeLock.unlock(); + } else { + RRset set = (RRset) types; + if (set.getType() != type) { + writeLock.unlock(); + return; + } + data.remove(name); } + writeLock.unlock(); } private SetResponse lookup(Name name, int type) { @@ -520,9 +506,11 @@ public RRset findExactMatch(Name name, int type) { * @param rrset The RRset to be added * @see RRset */ - public void addRRset(RRset rrset) { + public void addRRset(RRset rrset) throws IllegalMonitorStateException { + writeLock.lock(); Name name = rrset.getName(); addRRset(name, rrset); + writeLock.unlock(); } /** @@ -531,7 +519,8 @@ public void addRRset(RRset rrset) { * @param r The record to be added * @see Record */ - public void addRecord(T r) { + public void addRecord(T r) throws IllegalMonitorStateException { + writeLock.lock(); Name name = r.getName(); int rtype = r.getRRsetType(); RRset rrset = findRRset(name, rtype); @@ -541,6 +530,7 @@ public void addRecord(T r) { } else { rrset.addRR(r); } + writeLock.unlock(); } /** @@ -549,7 +539,8 @@ public void addRecord(T r) { * @param r The record to be removed * @see Record */ - public void removeRecord(Record r) { + public void removeRecord(Record r) throws IllegalMonitorStateException { + writeLock.lock(); Name name = r.getName(); int rtype = r.getRRsetType(); RRset rrset = findRRset(name, rtype); @@ -561,6 +552,7 @@ public void removeRecord(Record r) { } else { rrset.deleteRR(r); } + writeLock.unlock(); } /** Returns an Iterator over the RRsets in the zone. */ @@ -586,20 +578,17 @@ private void nodeToString(StringBuffer sb, Object node) { } /** Returns the contents of the Zone in master file format. */ - public String toMasterFile() { - try { - readLock.lock(); - StringBuffer sb = new StringBuffer(); - nodeToString(sb, originNode); - for (Map.Entry entry : data.entrySet()) { - if (!origin.equals(entry.getKey())) { - nodeToString(sb, entry.getValue()); - } + public String toMasterFile() throws IllegalMonitorStateException { + readLock.lock(); + StringBuffer sb = new StringBuffer(); + nodeToString(sb, originNode); + for (Map.Entry entry : data.entrySet()) { + if (!origin.equals(entry.getKey())) { + nodeToString(sb, entry.getValue()); } - return sb.toString(); - } finally { - readLock.unlock(); } + readLock.unlock(); + return sb.toString(); } /** Returns the contents of the Zone as a string (in master file format). */ diff --git a/src/main/java11/module-info.java b/src/main/java11/module-info.java index 8ed16887..247aca7a 100644 --- a/src/main/java11/module-info.java +++ b/src/main/java11/module-info.java @@ -7,6 +7,7 @@ requires static com.sun.jna.platform; requires static java.net.http; requires org.slf4j; + requires com.google.common; exports org.xbill.DNS; exports org.xbill.DNS.config; diff --git a/src/test/java/org/xbill/DNS/ZoneTest.java b/src/test/java/org/xbill/DNS/ZoneTest.java index 9f932565..89b16288 100644 --- a/src/test/java/org/xbill/DNS/ZoneTest.java +++ b/src/test/java/org/xbill/DNS/ZoneTest.java @@ -182,6 +182,7 @@ void testReadsWaitForWrites() throws Exception { @Override public void run() { try { + Thread.sleep(1000); zone = new Zone(testNameZone, zoneRecordElements); } catch (Exception e) { e.printStackTrace(); @@ -195,19 +196,13 @@ public void run() { @Override public void run() { Name testName = Name.fromConstantString("test.example."); - while (zone == null) { - try { - Thread.sleep(1); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } SetResponse resp = zone.findRecords(testName, Type.ANY); answers = resp.answers().get(0).size(); } }); t1.start(); + Thread.sleep(2000); t2.start(); t1.join(); From 0b0d96ee5312ec1afde4e748a21e22d06df5d742 Mon Sep 17 00:00:00 2001 From: Srijeet Chatterjee Date: Thu, 7 Dec 2023 17:50:28 -0700 Subject: [PATCH 3/5] cleanup --- src/main/java/org/xbill/DNS/Zone.java | 33 ++++++++++++++++----------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/xbill/DNS/Zone.java b/src/main/java/org/xbill/DNS/Zone.java index 2c7d3fb6..ea9044d0 100644 --- a/src/main/java/org/xbill/DNS/Zone.java +++ b/src/main/java/org/xbill/DNS/Zone.java @@ -69,7 +69,7 @@ public boolean hasNext() { } @Override - public RRset next() { + public RRset next() throws IllegalMonitorStateException { if (!hasNext()) { throw new NoSuchElementException(); } @@ -108,7 +108,7 @@ void setLock(ReentrantReadWriteLock.ReadLock lock) { readLock = lock; } - private void validate() throws IOException { + private void validate() throws IOException, IllegalMonitorStateException { originNode = exactName(origin); if (originNode == null) { throw new IOException(origin + ": no data specified"); @@ -150,6 +150,7 @@ public Zone(Name zone, String file) throws IOException, IllegalMonitorStateExcep data = new TreeMap<>(); if (zone == null) { + writeLock.unlock(); throw new IllegalArgumentException("no zone name specified"); } try (Master m = new Master(file, zone)) { @@ -211,7 +212,8 @@ private void fromXFR(ZoneTransferIn xfrin) * @param xfrin The incoming zone transfer to execute. * @see ZoneTransferIn */ - public Zone(ZoneTransferIn xfrin) throws IOException, ZoneTransferException { + public Zone(ZoneTransferIn xfrin) + throws IOException, ZoneTransferException, IllegalMonitorStateException { fromXFR(xfrin); } @@ -220,7 +222,8 @@ public Zone(ZoneTransferIn xfrin) throws IOException, ZoneTransferException { * * @see ZoneTransferIn */ - public Zone(Name zone, int dclass, String remote) throws IOException, ZoneTransferException { + public Zone(Name zone, int dclass, String remote) + throws IOException, ZoneTransferException, IllegalMonitorStateException { ZoneTransferIn xfrin = ZoneTransferIn.newAXFR(zone, remote, null); xfrin.setDClass(dclass); fromXFR(xfrin); @@ -299,13 +302,15 @@ private RRset findRRset(Name name, int type) { return oneRRset(types, type); } - private void addRRset(Name name, RRset rrset) { + private void addRRset(Name name, RRset rrset) throws IllegalMonitorStateException { + writeLock.lock(); if (!hasWild && name.isWild()) { hasWild = true; } Object types = data.get(name); if (types == null) { data.put(name, rrset); + writeLock.unlock(); return; } int rtype = rrset.getType(); @@ -316,6 +321,7 @@ private void addRRset(Name name, RRset rrset) { RRset set = list.get(i); if (set.getType() == rtype) { list.set(i, rrset); + writeLock.unlock(); return; } } @@ -331,6 +337,7 @@ private void addRRset(Name name, RRset rrset) { data.put(name, list); } } + writeLock.unlock(); } private void removeRRset(Name name, int type) throws IllegalMonitorStateException { @@ -365,7 +372,7 @@ private void removeRRset(Name name, int type) throws IllegalMonitorStateExceptio writeLock.unlock(); } - private SetResponse lookup(Name name, int type) { + private SetResponse lookup(Name name, int type) throws IllegalMonitorStateException { if (!name.subdomain(origin)) { return SetResponse.ofType(SetResponse.NXDOMAIN); } @@ -480,7 +487,7 @@ private RRset expandSet(RRset set, Name tname) { * @return A SetResponse object * @see SetResponse */ - public SetResponse findRecords(Name name, int type) { + public SetResponse findRecords(Name name, int type) throws IllegalMonitorStateException { return lookup(name, type); } @@ -492,7 +499,7 @@ public SetResponse findRecords(Name name, int type) { * @return The matching RRset * @see RRset */ - public RRset findExactMatch(Name name, int type) { + public RRset findExactMatch(Name name, int type) throws IllegalMonitorStateException { Object types = exactName(name); if (types == null) { return null; @@ -556,7 +563,7 @@ public void removeRecord(Record r) throws IllegalMonitorStateException { } /** Returns an Iterator over the RRsets in the zone. */ - public Iterator iterator() { + public Iterator iterator() throws IllegalMonitorStateException { return new ZoneIterator(false); } @@ -565,11 +572,11 @@ public Iterator iterator() { * This is identical to {@link #iterator} except that the SOA is returned at the end as well as * the beginning. */ - public Iterator AXFR() { + public Iterator AXFR() throws IllegalMonitorStateException { return new ZoneIterator(true); } - private void nodeToString(StringBuffer sb, Object node) { + private void nodeToString(StringBuilder sb, Object node) throws IllegalMonitorStateException { RRset[] sets = allRRsets(node); for (RRset rrset : sets) { rrset.rrs().forEach(r -> sb.append(r).append('\n')); @@ -580,7 +587,7 @@ private void nodeToString(StringBuffer sb, Object node) { /** Returns the contents of the Zone in master file format. */ public String toMasterFile() throws IllegalMonitorStateException { readLock.lock(); - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); nodeToString(sb, originNode); for (Map.Entry entry : data.entrySet()) { if (!origin.equals(entry.getKey())) { @@ -593,7 +600,7 @@ public String toMasterFile() throws IllegalMonitorStateException { /** Returns the contents of the Zone as a string (in master file format). */ @Override - public String toString() { + public String toString() throws IllegalMonitorStateException { return toMasterFile(); } } From bbe82399811d500c6fce9b079a262f64546e5f92 Mon Sep 17 00:00:00 2001 From: Srijeet Chatterjee Date: Mon, 11 Dec 2023 13:05:05 -0700 Subject: [PATCH 4/5] moving unlocking into finally block, other cleanup --- pom.xml | 5 - src/main/java/org/xbill/DNS/Zone.java | 386 ++++++++++++---------- src/main/java11/module-info.java | 1 - src/test/java/org/xbill/DNS/ZoneTest.java | 84 ----- 4 files changed, 208 insertions(+), 268 deletions(-) diff --git a/pom.xml b/pom.xml index 44c538de..dd9fce8b 100644 --- a/pom.xml +++ b/pom.xml @@ -535,11 +535,6 @@ 2.15.0 test - - com.google.guava - guava - 32.0.0-jre - diff --git a/src/main/java/org/xbill/DNS/Zone.java b/src/main/java/org/xbill/DNS/Zone.java index ea9044d0..3ae4f2dd 100644 --- a/src/main/java/org/xbill/DNS/Zone.java +++ b/src/main/java/org/xbill/DNS/Zone.java @@ -3,7 +3,6 @@ package org.xbill.DNS; -import com.google.common.annotations.VisibleForTesting; import java.io.IOException; import java.io.Serializable; import java.util.Iterator; @@ -44,23 +43,26 @@ class ZoneIterator implements Iterator { private int count; private boolean wantLastSOA; - ZoneIterator(boolean axfr) throws IllegalMonitorStateException { + ZoneIterator(boolean axfr) { readLock.lock(); - zentries = data.entrySet().iterator(); - wantLastSOA = axfr; - RRset[] sets = allRRsets(originNode); - current = new RRset[sets.length]; - for (int i = 0, j = 2; i < sets.length; i++) { - int type = sets[i].getType(); - if (type == Type.SOA) { - current[0] = sets[i]; - } else if (type == Type.NS) { - current[1] = sets[i]; - } else { - current[j++] = sets[i]; + try { + zentries = data.entrySet().iterator(); + wantLastSOA = axfr; + RRset[] sets = allRRsets(originNode); + current = new RRset[sets.length]; + for (int i = 0, j = 2; i < sets.length; i++) { + int type = sets[i].getType(); + if (type == Type.SOA) { + current[0] = sets[i]; + } else if (type == Type.NS) { + current[1] = sets[i]; + } else { + current[j++] = sets[i]; + } } + } finally { + readLock.unlock(); } - readLock.unlock(); } @Override @@ -69,7 +71,7 @@ public boolean hasNext() { } @Override - public RRset next() throws IllegalMonitorStateException { + public RRset next() { if (!hasNext()) { throw new NoSuchElementException(); } @@ -103,12 +105,16 @@ public void remove() { } } - @VisibleForTesting + /** + * Sets the Reader Lock for this Zone instance. Only to be used for testing. + * + * @param lock The Reader Lock to set for this Zone instance. + */ void setLock(ReentrantReadWriteLock.ReadLock lock) { readLock = lock; } - private void validate() throws IOException, IllegalMonitorStateException { + private void validate() throws IOException { originNode = exactName(origin); if (originNode == null) { throw new IOException(origin + ": no data specified"); @@ -126,7 +132,7 @@ private void validate() throws IOException, IllegalMonitorStateException { } } - private void maybeAddRecord(Record record) throws IOException, IllegalMonitorStateException { + private void maybeAddRecord(Record record) throws IOException { int rtype = record.getType(); Name name = record.getName(); @@ -145,24 +151,26 @@ private void maybeAddRecord(Record record) throws IOException, IllegalMonitorSta * @param file The master file to read from. * @see Master */ - public Zone(Name zone, String file) throws IOException, IllegalMonitorStateException { + public Zone(Name zone, String file) throws IOException { writeLock.lock(); - data = new TreeMap<>(); + try { + data = new TreeMap<>(); - if (zone == null) { - writeLock.unlock(); - throw new IllegalArgumentException("no zone name specified"); - } - try (Master m = new Master(file, zone)) { - Record record; + if (zone == null) { + throw new IllegalArgumentException("no zone name specified"); + } + try (Master m = new Master(file, zone)) { + Record record; - origin = zone; - while ((record = m.nextRecord()) != null) { - maybeAddRecord(record); + origin = zone; + while ((record = m.nextRecord()) != null) { + maybeAddRecord(record); + } } + validate(); + } finally { + writeLock.unlock(); } - validate(); - writeLock.unlock(); } /** @@ -172,38 +180,42 @@ public Zone(Name zone, String file) throws IOException, IllegalMonitorStateExcep * @param records The records to add to the zone. * @see Master */ - public Zone(Name zone, Record[] records) throws IOException, IllegalMonitorStateException { + public Zone(Name zone, Record[] records) throws IOException { writeLock.lock(); - data = new TreeMap<>(); + try { + data = new TreeMap<>(); - if (zone == null) { - throw new IllegalArgumentException("no zone name specified"); - } - origin = zone; - for (Record record : records) { - maybeAddRecord(record); + if (zone == null) { + throw new IllegalArgumentException("no zone name specified"); + } + origin = zone; + for (Record record : records) { + maybeAddRecord(record); + } + validate(); + } finally { + writeLock.unlock(); } - validate(); - writeLock.unlock(); } - private void fromXFR(ZoneTransferIn xfrin) - throws IOException, ZoneTransferException, IllegalMonitorStateException { + private void fromXFR(ZoneTransferIn xfrin) throws IOException, ZoneTransferException { writeLock.lock(); - data = new TreeMap<>(); + try { + data = new TreeMap<>(); - origin = xfrin.getName(); - xfrin.run(); - if (!xfrin.isAXFR()) { - writeLock.unlock(); - throw new IllegalArgumentException("zones can only be created from AXFRs"); - } + origin = xfrin.getName(); + xfrin.run(); + if (!xfrin.isAXFR()) { + throw new IllegalArgumentException("zones can only be created from AXFRs"); + } - for (Record record : xfrin.getAXFR()) { - maybeAddRecord(record); + for (Record record : xfrin.getAXFR()) { + maybeAddRecord(record); + } + validate(); + } finally { + writeLock.unlock(); } - validate(); - writeLock.unlock(); } /** @@ -212,8 +224,7 @@ private void fromXFR(ZoneTransferIn xfrin) * @param xfrin The incoming zone transfer to execute. * @see ZoneTransferIn */ - public Zone(ZoneTransferIn xfrin) - throws IOException, ZoneTransferException, IllegalMonitorStateException { + public Zone(ZoneTransferIn xfrin) throws IOException, ZoneTransferException { fromXFR(xfrin); } @@ -222,8 +233,7 @@ public Zone(ZoneTransferIn xfrin) * * @see ZoneTransferIn */ - public Zone(Name zone, int dclass, String remote) - throws IOException, ZoneTransferException, IllegalMonitorStateException { + public Zone(Name zone, int dclass, String remote) throws IOException, ZoneTransferException { ZoneTransferIn xfrin = ZoneTransferIn.newAXFR(zone, remote, null); xfrin.setDClass(dclass); fromXFR(xfrin); @@ -249,49 +259,56 @@ public int getDClass() { return DClass.IN; } - private Object exactName(Name name) throws IllegalMonitorStateException { + private Object exactName(Name name) { readLock.lock(); - Object val = data.get(name); - readLock.unlock(); - return val; + try { + Object val = data.get(name); + return val; + } finally { + readLock.unlock(); + } } - private RRset[] allRRsets(Object types) throws IllegalMonitorStateException { + private RRset[] allRRsets(Object types) { if (types instanceof List) { readLock.lock(); - @SuppressWarnings("unchecked") - List typelist = (List) types; - readLock.unlock(); - return typelist.toArray(new RRset[0]); + try { + @SuppressWarnings("unchecked") + List typelist = (List) types; + return typelist.toArray(new RRset[0]); + } finally { + readLock.unlock(); + } } else { RRset set = (RRset) types; return new RRset[] {set}; } } - private RRset oneRRset(Object types, int type) throws IllegalMonitorStateException { + private RRset oneRRset(Object types, int type) { if (type == Type.ANY) { throw new IllegalArgumentException("oneRRset(ANY)"); } readLock.lock(); - RRset resultSet = null; - if (types instanceof List) { - @SuppressWarnings("unchecked") - List list = (List) types; - for (RRset set : list) { + try { + if (types instanceof List) { + @SuppressWarnings("unchecked") + List list = (List) types; + for (RRset set : list) { + if (set.getType() == type) { + return set; + } + } + } else { + RRset set = (RRset) types; if (set.getType() == type) { - resultSet = set; - break; + return set; } } - } else { - RRset set = (RRset) types; - if (set.getType() == type) { - resultSet = set; - } + } finally { + readLock.unlock(); } - readLock.unlock(); - return resultSet; + return null; } private RRset findRRset(Name name, int type) { @@ -302,77 +319,78 @@ private RRset findRRset(Name name, int type) { return oneRRset(types, type); } - private void addRRset(Name name, RRset rrset) throws IllegalMonitorStateException { + private void addRRset(Name name, RRset rrset) { writeLock.lock(); - if (!hasWild && name.isWild()) { - hasWild = true; - } - Object types = data.get(name); - if (types == null) { - data.put(name, rrset); - writeLock.unlock(); - return; - } - int rtype = rrset.getType(); - if (types instanceof List) { - @SuppressWarnings("unchecked") - List list = (List) types; - for (int i = 0; i < list.size(); i++) { - RRset set = list.get(i); - if (set.getType() == rtype) { - list.set(i, rrset); - writeLock.unlock(); - return; - } + try { + if (!hasWild && name.isWild()) { + hasWild = true; } - list.add(rrset); - } else { - RRset set = (RRset) types; - if (set.getType() == rtype) { + Object types = data.get(name); + if (types == null) { data.put(name, rrset); - } else { - LinkedList list = new LinkedList<>(); - list.add(set); + return; + } + int rtype = rrset.getType(); + if (types instanceof List) { + @SuppressWarnings("unchecked") + List list = (List) types; + for (int i = 0; i < list.size(); i++) { + RRset set = list.get(i); + if (set.getType() == rtype) { + list.set(i, rrset); + return; + } + } list.add(rrset); - data.put(name, list); + } else { + RRset set = (RRset) types; + if (set.getType() == rtype) { + data.put(name, rrset); + } else { + LinkedList list = new LinkedList<>(); + list.add(set); + list.add(rrset); + data.put(name, list); + } } + } finally { + writeLock.unlock(); } - writeLock.unlock(); } - private void removeRRset(Name name, int type) throws IllegalMonitorStateException { + private void removeRRset(Name name, int type) { writeLock.lock(); - Object types = data.get(name); - if (types == null) { - writeLock.unlock(); - return; - } - if (types instanceof List) { - @SuppressWarnings("unchecked") - List list = (List) types; - for (int i = 0; i < list.size(); i++) { - RRset set = list.get(i); - if (set.getType() == type) { - list.remove(i); - if (list.isEmpty()) { - data.remove(name); + try { + Object types = data.get(name); + if (types == null) { + return; + } + if (types instanceof List) { + @SuppressWarnings("unchecked") + List list = (List) types; + for (int i = 0; i < list.size(); i++) { + RRset set = list.get(i); + if (set.getType() == type) { + list.remove(i); + if (list.isEmpty()) { + data.remove(name); + } + return; } - writeLock.unlock(); + } + } else { + RRset set = (RRset) types; + if (set.getType() != type) { return; } + data.remove(name); } - } else { - RRset set = (RRset) types; - if (set.getType() != type) { - writeLock.unlock(); - return; - } - data.remove(name); + } finally { + writeLock.unlock(); } - writeLock.unlock(); } - private SetResponse lookup(Name name, int type) throws IllegalMonitorStateException { + private SetResponse lookup(Name name, int type) { if (!name.subdomain(origin)) { return SetResponse.ofType(SetResponse.NXDOMAIN); } @@ -487,7 +505,7 @@ private RRset expandSet(RRset set, Name tname) { * @return A SetResponse object * @see SetResponse */ - public SetResponse findRecords(Name name, int type) throws IllegalMonitorStateException { + public SetResponse findRecords(Name name, int type) { return lookup(name, type); } @@ -499,7 +517,7 @@ public SetResponse findRecords(Name name, int type) throws IllegalMonitorStateEx * @return The matching RRset * @see RRset */ - public RRset findExactMatch(Name name, int type) throws IllegalMonitorStateException { + public RRset findExactMatch(Name name, int type) { Object types = exactName(name); if (types == null) { return null; @@ -513,11 +531,14 @@ public RRset findExactMatch(Name name, int type) throws IllegalMonitorStateExcep * @param rrset The RRset to be added * @see RRset */ - public void addRRset(RRset rrset) throws IllegalMonitorStateException { + public void addRRset(RRset rrset) { writeLock.lock(); - Name name = rrset.getName(); - addRRset(name, rrset); - writeLock.unlock(); + try { + Name name = rrset.getName(); + addRRset(name, rrset); + } finally { + writeLock.unlock(); + } } /** @@ -526,18 +547,21 @@ public void addRRset(RRset rrset) throws IllegalMonitorStateException { * @param r The record to be added * @see Record */ - public void addRecord(T r) throws IllegalMonitorStateException { + public void addRecord(T r) { writeLock.lock(); - Name name = r.getName(); - int rtype = r.getRRsetType(); - RRset rrset = findRRset(name, rtype); - if (rrset == null) { - rrset = new RRset(r); - addRRset(name, rrset); - } else { - rrset.addRR(r); + try { + Name name = r.getName(); + int rtype = r.getRRsetType(); + RRset rrset = findRRset(name, rtype); + if (rrset == null) { + rrset = new RRset(r); + addRRset(name, rrset); + } else { + rrset.addRR(r); + } + } finally { + writeLock.unlock(); } - writeLock.unlock(); } /** @@ -546,24 +570,27 @@ public void addRecord(T r) throws IllegalMonitorStateExceptio * @param r The record to be removed * @see Record */ - public void removeRecord(Record r) throws IllegalMonitorStateException { + public void removeRecord(Record r) { writeLock.lock(); - Name name = r.getName(); - int rtype = r.getRRsetType(); - RRset rrset = findRRset(name, rtype); - if (rrset == null) { - return; - } - if (rrset.size() == 1 && rrset.first().equals(r)) { - removeRRset(name, rtype); - } else { - rrset.deleteRR(r); + try { + Name name = r.getName(); + int rtype = r.getRRsetType(); + RRset rrset = findRRset(name, rtype); + if (rrset == null) { + return; + } + if (rrset.size() == 1 && rrset.first().equals(r)) { + removeRRset(name, rtype); + } else { + rrset.deleteRR(r); + } + } finally { + writeLock.unlock(); } - writeLock.unlock(); } /** Returns an Iterator over the RRsets in the zone. */ - public Iterator iterator() throws IllegalMonitorStateException { + public Iterator iterator() { return new ZoneIterator(false); } @@ -572,11 +599,11 @@ public Iterator iterator() throws IllegalMonitorStateException { * This is identical to {@link #iterator} except that the SOA is returned at the end as well as * the beginning. */ - public Iterator AXFR() throws IllegalMonitorStateException { + public Iterator AXFR() { return new ZoneIterator(true); } - private void nodeToString(StringBuilder sb, Object node) throws IllegalMonitorStateException { + private void nodeToString(StringBuilder sb, Object node) { RRset[] sets = allRRsets(node); for (RRset rrset : sets) { rrset.rrs().forEach(r -> sb.append(r).append('\n')); @@ -585,22 +612,25 @@ private void nodeToString(StringBuilder sb, Object node) throws IllegalMonitorSt } /** Returns the contents of the Zone in master file format. */ - public String toMasterFile() throws IllegalMonitorStateException { + public String toMasterFile() { readLock.lock(); - StringBuilder sb = new StringBuilder(); - nodeToString(sb, originNode); - for (Map.Entry entry : data.entrySet()) { - if (!origin.equals(entry.getKey())) { - nodeToString(sb, entry.getValue()); + try { + StringBuilder sb = new StringBuilder(); + nodeToString(sb, originNode); + for (Map.Entry entry : data.entrySet()) { + if (!origin.equals(entry.getKey())) { + nodeToString(sb, entry.getValue()); + } } + return sb.toString(); + } finally { + readLock.unlock(); } - readLock.unlock(); - return sb.toString(); } /** Returns the contents of the Zone as a string (in master file format). */ @Override - public String toString() throws IllegalMonitorStateException { + public String toString() { return toMasterFile(); } } diff --git a/src/main/java11/module-info.java b/src/main/java11/module-info.java index 247aca7a..8ed16887 100644 --- a/src/main/java11/module-info.java +++ b/src/main/java11/module-info.java @@ -7,7 +7,6 @@ requires static com.sun.jna.platform; requires static java.net.http; requires org.slf4j; - requires com.google.common; exports org.xbill.DNS; exports org.xbill.DNS.config; diff --git a/src/test/java/org/xbill/DNS/ZoneTest.java b/src/test/java/org/xbill/DNS/ZoneTest.java index 89b16288..f3301570 100644 --- a/src/test/java/org/xbill/DNS/ZoneTest.java +++ b/src/test/java/org/xbill/DNS/ZoneTest.java @@ -126,90 +126,6 @@ void testReadLocksAreAcquiredAndReleasedCorrectNumberOfTimes() { verify(readLock, times(5)).unlock(); } - @Test - void testReadsWaitForWrites() throws Exception { - final AAAARecord AAAA_1_TEST_RECORD; - final AAAARecord AAAA_2_TEST_RECORD; - final ARecord A_WILD_RECORD; - final TXTRecord TXT_WILD_RECORD; - - Name testNameZone = new Name("example."); - InetAddress localhost4 = InetAddress.getByName("127.0.0.1"); - InetAddress localhost6a = InetAddress.getByName("::1"); - InetAddress localhost6b = InetAddress.getByName("::2"); - AAAA_1_TEST_RECORD = - new AAAARecord(new Name("test", testNameZone), DClass.IN, 3600, localhost6a); - AAAA_2_TEST_RECORD = - new AAAARecord(new Name("test", testNameZone), DClass.IN, 3600, localhost6b); - A_WILD_RECORD = new ARecord(new Name("*", testNameZone), DClass.IN, 3600, localhost4); - TXT_WILD_RECORD = new TXTRecord(new Name("*", testNameZone), DClass.IN, 3600, "sometext"); - - Record[] zoneRecordElements = new Record[100]; - zoneRecordElements[0] = - new SOARecord( - testNameZone, - DClass.IN, - 3600L, - Name.fromConstantString("nameserver."), - new Name("hostmaster", testNameZone), - 1, - 21600L, - 7200L, - 2160000L, - 3600L); - - zoneRecordElements[1] = - new NSRecord(testNameZone, DClass.IN, 300L, Name.fromConstantString("nameserver.")); - zoneRecordElements[96] = AAAA_1_TEST_RECORD; - zoneRecordElements[97] = AAAA_2_TEST_RECORD; - zoneRecordElements[98] = A_WILD_RECORD; - zoneRecordElements[99] = TXT_WILD_RECORD; - - int start = 1; - for (int i = 2; i <= 95; i++) { - zoneRecordElements[i] = - new ARecord( - new Name("test", testNameZone), - DClass.IN, - 3600, - InetAddress.getByName("127.0.0." + start)); - start++; - } - - Thread t1 = - new Thread( - new Runnable() { - @Override - public void run() { - try { - Thread.sleep(1000); - zone = new Zone(testNameZone, zoneRecordElements); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - - Thread t2 = - new Thread( - new Runnable() { - @Override - public void run() { - Name testName = Name.fromConstantString("test.example."); - SetResponse resp = zone.findRecords(testName, Type.ANY); - answers = resp.answers().get(0).size(); - } - }); - - t1.start(); - Thread.sleep(2000); - t2.start(); - - t1.join(); - t2.join(); - assertEquals(94, answers); - } - private static List listOf(RRset... rrsets) { return Stream.of(rrsets).collect(Collectors.toList()); } From a96aba234d780a01afc8442e9e7218034203f4c2 Mon Sep 17 00:00:00 2001 From: Srijeet Chatterjee Date: Mon, 11 Dec 2023 13:06:22 -0700 Subject: [PATCH 5/5] remove unused variables --- src/test/java/org/xbill/DNS/ZoneTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/org/xbill/DNS/ZoneTest.java b/src/test/java/org/xbill/DNS/ZoneTest.java index f3301570..89211493 100644 --- a/src/test/java/org/xbill/DNS/ZoneTest.java +++ b/src/test/java/org/xbill/DNS/ZoneTest.java @@ -17,8 +17,6 @@ import org.junit.jupiter.api.Test; class ZoneTest { - int answers = 0; - Zone zone = null; private static final ARecord A_TEST; private static final AAAARecord AAAA_1_TEST; private static final AAAARecord AAAA_2_TEST;