From 68b82ae826fd8affc225d5914eb6abeba1e2437f Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Mon, 10 Oct 2011 22:35:46 +0100
Subject: [PATCH] Retrieve all remote transports from the DB in a single call.

---
 .../sf/briar/api/db/DatabaseComponent.java    |  15 +-
 components/net/sf/briar/db/Database.java      |  32 ++---
 .../sf/briar/db/DatabaseComponentImpl.java    |  91 ++++++------
 components/net/sf/briar/db/JdbcDatabase.java  | 135 +++++++++---------
 .../sf/briar/invitation/InvitationWorker.java |   2 +-
 .../sf/briar/db/DatabaseComponentTest.java    |  35 +++--
 test/net/sf/briar/db/H2DatabaseTest.java      |  71 ++++++---
 .../invitation/InvitationWorkerTest.java      |   2 +-
 8 files changed, 207 insertions(+), 176 deletions(-)

diff --git a/api/net/sf/briar/api/db/DatabaseComponent.java b/api/net/sf/briar/api/db/DatabaseComponent.java
index 4f5f339a62..5a4475108a 100644
--- a/api/net/sf/briar/api/db/DatabaseComponent.java
+++ b/api/net/sf/briar/api/db/DatabaseComponent.java
@@ -115,9 +115,17 @@ public interface DatabaseComponent {
 	/** Returns the IDs of all contacts. */
 	Collection<ContactId> getContacts() throws DbException;
 
+	/** Returns all local transport properties. */
+	Map<TransportId, Map<String, String>> getLocalTransports()
+	throws DbException;
+
 	/** Returns the user's rating for the given author. */
 	Rating getRating(AuthorId a) throws DbException;
 
+	/** Returns all remote transport properties. */
+	Map<TransportId, Map<ContactId, Map<String, String>>> getRemoteTransports()
+	throws DbException;
+
 	/** Returns the secret shared with the given contact. */
 	byte[] getSharedSecret(ContactId c) throws DbException;
 
@@ -127,13 +135,6 @@ public interface DatabaseComponent {
 	/** Returns the configuration for the given transport. */
 	Map<String, String> getTransportConfig(TransportId t) throws DbException;
 
-	/** Returns all local transport properties. */
-	Map<TransportId, Map<String, String>> getTransports() throws DbException;
-
-	/** Returns all transport properties for the given contact. */
-	Map<TransportId, Map<String, String>> getTransports(ContactId c)
-	throws DbException;
-
 	/** Returns the contacts to which the given group is visible. */
 	Collection<ContactId> getVisibility(GroupId g) throws DbException;
 
diff --git a/components/net/sf/briar/db/Database.java b/components/net/sf/briar/db/Database.java
index 55edbec1df..acb111fdd1 100644
--- a/components/net/sf/briar/db/Database.java
+++ b/components/net/sf/briar/db/Database.java
@@ -211,6 +211,14 @@ interface Database<T> {
 	 */
 	MessageId getGroupMessageParent(T txn, MessageId m) throws DbException;
 
+	/**
+	 * Returns all local transport properties.
+	 * <p>
+	 * Locking: transports read.
+	 */
+	Map<TransportId, Map<String, String>> getLocalTransports(T txn)
+	throws DbException;
+
 	/**
 	 * Returns the IDs of any batches sent to the given contact that should now
 	 * be considered lost.
@@ -269,6 +277,14 @@ interface Database<T> {
 	 */
 	Rating getRating(T txn, AuthorId a) throws DbException;
 
+	/**
+	 * Returns all remote transport properties.
+	 * <p>
+	 * Locking: contacts read, transports read.
+	 */
+	Map<TransportId, Map<ContactId, Map<String, String>>>
+	getRemoteTransports(T txn) throws DbException;
+
 	/**
 	 * Returns the sendability score of the given group message.
 	 * <p>
@@ -325,22 +341,6 @@ interface Database<T> {
 	Map<String, String> getTransportConfig(T txn, TransportId t)
 	throws DbException;
 
-	/**
-	 * Returns all local transport properties.
-	 * <p>
-	 * Locking: transports read.
-	 */
-	Map<TransportId, Map<String, String>> getTransports(T txn)
-	throws DbException;
-
-	/**
-	 * Returns all transport properties for the given contact.
-	 * <p>
-	 * Locking: contacts read, transports read.
-	 */
-	Map<TransportId, Map<String, String>> getTransports(T txn, ContactId c)
-	throws DbException;
-
 	/**
 	 * Returns the contacts to which the given group is visible.
 	 * <p>
diff --git a/components/net/sf/briar/db/DatabaseComponentImpl.java b/components/net/sf/briar/db/DatabaseComponentImpl.java
index 2c6be4f61d..0c33930ec7 100644
--- a/components/net/sf/briar/db/DatabaseComponentImpl.java
+++ b/components/net/sf/briar/db/DatabaseComponentImpl.java
@@ -615,7 +615,7 @@ DatabaseCleaner.Callback {
 			try {
 				T txn = db.startTransaction();
 				try {
-					transports = db.getTransports(txn);
+					transports = db.getLocalTransports(txn);
 					timestamp = System.currentTimeMillis();
 					db.setTransportTimestamp(txn, c, timestamp);
 					db.commitTransaction(txn);
@@ -699,6 +699,25 @@ DatabaseCleaner.Callback {
 		}
 	}
 
+	public Map<TransportId, Map<String, String>> getLocalTransports()
+	throws DbException {
+		transportLock.readLock().lock();
+		try {
+			T txn = db.startTransaction();
+			try {
+				Map<TransportId, Map<String, String>> transports =
+					db.getLocalTransports(txn);
+				db.commitTransaction(txn);
+				return transports;
+			} catch(DbException e) {
+				db.abortTransaction(txn);
+				throw e;
+			}
+		} finally {
+			transportLock.readLock().unlock();
+		}
+	}
+
 	public Rating getRating(AuthorId a) throws DbException {
 		ratingLock.readLock().lock();
 		try {
@@ -716,6 +735,30 @@ DatabaseCleaner.Callback {
 		}
 	}
 
+	public Map<TransportId, Map<ContactId, Map<String, String>>>
+	getRemoteTransports() throws DbException {
+		contactLock.readLock().lock();
+		try {
+			transportLock.readLock().lock();
+			try {
+				T txn = db.startTransaction();
+				try {
+					Map<TransportId, Map<ContactId, Map<String, String>>>
+					transports = db.getRemoteTransports(txn);
+					db.commitTransaction(txn);
+					return transports;
+				} catch(DbException e) {
+					db.abortTransaction(txn);
+					throw e;
+				}
+			} finally {
+				transportLock.readLock().unlock();
+			}
+		} finally {
+			contactLock.readLock().unlock();
+		}
+	}
+
 	public byte[] getSharedSecret(ContactId c) throws DbException {
 		contactLock.readLock().lock();
 		try {
@@ -769,50 +812,6 @@ DatabaseCleaner.Callback {
 		}
 	}
 
-	public Map<TransportId, Map<String, String>> getTransports()
-	throws DbException {
-		transportLock.readLock().lock();
-		try {
-			T txn = db.startTransaction();
-			try {
-				Map<TransportId, Map<String, String>> transports =
-					db.getTransports(txn);
-				db.commitTransaction(txn);
-				return transports;
-			} catch(DbException e) {
-				db.abortTransaction(txn);
-				throw e;
-			}
-		} finally {
-			transportLock.readLock().unlock();
-		}
-	}
-
-	public Map<TransportId, Map<String, String>> getTransports(ContactId c)
-	throws DbException {
-		contactLock.readLock().lock();
-		try {
-			if(!containsContact(c)) throw new NoSuchContactException();
-			transportLock.readLock().lock();
-			try {
-				T txn = db.startTransaction();
-				try {
-					Map<TransportId, Map<String, String>> transports =
-						db.getTransports(txn, c);
-					db.commitTransaction(txn);
-					return transports;
-				} catch(DbException e) {
-					db.abortTransaction(txn);
-					throw e;
-				}
-			} finally {
-				transportLock.readLock().unlock();
-			}
-		} finally {
-			contactLock.readLock().unlock();
-		}
-	}
-
 	public Collection<ContactId> getVisibility(GroupId g) throws DbException {
 		contactLock.readLock().lock();
 		try {
@@ -1252,7 +1251,7 @@ DatabaseCleaner.Callback {
 			T txn = db.startTransaction();
 			try {
 				Map<TransportId, Map<String, String>> transports =
-					db.getTransports(txn);
+					db.getLocalTransports(txn);
 				Map<String, String> old = transports.get(t);
 				if(!properties.equals(old)) {
 					db.setTransportProperties(txn, t, properties);
diff --git a/components/net/sf/briar/db/JdbcDatabase.java b/components/net/sf/briar/db/JdbcDatabase.java
index 537800e6cc..b6de1ca1bd 100644
--- a/components/net/sf/briar/db/JdbcDatabase.java
+++ b/components/net/sf/briar/db/JdbcDatabase.java
@@ -916,6 +916,37 @@ abstract class JdbcDatabase implements Database<Connection> {
 		} else return f.length();
 	}
 
+	public Map<TransportId, Map<String, String>> getLocalTransports(
+			Connection txn) throws DbException {
+		PreparedStatement ps = null;
+		ResultSet rs = null;
+		try {
+			String sql = "SELECT transportId, key, value FROM transports"
+				+ " ORDER BY transportId";
+			ps = txn.prepareStatement(sql);
+			rs = ps.executeQuery();
+			Map<TransportId, Map<String, String>> transports =
+				new TreeMap<TransportId, Map<String, String>>();
+			Map<String, String> properties = null;
+			TransportId lastId = null;
+			while(rs.next()) {
+				TransportId id = new TransportId(rs.getInt(1));
+				if(!id.equals(lastId)) {
+					properties = new TreeMap<String, String>();
+					transports.put(id, properties);
+				}
+				properties.put(rs.getString(2), rs.getString(3));
+			}
+			rs.close();
+			ps.close();
+			return transports;
+		} catch(SQLException e) {
+			tryToClose(rs);
+			tryToClose(ps);
+			throw new DbException(e);
+		}
+	}
+
 	public Collection<BatchId> getLostBatches(Connection txn, ContactId c)
 	throws DbException {
 		PreparedStatement ps = null;
@@ -1181,6 +1212,46 @@ abstract class JdbcDatabase implements Database<Connection> {
 		}
 	}
 
+	public Map<TransportId, Map<ContactId, Map<String, String>>>
+	getRemoteTransports(Connection txn) throws DbException {
+		PreparedStatement ps = null;
+		ResultSet rs = null;
+		try {
+			String sql = "SELECT transportId, contactId, key, value"
+				+ " FROM contactTransports"
+				+ " ORDER BY transportId";
+			ps = txn.prepareStatement(sql);
+			rs = ps.executeQuery();
+			Map<TransportId, Map<ContactId, Map<String, String>>> transports =
+				new TreeMap<TransportId, Map<ContactId, Map<String, String>>>();
+			Map<ContactId, Map<String, String>> contacts = null;
+			Map<String, String> properties = null;
+			TransportId lastTransportId = null;
+			ContactId lastContactId = null;
+			while(rs.next()) {
+				TransportId transportId = new TransportId(rs.getInt(1));
+				if(!transportId.equals(lastTransportId)) {
+					contacts = new HashMap<ContactId, Map<String, String>>();
+					transports.put(transportId, contacts);
+					lastContactId = null;
+				}
+				ContactId contactId = new ContactId(rs.getInt(2));
+				if(!contactId.equals(lastContactId)) {
+					properties = new TreeMap<String, String>();
+					contacts.put(contactId, properties);
+				}
+				properties.put(rs.getString(3), rs.getString(4));
+			}
+			rs.close();
+			ps.close();
+			return transports;
+		} catch(SQLException e) {
+			tryToClose(rs);
+			tryToClose(ps);
+			throw new DbException(e);
+		}
+	}
+
 	public byte[] getSharedSecret(Connection txn, ContactId c)
 	throws DbException {
 		PreparedStatement ps = null;
@@ -1418,70 +1489,6 @@ abstract class JdbcDatabase implements Database<Connection> {
 		}
 	}
 
-	public Map<TransportId, Map<String, String>> getTransports(Connection txn)
-	throws DbException {
-		PreparedStatement ps = null;
-		ResultSet rs = null;
-		try {
-			String sql = "SELECT transportId, key, value FROM transports"
-				+ " ORDER BY transportId";
-			ps = txn.prepareStatement(sql);
-			rs = ps.executeQuery();
-			Map<TransportId, Map<String, String>> transports =
-				new TreeMap<TransportId, Map<String, String>>();
-			Map<String, String> properties = null;
-			TransportId lastId = null;
-			while(rs.next()) {
-				TransportId id = new TransportId(rs.getInt(1));
-				if(!id.equals(lastId)) {
-					properties = new TreeMap<String, String>();
-					transports.put(id, properties);
-				}
-				properties.put(rs.getString(2), rs.getString(3));
-			}
-			rs.close();
-			ps.close();
-			return transports;
-		} catch(SQLException e) {
-			tryToClose(rs);
-			tryToClose(ps);
-			throw new DbException(e);
-		}
-	}
-
-	public Map<TransportId, Map<String, String>> getTransports(Connection txn,
-			ContactId c) throws DbException {
-		PreparedStatement ps = null;
-		ResultSet rs = null;
-		try {
-			String sql = "SELECT transportId, key, value FROM contactTransports"
-				+ " WHERE contactId = ?"
-				+ " ORDER BY transportId";
-			ps = txn.prepareStatement(sql);
-			ps.setInt(1, c.getInt());
-			rs = ps.executeQuery();
-			Map<TransportId, Map<String, String>> transports =
-				new TreeMap<TransportId, Map<String, String>>();
-			Map<String, String> properties = null;
-			TransportId lastId = null;
-			while(rs.next()) {
-				TransportId id = new TransportId(rs.getInt(1));
-				if(!id.equals(lastId)) {
-					properties = new TreeMap<String, String>();
-					transports.put(id, properties);
-				}
-				properties.put(rs.getString(2), rs.getString(3));
-			}
-			rs.close();
-			ps.close();
-			return transports;
-		} catch(SQLException e) {
-			tryToClose(rs);
-			tryToClose(ps);
-			throw new DbException(e);
-		}
-	}
-
 	public Collection<ContactId> getVisibility(Connection txn, GroupId g)
 	throws DbException {
 		PreparedStatement ps = null;
diff --git a/components/net/sf/briar/invitation/InvitationWorker.java b/components/net/sf/briar/invitation/InvitationWorker.java
index 68b323f8f0..9437f2d706 100644
--- a/components/net/sf/briar/invitation/InvitationWorker.java
+++ b/components/net/sf/briar/invitation/InvitationWorker.java
@@ -73,7 +73,7 @@ class InvitationWorker implements Runnable {
 		// FIXME: Create a real invitation
 		Map<TransportId, Map<String, String>> transports;
 		try {
-			transports = db.getTransports();
+			transports = db.getLocalTransports();
 		} catch(DbException e) {
 			throw new IOException(e.getMessage());
 		}
diff --git a/test/net/sf/briar/db/DatabaseComponentTest.java b/test/net/sf/briar/db/DatabaseComponentTest.java
index f171ea5f93..158e43731d 100644
--- a/test/net/sf/briar/db/DatabaseComponentTest.java
+++ b/test/net/sf/briar/db/DatabaseComponentTest.java
@@ -55,6 +55,8 @@ public abstract class DatabaseComponentTest extends TestCase {
 	private final Group group;
 	private final TransportId transportId;
 	private final Map<TransportId, Map<String, String>> transports;
+	private final Map<TransportId, Map<ContactId, Map<String, String>>>
+	remoteTransports;
 	private final byte[] secret;
 
 	public DatabaseComponentTest() {
@@ -74,8 +76,10 @@ public abstract class DatabaseComponentTest extends TestCase {
 			new TestMessage(messageId, null, null, null, timestamp, raw);
 		group = new TestGroup(groupId, "The really exciting group", null);
 		transportId = new TransportId(123);
-		transports = Collections.singletonMap(transportId,
-				Collections.singletonMap("bar", "baz"));
+		Map<String, String> properties = Collections.singletonMap("foo", "bar");
+		transports = Collections.singletonMap(transportId, properties);
+		remoteTransports = Collections.singletonMap(transportId,
+				Collections.singletonMap(contactId, properties));
 		secret = new byte[123];
 	}
 
@@ -121,11 +125,9 @@ public abstract class DatabaseComponentTest extends TestCase {
 			will(returnValue(true));
 			oneOf(database).getSharedSecret(txn, contactId);
 			will(returnValue(secret));
-			// getTransports(contactId)
-			oneOf(database).containsContact(txn, contactId);
-			will(returnValue(true));
-			oneOf(database).getTransports(txn, contactId);
-			will(returnValue(transports));
+			// getRemoteTransports()
+			oneOf(database).getRemoteTransports(txn);
+			will(returnValue(remoteTransports));
 			// subscribe(group)
 			oneOf(group).getId();
 			will(returnValue(groupId));
@@ -171,7 +173,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 		assertEquals(connectionWindow,
 				db.getConnectionWindow(contactId, transportId));
 		assertEquals(secret, db.getSharedSecret(contactId));
-		assertEquals(transports, db.getTransports(contactId));
+		assertEquals(remoteTransports, db.getRemoteTransports());
 		db.subscribe(group); // First time - check listeners are called
 		db.subscribe(group); // Second time - check listeners aren't called
 		assertEquals(Collections.singletonList(groupId), db.getSubscriptions());
@@ -468,11 +470,11 @@ public abstract class DatabaseComponentTest extends TestCase {
 			context.mock(TransportUpdate.class);
 		context.checking(new Expectations() {{
 			// Check whether the contact is still in the DB (which it's not)
-			exactly(18).of(database).startTransaction();
+			exactly(17).of(database).startTransaction();
 			will(returnValue(txn));
-			exactly(18).of(database).containsContact(txn, contactId);
+			exactly(17).of(database).containsContact(txn, contactId);
 			will(returnValue(false));
-			exactly(18).of(database).commitTransaction(txn);
+			exactly(17).of(database).commitTransaction(txn);
 		}});
 		DatabaseComponent db = createDatabaseComponent(database, cleaner);
 
@@ -522,11 +524,6 @@ public abstract class DatabaseComponentTest extends TestCase {
 			fail();
 		} catch(NoSuchContactException expected) {}
 
-		try {
-			db.getTransports(contactId);
-			fail();
-		} catch(NoSuchContactException expected) {}
-
 		try {
 			db.hasSendableMessages(contactId);
 			fail();
@@ -789,7 +786,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 			allowing(database).containsContact(txn, contactId);
 			will(returnValue(true));
 			// Get the local transport properties
-			oneOf(database).getTransports(txn);
+			oneOf(database).getLocalTransports(txn);
 			will(returnValue(transports));
 			oneOf(database).setTransportTimestamp(with(txn), with(contactId),
 					with(any(long.class)));
@@ -1286,7 +1283,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 		context.checking(new Expectations() {{
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
-			oneOf(database).getTransports(txn);
+			oneOf(database).getLocalTransports(txn);
 			will(returnValue(Collections.singletonMap(transportId,
 					properties)));
 			oneOf(database).setTransportProperties(txn, transportId,
@@ -1315,7 +1312,7 @@ public abstract class DatabaseComponentTest extends TestCase {
 		context.checking(new Expectations() {{
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
-			oneOf(database).getTransports(txn);
+			oneOf(database).getLocalTransports(txn);
 			will(returnValue(Collections.singletonMap(transportId,
 					properties)));
 			oneOf(database).commitTransaction(txn);
diff --git a/test/net/sf/briar/db/H2DatabaseTest.java b/test/net/sf/briar/db/H2DatabaseTest.java
index afa141a016..343757ef34 100644
--- a/test/net/sf/briar/db/H2DatabaseTest.java
+++ b/test/net/sf/briar/db/H2DatabaseTest.java
@@ -9,6 +9,7 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Random;
 import java.util.TreeMap;
 import java.util.concurrent.CountDownLatch;
@@ -71,6 +72,8 @@ public class H2DatabaseTest extends TestCase {
 	private final Group group;
 	private final TransportId transportId;
 	private final Map<TransportId, Map<String, String>> transports;
+	private final Map<TransportId, Map<ContactId, Map<String, String>>>
+	remoteTransports;
 	private final Map<Group, Long> subscriptions;
 	private final byte[] secret;
 
@@ -97,8 +100,10 @@ public class H2DatabaseTest extends TestCase {
 			new TestMessage(privateMessageId, null, null, null, timestamp, raw);
 		group = groupFactory.createGroup(groupId, "Group name", null);
 		transportId = new TransportId(0);
-		transports = Collections.singletonMap(transportId,
-				Collections.singletonMap("bar", "baz"));
+		Map<String, String> properties = Collections.singletonMap("foo", "bar");
+		transports = Collections.singletonMap(transportId, properties);
+		remoteTransports = Collections.singletonMap(transportId,
+				Collections.singletonMap(contactId, properties));
 		subscriptions = Collections.singletonMap(group, 0L);
 		secret = new byte[123];
 	}
@@ -132,7 +137,7 @@ public class H2DatabaseTest extends TestCase {
 		db = open(true);
 		txn = db.startTransaction();
 		assertTrue(db.containsContact(txn, contactId));
-		assertEquals(transports, db.getTransports(txn, contactId));
+		assertEquals(remoteTransports, db.getRemoteTransports(txn));
 		assertTrue(db.containsSubscription(txn, groupId));
 		assertTrue(db.containsMessage(txn, messageId));
 		byte[] raw1 = db.getMessage(txn, messageId);
@@ -152,7 +157,7 @@ public class H2DatabaseTest extends TestCase {
 		db = open(true);
 		txn = db.startTransaction();
 		assertFalse(db.containsContact(txn, contactId));
-		assertEquals(Collections.emptyMap(), db.getTransports(txn, contactId));
+		assertEquals(Collections.emptyMap(), db.getRemoteTransports(txn));
 		assertFalse(db.containsSubscription(txn, groupId));
 		assertFalse(db.containsMessage(txn, messageId));
 		assertFalse(db.containsMessage(txn, privateMessageId));
@@ -983,40 +988,49 @@ public class H2DatabaseTest extends TestCase {
 
 	@Test
 	public void testUpdateTransportProperties() throws Exception {
+		Map<String, String> properties = Collections.singletonMap("foo", "bar");
+		Map<String, String> properties1 =
+			Collections.singletonMap("baz", "bam");
+
 		Database<Connection> db = open(false);
 		Connection txn = db.startTransaction();
 
 		// Add a contact with some transport properties
 		assertEquals(contactId, db.addContact(txn, transports, secret));
-		assertEquals(transports, db.getTransports(txn, contactId));
+		assertEquals(remoteTransports, db.getRemoteTransports(txn));
 
 		// Replace the transport properties
 		TransportId transportId1 = new TransportId(1);
 		Map<TransportId, Map<String, String>> transports1 =
 			new TreeMap<TransportId, Map<String, String>>();
-		transports1.put(transportId, Collections.singletonMap("bar", "baz"));
-		transports1.put(transportId1, Collections.singletonMap("baz", "quux"));
+		transports1.put(transportId, properties);
+		transports1.put(transportId1, properties1);
+		Map<TransportId, Map<ContactId, Map<String, String>>> remoteTransports1
+		= new TreeMap<TransportId, Map<ContactId, Map<String, String>>>();
+		remoteTransports1.put(transportId, Collections.singletonMap(contactId,
+				properties));
+		remoteTransports1.put(transportId1, Collections.singletonMap(contactId,
+				properties1));
 		db.setTransports(txn, contactId, transports1, 1);
-		assertEquals(transports1, db.getTransports(txn, contactId));
+		assertEquals(remoteTransports1, db.getRemoteTransports(txn));
 
 		// Remove the transport properties
 		db.setTransports(txn, contactId,
 				Collections.<TransportId, Map<String, String>>emptyMap(), 2);
-		assertEquals(Collections.emptyMap(), db.getTransports(txn, contactId));
+		assertEquals(Collections.emptyMap(), db.getRemoteTransports(txn));
 
 		// Set the local transport properties
-		for(TransportId t : transports.keySet()) {
-			Map<String, String> properties = transports.get(t);
-			db.setTransportProperties(txn, transportId, properties);
+		for(Entry<TransportId, Map<String, String>> e : transports.entrySet()) {
+			db.setTransportProperties(txn, e.getKey(), e.getValue());
 		}
-		assertEquals(transports, db.getTransports(txn));
+		assertEquals(transports, db.getLocalTransports(txn));
 
 		// Remove the local transport properties
 		for(TransportId t : transports.keySet()) {
 			db.setTransportProperties(txn, t,
 					Collections.<String, String>emptyMap());
 		}
-		assertEquals(Collections.emptyMap(), db.getTransports(txn));
+		assertEquals(Collections.emptyMap(), db.getLocalTransports(txn));
 
 		db.commitTransaction(txn);
 		db.close();
@@ -1025,8 +1039,9 @@ public class H2DatabaseTest extends TestCase {
 
 	@Test
 	public void testUpdateTransportConfig() throws Exception {
-		Map<String, String> config = Collections.singletonMap("bar", "baz");
+		Map<String, String> config = Collections.singletonMap("foo", "bar");
 		Map<String, String> config1 = Collections.singletonMap("baz", "bam");
+
 		Database<Connection> db = open(false);
 		Connection txn = db.startTransaction();
 
@@ -1050,32 +1065,44 @@ public class H2DatabaseTest extends TestCase {
 
 	@Test
 	public void testTransportsNotUpdatedIfTimestampIsOld() throws Exception {
+		Map<String, String> properties = Collections.singletonMap("foo", "bar");
+		Map<String, String> properties1 =
+			Collections.singletonMap("baz", "bam");
+		Map<String, String> properties2 =
+			Collections.singletonMap("quux", "etc");
+
 		Database<Connection> db = open(false);
 		Connection txn = db.startTransaction();
 
 		// Add a contact with some transport properties
 		assertEquals(contactId, db.addContact(txn, transports, secret));
-		assertEquals(transports, db.getTransports(txn, contactId));
+		assertEquals(remoteTransports, db.getRemoteTransports(txn));
 
 		// Replace the transport properties using a timestamp of 2
 		TransportId transportId1 = new TransportId(1);
 		Map<TransportId, Map<String, String>> transports1 =
 			new TreeMap<TransportId, Map<String, String>>();
-		transports1.put(transportId, Collections.singletonMap("bar", "baz"));
-		transports1.put(transportId1, Collections.singletonMap("baz", "quux"));
+		transports1.put(transportId, properties);
+		transports1.put(transportId1, properties1);
+		Map<TransportId, Map<ContactId, Map<String, String>>> remoteTransports1
+		= new TreeMap<TransportId, Map<ContactId, Map<String, String>>>();
+		remoteTransports1.put(transportId, Collections.singletonMap(contactId,
+				properties));
+		remoteTransports1.put(transportId1, Collections.singletonMap(contactId,
+				properties1));
 		db.setTransports(txn, contactId, transports1, 2);
-		assertEquals(transports1, db.getTransports(txn, contactId));
+		assertEquals(remoteTransports1, db.getRemoteTransports(txn));
 
 		// Try to replace the transport properties using a timestamp of 1
 		TransportId transportId2 = new TransportId(2);
 		Map<TransportId, Map<String, String>> transports2 =
 			new TreeMap<TransportId, Map<String, String>>();
-		transports2.put(transportId1, Collections.singletonMap("baz", "quux"));
-		transports2.put(transportId2, Collections.singletonMap("quux", "etc"));
+		transports2.put(transportId1, properties1);
+		transports2.put(transportId2, properties2);
 		db.setTransports(txn, contactId, transports2, 1);
 
 		// The old properties should still be there
-		assertEquals(transports1, db.getTransports(txn, contactId));
+		assertEquals(remoteTransports1, db.getRemoteTransports(txn));
 
 		db.commitTransaction(txn);
 		db.close();
diff --git a/test/net/sf/briar/invitation/InvitationWorkerTest.java b/test/net/sf/briar/invitation/InvitationWorkerTest.java
index 6d2b0790cd..a6495143fb 100644
--- a/test/net/sf/briar/invitation/InvitationWorkerTest.java
+++ b/test/net/sf/briar/invitation/InvitationWorkerTest.java
@@ -139,7 +139,7 @@ public class InvitationWorkerTest extends TestCase {
 			oneOf(params).getPassword();
 			will(returnValue(new char[] {'x', 'y', 'z', 'z', 'y'}));
 			oneOf(callback).encryptingFile(invitation);
-			oneOf(database).getTransports();
+			oneOf(database).getLocalTransports();
 			will(returnValue(transports));
 			oneOf(writerFactory).createWriter(with(any(OutputStream.class)));
 			will(returnValue(writer));
-- 
GitLab