Add DB method for getting amount of data to sync.

This commit is contained in:
akwizgran
2021-05-05 17:52:37 +01:00
committed by Torsten Grote
parent f7fdf7745e
commit c5d6ee6782
6 changed files with 98 additions and 8 deletions

View File

@@ -292,6 +292,16 @@ public interface DatabaseComponent extends TransactionManager {
*/ */
Message getMessage(Transaction txn, MessageId m) throws DbException; 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.
* <p/>
* Read-only.
*/
long getMessageBytesToSend(Transaction txn, ContactId c, int maxLatency)
throws DbException;
/** /**
* Returns the IDs of all delivered messages in the given group. * Returns the IDs of all delivered messages in the given group.
* <p/> * <p/>

View File

@@ -347,6 +347,16 @@ interface Database<T> {
*/ */
Message getMessage(T txn, MessageId m) throws DbException; 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.
* <p/>
* Read-only.
*/
long getMessageBytesToSend(T txn, ContactId c, int maxLatency)
throws DbException;
/** /**
* Returns the IDs and states of all dependencies of the given message. * Returns the IDs and states of all dependencies of the given message.
* For missing dependencies and dependencies in other groups, the state * For missing dependencies and dependencies in other groups, the state

View File

@@ -575,6 +575,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.getMessage(txn, m); 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 @Override
public Collection<MessageId> getMessageIds(Transaction transaction, public Collection<MessageId> getMessageIds(Transaction transaction,
GroupId g) throws DbException { GroupId g) throws DbException {

View File

@@ -1758,6 +1758,37 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@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 @Override
public Collection<MessageId> getMessageIds(Connection txn, GroupId g) public Collection<MessageId> getMessageIds(Connection txn, GroupId g)
throws DbException { throws DbException {

View File

@@ -298,11 +298,11 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
throws Exception { throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check whether the contact is in the DB (which it's not) // 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)); will(returnValue(txn));
exactly(18).of(database).containsContact(txn, contactId); exactly(19).of(database).containsContact(txn, contactId);
will(returnValue(false)); will(returnValue(false));
exactly(18).of(database).abortTransaction(txn); exactly(19).of(database).abortTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, eventBus, DatabaseComponent db = createDatabaseComponent(database, eventBus,
eventExecutor, shutdownManager); eventExecutor, shutdownManager);
@@ -349,7 +349,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getContact(transaction, contactId)); db.getContact(transaction, contactId));
fail(); fail();
} catch (NoSuchContactException expected) { } catch (NoSuchContactException expected) {
@@ -357,7 +357,15 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { 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)); db.getMessageStatus(transaction, contactId, groupId));
fail(); fail();
} catch (NoSuchContactException expected) { } catch (NoSuchContactException expected) {
@@ -365,7 +373,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getMessageStatus(transaction, contactId, messageId)); db.getMessageStatus(transaction, contactId, messageId));
fail(); fail();
} catch (NoSuchContactException expected) { } catch (NoSuchContactException expected) {
@@ -373,7 +381,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getGroupVisibility(transaction, contactId, groupId)); db.getGroupVisibility(transaction, contactId, groupId));
fail(); fail();
} catch (NoSuchContactException expected) { } catch (NoSuchContactException expected) {
@@ -381,7 +389,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getSyncVersions(transaction, contactId)); db.getSyncVersions(transaction, contactId));
fail(); fail();
} catch (NoSuchContactException expected) { } catch (NoSuchContactException expected) {

View File

@@ -227,6 +227,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertEquals(singletonList(messageId), ids); assertEquals(singletonList(messageId), ids);
ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY);
assertEquals(singletonList(messageId), ids); assertEquals(singletonList(messageId), ids);
assertEquals(message.getRawLength(),
db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
// Changing the status to seen = true should make the message unsendable // Changing the status to seen = true should make the message unsendable
db.raiseSeenFlag(txn, contactId, messageId); db.raiseSeenFlag(txn, contactId, messageId);
@@ -234,6 +236,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
db.commitTransaction(txn); db.commitTransaction(txn);
db.close(); db.close();
@@ -258,6 +261,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
// Marking the message delivered should make it sendable // Marking the message delivered should make it sendable
db.setMessageState(txn, messageId, DELIVERED); db.setMessageState(txn, messageId, DELIVERED);
@@ -265,6 +269,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertEquals(singletonList(messageId), ids); assertEquals(singletonList(messageId), ids);
ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY);
assertEquals(singletonList(messageId), ids); assertEquals(singletonList(messageId), ids);
assertEquals(message.getRawLength(),
db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
// Marking the message invalid should make it unsendable // Marking the message invalid should make it unsendable
db.setMessageState(txn, messageId, INVALID); db.setMessageState(txn, messageId, INVALID);
@@ -272,6 +278,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
// Marking the message pending should make it unsendable // Marking the message pending should make it unsendable
db.setMessageState(txn, messageId, PENDING); db.setMessageState(txn, messageId, PENDING);
@@ -279,6 +286,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
db.commitTransaction(txn); db.commitTransaction(txn);
db.close(); db.close();
@@ -302,6 +310,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
// Making the group visible should not make the message sendable // Making the group visible should not make the message sendable
db.addGroupVisibility(txn, contactId, groupId, false); db.addGroupVisibility(txn, contactId, groupId, false);
@@ -309,6 +318,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
// Sharing the group should make the message sendable // Sharing the group should make the message sendable
db.setGroupVisibility(txn, contactId, groupId, true); db.setGroupVisibility(txn, contactId, groupId, true);
@@ -316,6 +326,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertEquals(singletonList(messageId), ids); assertEquals(singletonList(messageId), ids);
ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY);
assertEquals(singletonList(messageId), ids); assertEquals(singletonList(messageId), ids);
assertEquals(message.getRawLength(),
db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
// Unsharing the group should make the message unsendable // Unsharing the group should make the message unsendable
db.setGroupVisibility(txn, contactId, groupId, false); db.setGroupVisibility(txn, contactId, groupId, false);
@@ -323,6 +335,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
// Making the group invisible should make the message unsendable // Making the group invisible should make the message unsendable
db.removeGroupVisibility(txn, contactId, groupId); db.removeGroupVisibility(txn, contactId, groupId);
@@ -330,6 +343,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
db.commitTransaction(txn); db.commitTransaction(txn);
db.close(); db.close();
@@ -354,6 +368,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
assertEquals(0, db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
// Sharing the message should make it sendable // Sharing the message should make it sendable
db.setMessageShared(txn, messageId, true); db.setMessageShared(txn, messageId, true);
@@ -361,6 +376,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertEquals(singletonList(messageId), ids); assertEquals(singletonList(messageId), ids);
ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY);
assertEquals(singletonList(messageId), ids); assertEquals(singletonList(messageId), ids);
assertEquals(message.getRawLength(),
db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
db.commitTransaction(txn); db.commitTransaction(txn);
db.close(); db.close();
@@ -384,10 +401,15 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
db.getMessagesToSend(txn, contactId, message.getRawLength() - 1, db.getMessagesToSend(txn, contactId, message.getRawLength() - 1,
MAX_LATENCY); MAX_LATENCY);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
assertEquals(message.getRawLength(),
db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
// The message is just the right size to send // The message is just the right size to send
ids = db.getMessagesToSend(txn, contactId, message.getRawLength(), ids = db.getMessagesToSend(txn, contactId, message.getRawLength(),
MAX_LATENCY); MAX_LATENCY);
assertEquals(singletonList(messageId), ids); assertEquals(singletonList(messageId), ids);
assertEquals(message.getRawLength(),
db.getMessageBytesToSend(txn, contactId, MAX_LATENCY));
db.commitTransaction(txn); db.commitTransaction(txn);
db.close(); db.close();