Reduce DB queries for looking up transport properties.

parent 6c1901fe
Pipeline #677 passed with stage
in 9 minutes and 45 seconds
......@@ -347,8 +347,7 @@ class DroidtoothPlugin implements DuplexPlugin {
@Override
public DuplexTransportConnection createConnection(ContactId c) {
if (!isRunning()) return null;
TransportProperties p = callback.getRemoteProperties().get(c);
if (p == null) return null;
TransportProperties p = callback.getRemoteProperties(c);
String address = p.get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) return null;
String uuid = p.get(PROP_UUID);
......
......@@ -55,6 +55,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
......@@ -538,16 +539,21 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
public void poll(Collection<ContactId> connected) {
if (!isRunning()) return;
backoff.increment();
// TODO: Pass properties to connectAndCallBack()
for (ContactId c : callback.getRemoteProperties().keySet())
if (!connected.contains(c)) connectAndCallBack(c);
Map<ContactId, TransportProperties> remote =
callback.getRemoteProperties();
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() {
@Override
public void run() {
DuplexTransportConnection d = createConnection(c);
if (!isRunning()) return;
DuplexTransportConnection d = createConnection(p);
if (d != null) {
backoff.reset();
callback.outgoingConnectionCreated(c, d);
......@@ -559,8 +565,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override
public DuplexTransportConnection createConnection(ContactId c) {
if (!isRunning()) return null;
TransportProperties p = callback.getRemoteProperties().get(c);
if (p == null) return null;
return createConnection(callback.getRemoteProperties(c));
}
@Nullable
private DuplexTransportConnection createConnection(TransportProperties p) {
String onion = p.get(PROP_ONION);
if (StringUtils.isNullOrEmpty(onion)) return null;
if (!ONION.matcher(onion).matches()) {
......
......@@ -29,6 +29,11 @@ public interface PluginCallback {
*/
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
*/
......
......@@ -49,6 +49,13 @@ public interface TransportPropertyManager {
Map<ContactId, TransportProperties> getRemoteProperties(TransportId t)
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
* given transport.
......
......@@ -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
public void mergeSettings(Settings s) {
try {
......
......@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
......@@ -209,8 +210,9 @@ abstract class TcpPlugin implements DuplexPlugin {
public void poll(Collection<ContactId> connected) {
if (!isRunning()) return;
backoff.increment();
for (Entry<ContactId, TransportProperties> e :
callback.getRemoteProperties().entrySet()) {
Map<ContactId, TransportProperties> remote =
callback.getRemoteProperties();
for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
ContactId c = e.getKey();
if (!connected.contains(c)) connectAndCallBack(c, e.getValue());
}
......@@ -234,8 +236,7 @@ abstract class TcpPlugin implements DuplexPlugin {
@Override
public DuplexTransportConnection createConnection(ContactId c) {
if (!isRunning()) return null;
TransportProperties p = callback.getRemoteProperties().get(c);
return p == null ? null : createConnection(p);
return createConnection(callback.getRemoteProperties(c));
}
@Nullable
......
......@@ -160,35 +160,52 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Override
public Map<ContactId, TransportProperties> getRemoteProperties(
TransportId t) throws DbException {
Map<ContactId, TransportProperties> remote =
new HashMap<ContactId, TransportProperties>();
Transaction txn = db.startTransaction(true);
try {
Map<ContactId, TransportProperties> remote =
new HashMap<ContactId, TransportProperties>();
Transaction txn = db.startTransaction(true);
try {
for (Contact c : db.getContacts(txn)) {
// Don't return properties for inactive contacts
if (!c.isActive()) continue;
Group g = getContactGroup(c);
// Find the latest remote update
LatestUpdate latest = findLatest(txn, g.getId(), t, false);
if (latest != null) {
// Retrieve and parse the latest remote properties
BdfList message = clientHelper.getMessageAsList(txn,
latest.messageId);
if (message == null) throw new DbException();
remote.put(c.getId(), parseProperties(message));
}
}
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return remote;
for (Contact c : db.getContacts(txn))
remote.put(c.getId(), getRemoteProperties(txn, c, t));
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return remote;
}
private TransportProperties getRemoteProperties(Transaction txn, Contact c,
TransportId t) throws DbException {
// Don't return properties for inactive contacts
if (!c.isActive()) return new TransportProperties();
Group g = getContactGroup(c);
try {
// Find the latest remote update
LatestUpdate latest = findLatest(txn, g.getId(), t, false);
if (latest == null) return new TransportProperties();
// Retrieve and parse the latest remote properties
BdfList message =
clientHelper.getMessageAsList(txn, latest.messageId);
if (message == null) throw new DbException();
return parseProperties(message);
} catch (FormatException 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
public void mergeLocalProperties(TransportId t, TransportProperties p)
throws DbException {
......
......@@ -311,6 +311,11 @@ public class LanTcpPluginTest extends BrambleTestCase {
return remote;
}
@Override
public TransportProperties getRemoteProperties(ContactId c) {
return remote.get(c);
}
@Override
public void mergeSettings(Settings s) {
}
......
......@@ -249,8 +249,7 @@ class BluetoothPlugin implements DuplexPlugin {
@Override
public DuplexTransportConnection createConnection(ContactId c) {
if (!running) return null;
TransportProperties p = callback.getRemoteProperties().get(c);
if (p == null) return null;
TransportProperties p = callback.getRemoteProperties(c);
String address = p.get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) return null;
String uuid = p.get(PROP_UUID);
......
......@@ -145,8 +145,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
String fromIso = callback.getLocalProperties().get("iso3166");
if (StringUtils.isNullOrEmpty(fromIso)) return null;
// Get the ISO 3166 code for the callee's country
TransportProperties properties = callback.getRemoteProperties().get(c);
if (properties == null) return null;
TransportProperties properties = callback.getRemoteProperties(c);
String toIso = properties.get("iso3166");
if (StringUtils.isNullOrEmpty(toIso)) return null;
// Get the callee's phone number
......
......@@ -9,8 +9,6 @@ import org.jmock.Mockery;
import org.junit.Test;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
......@@ -65,12 +63,10 @@ public class ModemPluginTest extends BrambleTestCase {
final Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336);
TransportProperties p = new TransportProperties();
p.put("iso3166", ISO_1336);
p.put("number", NUMBER);
ContactId contactId = new ContactId(234);
final Map<ContactId, TransportProperties> remote =
Collections.singletonMap(contactId, p);
final TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER);
final ContactId contactId = new ContactId(234);
context.checking(new Expectations() {{
// start()
oneOf(serialPortList).getPortNames();
......@@ -82,7 +78,7 @@ public class ModemPluginTest extends BrambleTestCase {
// createConnection()
oneOf(callback).getLocalProperties();
will(returnValue(local));
oneOf(callback).getRemoteProperties();
oneOf(callback).getRemoteProperties(contactId);
will(returnValue(remote));
oneOf(modem).dial(NUMBER);
will(returnValue(true));
......@@ -106,12 +102,10 @@ public class ModemPluginTest extends BrambleTestCase {
final Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336);
TransportProperties p = new TransportProperties();
p.put("iso3166", ISO_1336);
p.put("number", NUMBER);
ContactId contactId = new ContactId(234);
final Map<ContactId, TransportProperties> remote =
Collections.singletonMap(contactId, p);
final TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER);
final ContactId contactId = new ContactId(234);
context.checking(new Expectations() {{
// start()
oneOf(serialPortList).getPortNames();
......@@ -123,7 +117,7 @@ public class ModemPluginTest extends BrambleTestCase {
// createConnection()
oneOf(callback).getLocalProperties();
will(returnValue(local));
oneOf(callback).getRemoteProperties();
oneOf(callback).getRemoteProperties(contactId);
will(returnValue(remote));
oneOf(modem).dial(NUMBER);
will(returnValue(false));
......@@ -147,12 +141,10 @@ public class ModemPluginTest extends BrambleTestCase {
final Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336);
TransportProperties p = new TransportProperties();
p.put("iso3166", ISO_1336);
p.put("number", NUMBER);
ContactId contactId = new ContactId(234);
final Map<ContactId, TransportProperties> remote =
Collections.singletonMap(contactId, p);
final TransportProperties remote = new TransportProperties();
remote.put("iso3166", ISO_1336);
remote.put("number", NUMBER);
final ContactId contactId = new ContactId(234);
context.checking(new Expectations() {{
// start()
oneOf(serialPortList).getPortNames();
......@@ -164,7 +156,7 @@ public class ModemPluginTest extends BrambleTestCase {
// createConnection()
oneOf(callback).getLocalProperties();
will(returnValue(local));
oneOf(callback).getRemoteProperties();
oneOf(callback).getRemoteProperties(contactId);
will(returnValue(remote));
oneOf(modem).dial(NUMBER);
will(throwException(new IOException()));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment