Skip to content
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

Add read timeout #89

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/com/serotonin/bacnet4j/ServiceFuture.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,6 @@

public interface ServiceFuture {
<T extends AcknowledgementService> T get() throws BACnetException;

<T extends AcknowledgementService> T get(long timeout) throws BACnetException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,35 @@ public class ServiceFutureImpl implements ServiceFuture, ResponseConsumer {
private volatile boolean done;

@Override
public synchronized <T extends AcknowledgementService> T get() throws BACnetException {
public <T extends AcknowledgementService> T get() throws BACnetException {
return get(this, 0);
}

@Override
public <T extends AcknowledgementService> T get(long timeout) throws BACnetException {
return get(this, timeout);
}

private synchronized <T extends AcknowledgementService> T get(Object monitor, long timeout) throws BACnetException {
if (done) {
return result();
}

ThreadUtils.wait(this);
if (timeout <= 0) {
ThreadUtils.wait(monitor);
} else {
ThreadUtils.wait(monitor, timeout);
}

return result();
}

@SuppressWarnings("unchecked")
private <T extends AcknowledgementService> T result() throws BACnetException {
if (!done) {
throw new BACnetTimeoutException("waiting timeout");
}

if (ex != null) {
// We want to preserve the original type of the exception, but not have
// to have a big if/then/else chain to handle all of the exception types.
Expand Down
30 changes: 20 additions & 10 deletions src/main/java/com/serotonin/bacnet4j/util/RequestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,12 @@ private static Map<PropertyIdentifier, Encodable> getProperties(final LocalDevic

public static Encodable sendReadPropertyAllowNull(final LocalDevice localDevice, final RemoteDevice d,
final ObjectIdentifier oid, final PropertyIdentifier pid) throws BACnetException {
return sendReadPropertyAllowNull(localDevice, d, oid, pid, null, null);
return sendReadPropertyAllowNull(localDevice, d, oid, pid, null, null, 0);
}

public static Encodable sendReadPropertyAllowNull(final LocalDevice localDevice, final RemoteDevice d,
final ObjectIdentifier oid, final PropertyIdentifier pid, long timeout) throws BACnetException {
return sendReadPropertyAllowNull(localDevice, d, oid, pid, null, null, timeout);
}

public static SequenceOf<ObjectIdentifier> getObjectList(final LocalDevice localDevice, final RemoteDevice d)
Expand All @@ -160,7 +165,7 @@ public static SequenceOf<ObjectIdentifier> getObjectList(final LocalDevice local
public static SequenceOf<ObjectIdentifier> getObjectList(final LocalDevice localDevice, final RemoteDevice d,
final ReadListener callback) throws BACnetException {
return (SequenceOf<ObjectIdentifier>) sendReadPropertyAllowNull(localDevice, d, d.getObjectIdentifier(),
PropertyIdentifier.objectList, null, callback);
PropertyIdentifier.objectList, null, callback, 0);
}

/**
Expand All @@ -169,10 +174,10 @@ public static SequenceOf<ObjectIdentifier> getObjectList(final LocalDevice local
*/
public static Encodable sendReadPropertyAllowNull(final LocalDevice localDevice, final RemoteDevice d,
final ObjectIdentifier oid, final PropertyIdentifier pid, final UnsignedInteger propertyArrayIndex,
final ReadListener callback) throws BACnetException {
final ReadListener callback, long timeout) throws BACnetException {
try {
final ReadPropertyAck ack = (ReadPropertyAck) localDevice
.send(d, new ReadPropertyRequest(oid, pid, propertyArrayIndex)).get();
.send(d, new ReadPropertyRequest(oid, pid, propertyArrayIndex)).get(timeout);
if (callback != null)
callback.progress(1, d.getInstanceNumber(), oid, pid, ack.getPropertyArrayIndex(), ack.getValue());
return ack.getValue();
Expand All @@ -186,7 +191,7 @@ public static Encodable sendReadPropertyAllowNull(final LocalDevice localDevice,

// ... then try getting it by sending requests for indices. Find out how many there are.
final int len = ((UnsignedInteger) sendReadPropertyAllowNull(localDevice, d, oid, pid,
UnsignedInteger.ZERO, null)).intValue();
UnsignedInteger.ZERO, null, timeout)).intValue();

// Create a list of individual property references.
final PropertyReferences refs = new PropertyReferences();
Expand Down Expand Up @@ -265,7 +270,12 @@ public static List<Pair<ObjectPropertyReference, Encodable>> readProperties(fina
}

public static PropertyValues readProperties(final LocalDevice localDevice, final RemoteDevice d,
final PropertyReferences refs, boolean allowNull, final ReadListener callback) throws BACnetException {
final PropertyReferences refs, boolean allowNull, final ReadListener callback) throws BACnetException {
return readProperties(localDevice, d, refs, allowNull, callback, 0);
}

public static PropertyValues readProperties(final LocalDevice localDevice, final RemoteDevice d,
final PropertyReferences refs, boolean allowNull, final ReadListener callback, long timeout) throws BACnetException {
Map<ObjectIdentifier, List<PropertyReference>> properties;
final PropertyValues propertyValues = new PropertyValues();
final ReadListenerUpdater updater = new ReadListenerUpdater(callback, propertyValues, refs.size());
Expand Down Expand Up @@ -381,7 +391,7 @@ public static PropertyValues readProperties(final LocalDevice localDevice, final
}else
populateWithError(d, properties, updater, e.getError());
}else {
sendOneAtATime(localDevice, d, partition, allowNull, updater);
sendOneAtATime(localDevice, d, partition, allowNull, updater, timeout);
}
partitions.remove(0);
} catch (final BACnetException e) {
Expand All @@ -393,7 +403,7 @@ public static PropertyValues readProperties(final LocalDevice localDevice, final
}
} else {
// If it doesn't support read property multiple, send them one at a time.
sendOneAtATime(localDevice, d, refs, allowNull, updater);
sendOneAtATime(localDevice, d, refs, allowNull, updater, timeout);
}

return propertyValues;
Expand All @@ -410,7 +420,7 @@ public static void populateWithError(final RemoteDevice d,
}

private static void sendOneAtATime(final LocalDevice localDevice, final RemoteDevice d,
final PropertyReferences refs, boolean allowNull, final ReadListenerUpdater updater) throws BACnetException {
final PropertyReferences refs, boolean allowNull, final ReadListenerUpdater updater, long timeout) throws BACnetException {
LOG.debug("Making property reference requests one at a time");
List<PropertyReference> refList;
ReadPropertyRequest request;
Expand Down Expand Up @@ -445,7 +455,7 @@ private static void sendOneAtATime(final LocalDevice localDevice, final RemoteDe

// ... then try getting it by sending requests for indices. Find out how many there are.
final int len = ((UnsignedInteger) sendReadPropertyAllowNull(localDevice, d, oid, ref.getPropertyIdentifier(),
UnsignedInteger.ZERO, null)).intValue();
UnsignedInteger.ZERO, null, timeout)).intValue();

// Create a list of individual property references.
final PropertyReferences newRefs = new PropertyReferences();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ public ServiceFuture answer(final InvocationOnMock invocation) throws Throwable
public <T extends AcknowledgementService> T get() throws BACnetException {
return (T) ack;
}

@Override
public <T extends AcknowledgementService> T get(long timeout) throws BACnetException {
return (T) ack;
}
};
}

Expand Down