From 945b5eb1ac0d5e291ba3ce63c3766d0ee2b91a04 Mon Sep 17 00:00:00 2001 From: akwizgran <akwizgran@users.sourceforge.net> Date: Fri, 1 Apr 2016 15:51:57 +0100 Subject: [PATCH] Create local state for clients at startup. #279 --- .../briarproject/android/AndroidModule.java | 4 +- .../org/briarproject/api/clients/Client.java | 12 +++++ .../api/clients/PrivateGroupFactory.java | 3 ++ .../api/db/DatabaseComponent.java | 26 ++++++---- .../api/lifecycle/LifecycleManager.java | 48 ++++++++++++------ .../clients/PrivateGroupFactoryImpl.java | 7 +++ .../db/DatabaseComponentImpl.java | 22 ++++++--- .../org/briarproject/forum/ForumModule.java | 5 +- .../forum/ForumSharingManagerImpl.java | 21 +++++--- .../introduction/IntroductionManagerImpl.java | 49 ++++++++++--------- .../introduction/IntroductionModule.java | 9 ++-- .../lifecycle/LifecycleManagerImpl.java | 39 ++++++++++++--- .../messaging/MessagingManagerImpl.java | 11 ++++- .../messaging/MessagingModule.java | 5 +- .../briarproject/plugins/PluginsModule.java | 2 +- .../properties/PropertiesModule.java | 3 ++ .../TransportPropertyManagerImpl.java | 31 ++++++------ .../src/org/briarproject/sync/SyncModule.java | 2 +- .../transport/TransportModule.java | 2 +- .../org/briarproject/TestLifecycleModule.java | 13 +++-- 20 files changed, 209 insertions(+), 105 deletions(-) create mode 100644 briar-api/src/org/briarproject/api/clients/Client.java diff --git a/briar-android/src/org/briarproject/android/AndroidModule.java b/briar-android/src/org/briarproject/android/AndroidModule.java index d3a7d8a4d5..9dc8fcd884 100644 --- a/briar-android/src/org/briarproject/android/AndroidModule.java +++ b/briar-android/src/org/briarproject/android/AndroidModule.java @@ -93,10 +93,8 @@ public class AndroidModule { AndroidNotificationManager provideAndroidNotificationManager( LifecycleManager lifecycleManager, EventBus eventBus, AndroidNotificationManagerImpl notificationManager) { - lifecycleManager.register(notificationManager); + lifecycleManager.registerService(notificationManager); eventBus.addListener(notificationManager); - return notificationManager; } - } diff --git a/briar-api/src/org/briarproject/api/clients/Client.java b/briar-api/src/org/briarproject/api/clients/Client.java new file mode 100644 index 0000000000..28954c238a --- /dev/null +++ b/briar-api/src/org/briarproject/api/clients/Client.java @@ -0,0 +1,12 @@ +package org.briarproject.api.clients; + +import org.briarproject.api.db.DbException; +import org.briarproject.api.db.Transaction; + +public interface Client { + + /** + * Called at startup to create any local state needed by the client. + */ + void createLocalState(Transaction txn) throws DbException; +} diff --git a/briar-api/src/org/briarproject/api/clients/PrivateGroupFactory.java b/briar-api/src/org/briarproject/api/clients/PrivateGroupFactory.java index 3a87775724..01e2680172 100644 --- a/briar-api/src/org/briarproject/api/clients/PrivateGroupFactory.java +++ b/briar-api/src/org/briarproject/api/clients/PrivateGroupFactory.java @@ -6,6 +6,9 @@ import org.briarproject.api.sync.Group; public interface PrivateGroupFactory { + /** Creates a group that is not shared with any contacts. */ + Group createLocalGroup(ClientId clientId); + /** Creates a group for the given client to share with the given contact. */ Group createPrivateGroup(ClientId clientId, Contact contact); } diff --git a/briar-api/src/org/briarproject/api/db/DatabaseComponent.java b/briar-api/src/org/briarproject/api/db/DatabaseComponent.java index a360fa98b6..2a627fb8a2 100644 --- a/briar-api/src/org/briarproject/api/db/DatabaseComponent.java +++ b/briar-api/src/org/briarproject/api/db/DatabaseComponent.java @@ -44,6 +44,7 @@ public interface DatabaseComponent { * <p/> * This method acquires locks, so it must not be called while holding a * lock. + * * @param readOnly true if the transaction will only be used for reading. */ Transaction startTransaction(boolean readOnly) throws DbException; @@ -90,13 +91,27 @@ public interface DatabaseComponent { void addTransportKeys(Transaction txn, ContactId c, TransportKeys k) throws DbException; + /** + * Returns true if the database contains the given contact for the given + * local pseudonym. + */ + boolean containsContact(Transaction txn, AuthorId remote, AuthorId local) + throws DbException; + + /** + * Returns true if the database contains the given group. + */ + boolean containsGroup(Transaction txn, GroupId g) throws DbException; + /** * Deletes the message with the given ID. The message ID and any other * associated data are not deleted. */ void deleteMessage(Transaction txn, MessageId m) throws DbException; - /** Deletes any metadata associated with the given message. */ + /** + * Deletes any metadata associated with the given message. + */ void deleteMessageMetadata(Transaction txn, MessageId m) throws DbException; /** @@ -162,13 +177,6 @@ public interface DatabaseComponent { Collection<ContactId> getContacts(Transaction txn, AuthorId a) throws DbException; - /** - * Returns true if the database contains the given contact for the given - * local pseudonym. - */ - boolean containsContact(Transaction txn, AuthorId remote, AuthorId local) - throws DbException; - /** * Returns the unique ID for this device. * <p/> @@ -359,7 +367,7 @@ public interface DatabaseComponent { * Marks the given contact as active or inactive. */ void setContactActive(Transaction txn, ContactId c, boolean active) - throws DbException; + throws DbException; /** * Marks the given message as shared or unshared. diff --git a/briar-api/src/org/briarproject/api/lifecycle/LifecycleManager.java b/briar-api/src/org/briarproject/api/lifecycle/LifecycleManager.java index 5f75237c25..536c9c3093 100644 --- a/briar-api/src/org/briarproject/api/lifecycle/LifecycleManager.java +++ b/briar-api/src/org/briarproject/api/lifecycle/LifecycleManager.java @@ -1,32 +1,49 @@ package org.briarproject.api.lifecycle; +import org.briarproject.api.clients.Client; + import java.util.concurrent.ExecutorService; /** - * Manages the lifecycle of the app, starting and stopping {@link Service - * Services}, shutting down {@link java.util.concurrent.ExecutorService + * Manages the lifecycle of the app, starting {@link + * org.briarproject.api.clients.Client Clients}, starting and stopping {@link + * Service Services}, shutting down {@link java.util.concurrent.ExecutorService * ExecutorServices}, and opening and closing the {@link * org.briarproject.api.db.DatabaseComponent DatabaseComponent}. */ public interface LifecycleManager { - /** The result of calling {@link LifecycleManager#startServices()}. */ - enum StartResult { ALREADY_RUNNING, DB_ERROR, SERVICE_ERROR, SUCCESS } + /** + * The result of calling {@link LifecycleManager#startServices()}. + */ + enum StartResult { + ALREADY_RUNNING, DB_ERROR, SERVICE_ERROR, SUCCESS + } + + /** + * Registers a {@link Service} to be started and stopped. + */ + void registerService(Service s); - /** Registers a {@link Service} to be started and stopped. */ - public void register(Service s); + /** + * Registers a {@link org.briarproject.api.clients.Client Client} to be + * started. + */ + void registerClient(Client c); /** * Registers an {@link java.util.concurrent.ExecutorService ExecutorService} * to be shut down. */ - public void registerForShutdown(ExecutorService e); + void registerForShutdown(ExecutorService e); /** - * Starts any registered {@link Service Services} and opens the {@link - * org.briarproject.api.db.DatabaseComponent DatabaseComponent}. + * Opens the {@link org.briarproject.api.db.DatabaseComponent + * DatabaseComponent} and starts any registered {@link + * org.briarproject.api.clients.Client Clients} and {@link Service + * Services}. */ - public StartResult startServices(); + StartResult startServices(); /** * Stops any registered {@link Service Services}, shuts down any @@ -34,20 +51,21 @@ public interface LifecycleManager { * and closes the {@link org.briarproject.api.db.DatabaseComponent * DatabaseComponent}. */ - public void stopServices(); + void stopServices(); /** * Waits for the {@link org.briarproject.api.db.DatabaseComponent * DatabaseComponent} to be opened before returning. */ - public void waitForDatabase() throws InterruptedException; + void waitForDatabase() throws InterruptedException; /** * Waits for the {@link org.briarproject.api.db.DatabaseComponent - * DatabaseComponent} to be opened and all registered {@link Service + * DatabaseComponent} to be opened and all registered {@link + * org.briarproject.api.clients.Client Clients} and {@link Service * Services} to start before returning. */ - public void waitForStartup() throws InterruptedException; + void waitForStartup() throws InterruptedException; /** * Waits for all registered {@link Service Services} to stop, all @@ -55,5 +73,5 @@ public interface LifecycleManager { * to shut down, and the {@link org.briarproject.api.db.DatabaseComponent * DatabaseComponent} to be closed before returning. */ - public void waitForShutdown() throws InterruptedException; + void waitForShutdown() throws InterruptedException; } \ No newline at end of file diff --git a/briar-core/src/org/briarproject/clients/PrivateGroupFactoryImpl.java b/briar-core/src/org/briarproject/clients/PrivateGroupFactoryImpl.java index bb0ede9441..56ed9f5300 100644 --- a/briar-core/src/org/briarproject/clients/PrivateGroupFactoryImpl.java +++ b/briar-core/src/org/briarproject/clients/PrivateGroupFactoryImpl.java @@ -16,6 +16,8 @@ import javax.inject.Inject; class PrivateGroupFactoryImpl implements PrivateGroupFactory { + private static final byte[] LOCAL_GROUP_DESCRIPTOR = new byte[0]; + private final GroupFactory groupFactory; private final ClientHelper clientHelper; @@ -26,6 +28,11 @@ class PrivateGroupFactoryImpl implements PrivateGroupFactory { this.clientHelper = clientHelper; } + @Override + public Group createLocalGroup(ClientId clientId) { + return groupFactory.createGroup(clientId, LOCAL_GROUP_DESCRIPTOR); + } + @Override public Group createPrivateGroup(ClientId clientId, Contact contact) { AuthorId local = contact.getLocalAuthorId(); diff --git a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java index d3e48748c6..6617823aa8 100644 --- a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java +++ b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java @@ -228,6 +228,20 @@ class DatabaseComponentImpl<T> implements DatabaseComponent { db.addTransportKeys(txn, c, k); } + public boolean containsContact(Transaction transaction, AuthorId remote, + AuthorId local) throws DbException { + T txn = unbox(transaction); + if (!db.containsLocalAuthor(txn, local)) + throw new NoSuchLocalAuthorException(); + return db.containsContact(txn, remote, local); + } + + public boolean containsGroup(Transaction transaction, GroupId g) + throws DbException { + T txn = unbox(transaction); + return db.containsGroup(txn, g); + } + public void deleteMessage(Transaction transaction, MessageId m) throws DbException { if (transaction.isReadOnly()) throw new IllegalArgumentException(); @@ -342,14 +356,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent { return db.getContacts(txn, a); } - public boolean containsContact(Transaction transaction, AuthorId remote, - AuthorId local) throws DbException { - T txn = unbox(transaction); - if (!db.containsLocalAuthor(txn, local)) - throw new NoSuchLocalAuthorException(); - return db.containsContact(txn, remote, local); - } - public DeviceId getDeviceId(Transaction transaction) throws DbException { T txn = unbox(transaction); return db.getDeviceId(txn); diff --git a/briar-core/src/org/briarproject/forum/ForumModule.java b/briar-core/src/org/briarproject/forum/ForumModule.java index 4a51872e7a..f801e2770c 100644 --- a/briar-core/src/org/briarproject/forum/ForumModule.java +++ b/briar-core/src/org/briarproject/forum/ForumModule.java @@ -3,14 +3,13 @@ package org.briarproject.forum; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.contact.ContactManager; import org.briarproject.api.crypto.CryptoComponent; -import org.briarproject.api.data.BdfReaderFactory; import org.briarproject.api.data.MetadataEncoder; -import org.briarproject.api.data.MetadataParser; import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.forum.ForumManager; import org.briarproject.api.forum.ForumPostFactory; import org.briarproject.api.forum.ForumSharingManager; import org.briarproject.api.identity.AuthorFactory; +import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.sync.ValidationManager; import org.briarproject.api.system.Clock; @@ -73,9 +72,11 @@ public class ForumModule { @Provides @Singleton ForumSharingManager provideForumSharingManager( + LifecycleManager lifecycleManager, ContactManager contactManager, ValidationManager validationManager, ForumSharingManagerImpl forumSharingManager) { + lifecycleManager.registerClient(forumSharingManager); contactManager.registerAddContactHook(forumSharingManager); contactManager.registerRemoveContactHook(forumSharingManager); validationManager.registerIncomingMessageHook( diff --git a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java index c30834e8f6..b975a45377 100644 --- a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java +++ b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java @@ -1,6 +1,7 @@ package org.briarproject.forum; import org.briarproject.api.FormatException; +import org.briarproject.api.clients.Client; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.PrivateGroupFactory; import org.briarproject.api.contact.Contact; @@ -43,15 +44,13 @@ import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH; import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH; import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; -class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook, - RemoveContactHook, IncomingMessageHook { +class ForumSharingManagerImpl implements ForumSharingManager, Client, + AddContactHook, RemoveContactHook, IncomingMessageHook { static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString( "cd11a5d04dccd9e2931d6fc3df456313" + "63bb3e9d9d0e9405fccdb051f41f5449")); - private static final byte[] LOCAL_GROUP_DESCRIPTOR = new byte[0]; - private final DatabaseComponent db; private final ForumManager forumManager; private final ClientHelper clientHelper; @@ -73,8 +72,14 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook, this.privateGroupFactory = privateGroupFactory; this.random = random; this.clock = clock; - localGroup = groupFactory.createGroup(CLIENT_ID, - LOCAL_GROUP_DESCRIPTOR); + localGroup = privateGroupFactory.createLocalGroup(CLIENT_ID); + } + + @Override + public void createLocalState(Transaction txn) throws DbException { + db.addGroup(txn, localGroup); + // Ensure we've set things up for any pre-existing contacts + for (Contact c : db.getContacts(txn)) addingContact(txn, c); } @Override @@ -82,6 +87,8 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook, try { // Create a group to share with the contact Group g = getContactGroup(c); + // Return if we've already set things up for this contact + if (db.containsGroup(txn, g.getId())) return; // Store the group and share it with the contact db.addGroup(txn, g); db.setVisibleToContact(txn, c.getId(), g.getId(), true); @@ -297,8 +304,6 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook, private List<Forum> getForumsSharedWithAllContacts(Transaction txn) throws DbException, FormatException { - // Ensure the local group exists - db.addGroup(txn, localGroup); // Find the latest update in the local group LatestUpdate latest = findLatest(txn, localGroup.getId(), true); if (latest == null) return Collections.emptyList(); diff --git a/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java b/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java index a01c62b101..e28af29e4d 100644 --- a/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java +++ b/briar-core/src/org/briarproject/introduction/IntroductionManagerImpl.java @@ -1,6 +1,7 @@ package org.briarproject.introduction; import org.briarproject.api.FormatException; +import org.briarproject.api.clients.Client; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.MessageQueueManager; import org.briarproject.api.clients.PrivateGroupFactory; @@ -31,7 +32,6 @@ import org.briarproject.api.introduction.SessionId; import org.briarproject.api.properties.TransportPropertyManager; import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.Group; -import org.briarproject.api.sync.GroupFactory; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.Message; import org.briarproject.api.sync.MessageId; @@ -82,14 +82,13 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUE import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE; class IntroductionManagerImpl extends BdfIncomingMessageHook - implements IntroductionManager, AddContactHook, RemoveContactHook { + implements IntroductionManager, Client, AddContactHook, + RemoveContactHook { static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString( "23b1897c198a90ae75b976ac023d0f32" + "80ca67b12f2346b2c23a34f34e2434c3")); - private static final byte[] LOCAL_GROUP_DESCRIPTOR = new byte[0]; - private static final Logger LOG = Logger.getLogger(IntroductionManagerImpl.class.getName()); @@ -104,8 +103,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook @Inject IntroductionManagerImpl(DatabaseComponent db, MessageQueueManager messageQueueManager, - ClientHelper clientHelper, GroupFactory groupFactory, - PrivateGroupFactory privateGroupFactory, + ClientHelper clientHelper, PrivateGroupFactory privateGroupFactory, MetadataEncoder metadataEncoder, MetadataParser metadataParser, CryptoComponent cryptoComponent, TransportPropertyManager transportPropertyManager, @@ -117,6 +115,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook this.messageQueueManager = messageQueueManager; this.privateGroupFactory = privateGroupFactory; this.metadataEncoder = metadataEncoder; + // TODO: Inject these dependencies for easier testing this.introducerManager = new IntroducerManager(this, clientHelper, clock, cryptoComponent); @@ -124,8 +123,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook new IntroduceeManager(db, this, clientHelper, clock, cryptoComponent, transportPropertyManager, authorFactory, contactManager); - localGroup = - groupFactory.createGroup(CLIENT_ID, LOCAL_GROUP_DESCRIPTOR); + localGroup = privateGroupFactory.createLocalGroup(CLIENT_ID); } @Override @@ -133,11 +131,21 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook return CLIENT_ID; } + @Override + public void createLocalState(Transaction txn) throws DbException { + db.addGroup(txn, localGroup); + // Ensure we've set things up for any pre-existing contacts + for (Contact c : db.getContacts(txn)) addingContact(txn, c); + } + @Override public void addingContact(Transaction txn, Contact c) throws DbException { try { - // create an introduction group for sending introduction messages + // Create an introduction group for sending introduction messages Group g = getIntroductionGroup(c); + // Return if we've already set things up for this contact + if (db.containsGroup(txn, g.getId())) return; + // Store the group and share it with the contact db.addGroup(txn, g); db.setVisibleToContact(txn, c.getId(), g.getId(), true); // Attach the contact ID to the group @@ -169,7 +177,6 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook introducerManager.abort(txn, d); } } - } } catch (FormatException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); @@ -189,9 +196,6 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook protected void incomingMessage(Transaction txn, Message m, BdfList body, BdfDictionary message) throws DbException { - // add local group for engine states to make sure it exists - db.addGroup(txn, localGroup); - // Get message data and type GroupId groupId = m.getGroupId(); message.put(GROUP_ID, groupId); @@ -265,15 +269,13 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook public void makeIntroduction(Contact c1, Contact c2, String msg) throws DbException, FormatException { - Transaction txn = db.startTransaction(false); - try { - // add local group for session states to make sure it exists - db.addGroup(txn, getLocalGroup()); - introducerManager.makeIntroduction(txn, c1, c2, msg); - txn.setComplete(); - } finally { - db.endTransaction(txn); - } + Transaction txn = db.startTransaction(false); + try { + introducerManager.makeIntroduction(txn, c1, c2, msg); + txn.setComplete(); + } finally { + db.endTransaction(txn); + } } @Override @@ -468,7 +470,7 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook } if (LOG.isLoggable(WARNING)) { LOG.warning( - "No session state found for this message with session ID " + + "No session state found for message with session ID " + Arrays.hashCode(sessionId)); } throw new FormatException(); @@ -505,5 +507,4 @@ class IntroductionManagerImpl extends BdfIncomingMessageHook db.deleteMessage(txn, messageId); db.deleteMessageMetadata(txn, messageId); } - } diff --git a/briar-core/src/org/briarproject/introduction/IntroductionModule.java b/briar-core/src/org/briarproject/introduction/IntroductionModule.java index 686a34edad..4fb0e493df 100644 --- a/briar-core/src/org/briarproject/introduction/IntroductionModule.java +++ b/briar-core/src/org/briarproject/introduction/IntroductionModule.java @@ -5,6 +5,7 @@ import org.briarproject.api.clients.MessageQueueManager; import org.briarproject.api.contact.ContactManager; import org.briarproject.api.data.MetadataEncoder; import org.briarproject.api.introduction.IntroductionManager; +import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.system.Clock; import javax.inject.Inject; @@ -41,15 +42,17 @@ public class IntroductionModule { @Provides @Singleton IntroductionManager getIntroductionManager( + LifecycleManager lifecycleManager, ContactManager contactManager, MessageQueueManager messageQueueManager, IntroductionManagerImpl introductionManager) { + lifecycleManager.registerClient(introductionManager); contactManager.registerAddContactHook(introductionManager); contactManager.registerRemoveContactHook(introductionManager); - messageQueueManager - .registerIncomingMessageHook(introductionManager.getClientId(), - introductionManager); + messageQueueManager.registerIncomingMessageHook( + introductionManager.getClientId(), + introductionManager); return introductionManager; } diff --git a/briar-core/src/org/briarproject/lifecycle/LifecycleManagerImpl.java b/briar-core/src/org/briarproject/lifecycle/LifecycleManagerImpl.java index f153a3a377..bd2d31765c 100644 --- a/briar-core/src/org/briarproject/lifecycle/LifecycleManagerImpl.java +++ b/briar-core/src/org/briarproject/lifecycle/LifecycleManagerImpl.java @@ -1,14 +1,16 @@ package org.briarproject.lifecycle; +import org.briarproject.api.clients.Client; import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DbException; +import org.briarproject.api.db.Transaction; import org.briarproject.api.event.EventBus; import org.briarproject.api.event.ShutdownEvent; import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.lifecycle.Service; import java.io.IOException; -import java.util.Collection; +import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -31,8 +33,9 @@ class LifecycleManagerImpl implements LifecycleManager { private final DatabaseComponent db; private final EventBus eventBus; - private final Collection<Service> services; - private final Collection<ExecutorService> executors; + private final List<Service> services; + private final List<Client> clients; + private final List<ExecutorService> executors; private final Semaphore startStopSemaphore = new Semaphore(1); private final CountDownLatch dbLatch = new CountDownLatch(1); private final CountDownLatch startupLatch = new CountDownLatch(1); @@ -43,15 +46,22 @@ class LifecycleManagerImpl implements LifecycleManager { this.db = db; this.eventBus = eventBus; services = new CopyOnWriteArrayList<Service>(); + clients = new CopyOnWriteArrayList<Client>(); executors = new CopyOnWriteArrayList<ExecutorService>(); } - public void register(Service s) { + public void registerService(Service s) { if (LOG.isLoggable(INFO)) LOG.info("Registering service " + s.getClass().getName()); services.add(s); } + public void registerClient(Client c) { + if (LOG.isLoggable(INFO)) + LOG.info("Registering client " + c.getClass().getName()); + clients.add(c); + } + public void registerForShutdown(ExecutorService e) { if (LOG.isLoggable(INFO)) LOG.info("Registering executor " + e.getClass().getName()); @@ -74,15 +84,28 @@ class LifecycleManagerImpl implements LifecycleManager { else LOG.info("Creating database took " + duration + " ms"); } dbLatch.countDown(); + Transaction txn = db.startTransaction(false); + try { + for (Client c : clients) { + start = System.currentTimeMillis(); + c.createLocalState(txn); + duration = System.currentTimeMillis() - start; + if (LOG.isLoggable(INFO)) { + LOG.info("Starting " + c.getClass().getName() + + " took " + duration + " ms"); + } + } + txn.setComplete(); + } finally { + db.endTransaction(txn); + } for (Service s : services) { start = System.currentTimeMillis(); boolean started = s.start(); duration = System.currentTimeMillis() - start; if (!started) { - if (LOG.isLoggable(WARNING)) { - String name = s.getClass().getName(); - LOG.warning(name + " did not start"); - } + if (LOG.isLoggable(WARNING)) + LOG.warning(s.getClass().getName() + " did not start"); return SERVICE_ERROR; } if (LOG.isLoggable(INFO)) { diff --git a/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java b/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java index e7e64552f5..93a0cc979c 100644 --- a/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java +++ b/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java @@ -1,6 +1,7 @@ package org.briarproject.messaging; import org.briarproject.api.FormatException; +import org.briarproject.api.clients.Client; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.PrivateGroupFactory; import org.briarproject.api.contact.Contact; @@ -28,7 +29,7 @@ import java.util.Map; import javax.inject.Inject; -class MessagingManagerImpl implements MessagingManager, AddContactHook, +class MessagingManagerImpl implements MessagingManager, Client, AddContactHook, RemoveContactHook { static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString( @@ -47,11 +48,19 @@ class MessagingManagerImpl implements MessagingManager, AddContactHook, this.privateGroupFactory = privateGroupFactory; } + @Override + public void createLocalState(Transaction txn) throws DbException { + // Ensure we've set things up for any pre-existing contacts + for (Contact c : db.getContacts(txn)) addingContact(txn, c); + } + @Override public void addingContact(Transaction txn, Contact c) throws DbException { try { // Create a group to share with the contact Group g = getContactGroup(c); + // Return if we've already set things up for this contact + if (db.containsGroup(txn, g.getId())) return; // Store the group and share it with the contact db.addGroup(txn, g); db.setVisibleToContact(txn, c.getId(), g.getId(), true); diff --git a/briar-core/src/org/briarproject/messaging/MessagingModule.java b/briar-core/src/org/briarproject/messaging/MessagingModule.java index b943a6921d..8fec2d9b6c 100644 --- a/briar-core/src/org/briarproject/messaging/MessagingModule.java +++ b/briar-core/src/org/briarproject/messaging/MessagingModule.java @@ -3,6 +3,7 @@ package org.briarproject.messaging; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.contact.ContactManager; import org.briarproject.api.data.MetadataEncoder; +import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.messaging.MessagingManager; import org.briarproject.api.messaging.PrivateMessageFactory; import org.briarproject.api.sync.ValidationManager; @@ -43,8 +44,10 @@ public class MessagingModule { @Provides @Singleton - MessagingManager getMessagingManager(ContactManager contactManager, + MessagingManager getMessagingManager(LifecycleManager lifecycleManager, + ContactManager contactManager, MessagingManagerImpl messagingManager) { + lifecycleManager.registerClient(messagingManager); contactManager.registerAddContactHook(messagingManager); contactManager.registerRemoveContactHook(messagingManager); return messagingManager; diff --git a/briar-core/src/org/briarproject/plugins/PluginsModule.java b/briar-core/src/org/briarproject/plugins/PluginsModule.java index d106d8920f..4129486659 100644 --- a/briar-core/src/org/briarproject/plugins/PluginsModule.java +++ b/briar-core/src/org/briarproject/plugins/PluginsModule.java @@ -64,7 +64,7 @@ public class PluginsModule { @Singleton PluginManager getPluginManager(LifecycleManager lifecycleManager, PluginManagerImpl pluginManager) { - lifecycleManager.register(pluginManager); + lifecycleManager.registerService(pluginManager); return pluginManager; } } diff --git a/briar-core/src/org/briarproject/properties/PropertiesModule.java b/briar-core/src/org/briarproject/properties/PropertiesModule.java index e9f2fcf580..cea2c7504e 100644 --- a/briar-core/src/org/briarproject/properties/PropertiesModule.java +++ b/briar-core/src/org/briarproject/properties/PropertiesModule.java @@ -3,6 +3,7 @@ package org.briarproject.properties; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.contact.ContactManager; import org.briarproject.api.data.MetadataEncoder; +import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.properties.TransportPropertyManager; import org.briarproject.api.sync.ValidationManager; import org.briarproject.api.system.Clock; @@ -36,8 +37,10 @@ public class PropertiesModule { @Provides @Singleton TransportPropertyManager getTransportPropertyManager( + LifecycleManager lifecycleManager, ContactManager contactManager, TransportPropertyManagerImpl transportPropertyManager) { + lifecycleManager.registerClient(transportPropertyManager); contactManager.registerAddContactHook(transportPropertyManager); contactManager.registerRemoveContactHook(transportPropertyManager); return transportPropertyManager; diff --git a/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java b/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java index 4b10c48ede..f393e3eaa2 100644 --- a/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java +++ b/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java @@ -3,6 +3,7 @@ package org.briarproject.properties; import org.briarproject.api.DeviceId; import org.briarproject.api.FormatException; import org.briarproject.api.TransportId; +import org.briarproject.api.clients.Client; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.PrivateGroupFactory; import org.briarproject.api.contact.Contact; @@ -13,13 +14,11 @@ import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfList; import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DbException; -import org.briarproject.api.db.NoSuchGroupException; import org.briarproject.api.db.Transaction; import org.briarproject.api.properties.TransportProperties; import org.briarproject.api.properties.TransportPropertyManager; import org.briarproject.api.sync.ClientId; import org.briarproject.api.sync.Group; -import org.briarproject.api.sync.GroupFactory; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.Message; import org.briarproject.api.sync.MessageId; @@ -34,14 +33,12 @@ import java.util.Map.Entry; import javax.inject.Inject; class TransportPropertyManagerImpl implements TransportPropertyManager, - AddContactHook, RemoveContactHook { + Client, AddContactHook, RemoveContactHook { static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString( "673ea091673561e28f70122f6a8ea8f4" + "97c3624b86fa07f785bb15f09fb87b4b")); - private static final byte[] LOCAL_GROUP_DESCRIPTOR = new byte[0]; - private final DatabaseComponent db; private final ClientHelper clientHelper; private final PrivateGroupFactory privateGroupFactory; @@ -50,20 +47,28 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, @Inject TransportPropertyManagerImpl(DatabaseComponent db, - ClientHelper clientHelper, GroupFactory groupFactory, - PrivateGroupFactory privateGroupFactory, Clock clock) { + ClientHelper clientHelper, PrivateGroupFactory privateGroupFactory, + Clock clock) { this.db = db; this.clientHelper = clientHelper; this.privateGroupFactory = privateGroupFactory; this.clock = clock; - localGroup = groupFactory.createGroup(CLIENT_ID, - LOCAL_GROUP_DESCRIPTOR); + localGroup = privateGroupFactory.createLocalGroup(CLIENT_ID); + } + + @Override + public void createLocalState(Transaction txn) throws DbException { + db.addGroup(txn, localGroup); + // Ensure we've set things up for any pre-existing contacts + for (Contact c : db.getContacts(txn)) addingContact(txn, c); } @Override public void addingContact(Transaction txn, Contact c) throws DbException { // Create a group to share with the contact Group g = getContactGroup(c); + // Return if we've already set things up for this contact + if (db.containsGroup(txn, g.getId())) return; // Store the group and share it with the contact db.addGroup(txn, g); db.setVisibleToContact(txn, c.getId(), g.getId(), true); @@ -126,9 +131,6 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, db.endTransaction(txn); } return p; - } catch (NoSuchGroupException e) { - // Local group doesn't exist - there are no local properties - return null; } catch (FormatException e) { throw new DbException(e); } @@ -169,8 +171,6 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, try { Transaction txn = db.startTransaction(false); try { - // Create the local group if necessary - db.addGroup(txn, localGroup); // Merge the new properties with any existing properties TransportProperties merged; boolean changed; @@ -230,9 +230,6 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, local.put(e.getKey(), parseProperties(message)); } return local; - } catch (NoSuchGroupException e) { - // Local group doesn't exist - there are no local properties - return Collections.emptyMap(); } catch (FormatException e) { throw new DbException(e); } diff --git a/briar-core/src/org/briarproject/sync/SyncModule.java b/briar-core/src/org/briarproject/sync/SyncModule.java index 15d13ce66f..2cbbac5d79 100644 --- a/briar-core/src/org/briarproject/sync/SyncModule.java +++ b/briar-core/src/org/briarproject/sync/SyncModule.java @@ -62,7 +62,7 @@ public class SyncModule { @Singleton ValidationManager getValidationManager(LifecycleManager lifecycleManager, EventBus eventBus, ValidationManagerImpl validationManager) { - lifecycleManager.register(validationManager); + lifecycleManager.registerService(validationManager); eventBus.addListener(validationManager); return validationManager; } diff --git a/briar-core/src/org/briarproject/transport/TransportModule.java b/briar-core/src/org/briarproject/transport/TransportModule.java index d5819fbfcb..5cc81e458a 100644 --- a/briar-core/src/org/briarproject/transport/TransportModule.java +++ b/briar-core/src/org/briarproject/transport/TransportModule.java @@ -37,7 +37,7 @@ public class TransportModule { @Singleton KeyManager getKeyManager(LifecycleManager lifecycleManager, EventBus eventBus, KeyManagerImpl keyManager) { - lifecycleManager.register(keyManager); + lifecycleManager.registerService(keyManager); eventBus.addListener(keyManager); return keyManager; } diff --git a/briar-tests/src/org/briarproject/TestLifecycleModule.java b/briar-tests/src/org/briarproject/TestLifecycleModule.java index fbf07ca0d4..04137713c0 100644 --- a/briar-tests/src/org/briarproject/TestLifecycleModule.java +++ b/briar-tests/src/org/briarproject/TestLifecycleModule.java @@ -1,5 +1,6 @@ package org.briarproject; +import org.briarproject.api.clients.Client; import org.briarproject.api.lifecycle.IoExecutor; import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.lifecycle.Service; @@ -20,8 +21,14 @@ public class TestLifecycleModule { @Provides LifecycleManager provideLifecycleManager() { return new LifecycleManager() { + @Override - public void register(Service s) { + public void registerService(Service s) { + + } + + @Override + public void registerClient(Client c) { } @@ -60,6 +67,7 @@ public class TestLifecycleModule { @Provides ShutdownManager provideShutdownManager() { return new ShutdownManager() { + @Override public int addShutdownHook(Runnable hook) { return 0; @@ -75,8 +83,7 @@ public class TestLifecycleModule { @Provides @IoExecutor @Singleton - Executor provideExecutor() { + Executor provideIoExecutor() { return Executors.newCachedThreadPool(); } - } -- GitLab