Skip to content
Snippets Groups Projects
Commit 13d35229 authored by akwizgran's avatar akwizgran
Browse files

Merge branch '1091-reduce-polling-queries' into 'master'

Reduce number of DB queries used when polling for connections

Closes #1091

See merge request !604
parents f0137b41 91d0f89f
No related branches found
No related tags found
No related merge requests found
Showing
with 127 additions and 76 deletions
...@@ -363,8 +363,7 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener { ...@@ -363,8 +363,7 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
@Override @Override
public DuplexTransportConnection createConnection(ContactId c) { public DuplexTransportConnection createConnection(ContactId c) {
if (!isRunning()) return null; if (!isRunning()) return null;
TransportProperties p = callback.getRemoteProperties().get(c); TransportProperties p = callback.getRemoteProperties(c);
if (p == null) return null;
String address = p.get(PROP_ADDRESS); String address = p.get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) return null; if (StringUtils.isNullOrEmpty(address)) return null;
String uuid = p.get(PROP_UUID); String uuid = p.get(PROP_UUID);
......
...@@ -55,6 +55,7 @@ import java.util.Collection; ...@@ -55,6 +55,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner; import java.util.Scanner;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
...@@ -538,16 +539,21 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { ...@@ -538,16 +539,21 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
public void poll(Collection<ContactId> connected) { public void poll(Collection<ContactId> connected) {
if (!isRunning()) return; if (!isRunning()) return;
backoff.increment(); backoff.increment();
// TODO: Pass properties to connectAndCallBack() Map<ContactId, TransportProperties> remote =
for (ContactId c : callback.getRemoteProperties().keySet()) callback.getRemoteProperties();
if (!connected.contains(c)) connectAndCallBack(c); for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
ContactId c = e.getKey();
if (!connected.contains(c)) connectAndCallBack(c, e.getValue());
}
} }
private void connectAndCallBack(final ContactId c) { private void connectAndCallBack(final ContactId c,
final TransportProperties p) {
ioExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
DuplexTransportConnection d = createConnection(c); if (!isRunning()) return;
DuplexTransportConnection d = createConnection(p);
if (d != null) { if (d != null) {
backoff.reset(); backoff.reset();
callback.outgoingConnectionCreated(c, d); callback.outgoingConnectionCreated(c, d);
...@@ -559,8 +565,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { ...@@ -559,8 +565,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override @Override
public DuplexTransportConnection createConnection(ContactId c) { public DuplexTransportConnection createConnection(ContactId c) {
if (!isRunning()) return null; if (!isRunning()) return null;
TransportProperties p = callback.getRemoteProperties().get(c); return createConnection(callback.getRemoteProperties(c));
if (p == null) return null; }
@Nullable
private DuplexTransportConnection createConnection(TransportProperties p) {
String onion = p.get(PROP_ONION); String onion = p.get(PROP_ONION);
if (StringUtils.isNullOrEmpty(onion)) return null; if (StringUtils.isNullOrEmpty(onion)) return null;
if (!ONION.matcher(onion).matches()) { if (!ONION.matcher(onion).matches()) {
......
...@@ -29,6 +29,11 @@ public interface PluginCallback { ...@@ -29,6 +29,11 @@ public interface PluginCallback {
*/ */
Map<ContactId, TransportProperties> getRemoteProperties(); Map<ContactId, TransportProperties> getRemoteProperties();
/**
* Returns the plugin's remote transport properties for the given contact.
*/
TransportProperties getRemoteProperties(ContactId c);
/** /**
* Merges the given settings with the namespaced settings * Merges the given settings with the namespaced settings
*/ */
......
...@@ -49,6 +49,13 @@ public interface TransportPropertyManager { ...@@ -49,6 +49,13 @@ public interface TransportPropertyManager {
Map<ContactId, TransportProperties> getRemoteProperties(TransportId t) Map<ContactId, TransportProperties> getRemoteProperties(TransportId t)
throws DbException; throws DbException;
/**
* Returns the remote transport properties for the given contact and
* transport.
*/
TransportProperties getRemoteProperties(ContactId c, TransportId t)
throws DbException;
/** /**
* Merges the given properties with the existing local properties for the * Merges the given properties with the existing local properties for the
* given transport. * given transport.
......
...@@ -283,6 +283,16 @@ class PluginManagerImpl implements PluginManager, Service { ...@@ -283,6 +283,16 @@ class PluginManagerImpl implements PluginManager, Service {
} }
} }
@Override
public TransportProperties getRemoteProperties(ContactId c) {
try {
return transportPropertyManager.getRemoteProperties(c, id);
} catch (DbException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return new TransportProperties();
}
}
@Override @Override
public void mergeSettings(Settings s) { public void mergeSettings(Settings s) {
try { try {
......
package org.briarproject.bramble.plugin.tcp; package org.briarproject.bramble.plugin.tcp;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection; import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener; import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
...@@ -126,9 +125,8 @@ class LanTcpPlugin extends TcpPlugin { ...@@ -126,9 +125,8 @@ class LanTcpPlugin extends TcpPlugin {
} }
@Override @Override
protected List<InetSocketAddress> getRemoteSocketAddresses(ContactId c) { protected List<InetSocketAddress> getRemoteSocketAddresses(
TransportProperties p = callback.getRemoteProperties().get(c); TransportProperties p) {
if (p == null) return Collections.emptyList();
return parseSocketAddresses(p.get(PROP_IP_PORTS)); return parseSocketAddresses(p.get(PROP_IP_PORTS));
} }
......
...@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.plugin.Backoff; ...@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection; import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import java.io.IOException; import java.io.IOException;
...@@ -24,6 +25,8 @@ import java.util.ArrayList; ...@@ -24,6 +25,8 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger; import java.util.logging.Logger;
...@@ -66,11 +69,11 @@ abstract class TcpPlugin implements DuplexPlugin { ...@@ -66,11 +69,11 @@ abstract class TcpPlugin implements DuplexPlugin {
protected abstract void setLocalSocketAddress(InetSocketAddress a); protected abstract void setLocalSocketAddress(InetSocketAddress a);
/** /**
* Returns zero or more socket addresses for connecting to the given * Returns zero or more socket addresses for connecting to a contact with
* contact. * the given transport properties.
*/ */
protected abstract List<InetSocketAddress> getRemoteSocketAddresses( protected abstract List<InetSocketAddress> getRemoteSocketAddresses(
ContactId c); TransportProperties p);
/** /**
* Returns true if connections to the given address can be attempted. * Returns true if connections to the given address can be attempted.
...@@ -207,16 +210,21 @@ abstract class TcpPlugin implements DuplexPlugin { ...@@ -207,16 +210,21 @@ abstract class TcpPlugin implements DuplexPlugin {
public void poll(Collection<ContactId> connected) { public void poll(Collection<ContactId> connected) {
if (!isRunning()) return; if (!isRunning()) return;
backoff.increment(); backoff.increment();
// TODO: Pass properties to connectAndCallBack() Map<ContactId, TransportProperties> remote =
for (ContactId c : callback.getRemoteProperties().keySet()) callback.getRemoteProperties();
if (!connected.contains(c)) connectAndCallBack(c); for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
ContactId c = e.getKey();
if (!connected.contains(c)) connectAndCallBack(c, e.getValue());
}
} }
private void connectAndCallBack(final ContactId c) { private void connectAndCallBack(final ContactId c,
final TransportProperties p) {
ioExecutor.execute(new Runnable() { ioExecutor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
DuplexTransportConnection d = createConnection(c); if (!isRunning()) return;
DuplexTransportConnection d = createConnection(p);
if (d != null) { if (d != null) {
backoff.reset(); backoff.reset();
callback.outgoingConnectionCreated(c, d); callback.outgoingConnectionCreated(c, d);
...@@ -228,7 +236,12 @@ abstract class TcpPlugin implements DuplexPlugin { ...@@ -228,7 +236,12 @@ abstract class TcpPlugin implements DuplexPlugin {
@Override @Override
public DuplexTransportConnection createConnection(ContactId c) { public DuplexTransportConnection createConnection(ContactId c) {
if (!isRunning()) return null; if (!isRunning()) return null;
for (InetSocketAddress remote : getRemoteSocketAddresses(c)) { return createConnection(callback.getRemoteProperties(c));
}
@Nullable
private DuplexTransportConnection createConnection(TransportProperties p) {
for (InetSocketAddress remote : getRemoteSocketAddresses(p)) {
if (!isConnectable(remote)) { if (!isConnectable(remote)) {
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(INFO)) {
SocketAddress local = socket.getLocalSocketAddress(); SocketAddress local = socket.getLocalSocketAddress();
......
package org.briarproject.bramble.plugin.tcp; package org.briarproject.bramble.plugin.tcp;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff; import org.briarproject.bramble.api.plugin.Backoff;
...@@ -78,9 +77,8 @@ class WanTcpPlugin extends TcpPlugin { ...@@ -78,9 +77,8 @@ class WanTcpPlugin extends TcpPlugin {
} }
@Override @Override
protected List<InetSocketAddress> getRemoteSocketAddresses(ContactId c) { protected List<InetSocketAddress> getRemoteSocketAddresses(
TransportProperties p = callback.getRemoteProperties().get(c); TransportProperties p) {
if (p == null) return Collections.emptyList();
InetSocketAddress parsed = parseSocketAddress(p.get(PROP_IP_PORT)); InetSocketAddress parsed = parseSocketAddress(p.get(PROP_IP_PORT));
if (parsed == null) return Collections.emptyList(); if (parsed == null) return Collections.emptyList();
return Collections.singletonList(parsed); return Collections.singletonList(parsed);
......
...@@ -160,35 +160,52 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, ...@@ -160,35 +160,52 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Override @Override
public Map<ContactId, TransportProperties> getRemoteProperties( public Map<ContactId, TransportProperties> getRemoteProperties(
TransportId t) throws DbException { TransportId t) throws DbException {
Map<ContactId, TransportProperties> remote =
new HashMap<ContactId, TransportProperties>();
Transaction txn = db.startTransaction(true);
try { try {
Map<ContactId, TransportProperties> remote = for (Contact c : db.getContacts(txn))
new HashMap<ContactId, TransportProperties>(); remote.put(c.getId(), getRemoteProperties(txn, c, t));
Transaction txn = db.startTransaction(true); db.commitTransaction(txn);
try { } finally {
for (Contact c : db.getContacts(txn)) { db.endTransaction(txn);
// Don't return properties for inactive contacts }
if (!c.isActive()) continue; return remote;
Group g = getContactGroup(c); }
// Find the latest remote update
LatestUpdate latest = findLatest(txn, g.getId(), t, false); private TransportProperties getRemoteProperties(Transaction txn, Contact c,
if (latest != null) { TransportId t) throws DbException {
// Retrieve and parse the latest remote properties // Don't return properties for inactive contacts
BdfList message = clientHelper.getMessageAsList(txn, if (!c.isActive()) return new TransportProperties();
latest.messageId); Group g = getContactGroup(c);
if (message == null) throw new DbException(); try {
remote.put(c.getId(), parseProperties(message)); // Find the latest remote update
} LatestUpdate latest = findLatest(txn, g.getId(), t, false);
} if (latest == null) return new TransportProperties();
db.commitTransaction(txn); // Retrieve and parse the latest remote properties
} finally { BdfList message =
db.endTransaction(txn); clientHelper.getMessageAsList(txn, latest.messageId);
} if (message == null) throw new DbException();
return remote; return parseProperties(message);
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
} }
} }
@Override
public TransportProperties getRemoteProperties(ContactId c, TransportId t)
throws DbException {
TransportProperties p;
Transaction txn = db.startTransaction(true);
try {
p = getRemoteProperties(txn, db.getContact(txn, c), t);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return p;
}
@Override @Override
public void mergeLocalProperties(TransportId t, TransportProperties p) public void mergeLocalProperties(TransportId t, TransportProperties p)
throws DbException { throws DbException {
......
...@@ -311,6 +311,11 @@ public class LanTcpPluginTest extends BrambleTestCase { ...@@ -311,6 +311,11 @@ public class LanTcpPluginTest extends BrambleTestCase {
return remote; return remote;
} }
@Override
public TransportProperties getRemoteProperties(ContactId c) {
return remote.get(c);
}
@Override @Override
public void mergeSettings(Settings s) { public void mergeSettings(Settings s) {
} }
......
...@@ -249,8 +249,7 @@ class BluetoothPlugin implements DuplexPlugin { ...@@ -249,8 +249,7 @@ class BluetoothPlugin implements DuplexPlugin {
@Override @Override
public DuplexTransportConnection createConnection(ContactId c) { public DuplexTransportConnection createConnection(ContactId c) {
if (!running) return null; if (!running) return null;
TransportProperties p = callback.getRemoteProperties().get(c); TransportProperties p = callback.getRemoteProperties(c);
if (p == null) return null;
String address = p.get(PROP_ADDRESS); String address = p.get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) return null; if (StringUtils.isNullOrEmpty(address)) return null;
String uuid = p.get(PROP_UUID); String uuid = p.get(PROP_UUID);
......
...@@ -145,8 +145,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback { ...@@ -145,8 +145,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
String fromIso = callback.getLocalProperties().get("iso3166"); String fromIso = callback.getLocalProperties().get("iso3166");
if (StringUtils.isNullOrEmpty(fromIso)) return null; if (StringUtils.isNullOrEmpty(fromIso)) return null;
// Get the ISO 3166 code for the callee's country // Get the ISO 3166 code for the callee's country
TransportProperties properties = callback.getRemoteProperties().get(c); TransportProperties properties = callback.getRemoteProperties(c);
if (properties == null) return null;
String toIso = properties.get("iso3166"); String toIso = properties.get("iso3166");
if (StringUtils.isNullOrEmpty(toIso)) return null; if (StringUtils.isNullOrEmpty(toIso)) return null;
// Get the callee's phone number // Get the callee's phone number
......
...@@ -9,8 +9,6 @@ import org.jmock.Mockery; ...@@ -9,8 +9,6 @@ import org.jmock.Mockery;
import org.junit.Test; import org.junit.Test;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
...@@ -65,12 +63,10 @@ public class ModemPluginTest extends BrambleTestCase { ...@@ -65,12 +63,10 @@ public class ModemPluginTest extends BrambleTestCase {
final Modem modem = context.mock(Modem.class); final Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties(); final TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336); local.put("iso3166", ISO_1336);
TransportProperties p = new TransportProperties(); final TransportProperties remote = new TransportProperties();
p.put("iso3166", ISO_1336); remote.put("iso3166", ISO_1336);
p.put("number", NUMBER); remote.put("number", NUMBER);
ContactId contactId = new ContactId(234); final ContactId contactId = new ContactId(234);
final Map<ContactId, TransportProperties> remote =
Collections.singletonMap(contactId, p);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// start() // start()
oneOf(serialPortList).getPortNames(); oneOf(serialPortList).getPortNames();
...@@ -82,7 +78,7 @@ public class ModemPluginTest extends BrambleTestCase { ...@@ -82,7 +78,7 @@ public class ModemPluginTest extends BrambleTestCase {
// createConnection() // createConnection()
oneOf(callback).getLocalProperties(); oneOf(callback).getLocalProperties();
will(returnValue(local)); will(returnValue(local));
oneOf(callback).getRemoteProperties(); oneOf(callback).getRemoteProperties(contactId);
will(returnValue(remote)); will(returnValue(remote));
oneOf(modem).dial(NUMBER); oneOf(modem).dial(NUMBER);
will(returnValue(true)); will(returnValue(true));
...@@ -106,12 +102,10 @@ public class ModemPluginTest extends BrambleTestCase { ...@@ -106,12 +102,10 @@ public class ModemPluginTest extends BrambleTestCase {
final Modem modem = context.mock(Modem.class); final Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties(); final TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336); local.put("iso3166", ISO_1336);
TransportProperties p = new TransportProperties(); final TransportProperties remote = new TransportProperties();
p.put("iso3166", ISO_1336); remote.put("iso3166", ISO_1336);
p.put("number", NUMBER); remote.put("number", NUMBER);
ContactId contactId = new ContactId(234); final ContactId contactId = new ContactId(234);
final Map<ContactId, TransportProperties> remote =
Collections.singletonMap(contactId, p);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// start() // start()
oneOf(serialPortList).getPortNames(); oneOf(serialPortList).getPortNames();
...@@ -123,7 +117,7 @@ public class ModemPluginTest extends BrambleTestCase { ...@@ -123,7 +117,7 @@ public class ModemPluginTest extends BrambleTestCase {
// createConnection() // createConnection()
oneOf(callback).getLocalProperties(); oneOf(callback).getLocalProperties();
will(returnValue(local)); will(returnValue(local));
oneOf(callback).getRemoteProperties(); oneOf(callback).getRemoteProperties(contactId);
will(returnValue(remote)); will(returnValue(remote));
oneOf(modem).dial(NUMBER); oneOf(modem).dial(NUMBER);
will(returnValue(false)); will(returnValue(false));
...@@ -147,12 +141,10 @@ public class ModemPluginTest extends BrambleTestCase { ...@@ -147,12 +141,10 @@ public class ModemPluginTest extends BrambleTestCase {
final Modem modem = context.mock(Modem.class); final Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties(); final TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336); local.put("iso3166", ISO_1336);
TransportProperties p = new TransportProperties(); final TransportProperties remote = new TransportProperties();
p.put("iso3166", ISO_1336); remote.put("iso3166", ISO_1336);
p.put("number", NUMBER); remote.put("number", NUMBER);
ContactId contactId = new ContactId(234); final ContactId contactId = new ContactId(234);
final Map<ContactId, TransportProperties> remote =
Collections.singletonMap(contactId, p);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// start() // start()
oneOf(serialPortList).getPortNames(); oneOf(serialPortList).getPortNames();
...@@ -164,7 +156,7 @@ public class ModemPluginTest extends BrambleTestCase { ...@@ -164,7 +156,7 @@ public class ModemPluginTest extends BrambleTestCase {
// createConnection() // createConnection()
oneOf(callback).getLocalProperties(); oneOf(callback).getLocalProperties();
will(returnValue(local)); will(returnValue(local));
oneOf(callback).getRemoteProperties(); oneOf(callback).getRemoteProperties(contactId);
will(returnValue(remote)); will(returnValue(remote));
oneOf(modem).dial(NUMBER); oneOf(modem).dial(NUMBER);
will(throwException(new IOException())); will(throwException(new IOException()));
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment