diff --git a/api/net/sf/briar/api/db/DatabaseComponent.java b/api/net/sf/briar/api/db/DatabaseComponent.java index ae0f59424..5671f13f1 100644 --- a/api/net/sf/briar/api/db/DatabaseComponent.java +++ b/api/net/sf/briar/api/db/DatabaseComponent.java @@ -151,6 +151,9 @@ public interface DatabaseComponent { /** Records the user's rating for the given author. */ void setRating(AuthorId a, Rating r) throws DbException; + /** Sets the local transport details, replacing any existing details. */ + void setTransports(Map transports) throws DbException; + /** * Makes the given group visible to the given set of contacts and invisible * to any other contacts. diff --git a/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java b/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java index 5f698cbc4..1b1d2bb16 100644 --- a/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java +++ b/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java @@ -902,6 +902,29 @@ class ReadWriteLockDatabaseComponent extends DatabaseComponentImpl { } } + public void setTransports(Map transports) + throws DbException { + boolean changed = false; + transportLock.writeLock().lock(); + try { + Txn txn = db.startTransaction(); + try { + if(!transports.equals(db.getTransports(txn))) { + db.setTransports(txn, transports); + changed = true; + } + db.commitTransaction(txn); + } catch(DbException e) { + db.abortTransaction(txn); + throw e; + } + } finally { + transportLock.writeLock().unlock(); + } + // Call the listeners outside the lock + if(changed) callListeners(DatabaseListener.Event.TRANSPORTS_UPDATED); + } + public void setVisibility(GroupId g, Collection visible) throws DbException { contactLock.readLock().lock(); diff --git a/components/net/sf/briar/db/SynchronizedDatabaseComponent.java b/components/net/sf/briar/db/SynchronizedDatabaseComponent.java index 5bf42d643..a5f58fa0f 100644 --- a/components/net/sf/briar/db/SynchronizedDatabaseComponent.java +++ b/components/net/sf/briar/db/SynchronizedDatabaseComponent.java @@ -668,6 +668,26 @@ class SynchronizedDatabaseComponent extends DatabaseComponentImpl { } } + public void setTransports(Map transports) + throws DbException { + boolean changed = false; + synchronized(transportLock) { + Txn txn = db.startTransaction(); + try { + if(!transports.equals(db.getTransports(txn))) { + db.setTransports(txn, transports); + changed = true; + } + db.commitTransaction(txn); + } catch(DbException e) { + db.abortTransaction(txn); + throw e; + } + } + // Call the listeners outside the lock + if(changed) callListeners(DatabaseListener.Event.TRANSPORTS_UPDATED); + } + public void setVisibility(GroupId g, Collection visible) throws DbException { synchronized(contactLock) { diff --git a/test/net/sf/briar/db/DatabaseComponentTest.java b/test/net/sf/briar/db/DatabaseComponentTest.java index 4deefed87..a4ccdcfef 100644 --- a/test/net/sf/briar/db/DatabaseComponentTest.java +++ b/test/net/sf/briar/db/DatabaseComponentTest.java @@ -1100,4 +1100,52 @@ public abstract class DatabaseComponentTest extends TestCase { context.assertIsSatisfied(); } + + @Test + public void testTransportsChangedCallsListeners() throws Exception { + Mockery context = new Mockery(); + @SuppressWarnings("unchecked") + final Database database = context.mock(Database.class); + final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); + final DatabaseListener listener = context.mock(DatabaseListener.class); + context.checking(new Expectations() {{ + oneOf(database).startTransaction(); + will(returnValue(txn)); + oneOf(database).getTransports(txn); + will(returnValue(Collections.singletonMap("foo", "bar"))); + oneOf(database).setTransports(txn, + Collections.singletonMap("bar", "baz")); + oneOf(database).commitTransaction(txn); + oneOf(listener).eventOccurred( + DatabaseListener.Event.TRANSPORTS_UPDATED); + }}); + DatabaseComponent db = createDatabaseComponent(database, cleaner); + + db.addListener(listener); + db.setTransports(Collections.singletonMap("bar", "baz")); + + context.assertIsSatisfied(); + } + + @Test + public void testTransportsUnchangedDoesNotCallListeners() throws Exception { + Mockery context = new Mockery(); + @SuppressWarnings("unchecked") + final Database database = context.mock(Database.class); + final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); + final DatabaseListener listener = context.mock(DatabaseListener.class); + context.checking(new Expectations() {{ + oneOf(database).startTransaction(); + will(returnValue(txn)); + oneOf(database).getTransports(txn); + will(returnValue(Collections.singletonMap("bar", "baz"))); + oneOf(database).commitTransaction(txn); + }}); + DatabaseComponent db = createDatabaseComponent(database, cleaner); + + db.addListener(listener); + db.setTransports(Collections.singletonMap("bar", "baz")); + + context.assertIsSatisfied(); + } }