Split containsAnythingToSend() into methods for acks and messages.

This commit is contained in:
akwizgran
2022-06-15 14:48:53 +01:00
parent 356e0ee07b
commit 924425522a
7 changed files with 114 additions and 69 deletions

View File

@@ -126,16 +126,11 @@ public interface DatabaseComponent extends TransactionManager {
TransportKeys k) throws DbException; TransportKeys k) throws DbException;
/** /**
* Returns true if there are any acks or messages to send to the given * Returns true if there are any acks to send to the given contact.
* contact over a transport with the given maximum latency.
* <p/> * <p/>
* Read-only. * Read-only.
*
* @param eager True if messages that are not yet due for retransmission
* should be included
*/ */
boolean containsAnythingToSend(Transaction txn, ContactId c, boolean containsAcksToSend(Transaction txn, ContactId c) throws DbException;
long maxLatency, boolean eager) throws DbException;
/** /**
* Returns true if the database contains the given contact for the given * 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; 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.
* <p/>
* 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. * Returns true if the database contains the given pending contact.
* <p/> * <p/>

View File

@@ -163,16 +163,11 @@ interface Database<T> {
throws DbException; throws DbException;
/** /**
* Returns true if there are any acks or messages to send to the given * Returns true if there are any acks to send to the given contact.
* contact over a transport with the given maximum latency.
* <p/> * <p/>
* Read-only. * 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 containsAcksToSend(T txn, ContactId c) throws DbException;
boolean eager) throws DbException;
/** /**
* Returns true if the database contains the given contact for the given * Returns true if the database contains the given contact for the given
@@ -212,6 +207,18 @@ interface Database<T> {
*/ */
boolean containsMessage(T txn, MessageId m) throws DbException; 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.
* <p/>
* 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. * Returns true if the database contains the given pending contact.
* <p/> * <p/>

View File

@@ -342,12 +342,12 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} }
@Override @Override
public boolean containsAnythingToSend(Transaction transaction, ContactId c, public boolean containsAcksToSend(Transaction transaction, ContactId c)
long maxLatency, boolean eager) throws DbException { throws DbException {
T txn = unbox(transaction); T txn = unbox(transaction);
if (!db.containsContact(txn, c)) if (!db.containsContact(txn, c))
throw new NoSuchContactException(); throw new NoSuchContactException();
return db.containsAnythingToSend(txn, c, maxLatency, eager); return db.containsAcksToSend(txn, c);
} }
@Override @Override
@@ -373,6 +373,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.containsIdentity(txn, a); 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 @Override
public boolean containsPendingContact(Transaction transaction, public boolean containsPendingContact(Transaction transaction,
PendingContactId p) throws DbException { PendingContactId p) throws DbException {

View File

@@ -1147,8 +1147,8 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
@Override @Override
public boolean containsAnythingToSend(Connection txn, ContactId c, public boolean containsAcksToSend(Connection txn, ContactId c)
long maxLatency, boolean eager) throws DbException { throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
@@ -1160,34 +1160,7 @@ abstract class JdbcDatabase implements Database<Connection> {
boolean acksToSend = rs.next(); boolean acksToSend = rs.next();
rs.close(); rs.close();
ps.close(); ps.close();
if (acksToSend) return true; return acksToSend;
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;
} catch (SQLException e) { } catch (SQLException e) {
tryToClose(rs, LOG, WARNING); tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING); tryToClose(ps, LOG, WARNING);
@@ -1307,6 +1280,46 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@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 @Override
public boolean containsPendingContact(Connection txn, PendingContactId p) public boolean containsPendingContact(Connection txn, PendingContactId p)
throws DbException { throws DbException {

View File

@@ -106,7 +106,8 @@ class RemovableDriveManagerImpl
@Override @Override
public boolean isWriterTaskNeeded(ContactId c) throws DbException { public boolean isWriterTaskNeeded(ContactId c) throws DbException {
return db.transactionWithResult(true, txn -> return db.transactionWithResult(true, txn ->
db.containsAnythingToSend(txn, c, MAX_LATENCY, true)); db.containsAcksToSend(txn, c) ||
db.containsMessagesToSend(txn, c, MAX_LATENCY, true));
} }
@Override @Override

View File

@@ -303,11 +303,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(25).of(database).startTransaction(); exactly(27).of(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
exactly(25).of(database).containsContact(txn, contactId); exactly(27).of(database).containsContact(txn, contactId);
will(returnValue(false)); will(returnValue(false));
exactly(25).of(database).abortTransaction(txn); exactly(27).of(database).abortTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, eventBus, DatabaseComponent db = createDatabaseComponent(database, eventBus,
eventExecutor, shutdownManager); eventExecutor, shutdownManager);
@@ -321,6 +321,23 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
// Expected // 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 { try {
db.transaction(false, transaction -> db.transaction(false, transaction ->
db.generateAck(transaction, contactId, 123)); db.generateAck(transaction, contactId, 123));

View File

@@ -378,9 +378,9 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Initially there should be nothing to send // Initially there should be nothing to send
assertFalse( assertFalse(
db.containsAnythingToSend(txn, contactId, MAX_LATENCY, false)); db.containsMessagesToSend(txn, contactId, MAX_LATENCY, false));
assertFalse( assertFalse(
db.containsAnythingToSend(txn, contactId, MAX_LATENCY, true)); db.containsMessagesToSend(txn, contactId, MAX_LATENCY, true));
// Add some messages to ack // Add some messages to ack
Message message1 = getMessage(groupId); Message message1 = getMessage(groupId);
@@ -389,10 +389,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
db.addMessage(txn, message1, DELIVERED, true, false, contactId); db.addMessage(txn, message1, DELIVERED, true, false, contactId);
// Both message IDs should be returned // Both message IDs should be returned
assertTrue( assertTrue(db.containsAcksToSend(txn, contactId));
db.containsAnythingToSend(txn, contactId, MAX_LATENCY, false));
assertTrue(
db.containsAnythingToSend(txn, contactId, MAX_LATENCY, true));
Collection<MessageId> ids = db.getMessagesToAck(txn, contactId, 1234); Collection<MessageId> ids = db.getMessagesToAck(txn, contactId, 1234);
assertEquals(asList(messageId, messageId1), ids); assertEquals(asList(messageId, messageId1), ids);
@@ -400,10 +397,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
db.lowerAckFlag(txn, contactId, asList(messageId, messageId1)); db.lowerAckFlag(txn, contactId, asList(messageId, messageId1));
// No message IDs should be returned // No message IDs should be returned
assertFalse( assertFalse(db.containsAcksToSend(txn, contactId));
db.containsAnythingToSend(txn, contactId, MAX_LATENCY, false));
assertFalse(
db.containsAnythingToSend(txn, contactId, MAX_LATENCY, true));
assertEquals(emptyList(), db.getMessagesToAck(txn, contactId, 1234)); assertEquals(emptyList(), db.getMessagesToAck(txn, contactId, 1234));
// Raise the ack flag again // Raise the ack flag again
@@ -411,10 +405,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
db.raiseAckFlag(txn, contactId, messageId1); db.raiseAckFlag(txn, contactId, messageId1);
// Both message IDs should be returned // Both message IDs should be returned
assertTrue( assertTrue(db.containsAcksToSend(txn, contactId));
db.containsAnythingToSend(txn, contactId, MAX_LATENCY, false));
assertTrue(
db.containsAnythingToSend(txn, contactId, MAX_LATENCY, true));
ids = db.getMessagesToAck(txn, contactId, 1234); ids = db.getMessagesToAck(txn, contactId, 1234);
assertEquals(asList(messageId, messageId1), ids); assertEquals(asList(messageId, messageId1), ids);
@@ -2579,7 +2570,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
private void assertNothingToSendLazily(Database<Connection> db, private void assertNothingToSendLazily(Database<Connection> db,
Connection txn) throws Exception { Connection txn) throws Exception {
assertFalse( assertFalse(
db.containsAnythingToSend(txn, contactId, MAX_LATENCY, false)); db.containsMessagesToSend(txn, contactId, MAX_LATENCY, false));
Collection<MessageId> ids = Collection<MessageId> ids =
db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY); db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY);
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
@@ -2590,7 +2581,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
private void assertOneMessageToSendLazily(Database<Connection> db, private void assertOneMessageToSendLazily(Database<Connection> db,
Connection txn) throws Exception { Connection txn) throws Exception {
assertTrue( assertTrue(
db.containsAnythingToSend(txn, contactId, MAX_LATENCY, false)); db.containsMessagesToSend(txn, contactId, MAX_LATENCY, false));
Collection<MessageId> ids = Collection<MessageId> ids =
db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY); db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY);
assertEquals(singletonList(messageId), ids); assertEquals(singletonList(messageId), ids);
@@ -2601,7 +2592,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
private void assertNothingToSendEagerly(Database<Connection> db, private void assertNothingToSendEagerly(Database<Connection> db,
Connection txn) throws Exception { Connection txn) throws Exception {
assertFalse( assertFalse(
db.containsAnythingToSend(txn, contactId, MAX_LATENCY, true)); db.containsMessagesToSend(txn, contactId, MAX_LATENCY, true));
Collection<MessageId> unacked = Collection<MessageId> unacked =
db.getUnackedMessagesToSend(txn, contactId); db.getUnackedMessagesToSend(txn, contactId);
assertTrue(unacked.isEmpty()); assertTrue(unacked.isEmpty());
@@ -2611,7 +2602,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
private void assertOneMessageToSendEagerly(Database<Connection> db, private void assertOneMessageToSendEagerly(Database<Connection> db,
Connection txn) throws Exception { Connection txn) throws Exception {
assertTrue( assertTrue(
db.containsAnythingToSend(txn, contactId, MAX_LATENCY, true)); db.containsMessagesToSend(txn, contactId, MAX_LATENCY, true));
Collection<MessageId> unacked = Collection<MessageId> unacked =
db.getUnackedMessagesToSend(txn, contactId); db.getUnackedMessagesToSend(txn, contactId);
assertEquals(singletonList(messageId), unacked); assertEquals(singletonList(messageId), unacked);