Group messages by group ID when fetching them from database.

This commit is contained in:
akwizgran
2021-02-26 12:45:26 +00:00
committed by Torsten Grote
parent 56e0d62597
commit 43b437af92
6 changed files with 30 additions and 39 deletions

View File

@@ -342,7 +342,7 @@ public interface DatabaseComponent extends TransactionManager {
* <p/> * <p/>
* Read-only. * Read-only.
*/ */
Map<MessageId, GroupId> getMessagesToDelete(Transaction txn) Map<GroupId, Collection<MessageId>> getMessagesToDelete(Transaction txn)
throws DbException; throws DbException;
/** /**

View File

@@ -20,9 +20,7 @@ import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.TaskScheduler; import org.briarproject.bramble.api.system.TaskScheduler;
import org.briarproject.bramble.api.versioning.ClientMajorVersion; import org.briarproject.bramble.api.versioning.ClientMajorVersion;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@@ -132,39 +130,25 @@ class CleanupManagerImpl implements CleanupManager, Service, EventListener {
} }
private void deleteMessages(Transaction txn) throws DbException { private void deleteMessages(Transaction txn) throws DbException {
Map<GroupId, ClientMajorVersion> clientCache = new HashMap<>(); Map<GroupId, Collection<MessageId>> ids = db.getMessagesToDelete(txn);
Map<GroupId, Collection<MessageId>> deleted = new HashMap<>(); for (Entry<GroupId, Collection<MessageId>> e : ids.entrySet()) {
Map<MessageId, GroupId> ids = db.getMessagesToDelete(txn); GroupId groupId = e.getKey();
if (LOG.isLoggable(INFO)) LOG.info(ids.size() + " messages to delete"); Collection<MessageId> messageIds = e.getValue();
for (Entry<MessageId, GroupId> e : ids.entrySet()) { if (LOG.isLoggable(INFO)) {
MessageId m = e.getKey(); LOG.info(messageIds.size() + " messages to delete");
GroupId g = e.getValue();
ClientMajorVersion cv = clientCache.get(g);
if (cv == null) {
Group group = db.getGroup(txn, g);
cv = new ClientMajorVersion(group.getClientId(),
group.getMajorVersion());
clientCache.put(g, cv);
} }
Group group = db.getGroup(txn, groupId);
ClientMajorVersion cv = new ClientMajorVersion(group.getClientId(),
group.getMajorVersion());
CleanupHook hook = hooks.get(cv); CleanupHook hook = hooks.get(cv);
if (hook == null) { if (hook == null) {
throw new IllegalStateException("No cleanup hook for " + cv); throw new IllegalStateException("No cleanup hook for " + cv);
} }
if (hook.deleteMessage(txn, g, m)) { for (MessageId m : messageIds) {
Collection<MessageId> messageIds = deleted.get(g); hook.deleteMessage(txn, groupId, m);
if (messageIds == null) {
messageIds = new ArrayList<>();
deleted.put(g, messageIds);
}
messageIds.add(m);
} else {
LOG.info("Message was not deleted");
// Stop the timer so we don't keep trying to delete this message
db.stopCleanupTimer(txn, m); db.stopCleanupTimer(txn, m);
} }
} txn.attach(new MessagesCleanedUpEvent(groupId, messageIds));
for (Entry<GroupId, Collection<MessageId>> e : deleted.entrySet()) {
txn.attach(new MessagesCleanedUpEvent(e.getKey(), e.getValue()));
} }
} }

View File

@@ -510,7 +510,8 @@ interface Database<T> {
* <p/> * <p/>
* Read-only. * Read-only.
*/ */
Map<MessageId, GroupId> getMessagesToDelete(T txn) throws DbException; Map<GroupId, Collection<MessageId>> getMessagesToDelete(T txn)
throws DbException;
/** /**
* Returns the next time (in milliseconds since the Unix epoch) when a * Returns the next time (in milliseconds since the Unix epoch) when a

View File

@@ -608,8 +608,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} }
@Override @Override
public Map<MessageId, GroupId> getMessagesToDelete(Transaction transaction) public Map<GroupId, Collection<MessageId>> getMessagesToDelete(
throws DbException { Transaction transaction) throws DbException {
T txn = unbox(transaction); T txn = unbox(transaction);
return db.getMessagesToDelete(txn); return db.getMessagesToDelete(txn);
} }

View File

@@ -2268,8 +2268,8 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
@Override @Override
public Map<MessageId, GroupId> getMessagesToDelete(Connection txn) public Map<GroupId, Collection<MessageId>> getMessagesToDelete(
throws DbException { Connection txn) throws DbException {
long now = clock.currentTimeMillis(); long now = clock.currentTimeMillis();
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
@@ -2279,10 +2279,16 @@ abstract class JdbcDatabase implements Database<Connection> {
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setLong(1, now); ps.setLong(1, now);
rs = ps.executeQuery(); rs = ps.executeQuery();
Map<MessageId, GroupId> ids = new HashMap<>(); Map<GroupId, Collection<MessageId>> ids = new HashMap<>();
while (rs.next()) { while (rs.next()) {
ids.put(new MessageId(rs.getBytes(1)), MessageId m = new MessageId(rs.getBytes(1));
new GroupId(rs.getBytes(2))); GroupId g = new GroupId(rs.getBytes(2));
Collection<MessageId> messageIds = ids.get(g);
if (messageIds == null) {
messageIds = new ArrayList<>();
ids.put(g, messageIds);
}
messageIds.add(m);
} }
rs.close(); rs.close();
ps.close(); ps.close();

View File

@@ -2474,14 +2474,14 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// When the timer expires, the message should be due and scheduled for // When the timer expires, the message should be due and scheduled for
// deletion // deletion
time.set(now + duration); time.set(now + duration);
assertEquals(singletonMap(messageId, groupId), assertEquals(singletonMap(groupId, singletonList(messageId)),
db.getMessagesToDelete(txn)); db.getMessagesToDelete(txn));
assertEquals(now + duration, db.getNextCleanupDeadline(txn)); assertEquals(now + duration, db.getNextCleanupDeadline(txn));
// 1 ms after the timer expires, the message should be due and // 1 ms after the timer expires, the message should be due and
// scheduled for deletion // scheduled for deletion
time.set(now + duration + 1); time.set(now + duration + 1);
assertEquals(singletonMap(messageId, groupId), assertEquals(singletonMap(groupId, singletonList(messageId)),
db.getMessagesToDelete(txn)); db.getMessagesToDelete(txn));
assertEquals(now + duration, db.getNextCleanupDeadline(txn)); assertEquals(now + duration, db.getNextCleanupDeadline(txn));