diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java b/bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java index c4fb1b41f..396168d2a 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/client/ClientHelper.java @@ -17,6 +17,7 @@ import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.MessageId; import java.security.GeneralSecurityException; +import java.util.Collection; import java.util.Map; @NotNullByDefault @@ -51,9 +52,11 @@ public interface ClientHelper { BdfDictionary getGroupMetadataAsDictionary(Transaction txn, GroupId g) throws DbException, FormatException; + Collection getMessageIds(Transaction txn, GroupId g, + BdfDictionary query) throws DbException, FormatException; + BdfDictionary getMessageMetadataAsDictionary(MessageId m) - throws DbException, - FormatException; + throws DbException, FormatException; BdfDictionary getMessageMetadataAsDictionary(Transaction txn, MessageId m) throws DbException, FormatException; 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 7c525bcd3..3a8046bb6 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 @@ -288,6 +288,16 @@ public interface DatabaseComponent extends TransactionManager { Collection getMessageIds(Transaction txn, GroupId g) throws DbException; + /** + * Returns the IDs of any delivered messages in the given group with + * metadata that matches all entries in the given query. If the query is + * empty, the IDs of all delivered messages are returned. + *

+ * Read-only. + */ + Collection getMessageIds(Transaction txn, GroupId g, + Metadata query) throws DbException; + /** * Returns the IDs of any messages that need to be validated. *

diff --git a/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java index a92aecde5..f483acdc8 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/client/ClientHelperImpl.java @@ -34,6 +34,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.GeneralSecurityException; +import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -154,6 +155,12 @@ class ClientHelperImpl implements ClientHelper { return metadataParser.parse(metadata); } + @Override + public Collection getMessageIds(Transaction txn, GroupId g, + BdfDictionary query) throws DbException, FormatException { + return db.getMessageIds(txn, g, metadataEncoder.encode(query)); + } + @Override public BdfDictionary getMessageMetadataAsDictionary(MessageId m) throws DbException, FormatException { 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 6ec1760af..6bc18af7b 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 @@ -576,6 +576,15 @@ class DatabaseComponentImpl implements DatabaseComponent { return db.getMessageIds(txn, g); } + @Override + public Collection getMessageIds(Transaction transaction, + GroupId g, Metadata query) throws DbException { + T txn = unbox(transaction); + if (!db.containsGroup(txn, g)) + throw new NoSuchGroupException(); + return db.getMessageIds(txn, g, query); + } + @Override public Collection getMessagesToValidate(Transaction transaction) 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 b8fb04bc8..dd6c4efc0 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 @@ -510,11 +510,11 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { throws Exception { context.checking(new Expectations() {{ // Check whether the group is in the DB (which it's not) - exactly(8).of(database).startTransaction(); + exactly(10).of(database).startTransaction(); will(returnValue(txn)); - exactly(8).of(database).containsGroup(txn, groupId); + exactly(10).of(database).containsGroup(txn, groupId); will(returnValue(false)); - exactly(8).of(database).abortTransaction(txn); + exactly(10).of(database).abortTransaction(txn); // Allow other checks to pass allowing(database).containsContact(txn, contactId); will(returnValue(true)); @@ -523,7 +523,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { eventExecutor, shutdownManager); try { - db.transaction(false, transaction -> + db.transaction(true, transaction -> db.getGroup(transaction, groupId)); fail(); } catch (NoSuchGroupException expected) { @@ -531,7 +531,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { } try { - db.transaction(false, transaction -> + db.transaction(true, transaction -> db.getGroupMetadata(transaction, groupId)); fail(); } catch (NoSuchGroupException expected) { @@ -539,7 +539,23 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { } try { - db.transaction(false, transaction -> + db.transaction(true, transaction -> + db.getMessageIds(transaction, groupId)); + fail(); + } catch (NoSuchGroupException expected) { + // Expected + } + + try { + db.transaction(true, transaction -> + db.getMessageIds(transaction, groupId, new Metadata())); + fail(); + } catch (NoSuchGroupException expected) { + // Expected + } + + try { + db.transaction(true, transaction -> db.getMessageMetadata(transaction, groupId)); fail(); } catch (NoSuchGroupException expected) { @@ -547,7 +563,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { } try { - db.transaction(false, transaction -> + db.transaction(true, transaction -> db.getMessageMetadata(transaction, groupId, new Metadata())); fail(); @@ -556,7 +572,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { } try { - db.transaction(false, transaction -> + db.transaction(true, transaction -> db.getMessageStatus(transaction, contactId, groupId)); fail(); } catch (NoSuchGroupException expected) { diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java index bd978f746..9475f5bdf 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroduceeProtocolEngine.java @@ -38,6 +38,7 @@ import org.briarproject.briar.api.introduction.event.IntroductionAbortedEvent; import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent; import java.security.GeneralSecurityException; +import java.util.Collection; import java.util.Map; import java.util.logging.Logger; @@ -587,10 +588,9 @@ class IntroduceeProtocolEngine BdfDictionary query = messageParser .getRequestsAvailableToAnswerQuery(s.getSessionId()); try { - Map results = - clientHelper.getMessageMetadataAsDictionary(txn, - s.getContactGroupId(), query); - for (MessageId m : results.keySet()) + Collection results = clientHelper.getMessageIds(txn, + s.getContactGroupId(), query); + for (MessageId m : results) markRequestAvailableToAnswer(txn, m, false); } catch (FormatException e) { throw new AssertionError(e); diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java index f3c232330..8d8a68a7a 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java @@ -494,15 +494,14 @@ class IntroductionManagerImpl extends ConversationClientImpl Contact introducer) throws DbException { BdfDictionary query = sessionEncoder .getIntroduceeSessionsByIntroducerQuery(introducer.getAuthor()); - Map sessions; + Collection sessionIds; try { - sessions = clientHelper - .getMessageMetadataAsDictionary(txn, localGroup.getId(), - query); + sessionIds = clientHelper.getMessageIds(txn, localGroup.getId(), + query); } catch (FormatException e) { throw new DbException(e); } - for (MessageId id : sessions.keySet()) { + for (MessageId id : sessionIds) { db.removeMessage(txn, id); } } @@ -708,9 +707,7 @@ class IntroductionManagerImpl extends ConversationClientImpl GroupId g = getContactGroup(db.getContact(txn, c)).getId(); BdfDictionary query = messageParser.getMessagesVisibleInUiQuery(); try { - Map results = - clientHelper.getMessageMetadataAsDictionary(txn, g, query); - return results.keySet(); + return new HashSet<>(clientHelper.getMessageIds(txn, g, query)); } catch (FormatException e) { throw new DbException(e); } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java index d11db5bbb..b52156ecd 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/AbstractProtocolEngine.java @@ -27,7 +27,7 @@ import org.briarproject.briar.api.privategroup.PrivateGroupFactory; import org.briarproject.briar.api.privategroup.PrivateGroupManager; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager; -import java.util.Map; +import java.util.Collection; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; @@ -237,10 +237,9 @@ abstract class AbstractProtocolEngine> GroupId privateGroupId = session.getPrivateGroupId(); BdfDictionary query = messageParser.getInvitesAvailableToAnswerQuery(privateGroupId); - Map results = - clientHelper.getMessageMetadataAsDictionary(txn, - session.getContactGroupId(), query); - for (MessageId m : results.keySet()) + Collection results = clientHelper.getMessageIds(txn, + session.getContactGroupId(), query); + for (MessageId m : results) markMessageAvailableToAnswer(txn, m, false); } diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java index b0243fa2f..c34a23c3e 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImpl.java @@ -437,10 +437,9 @@ class GroupInvitationManagerImpl extends ConversationClientImpl // Look up the available invite messages for each contact for (Contact c : db.getContacts(txn)) { GroupId contactGroupId = getContactGroup(c).getId(); - Map results = - clientHelper.getMessageMetadataAsDictionary(txn, - contactGroupId, query); - for (MessageId m : results.keySet()) + Collection results = clientHelper.getMessageIds(txn, + contactGroupId, query); + for (MessageId m : results) items.add(parseGroupInvitationItem(txn, c, m)); } db.commitTransaction(txn); @@ -769,9 +768,7 @@ class GroupInvitationManagerImpl extends ConversationClientImpl GroupId g = getContactGroup(db.getContact(txn, c)).getId(); BdfDictionary query = messageParser.getMessagesVisibleInUiQuery(); try { - Map results = - clientHelper.getMessageMetadataAsDictionary(txn, g, query); - return results.keySet(); + return new HashSet<>(clientHelper.getMessageIds(txn, g, query)); } catch (FormatException e) { throw new DbException(e); } diff --git a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java index 63803c341..8ebfbadcf 100644 --- a/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/sharing/SharingManagerImpl.java @@ -690,9 +690,7 @@ abstract class SharingManagerImpl GroupId g = getContactGroup(db.getContact(txn, c)).getId(); BdfDictionary query = messageParser.getMessagesVisibleInUiQuery(); try { - Map results = - clientHelper.getMessageMetadataAsDictionary(txn, g, query); - return results.keySet(); + return new HashSet<>(clientHelper.getMessageIds(txn, g, query)); } catch (FormatException e) { throw new DbException(e); } diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java index 51c5c1592..3785a649e 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java @@ -720,10 +720,8 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase { public void testGetInvitations() throws Exception { BdfDictionary query = BdfDictionary.of(new BdfEntry("q", "u")); Message message2 = getMessage(contactGroup.getId()); - BdfDictionary meta2 = BdfDictionary.of(new BdfEntry("m2", "e")); - Map results = new HashMap<>(); - results.put(message.getId(), meta); - results.put(message2.getId(), meta2); + Collection results = + asList(message.getId(), message2.getId()); long time1 = 1L, time2 = 2L; String groupName = getRandomString(MAX_GROUP_NAME_LENGTH); byte[] salt = getRandomBytes(GROUP_SALT_LENGTH); @@ -748,8 +746,7 @@ public class GroupInvitationManagerImplTest extends BrambleMockTestCase { oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, MAJOR_VERSION, contact); will(returnValue(contactGroup)); - oneOf(clientHelper).getMessageMetadataAsDictionary(txn, - contactGroup.getId(), query); + oneOf(clientHelper).getMessageIds(txn, contactGroup.getId(), query); will(returnValue(results)); // message 1 oneOf(messageParser).getInviteMessage(txn, message.getId()); diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngineTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngineTest.java index 7631aeb83..43e63f34f 100644 --- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngineTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/InviteeProtocolEngineTest.java @@ -10,9 +10,9 @@ import org.briarproject.briar.api.privategroup.GroupMessage; import org.jmock.Expectations; import org.junit.Test; -import java.util.Collections; -import java.util.Map; +import java.util.Collection; +import static java.util.Collections.singletonList; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE; @@ -757,15 +757,12 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest { private void expectMarkInvitesUnavailableToAnswer() throws Exception { BdfDictionary query = BdfDictionary.of(new BdfEntry("query", "")); - BdfDictionary meta = BdfDictionary.of(new BdfEntry("meta", "")); - Map invites = - Collections.singletonMap(lastRemoteMessageId, meta); + Collection invites = singletonList(lastRemoteMessageId); context.checking(new Expectations() {{ oneOf(messageParser) .getInvitesAvailableToAnswerQuery(privateGroupId); will(returnValue(query)); - oneOf(clientHelper) - .getMessageMetadataAsDictionary(txn, contactGroupId, query); + oneOf(clientHelper).getMessageIds(txn, contactGroupId, query); will(returnValue(invites)); }}); expectMarkMessageAvailableToAnswer(lastRemoteMessageId, false);