8000 Replace synchronization in Zone with locks by srijeet0406 · Pull Request #306 · dnsjava/dnsjava · GitHub
[go: up one dir, main page]

Skip to content

Replace synchronization in Zone with locks #306

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
8000 Loading
Diff view
Diff view
214 changes: 129 additions & 85 deletions src/main/java/org/xbill/DNS/Zone.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 */
Expand All @@ -41,21 +45,24 @@ class ZoneIterator implements Iterator<RRset> {
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();
}
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -231,51 +254,66 @@ 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<RRset> typelist = (List<RRset>) types;
return typelist.toArray(new RRset[0]);
try {
readLock.lock();
@SuppressWarnings("unchecked")
List<RRset> typelist = (List<RRset>) 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<RRset> list = (List<RRset>) 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<RRset> list = (List<RRset>) 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;
}
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;
}
Expand Down Expand Up @@ -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<RRset> list = (List<RRset>) 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<RRset> list = (List<RRset>) 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);
}
Expand Down Expand Up @@ -491,14 +534,12 @@ public void addRRset(RRset rrset) {
public <T extends Record> 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);
}
}

Expand All @@ -511,16 +552,14 @@ public <T extends Record> 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);
}
}

Expand All @@ -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<Name, Object> 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<Name, Object> 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). */
Expand Down
Loading
0