diff --git a/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java index 70afe99ef..bca45b25f 100644 --- a/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java @@ -8,6 +8,7 @@ import org.briarproject.api.blogs.BlogInvitationResponse; import org.briarproject.api.blogs.BlogManager; import org.briarproject.api.blogs.BlogPostFactory; import org.briarproject.api.blogs.BlogSharingManager; +import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; import org.briarproject.api.contact.ContactManager; @@ -25,6 +26,7 @@ import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.sharing.InvitationMessage; +import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.SyncSession; import org.briarproject.api.sync.SyncSessionFactory; import org.briarproject.api.sync.ValidationManager.State; @@ -62,12 +64,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -public class BlogSharingIntegrationTest extends BriarTestCase { +public class BlogSharingIntegrationTest extends BriarIntegrationTest { private LifecycleManager lifecycleManager0, lifecycleManager1, lifecycleManager2; - private SyncSessionFactory sync0, sync1, sync2; - private BlogManager blogManager0, blogManager1, blogManager2; + private SyncSessionFactory sync0, sync1; + private BlogManager blogManager0, blogManager1; private ContactManager contactManager0, contactManager1, contactManager2; private Contact contact1, contact2, contact01, contact02; private ContactId contactId1, contactId2, contactId01, contactId02; @@ -83,6 +85,8 @@ public class BlogSharingIntegrationTest extends BriarTestCase { @Inject AuthorFactory authorFactory; @Inject + ContactGroupFactory contactGroupFactory; + @Inject BlogPostFactory blogPostFactory; @Inject CryptoComponent cryptoComponent; @@ -138,13 +142,11 @@ public class BlogSharingIntegrationTest extends BriarTestCase { contactManager2 = t2.getContactManager(); blogManager0 = t0.getBlogManager(); blogManager1 = t1.getBlogManager(); - blogManager2 = t2.getBlogManager(); blogSharingManager0 = t0.getBlogSharingManager(); blogSharingManager1 = t1.getBlogSharingManager(); blogSharingManager2 = t2.getBlogSharingManager(); sync0 = t0.getSyncSessionFactory(); sync1 = t1.getSyncSessionFactory(); - sync2 = t2.getSyncSessionFactory(); // initialize waiters fresh for each test eventWaiter = new Waiter(); @@ -187,15 +189,23 @@ public class BlogSharingIntegrationTest extends BriarTestCase { // invitee has own blog and that of the sharer assertEquals(2, blogManager1.getBlogs().size()); + // get sharing group and assert group message count + GroupId g = contactGroupFactory + .createContactGroup(blogSharingManager0.getClientId(), + contact1).getId(); + assertGroupCount(blogSharingManager0, g, 1, 0); + // sync first request message sync0To1(); eventWaiter.await(TIMEOUT, 1); assertTrue(listener1.requestReceived); + assertGroupCount(blogSharingManager1, g, 2, 1); // sync response back sync1To0(); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.responseReceived); + assertGroupCount(blogSharingManager0, g, 2, 1); // blog was added successfully assertEquals(0, blogSharingManager0.getInvitations().size()); @@ -232,6 +242,10 @@ public class BlogSharingIntegrationTest extends BriarTestCase { assertFalse(blogSharingManager0.canBeShared(blog2.getId(), contact1)); assertFalse(blogSharingManager1.canBeShared(blog2.getId(), contact01)); + // group message count is still correct + assertGroupCount(blogSharingManager0, g, 2, 1); + assertGroupCount(blogSharingManager1, g, 2, 1); + stopLifecycles(); } @@ -510,8 +524,7 @@ public class BlogSharingIntegrationTest extends BriarTestCase { private class SharerListener implements EventListener { - volatile boolean requestReceived = false; - volatile boolean responseReceived = false; + private volatile boolean responseReceived = false; @Override public void eventOccurred(Event e) { @@ -534,7 +547,6 @@ public class BlogSharingIntegrationTest extends BriarTestCase { BlogInvitationReceivedEvent event = (BlogInvitationReceivedEvent) e; eventWaiter.assertEquals(contactId1, event.getContactId()); - requestReceived = true; Blog b = event.getBlog(); try { Contact c = contactManager0.getContact(contactId1); @@ -550,17 +562,16 @@ public class BlogSharingIntegrationTest extends BriarTestCase { private class InviteeListener implements EventListener { - volatile boolean requestReceived = false; - volatile boolean responseReceived = false; + private volatile boolean requestReceived = false; private final boolean accept, answer; - InviteeListener(boolean accept, boolean answer) { + private InviteeListener(boolean accept, boolean answer) { this.accept = accept; this.answer = answer; } - InviteeListener(boolean accept) { + private InviteeListener(boolean accept) { this(accept, true); } @@ -596,7 +607,6 @@ public class BlogSharingIntegrationTest extends BriarTestCase { BlogInvitationResponseReceivedEvent event = (BlogInvitationResponseReceivedEvent) e; eventWaiter.assertEquals(contactId01, event.getContactId()); - responseReceived = true; eventWaiter.resume(); } } diff --git a/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java new file mode 100644 index 000000000..f1b2a0914 --- /dev/null +++ b/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java @@ -0,0 +1,32 @@ +package org.briarproject; + +import org.briarproject.api.clients.MessageTracker; +import org.briarproject.api.clients.MessageTracker.GroupCount; +import org.briarproject.api.db.DbException; +import org.briarproject.api.sync.GroupId; + +import static org.junit.Assert.assertEquals; + +public abstract class BriarIntegrationTest extends BriarTestCase { + + // TODO maybe we could add uncaught exception handlers for other threads here (#670) + + protected void assertGroupCount(MessageTracker tracker, GroupId g, + long msgCount, long unreadCount, long latestMsg) + throws DbException { + + GroupCount groupCount = tracker.getGroupCount(g); + assertEquals(msgCount, groupCount.getMsgCount()); + assertEquals(unreadCount, groupCount.getUnreadCount()); + assertEquals(latestMsg, groupCount.getLatestMsgTime()); + } + + protected void assertGroupCount(MessageTracker tracker, GroupId g, + long msgCount, long unreadCount) throws DbException { + + GroupCount c1 = tracker.getGroupCount(g); + assertEquals(msgCount, c1.getMsgCount()); + assertEquals(unreadCount, c1.getUnreadCount()); + } + +} diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java b/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java index 0fa8e80c1..64ad251f0 100644 --- a/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java @@ -59,7 +59,7 @@ import static org.briarproject.api.sync.ValidationManager.State.INVALID; import static org.briarproject.api.sync.ValidationManager.State.PENDING; import static org.junit.Assert.assertTrue; -public class ForumManagerTest { +public class ForumManagerTest extends BriarIntegrationTest { private LifecycleManager lifecycleManager0, lifecycleManager1; private SyncSessionFactory sync0, sync1; @@ -150,9 +150,19 @@ public class ForumManagerTest { createForumPost(forum.getGroup().getId(), post1, body2, ms2); assertEquals(ms2, post2.getMessage().getTimestamp()); forumManager0.addLocalPost(post1); - forumManager0.setReadFlag(post1.getMessage().getId(), true); + forumManager0.setReadFlag(forum.getGroup().getId(), + post1.getMessage().getId(), true); + assertGroupCount(forumManager0, forum.getGroup().getId(), 1, 0, + post1.getMessage().getTimestamp()); forumManager0.addLocalPost(post2); - forumManager0.setReadFlag(post2.getMessage().getId(), false); + forumManager0.setReadFlag(forum.getGroup().getId(), + post2.getMessage().getId(), false); + assertGroupCount(forumManager0, forum.getGroup().getId(), 2, 1, + post2.getMessage().getTimestamp()); + forumManager0.setReadFlag(forum.getGroup().getId(), + post2.getMessage().getId(), false); + assertGroupCount(forumManager0, forum.getGroup().getId(), 2, 1, + post2.getMessage().getTimestamp()); Collection headers = forumManager0.getPostHeaders(forum.getGroup().getId()); assertEquals(2, headers.size()); @@ -202,23 +212,29 @@ public class ForumManagerTest { forumManager0.addLocalPost(post1); assertEquals(1, forumManager0.getPostHeaders(g).size()); assertEquals(0, forumManager1.getPostHeaders(g).size()); + assertGroupCount(forumManager0, g, 1, 0, time); + assertGroupCount(forumManager1, g, 0, 0, 0); // send post to 1 sync0To1(); deliveryWaiter.await(TIMEOUT, 1); assertEquals(1, forumManager1.getPostHeaders(g).size()); + assertGroupCount(forumManager1, g, 1, 1, time); // add another forum post - time = clock.currentTimeMillis(); - ForumPost post2 = createForumPost(g, null, "b", time); + long time2 = clock.currentTimeMillis(); + ForumPost post2 = createForumPost(g, null, "b", time2); forumManager1.addLocalPost(post2); assertEquals(1, forumManager0.getPostHeaders(g).size()); assertEquals(2, forumManager1.getPostHeaders(g).size()); + assertGroupCount(forumManager0, g, 1, 0, time); + assertGroupCount(forumManager1, g, 2, 1, time2); // send post to 0 sync1To0(); deliveryWaiter.await(TIMEOUT, 1); assertEquals(2, forumManager1.getPostHeaders(g).size()); + assertGroupCount(forumManager0, g, 2, 1, time2); stopLifecycles(); } diff --git a/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java index 364040e7c..e9c4487a4 100644 --- a/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java @@ -4,7 +4,7 @@ import android.support.annotation.Nullable; import net.jodah.concurrentunit.Waiter; -import org.briarproject.BriarTestCase; +import org.briarproject.BriarIntegrationTest; import org.briarproject.TestDatabaseModule; import org.briarproject.TestUtils; import org.briarproject.api.FormatException; @@ -99,7 +99,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -public class IntroductionIntegrationTest extends BriarTestCase { +public class IntroductionIntegrationTest extends BriarIntegrationTest { private LifecycleManager lifecycleManager0, lifecycleManager1, lifecycleManager2; @@ -200,29 +200,43 @@ public class IntroductionIntegrationTest extends BriarTestCase { introductionManager0 .makeIntroduction(introducee1, introducee2, "Hi!", time); + // check that messages are tracked properly + Group g1 = introductionGroupFactory + .createIntroductionGroup(introducee1); + Group g2 = introductionGroupFactory + .createIntroductionGroup(introducee2); + assertGroupCount(introductionManager0, g1.getId(), 1, 0, time); + assertGroupCount(introductionManager0, g2.getId(), 1, 0, time); + // sync first request message deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); eventWaiter.await(TIMEOUT, 1); assertTrue(listener1.requestReceived); + assertGroupCount(introductionManager1, g1.getId(), 2, 1); // sync second request message deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2"); eventWaiter.await(TIMEOUT, 1); assertTrue(listener2.requestReceived); + assertGroupCount(introductionManager2, g2.getId(), 2, 1); // sync first response deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.response1Received); + assertGroupCount(introductionManager0, g1.getId(), 2, 1); // sync second response deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0"); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.response2Received); + assertGroupCount(introductionManager0, g2.getId(), 2, 1); // sync forwarded responses to introducees deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2"); + assertGroupCount(introductionManager1, g1.getId(), 3, 2); + assertGroupCount(introductionManager2, g2.getId(), 3, 2); // sync first ACK and its forward deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); @@ -255,6 +269,10 @@ public class IntroductionIntegrationTest extends BriarTestCase { } assertDefaultUiMessages(); + assertGroupCount(introductionManager0, g1.getId(), 2, 1); + assertGroupCount(introductionManager0, g2.getId(), 2, 1); + assertGroupCount(introductionManager1, g1.getId(), 3, 2); + assertGroupCount(introductionManager2, g2.getId(), 3, 2); } finally { stopLifecycles(); } diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java index 7ec442b5b..722e6b858 100644 --- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java +++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java @@ -499,7 +499,7 @@ public class ConversationActivity extends BriarActivity for (MessageId m : unread) // not really clean, but the messaging manager can // handle introduction messages as well - messagingManager.setReadFlag(m, true); + messagingManager.setReadFlag(groupId, m, true); long duration = System.currentTimeMillis() - now; if (LOG.isLoggable(INFO)) LOG.info("Marking read took " + duration + " ms"); @@ -614,7 +614,7 @@ public class ConversationActivity extends BriarActivity @Override public void run() { try { - messagingManager.setReadFlag(m, true); + messagingManager.setReadFlag(groupId, m, true); loadMessages(); } catch (DbException e) { if (LOG.isLoggable(WARNING)) diff --git a/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java b/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java index bf147491b..98f7ac139 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java +++ b/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java @@ -291,13 +291,15 @@ public class ForumControllerImpl extends DbControllerImpl @Override public void entriesRead(final Collection forumEntries) { + if (forum == null) return; runOnDbThread(new Runnable() { @Override public void run() { try { long now = System.currentTimeMillis(); for (ForumEntry fe : forumEntries) { - forumManager.setReadFlag(fe.getId(), true); + forumManager + .setReadFlag(forum.getId(), fe.getId(), true); } long duration = System.currentTimeMillis() - now; if (LOG.isLoggable(INFO)) diff --git a/briar-api/src/org/briarproject/api/clients/MessageTracker.java b/briar-api/src/org/briarproject/api/clients/MessageTracker.java new file mode 100644 index 000000000..8226a3058 --- /dev/null +++ b/briar-api/src/org/briarproject/api/clients/MessageTracker.java @@ -0,0 +1,44 @@ +package org.briarproject.api.clients; + +import org.briarproject.api.db.DbException; +import org.briarproject.api.db.Transaction; +import org.briarproject.api.sync.GroupId; +import org.briarproject.api.sync.Message; +import org.briarproject.api.sync.MessageId; + +public interface MessageTracker { + + /** + * Gets the number of visible and unread messages in the group + * as well as the timestamp of the latest message + **/ + GroupCount getGroupCount(GroupId g) throws DbException; + + /** + * Marks a message as read or unread and updates the group counts in g. + **/ + void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException; + + class GroupCount { + private final long msgCount, unreadCount, latestMsgTime; + + public GroupCount(long msgCount, long unreadCount, long latestMsgTime) { + this.msgCount = msgCount; + this.unreadCount = unreadCount; + this.latestMsgTime = latestMsgTime; + } + + public long getMsgCount() { + return msgCount; + } + + public long getUnreadCount() { + return unreadCount; + } + + public long getLatestMsgTime() { + return latestMsgTime; + } + } + +} diff --git a/briar-api/src/org/briarproject/api/forum/ForumConstants.java b/briar-api/src/org/briarproject/api/forum/ForumConstants.java index 97557d5fe..048f6c3c7 100644 --- a/briar-api/src/org/briarproject/api/forum/ForumConstants.java +++ b/briar-api/src/org/briarproject/api/forum/ForumConstants.java @@ -28,6 +28,5 @@ public interface ForumConstants { String KEY_PUBLIC_NAME = "publicKey"; String KEY_AUTHOR = "author"; String KEY_LOCAL = "local"; - String KEY_READ = "read"; } diff --git a/briar-api/src/org/briarproject/api/forum/ForumManager.java b/briar-api/src/org/briarproject/api/forum/ForumManager.java index 8a1c0e7c4..8c35d05e3 100644 --- a/briar-api/src/org/briarproject/api/forum/ForumManager.java +++ b/briar-api/src/org/briarproject/api/forum/ForumManager.java @@ -1,5 +1,6 @@ package org.briarproject.api.forum; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Transaction; import org.briarproject.api.sync.ClientId; @@ -8,7 +9,7 @@ import org.briarproject.api.sync.MessageId; import java.util.Collection; -public interface ForumManager { +public interface ForumManager extends MessageTracker { /** Returns the unique ID of the forum client. */ ClientId getClientId(); @@ -37,9 +38,6 @@ public interface ForumManager { /** Returns the headers of all posts in the given forum. */ Collection getPostHeaders(GroupId g) throws DbException; - /** Marks a forum post as read or unread. */ - void setReadFlag(MessageId m, boolean read) throws DbException; - /** Registers a hook to be called whenever a forum is removed. */ void registerRemoveForumHook(RemoveForumHook hook); diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionConstants.java b/briar-api/src/org/briarproject/api/introduction/IntroductionConstants.java index ac8975e5c..de74b390f 100644 --- a/briar-api/src/org/briarproject/api/introduction/IntroductionConstants.java +++ b/briar-api/src/org/briarproject/api/introduction/IntroductionConstants.java @@ -45,7 +45,6 @@ public interface IntroductionConstants { String CONTACT_ID_2 = "contactId2"; String RESPONSE_1 = "response1"; String RESPONSE_2 = "response2"; - String READ = "read"; /* Introduction Request Action */ String PUBLIC_KEY1 = "publicKey1"; diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java b/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java index 9819c8758..3f2fcea12 100644 --- a/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java +++ b/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java @@ -1,6 +1,7 @@ package org.briarproject.api.introduction; import org.briarproject.api.FormatException; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.SessionId; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; @@ -9,7 +10,7 @@ import org.briarproject.api.sync.ClientId; import java.util.Collection; -public interface IntroductionManager { +public interface IntroductionManager extends MessageTracker { /** Returns the unique ID of the introduction client. */ ClientId getClientId(); diff --git a/briar-api/src/org/briarproject/api/messaging/MessagingManager.java b/briar-api/src/org/briarproject/api/messaging/MessagingManager.java index f22a5131a..627f5ceb6 100644 --- a/briar-api/src/org/briarproject/api/messaging/MessagingManager.java +++ b/briar-api/src/org/briarproject/api/messaging/MessagingManager.java @@ -1,5 +1,6 @@ package org.briarproject.api.messaging; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.contact.ContactId; import org.briarproject.api.db.DbException; import org.briarproject.api.sync.ClientId; @@ -8,7 +9,7 @@ import org.briarproject.api.sync.MessageId; import java.util.Collection; -public interface MessagingManager { +public interface MessagingManager extends MessageTracker { /** Returns the unique ID of the messaging client. */ ClientId getClientId(); @@ -31,6 +32,4 @@ public interface MessagingManager { /** Returns the body of the private message with the given ID. */ byte[] getMessageBody(MessageId m) throws DbException; - /** Marks a private message as read or unread. */ - void setReadFlag(MessageId m, boolean read) throws DbException; } diff --git a/briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java b/briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java index 3f2a63762..ab02e86bc 100644 --- a/briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java +++ b/briar-api/src/org/briarproject/api/privategroup/PrivateGroupManager.java @@ -1,5 +1,6 @@ package org.briarproject.api.privategroup; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Transaction; import org.briarproject.api.sync.ClientId; @@ -9,7 +10,7 @@ import org.jetbrains.annotations.NotNull; import java.util.Collection; -public interface PrivateGroupManager { +public interface PrivateGroupManager extends MessageTracker { /** Returns the unique ID of the private group client. */ @NotNull @@ -40,7 +41,4 @@ public interface PrivateGroupManager { @NotNull Collection getHeaders(GroupId g) throws DbException; - /** Marks a group message as read or unread. */ - void setReadFlag(MessageId m, boolean read) throws DbException; - } diff --git a/briar-api/src/org/briarproject/api/sharing/SharingConstants.java b/briar-api/src/org/briarproject/api/sharing/SharingConstants.java index 43d689729..e09b9015c 100644 --- a/briar-api/src/org/briarproject/api/sharing/SharingConstants.java +++ b/briar-api/src/org/briarproject/api/sharing/SharingConstants.java @@ -16,7 +16,6 @@ public interface SharingConstants { String STATE = "state"; String LOCAL = "local"; String TIME = "time"; - String READ = "read"; String IS_SHARER = "isSharer"; String SHAREABLE_ID = "shareableId"; String INVITATION_MSG = "invitationMsg"; diff --git a/briar-api/src/org/briarproject/api/sharing/SharingManager.java b/briar-api/src/org/briarproject/api/sharing/SharingManager.java index 0a66a5458..c633256f1 100644 --- a/briar-api/src/org/briarproject/api/sharing/SharingManager.java +++ b/briar-api/src/org/briarproject/api/sharing/SharingManager.java @@ -1,5 +1,6 @@ package org.briarproject.api.sharing; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; import org.briarproject.api.db.DbException; @@ -8,7 +9,7 @@ import org.briarproject.api.sync.GroupId; import java.util.Collection; -public interface SharingManager { +public interface SharingManager extends MessageTracker { /** Returns the unique ID of the group sharing client. */ ClientId getClientId(); diff --git a/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java b/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java index 094917991..d31023c44 100644 --- a/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java +++ b/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java @@ -86,7 +86,6 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager, "dafbe56f0c8971365cea4bb5f08ec9a6" + "1d686e058b943997b6ff259ba423f613")); - private final DatabaseComponent db; private final IdentityManager identityManager; private final ContactManager contactManager; private final BlogFactory blogFactory; @@ -98,9 +97,8 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager, ClientHelper clientHelper, MetadataParser metadataParser, ContactManager contactManager, BlogFactory blogFactory, BlogPostFactory blogPostFactory) { - super(clientHelper, metadataParser); + super(db, clientHelper, metadataParser); - this.db = db; this.identityManager = identityManager; this.contactManager = contactManager; this.blogFactory = blogFactory; diff --git a/briar-core/src/org/briarproject/clients/BdfConstants.java b/briar-core/src/org/briarproject/clients/BdfConstants.java new file mode 100644 index 000000000..6f8149185 --- /dev/null +++ b/briar-core/src/org/briarproject/clients/BdfConstants.java @@ -0,0 +1,11 @@ +package org.briarproject.clients; + +public interface BdfConstants { + + String GROUP_KEY_MSG_COUNT = "messageCount"; + String GROUP_KEY_UNREAD_COUNT = "unreadCount"; + String GROUP_KEY_LATEST_MSG = "latestMessageTime"; + + String MSG_KEY_READ = "read"; + +} diff --git a/briar-core/src/org/briarproject/clients/BdfIncomingMessageHook.java b/briar-core/src/org/briarproject/clients/BdfIncomingMessageHook.java index 3ca19d9bd..c81293ab0 100644 --- a/briar-core/src/org/briarproject/clients/BdfIncomingMessageHook.java +++ b/briar-core/src/org/briarproject/clients/BdfIncomingMessageHook.java @@ -3,27 +3,38 @@ package org.briarproject.clients; import org.briarproject.api.FormatException; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.MessageQueueManager.IncomingQueueMessageHook; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.QueueMessage; import org.briarproject.api.data.BdfDictionary; +import org.briarproject.api.data.BdfEntry; import org.briarproject.api.data.BdfList; import org.briarproject.api.data.MetadataParser; +import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Metadata; import org.briarproject.api.db.Transaction; +import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.Message; +import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.ValidationManager.IncomingMessageHook; import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH; import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; +import static org.briarproject.clients.BdfConstants.GROUP_KEY_LATEST_MSG; +import static org.briarproject.clients.BdfConstants.GROUP_KEY_MSG_COUNT; +import static org.briarproject.clients.BdfConstants.GROUP_KEY_UNREAD_COUNT; +import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; public abstract class BdfIncomingMessageHook implements IncomingMessageHook, - IncomingQueueMessageHook { + IncomingQueueMessageHook, MessageTracker { + protected final DatabaseComponent db; protected final ClientHelper clientHelper; protected final MetadataParser metadataParser; - protected BdfIncomingMessageHook(ClientHelper clientHelper, - MetadataParser metadataParser) { + protected BdfIncomingMessageHook(DatabaseComponent db, + ClientHelper clientHelper, MetadataParser metadataParser) { + this.db = db; this.clientHelper = clientHelper; this.metadataParser = metadataParser; } @@ -56,4 +67,102 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook, throw new DbException(e); } } + + protected void trackIncomingMessage(Transaction txn, Message m) + throws DbException { + trackMessage(txn, m.getGroupId(), m.getTimestamp(), false); + } + + protected void trackOutgoingMessage(Transaction txn, Message m) + throws DbException { + trackMessage(txn, m.getGroupId(), m.getTimestamp(), true); + } + + protected void trackMessage(Transaction txn, GroupId g, long time, + boolean read) throws DbException { + GroupCount c = getGroupCount(txn, g); + long msgCount = c.getMsgCount() + 1; + long unreadCount = c.getUnreadCount() + (read ? 0 : 1); + long latestTime = + time > c.getLatestMsgTime() ? time : c.getLatestMsgTime(); + storeGroupCount(txn, g, + new GroupCount(msgCount, unreadCount, latestTime)); + } + + @Override + public GroupCount getGroupCount(GroupId g) throws DbException { + GroupCount count; + Transaction txn = db.startTransaction(true); + try { + count = getGroupCount(txn, g); + txn.setComplete(); + } + finally { + db.endTransaction(txn); + } + return count; + } + + private GroupCount getGroupCount(Transaction txn, GroupId g) + throws DbException { + GroupCount count; + try { + BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(txn, g); + count = new GroupCount( + d.getLong(GROUP_KEY_MSG_COUNT, 0L), + d.getLong(GROUP_KEY_UNREAD_COUNT, 0L), + d.getLong(GROUP_KEY_LATEST_MSG, 0L) + ); + } catch (FormatException e) { + throw new DbException(e); + } + return count; + } + + private void storeGroupCount(Transaction txn, GroupId g, GroupCount c) + throws DbException{ + try { + BdfDictionary d = BdfDictionary.of( + new BdfEntry(GROUP_KEY_MSG_COUNT, c.getMsgCount()), + new BdfEntry(GROUP_KEY_UNREAD_COUNT, c.getUnreadCount()), + new BdfEntry(GROUP_KEY_LATEST_MSG, c.getLatestMsgTime()) + ); + clientHelper.mergeGroupMetadata(txn, g, d); + } catch (FormatException e) { + throw new DbException(e); + } + } + + @Override + public void setReadFlag(GroupId g, MessageId m, boolean read) + throws DbException { + Transaction txn = db.startTransaction(false); + try { + // check current read status of message + BdfDictionary old = + clientHelper.getMessageMetadataAsDictionary(txn, m); + boolean wasRead = old.getBoolean(MSG_KEY_READ, false); + + // if status changed + if (wasRead != read) { + // mark individual message as read + BdfDictionary meta = new BdfDictionary(); + meta.put(MSG_KEY_READ, read); + clientHelper.mergeMessageMetadata(txn, m, meta); + + // update unread counter in group metadata + GroupCount c = getGroupCount(txn, g); + BdfDictionary d = new BdfDictionary(); + d.put(GROUP_KEY_UNREAD_COUNT, + c.getUnreadCount() + (read ? -1 : 1)); + clientHelper.mergeGroupMetadata(txn, g, d); + } + txn.setComplete(); + } catch (FormatException e) { + throw new DbException(e); + } finally { + db.endTransaction(txn); + } + } + } diff --git a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumManagerImpl.java index d4697b759..77a7712e5 100644 --- a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java +++ b/briar-core/src/org/briarproject/forum/ForumManagerImpl.java @@ -45,9 +45,9 @@ import static org.briarproject.api.forum.ForumConstants.KEY_LOCAL; import static org.briarproject.api.forum.ForumConstants.KEY_NAME; import static org.briarproject.api.forum.ForumConstants.KEY_PARENT; import static org.briarproject.api.forum.ForumConstants.KEY_PUBLIC_NAME; -import static org.briarproject.api.forum.ForumConstants.KEY_READ; import static org.briarproject.api.forum.ForumConstants.KEY_TIMESTAMP; import static org.briarproject.api.identity.Author.Status.ANONYMOUS; +import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { @@ -55,7 +55,6 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { "859a7be50dca035b64bd6902fb797097" + "795af837abbf8c16d750b3c2ccc186ea")); - private final DatabaseComponent db; private final IdentityManager identityManager; private final ForumFactory forumFactory; private final List removeHooks; @@ -64,9 +63,8 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { ForumManagerImpl(DatabaseComponent db, IdentityManager identityManager, ClientHelper clientHelper, MetadataParser metadataParser, ForumFactory forumFactory) { + super(db, clientHelper, metadataParser); - super(clientHelper, metadataParser); - this.db = db; this.identityManager = identityManager; this.forumFactory = forumFactory; removeHooks = new CopyOnWriteArrayList(); @@ -76,6 +74,8 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { protected boolean incomingMessage(Transaction txn, Message m, BdfList body, BdfDictionary meta) throws DbException, FormatException { + trackIncomingMessage(txn, m); + ForumPostHeader post = getForumPostHeader(txn, m.getId(), meta); ForumPostReceivedEvent event = new ForumPostReceivedEvent(post, m.getGroupId()); @@ -119,6 +119,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { @Override public void addLocalPost(ForumPost p) throws DbException { + Transaction txn = db.startTransaction(false); try { BdfDictionary meta = new BdfDictionary(); meta.put(KEY_TIMESTAMP, p.getMessage().getTimestamp()); @@ -132,10 +133,14 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { meta.put(KEY_AUTHOR, authorMeta); } meta.put(KEY_LOCAL, true); - meta.put(KEY_READ, true); - clientHelper.addLocalMessage(p.getMessage(), meta, true); + meta.put(MSG_KEY_READ, true); + clientHelper.addLocalMessage(txn, p.getMessage(), meta, true); + trackOutgoingMessage(txn, p.getMessage()); + txn.setComplete(); } catch (FormatException e) { throw new RuntimeException(e); + } finally { + db.endTransaction(txn); } } @@ -230,17 +235,6 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { } } - @Override - public void setReadFlag(MessageId m, boolean read) throws DbException { - try { - BdfDictionary meta = new BdfDictionary(); - meta.put(KEY_READ, read); - clientHelper.mergeMessageMetadata(m, meta); - } catch (FormatException e) { - throw new RuntimeException(e); - } - } - @Override public void registerRemoveForumHook(RemoveForumHook hook) { removeHooks.add(hook); @@ -281,7 +275,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { status = identityManager.getAuthorStatus(txn, author.getId()); } } - boolean read = meta.getBoolean(KEY_READ); + boolean read = meta.getBoolean(MSG_KEY_READ); return new ForumPostHeader(id, parentId, timestamp, author, status, read); diff --git a/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java b/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java index b07108ed8..6c44e83e6 100644 --- a/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java +++ b/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java @@ -60,7 +60,6 @@ import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TI import static org.briarproject.api.introduction.IntroductionConstants.MSG; import static org.briarproject.api.introduction.IntroductionConstants.NAME; import static org.briarproject.api.introduction.IntroductionConstants.NOT_OUR_RESPONSE; -import static org.briarproject.api.introduction.IntroductionConstants.READ; import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_ID; import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_IS_US; import static org.briarproject.api.introduction.IntroductionConstants.RESPONSE_1; @@ -75,6 +74,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK; import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST; import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE; +import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; class IntroductionManagerImpl extends BdfIncomingMessageHook implements IntroductionManager, Client, AddContactHook, @@ -87,7 +87,6 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook private static final Logger LOG = Logger.getLogger(IntroductionManagerImpl.class.getName()); - private final DatabaseComponent db; private final IntroducerManager introducerManager; private final IntroduceeManager introduceeManager; private final IntroductionGroupFactory introductionGroupFactory; @@ -98,8 +97,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook IntroduceeManager introduceeManager, IntroductionGroupFactory introductionGroupFactory) { - super(clientHelper, metadataParser); - this.db = db; + super(db, clientHelper, metadataParser); this.introducerManager = introducerManager; this.introduceeManager = introduceeManager; this.introductionGroupFactory = introductionGroupFactory; @@ -208,7 +206,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook */ @Override protected boolean incomingMessage(Transaction txn, Message m, BdfList body, - BdfDictionary message) throws DbException { + BdfDictionary message) throws DbException { // Get message data and type GroupId groupId = m.getGroupId(); @@ -237,6 +235,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook } try { introduceeManager.incomingMessage(txn, state, message); + trackIncomingMessage(txn, m); } catch (DbException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); introduceeManager.abort(txn, state); @@ -270,6 +269,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook deleteMessage(txn, m.getId()); } } + if (type == TYPE_RESPONSE) trackIncomingMessage(txn, m); } catch (DbException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if (role == ROLE_INTRODUCER) introducerManager.abort(txn, state); @@ -296,6 +296,10 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook Transaction txn = db.startTransaction(false); try { introducerManager.makeIntroduction(txn, c1, c2, msg, timestamp); + Group g1 = introductionGroupFactory.createIntroductionGroup(c1); + Group g2 = introductionGroupFactory.createIntroductionGroup(c2); + trackMessage(txn, g1.getId(), timestamp, true); + trackMessage(txn, g2.getId(), timestamp, true); txn.setComplete(); } finally { db.endTransaction(txn); @@ -315,6 +319,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook getSessionState(txn, g.getId(), sessionId.getBytes()); introduceeManager.acceptIntroduction(txn, state, timestamp); + trackMessage(txn, g.getId(), timestamp, true); txn.setComplete(); } finally { db.endTransaction(txn); @@ -334,6 +339,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook getSessionState(txn, g.getId(), sessionId.getBytes()); introduceeManager.declineIntroduction(txn, state, timestamp); + trackMessage(txn, g.getId(), timestamp, true); txn.setComplete(); } finally { db.endTransaction(txn); @@ -377,7 +383,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook boolean local; long time = msg.getLong(MESSAGE_TIME); boolean accepted = msg.getBoolean(ACCEPT, false); - boolean read = msg.getBoolean(READ, false); + boolean read = msg.getBoolean(MSG_KEY_READ, false); AuthorId authorId; String name; if (type == TYPE_RESPONSE) { diff --git a/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java b/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java index d2af3d8a1..d5bc6db1d 100644 --- a/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java +++ b/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java @@ -33,6 +33,8 @@ import java.util.Map; import javax.inject.Inject; +import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; + class MessagingManagerImpl extends BdfIncomingMessageHook implements MessagingManager, Client, AddContactHook, RemoveContactHook { @@ -40,16 +42,13 @@ class MessagingManagerImpl extends BdfIncomingMessageHook "6bcdc006c0910b0f44e40644c3b31f1a" + "8bf9a6d6021d40d219c86b731b903070")); - private final DatabaseComponent db; private final ContactGroupFactory contactGroupFactory; @Inject MessagingManagerImpl(DatabaseComponent db, ClientHelper clientHelper, MetadataParser metadataParser, ContactGroupFactory contactGroupFactory) { - super(clientHelper, metadataParser); - - this.db = db; + super(db, clientHelper, metadataParser); this.contactGroupFactory = contactGroupFactory; } @@ -100,12 +99,13 @@ class MessagingManagerImpl extends BdfIncomingMessageHook long timestamp = meta.getLong("timestamp"); String contentType = meta.getString("contentType"); boolean local = meta.getBoolean("local"); - boolean read = meta.getBoolean("read"); + boolean read = meta.getBoolean(MSG_KEY_READ); PrivateMessageHeader header = new PrivateMessageHeader( m.getId(), timestamp, contentType, local, read, false, false); PrivateMessageReceivedEvent event = new PrivateMessageReceivedEvent( header, groupId); txn.attach(event); + trackIncomingMessage(txn, m); // don't share message return false; @@ -113,6 +113,7 @@ class MessagingManagerImpl extends BdfIncomingMessageHook @Override public void addLocalMessage(PrivateMessage m) throws DbException { + Transaction txn = db.startTransaction(false); try { BdfDictionary meta = new BdfDictionary(); meta.put("timestamp", m.getMessage().getTimestamp()); @@ -120,9 +121,13 @@ class MessagingManagerImpl extends BdfIncomingMessageHook meta.put("contentType", m.getContentType()); meta.put("local", true); meta.put("read", true); - clientHelper.addLocalMessage(m.getMessage(), meta, true); + clientHelper.addLocalMessage(txn, m.getMessage(), meta, true); + trackOutgoingMessage(txn, m.getMessage()); + txn.setComplete(); } catch (FormatException e) { throw new RuntimeException(e); + } finally { + db.endTransaction(txn); } } @@ -196,14 +201,4 @@ class MessagingManagerImpl extends BdfIncomingMessageHook } } - @Override - public void setReadFlag(MessageId m, boolean read) throws DbException { - try { - BdfDictionary meta = new BdfDictionary(); - meta.put("read", read); - clientHelper.mergeMessageMetadata(m, meta); - } catch (FormatException e) { - throw new RuntimeException(e); - } - } } diff --git a/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java b/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java index 74bd0d904..fec178b60 100644 --- a/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java +++ b/briar-core/src/org/briarproject/messaging/PrivateMessageValidator.java @@ -14,6 +14,7 @@ import org.briarproject.clients.BdfMessageValidator; import static org.briarproject.api.messaging.MessagingConstants.MAX_CONTENT_TYPE_LENGTH; import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH; +import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; class PrivateMessageValidator extends BdfMessageValidator { @@ -42,7 +43,7 @@ class PrivateMessageValidator extends BdfMessageValidator { if (parentId != null) meta.put("parent", parentId); meta.put("contentType", contentType); meta.put("local", false); - meta.put("read", false); + meta.put(MSG_KEY_READ, false); return new BdfMessageContext(meta); } } diff --git a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java b/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java index 15256467a..93623476d 100644 --- a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java +++ b/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java @@ -28,8 +28,6 @@ import java.util.Collections; import javax.inject.Inject; -import static org.briarproject.privategroup.Constants.KEY_READ; - public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements PrivateGroupManager { @@ -37,7 +35,6 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements StringUtils.fromHexString("5072697661746547726f75704d616e61" + "67657220627920546f727374656e2047")); - private final DatabaseComponent db; private final IdentityManager identityManager; private final PrivateGroupFactory privateGroupFactory; @@ -46,9 +43,8 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements MetadataParser metadataParser, DatabaseComponent db, IdentityManager identityManager, PrivateGroupFactory privateGroupFactory) { - super(clientHelper, metadataParser); + super(db, clientHelper, metadataParser); - this.db = db; this.identityManager = identityManager; this.privateGroupFactory = privateGroupFactory; } @@ -61,11 +57,16 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements @Override public void addLocalMessage(GroupMessage m) throws DbException { + Transaction txn = db.startTransaction(false); try { BdfDictionary meta = new BdfDictionary(); - clientHelper.addLocalMessage(m.getMessage(), meta, true); + clientHelper.addLocalMessage(txn, m.getMessage(), meta, true); + trackOutgoingMessage(txn, m.getMessage()); + txn.setComplete(); } catch (FormatException e) { throw new DbException(e); + } finally { + db.endTransaction(txn); } } @@ -104,21 +105,12 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements return Collections.emptyList(); } - @Override - public void setReadFlag(MessageId m, boolean read) throws DbException { - try { - BdfDictionary meta = new BdfDictionary(); - meta.put(KEY_READ, read); - clientHelper.mergeMessageMetadata(m, meta); - } catch (FormatException e) { - throw new RuntimeException(e); - } - } - @Override protected boolean incomingMessage(Transaction txn, Message m, BdfList body, BdfDictionary meta) throws DbException, FormatException { + trackIncomingMessage(txn, m); + return true; } diff --git a/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java b/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java index db29f569e..805b9d0b4 100644 --- a/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java +++ b/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java @@ -58,7 +58,6 @@ import static org.briarproject.api.clients.ProtocolEngine.StateUpdate; import static org.briarproject.api.sharing.SharingConstants.CONTACT_ID; import static org.briarproject.api.sharing.SharingConstants.IS_SHARER; import static org.briarproject.api.sharing.SharingConstants.LOCAL; -import static org.briarproject.api.sharing.SharingConstants.READ; import static org.briarproject.api.sharing.SharingConstants.SESSION_ID; import static org.briarproject.api.sharing.SharingConstants.SHAREABLE_ID; import static org.briarproject.api.sharing.SharingConstants.SHARED_BY_US; @@ -83,6 +82,7 @@ import static org.briarproject.api.sharing.SharingConstants.TO_BE_SHARED_BY_US; import static org.briarproject.api.sharing.SharingConstants.TYPE; import static org.briarproject.api.sharing.SharingMessage.BaseMessage; import static org.briarproject.api.sharing.SharingMessage.Invitation; +import static org.briarproject.clients.BdfConstants.MSG_KEY_READ; import static org.briarproject.sharing.InviteeSessionState.State.AWAIT_LOCAL_RESPONSE; abstract class SharingManagerImpl @@ -93,7 +93,6 @@ abstract class SharingManagerImpl(getIRFactory()); processInviteeStateUpdate(txn, m.getId(), engine.onMessageReceived(state, msg)); + trackIncomingMessage(txn, m); } catch (FormatException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); deleteMessage(txn, m.getId()); @@ -239,6 +238,7 @@ abstract class SharingManagerImpl