diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java index 3869e71a6..a934fa6c8 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java @@ -126,16 +126,11 @@ public interface DatabaseComponent extends TransactionManager { TransportKeys k) throws DbException; /** - * Returns true if there are any acks or messages to send to the given - * contact over a transport with the given maximum latency. + * Returns true if there are any acks to send to the given contact. *

* Read-only. - * - * @param eager True if messages that are not yet due for retransmission - * should be included */ - boolean containsAnythingToSend(Transaction txn, ContactId c, - long maxLatency, boolean eager) throws DbException; + boolean containsAcksToSend(Transaction txn, ContactId c) throws DbException; /** * Returns true if the database contains the given contact for the given @@ -161,6 +156,18 @@ public interface DatabaseComponent extends TransactionManager { */ boolean containsIdentity(Transaction txn, AuthorId a) throws DbException; + /** + * Returns true if there are any messages to send to the given contact + * over a transport with the given maximum latency. + *

+ * Read-only. + * + * @param eager True if messages that are not yet due for retransmission + * should be included + */ + boolean containsMessagesToSend(Transaction txn, ContactId c, + long maxLatency, boolean eager) throws DbException; + /** * Returns true if the database contains the given pending contact. *

diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java index e0aaaecc3..1e6f4ab31 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java @@ -163,16 +163,11 @@ interface Database { throws DbException; /** - * Returns true if there are any acks or messages to send to the given - * contact over a transport with the given maximum latency. + * Returns true if there are any acks to send to the given contact. *

* Read-only. - * - * @param eager True if messages that are not yet due for retransmission - * should be included */ - boolean containsAnythingToSend(T txn, ContactId c, long maxLatency, - boolean eager) throws DbException; + boolean containsAcksToSend(T txn, ContactId c) throws DbException; /** * Returns true if the database contains the given contact for the given @@ -212,6 +207,18 @@ interface Database { */ boolean containsMessage(T txn, MessageId m) throws DbException; + /** + * Returns true if there are any messages to send to the given + * contact over a transport with the given maximum latency. + *

+ * Read-only. + * + * @param eager True if messages that are not yet due for retransmission + * should be included + */ + boolean containsMessagesToSend(T txn, ContactId c, long maxLatency, + boolean eager) throws DbException; + /** * Returns true if the database contains the given pending contact. *

diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java index 64b6fc3c3..bdf191ba1 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java @@ -342,12 +342,12 @@ class DatabaseComponentImpl implements DatabaseComponent { } @Override - public boolean containsAnythingToSend(Transaction transaction, ContactId c, - long maxLatency, boolean eager) throws DbException { + public boolean containsAcksToSend(Transaction transaction, ContactId c) + throws DbException { T txn = unbox(transaction); if (!db.containsContact(txn, c)) throw new NoSuchContactException(); - return db.containsAnythingToSend(txn, c, maxLatency, eager); + return db.containsAcksToSend(txn, c); } @Override @@ -373,6 +373,15 @@ class DatabaseComponentImpl implements DatabaseComponent { return db.containsIdentity(txn, a); } + @Override + public boolean containsMessagesToSend(Transaction transaction, ContactId c, + long maxLatency, boolean eager) throws DbException { + T txn = unbox(transaction); + if (!db.containsContact(txn, c)) + throw new NoSuchContactException(); + return db.containsMessagesToSend(txn, c, maxLatency, eager); + } + @Override public boolean containsPendingContact(Transaction transaction, PendingContactId p) throws DbException { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java index 3c4093e8d..bf23fd683 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java @@ -1147,8 +1147,8 @@ abstract class JdbcDatabase implements Database { } @Override - public boolean containsAnythingToSend(Connection txn, ContactId c, - long maxLatency, boolean eager) throws DbException { + public boolean containsAcksToSend(Connection txn, ContactId c) + throws DbException { PreparedStatement ps = null; ResultSet rs = null; try { @@ -1160,34 +1160,7 @@ abstract class JdbcDatabase implements Database { boolean acksToSend = rs.next(); rs.close(); ps.close(); - if (acksToSend) return true; - if (eager) { - sql = "SELECT NULL from statuses" - + " WHERE contactId = ? AND state = ?" - + " AND groupShared = TRUE AND messageShared = TRUE" - + " AND deleted = FALSE AND seen = FALSE"; - ps = txn.prepareStatement(sql); - ps.setInt(1, c.getInt()); - ps.setInt(2, DELIVERED.getValue()); - } else { - long now = clock.currentTimeMillis(); - sql = "SELECT NULL FROM statuses" - + " WHERE contactId = ? AND state = ?" - + " AND groupShared = TRUE AND messageShared = TRUE" - + " AND deleted = FALSE AND seen = FALSE" - + " AND (expiry <= ? OR maxLatency IS NULL" - + " OR ? < maxLatency)"; - ps = txn.prepareStatement(sql); - ps.setInt(1, c.getInt()); - ps.setInt(2, DELIVERED.getValue()); - ps.setLong(3, now); - ps.setLong(4, maxLatency); - } - rs = ps.executeQuery(); - boolean messagesToSend = rs.next(); - rs.close(); - ps.close(); - return messagesToSend; + return acksToSend; } catch (SQLException e) { tryToClose(rs, LOG, WARNING); tryToClose(ps, LOG, WARNING); @@ -1307,6 +1280,46 @@ abstract class JdbcDatabase implements Database { } } + @Override + public boolean containsMessagesToSend(Connection txn, ContactId c, + long maxLatency, boolean eager) throws DbException { + PreparedStatement ps = null; + ResultSet rs = null; + try { + if (eager) { + String sql = "SELECT NULL from statuses" + + " WHERE contactId = ? AND state = ?" + + " AND groupShared = TRUE AND messageShared = TRUE" + + " AND deleted = FALSE AND seen = FALSE"; + ps = txn.prepareStatement(sql); + ps.setInt(1, c.getInt()); + ps.setInt(2, DELIVERED.getValue()); + } else { + long now = clock.currentTimeMillis(); + String sql = "SELECT NULL FROM statuses" + + " WHERE contactId = ? AND state = ?" + + " AND groupShared = TRUE AND messageShared = TRUE" + + " AND deleted = FALSE AND seen = FALSE" + + " AND (expiry <= ? OR maxLatency IS NULL" + + " OR ? < maxLatency)"; + ps = txn.prepareStatement(sql); + ps.setInt(1, c.getInt()); + ps.setInt(2, DELIVERED.getValue()); + ps.setLong(3, now); + ps.setLong(4, maxLatency); + } + rs = ps.executeQuery(); + boolean messagesToSend = rs.next(); + rs.close(); + ps.close(); + return messagesToSend; + } catch (SQLException e) { + tryToClose(rs, LOG, WARNING); + tryToClose(ps, LOG, WARNING); + throw new DbException(e); + } + } + @Override public boolean containsPendingContact(Connection txn, PendingContactId p) throws DbException { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/file/RemovableDriveManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/file/RemovableDriveManagerImpl.java index 386463dd7..c7a250d60 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/file/RemovableDriveManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/file/RemovableDriveManagerImpl.java @@ -106,7 +106,8 @@ class RemovableDriveManagerImpl @Override public boolean isWriterTaskNeeded(ContactId c) throws DbException { return db.transactionWithResult(true, txn -> - db.containsAnythingToSend(txn, c, MAX_LATENCY, true)); + db.containsAcksToSend(txn, c) || + db.containsMessagesToSend(txn, c, MAX_LATENCY, true)); } @Override diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java index e288e5507..2e342186a 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java @@ -303,11 +303,11 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { throws Exception { context.checking(new Expectations() {{ // Check whether the contact is in the DB (which it's not) - exactly(25).of(database).startTransaction(); + exactly(27).of(database).startTransaction(); will(returnValue(txn)); - exactly(25).of(database).containsContact(txn, contactId); + exactly(27).of(database).containsContact(txn, contactId); will(returnValue(false)); - exactly(25).of(database).abortTransaction(txn); + exactly(27).of(database).abortTransaction(txn); }}); DatabaseComponent db = createDatabaseComponent(database, eventBus, eventExecutor, shutdownManager); @@ -321,6 +321,23 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { // Expected } + try { + db.transaction(true, transaction -> + db.containsAcksToSend(transaction, contactId)); + fail(); + } catch (NoSuchContactException expected) { + // Expected + } + + try { + db.transaction(true, transaction -> + db.containsMessagesToSend(transaction, contactId, + 123, true)); + fail(); + } catch (NoSuchContactException expected) { + // Expected + } + try { db.transaction(false, transaction -> db.generateAck(transaction, contactId, 123)); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java index 567a89c60..54d19da0d 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java @@ -378,9 +378,9 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { // Initially there should be nothing to send assertFalse( - db.containsAnythingToSend(txn, contactId, MAX_LATENCY, false)); + db.containsMessagesToSend(txn, contactId, MAX_LATENCY, false)); assertFalse( - db.containsAnythingToSend(txn, contactId, MAX_LATENCY, true)); + db.containsMessagesToSend(txn, contactId, MAX_LATENCY, true)); // Add some messages to ack Message message1 = getMessage(groupId); @@ -389,10 +389,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { db.addMessage(txn, message1, DELIVERED, true, false, contactId); // Both message IDs should be returned - assertTrue( - db.containsAnythingToSend(txn, contactId, MAX_LATENCY, false)); - assertTrue( - db.containsAnythingToSend(txn, contactId, MAX_LATENCY, true)); + assertTrue(db.containsAcksToSend(txn, contactId)); Collection ids = db.getMessagesToAck(txn, contactId, 1234); assertEquals(asList(messageId, messageId1), ids); @@ -400,10 +397,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { db.lowerAckFlag(txn, contactId, asList(messageId, messageId1)); // No message IDs should be returned - assertFalse( - db.containsAnythingToSend(txn, contactId, MAX_LATENCY, false)); - assertFalse( - db.containsAnythingToSend(txn, contactId, MAX_LATENCY, true)); + assertFalse(db.containsAcksToSend(txn, contactId)); assertEquals(emptyList(), db.getMessagesToAck(txn, contactId, 1234)); // Raise the ack flag again @@ -411,10 +405,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { db.raiseAckFlag(txn, contactId, messageId1); // Both message IDs should be returned - assertTrue( - db.containsAnythingToSend(txn, contactId, MAX_LATENCY, false)); - assertTrue( - db.containsAnythingToSend(txn, contactId, MAX_LATENCY, true)); + assertTrue(db.containsAcksToSend(txn, contactId)); ids = db.getMessagesToAck(txn, contactId, 1234); assertEquals(asList(messageId, messageId1), ids); @@ -2579,7 +2570,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { private void assertNothingToSendLazily(Database db, Connection txn) throws Exception { assertFalse( - db.containsAnythingToSend(txn, contactId, MAX_LATENCY, false)); + db.containsMessagesToSend(txn, contactId, MAX_LATENCY, false)); Collection ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY); assertTrue(ids.isEmpty()); @@ -2590,7 +2581,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { private void assertOneMessageToSendLazily(Database db, Connection txn) throws Exception { assertTrue( - db.containsAnythingToSend(txn, contactId, MAX_LATENCY, false)); + db.containsMessagesToSend(txn, contactId, MAX_LATENCY, false)); Collection ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY); assertEquals(singletonList(messageId), ids); @@ -2601,7 +2592,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { private void assertNothingToSendEagerly(Database db, Connection txn) throws Exception { assertFalse( - db.containsAnythingToSend(txn, contactId, MAX_LATENCY, true)); + db.containsMessagesToSend(txn, contactId, MAX_LATENCY, true)); Collection unacked = db.getUnackedMessagesToSend(txn, contactId); assertTrue(unacked.isEmpty()); @@ -2611,7 +2602,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { private void assertOneMessageToSendEagerly(Database db, Connection txn) throws Exception { assertTrue( - db.containsAnythingToSend(txn, contactId, MAX_LATENCY, true)); + db.containsMessagesToSend(txn, contactId, MAX_LATENCY, true)); Collection unacked = db.getUnackedMessagesToSend(txn, contactId); assertEquals(singletonList(messageId), unacked);