Reduce DB queries for looking up transport properties.

This commit is contained in:
akwizgran
2017-10-10 10:59:39 +01:00
parent 6c1901fe5b
commit e074672e86
11 changed files with 106 additions and 63 deletions

View File

@@ -347,8 +347,7 @@ class DroidtoothPlugin implements DuplexPlugin {
@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);

View File

@@ -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 {
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 {
@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()) {

View File

@@ -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
*/ */

View File

@@ -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.

View File

@@ -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 {

View File

@@ -25,6 +25,7 @@ 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.Map.Entry;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@@ -209,8 +210,9 @@ 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();
for (Entry<ContactId, TransportProperties> e : Map<ContactId, TransportProperties> remote =
callback.getRemoteProperties().entrySet()) { callback.getRemoteProperties();
for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
ContactId c = e.getKey(); ContactId c = e.getKey();
if (!connected.contains(c)) connectAndCallBack(c, e.getValue()); if (!connected.contains(c)) connectAndCallBack(c, e.getValue());
} }
@@ -234,8 +236,7 @@ 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;
TransportProperties p = callback.getRemoteProperties().get(c); return createConnection(callback.getRemoteProperties(c));
return p == null ? null : createConnection(p);
} }
@Nullable @Nullable

View File

@@ -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 {

View File

@@ -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) {
} }

View File

@@ -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);

View File

@@ -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

View File

@@ -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 {
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 {
// 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 {
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 {
// 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 {
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 {
// 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()));