diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/ClientVersion.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/ClientMajorVersion.java similarity index 73% rename from bramble-core/src/main/java/org/briarproject/bramble/sync/ClientVersion.java rename to bramble-core/src/main/java/org/briarproject/bramble/sync/ClientMajorVersion.java index bd2d85b03819f486cbb355442ac5893563c26034..dfce298074c0e82135a27bc72183f2e5ec0d1bb7 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/ClientVersion.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/ClientMajorVersion.java @@ -7,20 +7,20 @@ import javax.annotation.concurrent.Immutable; @Immutable @NotNullByDefault -class ClientVersion implements Comparable<ClientVersion> { +class ClientMajorVersion implements Comparable<ClientMajorVersion> { final ClientId clientId; final int majorVersion; - ClientVersion(ClientId clientId, int majorVersion) { + ClientMajorVersion(ClientId clientId, int majorVersion) { this.clientId = clientId; this.majorVersion = majorVersion; } @Override public boolean equals(Object o) { - if (o instanceof ClientVersion) { - ClientVersion cv = (ClientVersion) o; + if (o instanceof ClientMajorVersion) { + ClientMajorVersion cv = (ClientMajorVersion) o; return clientId.equals(cv.clientId) && majorVersion == cv.majorVersion; } @@ -33,7 +33,7 @@ class ClientVersion implements Comparable<ClientVersion> { } @Override - public int compareTo(ClientVersion cv) { + public int compareTo(ClientMajorVersion cv) { int compare = clientId.compareTo(cv.clientId); if (compare != 0) return compare; return majorVersion - cv.majorVersion; diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/ClientVersioningManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/ClientVersioningManagerImpl.java index 6c9191f29f177f3eedbb12d608b1a545d826e1d0..6f74036d8bdb96dafec05f402a74a0bea00a6ff3 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/ClientVersioningManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/ClientVersioningManagerImpl.java @@ -61,15 +61,13 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, private final Clock clock; private final Group localGroup; - private final List<ClientMinorVersion> clients = - new CopyOnWriteArrayList<>(); - private final Map<ClientVersion, ClientVersioningHook> hooks = + private final List<ClientVersion> clients = new CopyOnWriteArrayList<>(); + private final Map<ClientMajorVersion, ClientVersioningHook> hooks = new ConcurrentHashMap<>(); @Inject - ClientVersioningManagerImpl(DatabaseComponent db, - ClientHelper clientHelper, ContactGroupFactory contactGroupFactory, - Clock clock) { + ClientVersioningManagerImpl(DatabaseComponent db, ClientHelper clientHelper, + ContactGroupFactory contactGroupFactory, Clock clock) { this.db = db; this.clientHelper = clientHelper; this.contactGroupFactory = contactGroupFactory; @@ -81,15 +79,14 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, @Override public void registerClient(ClientId clientId, int majorVersion, int minorVersion, ClientVersioningHook hook) { - clients.add(new ClientMinorVersion(clientId, majorVersion, - minorVersion)); - hooks.put(new ClientVersion(clientId, majorVersion), hook); + ClientMajorVersion cv = new ClientMajorVersion(clientId, majorVersion); + clients.add(new ClientVersion(cv, minorVersion)); + hooks.put(cv, hook); } @Override - public Visibility getClientVisibility(Transaction txn, - ContactId contactId, ClientId clientId, int majorVersion) - throws DbException { + public Visibility getClientVisibility(Transaction txn, ContactId contactId, + ClientId clientId, int majorVersion) throws DbException { try { Contact contact = db.getContact(txn, contactId); Group g = getContactGroup(contact); @@ -101,9 +98,10 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, if (latest.remote == null) return INVISIBLE; Update localUpdate = loadUpdate(txn, latest.local.messageId); Update remoteUpdate = loadUpdate(txn, latest.remote.messageId); - Map<ClientVersion, Visibility> visibilities = + Map<ClientMajorVersion, Visibility> visibilities = getVisibilities(localUpdate.states, remoteUpdate.states); - ClientVersion cv = new ClientVersion(clientId, majorVersion); + ClientMajorVersion cv = + new ClientMajorVersion(clientId, majorVersion); Visibility v = visibilities.get(cv); return v == null ? INVISIBLE : v; } catch (FormatException e) { @@ -121,7 +119,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, @Override public void startService() throws ServiceException { - List<ClientMinorVersion> versions = new ArrayList<>(clients); + List<ClientVersion> versions = new ArrayList<>(clients); Collections.sort(versions); try { Transaction txn = db.startTransaction(false); @@ -158,7 +156,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, throw new AssertionError(e); } // Create and store the first local update - List<ClientMinorVersion> versions = new ArrayList<>(clients); + List<ClientVersion> versions = new ArrayList<>(clients); Collections.sort(versions); storeFirstUpdate(txn, g.getId(), versions); } @@ -213,9 +211,9 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, oldLocalUpdateVersion + 1); } // Calculate the old and new client visibilities - Map<ClientVersion, Visibility> before = + Map<ClientMajorVersion, Visibility> before = getVisibilities(oldLocalStates, oldRemoteStates); - Map<ClientVersion, Visibility> after = + Map<ClientMajorVersion, Visibility> after = getVisibilities(newLocalStates, newRemoteStates); // Call hooks for any visibilities that have changed Contact c = getContact(txn, m.getGroupId()); @@ -227,7 +225,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, } private void storeClientVersions(Transaction txn, - List<ClientMinorVersion> versions) throws DbException { + List<ClientVersion> versions) throws DbException { long now = clock.currentTimeMillis(); BdfList body = encodeClientVersions(versions); try { @@ -239,34 +237,37 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, } } - private BdfList encodeClientVersions(List<ClientMinorVersion> versions) { + private BdfList encodeClientVersions(List<ClientVersion> versions) { BdfList encoded = new BdfList(); - for (ClientMinorVersion cm : versions) - encoded.add(encodeClientVersion(cm)); + for (ClientVersion cv : versions) encoded.add(encodeClientVersion(cv)); return encoded; } - private BdfList encodeClientVersion(ClientMinorVersion cm) { - return BdfList.of(cm.version.clientId.getString(), - cm.version.majorVersion, cm.minorVersion); + private BdfList encodeClientVersion(ClientVersion cv) { + return BdfList.of(cv.majorVersion.clientId.getString(), + cv.majorVersion.majorVersion, cv.minorVersion); } + /** + * Stores the local client versions and returns true if an update needs to + * be sent to contacts. + */ private boolean updateClientVersions(Transaction txn, - List<ClientMinorVersion> newVersions) throws DbException { + List<ClientVersion> newVersions) throws DbException { Collection<MessageId> ids = db.getMessageIds(txn, localGroup.getId()); if (ids.isEmpty()) { storeClientVersions(txn, newVersions); return true; } MessageId m = ids.iterator().next(); - List<ClientMinorVersion> oldVersions = loadClientVersions(txn, m); + List<ClientVersion> oldVersions = loadClientVersions(txn, m); if (oldVersions.equals(newVersions)) return false; db.removeMessage(txn, m); storeClientVersions(txn, newVersions); return true; } - private List<ClientMinorVersion> loadClientVersions(Transaction txn, + private List<ClientVersion> loadClientVersions(Transaction txn, MessageId m) throws DbException { try { BdfList body = clientHelper.getMessageAsList(txn, m); @@ -277,23 +278,23 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, } } - private List<ClientMinorVersion> parseClientVersions(BdfList body) + private List<ClientVersion> parseClientVersions(BdfList body) throws FormatException { int size = body.size(); - List<ClientMinorVersion> parsed = new ArrayList<>(size); + List<ClientVersion> parsed = new ArrayList<>(size); for (int i = 0; i < size; i++) { BdfList cv = body.getList(i); ClientId clientId = new ClientId(cv.getString(0)); int majorVersion = cv.getLong(1).intValue(); int minorVersion = cv.getLong(2).intValue(); - parsed.add(new ClientMinorVersion(clientId, majorVersion, + parsed.add(new ClientVersion(clientId, majorVersion, minorVersion)); } return parsed; } private void clientVersionsUpdated(Transaction txn, Contact c, - List<ClientMinorVersion> versions) throws DbException { + List<ClientVersion> versions) throws DbException { try { // Find the latest local and remote updates Group g = getContactGroup(c); @@ -316,9 +317,9 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, if (latest.remote == null) remoteStates = emptyList(); else remoteStates = loadUpdate(txn, latest.remote.messageId).states; // Calculate the old and new client visibilities - Map<ClientVersion, Visibility> before = + Map<ClientMajorVersion, Visibility> before = getVisibilities(oldLocalStates, remoteStates); - Map<ClientVersion, Visibility> after = + Map<ClientMajorVersion, Visibility> after = getVisibilities(newLocalStates, remoteStates); // Call hooks for any visibilities that have changed callVisibilityHooks(txn, c, before, after); @@ -390,14 +391,14 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, } private List<ClientState> updateStatesFromLocalVersions( - List<ClientState> oldStates, List<ClientMinorVersion> newVersions) { - Map<ClientVersion, ClientState> oldMap = new HashMap<>(); - for (ClientState cs : oldStates) oldMap.put(cs.version, cs); + List<ClientState> oldStates, List<ClientVersion> newVersions) { + Map<ClientMajorVersion, ClientState> oldMap = new HashMap<>(); + for (ClientState cs : oldStates) oldMap.put(cs.majorVersion, cs); List<ClientState> newStates = new ArrayList<>(newVersions.size()); - for (ClientMinorVersion newVersion : newVersions) { - ClientState oldState = oldMap.get(newVersion.version); + for (ClientVersion newVersion : newVersions) { + ClientState oldState = oldMap.get(newVersion.majorVersion); boolean active = oldState != null && oldState.active; - newStates.add(new ClientState(newVersion.version, + newStates.add(new ClientState(newVersion.majorVersion, newVersion.minorVersion, active)); } return newStates; @@ -425,32 +426,31 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, } private BdfList encodeClientState(ClientState cs) { - return BdfList.of(cs.version.clientId.getString(), - cs.version.majorVersion, cs.minorVersion, cs.active); + return BdfList.of(cs.majorVersion.clientId.getString(), + cs.majorVersion.majorVersion, cs.minorVersion, cs.active); } - private Map<ClientVersion, Visibility> getVisibilities( + private Map<ClientMajorVersion, Visibility> getVisibilities( List<ClientState> localStates, List<ClientState> remoteStates) { - Map<ClientVersion, ClientState> remoteMap = new HashMap<>(); - for (ClientState remote : remoteStates) - remoteMap.put(remote.version, remote); - Map<ClientVersion, Visibility> visibilities = new HashMap<>(); + Map<ClientMajorVersion, ClientState> remoteMap = new HashMap<>(); + for (ClientState cs : remoteStates) remoteMap.put(cs.majorVersion, cs); + Map<ClientMajorVersion, Visibility> visibilities = new HashMap<>(); for (ClientState local : localStates) { - ClientState remote = remoteMap.get(local.version); - if (remote == null) visibilities.put(local.version, INVISIBLE); - else if (remote.active) visibilities.put(local.version, SHARED); - else visibilities.put(local.version, VISIBLE); + ClientState remote = remoteMap.get(local.majorVersion); + if (remote == null) visibilities.put(local.majorVersion, INVISIBLE); + else if (remote.active) visibilities.put(local.majorVersion, SHARED); + else visibilities.put(local.majorVersion, VISIBLE); } return visibilities; } private void callVisibilityHooks(Transaction txn, Contact c, - Map<ClientVersion, Visibility> before, - Map<ClientVersion, Visibility> after) throws DbException { - Set<ClientVersion> keys = new TreeSet<>(); + Map<ClientMajorVersion, Visibility> before, + Map<ClientMajorVersion, Visibility> after) throws DbException { + Set<ClientMajorVersion> keys = new TreeSet<>(); keys.addAll(before.keySet()); keys.addAll(after.keySet()); - for (ClientVersion cv : keys) { + for (ClientMajorVersion cv : keys) { Visibility vBefore = before.get(cv), vAfter = after.get(cv); if (vAfter == null) { callVisibilityHook(txn, cv, c, INVISIBLE); @@ -460,17 +460,19 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, } } - private void callVisibilityHook(Transaction txn, ClientVersion cv, + private void callVisibilityHook(Transaction txn, ClientMajorVersion cv, Contact c, Visibility v) throws DbException { ClientVersioningHook hook = hooks.get(cv); if (hook != null) hook.onClientVisibilityChanging(txn, c, v); } private void storeFirstUpdate(Transaction txn, GroupId g, - List<ClientMinorVersion> versions) throws DbException { + List<ClientVersion> versions) throws DbException { List<ClientState> states = new ArrayList<>(versions.size()); - for (ClientMinorVersion cm : versions) - states.add(new ClientState(cm.version, cm.minorVersion, false)); + for (ClientVersion cv : versions) { + states.add(new ClientState(cv.majorVersion, cv.minorVersion, + false)); + } storeUpdate(txn, g, states, 1); } @@ -487,13 +489,13 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, private List<ClientState> updateStatesFromRemoteStates( List<ClientState> oldLocalStates, List<ClientState> remoteStates) { - Set<ClientVersion> remoteSet = new HashSet<>(); - for (ClientState remote : remoteStates) remoteSet.add(remote.version); + Set<ClientMajorVersion> remoteSet = new HashSet<>(); + for (ClientState cs : remoteStates) remoteSet.add(cs.majorVersion); List<ClientState> newLocalStates = new ArrayList<>(oldLocalStates.size()); for (ClientState oldState : oldLocalStates) { - boolean active = remoteSet.contains(oldState.version); - newLocalStates.add(new ClientState(oldState.version, + boolean active = remoteSet.contains(oldState.majorVersion); + newLocalStates.add(new ClientState(oldState.majorVersion, oldState.minorVersion, active)); } return newLocalStates; @@ -533,61 +535,61 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, } } - private static class ClientMinorVersion - implements Comparable<ClientMinorVersion> { + private static class ClientVersion implements Comparable<ClientVersion> { - private final ClientVersion version; + private final ClientMajorVersion majorVersion; private final int minorVersion; - private ClientMinorVersion(ClientVersion version, int minorVersion) { - this.version = version; + private ClientVersion(ClientMajorVersion majorVersion, + int minorVersion) { + this.majorVersion = majorVersion; this.minorVersion = minorVersion; } - private ClientMinorVersion(ClientId clientId, int majorVersion, + private ClientVersion(ClientId clientId, int majorVersion, int minorVersion) { - this(new ClientVersion(clientId, majorVersion), minorVersion); + this(new ClientMajorVersion(clientId, majorVersion), minorVersion); } @Override public boolean equals(Object o) { - if (o instanceof ClientMinorVersion) { - ClientMinorVersion cm = (ClientMinorVersion) o; - return version.equals(cm.version) - && minorVersion == cm.minorVersion; + if (o instanceof ClientVersion) { + ClientVersion cv = (ClientVersion) o; + return majorVersion.equals(cv.majorVersion) + && minorVersion == cv.minorVersion; } return false; } @Override public int hashCode() { - return version.hashCode(); + return majorVersion.hashCode(); } @Override - public int compareTo(ClientMinorVersion cm) { - int compare = version.compareTo(cm.version); + public int compareTo(ClientVersion cv) { + int compare = majorVersion.compareTo(cv.majorVersion); if (compare != 0) return compare; - return minorVersion - cm.minorVersion; + return minorVersion - cv.minorVersion; } } private static class ClientState { - private final ClientVersion version; + private final ClientMajorVersion majorVersion; private final int minorVersion; private final boolean active; - private ClientState(ClientVersion version, int minorVersion, + private ClientState(ClientMajorVersion majorVersion, int minorVersion, boolean active) { - this.version = version; + this.majorVersion = majorVersion; this.minorVersion = minorVersion; this.active = active; } private ClientState(ClientId clientId, int majorVersion, int minorVersion, boolean active) { - this(new ClientVersion(clientId, majorVersion), minorVersion, + this(new ClientMajorVersion(clientId, majorVersion), minorVersion, active); } @@ -595,7 +597,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, public boolean equals(Object o) { if (o instanceof ClientState) { ClientState cs = (ClientState) o; - return version.equals(cs.version) + return majorVersion.equals(cs.majorVersion) && minorVersion == cs.minorVersion && active == cs.active; } @@ -604,7 +606,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client, @Override public int hashCode() { - return version.hashCode(); + return majorVersion.hashCode(); } } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/ValidationManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/ValidationManagerImpl.java index f6f977b7305d6af334a670ed0a9022f9200b1ae7..9565e889f12ef04364e61cadecca0f822ddea0cb 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/ValidationManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/ValidationManagerImpl.java @@ -51,8 +51,8 @@ class ValidationManagerImpl implements ValidationManager, Service, private final DatabaseComponent db; private final Executor dbExecutor, validationExecutor; private final MessageFactory messageFactory; - private final Map<ClientVersion, MessageValidator> validators; - private final Map<ClientVersion, IncomingMessageHook> hooks; + private final Map<ClientMajorVersion, MessageValidator> validators; + private final Map<ClientMajorVersion, IncomingMessageHook> hooks; private final AtomicBoolean used = new AtomicBoolean(false); @Inject @@ -83,13 +83,13 @@ class ValidationManagerImpl implements ValidationManager, Service, @Override public void registerMessageValidator(ClientId c, int majorVersion, MessageValidator v) { - validators.put(new ClientVersion(c, majorVersion), v); + validators.put(new ClientMajorVersion(c, majorVersion), v); } @Override public void registerIncomingMessageHook(ClientId c, int majorVersion, IncomingMessageHook hook) { - hooks.put(new ClientVersion(c, majorVersion), hook); + hooks.put(new ClientMajorVersion(c, majorVersion), hook); } private void validateOutstandingMessagesAsync() { @@ -240,8 +240,8 @@ class ValidationManagerImpl implements ValidationManager, Service, @ValidationExecutor private void validateMessage(Message m, Group g) { - ClientVersion cv = - new ClientVersion(g.getClientId(), g.getMajorVersion()); + ClientMajorVersion cv = + new ClientMajorVersion(g.getClientId(), g.getMajorVersion()); MessageValidator v = validators.get(cv); if (v == null) { if (LOG.isLoggable(WARNING)) LOG.warning("No validator for " + cv); @@ -334,7 +334,7 @@ class ValidationManagerImpl implements ValidationManager, Service, ClientId c, int majorVersion, Metadata meta) throws DbException { // Deliver the message to the client if it's registered a hook boolean shareMsg = false; - ClientVersion cv = new ClientVersion(c, majorVersion); + ClientMajorVersion cv = new ClientMajorVersion(c, majorVersion); IncomingMessageHook hook = hooks.get(cv); if (hook != null) { try {