From f7875c99b6961a6951c6dce2c11d2492e86b60b5 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Wed, 5 May 2021 17:52:37 +0100 Subject: [PATCH] Add DB method for getting amount of data to sync. --- .../bramble/api/db/DatabaseComponent.java | 10 ++++++ .../org/briarproject/bramble/db/Database.java | 10 ++++++ .../bramble/db/DatabaseComponentImpl.java | 9 ++++++ .../briarproject/bramble/db/JdbcDatabase.java | 31 +++++++++++++++++++ .../bramble/db/DatabaseComponentImplTest.java | 24 +++++++++----- .../bramble/db/JdbcDatabaseTest.java | 22 +++++++++++++ 6 files changed, 98 insertions(+), 8 deletions(-) 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 b5cf1d617..3c79254d3 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 @@ -292,6 +292,16 @@ public interface DatabaseComponent extends TransactionManager { */ Message getMessage(Transaction txn, MessageId m) throws DbException; + /** + * Returns the total length, including headers, of any messages that are + * eligible to be sent to the given contact via a transport with the given + * max latency. + *

+ * Read-only. + */ + long getMessageBytesToSend(Transaction txn, ContactId c, int maxLatency) + throws DbException; + /** * Returns the IDs of all delivered messages in the given group. *

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 b6832d1e9..ab291fa30 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 @@ -347,6 +347,16 @@ interface Database { */ Message getMessage(T txn, MessageId m) throws DbException; + /** + * Returns the total length, including headers, of any messages that are + * eligible to be sent to the given contact via a transport with the given + * max latency. + *

+ * Read-only. + */ + long getMessageBytesToSend(T txn, ContactId c, int maxLatency) + throws DbException; + /** * Returns the IDs and states of all dependencies of the given message. * For missing dependencies and dependencies in other groups, the state 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 3bb052fe9..9cd1acbc9 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 @@ -569,6 +569,15 @@ class DatabaseComponentImpl implements DatabaseComponent { return db.getMessage(txn, m); } + @Override + public long getMessageBytesToSend(Transaction transaction, ContactId c, + int maxLatency) throws DbException { + T txn = unbox(transaction); + if (!db.containsContact(txn, c)) + throw new NoSuchContactException(); + return db.getMessageBytesToSend(txn, c, maxLatency); + } + @Override public Collection getMessageIds(Transaction transaction, GroupId g) 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 72ceec594..af54d4e9d 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 @@ -1758,6 +1758,37 @@ abstract class JdbcDatabase implements Database { } } + @Override + public long getMessageBytesToSend(Connection txn, ContactId c, + int maxLatency) throws DbException { + long now = clock.currentTimeMillis(); + long eta = now + maxLatency; + PreparedStatement ps = null; + ResultSet rs = null; + try { + String sql = "SELECT SUM(length) FROM statuses" + + " WHERE contactId = ? AND state = ?" + + " AND groupShared = TRUE AND messageShared = TRUE" + + " AND deleted = FALSE AND seen = FALSE" + + " AND (expiry <= ? OR eta > ?)"; + ps = txn.prepareStatement(sql); + ps.setInt(1, c.getInt()); + ps.setInt(2, DELIVERED.getValue()); + ps.setLong(3, now); + ps.setLong(4, eta); + rs = ps.executeQuery(); + rs.next(); + long total = rs.getInt(1); + rs.close(); + ps.close(); + return total; + } catch (SQLException e) { + tryToClose(rs, LOG, WARNING); + tryToClose(ps, LOG, WARNING); + throw new DbException(e); + } + } + @Override public Collection getMessageIds(Connection txn, GroupId g) throws DbException { 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 39615b2e5..4b53a781d 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 @@ -298,11 +298,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(18).of(database).startTransaction(); + exactly(19).of(database).startTransaction(); will(returnValue(txn)); - exactly(18).of(database).containsContact(txn, contactId); + exactly(19).of(database).containsContact(txn, contactId); will(returnValue(false)); - exactly(18).of(database).abortTransaction(txn); + exactly(19).of(database).abortTransaction(txn); }}); DatabaseComponent db = createDatabaseComponent(database, eventBus, eventExecutor, shutdownManager); @@ -349,7 +349,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { } try { - db.transaction(false, transaction -> + db.transaction(true, transaction -> db.getContact(transaction, contactId)); fail(); } catch (NoSuchContactException expected) { @@ -357,7 +357,15 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { } try { - db.transaction(false, transaction -> + db.transaction(true, transaction -> + db.getMessageBytesToSend(transaction, contactId, 123)); + fail(); + } catch (NoSuchContactException expected) { + // Expected + } + + try { + db.transaction(true, transaction -> db.getMessageStatus(transaction, contactId, groupId)); fail(); } catch (NoSuchContactException expected) { @@ -365,7 +373,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { } try { - db.transaction(false, transaction -> + db.transaction(true, transaction -> db.getMessageStatus(transaction, contactId, messageId)); fail(); } catch (NoSuchContactException expected) { @@ -373,7 +381,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { } try { - db.transaction(false, transaction -> + db.transaction(true, transaction -> db.getGroupVisibility(transaction, contactId, groupId)); fail(); } catch (NoSuchContactException expected) { @@ -381,7 +389,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { } try { - db.transaction(false, transaction -> + db.transaction(true, transaction -> db.getSyncVersions(transaction, contactId)); fail(); } catch (NoSuchContactException expected) { 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 4dfec5fce..69bc97671 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 @@ -227,6 +227,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { assertEquals(singletonList(messageId), ids); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); assertEquals(singletonList(messageId), ids); + assertEquals(message.getRawLength(), + db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); // Changing the status to seen = true should make the message unsendable db.raiseSeenFlag(txn, contactId, messageId); @@ -234,6 +236,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { assertTrue(ids.isEmpty()); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); assertTrue(ids.isEmpty()); + assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); db.commitTransaction(txn); db.close(); @@ -258,6 +261,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { assertTrue(ids.isEmpty()); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); assertTrue(ids.isEmpty()); + assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); // Marking the message delivered should make it sendable db.setMessageState(txn, messageId, DELIVERED); @@ -265,6 +269,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { assertEquals(singletonList(messageId), ids); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); assertEquals(singletonList(messageId), ids); + assertEquals(message.getRawLength(), + db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); // Marking the message invalid should make it unsendable db.setMessageState(txn, messageId, INVALID); @@ -272,6 +278,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { assertTrue(ids.isEmpty()); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); assertTrue(ids.isEmpty()); + assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); // Marking the message pending should make it unsendable db.setMessageState(txn, messageId, PENDING); @@ -279,6 +286,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { assertTrue(ids.isEmpty()); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); assertTrue(ids.isEmpty()); + assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); db.commitTransaction(txn); db.close(); @@ -302,6 +310,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { assertTrue(ids.isEmpty()); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); assertTrue(ids.isEmpty()); + assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); // Making the group visible should not make the message sendable db.addGroupVisibility(txn, contactId, groupId, false); @@ -309,6 +318,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { assertTrue(ids.isEmpty()); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); assertTrue(ids.isEmpty()); + assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); // Sharing the group should make the message sendable db.setGroupVisibility(txn, contactId, groupId, true); @@ -316,6 +326,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { assertEquals(singletonList(messageId), ids); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); assertEquals(singletonList(messageId), ids); + assertEquals(message.getRawLength(), + db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); // Unsharing the group should make the message unsendable db.setGroupVisibility(txn, contactId, groupId, false); @@ -323,6 +335,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { assertTrue(ids.isEmpty()); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); assertTrue(ids.isEmpty()); + assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); // Making the group invisible should make the message unsendable db.removeGroupVisibility(txn, contactId, groupId); @@ -330,6 +343,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { assertTrue(ids.isEmpty()); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); assertTrue(ids.isEmpty()); + assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); db.commitTransaction(txn); db.close(); @@ -354,6 +368,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { assertTrue(ids.isEmpty()); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); assertTrue(ids.isEmpty()); + assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); // Sharing the message should make it sendable db.setMessageShared(txn, messageId, true); @@ -361,6 +376,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { assertEquals(singletonList(messageId), ids); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); assertEquals(singletonList(messageId), ids); + assertEquals(message.getRawLength(), + db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); db.commitTransaction(txn); db.close(); @@ -384,10 +401,15 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { db.getMessagesToSend(txn, contactId, message.getRawLength() - 1, MAX_LATENCY); assertTrue(ids.isEmpty()); + assertEquals(message.getRawLength(), + db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); + // The message is just the right size to send ids = db.getMessagesToSend(txn, contactId, message.getRawLength(), MAX_LATENCY); assertEquals(singletonList(messageId), ids); + assertEquals(message.getRawLength(), + db.getMessageBytesToSend(txn, contactId, MAX_LATENCY)); db.commitTransaction(txn); db.close();