diff options
author | CNlucius <lukai1@huawei.com> | 2016-09-13 11:40:12 +0800 |
---|---|---|
committer | CNlucius <lukai1@huawei.com> | 2016-09-13 11:41:53 +0800 |
commit | b731e2f1dd0972409b136aebc7b463dd72c9cfad (patch) | |
tree | 5107d7d80c19ad8076c2c97c2b5ef8d1cf3ab903 /framework/src/onos/core/store | |
parent | ee93993458266114c29271a481ef9ce7ce621b2a (diff) |
ONOSFW-171
O/S-SFC-ONOS scenario documentation
Change-Id: I51ae1cf736ea24ab6680f8edca1b2bf5dd598365
Signed-off-by: CNlucius <lukai1@huawei.com>
Diffstat (limited to 'framework/src/onos/core/store')
226 files changed, 0 insertions, 33392 deletions
diff --git a/framework/src/onos/core/store/dist/pom.xml b/framework/src/onos/core/store/dist/pom.xml deleted file mode 100644 index d61fc1b6..00000000 --- a/framework/src/onos/core/store/dist/pom.xml +++ /dev/null @@ -1,119 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright 2014 Open Networking Laboratory - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> - - <parent> - <groupId>org.onosproject</groupId> - <artifactId>onos-core-store</artifactId> - <version>1.4.0-rc1</version> - <relativePath>../pom.xml</relativePath> - </parent> - - <artifactId>onos-core-dist</artifactId> - <packaging>bundle</packaging> - - <description>ONOS Gossip based distributed store subsystems</description> - - <dependencies> - - <dependency> - <groupId>org.apache.commons</groupId> - <artifactId>commons-math3</artifactId> - <version>3.2</version> - </dependency> - - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-core-serializers</artifactId> - <version>${project.version}</version> - </dependency> - - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onlab-netty</artifactId> - <version>${project.version}</version> - </dependency> - - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onlab-nio</artifactId> - <version>${project.version}</version> - </dependency> - - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onlab-misc</artifactId> - <version>${project.version}</version> - </dependency> - - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-core-common</artifactId> - </dependency> - - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-core-persistence</artifactId> - <version>${project.version}</version> - </dependency> - - <dependency> - <groupId>org.mapdb</groupId> - <artifactId>mapdb</artifactId> - <version>1.0.8</version> - </dependency> - - <dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-databind</artifactId> - </dependency> - <dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-annotations</artifactId> - </dependency> - - <dependency> - <groupId>com.google.guava</groupId> - <artifactId>guava-testlib</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.commons</groupId> - <artifactId>commons-lang3</artifactId> - </dependency> - <dependency> - <groupId>org.easymock</groupId> - <artifactId>easymock</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-api</artifactId> - <classifier>tests</classifier> - <scope>test</scope> - </dependency> - - <!-- for shaded copycat --> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onlab-thirdparty</artifactId> - </dependency> - </dependencies> -</project> diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/app/GossipApplicationStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/app/GossipApplicationStore.java deleted file mode 100644 index fe4aa0be..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/app/GossipApplicationStore.java +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.app; - -import com.google.common.base.Charsets; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; -import com.google.common.collect.Sets; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onosproject.app.ApplicationDescription; -import org.onosproject.app.ApplicationEvent; -import org.onosproject.app.ApplicationException; -import org.onosproject.app.ApplicationState; -import org.onosproject.app.ApplicationStore; -import org.onosproject.app.ApplicationStoreDelegate; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.common.app.ApplicationArchive; -import org.onosproject.core.Application; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.ApplicationIdStore; -import org.onosproject.core.CoreService; -import org.onosproject.core.DefaultApplication; -import org.onosproject.security.Permission; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.cluster.messaging.MessageSubject; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.EventuallyConsistentMapEvent; -import org.onosproject.store.service.EventuallyConsistentMapListener; -import org.onosproject.store.service.LogicalClockService; -import org.onosproject.store.service.MultiValuedTimestamp; -import org.onosproject.store.service.StorageException; -import org.onosproject.store.service.StorageService; -import org.slf4j.Logger; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.function.Function; - -import static com.google.common.collect.Multimaps.newSetMultimap; -import static com.google.common.collect.Multimaps.synchronizedSetMultimap; -import static com.google.common.io.ByteStreams.toByteArray; -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static org.onlab.util.Tools.groupedThreads; -import static org.onlab.util.Tools.randomDelay; -import static org.onosproject.app.ApplicationEvent.Type.*; -import static org.onosproject.store.app.GossipApplicationStore.InternalState.*; -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT; -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Manages inventory of applications in a distributed data store that uses - * optimistic replication and gossip based anti-entropy techniques. - */ -@Component(immediate = true) -@Service -public class GossipApplicationStore extends ApplicationArchive - implements ApplicationStore { - - private final Logger log = getLogger(getClass()); - - private static final MessageSubject APP_BITS_REQUEST = new MessageSubject("app-bits-request"); - - private static final int MAX_LOAD_RETRIES = 5; - private static final int RETRY_DELAY_MS = 2_000; - - private static final int FETCH_TIMEOUT_MS = 10_000; - - public enum InternalState { - INSTALLED, ACTIVATED, DEACTIVATED - } - - private ScheduledExecutorService executor; - private ExecutorService messageHandlingExecutor; - - private EventuallyConsistentMap<ApplicationId, Application> apps; - private EventuallyConsistentMap<Application, InternalState> states; - private EventuallyConsistentMap<Application, Set<Permission>> permissions; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterCommunicationService clusterCommunicator; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected LogicalClockService clockService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ApplicationIdStore idStore; - - // Multimap to track which apps are required by others apps - // app -> { required-by, ... } - // Apps explicitly activated will be required by the CORE app - private final Multimap<ApplicationId, ApplicationId> requiredBy = - synchronizedSetMultimap(newSetMultimap(Maps.newHashMap(), Sets::newHashSet)); - - private ApplicationId coreAppId; - - @Activate - public void activate() { - KryoNamespace.Builder serializer = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .register(MultiValuedTimestamp.class) - .register(InternalState.class); - - executor = Executors.newSingleThreadScheduledExecutor(groupedThreads("onos/app", "store")); - - messageHandlingExecutor = Executors.newSingleThreadExecutor( - groupedThreads("onos/store/app", "message-handler")); - - clusterCommunicator.<String, byte[]>addSubscriber(APP_BITS_REQUEST, - bytes -> new String(bytes, Charsets.UTF_8), - name -> { - try { - return toByteArray(getApplicationInputStream(name)); - } catch (IOException e) { - throw new StorageException(e); - } - }, - Function.identity(), - messageHandlingExecutor); - - // FIXME: Consider consolidating into a single map. - - apps = storageService.<ApplicationId, Application>eventuallyConsistentMapBuilder() - .withName("apps") - .withSerializer(serializer) - .withTimestampProvider((k, v) -> clockService.getTimestamp()) - .build(); - - states = storageService.<Application, InternalState>eventuallyConsistentMapBuilder() - .withName("app-states") - .withSerializer(serializer) - .withTimestampProvider((k, v) -> clockService.getTimestamp()) - .build(); - - states.addListener(new InternalAppStatesListener()); - - permissions = storageService.<Application, Set<Permission>>eventuallyConsistentMapBuilder() - .withName("app-permissions") - .withSerializer(serializer) - .withTimestampProvider((k, v) -> clockService.getTimestamp()) - .build(); - - coreAppId = getId(CoreService.CORE_APP_NAME); - log.info("Started"); - } - - /** - * Loads the application inventory from the disk and activates apps if - * they are marked to be active. - */ - private void loadFromDisk() { - getApplicationNames().forEach(appName -> { - Application app = loadFromDisk(appName); - if (app != null && isActive(app.id().name())) { - activate(app.id(), false); - // TODO Load app permissions - } - }); - } - - private Application loadFromDisk(String appName) { - for (int i = 0; i < MAX_LOAD_RETRIES; i++) { - try { - // Directly return if app already exists - ApplicationId appId = getId(appName); - if (appId != null) { - return getApplication(appId); - } - - ApplicationDescription appDesc = getApplicationDescription(appName); - boolean success = appDesc.requiredApps().stream() - .noneMatch(requiredApp -> loadFromDisk(requiredApp) == null); - return success ? create(appDesc, false) : null; - } catch (Exception e) { - log.warn("Unable to load application {} from disk; retrying", appName); - randomDelay(RETRY_DELAY_MS); //FIXME: This is a deliberate hack; fix in Falcon - } - } - return null; - } - - @Deactivate - public void deactivate() { - clusterCommunicator.removeSubscriber(APP_BITS_REQUEST); - messageHandlingExecutor.shutdown(); - executor.shutdown(); - apps.destroy(); - states.destroy(); - permissions.destroy(); - log.info("Stopped"); - } - - @Override - public void setDelegate(ApplicationStoreDelegate delegate) { - super.setDelegate(delegate); - loadFromDisk(); - } - - @Override - public Set<Application> getApplications() { - return ImmutableSet.copyOf(apps.values()); - } - - @Override - public ApplicationId getId(String name) { - return idStore.getAppId(name); - } - - @Override - public Application getApplication(ApplicationId appId) { - return apps.get(appId); - } - - @Override - public ApplicationState getState(ApplicationId appId) { - Application app = apps.get(appId); - InternalState s = app == null ? null : states.get(app); - return s == null ? null : s == ACTIVATED ? - ApplicationState.ACTIVE : ApplicationState.INSTALLED; - } - - @Override - public Application create(InputStream appDescStream) { - ApplicationDescription appDesc = saveApplication(appDescStream); - if (hasPrerequisites(appDesc)) { - return create(appDesc, true); - } - throw new ApplicationException("Missing dependencies for app " + appDesc.name()); - } - - private boolean hasPrerequisites(ApplicationDescription app) { - return !app.requiredApps().stream().map(n -> getId(n)) - .anyMatch(id -> id == null || getApplication(id) == null); - } - - private Application create(ApplicationDescription appDesc, boolean updateTime) { - Application app = registerApp(appDesc); - if (updateTime) { - updateTime(app.id().name()); - } - apps.put(app.id(), app); - states.put(app, INSTALLED); - return app; - } - - @Override - public void remove(ApplicationId appId) { - Application app = apps.get(appId); - if (app != null) { - uninstallDependentApps(app); - apps.remove(appId); - states.remove(app); - permissions.remove(app); - } - } - - // Uninstalls all apps that depend on the given app. - private void uninstallDependentApps(Application app) { - getApplications().stream() - .filter(a -> a.requiredApps().contains(app.id().name())) - .forEach(a -> remove(a.id())); - } - - @Override - public void activate(ApplicationId appId) { - activate(appId, coreAppId); - } - - private void activate(ApplicationId appId, ApplicationId forAppId) { - requiredBy.put(appId, forAppId); - activate(appId, true); - } - - - private void activate(ApplicationId appId, boolean updateTime) { - Application app = apps.get(appId); - if (app != null) { - if (updateTime) { - updateTime(appId.name()); - } - activateRequiredApps(app); - states.put(app, ACTIVATED); - } - } - - // Activates all apps required by this application. - private void activateRequiredApps(Application app) { - app.requiredApps().stream().map(this::getId).forEach(id -> activate(id, app.id())); - } - - @Override - public void deactivate(ApplicationId appId) { - deactivateDependentApps(getApplication(appId)); - deactivate(appId, coreAppId); - } - - private void deactivate(ApplicationId appId, ApplicationId forAppId) { - requiredBy.remove(appId, forAppId); - if (requiredBy.get(appId).isEmpty()) { - Application app = apps.get(appId); - if (app != null) { - updateTime(appId.name()); - states.put(app, DEACTIVATED); - deactivateRequiredApps(app); - } - } - } - - // Deactivates all apps that require this application. - private void deactivateDependentApps(Application app) { - getApplications().stream() - .filter(a -> states.get(a) == ACTIVATED) - .filter(a -> a.requiredApps().contains(app.id().name())) - .forEach(a -> deactivate(a.id())); - } - - // Deactivates all apps required by this application. - private void deactivateRequiredApps(Application app) { - app.requiredApps().stream().map(this::getId).map(this::getApplication) - .filter(a -> states.get(a) == ACTIVATED) - .forEach(a -> deactivate(a.id(), app.id())); - } - - @Override - public Set<Permission> getPermissions(ApplicationId appId) { - Application app = apps.get(appId); - return app != null ? permissions.get(app) : null; - } - - @Override - public void setPermissions(ApplicationId appId, Set<Permission> permissions) { - Application app = getApplication(appId); - if (app != null) { - this.permissions.put(app, permissions); - delegate.notify(new ApplicationEvent(APP_PERMISSIONS_CHANGED, app)); - } - } - - /** - * Listener to application state distributed map changes. - */ - private final class InternalAppStatesListener - implements EventuallyConsistentMapListener<Application, InternalState> { - @Override - public void event(EventuallyConsistentMapEvent<Application, InternalState> event) { - // If we do not have a delegate, refuse to process any events entirely. - // This is to allow the anti-entropy to kick in and process the events - // perhaps a bit later, but with opportunity to notify delegate. - if (delegate == null) { - return; - } - - Application app = event.key(); - InternalState state = event.value(); - - if (event.type() == PUT) { - if (state == INSTALLED) { - fetchBitsIfNeeded(app); - delegate.notify(new ApplicationEvent(APP_INSTALLED, app)); - - } else if (state == ACTIVATED) { - installAppIfNeeded(app); - setActive(app.id().name()); - delegate.notify(new ApplicationEvent(APP_ACTIVATED, app)); - - } else if (state == DEACTIVATED) { - clearActive(app.id().name()); - delegate.notify(new ApplicationEvent(APP_DEACTIVATED, app)); - } - } else if (event.type() == REMOVE) { - delegate.notify(new ApplicationEvent(APP_UNINSTALLED, app)); - purgeApplication(app.id().name()); - } - } - } - - /** - * Determines if the application bits are available locally. - */ - private boolean appBitsAvailable(Application app) { - try { - ApplicationDescription appDesc = getApplicationDescription(app.id().name()); - return appDesc.version().equals(app.version()); - } catch (ApplicationException e) { - return false; - } - } - - /** - * Fetches the bits from the cluster peers if necessary. - */ - private void fetchBitsIfNeeded(Application app) { - if (!appBitsAvailable(app)) { - fetchBits(app); - } - } - - /** - * Installs the application if necessary from the application peers. - */ - private void installAppIfNeeded(Application app) { - if (!appBitsAvailable(app)) { - fetchBits(app); - delegate.notify(new ApplicationEvent(APP_INSTALLED, app)); - } - } - - /** - * Fetches the bits from the cluster peers. - */ - private void fetchBits(Application app) { - ControllerNode localNode = clusterService.getLocalNode(); - CountDownLatch latch = new CountDownLatch(1); - - // FIXME: send message with name & version to make sure we don't get served old bits - - log.info("Downloading bits for application {}", app.id().name()); - for (ControllerNode node : clusterService.getNodes()) { - if (latch.getCount() == 0) { - break; - } - if (node.equals(localNode)) { - continue; - } - clusterCommunicator.sendAndReceive(app.id().name(), - APP_BITS_REQUEST, - s -> s.getBytes(Charsets.UTF_8), - Function.identity(), - node.id()) - .whenCompleteAsync((bits, error) -> { - if (error == null && latch.getCount() > 0) { - saveApplication(new ByteArrayInputStream(bits)); - log.info("Downloaded bits for application {} from node {}", - app.id().name(), node.id()); - latch.countDown(); - } else if (error != null) { - log.warn("Unable to fetch bits for application {} from node {}", - app.id().name(), node.id()); - } - }, executor); - } - - try { - if (!latch.await(FETCH_TIMEOUT_MS, MILLISECONDS)) { - log.warn("Unable to fetch bits for application {}", app.id().name()); - } - } catch (InterruptedException e) { - log.warn("Interrupted while fetching bits for application {}", app.id().name()); - } - } - - /** - * Prunes applications which are not in the map, but are on disk. - */ - private void pruneUninstalledApps() { - for (String name : getApplicationNames()) { - if (getApplication(getId(name)) == null) { - Application app = registerApp(getApplicationDescription(name)); - delegate.notify(new ApplicationEvent(APP_UNINSTALLED, app)); - purgeApplication(app.id().name()); - } - } - } - - /** - * Produces a registered application from the supplied description. - */ - private Application registerApp(ApplicationDescription appDesc) { - ApplicationId appId = idStore.registerApplication(appDesc.name()); - return new DefaultApplication(appId, appDesc.version(), appDesc.description(), - appDesc.origin(), appDesc.role(), appDesc.permissions(), - appDesc.featuresRepo(), appDesc.features(), - appDesc.requiredApps()); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/app/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/app/package-info.java deleted file mode 100644 index b2a909ee..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/app/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of distributed applications store. - */ -package org.onosproject.store.app; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cfg/GossipComponentConfigStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cfg/GossipComponentConfigStore.java deleted file mode 100644 index bf992643..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cfg/GossipComponentConfigStore.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.cfg; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onosproject.cfg.ComponentConfigEvent; -import org.onosproject.cfg.ComponentConfigStore; -import org.onosproject.cfg.ComponentConfigStoreDelegate; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.EventuallyConsistentMapEvent; -import org.onosproject.store.service.EventuallyConsistentMapListener; -import org.onosproject.store.service.LogicalClockService; -import org.onosproject.store.service.StorageService; -import org.slf4j.Logger; - -import static org.onosproject.cfg.ComponentConfigEvent.Type.PROPERTY_SET; -import static org.onosproject.cfg.ComponentConfigEvent.Type.PROPERTY_UNSET; -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT; -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Manages inventory of component configurations in a distributed data store - * that uses optimistic replication and gossip based anti-entropy techniques. - */ -@Component(immediate = true) -@Service -public class GossipComponentConfigStore - extends AbstractStore<ComponentConfigEvent, ComponentConfigStoreDelegate> - implements ComponentConfigStore { - - private static final String SEP = "#"; - - private final Logger log = getLogger(getClass()); - - private EventuallyConsistentMap<String, String> properties; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected LogicalClockService clockService; - - @Activate - public void activate() { - KryoNamespace.Builder serializer = KryoNamespace.newBuilder() - .register(KryoNamespaces.API); - - properties = storageService.<String, String>eventuallyConsistentMapBuilder() - .withName("cfg") - .withSerializer(serializer) - .withTimestampProvider((k, v) -> clockService.getTimestamp()) - .build(); - - properties.addListener(new InternalPropertiesListener()); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - properties.destroy(); - log.info("Stopped"); - } - - @Override - public void setProperty(String componentName, String name, String value) { - properties.put(key(componentName, name), value); - - } - - @Override - public void unsetProperty(String componentName, String name) { - properties.remove(key(componentName, name)); - } - - /** - * Listener to component configuration properties distributed map changes. - */ - private final class InternalPropertiesListener - implements EventuallyConsistentMapListener<String, String> { - - @Override - public void event(EventuallyConsistentMapEvent<String, String> event) { - String[] keys = event.key().split(SEP); - String value = event.value(); - if (event.type() == PUT) { - delegate.notify(new ComponentConfigEvent(PROPERTY_SET, keys[0], keys[1], value)); - } else if (event.type() == REMOVE) { - delegate.notify(new ComponentConfigEvent(PROPERTY_UNSET, keys[0], keys[1], null)); - } - } - } - - // Generates a key from component name and property name. - private String key(String componentName, String name) { - return componentName + SEP + name; - } - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cfg/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cfg/package-info.java deleted file mode 100644 index f8f8509a..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cfg/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of distributed component configuration store. - */ -package org.onosproject.store.cfg; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterManagementMessageSubjects.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterManagementMessageSubjects.java deleted file mode 100644 index 918f7921..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterManagementMessageSubjects.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.cluster.impl; - -import org.onosproject.store.cluster.messaging.MessageSubject; - -//Not used right now -public final class ClusterManagementMessageSubjects { - // avoid instantiation - private ClusterManagementMessageSubjects() {} - - public static final MessageSubject CLUSTER_MEMBERSHIP_EVENT = new MessageSubject("CLUSTER_MEMBERSHIP_EVENT"); -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterMembershipEvent.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterMembershipEvent.java deleted file mode 100644 index c6428739..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterMembershipEvent.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.cluster.impl; - -import org.onosproject.cluster.ControllerNode; - -//Not used right now -/** - * Contains information that will be published when a cluster membership event occurs. - */ -public class ClusterMembershipEvent { - - private final ClusterMembershipEventType type; - private final ControllerNode node; - - public ClusterMembershipEvent(ClusterMembershipEventType type, ControllerNode node) { - this.type = type; - this.node = node; - } - - public ClusterMembershipEventType type() { - return type; - } - - public ControllerNode node() { - return node; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterMembershipEventType.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterMembershipEventType.java deleted file mode 100644 index a7f09c71..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterMembershipEventType.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.cluster.impl; - -//Not used right now -public enum ClusterMembershipEventType { - NEW_MEMBER, - LEAVING_MEMBER, - UNREACHABLE_MEMBER, - HEART_BEAT, -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterNodesDelegate.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterNodesDelegate.java deleted file mode 100644 index 7aeca72f..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterNodesDelegate.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.cluster.impl; - -import org.onosproject.cluster.DefaultControllerNode; -import org.onosproject.cluster.NodeId; -import org.onlab.packet.IpAddress; - -// Not used right now -/** - * Simple back interface through which connection manager can interact with - * the cluster store. - */ -public interface ClusterNodesDelegate { - - /** - * Notifies about cluster node coming online. - * - * @param nodeId newly detected cluster node id - * @param ip node IP listen address - * @param tcpPort node TCP listen port - * @return the controller node - */ - DefaultControllerNode nodeDetected(NodeId nodeId, IpAddress ip, - int tcpPort); - - /** - * Notifies about cluster node going offline. - * - * @param nodeId identifier of the cluster node that vanished - */ - void nodeVanished(NodeId nodeId); - - /** - * Notifies about remote request to remove node from cluster. - * - * @param nodeId identifier of the cluster node that was removed - */ - void nodeRemoved(NodeId nodeId); - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java deleted file mode 100644 index 3bb6a708..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.cluster.impl; - -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Maps; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.joda.time.DateTime; -import org.onlab.packet.IpAddress; -import org.onlab.util.KryoNamespace; -import org.onosproject.cluster.ClusterEvent; -import org.onosproject.cluster.ClusterMetadataService; -import org.onosproject.cluster.ClusterStore; -import org.onosproject.cluster.ClusterStoreDelegate; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.ControllerNode.State; -import org.onosproject.cluster.DefaultControllerNode; -import org.onosproject.cluster.NodeId; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.cluster.messaging.Endpoint; -import org.onosproject.store.cluster.messaging.MessagingService; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.serializers.KryoSerializer; -import org.slf4j.Logger; - -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.onlab.util.Tools.groupedThreads; -import static org.slf4j.LoggerFactory.getLogger; - -@Component(immediate = true) -@Service -/** - * Distributed cluster nodes store that employs an accrual failure - * detector to identify cluster member up/down status. - */ -public class DistributedClusterStore - extends AbstractStore<ClusterEvent, ClusterStoreDelegate> - implements ClusterStore { - - private static final Logger log = getLogger(DistributedClusterStore.class); - - public static final String HEARTBEAT_MESSAGE = "onos-cluster-heartbeat"; - - // TODO: make these configurable. - private static final int HEARTBEAT_INTERVAL_MS = 100; - private static final int PHI_FAILURE_THRESHOLD = 10; - - private static final KryoSerializer SERIALIZER = new KryoSerializer() { - @Override - protected void setupKryoPool() { - serializerPool = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .register(HeartbeatMessage.class) - .build() - .populate(1); - } - }; - - private static final String INSTANCE_ID_NULL = "Instance ID cannot be null"; - - private final Map<NodeId, ControllerNode> allNodes = Maps.newConcurrentMap(); - private final Map<NodeId, State> nodeStates = Maps.newConcurrentMap(); - private final Map<NodeId, DateTime> nodeStateLastUpdatedTimes = Maps.newConcurrentMap(); - private ScheduledExecutorService heartBeatSender = Executors.newSingleThreadScheduledExecutor( - groupedThreads("onos/cluster/membership", "heartbeat-sender")); - private ExecutorService heartBeatMessageHandler = Executors.newSingleThreadExecutor( - groupedThreads("onos/cluster/membership", "heartbeat-receiver")); - - private PhiAccrualFailureDetector failureDetector; - - private ControllerNode localNode; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterMetadataService clusterMetadataService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MessagingService messagingService; - - @Activate - public void activate() { - localNode = clusterMetadataService.getLocalNode(); - - messagingService.registerHandler(HEARTBEAT_MESSAGE, - new HeartbeatMessageHandler(), heartBeatMessageHandler); - - failureDetector = new PhiAccrualFailureDetector(); - - heartBeatSender.scheduleWithFixedDelay(this::heartbeat, 0, - HEARTBEAT_INTERVAL_MS, TimeUnit.MILLISECONDS); - - log.info("Started"); - } - - @Deactivate - public void deactivate() { - messagingService.unregisterHandler(HEARTBEAT_MESSAGE); - heartBeatSender.shutdownNow(); - heartBeatMessageHandler.shutdownNow(); - - log.info("Stopped"); - } - - @Override - public void setDelegate(ClusterStoreDelegate delegate) { - checkNotNull(delegate, "Delegate cannot be null"); - this.delegate = delegate; - } - - @Override - public void unsetDelegate(ClusterStoreDelegate delegate) { - this.delegate = null; - } - - @Override - public boolean hasDelegate() { - return this.delegate != null; - } - - @Override - public ControllerNode getLocalNode() { - return localNode; - } - - @Override - public Set<ControllerNode> getNodes() { - return ImmutableSet.copyOf(allNodes.values()); - } - - @Override - public ControllerNode getNode(NodeId nodeId) { - checkNotNull(nodeId, INSTANCE_ID_NULL); - return allNodes.get(nodeId); - } - - @Override - public State getState(NodeId nodeId) { - checkNotNull(nodeId, INSTANCE_ID_NULL); - return nodeStates.get(nodeId); - } - - @Override - public ControllerNode addNode(NodeId nodeId, IpAddress ip, int tcpPort) { - ControllerNode node = new DefaultControllerNode(nodeId, ip, tcpPort); - addNode(node); - return node; - } - - @Override - public void removeNode(NodeId nodeId) { - checkNotNull(nodeId, INSTANCE_ID_NULL); - ControllerNode node = allNodes.remove(nodeId); - if (node != null) { - nodeStates.remove(nodeId); - notifyDelegate(new ClusterEvent(ClusterEvent.Type.INSTANCE_REMOVED, node)); - } - } - - private void addNode(ControllerNode node) { - allNodes.put(node.id(), node); - updateState(node.id(), node.equals(localNode) ? State.ACTIVE : State.INACTIVE); - notifyDelegate(new ClusterEvent(ClusterEvent.Type.INSTANCE_ADDED, node)); - } - - private void updateState(NodeId nodeId, State newState) { - nodeStates.put(nodeId, newState); - nodeStateLastUpdatedTimes.put(nodeId, DateTime.now()); - } - - private void heartbeat() { - try { - Set<ControllerNode> peers = allNodes.values() - .stream() - .filter(node -> !(node.id().equals(localNode.id()))) - .collect(Collectors.toSet()); - byte[] hbMessagePayload = SERIALIZER.encode(new HeartbeatMessage(localNode, peers)); - peers.forEach((node) -> { - heartbeatToPeer(hbMessagePayload, node); - State currentState = nodeStates.get(node.id()); - double phi = failureDetector.phi(node.id()); - if (phi >= PHI_FAILURE_THRESHOLD) { - if (currentState == State.ACTIVE) { - updateState(node.id(), State.INACTIVE); - notifyStateChange(node.id(), State.ACTIVE, State.INACTIVE); - } - } else { - if (currentState == State.INACTIVE) { - updateState(node.id(), State.ACTIVE); - notifyStateChange(node.id(), State.INACTIVE, State.ACTIVE); - } - } - }); - } catch (Exception e) { - log.debug("Failed to send heartbeat", e); - } - } - - private void notifyStateChange(NodeId nodeId, State oldState, State newState) { - ControllerNode node = allNodes.get(nodeId); - if (newState == State.ACTIVE) { - notifyDelegate(new ClusterEvent(ClusterEvent.Type.INSTANCE_ACTIVATED, node)); - } else { - notifyDelegate(new ClusterEvent(ClusterEvent.Type.INSTANCE_DEACTIVATED, node)); - } - } - - private void heartbeatToPeer(byte[] messagePayload, ControllerNode peer) { - Endpoint remoteEp = new Endpoint(peer.ip(), peer.tcpPort()); - messagingService.sendAsync(remoteEp, HEARTBEAT_MESSAGE, messagePayload).whenComplete((result, error) -> { - if (error != null) { - log.trace("Sending heartbeat to {} failed", remoteEp, error); - } - }); - } - - private class HeartbeatMessageHandler implements Consumer<byte[]> { - @Override - public void accept(byte[] message) { - HeartbeatMessage hb = SERIALIZER.decode(message); - failureDetector.report(hb.source().id()); - hb.knownPeers().forEach(node -> { - allNodes.put(node.id(), node); - }); - } - } - - private static class HeartbeatMessage { - private ControllerNode source; - private Set<ControllerNode> knownPeers; - - public HeartbeatMessage(ControllerNode source, Set<ControllerNode> members) { - this.source = source; - this.knownPeers = ImmutableSet.copyOf(members); - } - - public ControllerNode source() { - return source; - } - - public Set<ControllerNode> knownPeers() { - return knownPeers; - } - } - - @Override - public DateTime getLastUpdated(NodeId nodeId) { - return nodeStateLastUpdatedTimes.get(nodeId); - } - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/NodeInfo.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/NodeInfo.java deleted file mode 100644 index d436ca76..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/NodeInfo.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.cluster.impl; - -import static com.google.common.base.MoreObjects.toStringHelper; - -import java.util.Objects; - -import org.onosproject.cluster.ControllerNode; - -/** - * Node info read from configuration files during bootstrap. - */ -public final class NodeInfo { - private final String id; - private final String ip; - private final int tcpPort; - - private NodeInfo(String id, String ip, int port) { - this.id = id; - this.ip = ip; - this.tcpPort = port; - } - - /* - * Needed for serialization. - */ - private NodeInfo() { - id = null; - ip = null; - tcpPort = 0; - } - - /** - * Creates a new instance. - * @param id node id - * @param ip node ip address - * @param port tcp port - * @return NodeInfo - */ - public static NodeInfo from(String id, String ip, int port) { - NodeInfo node = new NodeInfo(id, ip, port); - return node; - } - - /** - * Returns the NodeInfo for a controller node. - * @param node controller node - * @return NodeInfo - */ - public static NodeInfo of(ControllerNode node) { - return NodeInfo.from(node.id().toString(), node.ip().toString(), node.tcpPort()); - } - - /** - * Returns node id. - * @return node id - */ - public String getId() { - return id; - } - - /** - * Returns node ip. - * @return node ip - */ - public String getIp() { - return ip; - } - - /** - * Returns node port. - * @return port - */ - public int getTcpPort() { - return tcpPort; - } - - @Override - public int hashCode() { - return Objects.hash(id, ip, tcpPort); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o instanceof NodeInfo) { - NodeInfo that = (NodeInfo) o; - return Objects.equals(this.id, that.id) && - Objects.equals(this.ip, that.ip) && - Objects.equals(this.tcpPort, that.tcpPort); - } - return false; - } - - @Override - public String toString() { - return toStringHelper(this) - .add("id", id) - .add("ip", ip) - .add("tcpPort", tcpPort).toString(); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/PhiAccrualFailureDetector.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/PhiAccrualFailureDetector.java deleted file mode 100644 index cdb138b4..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/PhiAccrualFailureDetector.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.cluster.impl; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.Map; - -import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; -import org.onosproject.cluster.NodeId; - -import com.google.common.collect.Maps; - -/** - * Phi Accrual failure detector. - * <p> - * Based on a paper titled: "The φ Accrual Failure Detector" by Hayashibara, et al. - */ -public class PhiAccrualFailureDetector { - private final Map<NodeId, History> states = Maps.newConcurrentMap(); - - // TODO: make these configurable. - private static final int WINDOW_SIZE = 250; - private static final int MIN_SAMPLES = 25; - private static final double PHI_FACTOR = 1.0 / Math.log(10.0); - - // If a node does not have any heartbeats, this is the phi - // value to report. Indicates the node is inactive (from the - // detectors perspective. - private static final double BOOTSTRAP_PHI_VALUE = 100.0; - - /** - * Report a new heart beat for the specified node id. - * @param nodeId node id - */ - public void report(NodeId nodeId) { - report(nodeId, System.currentTimeMillis()); - } - - /** - * Report a new heart beat for the specified node id. - * @param nodeId node id - * @param arrivalTime arrival time - */ - public void report(NodeId nodeId, long arrivalTime) { - checkNotNull(nodeId, "NodeId must not be null"); - checkArgument(arrivalTime >= 0, "arrivalTime must not be negative"); - History nodeState = - states.computeIfAbsent(nodeId, key -> new History()); - synchronized (nodeState) { - long latestHeartbeat = nodeState.latestHeartbeatTime(); - if (latestHeartbeat != -1) { - nodeState.samples().addValue(arrivalTime - latestHeartbeat); - } - nodeState.setLatestHeartbeatTime(arrivalTime); - } - } - - /** - * Compute phi for the specified node id. - * @param nodeId node id - * @return phi value - */ - public double phi(NodeId nodeId) { - checkNotNull(nodeId, "NodeId must not be null"); - if (!states.containsKey(nodeId)) { - return BOOTSTRAP_PHI_VALUE; - } - History nodeState = states.get(nodeId); - synchronized (nodeState) { - long latestHeartbeat = nodeState.latestHeartbeatTime(); - DescriptiveStatistics samples = nodeState.samples(); - if (latestHeartbeat == -1 || samples.getN() < MIN_SAMPLES) { - return 0.0; - } - return computePhi(samples, latestHeartbeat, System.currentTimeMillis()); - } - } - - private double computePhi(DescriptiveStatistics samples, long tLast, long tNow) { - long size = samples.getN(); - long t = tNow - tLast; - return (size > 0) - ? PHI_FACTOR * t / samples.getMean() - : BOOTSTRAP_PHI_VALUE; - } - - private static class History { - DescriptiveStatistics samples = - new DescriptiveStatistics(WINDOW_SIZE); - long lastHeartbeatTime = -1; - - public DescriptiveStatistics samples() { - return samples; - } - - public long latestHeartbeatTime() { - return lastHeartbeatTime; - } - - public void setLatestHeartbeatTime(long value) { - lastHeartbeatTime = value; - } - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java deleted file mode 100644 index 3cd992bb..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java +++ /dev/null @@ -1,258 +0,0 @@ -package org.onosproject.store.cluster.impl; - -import static com.google.common.base.Preconditions.checkNotNull; -import static java.net.NetworkInterface.getNetworkInterfaces; -import static org.slf4j.LoggerFactory.getLogger; - -import java.io.File; -import java.io.IOException; -import java.net.InetAddress; -import java.net.Inet4Address; -import java.net.NetworkInterface; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Function; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Service; -import org.onlab.packet.IpAddress; -import org.onosproject.cluster.ClusterMetadata; -import org.onosproject.cluster.ClusterMetadataEvent; -import org.onosproject.cluster.ClusterMetadataStore; -import org.onosproject.cluster.ClusterMetadataStoreDelegate; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.DefaultControllerNode; -import org.onosproject.cluster.NodeId; -import org.onosproject.cluster.Partition; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.service.Versioned; -import org.slf4j.Logger; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.module.SimpleModule; -import com.google.common.base.Throwables; -import com.google.common.collect.Lists; -import com.google.common.io.Files; - -/** - * ClusterMetadataStore backed by a local file. - */ -@Component(immediate = true, enabled = true) -@Service -public class StaticClusterMetadataStore - extends AbstractStore<ClusterMetadataEvent, ClusterMetadataStoreDelegate> - implements ClusterMetadataStore { - - private final Logger log = getLogger(getClass()); - - private static final String ONOS_IP = "ONOS_IP"; - private static final String ONOS_INTERFACE = "ONOS_INTERFACE"; - private static final String ONOS_ALLOW_IPV6 = "ONOS_ALLOW_IPV6"; - private static final String DEFAULT_ONOS_INTERFACE = "eth0"; - private static final String CLUSTER_METADATA_FILE = "../config/cluster.json"; - private static final int DEFAULT_ONOS_PORT = 9876; - private final File metadataFile = new File(CLUSTER_METADATA_FILE); - private AtomicReference<ClusterMetadata> metadata = new AtomicReference<>(); - private ObjectMapper mapper; - private long version; - - @Activate - public void activate() { - mapper = new ObjectMapper(); - SimpleModule module = new SimpleModule(); - module.addSerializer(NodeId.class, new NodeIdSerializer()); - module.addDeserializer(NodeId.class, new NodeIdDeserializer()); - module.addSerializer(ControllerNode.class, new ControllerNodeSerializer()); - module.addDeserializer(ControllerNode.class, new ControllerNodeDeserializer()); - mapper.registerModule(module); - File metadataFile = new File(CLUSTER_METADATA_FILE); - if (metadataFile.exists()) { - try { - metadata.set(mapper.readValue(metadataFile, ClusterMetadata.class)); - version = metadataFile.lastModified(); - } catch (IOException e) { - Throwables.propagate(e); - } - } else { - String localIp = getSiteLocalAddress(); - ControllerNode localNode = - new DefaultControllerNode(new NodeId(localIp), IpAddress.valueOf(localIp), DEFAULT_ONOS_PORT); - metadata.set(ClusterMetadata.builder() - .withName("default") - .withControllerNodes(Arrays.asList(localNode)) - .withPartitions(Lists.newArrayList(new Partition("p1", Lists.newArrayList(localNode.id())))) - .build()); - version = System.currentTimeMillis(); - } - log.info("Started"); - } - - @Deactivate - public void deactivate() { - log.info("Stopped"); - } - - @Override - public void setDelegate(ClusterMetadataStoreDelegate delegate) { - checkNotNull(delegate, "Delegate cannot be null"); - this.delegate = delegate; - } - - @Override - public void unsetDelegate(ClusterMetadataStoreDelegate delegate) { - this.delegate = null; - } - - @Override - public boolean hasDelegate() { - return this.delegate != null; - } - - @Override - public Versioned<ClusterMetadata> getClusterMetadata() { - return new Versioned<>(metadata.get(), version); - } - - @Override - public void setClusterMetadata(ClusterMetadata metadata) { - checkNotNull(metadata); - try { - Files.createParentDirs(metadataFile); - mapper.writeValue(metadataFile, metadata); - this.metadata.set(metadata); - } catch (IOException e) { - Throwables.propagate(e); - } - } - - @Override - public void setActiveReplica(String partitionId, NodeId nodeId) { - throw new UnsupportedOperationException(); - } - - @Override - public void unsetActiveReplica(String partitionId, NodeId nodeId) { - throw new UnsupportedOperationException(); - } - - @Override - public Collection<NodeId> getActiveReplicas(String partitionId) { - return metadata.get().getPartitions() - .stream() - .filter(r -> r.getName().equals(partitionId)) - .findFirst() - .map(r -> r.getMembers()) - .orElse(null); - } - - private static class ControllerNodeSerializer extends JsonSerializer<ControllerNode> { - @Override - public void serialize(ControllerNode node, JsonGenerator jgen, SerializerProvider provider) - throws IOException, JsonProcessingException { - jgen.writeStartObject(); - jgen.writeStringField("id", node.id().toString()); - jgen.writeStringField("ip", node.ip().toString()); - jgen.writeNumberField("port", node.tcpPort()); - jgen.writeEndObject(); - } - } - - private static class ControllerNodeDeserializer extends JsonDeserializer<ControllerNode> { - @Override - public ControllerNode deserialize(JsonParser jp, DeserializationContext ctxt) - throws IOException, JsonProcessingException { - JsonNode node = jp.getCodec().readTree(jp); - NodeId nodeId = new NodeId(node.get("id").textValue()); - IpAddress ip = IpAddress.valueOf(node.get("ip").textValue()); - int port = node.get("port").asInt(); - return new DefaultControllerNode(nodeId, ip, port); - } - } - - private static class NodeIdSerializer extends JsonSerializer<NodeId> { - @Override - public void serialize(NodeId nodeId, JsonGenerator jgen, SerializerProvider provider) - throws IOException, JsonProcessingException { - jgen.writeString(nodeId.toString()); - } - } - - private class NodeIdDeserializer extends JsonDeserializer<NodeId> { - @Override - public NodeId deserialize(JsonParser jp, DeserializationContext ctxt) - throws IOException, JsonProcessingException { - JsonNode node = jp.getCodec().readTree(jp); - return new NodeId(node.asText()); - } - } - - - private static String getSiteLocalAddress() { - - /* - * If the IP ONOS should use is set via the environment variable we will assume it is valid and should be used. - * Setting the IP address takes presidence over setting the interface via the environment. - */ - String useOnosIp = System.getenv(ONOS_IP); - if (useOnosIp != null) { - return useOnosIp; - } - - // Read environment variables for IP interface information or set to default - String useOnosInterface = System.getenv(ONOS_INTERFACE); - if (useOnosInterface == null) { - useOnosInterface = DEFAULT_ONOS_INTERFACE; - } - - // Capture if they want to limit IP address selection to only IPv4 (default). - boolean allowIPv6 = (System.getenv(ONOS_ALLOW_IPV6) != null); - - Function<NetworkInterface, IpAddress> ipLookup = nif -> { - IpAddress fallback = null; - - // nif can be null if the interface name specified doesn't exist on the node's host - if (nif != null) { - for (InetAddress address : Collections.list(nif.getInetAddresses())) { - if (address.isSiteLocalAddress() && (allowIPv6 || address instanceof Inet4Address)) { - return IpAddress.valueOf(address); - } - if (fallback == null && !address.isLoopbackAddress() && !address.isMulticastAddress() - && (allowIPv6 || address instanceof Inet4Address)) { - fallback = IpAddress.valueOf(address); - } - } - } - return fallback; - }; - try { - IpAddress ip = ipLookup.apply(NetworkInterface.getByName(useOnosInterface)); - if (ip != null) { - return ip.toString(); - } - for (NetworkInterface nif : Collections.list(getNetworkInterfaces())) { - if (!nif.getName().equals(useOnosInterface)) { - ip = ipLookup.apply(nif); - if (ip != null) { - return ip.toString(); - } - } - } - } catch (Exception e) { - throw new IllegalStateException("Unable to get network interfaces", e); - } - - return IpAddress.valueOf(InetAddress.getLoopbackAddress()).toString(); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/package-info.java deleted file mode 100644 index 9e2db676..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of a distributed cluster node store using Hazelcast. - */ -package org.onosproject.store.cluster.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/ClusterCommunicationManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/ClusterCommunicationManager.java deleted file mode 100644 index 8a237ef0..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/ClusterCommunicationManager.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.cluster.messaging.impl; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.Tools; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.NodeId; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.cluster.messaging.ClusterMessage; -import org.onosproject.store.cluster.messaging.ClusterMessageHandler; -import org.onosproject.store.cluster.messaging.Endpoint; -import org.onosproject.store.cluster.messaging.MessageSubject; -import org.onosproject.store.cluster.messaging.MessagingService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Objects; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkArgument; - -@Component(immediate = true) -@Service -public class ClusterCommunicationManager - implements ClusterCommunicationService { - - private final Logger log = LoggerFactory.getLogger(getClass()); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - private ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MessagingService messagingService; - - private NodeId localNodeId; - - @Activate - public void activate() { - localNodeId = clusterService.getLocalNode().id(); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - log.info("Stopped"); - } - - @Override - public <M> void broadcast(M message, - MessageSubject subject, - Function<M, byte[]> encoder) { - multicast(message, - subject, - encoder, - clusterService.getNodes() - .stream() - .filter(node -> !Objects.equal(node, clusterService.getLocalNode())) - .map(ControllerNode::id) - .collect(Collectors.toSet())); - } - - @Override - public <M> void broadcastIncludeSelf(M message, - MessageSubject subject, - Function<M, byte[]> encoder) { - multicast(message, - subject, - encoder, - clusterService.getNodes() - .stream() - .map(ControllerNode::id) - .collect(Collectors.toSet())); - } - - @Override - public <M> CompletableFuture<Void> unicast(M message, - MessageSubject subject, - Function<M, byte[]> encoder, - NodeId toNodeId) { - try { - byte[] payload = new ClusterMessage( - localNodeId, - subject, - encoder.apply(message)).getBytes(); - return doUnicast(subject, payload, toNodeId); - } catch (Exception e) { - return Tools.exceptionalFuture(e); - } - } - - @Override - public <M> void multicast(M message, - MessageSubject subject, - Function<M, byte[]> encoder, - Set<NodeId> nodes) { - byte[] payload = new ClusterMessage( - localNodeId, - subject, - encoder.apply(message)).getBytes(); - nodes.forEach(nodeId -> doUnicast(subject, payload, nodeId)); - } - - @Override - public <M, R> CompletableFuture<R> sendAndReceive(M message, - MessageSubject subject, - Function<M, byte[]> encoder, - Function<byte[], R> decoder, - NodeId toNodeId) { - try { - ClusterMessage envelope = new ClusterMessage( - clusterService.getLocalNode().id(), - subject, - encoder.apply(message)); - return sendAndReceive(subject, envelope.getBytes(), toNodeId).thenApply(decoder); - } catch (Exception e) { - return Tools.exceptionalFuture(e); - } - } - - private CompletableFuture<Void> doUnicast(MessageSubject subject, byte[] payload, NodeId toNodeId) { - ControllerNode node = clusterService.getNode(toNodeId); - checkArgument(node != null, "Unknown nodeId: %s", toNodeId); - Endpoint nodeEp = new Endpoint(node.ip(), node.tcpPort()); - return messagingService.sendAsync(nodeEp, subject.value(), payload); - } - - private CompletableFuture<byte[]> sendAndReceive(MessageSubject subject, byte[] payload, NodeId toNodeId) { - ControllerNode node = clusterService.getNode(toNodeId); - checkArgument(node != null, "Unknown nodeId: %s", toNodeId); - Endpoint nodeEp = new Endpoint(node.ip(), node.tcpPort()); - return messagingService.sendAndReceive(nodeEp, subject.value(), payload); - } - - @Override - public void addSubscriber(MessageSubject subject, - ClusterMessageHandler subscriber, - ExecutorService executor) { - messagingService.registerHandler(subject.value(), - new InternalClusterMessageHandler(subscriber), - executor); - } - - @Override - public void removeSubscriber(MessageSubject subject) { - messagingService.unregisterHandler(subject.value()); - } - - @Override - public <M, R> void addSubscriber(MessageSubject subject, - Function<byte[], M> decoder, - Function<M, R> handler, - Function<R, byte[]> encoder, - Executor executor) { - messagingService.registerHandler(subject.value(), - new InternalMessageResponder<M, R>(decoder, encoder, m -> { - CompletableFuture<R> responseFuture = new CompletableFuture<>(); - executor.execute(() -> { - try { - responseFuture.complete(handler.apply(m)); - } catch (Exception e) { - responseFuture.completeExceptionally(e); - } - }); - return responseFuture; - })); - } - - @Override - public <M, R> void addSubscriber(MessageSubject subject, - Function<byte[], M> decoder, - Function<M, CompletableFuture<R>> handler, - Function<R, byte[]> encoder) { - messagingService.registerHandler(subject.value(), - new InternalMessageResponder<>(decoder, encoder, handler)); - } - - @Override - public <M> void addSubscriber(MessageSubject subject, - Function<byte[], M> decoder, - Consumer<M> handler, - Executor executor) { - messagingService.registerHandler(subject.value(), - new InternalMessageConsumer<>(decoder, handler), - executor); - } - - private class InternalClusterMessageHandler implements Function<byte[], byte[]> { - private ClusterMessageHandler handler; - - public InternalClusterMessageHandler(ClusterMessageHandler handler) { - this.handler = handler; - } - - @Override - public byte[] apply(byte[] bytes) { - ClusterMessage message = ClusterMessage.fromBytes(bytes); - handler.handle(message); - return message.response(); - } - } - - private class InternalMessageResponder<M, R> implements Function<byte[], CompletableFuture<byte[]>> { - private final Function<byte[], M> decoder; - private final Function<R, byte[]> encoder; - private final Function<M, CompletableFuture<R>> handler; - - public InternalMessageResponder(Function<byte[], M> decoder, - Function<R, byte[]> encoder, - Function<M, CompletableFuture<R>> handler) { - this.decoder = decoder; - this.encoder = encoder; - this.handler = handler; - } - - @Override - public CompletableFuture<byte[]> apply(byte[] bytes) { - return handler.apply(decoder.apply(ClusterMessage.fromBytes(bytes).payload())).thenApply(encoder); - } - } - - private class InternalMessageConsumer<M> implements Consumer<byte[]> { - private final Function<byte[], M> decoder; - private final Consumer<M> consumer; - - public InternalMessageConsumer(Function<byte[], M> decoder, Consumer<M> consumer) { - this.decoder = decoder; - this.consumer = consumer; - } - - @Override - public void accept(byte[] bytes) { - consumer.accept(decoder.apply(ClusterMessage.fromBytes(bytes).payload())); - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/IOLoopMessagingManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/IOLoopMessagingManager.java deleted file mode 100644 index ddb45f71..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/IOLoopMessagingManager.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.cluster.messaging.impl; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.nio.service.IOLoopMessaging; -import org.onosproject.cluster.ClusterMetadataService; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.store.cluster.messaging.Endpoint; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * IOLoop based MessagingService. - */ -@Component(immediate = true, enabled = false) -@Service -public class IOLoopMessagingManager extends IOLoopMessaging { - - private final Logger log = LoggerFactory.getLogger(getClass()); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterMetadataService clusterMetadataService; - - @Activate - public void activate() throws Exception { - ControllerNode localNode = clusterMetadataService.getLocalNode(); - super.start(new Endpoint(localNode.ip(), localNode.tcpPort())); - log.info("Started"); - } - - @Deactivate - public void deactivate() throws Exception { - super.stop(); - log.info("Stopped"); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java deleted file mode 100644 index ca6f9c1c..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.cluster.messaging.impl; - -import com.google.common.base.Strings; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.netty.NettyMessaging; -import org.onosproject.cluster.ClusterMetadataService; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.store.cluster.messaging.Endpoint; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Netty based MessagingService. - */ -@Component(immediate = true, enabled = true) -@Service -public class NettyMessagingManager extends NettyMessaging { - - private final Logger log = LoggerFactory.getLogger(getClass()); - - private static final short MIN_KS_LENGTH = 6; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterMetadataService clusterMetadataService; - - @Activate - public void activate() throws Exception { - ControllerNode localNode = clusterMetadataService.getLocalNode(); - getTlsParameters(); - super.start(clusterMetadataService.getClusterMetadata().getName().hashCode(), - new Endpoint(localNode.ip(), localNode.tcpPort())); - log.info("Started"); - } - - @Deactivate - public void deactivate() throws Exception { - super.stop(); - log.info("Stopped"); - } - - private void getTlsParameters() { - String tempString = System.getProperty("enableNettyTLS"); - enableNettyTls = Strings.isNullOrEmpty(tempString) ? TLS_DISABLED : Boolean.parseBoolean(tempString); - log.info("enableNettyTLS = {}", enableNettyTls); - if (enableNettyTls) { - ksLocation = System.getProperty("javax.net.ssl.keyStore"); - if (Strings.isNullOrEmpty(ksLocation)) { - enableNettyTls = TLS_DISABLED; - return; - } - tsLocation = System.getProperty("javax.net.ssl.trustStore"); - if (Strings.isNullOrEmpty(tsLocation)) { - enableNettyTls = TLS_DISABLED; - return; - } - ksPwd = System.getProperty("javax.net.ssl.keyStorePassword").toCharArray(); - if (MIN_KS_LENGTH > ksPwd.length) { - enableNettyTls = TLS_DISABLED; - return; - } - tsPwd = System.getProperty("javax.net.ssl.trustStorePassword").toCharArray(); - if (MIN_KS_LENGTH > tsPwd.length) { - enableNettyTls = TLS_DISABLED; - return; - } - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/package-info.java deleted file mode 100644 index 7157277e..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of the cluster messaging mechanism. - */ -package org.onosproject.store.cluster.messaging.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/config/impl/DistributedNetworkConfigStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/config/impl/DistributedNetworkConfigStore.java deleted file mode 100644 index 27c79122..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/config/impl/DistributedNetworkConfigStore.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.config.impl; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.BooleanNode; -import com.fasterxml.jackson.databind.node.DoubleNode; -import com.fasterxml.jackson.databind.node.IntNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.LongNode; -import com.fasterxml.jackson.databind.node.NullNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.databind.node.ShortNode; -import com.fasterxml.jackson.databind.node.TextNode; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Maps; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onlab.util.Tools; -import org.onosproject.net.config.Config; -import org.onosproject.net.config.ConfigApplyDelegate; -import org.onosproject.net.config.ConfigFactory; -import org.onosproject.net.config.NetworkConfigEvent; -import org.onosproject.net.config.NetworkConfigStore; -import org.onosproject.net.config.NetworkConfigStoreDelegate; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.ConsistentMapException; -import org.onosproject.store.service.MapEvent; -import org.onosproject.store.service.MapEventListener; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.StorageService; -import org.onosproject.store.service.Versioned; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -import static com.google.common.base.Preconditions.checkArgument; -import static org.onosproject.net.config.NetworkConfigEvent.Type.*; - -/** - * Implementation of a distributed network configuration store. - */ -@Component(immediate = true) -@Service -public class DistributedNetworkConfigStore - extends AbstractStore<NetworkConfigEvent, NetworkConfigStoreDelegate> - implements NetworkConfigStore { - - private final Logger log = LoggerFactory.getLogger(getClass()); - - private static final int MAX_BACKOFF = 10; - private static final String INVALID_CONFIG_JSON = - "JSON node does not contain valid configuration"; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - private ConsistentMap<ConfigKey, JsonNode> configs; - - private final Map<String, ConfigFactory> factoriesByConfig = Maps.newConcurrentMap(); - private final ObjectMapper mapper = new ObjectMapper(); - private final ConfigApplyDelegate applyDelegate = new InternalApplyDelegate(); - private final MapEventListener<ConfigKey, JsonNode> listener = new InternalMapListener(); - - @Activate - public void activate() { - KryoNamespace.Builder kryoBuilder = new KryoNamespace.Builder() - .register(KryoNamespaces.API) - .register(ConfigKey.class, ObjectNode.class, ArrayNode.class, - JsonNodeFactory.class, LinkedHashMap.class, - TextNode.class, BooleanNode.class, - LongNode.class, DoubleNode.class, ShortNode.class, IntNode.class, - NullNode.class); - - configs = storageService.<ConfigKey, JsonNode>consistentMapBuilder() - .withSerializer(Serializer.using(kryoBuilder.build())) - .withName("onos-network-configs") - .withRelaxedReadConsistency() - .build(); - configs.addListener(listener); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - configs.removeListener(listener); - log.info("Stopped"); - } - - @Override - public void addConfigFactory(ConfigFactory configFactory) { - factoriesByConfig.put(configFactory.configClass().getName(), configFactory); - notifyDelegate(new NetworkConfigEvent(CONFIG_REGISTERED, configFactory.configKey(), - configFactory.configClass())); - } - - @Override - public void removeConfigFactory(ConfigFactory configFactory) { - factoriesByConfig.remove(configFactory.configClass().getName()); - notifyDelegate(new NetworkConfigEvent(CONFIG_UNREGISTERED, configFactory.configKey(), - configFactory.configClass())); - } - - @Override - @SuppressWarnings("unchecked") - public <S, C extends Config<S>> ConfigFactory<S, C> getConfigFactory(Class<C> configClass) { - return (ConfigFactory<S, C>) factoriesByConfig.get(configClass.getName()); - } - - @Override - @SuppressWarnings("unchecked") - public <S> Set<S> getSubjects(Class<S> subjectClass) { - ImmutableSet.Builder<S> builder = ImmutableSet.builder(); - configs.keySet().forEach(k -> { - if (subjectClass.isInstance(k.subject)) { - builder.add((S) k.subject); - } - }); - return builder.build(); - } - - @Override - @SuppressWarnings("unchecked") - public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass, Class<C> configClass) { - ImmutableSet.Builder<S> builder = ImmutableSet.builder(); - String cName = configClass.getName(); - configs.keySet().forEach(k -> { - if (subjectClass.isInstance(k.subject) && cName.equals(k.configClass)) { - builder.add((S) k.subject); - } - }); - return builder.build(); - } - - @Override - @SuppressWarnings("unchecked") - public <S> Set<Class<? extends Config<S>>> getConfigClasses(S subject) { - ImmutableSet.Builder<Class<? extends Config<S>>> builder = ImmutableSet.builder(); - configs.keySet().forEach(k -> { - if (Objects.equals(subject, k.subject) && delegate != null) { - builder.add(factoriesByConfig.get(k.configClass).configClass()); - } - }); - return builder.build(); - } - - @Override - public <S, T extends Config<S>> T getConfig(S subject, Class<T> configClass) { - // TODO: need to identify and address the root cause for timeouts. - Versioned<JsonNode> json = Tools.retryable(configs::get, ConsistentMapException.class, 1, MAX_BACKOFF) - .apply(key(subject, configClass)); - return json != null ? createConfig(subject, configClass, json.value()) : null; - } - - - @Override - public <S, C extends Config<S>> C createConfig(S subject, Class<C> configClass) { - ConfigFactory<S, C> factory = getConfigFactory(configClass); - Versioned<JsonNode> json = configs.computeIfAbsent(key(subject, configClass), - k -> factory.isList() ? - mapper.createArrayNode() : - mapper.createObjectNode()); - return createConfig(subject, configClass, json.value()); - } - - @Override - public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) { - // Create the configuration and validate it. - C config = createConfig(subject, configClass, json); - checkArgument(config.isValid(), INVALID_CONFIG_JSON); - - // Insert the validated configuration and get it back. - Versioned<JsonNode> versioned = configs.putAndGet(key(subject, configClass), json); - - // Re-create the config if for some reason what we attempted to put - // was supplanted by someone else already. - return versioned.value() == json ? config : - createConfig(subject, configClass, versioned.value()); - } - - @Override - public <S, C extends Config<S>> void clearConfig(S subject, Class<C> configClass) { - configs.remove(key(subject, configClass)); - } - - /** - * Produces a config from the specified subject, config class and raw JSON. - * - * @param subject config subject - * @param configClass config class - * @param json raw JSON data - * @return config object or null of no factory found or if the specified - * JSON is null - */ - @SuppressWarnings("unchecked") - private <S, C extends Config<S>> C createConfig(S subject, Class<C> configClass, - JsonNode json) { - if (json != null) { - ConfigFactory<S, C> factory = factoriesByConfig.get(configClass.getName()); - if (factory != null) { - C config = factory.createConfig(); - config.init(subject, factory.configKey(), json, mapper, applyDelegate); - return config; - } - } - return null; - } - - - // Auxiliary delegate to receive notifications about changes applied to - // the network configuration - by the apps. - private class InternalApplyDelegate implements ConfigApplyDelegate { - @Override - public void onApply(Config config) { - configs.put(key(config.subject(), config.getClass()), config.node()); - } - } - - // Produces a key for uniquely tracking a subject config. - private static ConfigKey key(Object subject, Class<?> configClass) { - return new ConfigKey(subject, configClass); - } - - // Auxiliary key to track subject configurations. - private static final class ConfigKey { - final Object subject; - final String configClass; - - private ConfigKey(Object subject, Class<?> configClass) { - this.subject = subject; - this.configClass = configClass.getName(); - } - - @Override - public int hashCode() { - return Objects.hash(subject, configClass); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof ConfigKey) { - final ConfigKey other = (ConfigKey) obj; - return Objects.equals(this.subject, other.subject) - && Objects.equals(this.configClass, other.configClass); - } - return false; - } - } - - private class InternalMapListener implements MapEventListener<ConfigKey, JsonNode> { - @Override - public void event(MapEvent<ConfigKey, JsonNode> event) { - NetworkConfigEvent.Type type; - switch (event.type()) { - case INSERT: - type = CONFIG_ADDED; - break; - case UPDATE: - type = CONFIG_UPDATED; - break; - case REMOVE: - default: - type = CONFIG_REMOVED; - break; - } - ConfigFactory factory = factoriesByConfig.get(event.key().configClass); - if (factory != null) { - notifyDelegate(new NetworkConfigEvent(type, event.key().subject, - factory.configClass())); - } - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/config/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/config/impl/package-info.java deleted file mode 100644 index 0e1264eb..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/config/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of the network configuration distributed store. - */ -package org.onosproject.store.config.impl;
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/AsyncCachingConsistentMap.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/AsyncCachingConsistentMap.java deleted file mode 100644 index 92db5b44..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/AsyncCachingConsistentMap.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import java.util.concurrent.CompletableFuture; - -import org.onosproject.core.ApplicationId; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.Versioned; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; - -/** - * Extension of {@link DefaultAsyncConsistentMap} that provides a weaker read consistency - * guarantee in return for better read performance. - * <p> - * For read/write operations that are local to a node this map implementation provides - * guarantees similar to a ConsistentMap. However for read/write operations executed - * across multiple nodes this implementation only provides eventual consistency. - * - * @param <K> key type - * @param <V> value type - */ -public class AsyncCachingConsistentMap<K, V> extends DefaultAsyncConsistentMap<K, V> { - - private final LoadingCache<K, CompletableFuture<Versioned<V>>> cache = - CacheBuilder.newBuilder() - .maximumSize(10000) // TODO: make configurable - .build(new CacheLoader<K, CompletableFuture<Versioned<V>>>() { - @Override - public CompletableFuture<Versioned<V>> load(K key) - throws Exception { - return AsyncCachingConsistentMap.super.get(key); - } - }); - - public AsyncCachingConsistentMap(String name, - ApplicationId applicationId, - Database database, - Serializer serializer, - boolean readOnly, - boolean purgeOnUninstall, - boolean meteringEnabled) { - super(name, applicationId, database, serializer, readOnly, purgeOnUninstall, meteringEnabled); - addListener(event -> cache.invalidate(event.key())); - } - - @Override - public CompletableFuture<Versioned<V>> get(K key) { - CompletableFuture<Versioned<V>> cachedValue = cache.getIfPresent(key); - if (cachedValue != null) { - if (cachedValue.isCompletedExceptionally()) { - cache.invalidate(key); - } else { - return cachedValue; - } - } - return cache.getUnchecked(key); - } - - @Override - protected void beforeUpdate(K key) { - super.beforeUpdate(key); - cache.invalidate(key); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/CommitResponse.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/CommitResponse.java deleted file mode 100644 index bbc8e6e0..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/CommitResponse.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import static com.google.common.base.MoreObjects.toStringHelper; - -import java.util.Collections; -import java.util.List; - -import com.google.common.collect.ImmutableList; - -/** - * Result of a Transaction commit operation. - */ -public final class CommitResponse { - - private boolean success; - private List<UpdateResult<String, byte[]>> updates; - - public static CommitResponse success(List<UpdateResult<String, byte[]>> updates) { - return new CommitResponse(true, updates); - } - - public static CommitResponse failure() { - return new CommitResponse(false, Collections.emptyList()); - } - - private CommitResponse(boolean success, List<UpdateResult<String, byte[]>> updates) { - this.success = success; - this.updates = ImmutableList.copyOf(updates); - } - - public boolean success() { - return success; - } - - public List<UpdateResult<String, byte[]>> updates() { - return updates; - } - - @Override - public String toString() { - return toStringHelper(this) - .add("success", success) - .add("udpates", updates) - .toString(); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/ConsistentMapBackedJavaMap.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/ConsistentMapBackedJavaMap.java deleted file mode 100644 index 5183924c..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/ConsistentMapBackedJavaMap.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.Versioned; - -import com.google.common.collect.Collections2; -import com.google.common.collect.Maps; - -/** - * Standard java Map backed by a ConsistentMap. - * - * @param <K> key type - * @param <V> value type - */ -public final class ConsistentMapBackedJavaMap<K, V> implements Map<K, V> { - - private final ConsistentMap<K, V> backingMap; - - public ConsistentMapBackedJavaMap(ConsistentMap<K, V> backingMap) { - this.backingMap = backingMap; - } - - @Override - public int size() { - return backingMap.size(); - } - - @Override - public boolean isEmpty() { - return backingMap.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - return backingMap.containsKey((K) key); - } - - @Override - public boolean containsValue(Object value) { - return backingMap.containsValue((V) value); - } - - @Override - public V get(Object key) { - return Versioned.valueOrElse(backingMap.get((K) key), null); - } - - @Override - public V getOrDefault(Object key, V defaultValue) { - return Versioned.valueOrElse(backingMap.get((K) key), defaultValue); - } - - @Override - public V put(K key, V value) { - return Versioned.valueOrElse(backingMap.put(key, value), null); - } - - @Override - public V putIfAbsent(K key, V value) { - return Versioned.valueOrElse(backingMap.putIfAbsent(key, value), null); - } - - @Override - public V remove(Object key) { - return Versioned.valueOrElse(backingMap.remove((K) key), null); - } - - @Override - public boolean remove(Object key, Object value) { - return backingMap.remove((K) key, (V) value); - } - - @Override - public V replace(K key, V value) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean replace(K key, V oldValue, V newValue) { - return backingMap.replace(key, oldValue, newValue); - } - - @Override - public void putAll(Map<? extends K, ? extends V> m) { - m.forEach((k, v) -> { - backingMap.put(k, v); - }); - } - - @Override - public void clear() { - backingMap.clear(); - } - - @Override - public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { - return Versioned.valueOrElse(backingMap.compute(key, remappingFunction), null); - } - - @Override - public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { - return Versioned.valueOrElse(backingMap.computeIfAbsent(key, mappingFunction), null); - } - - @Override - public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { - return Versioned.valueOrElse(backingMap.computeIfPresent(key, remappingFunction), null); - } - - @Override - public Set<K> keySet() { - return backingMap.keySet(); - } - - @Override - public Collection<V> values() { - return Collections2.transform(backingMap.values(), v -> v.value()); - } - - @Override - public Set<java.util.Map.Entry<K, V>> entrySet() { - return backingMap.entrySet() - .stream() - .map(entry -> Maps.immutableEntry(entry.getKey(), entry.getValue().value())) - .collect(Collectors.toSet()); - } - - @Override - public void forEach(BiConsumer<? super K, ? super V> action) { - entrySet().forEach(e -> action.accept(e.getKey(), e.getValue())); - } - - @Override - public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) { - return computeIfPresent(key, (k, v) -> v == null ? value : remappingFunction.apply(v, value)); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/CopycatCommunicationProtocol.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/CopycatCommunicationProtocol.java deleted file mode 100644 index 88ddae62..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/CopycatCommunicationProtocol.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import java.net.URI; -import java.nio.ByteBuffer; -import java.util.concurrent.CompletableFuture; - -import org.onlab.util.Tools; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.NodeId; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.cluster.messaging.MessageSubject; - -import net.kuujo.copycat.protocol.AbstractProtocol; -import net.kuujo.copycat.protocol.ProtocolClient; -import net.kuujo.copycat.protocol.ProtocolHandler; -import net.kuujo.copycat.protocol.ProtocolServer; -import net.kuujo.copycat.util.Configurable; - -/** - * Protocol for Copycat communication that employs - * {@code ClusterCommunicationService}. - */ -public class CopycatCommunicationProtocol extends AbstractProtocol { - - private static final MessageSubject COPYCAT_MESSAGE_SUBJECT = - new MessageSubject("onos-copycat-message"); - - protected ClusterService clusterService; - protected ClusterCommunicationService clusterCommunicator; - - public CopycatCommunicationProtocol(ClusterService clusterService, - ClusterCommunicationService clusterCommunicator) { - this.clusterService = clusterService; - this.clusterCommunicator = clusterCommunicator; - } - - @Override - public Configurable copy() { - return this; - } - - @Override - public ProtocolClient createClient(URI uri) { - NodeId nodeId = uriToNodeId(uri); - if (nodeId == null) { - throw new IllegalStateException("Unknown peer " + uri); - } - return new Client(nodeId); - } - - @Override - public ProtocolServer createServer(URI uri) { - return new Server(); - } - - private class Server implements ProtocolServer { - - @Override - public void handler(ProtocolHandler handler) { - if (handler == null) { - clusterCommunicator.removeSubscriber(COPYCAT_MESSAGE_SUBJECT); - } else { - clusterCommunicator.addSubscriber(COPYCAT_MESSAGE_SUBJECT, - ByteBuffer::wrap, - handler, - Tools::byteBuffertoArray); - // FIXME: Tools::byteBuffertoArray involves a array copy. - } - } - - @Override - public CompletableFuture<Void> listen() { - return CompletableFuture.completedFuture(null); - } - - @Override - public CompletableFuture<Void> close() { - clusterCommunicator.removeSubscriber(COPYCAT_MESSAGE_SUBJECT); - return CompletableFuture.completedFuture(null); - } - } - - private class Client implements ProtocolClient { - private final NodeId peer; - - public Client(NodeId peer) { - this.peer = peer; - } - - @Override - public CompletableFuture<ByteBuffer> write(ByteBuffer request) { - return clusterCommunicator.sendAndReceive(request, - COPYCAT_MESSAGE_SUBJECT, - Tools::byteBuffertoArray, - ByteBuffer::wrap, - peer); - } - - @Override - public CompletableFuture<Void> connect() { - return CompletableFuture.completedFuture(null); - } - - @Override - public CompletableFuture<Void> close() { - return CompletableFuture.completedFuture(null); - } - } - - private NodeId uriToNodeId(URI uri) { - return clusterService.getNodes() - .stream() - .filter(node -> uri.getHost().equals(node.ip().toString())) - .map(ControllerNode::id) - .findAny() - .orElse(null); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/Database.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/Database.java deleted file mode 100644 index 52a999a4..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/Database.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - - -import java.util.function.Consumer; - -import net.kuujo.copycat.cluster.ClusterConfig; -import net.kuujo.copycat.cluster.internal.coordinator.ClusterCoordinator; -import net.kuujo.copycat.cluster.internal.coordinator.CoordinatorConfig; -import net.kuujo.copycat.cluster.internal.coordinator.DefaultClusterCoordinator; -import net.kuujo.copycat.resource.Resource; - -/** - * Database. - */ -public interface Database extends DatabaseProxy<String, byte[]>, Resource<Database> { - - /** - * Creates a new database with the default cluster configuration.<p> - * - * The database will be constructed with the default cluster configuration. The default cluster configuration - * searches for two resources on the classpath - {@code cluster} and {cluster-defaults} - in that order. Configuration - * options specified in {@code cluster.conf} will override those in {cluster-defaults.conf}.<p> - * - * Additionally, the database will be constructed with an database configuration that searches the classpath for - * three configuration files - {@code name}, {@code database}, {@code database-defaults}, {@code resource}, and - * {@code resource-defaults} - in that order. The first resource is a configuration resource with the same name - * as the map resource. If the resource is namespaced - e.g. `databases.my-database.conf` - then resource - * configurations will be loaded according to namespaces as well; for example, `databases.conf`. - * - * @param name The database name. - * @return The database. - */ - static Database create(String name) { - return create(name, new ClusterConfig(), new DatabaseConfig()); - } - - /** - * Creates a new database.<p> - * - * The database will be constructed with an database configuration that searches the classpath for - * three configuration files - {@code name}, {@code database}, {@code database-defaults}, {@code resource}, and - * {@code resource-defaults} - in that order. The first resource is a configuration resource with the same name - * as the database resource. If the resource is namespaced - e.g. `databases.my-database.conf` - then resource - * configurations will be loaded according to namespaces as well; for example, `databases.conf`. - * - * @param name The database name. - * @param cluster The cluster configuration. - * @return The database. - */ - static Database create(String name, ClusterConfig cluster) { - return create(name, cluster, new DatabaseConfig()); - } - - /** - * Creates a new database. - * - * @param name The database name. - * @param cluster The cluster configuration. - * @param config The database configuration. - - * @return The database. - */ - static Database create(String name, ClusterConfig cluster, DatabaseConfig config) { - ClusterCoordinator coordinator = - new DefaultClusterCoordinator(new CoordinatorConfig().withName(name).withClusterConfig(cluster)); - return coordinator.<Database>getResource(name, config.resolve(cluster)) - .addStartupTask(() -> coordinator.open().thenApply(v -> null)) - .addShutdownTask(coordinator::close); - } - - /** - * Tells whether the database supports change notifications. - * @return true if notifications are supported; false otherwise - */ - default boolean hasChangeNotificationSupport() { - return true; - } - - /** - * Registers a new consumer of StateMachineUpdates. - * @param consumer consumer to register - */ - void registerConsumer(Consumer<StateMachineUpdate> consumer); - - /** - * Unregisters a consumer of StateMachineUpdates. - * @param consumer consumer to unregister - */ - void unregisterConsumer(Consumer<StateMachineUpdate> consumer); -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseConfig.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseConfig.java deleted file mode 100644 index bd774b99..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseConfig.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import com.typesafe.config.ConfigValueFactory; -import net.kuujo.copycat.cluster.ClusterConfig; -import net.kuujo.copycat.cluster.internal.coordinator.CoordinatedResourceConfig; -import net.kuujo.copycat.protocol.Consistency; -import net.kuujo.copycat.resource.ResourceConfig; -import net.kuujo.copycat.state.StateLogConfig; -import net.kuujo.copycat.util.internal.Assert; - -import java.util.Map; - -/** - * Database configuration. - * - */ -public class DatabaseConfig extends ResourceConfig<DatabaseConfig> { - private static final String DATABASE_CONSISTENCY = "consistency"; - - private static final String DEFAULT_CONFIGURATION = "database-defaults"; - private static final String CONFIGURATION = "database"; - - private String name; - - public DatabaseConfig() { - super(CONFIGURATION, DEFAULT_CONFIGURATION); - } - - public DatabaseConfig(Map<String, Object> config) { - super(config, CONFIGURATION, DEFAULT_CONFIGURATION); - } - - public DatabaseConfig(String resource) { - super(resource, CONFIGURATION, DEFAULT_CONFIGURATION); - } - - protected DatabaseConfig(DatabaseConfig config) { - super(config); - } - - @Override - public DatabaseConfig copy() { - return new DatabaseConfig(this); - } - - /** - * Sets the database read consistency. - * - * @param consistency The database read consistency. - * @throws java.lang.NullPointerException If the consistency is {@code null} - */ - public void setConsistency(String consistency) { - this.config = config.withValue(DATABASE_CONSISTENCY, - ConfigValueFactory.fromAnyRef( - Consistency.parse(Assert.isNotNull(consistency, "consistency")).toString())); - } - - /** - * Sets the database read consistency. - * - * @param consistency The database read consistency. - * @throws java.lang.NullPointerException If the consistency is {@code null} - */ - public void setConsistency(Consistency consistency) { - this.config = config.withValue(DATABASE_CONSISTENCY, - ConfigValueFactory.fromAnyRef( - Assert.isNotNull(consistency, "consistency").toString())); - } - - /** - * Returns the database read consistency. - * - * @return The database read consistency. - */ - public Consistency getConsistency() { - return Consistency.parse(config.getString(DATABASE_CONSISTENCY)); - } - - /** - * Sets the database read consistency, returning the configuration for method chaining. - * - * @param consistency The database read consistency. - * @return The database configuration. - * @throws java.lang.NullPointerException If the consistency is {@code null} - */ - public DatabaseConfig withConsistency(String consistency) { - setConsistency(consistency); - return this; - } - - /** - * Sets the database read consistency, returning the configuration for method chaining. - * - * @param consistency The database read consistency. - * @return The database configuration. - * @throws java.lang.NullPointerException If the consistency is {@code null} - */ - public DatabaseConfig withConsistency(Consistency consistency) { - setConsistency(consistency); - return this; - } - - /** - * Returns the database name. - * - * @return The database name - */ - public String getName() { - return name; - } - - /** - * Sets the database name, returning the configuration for method chaining. - * - * @param name The database name - * @return The database configuration - * @throws java.lang.NullPointerException If the name is {@code null} - */ - public DatabaseConfig withName(String name) { - setName(Assert.isNotNull(name, "name")); - return this; - } - - /** - * Sets the database name. - * - * @param name The database name - * @throws java.lang.NullPointerException If the name is {@code null} - */ - public void setName(String name) { - this.name = Assert.isNotNull(name, "name"); - } - - @Override - public CoordinatedResourceConfig resolve(ClusterConfig cluster) { - return new StateLogConfig(toMap()) - .resolve(cluster) - .withResourceType(DefaultDatabase.class); - } - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseManager.java deleted file mode 100644 index 90d81ee7..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseManager.java +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; -import com.google.common.collect.Multimaps; -import com.google.common.collect.Sets; -import com.google.common.util.concurrent.Futures; - -import net.kuujo.copycat.CopycatConfig; -import net.kuujo.copycat.cluster.ClusterConfig; -import net.kuujo.copycat.cluster.Member; -import net.kuujo.copycat.cluster.Member.Type; -import net.kuujo.copycat.cluster.internal.coordinator.ClusterCoordinator; -import net.kuujo.copycat.cluster.internal.coordinator.DefaultClusterCoordinator; -import net.kuujo.copycat.log.BufferedLog; -import net.kuujo.copycat.log.FileLog; -import net.kuujo.copycat.log.Log; -import net.kuujo.copycat.protocol.Consistency; -import net.kuujo.copycat.protocol.Protocol; -import net.kuujo.copycat.util.concurrent.NamedThreadFactory; - -import org.apache.commons.lang.math.RandomUtils; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.ReferencePolicy; -import org.apache.felix.scr.annotations.Service; -import org.onosproject.app.ApplicationEvent; -import org.onosproject.app.ApplicationListener; -import org.onosproject.app.ApplicationService; -import org.onosproject.cluster.ClusterMetadataService; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.NodeId; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.IdGenerator; -import org.onosproject.persistence.PersistenceService; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.ecmap.EventuallyConsistentMapBuilderImpl; -import org.onosproject.store.service.AtomicCounterBuilder; -import org.onosproject.store.service.AtomicValueBuilder; -import org.onosproject.store.service.ConsistentMapBuilder; -import org.onosproject.store.service.ConsistentMapException; -import org.onosproject.store.service.DistributedQueueBuilder; -import org.onosproject.store.service.EventuallyConsistentMapBuilder; -import org.onosproject.store.service.MapInfo; -import org.onosproject.store.service.PartitionInfo; -import org.onosproject.store.service.DistributedSetBuilder; -import org.onosproject.store.service.StorageAdminService; -import org.onosproject.store.service.StorageService; -import org.onosproject.store.service.Transaction; -import org.onosproject.store.service.TransactionContextBuilder; -import org.slf4j.Logger; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.stream.Collectors; - -import static org.slf4j.LoggerFactory.getLogger; -import static org.onosproject.app.ApplicationEvent.Type.APP_UNINSTALLED; -import static org.onosproject.app.ApplicationEvent.Type.APP_DEACTIVATED; - -/** - * Database manager. - */ -@Component(immediate = true, enabled = true) -@Service -public class DatabaseManager implements StorageService, StorageAdminService { - - private final Logger log = getLogger(getClass()); - - public static final String BASE_PARTITION_NAME = "p0"; - - private static final int RAFT_ELECTION_TIMEOUT_MILLIS = 3000; - private static final int DATABASE_OPERATION_TIMEOUT_MILLIS = 5000; - - private ClusterCoordinator coordinator; - protected PartitionedDatabase partitionedDatabase; - protected Database inMemoryDatabase; - protected NodeId localNodeId; - - private TransactionManager transactionManager; - private final IdGenerator transactionIdGenerator = () -> RandomUtils.nextLong(); - - private ApplicationListener appListener = new InternalApplicationListener(); - - private final Multimap<String, DefaultAsyncConsistentMap> maps = - Multimaps.synchronizedMultimap(ArrayListMultimap.create()); - private final Multimap<ApplicationId, DefaultAsyncConsistentMap> mapsByApplication = - Multimaps.synchronizedMultimap(ArrayListMultimap.create()); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterMetadataService clusterMetadataService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC) - protected ApplicationService applicationService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterCommunicationService clusterCommunicator; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected PersistenceService persistenceService; - - protected String nodeIdToUri(NodeId nodeId) { - ControllerNode node = clusterService.getNode(nodeId); - return String.format("onos://%s:%d", node.ip(), node.tcpPort()); - } - - protected void bindApplicationService(ApplicationService service) { - applicationService = service; - applicationService.addListener(appListener); - } - - protected void unbindApplicationService(ApplicationService service) { - applicationService.removeListener(appListener); - this.applicationService = null; - } - - @Activate - public void activate() { - localNodeId = clusterService.getLocalNode().id(); - - Map<String, Set<NodeId>> partitionMap = Maps.newHashMap(); - clusterMetadataService.getClusterMetadata().getPartitions().forEach(p -> { - partitionMap.put(p.getName(), Sets.newHashSet(p.getMembers())); - }); - - - String[] activeNodeUris = partitionMap.values() - .stream() - .reduce((s1, s2) -> Sets.union(s1, s2)) - .get() - .stream() - .map(this::nodeIdToUri) - .toArray(String[]::new); - - String localNodeUri = nodeIdToUri(clusterMetadataService.getLocalNode().id()); - Protocol protocol = new CopycatCommunicationProtocol(clusterService, clusterCommunicator); - - ClusterConfig clusterConfig = new ClusterConfig() - .withProtocol(protocol) - .withElectionTimeout(electionTimeoutMillis(activeNodeUris)) - .withHeartbeatInterval(heartbeatTimeoutMillis(activeNodeUris)) - .withMembers(activeNodeUris) - .withLocalMember(localNodeUri); - - CopycatConfig copycatConfig = new CopycatConfig() - .withName("onos") - .withClusterConfig(clusterConfig) - .withDefaultSerializer(new DatabaseSerializer()) - .withDefaultExecutor(Executors.newSingleThreadExecutor(new NamedThreadFactory("copycat-coordinator-%d"))); - - coordinator = new DefaultClusterCoordinator(copycatConfig.resolve()); - - DatabaseConfig inMemoryDatabaseConfig = - newDatabaseConfig(BASE_PARTITION_NAME, newInMemoryLog(), activeNodeUris); - inMemoryDatabase = coordinator - .getResource(inMemoryDatabaseConfig.getName(), inMemoryDatabaseConfig.resolve(clusterConfig) - .withSerializer(copycatConfig.getDefaultSerializer()) - .withDefaultExecutor(copycatConfig.getDefaultExecutor())); - - List<Database> partitions = partitionMap.entrySet() - .stream() - .map(entry -> { - String[] replicas = entry.getValue().stream().map(this::nodeIdToUri).toArray(String[]::new); - return newDatabaseConfig(entry.getKey(), newPersistentLog(), replicas); - }) - .map(config -> { - Database db = coordinator.getResource(config.getName(), config.resolve(clusterConfig) - .withSerializer(copycatConfig.getDefaultSerializer()) - .withDefaultExecutor(copycatConfig.getDefaultExecutor())); - return db; - }) - .collect(Collectors.toList()); - - partitionedDatabase = new PartitionedDatabase("onos-store", partitions); - - CompletableFuture<Void> status = coordinator.open() - .thenCompose(v -> CompletableFuture.allOf(inMemoryDatabase.open(), partitionedDatabase.open()) - .whenComplete((db, error) -> { - if (error != null) { - log.error("Failed to initialize database.", error); - } else { - log.info("Successfully initialized database."); - } - })); - - Futures.getUnchecked(status); - - transactionManager = new TransactionManager(partitionedDatabase, consistentMapBuilder()); - partitionedDatabase.setTransactionManager(transactionManager); - - log.info("Started"); - } - - @Deactivate - public void deactivate() { - CompletableFuture.allOf(inMemoryDatabase.close(), partitionedDatabase.close()) - .thenCompose(v -> coordinator.close()) - .whenComplete((result, error) -> { - if (error != null) { - log.warn("Failed to cleanly close databases.", error); - } else { - log.info("Successfully closed databases."); - } - }); - ImmutableList.copyOf(maps.values()).forEach(this::unregisterMap); - if (applicationService != null) { - applicationService.removeListener(appListener); - } - log.info("Stopped"); - } - - @Override - public TransactionContextBuilder transactionContextBuilder() { - return new DefaultTransactionContextBuilder(this, transactionIdGenerator.getNewId()); - } - - @Override - public List<PartitionInfo> getPartitionInfo() { - return Lists.asList( - inMemoryDatabase, - partitionedDatabase.getPartitions().toArray(new Database[]{})) - .stream() - .map(DatabaseManager::toPartitionInfo) - .collect(Collectors.toList()); - } - - private Log newPersistentLog() { - String logDir = System.getProperty("karaf.data", "./data"); - return new FileLog() - .withDirectory(logDir) - .withSegmentSize(1073741824) // 1GB - .withFlushOnWrite(true) - .withSegmentInterval(Long.MAX_VALUE); - } - - private Log newInMemoryLog() { - return new BufferedLog() - .withFlushOnWrite(false) - .withFlushInterval(Long.MAX_VALUE) - .withSegmentSize(10485760) // 10MB - .withSegmentInterval(Long.MAX_VALUE); - } - - private DatabaseConfig newDatabaseConfig(String name, Log log, String[] replicas) { - return new DatabaseConfig() - .withName(name) - .withElectionTimeout(electionTimeoutMillis(replicas)) - .withHeartbeatInterval(heartbeatTimeoutMillis(replicas)) - .withConsistency(Consistency.DEFAULT) - .withLog(log) - .withDefaultSerializer(new DatabaseSerializer()) - .withReplicas(replicas); - } - - private long electionTimeoutMillis(String[] replicas) { - return replicas.length == 1 ? 10L : RAFT_ELECTION_TIMEOUT_MILLIS; - } - - private long heartbeatTimeoutMillis(String[] replicas) { - return electionTimeoutMillis(replicas) / 2; - } - - /** - * Maps a Raft Database object to a PartitionInfo object. - * - * @param database database containing input data - * @return PartitionInfo object - */ - private static PartitionInfo toPartitionInfo(Database database) { - return new PartitionInfo(database.name(), - database.cluster().term(), - database.cluster().members() - .stream() - .filter(member -> Type.ACTIVE.equals(member.type())) - .map(Member::uri) - .sorted() - .collect(Collectors.toList()), - database.cluster().leader() != null ? - database.cluster().leader().uri() : null); - } - - - @Override - public <K, V> EventuallyConsistentMapBuilder<K, V> eventuallyConsistentMapBuilder() { - return new EventuallyConsistentMapBuilderImpl<>(clusterService, - clusterCommunicator, - persistenceService); - } - - @Override - public <K, V> ConsistentMapBuilder<K, V> consistentMapBuilder() { - return new DefaultConsistentMapBuilder<>(this); - } - - @Override - public <E> DistributedSetBuilder<E> setBuilder() { - return new DefaultDistributedSetBuilder<>(this); - } - - - @Override - public <E> DistributedQueueBuilder<E> queueBuilder() { - return new DefaultDistributedQueueBuilder<>(this); - } - - @Override - public AtomicCounterBuilder atomicCounterBuilder() { - return new DefaultAtomicCounterBuilder(inMemoryDatabase, partitionedDatabase); - } - - @Override - public <V> AtomicValueBuilder<V> atomicValueBuilder() { - return new DefaultAtomicValueBuilder<>(this); - } - - @Override - public List<MapInfo> getMapInfo() { - List<MapInfo> maps = Lists.newArrayList(); - maps.addAll(getMapInfo(inMemoryDatabase)); - maps.addAll(getMapInfo(partitionedDatabase)); - return maps; - } - - private List<MapInfo> getMapInfo(Database database) { - return complete(database.maps()) - .stream() - .map(name -> new MapInfo(name, complete(database.mapSize(name)))) - .filter(info -> info.size() > 0) - .collect(Collectors.toList()); - } - - - @Override - public Map<String, Long> getCounters() { - Map<String, Long> counters = Maps.newHashMap(); - counters.putAll(complete(inMemoryDatabase.counters())); - counters.putAll(complete(partitionedDatabase.counters())); - return counters; - } - - @Override - public Map<String, Long> getPartitionedDatabaseCounters() { - Map<String, Long> counters = Maps.newHashMap(); - counters.putAll(complete(partitionedDatabase.counters())); - return counters; - } - - @Override - public Map<String, Long> getInMemoryDatabaseCounters() { - Map<String, Long> counters = Maps.newHashMap(); - counters.putAll(complete(inMemoryDatabase.counters())); - return counters; - } - - @Override - public Collection<Transaction> getTransactions() { - return complete(transactionManager.getTransactions()); - } - - private static <T> T complete(CompletableFuture<T> future) { - try { - return future.get(DATABASE_OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ConsistentMapException.Interrupted(); - } catch (TimeoutException e) { - throw new ConsistentMapException.Timeout(); - } catch (ExecutionException e) { - throw new ConsistentMapException(e.getCause()); - } - } - - @Override - public void redriveTransactions() { - getTransactions().stream().forEach(transactionManager::execute); - } - - protected <K, V> DefaultAsyncConsistentMap<K, V> registerMap(DefaultAsyncConsistentMap<K, V> map) { - maps.put(map.name(), map); - if (map.applicationId() != null) { - mapsByApplication.put(map.applicationId(), map); - } - return map; - } - - protected <K, V> void unregisterMap(DefaultAsyncConsistentMap<K, V> map) { - maps.remove(map.name(), map); - if (map.applicationId() != null) { - mapsByApplication.remove(map.applicationId(), map); - } - } - - private class InternalApplicationListener implements ApplicationListener { - @Override - public void event(ApplicationEvent event) { - if (event.type() == APP_UNINSTALLED || event.type() == APP_DEACTIVATED) { - ApplicationId appId = event.subject().id(); - List<DefaultAsyncConsistentMap> mapsToRemove; - synchronized (mapsByApplication) { - mapsToRemove = ImmutableList.copyOf(mapsByApplication.get(appId)); - } - mapsToRemove.forEach(DatabaseManager.this::unregisterMap); - if (event.type() == APP_UNINSTALLED) { - mapsToRemove.stream().filter(map -> map.purgeOnUninstall()).forEach(map -> map.clear()); - } - } - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabasePartitioner.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabasePartitioner.java deleted file mode 100644 index 740f81ad..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabasePartitioner.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import static com.google.common.base.Preconditions.checkState; - -import java.util.List; -import com.google.common.base.Charsets; -import com.google.common.collect.ImmutableList; -import com.google.common.hash.Hashing; - -/** - * Partitioner for mapping map entries to individual database partitions. - * <p> - * By default a md5 hash of the hash key (key or map name) is used to pick a - * partition. - */ -public abstract class DatabasePartitioner implements Partitioner<String> { - // Database partitions sorted by their partition name. - protected final List<Database> partitions; - - public DatabasePartitioner(List<Database> partitions) { - checkState(partitions != null && !partitions.isEmpty(), "Partitions cannot be null or empty"); - this.partitions = ImmutableList.copyOf(partitions); - } - - protected int hash(String key) { - return Math.abs(Hashing.md5().newHasher().putBytes(key.getBytes(Charsets.UTF_8)).hash().asInt()); - } - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseProxy.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseProxy.java deleted file mode 100644 index 1d81f998..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseProxy.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import org.onosproject.store.service.Transaction; -import org.onosproject.store.service.Versioned; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; - -/** - * Database proxy. - */ -public interface DatabaseProxy<K, V> { - - /** - * Returns a set of all map names. - * - * @return A completable future to be completed with the result once complete. - */ - CompletableFuture<Set<String>> maps(); - - /** - * Returns a mapping from counter name to next value. - * - * @return A completable future to be completed with the result once complete. - */ - CompletableFuture<Map<String, Long>> counters(); - - /** - * Returns the number of entries in map. - * - * @param mapName map name - * @return A completable future to be completed with the result once complete. - */ - CompletableFuture<Integer> mapSize(String mapName); - - /** - * Checks whether the map is empty. - * - * @param mapName map name - * @return A completable future to be completed with the result once complete. - */ - CompletableFuture<Boolean> mapIsEmpty(String mapName); - - /** - * Checks whether the map contains a key. - * - * @param mapName map name - * @param key key to check. - * @return A completable future to be completed with the result once complete. - */ - CompletableFuture<Boolean> mapContainsKey(String mapName, K key); - - /** - * Checks whether the map contains a value. - * - * @param mapName map name - * @param value The value to check. - * @return A completable future to be completed with the result once complete. - */ - CompletableFuture<Boolean> mapContainsValue(String mapName, V value); - - /** - * Gets a value from the map. - * - * @param mapName map name - * @param key The key to get. - * @return A completable future to be completed with the result once complete. - */ - CompletableFuture<Versioned<V>> mapGet(String mapName, K key); - - /** - * Updates the map. - * - * @param mapName map name - * @param key The key to set - * @param valueMatch match for checking existing value - * @param versionMatch match for checking existing version - * @param value new value - * @return A completable future to be completed with the result once complete - */ - CompletableFuture<Result<UpdateResult<K, V>>> mapUpdate( - String mapName, K key, Match<V> valueMatch, Match<Long> versionMatch, V value); - - /** - * Clears the map. - * - * @param mapName map name - * @return A completable future to be completed with the result once complete. - */ - CompletableFuture<Result<Void>> mapClear(String mapName); - - /** - * Gets a set of keys in the map. - * - * @param mapName map name - * @return A completable future to be completed with the result once complete. - */ - CompletableFuture<Set<K>> mapKeySet(String mapName); - - /** - * Gets a collection of values in the map. - * - * @param mapName map name - * @return A completable future to be completed with the result once complete. - */ - CompletableFuture<Collection<Versioned<V>>> mapValues(String mapName); - - /** - * Gets a set of entries in the map. - * - * @param mapName map name - * @return A completable future to be completed with the result once complete. - */ - CompletableFuture<Set<Map.Entry<K, Versioned<V>>>> mapEntrySet(String mapName); - - /** - * Atomically add the given value to current value of the specified counter. - * - * @param counterName counter name - * @param delta value to add - * @return updated value - */ - CompletableFuture<Long> counterAddAndGet(String counterName, long delta); - - /** - * Atomically add the given value to current value of the specified counter. - * - * @param counterName counter name - * @param delta value to add - * @return previous value - */ - CompletableFuture<Long> counterGetAndAdd(String counterName, long delta); - - - /** - * Atomically sets the given value to current value of the specified counter. - * - * @param counterName counter name - * @param value value to set - * @return void future - */ - CompletableFuture<Void> counterSet(String counterName, long value); - - /** - * Atomically sets the given counter to the specified update value if and only if the current value is equal to the - * expected value. - * @param counterName counter name - * @param expectedValue value to use for equivalence check - * @param update value to set if expected value is current value - * @return true if an update occurred, false otherwise - */ - CompletableFuture<Boolean> counterCompareAndSet(String counterName, long expectedValue, long update); - - /** - * Returns the current value of the specified atomic counter. - * - * @param counterName counter name - * @return current value - */ - CompletableFuture<Long> counterGet(String counterName); - - /** - * Returns the size of queue. - * - * @param queueName queue name - * @return queue size - */ - CompletableFuture<Long> queueSize(String queueName); - - /** - * Inserts an entry into the queue. - * - * @param queueName queue name - * @param entry queue entry - * @return void future - */ - CompletableFuture<Void> queuePush(String queueName, byte[] entry); - - /** - * Removes an entry from the queue if the queue is non-empty. - * - * @param queueName queue name - * @return entry future. Can be completed with null if queue is empty - */ - CompletableFuture<byte[]> queuePop(String queueName); - - /** - * Returns but does not remove an entry from the queue. - * - * @param queueName queue name - * @return entry. Can be null if queue is empty - */ - CompletableFuture<byte[]> queuePeek(String queueName); - - /** - * Prepare and commit the specified transaction. - * - * @param transaction transaction to commit (after preparation) - * @return A completable future to be completed with the result once complete - */ - CompletableFuture<CommitResponse> prepareAndCommit(Transaction transaction); - - /** - * Prepare the specified transaction for commit. A successful prepare implies - * all the affected resources are locked thus ensuring no concurrent updates can interfere. - * - * @param transaction transaction to prepare (for commit) - * @return A completable future to be completed with the result once complete. The future is completed - * with true if the transaction is successfully prepared i.e. all pre-conditions are met and - * applicable resources locked. - */ - CompletableFuture<Boolean> prepare(Transaction transaction); - - /** - * Commit the specified transaction. A successful commit implies - * all the updates are applied, are now durable and are now visible externally. - * - * @param transaction transaction to commit - * @return A completable future to be completed with the result once complete - */ - CompletableFuture<CommitResponse> commit(Transaction transaction); - - /** - * Rollback the specified transaction. A successful rollback implies - * all previously acquired locks for the affected resources are released. - * - * @param transaction transaction to rollback - * @return A completable future to be completed with the result once complete - */ - CompletableFuture<Boolean> rollback(Transaction transaction); -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseSerializer.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseSerializer.java deleted file mode 100644 index de734144..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseSerializer.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import java.nio.ByteBuffer; - -import org.onlab.util.KryoNamespace; -import org.onosproject.cluster.NodeId; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.serializers.KryoSerializer; -import org.onosproject.store.service.DatabaseUpdate; -import org.onosproject.store.service.Transaction; -import org.onosproject.store.service.Versioned; - -import net.kuujo.copycat.cluster.internal.MemberInfo; -import net.kuujo.copycat.raft.protocol.AppendRequest; -import net.kuujo.copycat.raft.protocol.AppendResponse; -import net.kuujo.copycat.raft.protocol.CommitRequest; -import net.kuujo.copycat.raft.protocol.CommitResponse; -import net.kuujo.copycat.raft.protocol.PollRequest; -import net.kuujo.copycat.raft.protocol.PollResponse; -import net.kuujo.copycat.raft.protocol.QueryRequest; -import net.kuujo.copycat.raft.protocol.QueryResponse; -import net.kuujo.copycat.raft.protocol.ReplicaInfo; -import net.kuujo.copycat.raft.protocol.SyncRequest; -import net.kuujo.copycat.raft.protocol.SyncResponse; -import net.kuujo.copycat.raft.protocol.VoteRequest; -import net.kuujo.copycat.raft.protocol.VoteResponse; -import net.kuujo.copycat.util.serializer.SerializerConfig; - -/** - * Serializer for DatabaseManager's interaction with Copycat. - */ -public class DatabaseSerializer extends SerializerConfig { - - private static final KryoNamespace COPYCAT = KryoNamespace.newBuilder() - .nextId(KryoNamespace.FLOATING_ID) - .register(AppendRequest.class) - .register(AppendResponse.class) - .register(SyncRequest.class) - .register(SyncResponse.class) - .register(VoteRequest.class) - .register(VoteResponse.class) - .register(PollRequest.class) - .register(PollResponse.class) - .register(QueryRequest.class) - .register(QueryResponse.class) - .register(CommitRequest.class) - .register(CommitResponse.class) - .register(ReplicaInfo.class) - .register(MemberInfo.class) - .build(); - - private static final KryoNamespace ONOS_STORE = KryoNamespace.newBuilder() - .nextId(KryoNamespace.FLOATING_ID) - .register(Versioned.class) - .register(DatabaseUpdate.class) - .register(DatabaseUpdate.Type.class) - .register(Result.class) - .register(UpdateResult.class) - .register(Result.Status.class) - .register(DefaultTransaction.class) - .register(Transaction.State.class) - .register(org.onosproject.store.consistent.impl.CommitResponse.class) - .register(Match.class) - .register(NodeId.class) - .build(); - - private static final KryoSerializer SERIALIZER = new KryoSerializer() { - @Override - protected void setupKryoPool() { - serializerPool = KryoNamespace.newBuilder() - .register(KryoNamespaces.BASIC) - .register(COPYCAT) - .register(ONOS_STORE) - .build(); - } - }; - - @Override - public ByteBuffer writeObject(Object object) { - return ByteBuffer.wrap(SERIALIZER.encode(object)); - } - - @Override - public <T> T readObject(ByteBuffer buffer) { - return SERIALIZER.decode(buffer); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseState.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseState.java deleted file mode 100644 index 1136428b..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseState.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import net.kuujo.copycat.state.Command; -import net.kuujo.copycat.state.Initializer; -import net.kuujo.copycat.state.Query; -import net.kuujo.copycat.state.StateContext; -import org.onosproject.store.service.Transaction; -import org.onosproject.store.service.Versioned; - -import java.util.Collection; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * Database state. - * - */ -public interface DatabaseState<K, V> { - - /** - * Initializes the database state. - * - * @param context The map state context. - */ - @Initializer - void init(StateContext<DatabaseState<K, V>> context); - - @Query - Set<String> maps(); - - @Query - Map<String, Long> counters(); - - @Query - int mapSize(String mapName); - - @Query - boolean mapIsEmpty(String mapName); - - @Query - boolean mapContainsKey(String mapName, K key); - - @Query - boolean mapContainsValue(String mapName, V value); - - @Query - Versioned<V> mapGet(String mapName, K key); - - @Command - Result<UpdateResult<K, V>> mapUpdate(String mapName, K key, Match<V> valueMatch, Match<Long> versionMatch, V value); - - @Command - Result<Void> mapClear(String mapName); - - @Query - Set<K> mapKeySet(String mapName); - - @Query - Collection<Versioned<V>> mapValues(String mapName); - - @Query - Set<Entry<K, Versioned<V>>> mapEntrySet(String mapName); - - @Command - Long counterAddAndGet(String counterName, long delta); - - @Command - Boolean counterCompareAndSet(String counterName, long expectedValue, long updateValue); - - @Command - Long counterGetAndAdd(String counterName, long delta); - - @Query - Long queueSize(String queueName); - - @Query - byte[] queuePeek(String queueName); - - @Command - byte[] queuePop(String queueName); - - @Command - void queuePush(String queueName, byte[] entry); - - @Query - Long counterGet(String counterName); - - @Command - CommitResponse prepareAndCommit(Transaction transaction); - - @Command - boolean prepare(Transaction transaction); - - @Command - CommitResponse commit(Transaction transaction); - - @Command - boolean rollback(Transaction transaction); -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncAtomicCounter.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncAtomicCounter.java deleted file mode 100644 index d851eaa0..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncAtomicCounter.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import org.onosproject.store.service.AsyncAtomicCounter; - -import java.util.concurrent.CompletableFuture; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Default implementation for a distributed AsyncAtomicCounter backed by - * partitioned Raft DB. - * <p> - * The initial value will be zero. - */ -public class DefaultAsyncAtomicCounter implements AsyncAtomicCounter { - - private final String name; - private final Database database; - private final MeteringAgent monitor; - - private static final String PRIMITIVE_NAME = "atomicCounter"; - private static final String INCREMENT_AND_GET = "incrementAndGet"; - private static final String GET_AND_INCREMENT = "getAndIncrement"; - private static final String GET_AND_ADD = "getAndAdd"; - private static final String ADD_AND_GET = "addAndGet"; - private static final String GET = "get"; - private static final String SET = "set"; - private static final String COMPARE_AND_SET = "compareAndSet"; - - public DefaultAsyncAtomicCounter(String name, - Database database, - boolean meteringEnabled) { - this.name = checkNotNull(name); - this.database = checkNotNull(database); - this.monitor = new MeteringAgent(PRIMITIVE_NAME, name, meteringEnabled); - } - - @Override - public CompletableFuture<Long> incrementAndGet() { - final MeteringAgent.Context timer = monitor.startTimer(INCREMENT_AND_GET); - return addAndGet(1L) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Long> get() { - final MeteringAgent.Context timer = monitor.startTimer(GET); - return database.counterGet(name) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Long> getAndIncrement() { - final MeteringAgent.Context timer = monitor.startTimer(GET_AND_INCREMENT); - return getAndAdd(1L) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Long> getAndAdd(long delta) { - final MeteringAgent.Context timer = monitor.startTimer(GET_AND_ADD); - return database.counterGetAndAdd(name, delta) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Long> addAndGet(long delta) { - final MeteringAgent.Context timer = monitor.startTimer(ADD_AND_GET); - return database.counterAddAndGet(name, delta) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Void> set(long value) { - final MeteringAgent.Context timer = monitor.startTimer(SET); - return database.counterSet(name, value) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Boolean> compareAndSet(long expectedValue, long updateValue) { - final MeteringAgent.Context timer = monitor.startTimer(COMPARE_AND_SET); - return database.counterCompareAndSet(name, expectedValue, updateValue) - .whenComplete((r, e) -> timer.stop(e)); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMap.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMap.java deleted file mode 100644 index af2bb74d..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMap.java +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.Maps; - -import org.onlab.util.HexString; -import org.onlab.util.SharedExecutors; -import org.onlab.util.Tools; -import org.onosproject.core.ApplicationId; -import org.onosproject.store.service.AsyncConsistentMap; -import org.onosproject.store.service.ConsistentMapException; -import org.onosproject.store.service.MapEvent; -import org.onosproject.store.service.MapEventListener; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.Versioned; -import org.slf4j.Logger; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.onosproject.store.consistent.impl.StateMachineUpdate.Target.MAP_UPDATE; -import static org.onosproject.store.consistent.impl.StateMachineUpdate.Target.TX_COMMIT; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * AsyncConsistentMap implementation that is backed by a Raft consensus - * based database. - * - * @param <K> type of key. - * @param <V> type of value. - */ -public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V> { - - private final String name; - private final ApplicationId applicationId; - private final Database database; - private final Serializer serializer; - private final boolean readOnly; - private final boolean purgeOnUninstall; - - private static final String PRIMITIVE_NAME = "consistentMap"; - private static final String SIZE = "size"; - private static final String IS_EMPTY = "isEmpty"; - private static final String CONTAINS_KEY = "containsKey"; - private static final String CONTAINS_VALUE = "containsValue"; - private static final String GET = "get"; - private static final String COMPUTE_IF = "computeIf"; - private static final String PUT = "put"; - private static final String PUT_AND_GET = "putAndGet"; - private static final String PUT_IF_ABSENT = "putIfAbsent"; - private static final String REMOVE = "remove"; - private static final String CLEAR = "clear"; - private static final String KEY_SET = "keySet"; - private static final String VALUES = "values"; - private static final String ENTRY_SET = "entrySet"; - private static final String REPLACE = "replace"; - private static final String COMPUTE_IF_ABSENT = "computeIfAbsent"; - - private final Set<MapEventListener<K, V>> listeners = new CopyOnWriteArraySet<>(); - - private final Logger log = getLogger(getClass()); - private final MeteringAgent monitor; - - private static final String ERROR_NULL_KEY = "Key cannot be null"; - private static final String ERROR_NULL_VALUE = "Null values are not allowed"; - - // String representation of serialized byte[] -> original key Object - private final LoadingCache<String, K> keyCache = CacheBuilder.newBuilder() - .softValues() - .build(new CacheLoader<String, K>() { - - @Override - public K load(String key) { - return serializer.decode(HexString.fromHexString(key)); - } - }); - - protected String sK(K key) { - String s = HexString.toHexString(serializer.encode(key)); - keyCache.put(s, key); - return s; - } - - protected K dK(String key) { - return keyCache.getUnchecked(key); - } - - public DefaultAsyncConsistentMap(String name, - ApplicationId applicationId, - Database database, - Serializer serializer, - boolean readOnly, - boolean purgeOnUninstall, - boolean meteringEnabled) { - this.name = checkNotNull(name, "map name cannot be null"); - this.applicationId = applicationId; - this.database = checkNotNull(database, "database cannot be null"); - this.serializer = checkNotNull(serializer, "serializer cannot be null"); - this.readOnly = readOnly; - this.purgeOnUninstall = purgeOnUninstall; - this.database.registerConsumer(update -> { - SharedExecutors.getSingleThreadExecutor().execute(() -> { - if (listeners.isEmpty()) { - return; - } - try { - if (update.target() == MAP_UPDATE) { - Result<UpdateResult<String, byte[]>> result = update.output(); - if (result.success() && result.value().mapName().equals(name)) { - MapEvent<K, V> mapEvent = result.value() - .<K, V>map(this::dK, - v -> serializer.decode(Tools.copyOf(v))) - .toMapEvent(); - notifyListeners(mapEvent); - } - } else if (update.target() == TX_COMMIT) { - CommitResponse response = update.output(); - if (response.success()) { - response.updates().forEach(u -> { - if (u.mapName().equals(name)) { - MapEvent<K, V> mapEvent = - u.<K, V>map(this::dK, - v -> serializer.decode(Tools.copyOf(v))) - .toMapEvent(); - notifyListeners(mapEvent); - } - }); - } - } - } catch (Exception e) { - log.warn("Error notifying listeners", e); - } - }); - }); - this.monitor = new MeteringAgent(PRIMITIVE_NAME, name, meteringEnabled); - } - - /** - * Returns this map name. - * @return map name - */ - public String name() { - return name; - } - - /** - * Returns the serializer for map entries. - * @return map entry serializer - */ - public Serializer serializer() { - return serializer; - } - - /** - * Returns the applicationId owning this map. - * @return application Id - */ - public ApplicationId applicationId() { - return applicationId; - } - - /** - * Returns whether the map entries should be purged when the application - * owning it is uninstalled. - * @return true is map needs to cleared on app uninstall; false otherwise - */ - public boolean purgeOnUninstall() { - return purgeOnUninstall; - } - - @Override - public CompletableFuture<Integer> size() { - final MeteringAgent.Context timer = monitor.startTimer(SIZE); - return database.mapSize(name) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Boolean> isEmpty() { - final MeteringAgent.Context timer = monitor.startTimer(IS_EMPTY); - return database.mapIsEmpty(name) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Boolean> containsKey(K key) { - checkNotNull(key, ERROR_NULL_KEY); - final MeteringAgent.Context timer = monitor.startTimer(CONTAINS_KEY); - return database.mapContainsKey(name, sK(key)) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Boolean> containsValue(V value) { - checkNotNull(value, ERROR_NULL_VALUE); - final MeteringAgent.Context timer = monitor.startTimer(CONTAINS_VALUE); - return database.mapContainsValue(name, serializer.encode(value)) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Versioned<V>> get(K key) { - checkNotNull(key, ERROR_NULL_KEY); - final MeteringAgent.Context timer = monitor.startTimer(GET); - return database.mapGet(name, sK(key)) - .whenComplete((r, e) -> timer.stop(e)) - .thenApply(v -> v != null ? v.map(serializer::decode) : null); - } - - @Override - public CompletableFuture<Versioned<V>> computeIfAbsent(K key, - Function<? super K, ? extends V> mappingFunction) { - checkNotNull(key, ERROR_NULL_KEY); - checkNotNull(mappingFunction, "Mapping function cannot be null"); - final MeteringAgent.Context timer = monitor.startTimer(COMPUTE_IF_ABSENT); - return updateAndGet(key, Match.ifNull(), Match.any(), mappingFunction.apply(key)) - .whenComplete((r, e) -> timer.stop(e)) - .thenApply(v -> v.newValue()); - } - - @Override - public CompletableFuture<Versioned<V>> computeIfPresent(K key, - BiFunction<? super K, ? super V, ? extends V> remappingFunction) { - return computeIf(key, Objects::nonNull, remappingFunction); - } - - @Override - public CompletableFuture<Versioned<V>> compute(K key, - BiFunction<? super K, ? super V, ? extends V> remappingFunction) { - return computeIf(key, v -> true, remappingFunction); - } - - @Override - public CompletableFuture<Versioned<V>> computeIf(K key, - Predicate<? super V> condition, - BiFunction<? super K, ? super V, ? extends V> remappingFunction) { - checkNotNull(key, ERROR_NULL_KEY); - checkNotNull(condition, "predicate function cannot be null"); - checkNotNull(remappingFunction, "Remapping function cannot be null"); - final MeteringAgent.Context timer = monitor.startTimer(COMPUTE_IF); - return get(key).thenCompose(r1 -> { - V existingValue = r1 == null ? null : r1.value(); - // if the condition evaluates to false, return existing value. - if (!condition.test(existingValue)) { - return CompletableFuture.completedFuture(r1); - } - - AtomicReference<V> computedValue = new AtomicReference<>(); - // if remappingFunction throws an exception, return the exception. - try { - computedValue.set(remappingFunction.apply(key, existingValue)); - } catch (Exception e) { - return Tools.exceptionalFuture(e); - } - if (computedValue.get() == null && r1 == null) { - return CompletableFuture.completedFuture(null); - } - Match<V> valueMatcher = r1 == null ? Match.ifNull() : Match.any(); - Match<Long> versionMatcher = r1 == null ? Match.any() : Match.ifValue(r1.version()); - return updateAndGet(key, valueMatcher, versionMatcher, computedValue.get()) - .whenComplete((r, e) -> timer.stop(e)) - .thenApply(v -> { - if (v.updated()) { - return v.newValue(); - } else { - throw new ConsistentMapException.ConcurrentModification(); - } - }); - }); - } - - @Override - public CompletableFuture<Versioned<V>> put(K key, V value) { - checkNotNull(key, ERROR_NULL_KEY); - checkNotNull(value, ERROR_NULL_VALUE); - final MeteringAgent.Context timer = monitor.startTimer(PUT); - return updateAndGet(key, Match.any(), Match.any(), value).thenApply(v -> v.oldValue()) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Versioned<V>> putAndGet(K key, V value) { - checkNotNull(key, ERROR_NULL_KEY); - checkNotNull(value, ERROR_NULL_VALUE); - final MeteringAgent.Context timer = monitor.startTimer(PUT_AND_GET); - return updateAndGet(key, Match.any(), Match.any(), value).thenApply(v -> v.newValue()) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Versioned<V>> remove(K key) { - checkNotNull(key, ERROR_NULL_KEY); - final MeteringAgent.Context timer = monitor.startTimer(REMOVE); - return updateAndGet(key, Match.any(), Match.any(), null).thenApply(v -> v.oldValue()) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Void> clear() { - checkIfUnmodifiable(); - final MeteringAgent.Context timer = monitor.startTimer(CLEAR); - return database.mapClear(name).thenApply(this::unwrapResult) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Set<K>> keySet() { - final MeteringAgent.Context timer = monitor.startTimer(KEY_SET); - return database.mapKeySet(name) - .thenApply(s -> newMappingKeySet(s)) - .whenComplete((r, e) -> timer.stop(e)); - } - - @Override - public CompletableFuture<Collection<Versioned<V>>> values() { - final MeteringAgent.Context timer = monitor.startTimer(VALUES); - return database.mapValues(name) - .whenComplete((r, e) -> timer.stop(e)) - .thenApply(c -> c - .stream() - .map(v -> v.<V>map(serializer::decode)) - .collect(Collectors.toList())); - } - - @Override - public CompletableFuture<Set<Entry<K, Versioned<V>>>> entrySet() { - final MeteringAgent.Context timer = monitor.startTimer(ENTRY_SET); - return database.mapEntrySet(name) - .whenComplete((r, e) -> timer.stop(e)) - .thenApply(s -> newMappingEntrySet(s)); - } - - @Override - public CompletableFuture<Versioned<V>> putIfAbsent(K key, V value) { - checkNotNull(key, ERROR_NULL_KEY); - checkNotNull(value, ERROR_NULL_VALUE); - final MeteringAgent.Context timer = monitor.startTimer(PUT_IF_ABSENT); - return updateAndGet(key, Match.ifNull(), Match.any(), value) - .whenComplete((r, e) -> timer.stop(e)) - .thenApply(v -> v.oldValue()); - } - - @Override - public CompletableFuture<Boolean> remove(K key, V value) { - checkNotNull(key, ERROR_NULL_KEY); - checkNotNull(value, ERROR_NULL_VALUE); - final MeteringAgent.Context timer = monitor.startTimer(REMOVE); - return updateAndGet(key, Match.ifValue(value), Match.any(), null) - .whenComplete((r, e) -> timer.stop(e)) - .thenApply(v -> v.updated()); - } - - @Override - public CompletableFuture<Boolean> remove(K key, long version) { - checkNotNull(key, ERROR_NULL_KEY); - final MeteringAgent.Context timer = monitor.startTimer(REMOVE); - return updateAndGet(key, Match.any(), Match.ifValue(version), null) - .whenComplete((r, e) -> timer.stop(e)) - .thenApply(v -> v.updated()); - } - - @Override - public CompletableFuture<Boolean> replace(K key, V oldValue, V newValue) { - checkNotNull(key, ERROR_NULL_KEY); - checkNotNull(oldValue, ERROR_NULL_VALUE); - checkNotNull(newValue, ERROR_NULL_VALUE); - final MeteringAgent.Context timer = monitor.startTimer(REPLACE); - return updateAndGet(key, Match.ifValue(oldValue), Match.any(), newValue) - .whenComplete((r, e) -> timer.stop(e)) - .thenApply(v -> v.updated()); - } - - @Override - public CompletableFuture<Boolean> replace(K key, long oldVersion, V newValue) { - final MeteringAgent.Context timer = monitor.startTimer(REPLACE); - return updateAndGet(key, Match.any(), Match.ifValue(oldVersion), newValue) - .whenComplete((r, e) -> timer.stop(e)) - .thenApply(v -> v.updated()); - } - - /** - * Pre-update hook for performing required checks/actions before going forward with an update operation. - * @param key map key. - */ - protected void beforeUpdate(K key) { - checkIfUnmodifiable(); - } - - private Set<K> newMappingKeySet(Set<String> s) { - return new MappingSet<>(s, Collections::unmodifiableSet, - this::sK, this::dK); - } - - private Set<Entry<K, Versioned<V>>> newMappingEntrySet(Set<Entry<String, Versioned<byte[]>>> s) { - return new MappingSet<>(s, Collections::unmodifiableSet, - this::reverseMapRawEntry, this::mapRawEntry); - } - - private Map.Entry<K, Versioned<V>> mapRawEntry(Map.Entry<String, Versioned<byte[]>> e) { - return Maps.immutableEntry(dK(e.getKey()), e.getValue().<V>map(serializer::decode)); - } - - private Map.Entry<String, Versioned<byte[]>> reverseMapRawEntry(Map.Entry<K, Versioned<V>> e) { - return Maps.immutableEntry(sK(e.getKey()), e.getValue().map(serializer::encode)); - } - - private CompletableFuture<UpdateResult<K, V>> updateAndGet(K key, - Match<V> oldValueMatch, - Match<Long> oldVersionMatch, - V value) { - beforeUpdate(key); - return database.mapUpdate(name, - sK(key), - oldValueMatch.map(serializer::encode), - oldVersionMatch, - value == null ? null : serializer.encode(value)) - .thenApply(this::unwrapResult) - .thenApply(r -> r.<K, V>map(this::dK, serializer::decode)); - } - - private <T> T unwrapResult(Result<T> result) { - if (result.status() == Result.Status.LOCKED) { - throw new ConsistentMapException.ConcurrentModification(); - } else if (result.success()) { - return result.value(); - } else { - throw new IllegalStateException("Must not be here"); - } - } - - private void checkIfUnmodifiable() { - if (readOnly) { - throw new UnsupportedOperationException(); - } - } - - @Override - public void addListener(MapEventListener<K, V> listener) { - listeners.add(listener); - } - - @Override - public void removeListener(MapEventListener<K, V> listener) { - listeners.remove(listener); - } - - protected void notifyListeners(MapEvent<K, V> event) { - if (event == null) { - return; - } - listeners.forEach(listener -> { - try { - listener.event(event); - } catch (Exception e) { - log.warn("Failure notifying listener about {}", event, e); - } - }); - } - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAtomicCounter.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAtomicCounter.java deleted file mode 100644 index 2d6a956c..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAtomicCounter.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import org.onosproject.store.service.AsyncAtomicCounter; -import org.onosproject.store.service.AtomicCounter; -import org.onosproject.store.service.StorageException; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * Default implementation for a distributed AtomicCounter backed by - * partitioned Raft DB. - * <p> - * The initial value will be zero. - */ -public class DefaultAtomicCounter implements AtomicCounter { - - private static final int OPERATION_TIMEOUT_MILLIS = 5000; - - private final AsyncAtomicCounter asyncCounter; - - public DefaultAtomicCounter(String name, - Database database, - boolean meteringEnabled) { - asyncCounter = new DefaultAsyncAtomicCounter(name, database, meteringEnabled); - } - - @Override - public long incrementAndGet() { - return complete(asyncCounter.incrementAndGet()); - } - - @Override - public long getAndIncrement() { - return complete(asyncCounter.getAndIncrement()); - } - - @Override - public long getAndAdd(long delta) { - return complete(asyncCounter.getAndAdd(delta)); - } - - @Override - public long addAndGet(long delta) { - return complete(asyncCounter.getAndAdd(delta)); - } - - @Override - public void set(long value) { - complete(asyncCounter.set(value)); - } - - @Override - public boolean compareAndSet(long expectedValue, long updateValue) { - return complete(asyncCounter.compareAndSet(expectedValue, updateValue)); - } - - @Override - public long get() { - return complete(asyncCounter.get()); - } - - private static <T> T complete(CompletableFuture<T> future) { - try { - return future.get(OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new StorageException.Interrupted(); - } catch (TimeoutException e) { - throw new StorageException.Timeout(); - } catch (ExecutionException e) { - throw new StorageException(e.getCause()); - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAtomicCounterBuilder.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAtomicCounterBuilder.java deleted file mode 100644 index dba4443b..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAtomicCounterBuilder.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import org.onosproject.store.service.AsyncAtomicCounter; -import org.onosproject.store.service.AtomicCounter; -import org.onosproject.store.service.AtomicCounterBuilder; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; - -/** - * Default implementation of AtomicCounterBuilder. - */ -public class DefaultAtomicCounterBuilder implements AtomicCounterBuilder { - - private String name; - private boolean partitionsEnabled = true; - private final Database partitionedDatabase; - private final Database inMemoryDatabase; - private boolean metering = true; - - public DefaultAtomicCounterBuilder(Database inMemoryDatabase, Database partitionedDatabase) { - this.inMemoryDatabase = inMemoryDatabase; - this.partitionedDatabase = partitionedDatabase; - } - - @Override - public AtomicCounterBuilder withName(String name) { - checkArgument(name != null && !name.isEmpty()); - this.name = name; - return this; - } - - @Override - public AtomicCounterBuilder withPartitionsDisabled() { - partitionsEnabled = false; - return this; - } - - @Override - public AtomicCounter build() { - validateInputs(); - Database database = partitionsEnabled ? partitionedDatabase : inMemoryDatabase; - return new DefaultAtomicCounter(name, database, metering); - } - - @Override - public AsyncAtomicCounter buildAsyncCounter() { - validateInputs(); - Database database = partitionsEnabled ? partitionedDatabase : inMemoryDatabase; - return new DefaultAsyncAtomicCounter(name, database, metering); - } - - @Override - public AtomicCounterBuilder withMeteringDisabled() { - metering = false; - return this; - } - - private void validateInputs() { - checkState(name != null, "name must be specified"); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAtomicValue.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAtomicValue.java deleted file mode 100644 index e8c93f31..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAtomicValue.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import org.onosproject.store.service.AtomicValue; -import org.onosproject.store.service.AtomicValueEvent; -import org.onosproject.store.service.AtomicValueEventListener; -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.MapEvent; -import org.onosproject.store.service.MapEventListener; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.Versioned; - -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; - -/** - * Default implementation of AtomicValue. - * - * @param <V> value type - */ -public class DefaultAtomicValue<V> implements AtomicValue<V> { - - private final Set<AtomicValueEventListener<V>> listeners = new CopyOnWriteArraySet<>(); - private final ConsistentMap<String, byte[]> valueMap; - private final String name; - private final Serializer serializer; - private final MapEventListener<String, byte[]> mapEventListener = new InternalMapEventListener(); - private final MeteringAgent monitor; - - private static final String COMPONENT_NAME = "atomicValue"; - private static final String GET = "get"; - private static final String GET_AND_SET = "getAndSet"; - private static final String COMPARE_AND_SET = "compareAndSet"; - - public DefaultAtomicValue(ConsistentMap<String, byte[]> valueMap, - String name, - boolean meteringEnabled, - Serializer serializer) { - this.valueMap = valueMap; - this.name = name; - this.serializer = serializer; - this.monitor = new MeteringAgent(COMPONENT_NAME, name, meteringEnabled); - } - - @Override - public boolean compareAndSet(V expect, V update) { - final MeteringAgent.Context newTimer = monitor.startTimer(COMPARE_AND_SET); - try { - if (expect == null) { - if (update == null) { - return true; - } - return valueMap.putIfAbsent(name, serializer.encode(update)) == null; - } else { - if (update == null) { - return valueMap.remove(name, serializer.encode(expect)); - } - return valueMap.replace(name, serializer.encode(expect), serializer.encode(update)); - } - } finally { - newTimer.stop(null); - } - } - - @Override - public V get() { - final MeteringAgent.Context newTimer = monitor.startTimer(GET); - try { - Versioned<byte[]> rawValue = valueMap.get(name); - return rawValue == null ? null : serializer.decode(rawValue.value()); - } finally { - newTimer.stop(null); - } - } - - @Override - public V getAndSet(V value) { - final MeteringAgent.Context newTimer = monitor.startTimer(GET_AND_SET); - try { - Versioned<byte[]> previousValue = value == null ? - valueMap.remove(name) : valueMap.put(name, serializer.encode(value)); - return previousValue == null ? null : serializer.decode(previousValue.value()); - } finally { - newTimer.stop(null); - } - } - - @Override - public void set(V value) { - getAndSet(value); - } - - @Override - public void addListener(AtomicValueEventListener<V> listener) { - synchronized (listeners) { - if (listeners.add(listener)) { - if (listeners.size() == 1) { - valueMap.addListener(mapEventListener); - } - } - } - } - - @Override - public void removeListener(AtomicValueEventListener<V> listener) { - synchronized (listeners) { - if (listeners.remove(listener)) { - if (listeners.size() == 0) { - valueMap.removeListener(mapEventListener); - } - } - } - } - - private class InternalMapEventListener implements MapEventListener<String, byte[]> { - - @Override - public void event(MapEvent<String, byte[]> mapEvent) { - V newValue = mapEvent.type() == MapEvent.Type.REMOVE ? null : serializer.decode(mapEvent.value().value()); - AtomicValueEvent<V> atomicValueEvent = new AtomicValueEvent<>(name, AtomicValueEvent.Type.UPDATE, newValue); - listeners.forEach(l -> l.event(atomicValueEvent)); - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAtomicValueBuilder.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAtomicValueBuilder.java deleted file mode 100644 index b39004b3..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAtomicValueBuilder.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.AtomicValue; -import org.onosproject.store.service.AtomicValueBuilder; -import org.onosproject.store.service.ConsistentMapBuilder; -import org.onosproject.store.service.Serializer; - -/** - * Default implementation of AtomicValueBuilder. - * - * @param <V> value type - */ -public class DefaultAtomicValueBuilder<V> implements AtomicValueBuilder<V> { - - private Serializer serializer; - private String name; - private ConsistentMapBuilder<String, byte[]> mapBuilder; - private boolean metering = true; - - public DefaultAtomicValueBuilder(DatabaseManager manager) { - mapBuilder = manager.<String, byte[]>consistentMapBuilder() - .withName("onos-atomic-values") - .withMeteringDisabled() - .withSerializer(Serializer.using(KryoNamespaces.BASIC)); - } - - @Override - public AtomicValueBuilder<V> withName(String name) { - this.name = name; - return this; - } - - @Override - public AtomicValueBuilder<V> withSerializer(Serializer serializer) { - this.serializer = serializer; - return this; - } - - @Override - public AtomicValueBuilder<V> withPartitionsDisabled() { - mapBuilder.withPartitionsDisabled(); - return this; - } - - @Override - public AtomicValueBuilder<V> withMeteringDisabled() { - metering = false; - return this; - } - - @Override - public AtomicValue<V> build() { - return new DefaultAtomicValue<>(mapBuilder.build(), name, metering, serializer); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultConsistentMap.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultConsistentMap.java deleted file mode 100644 index 6f7b5487..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultConsistentMap.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import java.util.Collection; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.Set; - -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.ConsistentMapException; -import org.onosproject.store.service.MapEventListener; -import org.onosproject.store.service.Versioned; - -/** - * ConsistentMap implementation that is backed by a Raft consensus - * based database. - * - * @param <K> type of key. - * @param <V> type of value. - */ -public class DefaultConsistentMap<K, V> implements ConsistentMap<K, V> { - - private static final int OPERATION_TIMEOUT_MILLIS = 5000; - - private final DefaultAsyncConsistentMap<K, V> asyncMap; - private Map<K, V> javaMap; - - public String name() { - return asyncMap.name(); - } - - public DefaultConsistentMap(DefaultAsyncConsistentMap<K, V> asyncMap) { - this.asyncMap = asyncMap; - } - - @Override - public int size() { - return complete(asyncMap.size()); - } - - @Override - public boolean isEmpty() { - return complete(asyncMap.isEmpty()); - } - - @Override - public boolean containsKey(K key) { - return complete(asyncMap.containsKey(key)); - } - - @Override - public boolean containsValue(V value) { - return complete(asyncMap.containsValue(value)); - } - - @Override - public Versioned<V> get(K key) { - return complete(asyncMap.get(key)); - } - - @Override - public Versioned<V> computeIfAbsent(K key, - Function<? super K, ? extends V> mappingFunction) { - return complete(asyncMap.computeIfAbsent(key, mappingFunction)); - } - - @Override - public Versioned<V> computeIfPresent(K key, - BiFunction<? super K, ? super V, ? extends V> remappingFunction) { - return complete(asyncMap.computeIfPresent(key, remappingFunction)); - } - - @Override - public Versioned<V> compute(K key, - BiFunction<? super K, ? super V, ? extends V> remappingFunction) { - return complete(asyncMap.compute(key, remappingFunction)); - } - - @Override - public Versioned<V> computeIf(K key, - Predicate<? super V> condition, - BiFunction<? super K, ? super V, ? extends V> remappingFunction) { - return complete(asyncMap.computeIf(key, condition, remappingFunction)); - } - - @Override - public Versioned<V> put(K key, V value) { - return complete(asyncMap.put(key, value)); - } - - @Override - public Versioned<V> putAndGet(K key, V value) { - return complete(asyncMap.putAndGet(key, value)); - } - - @Override - public Versioned<V> remove(K key) { - return complete(asyncMap.remove(key)); - } - - @Override - public void clear() { - complete(asyncMap.clear()); - } - - @Override - public Set<K> keySet() { - return complete(asyncMap.keySet()); - } - - @Override - public Collection<Versioned<V>> values() { - return complete(asyncMap.values()); - } - - @Override - public Set<Entry<K, Versioned<V>>> entrySet() { - return complete(asyncMap.entrySet()); - } - - @Override - public Versioned<V> putIfAbsent(K key, V value) { - return complete(asyncMap.putIfAbsent(key, value)); - } - - @Override - public boolean remove(K key, V value) { - return complete(asyncMap.remove(key, value)); - } - - @Override - public boolean remove(K key, long version) { - return complete(asyncMap.remove(key, version)); - } - - @Override - public boolean replace(K key, V oldValue, V newValue) { - return complete(asyncMap.replace(key, oldValue, newValue)); - } - - @Override - public boolean replace(K key, long oldVersion, V newValue) { - return complete(asyncMap.replace(key, oldVersion, newValue)); - } - - private static <T> T complete(CompletableFuture<T> future) { - try { - return future.get(OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ConsistentMapException.Interrupted(); - } catch (TimeoutException e) { - throw new ConsistentMapException.Timeout(); - } catch (ExecutionException e) { - if (e.getCause() instanceof ConsistentMapException) { - throw (ConsistentMapException) e.getCause(); - } else { - throw new ConsistentMapException(e.getCause()); - } - } - } - - @Override - public void addListener(MapEventListener<K, V> listener) { - asyncMap.addListener(listener); - } - - @Override - public void removeListener(MapEventListener<K, V> listener) { - asyncMap.addListener(listener); - } - - @Override - public Map<K, V> asJavaMap() { - synchronized (this) { - if (javaMap == null) { - javaMap = new ConsistentMapBackedJavaMap<>(this); - } - } - return javaMap; - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultConsistentMapBuilder.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultConsistentMapBuilder.java deleted file mode 100644 index 0e11794e..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultConsistentMapBuilder.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import org.onosproject.core.ApplicationId; -import org.onosproject.store.service.AsyncConsistentMap; -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.ConsistentMapBuilder; -import org.onosproject.store.service.Serializer; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; - -/** - * Default Consistent Map builder. - * - * @param <K> type for map key - * @param <V> type for map value - */ -public class DefaultConsistentMapBuilder<K, V> implements ConsistentMapBuilder<K, V> { - - private Serializer serializer; - private String name; - private ApplicationId applicationId; - private boolean purgeOnUninstall = false; - private boolean partitionsEnabled = true; - private boolean readOnly = false; - private boolean metering = true; - private boolean relaxedReadConsistency = false; - private final DatabaseManager manager; - - public DefaultConsistentMapBuilder(DatabaseManager manager) { - this.manager = manager; - } - - @Override - public ConsistentMapBuilder<K, V> withName(String name) { - checkArgument(name != null && !name.isEmpty()); - this.name = name; - return this; - } - - @Override - public ConsistentMapBuilder<K, V> withApplicationId(ApplicationId id) { - checkArgument(id != null); - this.applicationId = id; - return this; - } - - @Override - public ConsistentMapBuilder<K, V> withPurgeOnUninstall() { - purgeOnUninstall = true; - return this; - } - - @Override - public ConsistentMapBuilder<K, V> withMeteringDisabled() { - metering = false; - return this; - } - - @Override - public ConsistentMapBuilder<K, V> withSerializer(Serializer serializer) { - checkArgument(serializer != null); - this.serializer = serializer; - return this; - } - - @Override - public ConsistentMapBuilder<K, V> withPartitionsDisabled() { - partitionsEnabled = false; - return this; - } - - @Override - public ConsistentMapBuilder<K, V> withUpdatesDisabled() { - readOnly = true; - return this; - } - - @Override - public ConsistentMapBuilder<K, V> withRelaxedReadConsistency() { - relaxedReadConsistency = true; - return this; - } - - private void validateInputs() { - checkState(name != null, "name must be specified"); - checkState(serializer != null, "serializer must be specified"); - if (purgeOnUninstall) { - checkState(applicationId != null, "ApplicationId must be specified when purgeOnUninstall is enabled"); - } - } - - @Override - public ConsistentMap<K, V> build() { - return new DefaultConsistentMap<>(buildAndRegisterMap()); - } - - @Override - public AsyncConsistentMap<K, V> buildAsyncMap() { - return buildAndRegisterMap(); - } - - private DefaultAsyncConsistentMap<K, V> buildAndRegisterMap() { - validateInputs(); - Database database = partitionsEnabled ? manager.partitionedDatabase : manager.inMemoryDatabase; - if (relaxedReadConsistency) { - return manager.registerMap( - new AsyncCachingConsistentMap<>(name, - applicationId, - database, - serializer, - readOnly, - purgeOnUninstall, - metering)); - } else { - return manager.registerMap( - new DefaultAsyncConsistentMap<>(name, - applicationId, - database, - serializer, - readOnly, - purgeOnUninstall, - metering)); - } - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDatabase.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDatabase.java deleted file mode 100644 index 2a50fbd6..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDatabase.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import com.google.common.collect.Sets; -import net.kuujo.copycat.resource.internal.AbstractResource; -import net.kuujo.copycat.resource.internal.ResourceManager; -import net.kuujo.copycat.state.StateMachine; -import net.kuujo.copycat.state.internal.DefaultStateMachine; -import net.kuujo.copycat.util.concurrent.Futures; -import net.kuujo.copycat.util.function.TriConsumer; -import org.onosproject.store.service.Transaction; -import org.onosproject.store.service.Versioned; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; -import java.util.function.Supplier; - -/** - * Default database. - */ -public class DefaultDatabase extends AbstractResource<Database> implements Database { - private final StateMachine<DatabaseState<String, byte[]>> stateMachine; - private DatabaseProxy<String, byte[]> proxy; - private final Set<Consumer<StateMachineUpdate>> consumers = Sets.newCopyOnWriteArraySet(); - private final TriConsumer<String, Object, Object> watcher = new InternalStateMachineWatcher(); - - @SuppressWarnings({"unchecked", "rawtypes"}) - public DefaultDatabase(ResourceManager context) { - super(context); - this.stateMachine = new DefaultStateMachine(context, - DatabaseState.class, - DefaultDatabaseState.class, - DefaultDatabase.class.getClassLoader()); - this.stateMachine.addStartupTask(() -> { - stateMachine.registerWatcher(watcher); - return CompletableFuture.completedFuture(null); - }); - this.stateMachine.addShutdownTask(() -> { - stateMachine.unregisterWatcher(watcher); - return CompletableFuture.completedFuture(null); - }); - } - - /** - * If the database is closed, returning a failed CompletableFuture. Otherwise, calls the given supplier to - * return the completed future result. - * - * @param supplier The supplier to call if the database is open. - * @param <T> The future result type. - * @return A completable future that if this database is closed is immediately failed. - */ - protected <T> CompletableFuture<T> checkOpen(Supplier<CompletableFuture<T>> supplier) { - if (proxy == null) { - return Futures.exceptionalFuture(new IllegalStateException("Database closed")); - } - return supplier.get(); - } - - @Override - public CompletableFuture<Set<String>> maps() { - return checkOpen(() -> proxy.maps()); - } - - @Override - public CompletableFuture<Map<String, Long>> counters() { - return checkOpen(() -> proxy.counters()); - } - - @Override - public CompletableFuture<Integer> mapSize(String mapName) { - return checkOpen(() -> proxy.mapSize(mapName)); - } - - @Override - public CompletableFuture<Boolean> mapIsEmpty(String mapName) { - return checkOpen(() -> proxy.mapIsEmpty(mapName)); - } - - @Override - public CompletableFuture<Boolean> mapContainsKey(String mapName, String key) { - return checkOpen(() -> proxy.mapContainsKey(mapName, key)); - } - - @Override - public CompletableFuture<Boolean> mapContainsValue(String mapName, byte[] value) { - return checkOpen(() -> proxy.mapContainsValue(mapName, value)); - } - - @Override - public CompletableFuture<Versioned<byte[]>> mapGet(String mapName, String key) { - return checkOpen(() -> proxy.mapGet(mapName, key)); - } - - @Override - public CompletableFuture<Result<UpdateResult<String, byte[]>>> mapUpdate( - String mapName, String key, Match<byte[]> valueMatch, Match<Long> versionMatch, byte[] value) { - return checkOpen(() -> proxy.mapUpdate(mapName, key, valueMatch, versionMatch, value)); - } - - @Override - public CompletableFuture<Result<Void>> mapClear(String mapName) { - return checkOpen(() -> proxy.mapClear(mapName)); - } - - @Override - public CompletableFuture<Set<String>> mapKeySet(String mapName) { - return checkOpen(() -> proxy.mapKeySet(mapName)); - } - - @Override - public CompletableFuture<Collection<Versioned<byte[]>>> mapValues(String mapName) { - return checkOpen(() -> proxy.mapValues(mapName)); - } - - @Override - public CompletableFuture<Set<Map.Entry<String, Versioned<byte[]>>>> mapEntrySet(String mapName) { - return checkOpen(() -> proxy.mapEntrySet(mapName)); - } - - @Override - public CompletableFuture<Long> counterGet(String counterName) { - return checkOpen(() -> proxy.counterGet(counterName)); - } - - @Override - public CompletableFuture<Long> counterAddAndGet(String counterName, long delta) { - return checkOpen(() -> proxy.counterAddAndGet(counterName, delta)); - } - - @Override - public CompletableFuture<Long> counterGetAndAdd(String counterName, long delta) { - return checkOpen(() -> proxy.counterGetAndAdd(counterName, delta)); - } - - @Override - public CompletableFuture<Void> counterSet(String counterName, long value) { - return checkOpen(() -> proxy.counterSet(counterName, value)); - } - - @Override - public CompletableFuture<Boolean> counterCompareAndSet(String counterName, long expectedValue, long update) { - return checkOpen(() -> proxy.counterCompareAndSet(counterName, expectedValue, update)); - } - - @Override - public CompletableFuture<Long> queueSize(String queueName) { - return checkOpen(() -> proxy.queueSize(queueName)); - } - - @Override - public CompletableFuture<Void> queuePush(String queueName, byte[] entry) { - return checkOpen(() -> proxy.queuePush(queueName, entry)); - } - - @Override - public CompletableFuture<byte[]> queuePop(String queueName) { - return checkOpen(() -> proxy.queuePop(queueName)); - } - - @Override - public CompletableFuture<byte[]> queuePeek(String queueName) { - return checkOpen(() -> proxy.queuePeek(queueName)); - } - - @Override - public CompletableFuture<CommitResponse> prepareAndCommit(Transaction transaction) { - return checkOpen(() -> proxy.prepareAndCommit(transaction)); - } - - @Override - public CompletableFuture<Boolean> prepare(Transaction transaction) { - return checkOpen(() -> proxy.prepare(transaction)); - } - - @Override - public CompletableFuture<CommitResponse> commit(Transaction transaction) { - return checkOpen(() -> proxy.commit(transaction)); - } - - @Override - public CompletableFuture<Boolean> rollback(Transaction transaction) { - return checkOpen(() -> proxy.rollback(transaction)); - } - - @Override - @SuppressWarnings("unchecked") - public synchronized CompletableFuture<Database> open() { - return runStartupTasks() - .thenCompose(v -> stateMachine.open()) - .thenRun(() -> { - this.proxy = stateMachine.createProxy(DatabaseProxy.class, this.getClass().getClassLoader()); - }) - .thenApply(v -> null); - } - - @Override - public synchronized CompletableFuture<Void> close() { - proxy = null; - return stateMachine.close() - .thenCompose(v -> runShutdownTasks()); - } - - @Override - public int hashCode() { - return name().hashCode(); - } - - @Override - public boolean equals(Object other) { - if (other instanceof Database) { - return name().equals(((Database) other).name()); - } - return false; - } - - @Override - public void registerConsumer(Consumer<StateMachineUpdate> consumer) { - consumers.add(consumer); - } - - @Override - public void unregisterConsumer(Consumer<StateMachineUpdate> consumer) { - consumers.remove(consumer); - } - - private class InternalStateMachineWatcher implements TriConsumer<String, Object, Object> { - @Override - public void accept(String name, Object input, Object output) { - StateMachineUpdate update = new StateMachineUpdate(name, input, output); - consumers.forEach(consumer -> consumer.accept(update)); - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDatabaseState.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDatabaseState.java deleted file mode 100644 index 8943fc87..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDatabaseState.java +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import com.google.common.base.Objects; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import net.kuujo.copycat.state.Initializer; -import net.kuujo.copycat.state.StateContext; -import org.onosproject.store.service.DatabaseUpdate; -import org.onosproject.store.service.Transaction; -import org.onosproject.store.service.Versioned; - -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedList; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.atomic.AtomicLong; -import java.util.stream.Collectors; - -/** - * Default database state. - */ -public class DefaultDatabaseState implements DatabaseState<String, byte[]> { - private Long nextVersion; - private Map<String, AtomicLong> counters; - private Map<String, Map<String, Versioned<byte[]>>> maps; - private Map<String, Queue<byte[]>> queues; - - /** - * This locks map has a structure similar to the "tables" map above and - * holds all the provisional updates made during a transaction's prepare phase. - * The entry value is represented as the tuple: (transactionId, newValue) - * If newValue == null that signifies this update is attempting to - * delete the existing value. - * This map also serves as a lock on the entries that are being updated. - * The presence of a entry in this map indicates that element is - * participating in a transaction and is currently locked for updates. - */ - private Map<String, Map<String, Update>> locks; - - @Initializer - @Override - public void init(StateContext<DatabaseState<String, byte[]>> context) { - counters = context.get("counters"); - if (counters == null) { - counters = Maps.newConcurrentMap(); - context.put("counters", counters); - } - maps = context.get("maps"); - if (maps == null) { - maps = Maps.newConcurrentMap(); - context.put("maps", maps); - } - locks = context.get("locks"); - if (locks == null) { - locks = Maps.newConcurrentMap(); - context.put("locks", locks); - } - queues = context.get("queues"); - if (queues == null) { - queues = Maps.newConcurrentMap(); - context.put("queues", queues); - } - nextVersion = context.get("nextVersion"); - if (nextVersion == null) { - nextVersion = 0L; - context.put("nextVersion", nextVersion); - } - } - - @Override - public Set<String> maps() { - return ImmutableSet.copyOf(maps.keySet()); - } - - @Override - public Map<String, Long> counters() { - Map<String, Long> counterMap = Maps.newHashMap(); - counters.forEach((k, v) -> counterMap.put(k, v.get())); - return counterMap; - } - - @Override - public int mapSize(String mapName) { - return getMap(mapName).size(); - } - - @Override - public boolean mapIsEmpty(String mapName) { - return getMap(mapName).isEmpty(); - } - - @Override - public boolean mapContainsKey(String mapName, String key) { - return getMap(mapName).containsKey(key); - } - - @Override - public boolean mapContainsValue(String mapName, byte[] value) { - return getMap(mapName).values().stream().anyMatch(v -> Arrays.equals(v.value(), value)); - } - - @Override - public Versioned<byte[]> mapGet(String mapName, String key) { - return getMap(mapName).get(key); - } - - - @Override - public Result<UpdateResult<String, byte[]>> mapUpdate( - String mapName, - String key, - Match<byte[]> valueMatch, - Match<Long> versionMatch, - byte[] value) { - if (isLockedForUpdates(mapName, key)) { - return Result.locked(); - } - Versioned<byte[]> currentValue = getMap(mapName).get(key); - if (!valueMatch.matches(currentValue == null ? null : currentValue.value()) || - !versionMatch.matches(currentValue == null ? null : currentValue.version())) { - return Result.ok(new UpdateResult<>(false, mapName, key, currentValue, currentValue)); - } else { - if (value == null) { - if (currentValue == null) { - return Result.ok(new UpdateResult<>(false, mapName, key, null, null)); - } else { - getMap(mapName).remove(key); - return Result.ok(new UpdateResult<>(true, mapName, key, currentValue, null)); - } - } - Versioned<byte[]> newValue = new Versioned<>(value, ++nextVersion); - getMap(mapName).put(key, newValue); - return Result.ok(new UpdateResult<>(true, mapName, key, currentValue, newValue)); - } - } - - @Override - public Result<Void> mapClear(String mapName) { - if (areTransactionsInProgress(mapName)) { - return Result.locked(); - } - getMap(mapName).clear(); - return Result.ok(null); - } - - @Override - public Set<String> mapKeySet(String mapName) { - return ImmutableSet.copyOf(getMap(mapName).keySet()); - } - - @Override - public Collection<Versioned<byte[]>> mapValues(String mapName) { - return ImmutableList.copyOf(getMap(mapName).values()); - } - - @Override - public Set<Entry<String, Versioned<byte[]>>> mapEntrySet(String mapName) { - return ImmutableSet.copyOf(getMap(mapName) - .entrySet() - .stream() - .map(entry -> Maps.immutableEntry(entry.getKey(), entry.getValue())) - .collect(Collectors.toSet())); - } - - @Override - public Long counterAddAndGet(String counterName, long delta) { - return getCounter(counterName).addAndGet(delta); - } - - @Override - public Long counterGetAndAdd(String counterName, long delta) { - return getCounter(counterName).getAndAdd(delta); - } - - @Override - public Boolean counterCompareAndSet(String counterName, long expectedValue, long updateValue) { - return getCounter(counterName).compareAndSet(expectedValue, updateValue); - } - - @Override - public Long counterGet(String counterName) { - return getCounter(counterName).get(); - } - - @Override - public Long queueSize(String queueName) { - return Long.valueOf(getQueue(queueName).size()); - } - - @Override - public byte[] queuePeek(String queueName) { - return getQueue(queueName).peek(); - } - - @Override - public byte[] queuePop(String queueName) { - return getQueue(queueName).poll(); - } - - @Override - public void queuePush(String queueName, byte[] entry) { - getQueue(queueName).offer(entry); - } - - @Override - public CommitResponse prepareAndCommit(Transaction transaction) { - if (prepare(transaction)) { - return commit(transaction); - } - return CommitResponse.failure(); - } - - @Override - public boolean prepare(Transaction transaction) { - if (transaction.updates().stream().anyMatch(update -> - isLockedByAnotherTransaction(update.mapName(), - update.key(), - transaction.id()))) { - return false; - } - - if (transaction.updates().stream().allMatch(this::isUpdatePossible)) { - transaction.updates().forEach(update -> doProvisionalUpdate(update, transaction.id())); - return true; - } - return false; - } - - @Override - public CommitResponse commit(Transaction transaction) { - return CommitResponse.success(Lists.transform(transaction.updates(), - update -> commitProvisionalUpdate(update, transaction.id()))); - } - - @Override - public boolean rollback(Transaction transaction) { - transaction.updates().forEach(update -> undoProvisionalUpdate(update, transaction.id())); - return true; - } - - private Map<String, Versioned<byte[]>> getMap(String mapName) { - return maps.computeIfAbsent(mapName, name -> Maps.newConcurrentMap()); - } - - private Map<String, Update> getLockMap(String mapName) { - return locks.computeIfAbsent(mapName, name -> Maps.newConcurrentMap()); - } - - private AtomicLong getCounter(String counterName) { - return counters.computeIfAbsent(counterName, name -> new AtomicLong(0)); - } - - private Queue<byte[]> getQueue(String queueName) { - return queues.computeIfAbsent(queueName, name -> new LinkedList<>()); - } - - private boolean isUpdatePossible(DatabaseUpdate update) { - Versioned<byte[]> existingEntry = mapGet(update.mapName(), update.key()); - switch (update.type()) { - case PUT: - case REMOVE: - return true; - case PUT_IF_ABSENT: - return existingEntry == null; - case PUT_IF_VERSION_MATCH: - return existingEntry != null && existingEntry.version() == update.currentVersion(); - case PUT_IF_VALUE_MATCH: - return existingEntry != null && Arrays.equals(existingEntry.value(), update.currentValue()); - case REMOVE_IF_VERSION_MATCH: - return existingEntry == null || existingEntry.version() == update.currentVersion(); - case REMOVE_IF_VALUE_MATCH: - return existingEntry == null || Arrays.equals(existingEntry.value(), update.currentValue()); - default: - throw new IllegalStateException("Unsupported type: " + update.type()); - } - } - - private void doProvisionalUpdate(DatabaseUpdate update, long transactionId) { - Map<String, Update> lockMap = getLockMap(update.mapName()); - switch (update.type()) { - case PUT: - case PUT_IF_ABSENT: - case PUT_IF_VERSION_MATCH: - case PUT_IF_VALUE_MATCH: - lockMap.put(update.key(), new Update(transactionId, update.value())); - break; - case REMOVE: - case REMOVE_IF_VERSION_MATCH: - case REMOVE_IF_VALUE_MATCH: - lockMap.put(update.key(), new Update(transactionId, null)); - break; - default: - throw new IllegalStateException("Unsupported type: " + update.type()); - } - } - - private UpdateResult<String, byte[]> commitProvisionalUpdate(DatabaseUpdate update, long transactionId) { - String mapName = update.mapName(); - String key = update.key(); - Update provisionalUpdate = getLockMap(mapName).get(key); - if (Objects.equal(transactionId, provisionalUpdate.transactionId())) { - getLockMap(mapName).remove(key); - } else { - throw new IllegalStateException("Invalid transaction Id"); - } - return mapUpdate(mapName, key, Match.any(), Match.any(), provisionalUpdate.value()).value(); - } - - private void undoProvisionalUpdate(DatabaseUpdate update, long transactionId) { - String mapName = update.mapName(); - String key = update.key(); - Update provisionalUpdate = getLockMap(mapName).get(key); - if (provisionalUpdate == null) { - return; - } - if (Objects.equal(transactionId, provisionalUpdate.transactionId())) { - getLockMap(mapName).remove(key); - } - } - - private boolean isLockedByAnotherTransaction(String mapName, String key, long transactionId) { - Update update = getLockMap(mapName).get(key); - return update != null && !Objects.equal(transactionId, update.transactionId()); - } - - private boolean isLockedForUpdates(String mapName, String key) { - return getLockMap(mapName).containsKey(key); - } - - private boolean areTransactionsInProgress(String mapName) { - return !getLockMap(mapName).isEmpty(); - } - - private class Update { - private final long transactionId; - private final byte[] value; - - public Update(long txId, byte[] value) { - this.transactionId = txId; - this.value = value; - } - - public long transactionId() { - return this.transactionId; - } - - public byte[] value() { - return this.value; - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDistributedQueue.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDistributedQueue.java deleted file mode 100644 index 5f69fde8..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDistributedQueue.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import com.google.common.collect.Sets; -import com.google.common.util.concurrent.Futures; - -import org.onlab.util.SharedExecutors; -import org.onosproject.store.service.DistributedQueue; -import org.onosproject.store.service.Serializer; - -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import static com.google.common.base.Preconditions.checkNotNull; -import static org.onosproject.store.consistent.impl.StateMachineUpdate.Target.QUEUE_PUSH; - -/** - * DistributedQueue implementation that provides FIFO ordering semantics. - * - * @param <E> queue entry type - */ -public class DefaultDistributedQueue<E> implements DistributedQueue<E> { - - private final String name; - private final Database database; - private final Serializer serializer; - private final Set<CompletableFuture<E>> pendingFutures = Sets.newIdentityHashSet(); - - private static final String PRIMITIVE_NAME = "distributedQueue"; - private static final String SIZE = "size"; - private static final String PUSH = "push"; - private static final String POP = "pop"; - private static final String PEEK = "peek"; - - private static final String ERROR_NULL_ENTRY = "Null entries are not allowed"; - private final MeteringAgent monitor; - - public DefaultDistributedQueue(String name, - Database database, - Serializer serializer, - boolean meteringEnabled) { - this.name = checkNotNull(name, "queue name cannot be null"); - this.database = checkNotNull(database, "database cannot be null"); - this.serializer = checkNotNull(serializer, "serializer cannot be null"); - this.monitor = new MeteringAgent(PRIMITIVE_NAME, name, meteringEnabled); - this.database.registerConsumer(update -> { - SharedExecutors.getSingleThreadExecutor().execute(() -> { - if (update.target() == QUEUE_PUSH) { - List<Object> input = update.input(); - String queueName = (String) input.get(0); - if (queueName.equals(name)) { - tryPoll(); - } - } - }); - }); - } - - @Override - public long size() { - final MeteringAgent.Context timer = monitor.startTimer(SIZE); - return Futures.getUnchecked(database.queueSize(name).whenComplete((r, e) -> timer.stop(e))); - } - - @Override - public void push(E entry) { - checkNotNull(entry, ERROR_NULL_ENTRY); - final MeteringAgent.Context timer = monitor.startTimer(PUSH); - Futures.getUnchecked(database.queuePush(name, serializer.encode(entry)) - .whenComplete((r, e) -> timer.stop(e))); - } - - @Override - public CompletableFuture<E> pop() { - final MeteringAgent.Context timer = monitor.startTimer(POP); - return database.queuePop(name) - .whenComplete((r, e) -> timer.stop(e)) - .thenCompose(v -> { - if (v != null) { - return CompletableFuture.<E>completedFuture(serializer.decode(v)); - } - CompletableFuture<E> newPendingFuture = new CompletableFuture<>(); - pendingFutures.add(newPendingFuture); - return newPendingFuture; - }); - - } - - @Override - public E peek() { - final MeteringAgent.Context timer = monitor.startTimer(PEEK); - return Futures.getUnchecked(database.queuePeek(name) - .thenApply(v -> v != null ? serializer.<E>decode(v) : null) - .whenComplete((r, e) -> timer.stop(e))); - } - - public String name() { - return name; - } - - protected void tryPoll() { - Set<CompletableFuture<E>> completedFutures = Sets.newHashSet(); - for (CompletableFuture<E> future : pendingFutures) { - E entry = Futures.getUnchecked(database.queuePop(name) - .thenApply(v -> v != null ? serializer.decode(v) : null)); - if (entry != null) { - future.complete(entry); - completedFutures.add(future); - } else { - break; - } - } - pendingFutures.removeAll(completedFutures); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDistributedQueueBuilder.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDistributedQueueBuilder.java deleted file mode 100644 index d6654e27..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDistributedQueueBuilder.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import org.onosproject.store.service.DistributedQueue; -import org.onosproject.store.service.DistributedQueueBuilder; -import org.onosproject.store.service.Serializer; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; - -/** - * Default implementation of a {@code DistributedQueueBuilder}. - * - * @param <E> queue entry type - */ -public class DefaultDistributedQueueBuilder<E> implements DistributedQueueBuilder<E> { - - private Serializer serializer; - private String name; - private boolean persistenceEnabled = true; - private final DatabaseManager databaseManager; - private boolean metering = true; - - public DefaultDistributedQueueBuilder(DatabaseManager databaseManager) { - this.databaseManager = databaseManager; - } - - @Override - public DistributedQueueBuilder<E> withName(String name) { - checkArgument(name != null && !name.isEmpty()); - this.name = name; - return this; - } - - @Override - public DistributedQueueBuilder<E> withSerializer(Serializer serializer) { - checkArgument(serializer != null); - this.serializer = serializer; - return this; - } - - @Override - public DistributedQueueBuilder<E> withMeteringDisabled() { - metering = false; - return this; - } - - @Override - public DistributedQueueBuilder<E> withPersistenceDisabled() { - persistenceEnabled = false; - return this; - } - - private boolean validInputs() { - return name != null && serializer != null; - } - - @Override - public DistributedQueue<E> build() { - checkState(validInputs()); - return new DefaultDistributedQueue<>( - name, - persistenceEnabled ? databaseManager.partitionedDatabase : databaseManager.inMemoryDatabase, - serializer, - metering); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDistributedSet.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDistributedSet.java deleted file mode 100644 index 677724df..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDistributedSet.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.DistributedSet; -import org.onosproject.store.service.MapEvent; -import org.onosproject.store.service.MapEventListener; -import org.onosproject.store.service.SetEvent; -import org.onosproject.store.service.SetEventListener; - -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -/** - * Implementation of distributed set that is backed by a ConsistentMap. - - * @param <E> set element type - */ -public class DefaultDistributedSet<E> implements DistributedSet<E> { - - private static final String CONTAINS = "contains"; - private static final String PRIMITIVE_NAME = "distributedSet"; - private static final String SIZE = "size"; - private static final String IS_EMPTY = "isEmpty"; - private static final String ITERATOR = "iterator"; - private static final String TO_ARRAY = "toArray"; - private static final String ADD = "add"; - private static final String REMOVE = "remove"; - private static final String CONTAINS_ALL = "containsAll"; - private static final String ADD_ALL = "addAll"; - private static final String RETAIN_ALL = "retainAll"; - private static final String REMOVE_ALL = "removeAll"; - private static final String CLEAR = "clear"; - - private final String name; - private final ConsistentMap<E, Boolean> backingMap; - private final Map<SetEventListener<E>, MapEventListener<E, Boolean>> listenerMapping = Maps.newIdentityHashMap(); - private final MeteringAgent monitor; - - public DefaultDistributedSet(String name, boolean meteringEnabled, ConsistentMap<E, Boolean> backingMap) { - this.name = name; - this.backingMap = backingMap; - monitor = new MeteringAgent(PRIMITIVE_NAME, name, meteringEnabled); - } - - @Override - public int size() { - final MeteringAgent.Context timer = monitor.startTimer(SIZE); - try { - return backingMap.size(); - } finally { - timer.stop(null); - } - } - - @Override - public boolean isEmpty() { - final MeteringAgent.Context timer = monitor.startTimer(IS_EMPTY); - try { - return backingMap.isEmpty(); - } finally { - timer.stop(null); - } - } - - @SuppressWarnings("unchecked") - @Override - public boolean contains(Object o) { - final MeteringAgent.Context timer = monitor.startTimer(CONTAINS); - try { - return backingMap.containsKey((E) o); - } finally { - timer.stop(null); - } - } - - @Override - public Iterator<E> iterator() { - final MeteringAgent.Context timer = monitor.startTimer(ITERATOR); - //Do we have to measure this guy? - try { - return backingMap.keySet().iterator(); - } finally { - timer.stop(null); - } - } - - @Override - public Object[] toArray() { - final MeteringAgent.Context timer = monitor.startTimer(TO_ARRAY); - try { - return backingMap.keySet().stream().toArray(); - } finally { - timer.stop(null); - } - } - - @Override - public <T> T[] toArray(T[] a) { - final MeteringAgent.Context timer = monitor.startTimer(TO_ARRAY); - try { - return backingMap.keySet().stream().toArray(size -> a); - } finally { - timer.stop(null); - } - } - - @Override - public boolean add(E e) { - final MeteringAgent.Context timer = monitor.startTimer(ADD); - try { - return backingMap.putIfAbsent(e, true) == null; - } finally { - timer.stop(null); - } - } - - @SuppressWarnings("unchecked") - @Override - public boolean remove(Object o) { - final MeteringAgent.Context timer = monitor.startTimer(REMOVE); - try { - return backingMap.remove((E) o) != null; - } finally { - timer.stop(null); - } - } - - @Override - public boolean containsAll(Collection<?> c) { - final MeteringAgent.Context timer = monitor.startTimer(CONTAINS_ALL); - try { - return c.stream() - .allMatch(this::contains); - } finally { - timer.stop(null); - } - } - - @Override - public boolean addAll(Collection<? extends E> c) { - final MeteringAgent.Context timer = monitor.startTimer(ADD_ALL); - try { - return c.stream() - .map(this::add) - .reduce(Boolean::logicalOr) - .orElse(false); - } finally { - timer.stop(null); - } - } - - @Override - public boolean retainAll(Collection<?> c) { - final MeteringAgent.Context timer = monitor.startTimer(RETAIN_ALL); - try { - Set<?> retainSet = Sets.newHashSet(c); - return backingMap.keySet() - .stream() - .filter(k -> !retainSet.contains(k)) - .map(this::remove) - .reduce(Boolean::logicalOr) - .orElse(false); - } finally { - timer.stop(null); - } - } - - @Override - public boolean removeAll(Collection<?> c) { - final MeteringAgent.Context timer = monitor.startTimer(REMOVE_ALL); - try { - Set<?> removeSet = Sets.newHashSet(c); - return backingMap.keySet() - .stream() - .filter(removeSet::contains) - .map(this::remove) - .reduce(Boolean::logicalOr) - .orElse(false); - } finally { - timer.stop(null); - } - } - - @Override - public void clear() { - final MeteringAgent.Context timer = monitor.startTimer(CLEAR); - try { - backingMap.clear(); - } finally { - timer.stop(null); - } - } - - @Override - public void addListener(SetEventListener<E> listener) { - MapEventListener<E, Boolean> mapEventListener = mapEvent -> { - if (mapEvent.type() == MapEvent.Type.INSERT) { - listener.event(new SetEvent<>(name, SetEvent.Type.ADD, mapEvent.key())); - } else if (mapEvent.type() == MapEvent.Type.REMOVE) { - listener.event(new SetEvent<>(name, SetEvent.Type.REMOVE, mapEvent.key())); - } - }; - if (listenerMapping.putIfAbsent(listener, mapEventListener) == null) { - backingMap.addListener(mapEventListener); - } - } - - @Override - public void removeListener(SetEventListener<E> listener) { - MapEventListener<E, Boolean> mapEventListener = listenerMapping.remove(listener); - if (mapEventListener != null) { - backingMap.removeListener(mapEventListener); - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDistributedSetBuilder.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDistributedSetBuilder.java deleted file mode 100644 index f7957f39..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultDistributedSetBuilder.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import org.onosproject.core.ApplicationId; -import org.onosproject.store.service.ConsistentMapBuilder; -import org.onosproject.store.service.DistributedSet; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.DistributedSetBuilder; - -/** - * Default distributed set builder. - * - * @param <E> type for set elements - */ -public class DefaultDistributedSetBuilder<E> implements DistributedSetBuilder<E> { - - private String name; - private ConsistentMapBuilder<E, Boolean> mapBuilder; - private boolean metering = true; - - public DefaultDistributedSetBuilder(DatabaseManager manager) { - this.mapBuilder = manager.consistentMapBuilder(); - mapBuilder.withMeteringDisabled(); - } - - @Override - public DistributedSetBuilder<E> withName(String name) { - mapBuilder.withName(name); - this.name = name; - return this; - } - - @Override - public DistributedSetBuilder<E> withApplicationId(ApplicationId id) { - mapBuilder.withApplicationId(id); - return this; - } - - @Override - public DistributedSetBuilder<E> withPurgeOnUninstall() { - mapBuilder.withPurgeOnUninstall(); - return this; - } - - @Override - public DistributedSetBuilder<E> withSerializer(Serializer serializer) { - mapBuilder.withSerializer(serializer); - return this; - } - - @Override - public DistributedSetBuilder<E> withUpdatesDisabled() { - mapBuilder.withUpdatesDisabled(); - return this; - } - - @Override - public DistributedSetBuilder<E> withRelaxedReadConsistency() { - mapBuilder.withRelaxedReadConsistency(); - return this; - } - - @Override - public DistributedSetBuilder<E> withPartitionsDisabled() { - mapBuilder.withPartitionsDisabled(); - return this; - } - - @Override - public DistributedSetBuilder<E> withMeteringDisabled() { - metering = false; - return this; - } - - @Override - public DistributedSet<E> build() { - return new DefaultDistributedSet<E>(name, metering, mapBuilder.build()); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransaction.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransaction.java deleted file mode 100644 index 2ff7a2dc..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransaction.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import java.util.List; - -import org.onosproject.store.service.DatabaseUpdate; -import org.onosproject.store.service.Transaction; - -import com.google.common.collect.ImmutableList; - -/** - * A Default transaction implementation. - */ -public class DefaultTransaction implements Transaction { - - private final long transactionId; - private final List<DatabaseUpdate> updates; - private final State state; - private final long lastUpdated; - - public DefaultTransaction(long transactionId, List<DatabaseUpdate> updates) { - this(transactionId, updates, State.PREPARING, System.currentTimeMillis()); - } - - private DefaultTransaction(long transactionId, List<DatabaseUpdate> updates, State state, long lastUpdated) { - this.transactionId = transactionId; - this.updates = ImmutableList.copyOf(updates); - this.state = state; - this.lastUpdated = lastUpdated; - } - - @Override - public long id() { - return transactionId; - } - - @Override - public List<DatabaseUpdate> updates() { - return updates; - } - - @Override - public State state() { - return state; - } - - @Override - public Transaction transition(State newState) { - return new DefaultTransaction(transactionId, updates, newState, System.currentTimeMillis()); - } - - @Override - public long lastUpdated() { - return lastUpdated; - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java deleted file mode 100644 index 73888221..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; - -import static com.google.common.base.Preconditions.*; - -import org.onosproject.store.service.ConsistentMapBuilder; -import org.onosproject.store.service.DatabaseUpdate; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.Transaction; -import org.onosproject.store.service.TransactionContext; -import org.onosproject.store.service.TransactionalMap; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.util.concurrent.Futures; - -/** - * Default TransactionContext implementation. - */ -public class DefaultTransactionContext implements TransactionContext { - private static final String TX_NOT_OPEN_ERROR = "Transaction Context is not open"; - - @SuppressWarnings("rawtypes") - private final Map<String, DefaultTransactionalMap> txMaps = Maps.newConcurrentMap(); - private boolean isOpen = false; - private final Database database; - private final long transactionId; - private final Supplier<ConsistentMapBuilder> mapBuilderSupplier; - - public DefaultTransactionContext(long transactionId, - Database database, - Supplier<ConsistentMapBuilder> mapBuilderSupplier) { - this.transactionId = transactionId; - this.database = checkNotNull(database); - this.mapBuilderSupplier = checkNotNull(mapBuilderSupplier); - } - - @Override - public long transactionId() { - return transactionId; - } - - @Override - public void begin() { - checkState(!isOpen, "Transaction Context is already open"); - isOpen = true; - } - - @Override - public boolean isOpen() { - return isOpen; - } - - @Override - @SuppressWarnings("unchecked") - public <K, V> TransactionalMap<K, V> getTransactionalMap(String mapName, - Serializer serializer) { - checkState(isOpen, TX_NOT_OPEN_ERROR); - checkNotNull(mapName); - checkNotNull(serializer); - return txMaps.computeIfAbsent(mapName, name -> new DefaultTransactionalMap<>( - name, - mapBuilderSupplier.get().withName(name).withSerializer(serializer).build(), - this, - serializer)); - } - - @SuppressWarnings("unchecked") - @Override - public boolean commit() { - // TODO: rework commit implementation to be more intuitive - checkState(isOpen, TX_NOT_OPEN_ERROR); - CommitResponse response = null; - try { - List<DatabaseUpdate> updates = Lists.newLinkedList(); - txMaps.values().forEach(m -> updates.addAll(m.prepareDatabaseUpdates())); - Transaction transaction = new DefaultTransaction(transactionId, updates); - response = Futures.getUnchecked(database.prepareAndCommit(transaction)); - return response.success(); - } catch (Exception e) { - abort(); - return false; - } finally { - isOpen = false; - } - } - - @Override - public void abort() { - if (isOpen) { - try { - txMaps.values().forEach(m -> m.rollback()); - } finally { - isOpen = false; - } - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContextBuilder.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContextBuilder.java deleted file mode 100644 index f20bfb80..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContextBuilder.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import org.onosproject.store.service.TransactionContext; -import org.onosproject.store.service.TransactionContextBuilder; - -/** - * The default implementation of a transaction context builder. This builder - * generates a {@link DefaultTransactionContext}. - */ -public class DefaultTransactionContextBuilder implements TransactionContextBuilder { - - private boolean partitionsEnabled = true; - private final DatabaseManager manager; - private final long transactionId; - - public DefaultTransactionContextBuilder(DatabaseManager manager, long transactionId) { - this.manager = manager; - this.transactionId = transactionId; - } - - @Override - public TransactionContextBuilder withPartitionsDisabled() { - partitionsEnabled = false; - return this; - } - - @Override - public TransactionContext build() { - return new DefaultTransactionContext( - transactionId, - partitionsEnabled ? manager.partitionedDatabase : manager.inMemoryDatabase, - () -> partitionsEnabled ? manager.consistentMapBuilder() - : manager.consistentMapBuilder().withPartitionsDisabled()); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionalMap.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionalMap.java deleted file mode 100644 index ade70335..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionalMap.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.onlab.util.HexString; -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.DatabaseUpdate; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.TransactionContext; -import org.onosproject.store.service.TransactionalMap; -import org.onosproject.store.service.Versioned; - -import static com.google.common.base.Preconditions.*; - -import com.google.common.base.Objects; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -/** - * Default Transactional Map implementation that provides a repeatable reads - * transaction isolation level. - * - * @param <K> key type - * @param <V> value type. - */ -public class DefaultTransactionalMap<K, V> implements TransactionalMap<K, V> { - - private final TransactionContext txContext; - private static final String TX_CLOSED_ERROR = "Transaction is closed"; - private final ConsistentMap<K, V> backingMap; - private final String name; - private final Serializer serializer; - private final Map<K, Versioned<V>> readCache = Maps.newConcurrentMap(); - private final Map<K, V> writeCache = Maps.newConcurrentMap(); - private final Set<K> deleteSet = Sets.newConcurrentHashSet(); - - private static final String ERROR_NULL_VALUE = "Null values are not allowed"; - private static final String ERROR_NULL_KEY = "Null key is not allowed"; - - private final LoadingCache<K, String> keyCache = CacheBuilder.newBuilder() - .softValues() - .build(new CacheLoader<K, String>() { - - @Override - public String load(K key) { - return HexString.toHexString(serializer.encode(key)); - } - }); - - protected K dK(String key) { - return serializer.decode(HexString.fromHexString(key)); - } - - public DefaultTransactionalMap( - String name, - ConsistentMap<K, V> backingMap, - TransactionContext txContext, - Serializer serializer) { - this.name = name; - this.backingMap = backingMap; - this.txContext = txContext; - this.serializer = serializer; - } - - @Override - public V get(K key) { - checkState(txContext.isOpen(), TX_CLOSED_ERROR); - checkNotNull(key, ERROR_NULL_KEY); - if (deleteSet.contains(key)) { - return null; - } - V latest = writeCache.get(key); - if (latest != null) { - return latest; - } else { - Versioned<V> v = readCache.computeIfAbsent(key, k -> backingMap.get(k)); - return v != null ? v.value() : null; - } - } - - @Override - public V put(K key, V value) { - checkState(txContext.isOpen(), TX_CLOSED_ERROR); - checkNotNull(value, ERROR_NULL_VALUE); - - V latest = get(key); - writeCache.put(key, value); - deleteSet.remove(key); - return latest; - } - - @Override - public V remove(K key) { - checkState(txContext.isOpen(), TX_CLOSED_ERROR); - V latest = get(key); - if (latest != null) { - writeCache.remove(key); - deleteSet.add(key); - } - return latest; - } - - @Override - public boolean remove(K key, V value) { - checkState(txContext.isOpen(), TX_CLOSED_ERROR); - checkNotNull(value, ERROR_NULL_VALUE); - V latest = get(key); - if (Objects.equal(value, latest)) { - remove(key); - return true; - } - return false; - } - - @Override - public boolean replace(K key, V oldValue, V newValue) { - checkState(txContext.isOpen(), TX_CLOSED_ERROR); - checkNotNull(oldValue, ERROR_NULL_VALUE); - checkNotNull(newValue, ERROR_NULL_VALUE); - V latest = get(key); - if (Objects.equal(oldValue, latest)) { - put(key, newValue); - return true; - } - return false; - } - - @Override - public V putIfAbsent(K key, V value) { - checkState(txContext.isOpen(), TX_CLOSED_ERROR); - checkNotNull(value, ERROR_NULL_VALUE); - V latest = get(key); - if (latest == null) { - put(key, value); - } - return latest; - } - - protected List<DatabaseUpdate> prepareDatabaseUpdates() { - List<DatabaseUpdate> updates = Lists.newLinkedList(); - deleteSet.forEach(key -> { - Versioned<V> original = readCache.get(key); - if (original != null) { - updates.add(DatabaseUpdate.newBuilder() - .withMapName(name) - .withType(DatabaseUpdate.Type.REMOVE_IF_VERSION_MATCH) - .withKey(keyCache.getUnchecked(key)) - .withCurrentVersion(original.version()) - .build()); - } - }); - writeCache.forEach((key, value) -> { - Versioned<V> original = readCache.get(key); - if (original == null) { - updates.add(DatabaseUpdate.newBuilder() - .withMapName(name) - .withType(DatabaseUpdate.Type.PUT_IF_ABSENT) - .withKey(keyCache.getUnchecked(key)) - .withValue(serializer.encode(value)) - .build()); - } else { - updates.add(DatabaseUpdate.newBuilder() - .withMapName(name) - .withType(DatabaseUpdate.Type.PUT_IF_VERSION_MATCH) - .withKey(keyCache.getUnchecked(key)) - .withCurrentVersion(original.version()) - .withValue(serializer.encode(value)) - .build()); - } - }); - return updates; - } - - /** - * Discards all changes made to this transactional map. - */ - protected void rollback() { - readCache.clear(); - writeCache.clear(); - deleteSet.clear(); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DistributedLeadershipManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DistributedLeadershipManager.java deleted file mode 100644 index 1882b1b5..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DistributedLeadershipManager.java +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.MapDifference; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -import org.apache.commons.lang.math.RandomUtils; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onosproject.cluster.ClusterEvent; -import org.onosproject.cluster.ClusterEvent.Type; -import org.onosproject.cluster.ClusterEventListener; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.Leadership; -import org.onosproject.cluster.LeadershipEvent; -import org.onosproject.cluster.LeadershipEventListener; -import org.onosproject.cluster.LeadershipService; -import org.onosproject.cluster.NodeId; -import org.onosproject.event.ListenerRegistry; -import org.onosproject.event.EventDeliveryService; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.ConsistentMapException; -import org.onosproject.store.service.MapEvent; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.StorageService; -import org.onosproject.store.service.Versioned; -import org.slf4j.Logger; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Set; -import java.util.List; -import java.util.concurrent.CancellationException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkArgument; -import static org.onlab.util.Tools.groupedThreads; -import static org.slf4j.LoggerFactory.getLogger; -import static org.onosproject.cluster.ControllerNode.State.ACTIVE; -import static org.onosproject.cluster.ControllerNode.State.INACTIVE; - -/** - * Distributed Lock Manager implemented on top of ConsistentMap. - * <p> - * This implementation makes use of ClusterService's failure - * detection capabilities to detect and purge stale locks. - * TODO: Ensure lock safety and liveness. - */ -@Component(immediate = true, enabled = true) -@Service -public class DistributedLeadershipManager implements LeadershipService { - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterCommunicationService clusterCommunicator; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected EventDeliveryService eventDispatcher; - - private final Logger log = getLogger(getClass()); - private ScheduledExecutorService electionRunner; - private ScheduledExecutorService lockExecutor; - private ScheduledExecutorService staleLeadershipPurgeExecutor; - private ScheduledExecutorService leadershipRefresher; - - private ConsistentMap<String, NodeId> leaderMap; - private ConsistentMap<String, List<NodeId>> candidateMap; - - private ListenerRegistry<LeadershipEvent, LeadershipEventListener> listenerRegistry; - private final Map<String, Leadership> leaderBoard = Maps.newConcurrentMap(); - private final Map<String, Leadership> candidateBoard = Maps.newConcurrentMap(); - private final ClusterEventListener clusterEventListener = new InternalClusterEventListener(); - - private NodeId localNodeId; - private Set<String> activeTopics = Sets.newConcurrentHashSet(); - private Map<String, CompletableFuture<Leadership>> pendingFutures = Maps.newConcurrentMap(); - - // The actual delay is randomly chosen from the interval [0, WAIT_BEFORE_RETRY_MILLIS) - private static final int WAIT_BEFORE_RETRY_MILLIS = 150; - private static final int DELAY_BETWEEN_LEADER_LOCK_ATTEMPTS_SEC = 2; - private static final int LEADERSHIP_REFRESH_INTERVAL_SEC = 2; - private static final int DELAY_BETWEEN_STALE_LEADERSHIP_PURGE_ATTEMPTS_SEC = 2; - - private final AtomicBoolean staleLeadershipPurgeScheduled = new AtomicBoolean(false); - - private static final Serializer SERIALIZER = Serializer.using(KryoNamespaces.API); - - @Activate - public void activate() { - leaderMap = storageService.<String, NodeId>consistentMapBuilder() - .withName("onos-topic-leaders") - .withSerializer(SERIALIZER) - .withPartitionsDisabled().build(); - candidateMap = storageService.<String, List<NodeId>>consistentMapBuilder() - .withName("onos-topic-candidates") - .withSerializer(SERIALIZER) - .withPartitionsDisabled().build(); - - leaderMap.addListener(event -> { - log.debug("Received {}", event); - LeadershipEvent.Type leadershipEventType = null; - if (event.type() == MapEvent.Type.INSERT || event.type() == MapEvent.Type.UPDATE) { - leadershipEventType = LeadershipEvent.Type.LEADER_ELECTED; - } else if (event.type() == MapEvent.Type.REMOVE) { - leadershipEventType = LeadershipEvent.Type.LEADER_BOOTED; - } - onLeadershipEvent(new LeadershipEvent( - leadershipEventType, - new Leadership(event.key(), - event.value().value(), - event.value().version(), - event.value().creationTime()))); - }); - - candidateMap.addListener(event -> { - log.debug("Received {}", event); - if (event.type() != MapEvent.Type.INSERT && event.type() != MapEvent.Type.UPDATE) { - log.error("Entries must not be removed from candidate map"); - return; - } - onLeadershipEvent(new LeadershipEvent( - LeadershipEvent.Type.CANDIDATES_CHANGED, - new Leadership(event.key(), - event.value().value(), - event.value().version(), - event.value().creationTime()))); - }); - - localNodeId = clusterService.getLocalNode().id(); - - electionRunner = Executors.newSingleThreadScheduledExecutor( - groupedThreads("onos/store/leadership", "election-runner")); - lockExecutor = Executors.newScheduledThreadPool( - 4, groupedThreads("onos/store/leadership", "election-thread-%d")); - staleLeadershipPurgeExecutor = Executors.newSingleThreadScheduledExecutor( - groupedThreads("onos/store/leadership", "stale-leadership-evictor")); - leadershipRefresher = Executors.newSingleThreadScheduledExecutor( - groupedThreads("onos/store/leadership", "refresh-thread")); - - clusterService.addListener(clusterEventListener); - - electionRunner.scheduleWithFixedDelay( - this::electLeaders, 0, DELAY_BETWEEN_LEADER_LOCK_ATTEMPTS_SEC, TimeUnit.SECONDS); - - leadershipRefresher.scheduleWithFixedDelay( - this::refreshLeaderBoard, 0, LEADERSHIP_REFRESH_INTERVAL_SEC, TimeUnit.SECONDS); - - listenerRegistry = new ListenerRegistry<>(); - eventDispatcher.addSink(LeadershipEvent.class, listenerRegistry); - - log.info("Started"); - } - - @Deactivate - public void deactivate() { - if (clusterService.getNodes().size() > 1) { - // FIXME: Determine why this takes ~50 seconds to shutdown on a single node! - leaderBoard.forEach((topic, leadership) -> { - if (localNodeId.equals(leadership.leader())) { - withdraw(topic); - } - }); - } - - clusterService.removeListener(clusterEventListener); - eventDispatcher.removeSink(LeadershipEvent.class); - - electionRunner.shutdown(); - lockExecutor.shutdown(); - staleLeadershipPurgeExecutor.shutdown(); - leadershipRefresher.shutdown(); - - log.info("Stopped"); - } - - @Override - public Map<String, Leadership> getLeaderBoard() { - return ImmutableMap.copyOf(leaderBoard); - } - - @Override - public Map<String, List<NodeId>> getCandidates() { - return Maps.toMap(candidateBoard.keySet(), this::getCandidates); - } - - @Override - public List<NodeId> getCandidates(String path) { - Leadership current = candidateBoard.get(path); - return current == null ? ImmutableList.of() : ImmutableList.copyOf(current.candidates()); - } - - @Override - public NodeId getLeader(String path) { - Leadership leadership = leaderBoard.get(path); - return leadership != null ? leadership.leader() : null; - } - - @Override - public Leadership getLeadership(String path) { - checkArgument(path != null); - return leaderBoard.get(path); - } - - @Override - public Set<String> ownedTopics(NodeId nodeId) { - checkArgument(nodeId != null); - return leaderBoard.entrySet() - .stream() - .filter(entry -> nodeId.equals(entry.getValue().leader())) - .map(Entry::getKey) - .collect(Collectors.toSet()); - } - - @Override - public CompletableFuture<Leadership> runForLeadership(String path) { - log.debug("Running for leadership for topic: {}", path); - CompletableFuture<Leadership> resultFuture = new CompletableFuture<>(); - doRunForLeadership(path, resultFuture); - return resultFuture; - } - - private void doRunForLeadership(String path, CompletableFuture<Leadership> future) { - try { - Versioned<List<NodeId>> candidates = candidateMap.computeIf(path, - currentList -> currentList == null || !currentList.contains(localNodeId), - (topic, currentList) -> { - if (currentList == null) { - return ImmutableList.of(localNodeId); - } else { - List<NodeId> newList = Lists.newLinkedList(); - newList.addAll(currentList); - newList.add(localNodeId); - return newList; - } - }); - log.debug("In the leadership race for topic {} with candidates {}", path, candidates); - activeTopics.add(path); - Leadership leadership = electLeader(path, candidates.value()); - if (leadership == null) { - pendingFutures.put(path, future); - } else { - future.complete(leadership); - } - } catch (ConsistentMapException e) { - log.debug("Failed to enter topic leader race for {}. Retrying.", path, e); - rerunForLeadership(path, future); - } - } - - @Override - public CompletableFuture<Void> withdraw(String path) { - activeTopics.remove(path); - CompletableFuture<Void> resultFuture = new CompletableFuture<>(); - doWithdraw(path, resultFuture); - return resultFuture; - } - - - private void doWithdraw(String path, CompletableFuture<Void> future) { - if (activeTopics.contains(path)) { - future.completeExceptionally(new CancellationException(String.format("%s is now a active topic", path))); - } - try { - leaderMap.computeIf(path, - localNodeId::equals, - (topic, leader) -> null); - candidateMap.computeIf(path, - candidates -> candidates != null && candidates.contains(localNodeId), - (topic, candidates) -> candidates.stream() - .filter(nodeId -> !localNodeId.equals(nodeId)) - .collect(Collectors.toList())); - future.complete(null); - } catch (Exception e) { - log.debug("Failed to verify (and clear) any lock this node might be holding for {}", path, e); - retryWithdraw(path, future); - } - } - - @Override - public boolean stepdown(String path) { - if (!activeTopics.contains(path) || !Objects.equals(localNodeId, getLeader(path))) { - return false; - } - - try { - return leaderMap.computeIf(path, - localNodeId::equals, - (topic, leader) -> null) == null; - } catch (Exception e) { - log.warn("Error executing stepdown for {}", path, e); - } - return false; - } - - @Override - public void addListener(LeadershipEventListener listener) { - listenerRegistry.addListener(listener); - } - - @Override - public void removeListener(LeadershipEventListener listener) { - listenerRegistry.removeListener(listener); - } - - @Override - public boolean makeTopCandidate(String path, NodeId nodeId) { - Versioned<List<NodeId>> candidateList = candidateMap.computeIf(path, - candidates -> candidates != null && - candidates.contains(nodeId) && - !nodeId.equals(Iterables.getFirst(candidates, null)), - (topic, candidates) -> { - List<NodeId> updatedCandidates = new ArrayList<>(candidates.size()); - updatedCandidates.add(nodeId); - candidates.stream().filter(id -> !nodeId.equals(id)).forEach(updatedCandidates::add); - return updatedCandidates; - }); - List<NodeId> candidates = candidateList != null ? candidateList.value() : Collections.emptyList(); - return candidates.size() > 0 && nodeId.equals(candidates.get(0)); - } - - private Leadership electLeader(String path, List<NodeId> candidates) { - Leadership currentLeadership = getLeadership(path); - if (currentLeadership != null) { - return currentLeadership; - } else { - NodeId topCandidate = candidates - .stream() - .filter(n -> clusterService.getState(n) == ACTIVE) - .findFirst() - .orElse(null); - try { - Versioned<NodeId> leader = localNodeId.equals(topCandidate) - ? leaderMap.computeIfAbsent(path, p -> localNodeId) : leaderMap.get(path); - if (leader != null) { - Leadership newLeadership = new Leadership(path, - leader.value(), - leader.version(), - leader.creationTime()); - // Since reads only go through the local copy of leader board, we ought to update it - // first before returning from this method. - // This is to ensure a subsequent read will not read a stale value. - onLeadershipEvent(new LeadershipEvent(LeadershipEvent.Type.LEADER_ELECTED, newLeadership)); - return newLeadership; - } - } catch (Exception e) { - log.debug("Failed to elect leader for {}", path, e); - } - } - return null; - } - - private void electLeaders() { - try { - candidateMap.entrySet().forEach(entry -> { - String path = entry.getKey(); - Versioned<List<NodeId>> candidates = entry.getValue(); - // for active topics, check if this node can become a leader (if it isn't already) - if (activeTopics.contains(path)) { - lockExecutor.submit(() -> { - Leadership leadership = electLeader(path, candidates.value()); - if (leadership != null) { - CompletableFuture<Leadership> future = pendingFutures.remove(path); - if (future != null) { - future.complete(leadership); - } - } - }); - } - // Raise a CANDIDATES_CHANGED event to force refresh local candidate board - // and also to update local listeners. - // Don't worry about duplicate events as they will be suppressed. - onLeadershipEvent(new LeadershipEvent(LeadershipEvent.Type.CANDIDATES_CHANGED, - new Leadership(path, - candidates.value(), - candidates.version(), - candidates.creationTime()))); - }); - } catch (Exception e) { - log.debug("Failure electing leaders", e); - } - } - - private void onLeadershipEvent(LeadershipEvent leadershipEvent) { - log.trace("Leadership Event: time = {} type = {} event = {}", - leadershipEvent.time(), leadershipEvent.type(), - leadershipEvent); - - Leadership leadershipUpdate = leadershipEvent.subject(); - LeadershipEvent.Type eventType = leadershipEvent.type(); - String topic = leadershipUpdate.topic(); - - AtomicBoolean updateAccepted = new AtomicBoolean(false); - if (eventType.equals(LeadershipEvent.Type.LEADER_ELECTED)) { - leaderBoard.compute(topic, (k, currentLeadership) -> { - if (currentLeadership == null || currentLeadership.epoch() < leadershipUpdate.epoch()) { - updateAccepted.set(true); - return leadershipUpdate; - } - return currentLeadership; - }); - } else if (eventType.equals(LeadershipEvent.Type.LEADER_BOOTED)) { - leaderBoard.compute(topic, (k, currentLeadership) -> { - if (currentLeadership == null || currentLeadership.epoch() <= leadershipUpdate.epoch()) { - updateAccepted.set(true); - // FIXME: Removing entries from leaderboard is not safe and should be visited. - return null; - } - return currentLeadership; - }); - } else if (eventType.equals(LeadershipEvent.Type.CANDIDATES_CHANGED)) { - candidateBoard.compute(topic, (k, currentInfo) -> { - if (currentInfo == null || currentInfo.epoch() < leadershipUpdate.epoch()) { - updateAccepted.set(true); - return leadershipUpdate; - } - return currentInfo; - }); - } else { - throw new IllegalStateException("Unknown event type."); - } - - if (updateAccepted.get()) { - eventDispatcher.post(leadershipEvent); - } - } - - private void rerunForLeadership(String path, CompletableFuture<Leadership> future) { - lockExecutor.schedule( - () -> doRunForLeadership(path, future), - RandomUtils.nextInt(WAIT_BEFORE_RETRY_MILLIS), - TimeUnit.MILLISECONDS); - } - - private void retryWithdraw(String path, CompletableFuture<Void> future) { - lockExecutor.schedule( - () -> doWithdraw(path, future), - RandomUtils.nextInt(WAIT_BEFORE_RETRY_MILLIS), - TimeUnit.MILLISECONDS); - } - - private void scheduleStaleLeadershipPurge(int afterDelaySec) { - if (staleLeadershipPurgeScheduled.compareAndSet(false, true)) { - staleLeadershipPurgeExecutor.schedule( - this::purgeStaleLeadership, - afterDelaySec, - TimeUnit.SECONDS); - } - } - - /** - * Purges locks held by inactive nodes and evicts inactive nodes from candidacy. - */ - private void purgeStaleLeadership() { - AtomicBoolean rerunPurge = new AtomicBoolean(false); - try { - staleLeadershipPurgeScheduled.set(false); - leaderMap.entrySet() - .stream() - .filter(e -> clusterService.getState(e.getValue().value()) == INACTIVE) - .forEach(entry -> { - String path = entry.getKey(); - NodeId nodeId = entry.getValue().value(); - try { - leaderMap.computeIf(path, nodeId::equals, (topic, leader) -> null); - } catch (Exception e) { - log.debug("Failed to purge stale lock held by {} for {}", nodeId, path, e); - rerunPurge.set(true); - } - }); - - candidateMap.entrySet() - .forEach(entry -> { - String path = entry.getKey(); - Versioned<List<NodeId>> candidates = entry.getValue(); - List<NodeId> candidatesList = candidates != null - ? candidates.value() : Collections.emptyList(); - List<NodeId> activeCandidatesList = - candidatesList.stream() - .filter(n -> clusterService.getState(n) == ACTIVE) - .filter(n -> !localNodeId.equals(n) || activeTopics.contains(path)) - .collect(Collectors.toList()); - if (activeCandidatesList.size() < candidatesList.size()) { - Set<NodeId> removedCandidates = - Sets.difference(Sets.newHashSet(candidatesList), - Sets.newHashSet(activeCandidatesList)); - try { - candidateMap.computeIf(path, - c -> c.stream() - .filter(n -> clusterService.getState(n) == INACTIVE) - .count() > 0, - (topic, c) -> c.stream() - .filter(n -> clusterService.getState(n) == ACTIVE) - .filter(n -> !localNodeId.equals(n) || - activeTopics.contains(path)) - .collect(Collectors.toList())); - } catch (Exception e) { - log.debug("Failed to evict inactive candidates {} from " - + "candidate list for {}", removedCandidates, path, e); - rerunPurge.set(true); - } - } - }); - } catch (Exception e) { - log.debug("Failure purging state leadership.", e); - rerunPurge.set(true); - } - - if (rerunPurge.get()) { - log.debug("Rescheduling stale leadership purge due to errors encountered in previous run"); - scheduleStaleLeadershipPurge(DELAY_BETWEEN_STALE_LEADERSHIP_PURGE_ATTEMPTS_SEC); - } - } - - private void refreshLeaderBoard() { - try { - Map<String, Leadership> newLeaderBoard = Maps.newHashMap(); - leaderMap.entrySet().forEach(entry -> { - String path = entry.getKey(); - Versioned<NodeId> leader = entry.getValue(); - Leadership leadership = new Leadership(path, - leader.value(), - leader.version(), - leader.creationTime()); - newLeaderBoard.put(path, leadership); - }); - - // first take snapshot of current leader board. - Map<String, Leadership> currentLeaderBoard = ImmutableMap.copyOf(leaderBoard); - - MapDifference<String, Leadership> diff = Maps.difference(currentLeaderBoard, newLeaderBoard); - - // evict stale leaders - diff.entriesOnlyOnLeft().forEach((path, leadership) -> { - log.debug("Evicting {} from leaderboard. It is no longer active leader.", leadership); - onLeadershipEvent(new LeadershipEvent(LeadershipEvent.Type.LEADER_BOOTED, leadership)); - }); - - // add missing leaders - diff.entriesOnlyOnRight().forEach((path, leadership) -> { - log.debug("Adding {} to leaderboard. It is now the active leader.", leadership); - onLeadershipEvent(new LeadershipEvent(LeadershipEvent.Type.LEADER_ELECTED, leadership)); - }); - - // add updated leaders - diff.entriesDiffering().forEach((path, difference) -> { - Leadership current = difference.leftValue(); - Leadership updated = difference.rightValue(); - if (current.epoch() < updated.epoch()) { - log.debug("Updated {} in leaderboard.", updated); - onLeadershipEvent(new LeadershipEvent(LeadershipEvent.Type.LEADER_ELECTED, updated)); - } - }); - } catch (Exception e) { - log.debug("Failed to refresh leader board", e); - } - } - - private class InternalClusterEventListener implements ClusterEventListener { - - @Override - public void event(ClusterEvent event) { - if (event.type() == Type.INSTANCE_DEACTIVATED || event.type() == Type.INSTANCE_REMOVED) { - scheduleStaleLeadershipPurge(0); - } - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/MappingSet.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/MappingSet.java deleted file mode 100644 index 9bf80a73..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/MappingSet.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - -import com.google.common.collect.Iterators; - -/** - * Set view backed by Set with element type {@code <BACK>} but returns - * element as {@code <OUT>} for convenience. - * - * @param <BACK> Backing {@link Set} element type. - * MappingSet will follow this type's equality behavior. - * @param <OUT> external facing element type. - * MappingSet will ignores equality defined by this type. - */ -class MappingSet<BACK, OUT> implements Set<OUT> { - - private final Set<BACK> backedSet; - private final Function<OUT, BACK> toBack; - private final Function<BACK, OUT> toOut; - - public MappingSet(Set<BACK> backedSet, - Function<Set<BACK>, Set<BACK>> supplier, - Function<OUT, BACK> toBack, Function<BACK, OUT> toOut) { - this.backedSet = supplier.apply(backedSet); - this.toBack = toBack; - this.toOut = toOut; - } - - @Override - public int size() { - return backedSet.size(); - } - - @Override - public boolean isEmpty() { - return backedSet.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return backedSet.contains(toBack.apply((OUT) o)); - } - - @Override - public Iterator<OUT> iterator() { - return Iterators.transform(backedSet.iterator(), toOut::apply); - } - - @Override - public Object[] toArray() { - return backedSet.stream() - .map(toOut) - .toArray(); - } - - @Override - public <T> T[] toArray(T[] a) { - return backedSet.stream() - .map(toOut) - .toArray(size -> { - if (size < a.length) { - return (T[]) new Object[size]; - } else { - Arrays.fill(a, null); - return a; - } - }); - } - - @Override - public boolean add(OUT e) { - return backedSet.add(toBack.apply(e)); - } - - @Override - public boolean remove(Object o) { - return backedSet.remove(toBack.apply((OUT) o)); - } - - @Override - public boolean containsAll(Collection<?> c) { - return c.stream() - .map(e -> toBack.apply((OUT) e)) - .allMatch(backedSet::contains); - } - - @Override - public boolean addAll(Collection<? extends OUT> c) { - return backedSet.addAll(c.stream().map(toBack).collect(Collectors.toList())); - } - - @Override - public boolean retainAll(Collection<?> c) { - return backedSet.retainAll(c.stream() - .map(x -> toBack.apply((OUT) x)) - .collect(Collectors.toList())); - } - - @Override - public boolean removeAll(Collection<?> c) { - return backedSet.removeAll(c.stream() - .map(x -> toBack.apply((OUT) x)) - .collect(Collectors.toList())); - } - - @Override - public void clear() { - backedSet.clear(); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/Match.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/Match.java deleted file mode 100644 index 5f707d62..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/Match.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import static com.google.common.base.MoreObjects.toStringHelper; - -import java.util.Arrays; -import java.util.Objects; -import java.util.function.Function; - -/** - * Utility class for checking matching values. - * - * @param <T> type of value - */ -public final class Match<T> { - - private final boolean matchAny; - private final T value; - - /** - * Returns a Match that matches any value. - * @param <T> match type - * @return new instance - */ - public static <T> Match<T> any() { - return new Match<>(); - } - - /** - * Returns a Match that matches null values. - * @param <T> match type - * @return new instance - */ - public static <T> Match<T> ifNull() { - return ifValue(null); - } - - /** - * Returns a Match that matches only specified value. - * @param value value to match - * @param <T> match type - * @return new instance - */ - public static <T> Match<T> ifValue(T value) { - return new Match<>(value); - } - - private Match() { - matchAny = true; - value = null; - } - - private Match(T value) { - matchAny = false; - this.value = value; - } - - /** - * Maps this instance to a Match of another type. - * @param mapper transformation function - * @param <V> new match type - * @return new instance - */ - public <V> Match<V> map(Function<T, V> mapper) { - if (matchAny) { - return any(); - } else if (value == null) { - return ifNull(); - } else { - return ifValue(mapper.apply(value)); - } - } - - /** - * Checks if this instance matches specified value. - * @param other other value - * @return true if matches; false otherwise - */ - public boolean matches(T other) { - if (matchAny) { - return true; - } else if (other == null) { - return value == null; - } else { - if (value instanceof byte[]) { - return Arrays.equals((byte[]) value, (byte[]) other); - } - return Objects.equals(value, other); - } - } - - @Override - public int hashCode() { - return Objects.hash(matchAny, value); - } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object other) { - if (!(other instanceof Match)) { - return false; - } - Match<T> that = (Match<T>) other; - return Objects.equals(this.matchAny, that.matchAny) && - Objects.equals(this.value, that.value); - } - - @Override - public String toString() { - return toStringHelper(this) - .add("matchAny", matchAny) - .add("value", value) - .toString(); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/MeteringAgent.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/MeteringAgent.java deleted file mode 100644 index 6475bf7b..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/MeteringAgent.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import com.codahale.metrics.Counter; -import com.codahale.metrics.Timer; -import com.google.common.collect.Maps; -import org.onlab.metrics.MetricsComponent; -import org.onlab.metrics.MetricsFeature; -import org.onlab.metrics.MetricsService; -import org.onlab.osgi.DefaultServiceDirectory; - -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Agent that implements usage and performance monitoring via the metrics service. - */ -public class MeteringAgent { - - private Counter exceptionCounter; - private Counter perObjExceptionCounter; - private MetricsService metricsService; - private MetricsComponent metricsComponent; - private MetricsFeature metricsFeature; - private final Map<String, Timer> perObjOpTimers = Maps.newConcurrentMap(); - private final Map<String, Timer> perOpTimers = Maps.newConcurrentMap(); - private Timer perPrimitiveTimer; - private Timer perObjTimer; - private MetricsFeature wildcard; - private final boolean activated; - private Context nullTimer; - - /** - * Constructs a new MeteringAgent for a given distributed primitive. - * Instantiates the metrics service - * Initializes all the general metrics for that object - * - * @param primitiveName Type of primitive to be metered - * @param objName Global name of the primitive - * @param activated boolean flag for whether metering is enabled or not - */ - public MeteringAgent(String primitiveName, String objName, boolean activated) { - checkNotNull(objName, "Object name cannot be null"); - this.activated = activated; - nullTimer = new Context(null, ""); - if (this.activated) { - this.metricsService = DefaultServiceDirectory.getService(MetricsService.class); - this.metricsComponent = metricsService.registerComponent(primitiveName); - this.metricsFeature = metricsComponent.registerFeature(objName); - this.wildcard = metricsComponent.registerFeature("*"); - this.perObjTimer = metricsService.createTimer(metricsComponent, metricsFeature, "*"); - this.perPrimitiveTimer = metricsService.createTimer(metricsComponent, wildcard, "*"); - this.perObjExceptionCounter = metricsService.createCounter(metricsComponent, metricsFeature, "exceptions"); - this.exceptionCounter = metricsService.createCounter(metricsComponent, wildcard, "exceptions"); - } - } - - /** - * Initializes a specific timer for a given operation. - * - * @param op Specific operation being metered - * @return timer context - */ - public Context startTimer(String op) { - if (!activated) { - return nullTimer; - } - // Check if timer exists, if it doesn't creates it - final Timer currTimer = perObjOpTimers.computeIfAbsent(op, timer -> - metricsService.createTimer(metricsComponent, metricsFeature, op)); - perOpTimers.computeIfAbsent(op, timer -> metricsService.createTimer(metricsComponent, wildcard, op)); - // Starts timer - return new Context(currTimer.time(), op); - } - - /** - * Timer.Context with a specific operation. - */ - public class Context { - private final Timer.Context context; - private final String operation; - - /** - * Constructs Context. - * - * @param context context - * @param operation operation name - */ - public Context(Timer.Context context, String operation) { - this.context = context; - this.operation = operation; - } - - /** - * Stops timer given a specific context and updates all related metrics. - * @param e throwable - */ - public void stop(Throwable e) { - if (!activated) { - return; - } - if (e == null) { - //Stop and updates timer with specific measurements per map, per operation - final long time = context.stop(); - //updates timer with aggregated measurements per map - perOpTimers.get(operation).update(time, TimeUnit.NANOSECONDS); - //updates timer with aggregated measurements per map - perObjTimer.update(time, TimeUnit.NANOSECONDS); - //updates timer with aggregated measurements per all Consistent Maps - perPrimitiveTimer.update(time, TimeUnit.NANOSECONDS); - } else { - exceptionCounter.inc(); - perObjExceptionCounter.inc(); - } - } - } - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/MutexExecutionManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/MutexExecutionManager.java deleted file mode 100644 index d8593e37..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/MutexExecutionManager.java +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import static org.slf4j.LoggerFactory.getLogger; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.Tools; -import org.onosproject.cluster.ClusterEvent; -import org.onosproject.cluster.ClusterEventListener; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.ControllerNode.State; -import org.onosproject.cluster.NodeId; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.ConsistentMapException; -import org.onosproject.store.service.MapEvent; -import org.onosproject.store.service.MapEventListener; -import org.onosproject.store.service.MutexExecutionService; -import org.onosproject.store.service.MutexTask; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.StorageService; -import org.onosproject.store.service.Versioned; -import org.slf4j.Logger; - -import com.google.common.base.MoreObjects; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; - -/** - * Implementation of a MutexExecutionService. - */ -@Component(immediate = true) -@Service -public class MutexExecutionManager implements MutexExecutionService { - - private final Logger log = getLogger(getClass()); - - protected ConsistentMap<String, MutexState> lockMap; - protected NodeId localNodeId; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - private final MapEventListener<String, MutexState> mapEventListener = new InternalLockMapEventListener(); - private final ClusterEventListener clusterEventListener = new InternalClusterEventListener(); - - private Map<String, CompletableFuture<MutexState>> pending = Maps.newConcurrentMap(); - private Map<String, InnerMutexTask> activeTasks = Maps.newConcurrentMap(); - - @Activate - public void activate() { - localNodeId = clusterService.getLocalNode().id(); - lockMap = storageService.<String, MutexState>consistentMapBuilder() - .withName("onos-mutexes") - .withSerializer(Serializer.using(Arrays.asList(KryoNamespaces.API), MutexState.class)) - .withPartitionsDisabled() - .build(); - lockMap.addListener(mapEventListener); - clusterService.addListener(clusterEventListener); - releaseOldLocks(); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - lockMap.removeListener(mapEventListener); - pending.values().forEach(future -> future.cancel(true)); - activeTasks.forEach((k, v) -> { - v.stop(); - unlock(k); - }); - clusterService.removeListener(clusterEventListener); - log.info("Stopped"); - } - - @Override - public CompletableFuture<Void> execute(MutexTask task, String exclusionPath, Executor executor) { - return lock(exclusionPath) - .thenApply(state -> activeTasks.computeIfAbsent(exclusionPath, - k -> new InnerMutexTask(exclusionPath, - task, - state.term()))) - .thenAcceptAsync(t -> t.start(), executor) - .whenComplete((r, e) -> unlock(exclusionPath)); - } - - protected CompletableFuture<MutexState> lock(String exclusionPath) { - CompletableFuture<MutexState> future = - pending.computeIfAbsent(exclusionPath, k -> new CompletableFuture<>()); - tryLock(exclusionPath); - return future; - } - - /** - * Attempts to acquire lock for a path. If lock is held by some other node, adds this node to - * the wait list. - * @param exclusionPath exclusion path - */ - protected void tryLock(String exclusionPath) { - Tools.retryable(() -> lockMap.asJavaMap() - .compute(exclusionPath, - (k, v) -> MutexState.admit(v, localNodeId)), - ConsistentMapException.ConcurrentModification.class, - Integer.MAX_VALUE, - 100).get(); - } - - /** - * Releases lock for the specific path. This operation is idempotent. - * @param exclusionPath exclusion path - */ - protected void unlock(String exclusionPath) { - Tools.retryable(() -> lockMap.asJavaMap() - .compute(exclusionPath, (k, v) -> MutexState.evict(v, localNodeId)), - ConsistentMapException.ConcurrentModification.class, - Integer.MAX_VALUE, - 100).get(); - } - - /** - * Detects and releases all locks held by this node. - */ - private void releaseOldLocks() { - Maps.filterValues(lockMap.asJavaMap(), state -> localNodeId.equals(state.holder())) - .keySet() - .forEach(path -> { - log.info("Detected zombie task still holding lock for {}. Releasing lock.", path); - unlock(path); - }); - } - - private class InternalLockMapEventListener implements MapEventListener<String, MutexState> { - - @Override - public void event(MapEvent<String, MutexState> event) { - log.debug("Received {}", event); - if (event.type() == MapEvent.Type.UPDATE || event.type() == MapEvent.Type.INSERT) { - pending.computeIfPresent(event.key(), (k, future) -> { - MutexState state = Versioned.valueOrElse(event.value(), null); - if (state != null && localNodeId.equals(state.holder())) { - log.debug("Local node is now owner for {}", event.key()); - future.complete(state); - return null; - } else { - return future; - } - }); - InnerMutexTask task = activeTasks.get(event.key()); - if (task != null && task.term() < Versioned.valueOrElse(event.value(), null).term()) { - task.stop(); - } - } - } - } - - private class InternalClusterEventListener implements ClusterEventListener { - - @Override - public void event(ClusterEvent event) { - if (event.type() == ClusterEvent.Type.INSTANCE_DEACTIVATED || - event.type() == ClusterEvent.Type.INSTANCE_REMOVED) { - NodeId nodeId = event.subject().id(); - log.debug("{} is no longer active. Attemping to clean up its locks.", nodeId); - lockMap.asJavaMap().forEach((k, v) -> { - if (v.contains(nodeId)) { - lockMap.compute(k, (path, state) -> MutexState.evict(v, nodeId)); - } - }); - } - long activeNodes = clusterService.getNodes() - .stream() - .map(node -> clusterService.getState(node.id())) - .filter(State.ACTIVE::equals) - .count(); - if (clusterService.getNodes().size() > 1 && activeNodes == 1) { - log.info("This node is partitioned away from the cluster. Stopping all inflight executions"); - activeTasks.forEach((k, v) -> { - v.stop(); - }); - } - } - } - - private static final class MutexState { - - private final NodeId holder; - private final List<NodeId> waitList; - private final long term; - - public static MutexState admit(MutexState state, NodeId nodeId) { - if (state == null) { - return new MutexState(nodeId, 1L, Lists.newArrayList()); - } else if (state.holder() == null) { - return new MutexState(nodeId, state.term() + 1, Lists.newArrayList()); - } else { - if (!state.contains(nodeId)) { - NodeId newHolder = state.holder(); - List<NodeId> newWaitList = Lists.newArrayList(state.waitList()); - newWaitList.add(nodeId); - return new MutexState(newHolder, state.term(), newWaitList); - } else { - return state; - } - } - } - - public static MutexState evict(MutexState state, NodeId nodeId) { - return state.evict(nodeId); - } - - public MutexState evict(NodeId nodeId) { - if (nodeId.equals(holder)) { - if (waitList.isEmpty()) { - return new MutexState(null, term, waitList); - } - List<NodeId> newWaitList = Lists.newArrayList(waitList); - NodeId newHolder = newWaitList.remove(0); - return new MutexState(newHolder, term + 1, newWaitList); - } else { - NodeId newHolder = holder; - List<NodeId> newWaitList = Lists.newArrayList(waitList); - newWaitList.remove(nodeId); - return new MutexState(newHolder, term, newWaitList); - } - } - - public NodeId holder() { - return holder; - } - - public List<NodeId> waitList() { - return waitList; - } - - public long term() { - return term; - } - - private boolean contains(NodeId nodeId) { - return (nodeId.equals(holder) || waitList.contains(nodeId)); - } - - private MutexState(NodeId holder, long term, List<NodeId> waitList) { - this.holder = holder; - this.term = term; - this.waitList = Lists.newArrayList(waitList); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("holder", holder) - .add("term", term) - .add("waitList", waitList) - .toString(); - } - } - - private class InnerMutexTask implements MutexTask { - private final MutexTask task; - private final String mutexPath; - private final long term; - - public InnerMutexTask(String mutexPath, MutexTask task, long term) { - this.mutexPath = mutexPath; - this.term = term; - this.task = task; - } - - public long term() { - return term; - } - - @Override - public void start() { - log.debug("Starting execution for mutex task guarded by {}", mutexPath); - task.start(); - log.debug("Finished execution for mutex task guarded by {}", mutexPath); - } - - @Override - public void stop() { - log.debug("Stopping execution for mutex task guarded by {}", mutexPath); - task.stop(); - } - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/PartitionedDatabase.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/PartitionedDatabase.java deleted file mode 100644 index f741b367..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/PartitionedDatabase.java +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import net.kuujo.copycat.Task; -import net.kuujo.copycat.cluster.Cluster; -import net.kuujo.copycat.resource.ResourceState; -import org.onosproject.store.service.DatabaseUpdate; -import org.onosproject.store.service.Transaction; -import org.onosproject.store.service.Versioned; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkState; - -/** - * A database that partitions the keys across one or more database partitions. - */ -public class PartitionedDatabase implements Database { - - private final String name; - private final Partitioner<String> partitioner; - private final List<Database> partitions; - private final AtomicBoolean isOpen = new AtomicBoolean(false); - private static final String DB_NOT_OPEN = "Partitioned Database is not open"; - private TransactionManager transactionManager; - - public PartitionedDatabase( - String name, - Collection<Database> partitions) { - this.name = name; - this.partitions = partitions - .stream() - .sorted((db1, db2) -> db1.name().compareTo(db2.name())) - .collect(Collectors.toList()); - this.partitioner = new SimpleKeyHashPartitioner(this.partitions); - } - - /** - * Returns the databases for individual partitions. - * @return list of database partitions - */ - public List<Database> getPartitions() { - return partitions; - } - - /** - * Returns true if the database is open. - * @return true if open, false otherwise - */ - @Override - public boolean isOpen() { - return isOpen.get(); - } - - @Override - public CompletableFuture<Set<String>> maps() { - checkState(isOpen.get(), DB_NOT_OPEN); - Set<String> mapNames = Sets.newConcurrentHashSet(); - return CompletableFuture.allOf(partitions - .stream() - .map(db -> db.maps().thenApply(mapNames::addAll)) - .toArray(CompletableFuture[]::new)) - .thenApply(v -> mapNames); - } - - @Override - public CompletableFuture<Map<String, Long>> counters() { - checkState(isOpen.get(), DB_NOT_OPEN); - Map<String, Long> counters = Maps.newConcurrentMap(); - return CompletableFuture.allOf(partitions - .stream() - .map(db -> db.counters() - .thenApply(m -> { - counters.putAll(m); - return null; - })) - .toArray(CompletableFuture[]::new)) - .thenApply(v -> counters); - } - - @Override - public CompletableFuture<Integer> mapSize(String mapName) { - checkState(isOpen.get(), DB_NOT_OPEN); - AtomicInteger totalSize = new AtomicInteger(0); - return CompletableFuture.allOf(partitions - .stream() - .map(p -> p.mapSize(mapName).thenApply(totalSize::addAndGet)) - .toArray(CompletableFuture[]::new)) - .thenApply(v -> totalSize.get()); - } - - @Override - public CompletableFuture<Boolean> mapIsEmpty(String mapName) { - checkState(isOpen.get(), DB_NOT_OPEN); - return mapSize(mapName).thenApply(size -> size == 0); - } - - @Override - public CompletableFuture<Boolean> mapContainsKey(String mapName, String key) { - checkState(isOpen.get(), DB_NOT_OPEN); - return partitioner.getPartition(mapName, key).mapContainsKey(mapName, key); - } - - @Override - public CompletableFuture<Boolean> mapContainsValue(String mapName, byte[] value) { - checkState(isOpen.get(), DB_NOT_OPEN); - AtomicBoolean containsValue = new AtomicBoolean(false); - return CompletableFuture.allOf(partitions - .stream() - .map(p -> p.mapContainsValue(mapName, value) - .thenApply(v -> containsValue.compareAndSet(false, v))) - .toArray(CompletableFuture[]::new)) - .thenApply(v -> containsValue.get()); - } - - @Override - public CompletableFuture<Versioned<byte[]>> mapGet(String mapName, String key) { - checkState(isOpen.get(), DB_NOT_OPEN); - return partitioner.getPartition(mapName, key).mapGet(mapName, key); - } - - @Override - public CompletableFuture<Result<UpdateResult<String, byte[]>>> mapUpdate( - String mapName, String key, Match<byte[]> valueMatch, - Match<Long> versionMatch, byte[] value) { - return partitioner.getPartition(mapName, key).mapUpdate(mapName, key, valueMatch, versionMatch, value); - - } - - @Override - public CompletableFuture<Result<Void>> mapClear(String mapName) { - AtomicBoolean isLocked = new AtomicBoolean(false); - checkState(isOpen.get(), DB_NOT_OPEN); - return CompletableFuture.allOf(partitions - .stream() - .map(p -> p.mapClear(mapName) - .thenApply(v -> isLocked.compareAndSet(false, Result.Status.LOCKED == v.status()))) - .toArray(CompletableFuture[]::new)) - .thenApply(v -> isLocked.get() ? Result.locked() : Result.ok(null)); - } - - @Override - public CompletableFuture<Set<String>> mapKeySet(String mapName) { - checkState(isOpen.get(), DB_NOT_OPEN); - Set<String> keySet = Sets.newConcurrentHashSet(); - return CompletableFuture.allOf(partitions - .stream() - .map(p -> p.mapKeySet(mapName).thenApply(keySet::addAll)) - .toArray(CompletableFuture[]::new)) - .thenApply(v -> keySet); - } - - @Override - public CompletableFuture<Collection<Versioned<byte[]>>> mapValues(String mapName) { - checkState(isOpen.get(), DB_NOT_OPEN); - List<Versioned<byte[]>> values = new CopyOnWriteArrayList<>(); - return CompletableFuture.allOf(partitions - .stream() - .map(p -> p.mapValues(mapName).thenApply(values::addAll)) - .toArray(CompletableFuture[]::new)) - .thenApply(v -> values); - } - - @Override - public CompletableFuture<Set<Entry<String, Versioned<byte[]>>>> mapEntrySet(String mapName) { - checkState(isOpen.get(), DB_NOT_OPEN); - Set<Entry<String, Versioned<byte[]>>> entrySet = Sets.newConcurrentHashSet(); - return CompletableFuture.allOf(partitions - .stream() - .map(p -> p.mapEntrySet(mapName).thenApply(entrySet::addAll)) - .toArray(CompletableFuture[]::new)) - .thenApply(v -> entrySet); - } - - @Override - public CompletableFuture<Long> counterGet(String counterName) { - checkState(isOpen.get(), DB_NOT_OPEN); - return partitioner.getPartition(counterName, counterName).counterGet(counterName); - } - - @Override - public CompletableFuture<Long> counterAddAndGet(String counterName, long delta) { - checkState(isOpen.get(), DB_NOT_OPEN); - return partitioner.getPartition(counterName, counterName).counterAddAndGet(counterName, delta); - } - - @Override - public CompletableFuture<Long> counterGetAndAdd(String counterName, long delta) { - checkState(isOpen.get(), DB_NOT_OPEN); - return partitioner.getPartition(counterName, counterName).counterGetAndAdd(counterName, delta); - } - - @Override - public CompletableFuture<Void> counterSet(String counterName, long value) { - checkState(isOpen.get(), DB_NOT_OPEN); - return partitioner.getPartition(counterName, counterName).counterSet(counterName, value); - } - - @Override - public CompletableFuture<Boolean> counterCompareAndSet(String counterName, long expectedValue, long updateValue) { - checkState(isOpen.get(), DB_NOT_OPEN); - return partitioner.getPartition(counterName, counterName). - counterCompareAndSet(counterName, expectedValue, updateValue); - - } - - @Override - public CompletableFuture<Long> queueSize(String queueName) { - checkState(isOpen.get(), DB_NOT_OPEN); - return partitioner.getPartition(queueName, queueName).queueSize(queueName); - } - - @Override - public CompletableFuture<Void> queuePush(String queueName, byte[] entry) { - checkState(isOpen.get(), DB_NOT_OPEN); - return partitioner.getPartition(queueName, queueName).queuePush(queueName, entry); - } - - @Override - public CompletableFuture<byte[]> queuePop(String queueName) { - checkState(isOpen.get(), DB_NOT_OPEN); - return partitioner.getPartition(queueName, queueName).queuePop(queueName); - } - - @Override - public CompletableFuture<byte[]> queuePeek(String queueName) { - checkState(isOpen.get(), DB_NOT_OPEN); - return partitioner.getPartition(queueName, queueName).queuePeek(queueName); - } - - @Override - public CompletableFuture<CommitResponse> prepareAndCommit(Transaction transaction) { - Map<Database, Transaction> subTransactions = createSubTransactions(transaction); - if (subTransactions.isEmpty()) { - return CompletableFuture.completedFuture(CommitResponse.success(ImmutableList.of())); - } else if (subTransactions.size() == 1) { - Entry<Database, Transaction> entry = - subTransactions.entrySet().iterator().next(); - return entry.getKey().prepareAndCommit(entry.getValue()); - } else { - if (transactionManager == null) { - throw new IllegalStateException("TransactionManager is not initialized"); - } - return transactionManager.execute(transaction); - } - } - - @Override - public CompletableFuture<Boolean> prepare(Transaction transaction) { - Map<Database, Transaction> subTransactions = createSubTransactions(transaction); - AtomicBoolean status = new AtomicBoolean(true); - return CompletableFuture.allOf(subTransactions.entrySet() - .stream() - .map(entry -> entry - .getKey() - .prepare(entry.getValue()) - .thenApply(v -> status.compareAndSet(true, v))) - .toArray(CompletableFuture[]::new)) - .thenApply(v -> status.get()); - } - - @Override - public CompletableFuture<CommitResponse> commit(Transaction transaction) { - Map<Database, Transaction> subTransactions = createSubTransactions(transaction); - AtomicBoolean success = new AtomicBoolean(true); - List<UpdateResult<String, byte[]>> allUpdates = Lists.newArrayList(); - return CompletableFuture.allOf(subTransactions.entrySet() - .stream() - .map(entry -> entry.getKey().commit(entry.getValue()) - .thenAccept(response -> { - success.set(success.get() && response.success()); - if (success.get()) { - allUpdates.addAll(response.updates()); - } - })) - .toArray(CompletableFuture[]::new)) - .thenApply(v -> success.get() ? - CommitResponse.success(allUpdates) : CommitResponse.failure()); - } - - @Override - public CompletableFuture<Boolean> rollback(Transaction transaction) { - Map<Database, Transaction> subTransactions = createSubTransactions(transaction); - return CompletableFuture.allOf(subTransactions.entrySet() - .stream() - .map(entry -> entry.getKey().rollback(entry.getValue())) - .toArray(CompletableFuture[]::new)) - .thenApply(v -> true); - } - - @Override - public CompletableFuture<Database> open() { - return CompletableFuture.allOf(partitions - .stream() - .map(Database::open) - .toArray(CompletableFuture[]::new)) - .thenApply(v -> { - isOpen.set(true); - return this; - }); - } - - @Override - public CompletableFuture<Void> close() { - checkState(isOpen.get(), DB_NOT_OPEN); - return CompletableFuture.allOf(partitions - .stream() - .map(database -> database.close()) - .toArray(CompletableFuture[]::new)); - } - - @Override - public boolean isClosed() { - return !isOpen.get(); - } - - @Override - public String name() { - return name; - } - - @Override - public Cluster cluster() { - throw new UnsupportedOperationException(); - } - - @Override - public Database addStartupTask(Task<CompletableFuture<Void>> task) { - throw new UnsupportedOperationException(); - } - - @Override - public Database addShutdownTask(Task<CompletableFuture<Void>> task) { - throw new UnsupportedOperationException(); - } - - @Override - public ResourceState state() { - throw new UnsupportedOperationException(); - } - - private Map<Database, Transaction> createSubTransactions( - Transaction transaction) { - Map<Database, List<DatabaseUpdate>> perPartitionUpdates = Maps.newHashMap(); - for (DatabaseUpdate update : transaction.updates()) { - Database partition = partitioner.getPartition(update.mapName(), update.key()); - List<DatabaseUpdate> partitionUpdates = - perPartitionUpdates.computeIfAbsent(partition, k -> Lists.newLinkedList()); - partitionUpdates.add(update); - } - Map<Database, Transaction> subTransactions = Maps.newHashMap(); - perPartitionUpdates.forEach((k, v) -> subTransactions.put(k, new DefaultTransaction(transaction.id(), v))); - return subTransactions; - } - - protected void setTransactionManager(TransactionManager transactionManager) { - this.transactionManager = transactionManager; - } - - @Override - public void registerConsumer(Consumer<StateMachineUpdate> consumer) { - partitions.forEach(p -> p.registerConsumer(consumer)); - } - - @Override - public void unregisterConsumer(Consumer<StateMachineUpdate> consumer) { - partitions.forEach(p -> p.unregisterConsumer(consumer)); - } -} - diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/Partitioner.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/Partitioner.java deleted file mode 100644 index de630b90..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/Partitioner.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -/** - * Partitioner is responsible for mapping keys to individual database partitions. - * - * @param <K> key type. - */ -public interface Partitioner<K> { - - /** - * Returns the database partition. - * @param mapName map name - * @param key key - * @return Database partition - */ - Database getPartition(String mapName, K key); -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/Result.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/Result.java deleted file mode 100644 index 856f706d..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/Result.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import static com.google.common.base.MoreObjects.toStringHelper; - -import java.util.Objects; - -/** - * Result of a database update operation. - * - * @param <V> return value type - */ -public final class Result<V> { - - public enum Status { - /** - * Indicates a successful update. - */ - OK, - - /** - * Indicates a failure due to underlying state being locked by another transaction. - */ - LOCKED - } - - private final Status status; - private final V value; - - /** - * Creates a new Result instance with the specified value with status set to Status.OK. - * - * @param <V> result value type - * @param value result value - * @return Result instance - */ - public static <V> Result<V> ok(V value) { - return new Result<>(value, Status.OK); - } - - /** - * Creates a new Result instance with status set to Status.LOCKED. - * - * @param <V> result value type - * @return Result instance - */ - public static <V> Result<V> locked() { - return new Result<>(null, Status.LOCKED); - } - - private Result(V value, Status status) { - this.value = value; - this.status = status; - } - - /** - * Returns true if this result indicates a successful execution i.e status is Status.OK. - * - * @return true if successful, false otherwise - */ - public boolean success() { - return status == Status.OK; - } - - /** - * Returns the status of database update operation. - * - * @return database update status - */ - public Status status() { - return status; - } - - /** - * Returns the return value for the update. - * - * @return value returned by database update. If the status is another - * other than Status.OK, this returns a null - */ - public V value() { - return value; - } - - @Override - public int hashCode() { - return Objects.hash(value, status); - } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object other) { - if (!(other instanceof Result)) { - return false; - } - Result<V> that = (Result<V>) other; - return Objects.equals(this.value, that.value) && - Objects.equals(this.status, that.status); - } - - @Override - public String toString() { - return toStringHelper(this) - .add("status", status) - .add("value", value) - .toString(); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/SimpleKeyHashPartitioner.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/SimpleKeyHashPartitioner.java deleted file mode 100644 index 40864286..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/SimpleKeyHashPartitioner.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import java.util.List; - -/** - * A simple Partitioner for mapping keys to database partitions. - * <p> - * This class uses a md5 hash based hashing scheme for hashing the key to - * a partition. - * - */ -public class SimpleKeyHashPartitioner extends DatabasePartitioner { - - public SimpleKeyHashPartitioner(List<Database> partitions) { - super(partitions); - } - - @Override - public Database getPartition(String mapName, String key) { - return partitions.get(hash(key) % partitions.size()); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/SimpleTableHashPartitioner.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/SimpleTableHashPartitioner.java deleted file mode 100644 index 8dc26e0f..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/SimpleTableHashPartitioner.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.consistent.impl; - -import java.util.List; - -/** - * A simple Partitioner that uses the map name hash to - * pick a partition. - * <p> - * This class uses a md5 hash based hashing scheme for hashing the map name to - * a partition. This partitioner maps all keys for a map to the same database - * partition. - */ -public class SimpleTableHashPartitioner extends DatabasePartitioner { - - public SimpleTableHashPartitioner(List<Database> partitions) { - super(partitions); - } - - @Override - public Database getPartition(String mapName, String key) { - return partitions.get(hash(mapName) % partitions.size()); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/StateMachineUpdate.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/StateMachineUpdate.java deleted file mode 100644 index 72356d0b..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/StateMachineUpdate.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import static com.google.common.base.MoreObjects.toStringHelper; - -/** - * Representation of a state machine update. - */ -public class StateMachineUpdate { - - /** - * Target data structure type this update is for. - */ - enum Target { - /** - * Update is for a map. - */ - MAP_UPDATE, - - /** - * Update is a transaction commit. - */ - TX_COMMIT, - - /** - * Update is a queue push. - */ - QUEUE_PUSH, - - /** - * Update is for some other operation. - */ - OTHER - } - - private final String operationName; - private final Object input; - private final Object output; - - public StateMachineUpdate(String operationName, Object input, Object output) { - this.operationName = operationName; - this.input = input; - this.output = output; - } - - public Target target() { - // FIXME: This check is brittle - if (operationName.contains("mapUpdate")) { - return Target.MAP_UPDATE; - } else if (operationName.contains("commit") || operationName.contains("prepareAndCommit")) { - return Target.TX_COMMIT; - } else if (operationName.contains("queuePush")) { - return Target.QUEUE_PUSH; - } else { - return Target.OTHER; - } - } - - @SuppressWarnings("unchecked") - public <T> T input() { - return (T) input; - } - - @SuppressWarnings("unchecked") - public <T> T output() { - return (T) output; - } - - @Override - public String toString() { - return toStringHelper(this) - .add("name", operationName) - .add("input", input) - .add("output", output) - .toString(); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/TransactionManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/TransactionManager.java deleted file mode 100644 index fc6e58d0..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/TransactionManager.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.Arrays; -import java.util.Collection; -import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; - -import org.onlab.util.KryoNamespace; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.AsyncConsistentMap; -import org.onosproject.store.service.ConsistentMapBuilder; -import org.onosproject.store.service.DatabaseUpdate; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.Transaction; -import org.onosproject.store.service.Versioned; -import org.onosproject.store.service.Transaction.State; - -import com.google.common.collect.ImmutableList; - -/** - * Agent that runs the two phase commit protocol. - */ -public class TransactionManager { - - private static final KryoNamespace KRYO_NAMESPACE = KryoNamespace.newBuilder() - .register(KryoNamespaces.BASIC) - .nextId(KryoNamespace.FLOATING_ID) - .register(Versioned.class) - .register(DatabaseUpdate.class) - .register(DatabaseUpdate.Type.class) - .register(DefaultTransaction.class) - .register(Transaction.State.class) - .build(); - - private final Serializer serializer = Serializer.using(Arrays.asList(KRYO_NAMESPACE)); - private final Database database; - private final AsyncConsistentMap<Long, Transaction> transactions; - - /** - * Constructs a new TransactionManager for the specified database instance. - * - * @param database database - * @param mapBuilder builder for ConsistentMap instances - */ - public TransactionManager(Database database, ConsistentMapBuilder<Long, Transaction> mapBuilder) { - this.database = checkNotNull(database, "database cannot be null"); - this.transactions = mapBuilder.withName("onos-transactions") - .withSerializer(serializer) - .buildAsyncMap(); - } - - /** - * Executes the specified transaction by employing a two phase commit protocol. - * - * @param transaction transaction to commit - * @return transaction result. Result value true indicates a successful commit, false - * indicates abort - */ - public CompletableFuture<CommitResponse> execute(Transaction transaction) { - // clean up if this transaction in already in a terminal state. - if (transaction.state() == Transaction.State.COMMITTED || - transaction.state() == Transaction.State.ROLLEDBACK) { - return transactions.remove(transaction.id()).thenApply(v -> CommitResponse.success(ImmutableList.of())); - } else if (transaction.state() == Transaction.State.COMMITTING) { - return commit(transaction); - } else if (transaction.state() == Transaction.State.ROLLINGBACK) { - return rollback(transaction).thenApply(v -> CommitResponse.success(ImmutableList.of())); - } else { - return prepare(transaction).thenCompose(v -> v ? commit(transaction) : rollback(transaction)); - } - } - - - /** - * Returns all transactions in the system. - * - * @return future for a collection of transactions - */ - public CompletableFuture<Collection<Transaction>> getTransactions() { - return transactions.values().thenApply(c -> { - Collection<Transaction> txns = c.stream().map(v -> v.value()).collect(Collectors.toList()); - return txns; - }); - } - - private CompletableFuture<Boolean> prepare(Transaction transaction) { - return transactions.put(transaction.id(), transaction) - .thenCompose(v -> database.prepare(transaction)) - .thenCompose(status -> transactions.put( - transaction.id(), - transaction.transition(status ? State.COMMITTING : State.ROLLINGBACK)) - .thenApply(v -> status)); - } - - private CompletableFuture<CommitResponse> commit(Transaction transaction) { - return database.commit(transaction) - .whenComplete((r, e) -> transactions.put( - transaction.id(), - transaction.transition(Transaction.State.COMMITTED))); - } - - private CompletableFuture<CommitResponse> rollback(Transaction transaction) { - return database.rollback(transaction) - .thenCompose(v -> transactions.put( - transaction.id(), - transaction.transition(Transaction.State.ROLLEDBACK))) - .thenApply(v -> CommitResponse.failure()); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/UpdateResult.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/UpdateResult.java deleted file mode 100644 index 50b78dd4..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/UpdateResult.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import java.util.function.Function; - -import org.onosproject.store.service.MapEvent; -import org.onosproject.store.service.Versioned; - -/** - * Result of a update operation. - * <p> - * Both old and new values are accessible along with a flag that indicates if the - * the value was updated. If flag is false, oldValue and newValue both - * point to the same unmodified value. - * @param <V> result type - */ -public class UpdateResult<K, V> { - - private final boolean updated; - private final String mapName; - private final K key; - private final Versioned<V> oldValue; - private final Versioned<V> newValue; - - public UpdateResult(boolean updated, String mapName, K key, Versioned<V> oldValue, Versioned<V> newValue) { - this.updated = updated; - this.mapName = mapName; - this.key = key; - this.oldValue = oldValue; - this.newValue = newValue; - } - - public boolean updated() { - return updated; - } - - public String mapName() { - return mapName; - } - - public K key() { - return key; - } - - public Versioned<V> oldValue() { - return oldValue; - } - - public Versioned<V> newValue() { - return newValue; - } - - public <K1, V1> UpdateResult<K1, V1> map(Function<K, K1> keyTransform, Function<V, V1> valueMapper) { - return new UpdateResult<>(updated, - mapName, - keyTransform.apply(key), - oldValue == null ? null : oldValue.map(valueMapper), - newValue == null ? null : newValue.map(valueMapper)); - } - - public MapEvent<K, V> toMapEvent() { - if (!updated) { - return null; - } else { - MapEvent.Type eventType = oldValue == null ? - MapEvent.Type.INSERT : newValue == null ? MapEvent.Type.REMOVE : MapEvent.Type.UPDATE; - Versioned<V> eventValue = eventType == MapEvent.Type.REMOVE ? oldValue : newValue; - return new MapEvent<>(mapName(), eventType, key(), eventValue); - } - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/package-info.java deleted file mode 100644 index 3dae86b5..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of partitioned and distributed store facility capable of - * providing consistent update semantics. - */ -package org.onosproject.store.consistent.impl;
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/AppIdEvent.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/AppIdEvent.java deleted file mode 100644 index 9f021b13..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/AppIdEvent.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.core.impl; - -import org.onosproject.core.ApplicationId; -import org.onosproject.event.AbstractEvent; - -/** - * Application ID event. - */ -public class AppIdEvent extends AbstractEvent<AppIdEvent.Type, ApplicationId> { - - public enum Type { - APP_REGISTERED - } - - protected AppIdEvent(Type type, ApplicationId subject) { - super(type, subject); - } - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/AppIdStoreDelegate.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/AppIdStoreDelegate.java deleted file mode 100644 index 6240a311..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/AppIdStoreDelegate.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.core.impl; - -import org.onosproject.store.StoreDelegate; - -/** - * Application ID store delegate. - */ -public interface AppIdStoreDelegate extends StoreDelegate<AppIdEvent> { -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/ConsistentApplicationIdStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/ConsistentApplicationIdStore.java deleted file mode 100644 index 7c3769a3..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/ConsistentApplicationIdStore.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.core.impl; - -import static org.slf4j.LoggerFactory.getLogger; - -import java.util.Map; -import java.util.Set; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onlab.util.Tools; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.ApplicationIdStore; -import org.onosproject.core.DefaultApplicationId; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.AtomicCounter; -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.StorageException; -import org.onosproject.store.service.StorageService; -import org.onosproject.store.service.Versioned; -import org.slf4j.Logger; - -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Maps; - -/** - * ApplicationIdStore implementation on top of {@code AtomicCounter} - * and {@code ConsistentMap} primitives. - */ -@Component(immediate = true, enabled = true) -@Service -public class ConsistentApplicationIdStore implements ApplicationIdStore { - - private final Logger log = getLogger(getClass()); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - private AtomicCounter appIdCounter; - private ConsistentMap<String, ApplicationId> registeredIds; - private Map<String, ApplicationId> nameToAppIdCache = Maps.newConcurrentMap(); - private Map<Short, ApplicationId> idToAppIdCache = Maps.newConcurrentMap(); - - private static final Serializer SERIALIZER = Serializer.using(new KryoNamespace.Builder() - .register(KryoNamespaces.API) - .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID) - .build()); - - @Activate - public void activate() { - appIdCounter = storageService.atomicCounterBuilder() - .withName("onos-app-id-counter") - .withPartitionsDisabled() - .build(); - - registeredIds = storageService.<String, ApplicationId>consistentMapBuilder() - .withName("onos-app-ids") - .withPartitionsDisabled() - .withSerializer(SERIALIZER) - .build(); - - primeAppIds(); - - log.info("Started"); - } - - @Deactivate - public void deactivate() { - log.info("Stopped"); - } - - @Override - public Set<ApplicationId> getAppIds() { - // TODO: Rework this when we have notification support in ConsistentMap. - primeAppIds(); - return ImmutableSet.copyOf(nameToAppIdCache.values()); - } - - @Override - public ApplicationId getAppId(Short id) { - if (!idToAppIdCache.containsKey(id)) { - primeAppIds(); - } - return idToAppIdCache.get(id); - } - - @Override - public ApplicationId getAppId(String name) { - ApplicationId appId = nameToAppIdCache.computeIfAbsent(name, key -> { - Versioned<ApplicationId> existingAppId = registeredIds.get(key); - return existingAppId != null ? existingAppId.value() : null; - }); - if (appId != null) { - idToAppIdCache.putIfAbsent(appId.id(), appId); - } - return appId; - } - - @Override - public ApplicationId registerApplication(String name) { - ApplicationId appId = nameToAppIdCache.computeIfAbsent(name, key -> { - Versioned<ApplicationId> existingAppId = registeredIds.get(name); - if (existingAppId == null) { - int id = Tools.retryable(appIdCounter::incrementAndGet, StorageException.class, 1, 2000) - .get() - .intValue(); - DefaultApplicationId newAppId = new DefaultApplicationId(id, name); - existingAppId = registeredIds.putIfAbsent(name, newAppId); - if (existingAppId != null) { - return existingAppId.value(); - } else { - return newAppId; - } - } else { - return existingAppId.value(); - } - }); - idToAppIdCache.putIfAbsent(appId.id(), appId); - return appId; - } - - private void primeAppIds() { - registeredIds.values() - .stream() - .map(Versioned::value) - .forEach(appId -> { - nameToAppIdCache.putIfAbsent(appId.name(), appId); - idToAppIdCache.putIfAbsent(appId.id(), appId); - }); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/ConsistentIdBlockStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/ConsistentIdBlockStore.java deleted file mode 100644 index c6f48a44..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/ConsistentIdBlockStore.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.core.impl; - -import com.google.common.collect.Maps; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.Tools; -import org.onosproject.core.IdBlock; -import org.onosproject.core.IdBlockStore; -import org.onosproject.store.service.AtomicCounter; -import org.onosproject.store.service.StorageException; -import org.onosproject.store.service.StorageService; -import org.slf4j.Logger; - -import java.util.Map; - -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Implementation of {@code IdBlockStore} using {@code AtomicCounter}. - */ -@Component(immediate = true, enabled = true) -@Service -public class ConsistentIdBlockStore implements IdBlockStore { - - private static final int MAX_TRIES = 5; - private static final int RETRY_DELAY_MS = 2_000; - - private final Logger log = getLogger(getClass()); - private final Map<String, AtomicCounter> topicCounters = Maps.newConcurrentMap(); - - private static final long DEFAULT_BLOCK_SIZE = 0x100000L; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - @Activate - public void activate() { - log.info("Started"); - } - - @Deactivate - public void deactivate() { - log.info("Stopped"); - } - - @Override - public IdBlock getIdBlock(String topic) { - AtomicCounter counter = topicCounters - .computeIfAbsent(topic, - name -> storageService.atomicCounterBuilder() - .withName(name) - .build()); - Long blockBase = Tools.retryable(counter::getAndAdd, - StorageException.class, - MAX_TRIES, - RETRY_DELAY_MS).apply(DEFAULT_BLOCK_SIZE); - return new IdBlock(blockBase, DEFAULT_BLOCK_SIZE); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/LogicalClockManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/LogicalClockManager.java deleted file mode 100644 index 6a667e32..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/LogicalClockManager.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.core.impl; - -import static org.slf4j.LoggerFactory.getLogger; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onosproject.store.Timestamp; -import org.onosproject.store.impl.LogicalTimestamp; -import org.onosproject.store.service.AtomicCounter; -import org.onosproject.store.service.LogicalClockService; -import org.onosproject.store.service.StorageService; -import org.slf4j.Logger; - -/** - * LogicalClockService implementation based on a AtomicCounter. - */ -@Component(immediate = true, enabled = true) -@Service -public class LogicalClockManager implements LogicalClockService { - - private final Logger log = getLogger(getClass()); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - private static final String SYSTEM_LOGICAL_CLOCK_COUNTER_NAME = "sys-clock-counter"; - private AtomicCounter atomicCounter; - - @Activate - public void activate() { - atomicCounter = storageService.atomicCounterBuilder() - .withName(SYSTEM_LOGICAL_CLOCK_COUNTER_NAME) - .withPartitionsDisabled() - .build(); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - log.info("Stopped"); - } - - @Override - public Timestamp getTimestamp() { - return new LogicalTimestamp(atomicCounter.incrementAndGet()); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/package-info.java deleted file mode 100644 index bb758b10..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/core/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of a distributed application ID registry store using Hazelcast. - */ -package org.onosproject.store.core.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceAntiEntropyAdvertisement.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceAntiEntropyAdvertisement.java deleted file mode 100644 index 491d1334..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceAntiEntropyAdvertisement.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.Map; - -import org.onosproject.cluster.NodeId; -import org.onosproject.net.DeviceId; -import org.onosproject.store.Timestamp; - - -/** - * Device Advertisement message. - */ -public class DeviceAntiEntropyAdvertisement { - - private final NodeId sender; - private final Map<DeviceFragmentId, Timestamp> deviceFingerPrints; - private final Map<PortFragmentId, Timestamp> portFingerPrints; - private final Map<DeviceId, Timestamp> offline; - - - public DeviceAntiEntropyAdvertisement(NodeId sender, - Map<DeviceFragmentId, Timestamp> devices, - Map<PortFragmentId, Timestamp> ports, - Map<DeviceId, Timestamp> offline) { - this.sender = checkNotNull(sender); - this.deviceFingerPrints = checkNotNull(devices); - this.portFingerPrints = checkNotNull(ports); - this.offline = checkNotNull(offline); - } - - public NodeId sender() { - return sender; - } - - public Map<DeviceFragmentId, Timestamp> deviceFingerPrints() { - return deviceFingerPrints; - } - - public Map<PortFragmentId, Timestamp> ports() { - return portFingerPrints; - } - - public Map<DeviceId, Timestamp> offline() { - return offline; - } - - // For serializer - @SuppressWarnings("unused") - private DeviceAntiEntropyAdvertisement() { - this.sender = null; - this.deviceFingerPrints = null; - this.portFingerPrints = null; - this.offline = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceAntiEntropyRequest.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceAntiEntropyRequest.java deleted file mode 100644 index a719a770..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceAntiEntropyRequest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.Collection; - -import org.onosproject.cluster.NodeId; - -/** - * Message to request for other peers information. - */ -public class DeviceAntiEntropyRequest { - - private final NodeId sender; - private final Collection<DeviceFragmentId> devices; - private final Collection<PortFragmentId> ports; - - public DeviceAntiEntropyRequest(NodeId sender, - Collection<DeviceFragmentId> devices, - Collection<PortFragmentId> ports) { - - this.sender = checkNotNull(sender); - this.devices = checkNotNull(devices); - this.ports = checkNotNull(ports); - } - - public NodeId sender() { - return sender; - } - - public Collection<DeviceFragmentId> devices() { - return devices; - } - - public Collection<PortFragmentId> ports() { - return ports; - } - - // For serializer - @SuppressWarnings("unused") - private DeviceAntiEntropyRequest() { - this.sender = null; - this.devices = null; - this.ports = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceClockManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceClockManager.java deleted file mode 100644 index da5bd5de..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceClockManager.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import static org.slf4j.LoggerFactory.getLogger; - -import java.util.concurrent.atomic.AtomicLong; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.NodeId; -import org.onosproject.mastership.MastershipTerm; -import org.onosproject.mastership.MastershipTermService; -import org.onosproject.net.DeviceId; -import org.onosproject.net.device.DeviceClockService; -import org.onosproject.store.Timestamp; -import org.onosproject.store.impl.MastershipBasedTimestamp; -import org.slf4j.Logger; - -/** - * Clock service to issue Timestamp based on Device Mastership. - */ -@Component(immediate = true) -@Service -public class DeviceClockManager implements DeviceClockService { - - private final Logger log = getLogger(getClass()); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipTermService mastershipTermService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - protected NodeId localNodeId; - - private final AtomicLong ticker = new AtomicLong(0); - - @Activate - public void activate() { - localNodeId = clusterService.getLocalNode().id(); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - log.info("Stopped"); - } - - @Override - public Timestamp getTimestamp(DeviceId deviceId) { - MastershipTerm term = mastershipTermService.getMastershipTerm(deviceId); - if (term == null || !localNodeId.equals(term.master())) { - throw new IllegalStateException("Requesting timestamp for " + deviceId + " without mastership"); - } - return new MastershipBasedTimestamp(term.termNumber(), ticker.incrementAndGet()); - } - - @Override - public boolean isTimestampAvailable(DeviceId deviceId) { - MastershipTerm term = mastershipTermService.getMastershipTerm(deviceId); - return term != null && localNodeId.equals(term.master()); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceDescriptions.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceDescriptions.java deleted file mode 100644 index 23206725..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceDescriptions.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.onosproject.net.DefaultAnnotations.union; - -import java.util.Collections; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import org.onosproject.net.PortNumber; -import org.onosproject.net.SparseAnnotations; -import org.onosproject.net.device.DefaultDeviceDescription; -import org.onosproject.net.device.DefaultPortDescription; -import org.onosproject.net.device.DeviceDescription; -import org.onosproject.net.device.OchPortDescription; -import org.onosproject.net.device.OduCltPortDescription; -import org.onosproject.net.device.OmsPortDescription; -import org.onosproject.net.device.PortDescription; -import org.onosproject.store.Timestamp; -import org.onosproject.store.impl.Timestamped; - -/* - * Collection of Description of a Device and Ports, given from a Provider. - */ -class DeviceDescriptions { - - private volatile Timestamped<DeviceDescription> deviceDesc; - - private final ConcurrentMap<PortNumber, Timestamped<PortDescription>> portDescs; - - public DeviceDescriptions(Timestamped<DeviceDescription> desc) { - this.deviceDesc = checkNotNull(desc); - this.portDescs = new ConcurrentHashMap<>(); - } - - public Timestamp getLatestTimestamp() { - Timestamp latest = deviceDesc.timestamp(); - for (Timestamped<PortDescription> desc : portDescs.values()) { - if (desc.timestamp().compareTo(latest) > 0) { - latest = desc.timestamp(); - } - } - return latest; - } - - public Timestamped<DeviceDescription> getDeviceDesc() { - return deviceDesc; - } - - public Timestamped<PortDescription> getPortDesc(PortNumber number) { - return portDescs.get(number); - } - - public Map<PortNumber, Timestamped<PortDescription>> getPortDescs() { - return Collections.unmodifiableMap(portDescs); - } - - /** - * Puts DeviceDescription, merging annotations as necessary. - * - * @param newDesc new DeviceDescription - */ - public void putDeviceDesc(Timestamped<DeviceDescription> newDesc) { - Timestamped<DeviceDescription> oldOne = deviceDesc; - Timestamped<DeviceDescription> newOne = newDesc; - if (oldOne != null) { - SparseAnnotations merged = union(oldOne.value().annotations(), - newDesc.value().annotations()); - newOne = new Timestamped<>( - new DefaultDeviceDescription(newDesc.value(), merged), - newDesc.timestamp()); - } - deviceDesc = newOne; - } - - /** - * Puts PortDescription, merging annotations as necessary. - * - * @param newDesc new PortDescription - */ - public void putPortDesc(Timestamped<PortDescription> newDesc) { - Timestamped<PortDescription> oldOne = portDescs.get(newDesc.value().portNumber()); - Timestamped<PortDescription> newOne = newDesc; - if (oldOne != null) { - SparseAnnotations merged = union(oldOne.value().annotations(), - newDesc.value().annotations()); - newOne = null; - switch (newDesc.value().type()) { - case OMS: - OmsPortDescription omsDesc = (OmsPortDescription) (newDesc.value()); - newOne = new Timestamped<>( - new OmsPortDescription( - omsDesc, omsDesc.minFrequency(), omsDesc.maxFrequency(), omsDesc.grid(), merged), - newDesc.timestamp()); - break; - case OCH: - OchPortDescription ochDesc = (OchPortDescription) (newDesc.value()); - newOne = new Timestamped<>( - new OchPortDescription( - ochDesc, ochDesc.signalType(), ochDesc.isTunable(), ochDesc.lambda(), merged), - newDesc.timestamp()); - break; - case ODUCLT: - OduCltPortDescription ocDesc = (OduCltPortDescription) (newDesc.value()); - newOne = new Timestamped<>( - new OduCltPortDescription( - ocDesc, ocDesc.signalType(), merged), - newDesc.timestamp()); - break; - default: - newOne = new Timestamped<>( - new DefaultPortDescription(newDesc.value(), merged), - newDesc.timestamp()); - } - } - portDescs.put(newOne.value().portNumber(), newOne); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceFragmentId.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceFragmentId.java deleted file mode 100644 index 214f4c23..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceFragmentId.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import java.util.Objects; - -import org.onosproject.net.DeviceId; -import org.onosproject.net.provider.ProviderId; - -import com.google.common.base.MoreObjects; - -/** - * Identifier for DeviceDesctiption from a Provider. - */ -public final class DeviceFragmentId { - public final ProviderId providerId; - public final DeviceId deviceId; - - public DeviceFragmentId(DeviceId deviceId, ProviderId providerId) { - this.providerId = providerId; - this.deviceId = deviceId; - } - - @Override - public int hashCode() { - return Objects.hash(providerId, deviceId); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof DeviceFragmentId)) { - return false; - } - DeviceFragmentId that = (DeviceFragmentId) obj; - return Objects.equals(this.deviceId, that.deviceId) && - Objects.equals(this.providerId, that.providerId); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("providerId", providerId) - .add("deviceId", deviceId) - .toString(); - } - - // for serializer - @SuppressWarnings("unused") - private DeviceFragmentId() { - this.providerId = null; - this.deviceId = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceInjectedEvent.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceInjectedEvent.java deleted file mode 100644 index 3c3bbb65..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceInjectedEvent.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import com.google.common.base.MoreObjects; -import org.onosproject.net.DeviceId; -import org.onosproject.net.device.DeviceDescription; -import org.onosproject.net.provider.ProviderId; - -public class DeviceInjectedEvent { - private final ProviderId providerId; - private final DeviceId deviceId; - private final DeviceDescription deviceDescription; - - protected DeviceInjectedEvent( - ProviderId providerId, - DeviceId deviceId, - DeviceDescription deviceDescription) { - this.providerId = providerId; - this.deviceId = deviceId; - this.deviceDescription = deviceDescription; - } - - public DeviceId deviceId() { - return deviceId; - } - - public ProviderId providerId() { - return providerId; - } - - public DeviceDescription deviceDescription() { - return deviceDescription; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("providerId", providerId) - .add("deviceId", deviceId) - .add("deviceDescription", deviceDescription) - .toString(); - } - - // for serializer - protected DeviceInjectedEvent() { - this.providerId = null; - this.deviceId = null; - this.deviceDescription = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceKey.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceKey.java deleted file mode 100644 index 0896bf18..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceKey.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import java.util.Objects; - -import org.onosproject.net.DeviceId; -import org.onosproject.net.provider.ProviderId; - -import com.google.common.base.MoreObjects; - -/** - * Key for DeviceDescriptions in ECDeviceStore. - */ -public class DeviceKey { - private final ProviderId providerId; - private final DeviceId deviceId; - - public DeviceKey(ProviderId providerId, DeviceId deviceId) { - this.providerId = providerId; - this.deviceId = deviceId; - } - - public ProviderId providerId() { - return providerId; - } - - public DeviceId deviceId() { - return deviceId; - } - - @Override - public int hashCode() { - return Objects.hash(providerId, deviceId); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof DeviceKey)) { - return false; - } - DeviceKey that = (DeviceKey) obj; - return Objects.equals(this.deviceId, that.deviceId) && - Objects.equals(this.providerId, that.providerId); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("providerId", providerId) - .add("deviceId", deviceId) - .toString(); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/ECDeviceStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/ECDeviceStore.java deleted file mode 100644 index 2dae55bb..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/ECDeviceStore.java +++ /dev/null @@ -1,784 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Verify.verify; -import static org.onosproject.net.DefaultAnnotations.merge; -import static org.slf4j.LoggerFactory.getLogger; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.Map.Entry; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.packet.ChassisId; -import org.onlab.util.KryoNamespace; -import org.onlab.util.SharedExecutors; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.NodeId; -import org.onosproject.mastership.MastershipService; -import org.onosproject.mastership.MastershipTermService; -import org.onosproject.net.Annotations; -import org.onosproject.net.AnnotationsUtil; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.DefaultDevice; -import org.onosproject.net.DefaultPort; -import org.onosproject.net.Device; -import org.onosproject.net.DeviceId; -import org.onosproject.net.MastershipRole; -import org.onosproject.net.OchPort; -import org.onosproject.net.OduCltPort; -import org.onosproject.net.OmsPort; -import org.onosproject.net.Port; -import org.onosproject.net.PortNumber; -import org.onosproject.net.Device.Type; -import org.onosproject.net.device.DefaultPortStatistics; -import org.onosproject.net.device.DeviceClockService; -import org.onosproject.net.device.DeviceDescription; -import org.onosproject.net.device.DeviceEvent; -import org.onosproject.net.device.DeviceStore; -import org.onosproject.net.device.DeviceStoreDelegate; -import org.onosproject.net.device.OchPortDescription; -import org.onosproject.net.device.OduCltPortDescription; -import org.onosproject.net.device.OmsPortDescription; -import org.onosproject.net.device.PortDescription; -import org.onosproject.net.device.PortStatistics; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.impl.MastershipBasedTimestamp; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.serializers.KryoSerializer; -import org.onosproject.store.serializers.custom.DistributedStoreSerializers; -import org.onosproject.store.service.DistributedSet; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.EventuallyConsistentMapEvent; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.SetEvent; -import org.onosproject.store.service.SetEventListener; -import org.onosproject.store.service.WallClockTimestamp; - -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT; -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE; - -import org.onosproject.store.service.EventuallyConsistentMapListener; -import org.onosproject.store.service.StorageService; -import org.slf4j.Logger; - -import static org.onosproject.net.device.DeviceEvent.Type.*; -import static org.onosproject.store.device.impl.GossipDeviceStoreMessageSubjects.DEVICE_INJECTED; -import static org.onosproject.store.device.impl.GossipDeviceStoreMessageSubjects.DEVICE_REMOVE_REQ; -import static org.onosproject.store.device.impl.GossipDeviceStoreMessageSubjects.PORT_INJECTED; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.common.util.concurrent.Futures; - -/** - * Manages the inventory of devices using a {@code EventuallyConsistentMap}. - */ -@Component(immediate = true, enabled = false) -@Service -public class ECDeviceStore - extends AbstractStore<DeviceEvent, DeviceStoreDelegate> - implements DeviceStore { - - private final Logger log = getLogger(getClass()); - - private static final String DEVICE_NOT_FOUND = "Device with ID %s not found"; - - private final Map<DeviceId, Device> devices = Maps.newConcurrentMap(); - private final Map<DeviceId, Map<PortNumber, Port>> devicePorts = Maps.newConcurrentMap(); - Set<DeviceId> pendingAvailableChangeUpdates = Sets.newConcurrentHashSet(); - - private EventuallyConsistentMap<DeviceKey, DeviceDescription> deviceDescriptions; - private EventuallyConsistentMap<PortKey, PortDescription> portDescriptions; - private EventuallyConsistentMap<DeviceId, Map<PortNumber, PortStatistics>> devicePortStats; - private EventuallyConsistentMap<DeviceId, Map<PortNumber, PortStatistics>> devicePortDeltaStats; - - private DistributedSet<DeviceId> availableDevices; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipService mastershipService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipTermService mastershipTermService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected DeviceClockService deviceClockService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterCommunicationService clusterCommunicator; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - private NodeId localNodeId; - private EventuallyConsistentMapListener<DeviceKey, DeviceDescription> deviceUpdateListener = - new InternalDeviceChangeEventListener(); - private EventuallyConsistentMapListener<PortKey, PortDescription> portUpdateListener = - new InternalPortChangeEventListener(); - private final EventuallyConsistentMapListener<DeviceId, Map<PortNumber, PortStatistics>> portStatsListener = - new InternalPortStatsListener(); - private final SetEventListener<DeviceId> deviceStatusTracker = - new InternalDeviceStatusTracker(); - - protected static final KryoSerializer SERIALIZER = new KryoSerializer() { - @Override - protected void setupKryoPool() { - serializerPool = KryoNamespace.newBuilder() - .register(DistributedStoreSerializers.STORE_COMMON) - .nextId(DistributedStoreSerializers.STORE_CUSTOM_BEGIN) - .register(DeviceInjectedEvent.class) - .register(PortInjectedEvent.class) - .build(); - } - }; - - protected static final KryoNamespace.Builder SERIALIZER_BUILDER = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .register(DeviceKey.class) - .register(PortKey.class) - .register(DeviceKey.class) - .register(PortKey.class) - .register(MastershipBasedTimestamp.class); - - @Activate - public void activate() { - localNodeId = clusterService.getLocalNode().id(); - - deviceDescriptions = storageService.<DeviceKey, DeviceDescription>eventuallyConsistentMapBuilder() - .withName("onos-device-descriptions") - .withSerializer(SERIALIZER_BUILDER) - .withTimestampProvider((k, v) -> { - try { - return deviceClockService.getTimestamp(k.deviceId()); - } catch (IllegalStateException e) { - return null; - } - }).build(); - - portDescriptions = storageService.<PortKey, PortDescription>eventuallyConsistentMapBuilder() - .withName("onos-port-descriptions") - .withSerializer(SERIALIZER_BUILDER) - .withTimestampProvider((k, v) -> { - try { - return deviceClockService.getTimestamp(k.deviceId()); - } catch (IllegalStateException e) { - return null; - } - }).build(); - - devicePortStats = storageService.<DeviceId, Map<PortNumber, PortStatistics>>eventuallyConsistentMapBuilder() - .withName("onos-port-stats") - .withSerializer(SERIALIZER_BUILDER) - .withAntiEntropyPeriod(5, TimeUnit.SECONDS) - .withTimestampProvider((k, v) -> new WallClockTimestamp()) - .withTombstonesDisabled() - .build(); - - devicePortDeltaStats = storageService.<DeviceId, Map<PortNumber, PortStatistics>> - eventuallyConsistentMapBuilder() - .withName("onos-port-stats-delta") - .withSerializer(SERIALIZER_BUILDER) - .withAntiEntropyPeriod(5, TimeUnit.SECONDS) - .withTimestampProvider((k, v) -> new WallClockTimestamp()) - .withTombstonesDisabled() - .build(); - - clusterCommunicator.addSubscriber(DEVICE_INJECTED, - SERIALIZER::decode, - this::injectDevice, - SERIALIZER::encode, - SharedExecutors.getPoolThreadExecutor()); - - clusterCommunicator.addSubscriber(PORT_INJECTED, - SERIALIZER::decode, - this::injectPort, - SERIALIZER::encode, - SharedExecutors.getPoolThreadExecutor()); - - availableDevices = storageService.<DeviceId>setBuilder() - .withName("onos-online-devices") - .withSerializer(Serializer.using(KryoNamespaces.API)) - .withPartitionsDisabled() - .withRelaxedReadConsistency() - .build(); - - deviceDescriptions.addListener(deviceUpdateListener); - portDescriptions.addListener(portUpdateListener); - devicePortStats.addListener(portStatsListener); - availableDevices.addListener(deviceStatusTracker); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - devicePortStats.removeListener(portStatsListener); - deviceDescriptions.removeListener(deviceUpdateListener); - portDescriptions.removeListener(portUpdateListener); - availableDevices.removeListener(deviceStatusTracker); - devicePortStats.destroy(); - devicePortDeltaStats.destroy(); - deviceDescriptions.destroy(); - portDescriptions.destroy(); - devices.clear(); - devicePorts.clear(); - clusterCommunicator.removeSubscriber(DEVICE_INJECTED); - clusterCommunicator.removeSubscriber(PORT_INJECTED); - log.info("Stopped"); - } - - @Override - public Iterable<Device> getDevices() { - return devices.values(); - } - - @Override - public int getDeviceCount() { - return devices.size(); - } - - @Override - public Device getDevice(DeviceId deviceId) { - return devices.get(deviceId); - } - - @Override - public DeviceEvent createOrUpdateDevice(ProviderId providerId, - DeviceId deviceId, - DeviceDescription deviceDescription) { - NodeId master = mastershipService.getMasterFor(deviceId); - if (localNodeId.equals(master)) { - deviceDescriptions.put(new DeviceKey(providerId, deviceId), deviceDescription); - return refreshDeviceCache(providerId, deviceId); - } else { - DeviceInjectedEvent deviceInjectedEvent = new DeviceInjectedEvent(providerId, deviceId, deviceDescription); - return Futures.getUnchecked( - clusterCommunicator.sendAndReceive(deviceInjectedEvent, - DEVICE_INJECTED, - SERIALIZER::encode, - SERIALIZER::decode, - master)); - } - } - - private DeviceEvent refreshDeviceCache(ProviderId providerId, DeviceId deviceId) { - AtomicReference<DeviceEvent.Type> eventType = new AtomicReference<>(); - Device device = devices.compute(deviceId, (k, existingDevice) -> { - Device newDevice = composeDevice(deviceId); - if (existingDevice == null) { - eventType.set(DEVICE_ADDED); - } else { - // We allow only certain attributes to trigger update - boolean propertiesChanged = - !Objects.equals(existingDevice.hwVersion(), newDevice.hwVersion()) || - !Objects.equals(existingDevice.swVersion(), newDevice.swVersion()) || - !Objects.equals(existingDevice.providerId(), newDevice.providerId()); - boolean annotationsChanged = - !AnnotationsUtil.isEqual(existingDevice.annotations(), newDevice.annotations()); - - // Primary providers can respond to all changes, but ancillary ones - // should respond only to annotation changes. - if ((providerId.isAncillary() && annotationsChanged) || - (!providerId.isAncillary() && (propertiesChanged || annotationsChanged))) { - boolean replaced = devices.replace(deviceId, existingDevice, newDevice); - verify(replaced, "Replacing devices cache failed. PID:%s [expected:%s, found:%s, new=%s]", - providerId, existingDevice, devices.get(deviceId), newDevice); - eventType.set(DEVICE_UPDATED); - } - } - return newDevice; - }); - if (eventType.get() != null && !providerId.isAncillary()) { - markOnline(deviceId); - } - return eventType.get() != null ? new DeviceEvent(eventType.get(), device) : null; - } - - /** - * Returns the primary providerId for a device. - * @param deviceId device identifier - * @return primary providerId - */ - private Set<ProviderId> getAllProviders(DeviceId deviceId) { - return deviceDescriptions.keySet() - .stream() - .filter(deviceKey -> deviceKey.deviceId().equals(deviceId)) - .map(deviceKey -> deviceKey.providerId()) - .collect(Collectors.toSet()); - } - - /** - * Returns the identifier for all providers for a device. - * @param deviceId device identifier - * @return set of provider identifiers - */ - private ProviderId getPrimaryProviderId(DeviceId deviceId) { - Set<ProviderId> allProviderIds = getAllProviders(deviceId); - return allProviderIds.stream() - .filter(p -> !p.isAncillary()) - .findFirst() - .orElse(Iterables.getFirst(allProviderIds, null)); - } - - /** - * Returns a Device, merging descriptions from multiple Providers. - * - * @param deviceId device identifier - * @return Device instance - */ - private Device composeDevice(DeviceId deviceId) { - - ProviderId primaryProviderId = getPrimaryProviderId(deviceId); - DeviceDescription primaryDeviceDescription = - deviceDescriptions.get(new DeviceKey(primaryProviderId, deviceId)); - - Type type = primaryDeviceDescription.type(); - String manufacturer = primaryDeviceDescription.manufacturer(); - String hwVersion = primaryDeviceDescription.hwVersion(); - String swVersion = primaryDeviceDescription.swVersion(); - String serialNumber = primaryDeviceDescription.serialNumber(); - ChassisId chassisId = primaryDeviceDescription.chassisId(); - DefaultAnnotations annotations = mergeAnnotations(deviceId); - - return new DefaultDevice(primaryProviderId, deviceId, type, manufacturer, - hwVersion, swVersion, serialNumber, - chassisId, annotations); - } - - private DeviceEvent purgeDeviceCache(DeviceId deviceId) { - Device removedDevice = devices.remove(deviceId); - if (removedDevice != null) { - getAllProviders(deviceId).forEach(p -> deviceDescriptions.remove(new DeviceKey(p, deviceId))); - return new DeviceEvent(DEVICE_REMOVED, removedDevice); - } - return null; - } - - private boolean markOnline(DeviceId deviceId) { - return availableDevices.add(deviceId); - } - - @Override - public DeviceEvent markOffline(DeviceId deviceId) { - availableDevices.remove(deviceId); - // set update listener will raise the event. - return null; - } - - @Override - public List<DeviceEvent> updatePorts(ProviderId providerId, - DeviceId deviceId, - List<PortDescription> descriptions) { - NodeId master = mastershipService.getMasterFor(deviceId); - List<DeviceEvent> deviceEvents = null; - if (localNodeId.equals(master)) { - descriptions.forEach(description -> { - PortKey portKey = new PortKey(providerId, deviceId, description.portNumber()); - portDescriptions.put(portKey, description); - }); - deviceEvents = refreshDevicePortCache(providerId, deviceId, Optional.empty()); - } else { - if (master == null) { - return Collections.emptyList(); - } - PortInjectedEvent portInjectedEvent = new PortInjectedEvent(providerId, deviceId, descriptions); - deviceEvents = Futures.getUnchecked( - clusterCommunicator.sendAndReceive(portInjectedEvent, - PORT_INJECTED, - SERIALIZER::encode, - SERIALIZER::decode, - master)); - } - return deviceEvents == null ? Collections.emptyList() : deviceEvents; - } - - private List<DeviceEvent> refreshDevicePortCache(ProviderId providerId, - DeviceId deviceId, - Optional<PortNumber> portNumber) { - Device device = devices.get(deviceId); - checkArgument(device != null, DEVICE_NOT_FOUND, deviceId); - List<DeviceEvent> events = Lists.newArrayList(); - - Map<PortNumber, Port> ports = devicePorts.computeIfAbsent(deviceId, key -> Maps.newConcurrentMap()); - List<PortDescription> descriptions = Lists.newArrayList(); - portDescriptions.entrySet().forEach(e -> { - PortKey key = e.getKey(); - PortDescription value = e.getValue(); - if (key.deviceId().equals(deviceId) && key.providerId().equals(providerId)) { - if (portNumber.isPresent()) { - if (portNumber.get().equals(key.portNumber())) { - descriptions.add(value); - } - } else { - descriptions.add(value); - } - } - }); - - for (PortDescription description : descriptions) { - final PortNumber number = description.portNumber(); - ports.compute(number, (k, existingPort) -> { - Port newPort = composePort(device, number); - if (existingPort == null) { - events.add(new DeviceEvent(PORT_ADDED, device, newPort)); - } else { - if (existingPort.isEnabled() != newPort.isEnabled() || - existingPort.type() != newPort.type() || - existingPort.portSpeed() != newPort.portSpeed() || - !AnnotationsUtil.isEqual(existingPort.annotations(), newPort.annotations())) { - events.add(new DeviceEvent(PORT_UPDATED, device, newPort)); - } - } - return newPort; - }); - } - - return events; - } - - /** - * Returns a Port, merging descriptions from multiple Providers. - * - * @param device device the port is on - * @param number port number - * @return Port instance - */ - private Port composePort(Device device, PortNumber number) { - - Map<ProviderId, PortDescription> descriptions = Maps.newHashMap(); - portDescriptions.entrySet().forEach(entry -> { - PortKey portKey = entry.getKey(); - if (portKey.deviceId().equals(device.id()) && portKey.portNumber().equals(number)) { - descriptions.put(portKey.providerId(), entry.getValue()); - } - }); - ProviderId primary = getPrimaryProviderId(device.id()); - PortDescription primaryDescription = descriptions.get(primary); - - // if no primary, assume not enabled - boolean isEnabled = false; - DefaultAnnotations annotations = DefaultAnnotations.builder().build(); - if (primaryDescription != null) { - isEnabled = primaryDescription.isEnabled(); - annotations = merge(annotations, primaryDescription.annotations()); - } - Port updated = null; - for (Entry<ProviderId, PortDescription> e : descriptions.entrySet()) { - if (e.getKey().equals(primary)) { - continue; - } - annotations = merge(annotations, e.getValue().annotations()); - updated = buildTypedPort(device, number, isEnabled, e.getValue(), annotations); - } - if (primaryDescription == null) { - return updated == null ? new DefaultPort(device, number, false, annotations) : updated; - } - return updated == null - ? buildTypedPort(device, number, isEnabled, primaryDescription, annotations) - : updated; - } - - private Port buildTypedPort(Device device, PortNumber number, boolean isEnabled, - PortDescription description, Annotations annotations) { - switch (description.type()) { - case OMS: - OmsPortDescription omsDesc = (OmsPortDescription) description; - return new OmsPort(device, number, isEnabled, omsDesc.minFrequency(), - omsDesc.maxFrequency(), omsDesc.grid(), annotations); - case OCH: - OchPortDescription ochDesc = (OchPortDescription) description; - return new OchPort(device, number, isEnabled, ochDesc.signalType(), - ochDesc.isTunable(), ochDesc.lambda(), annotations); - case ODUCLT: - OduCltPortDescription oduDesc = (OduCltPortDescription) description; - return new OduCltPort(device, number, isEnabled, oduDesc.signalType(), annotations); - default: - return new DefaultPort(device, number, isEnabled, description.type(), - description.portSpeed(), annotations); - } - } - - @Override - public DeviceEvent updatePortStatus(ProviderId providerId, - DeviceId deviceId, - PortDescription portDescription) { - portDescriptions.put(new PortKey(providerId, deviceId, portDescription.portNumber()), portDescription); - List<DeviceEvent> events = - refreshDevicePortCache(providerId, deviceId, Optional.of(portDescription.portNumber())); - return Iterables.getFirst(events, null); - } - - @Override - public List<Port> getPorts(DeviceId deviceId) { - return ImmutableList.copyOf(devicePorts.getOrDefault(deviceId, Maps.newHashMap()).values()); - } - - @Override - public Port getPort(DeviceId deviceId, PortNumber portNumber) { - return devicePorts.getOrDefault(deviceId, Maps.newHashMap()).get(portNumber); - } - - @Override - public DeviceEvent updatePortStatistics(ProviderId providerId, - DeviceId deviceId, - Collection<PortStatistics> newStatsCollection) { - - Map<PortNumber, PortStatistics> prvStatsMap = devicePortStats.get(deviceId); - Map<PortNumber, PortStatistics> newStatsMap = Maps.newHashMap(); - Map<PortNumber, PortStatistics> deltaStatsMap = Maps.newHashMap(); - - if (prvStatsMap != null) { - for (PortStatistics newStats : newStatsCollection) { - PortNumber port = PortNumber.portNumber(newStats.port()); - PortStatistics prvStats = prvStatsMap.get(port); - DefaultPortStatistics.Builder builder = DefaultPortStatistics.builder(); - PortStatistics deltaStats = builder.build(); - if (prvStats != null) { - deltaStats = calcDeltaStats(deviceId, prvStats, newStats); - } - deltaStatsMap.put(port, deltaStats); - newStatsMap.put(port, newStats); - } - } else { - for (PortStatistics newStats : newStatsCollection) { - PortNumber port = PortNumber.portNumber(newStats.port()); - newStatsMap.put(port, newStats); - } - } - devicePortDeltaStats.put(deviceId, deltaStatsMap); - devicePortStats.put(deviceId, newStatsMap); - // DeviceEvent returns null because of InternalPortStatsListener usage - return null; - } - - /** - * Calculate delta statistics by subtracting previous from new statistics. - * - * @param deviceId device indentifier - * @param prvStats previous port statistics - * @param newStats new port statistics - * @return PortStatistics - */ - public PortStatistics calcDeltaStats(DeviceId deviceId, PortStatistics prvStats, PortStatistics newStats) { - // calculate time difference - long deltaStatsSec, deltaStatsNano; - if (newStats.durationNano() < prvStats.durationNano()) { - deltaStatsNano = newStats.durationNano() - prvStats.durationNano() + TimeUnit.SECONDS.toNanos(1); - deltaStatsSec = newStats.durationSec() - prvStats.durationSec() - 1L; - } else { - deltaStatsNano = newStats.durationNano() - prvStats.durationNano(); - deltaStatsSec = newStats.durationSec() - prvStats.durationSec(); - } - DefaultPortStatistics.Builder builder = DefaultPortStatistics.builder(); - DefaultPortStatistics deltaStats = builder.setDeviceId(deviceId) - .setPort(newStats.port()) - .setPacketsReceived(newStats.packetsReceived() - prvStats.packetsReceived()) - .setPacketsSent(newStats.packetsSent() - prvStats.packetsSent()) - .setBytesReceived(newStats.bytesReceived() - prvStats.bytesReceived()) - .setBytesSent(newStats.bytesSent() - prvStats.bytesSent()) - .setPacketsRxDropped(newStats.packetsRxDropped() - prvStats.packetsRxDropped()) - .setPacketsTxDropped(newStats.packetsTxDropped() - prvStats.packetsTxDropped()) - .setPacketsRxErrors(newStats.packetsRxErrors() - prvStats.packetsRxErrors()) - .setPacketsTxErrors(newStats.packetsTxErrors() - prvStats.packetsTxErrors()) - .setDurationSec(deltaStatsSec) - .setDurationNano(deltaStatsNano) - .build(); - return deltaStats; - } - - @Override - public List<PortStatistics> getPortStatistics(DeviceId deviceId) { - Map<PortNumber, PortStatistics> portStats = devicePortStats.get(deviceId); - if (portStats == null) { - return Collections.emptyList(); - } - return ImmutableList.copyOf(portStats.values()); - } - - @Override - public List<PortStatistics> getPortDeltaStatistics(DeviceId deviceId) { - Map<PortNumber, PortStatistics> portStats = devicePortDeltaStats.get(deviceId); - if (portStats == null) { - return Collections.emptyList(); - } - return ImmutableList.copyOf(portStats.values()); - } - - @Override - public boolean isAvailable(DeviceId deviceId) { - return availableDevices.contains(deviceId); - } - - @Override - public Iterable<Device> getAvailableDevices() { - return Iterables.filter(Iterables.transform(availableDevices, devices::get), d -> d != null); - } - - @Override - public DeviceEvent removeDevice(DeviceId deviceId) { - NodeId master = mastershipService.getMasterFor(deviceId); - // if there exist a master, forward - // if there is no master, try to become one and process - boolean relinquishAtEnd = false; - if (master == null) { - final MastershipRole myRole = mastershipService.getLocalRole(deviceId); - if (myRole != MastershipRole.NONE) { - relinquishAtEnd = true; - } - log.debug("Temporarily requesting role for {} to remove", deviceId); - MastershipRole role = Futures.getUnchecked(mastershipService.requestRoleFor(deviceId)); - if (role == MastershipRole.MASTER) { - master = localNodeId; - } - } - - if (!localNodeId.equals(master)) { - log.debug("{} has control of {}, forwarding remove request", - master, deviceId); - - clusterCommunicator.unicast(deviceId, DEVICE_REMOVE_REQ, SERIALIZER::encode, master) - .whenComplete((r, e) -> { - if (e != null) { - log.error("Failed to forward {} remove request to its master", deviceId, e); - } - }); - return null; - } - - // I have control.. - DeviceEvent event = null; - final DeviceKey deviceKey = new DeviceKey(getPrimaryProviderId(deviceId), deviceId); - DeviceDescription removedDeviceDescription = - deviceDescriptions.remove(deviceKey); - if (removedDeviceDescription != null) { - event = purgeDeviceCache(deviceId); - } - - if (relinquishAtEnd) { - log.debug("Relinquishing temporary role acquired for {}", deviceId); - mastershipService.relinquishMastership(deviceId); - } - return event; - } - - private DeviceEvent injectDevice(DeviceInjectedEvent event) { - return createOrUpdateDevice(event.providerId(), event.deviceId(), event.deviceDescription()); - } - - private List<DeviceEvent> injectPort(PortInjectedEvent event) { - return updatePorts(event.providerId(), event.deviceId(), event.portDescriptions()); - } - - private DefaultAnnotations mergeAnnotations(DeviceId deviceId) { - ProviderId primaryProviderId = getPrimaryProviderId(deviceId); - DeviceDescription primaryDeviceDescription = - deviceDescriptions.get(new DeviceKey(primaryProviderId, deviceId)); - DefaultAnnotations annotations = DefaultAnnotations.builder().build(); - annotations = merge(annotations, primaryDeviceDescription.annotations()); - for (ProviderId providerId : getAllProviders(deviceId)) { - if (!providerId.equals(primaryProviderId)) { - annotations = merge(annotations, - deviceDescriptions.get(new DeviceKey(providerId, deviceId)).annotations()); - } - } - return annotations; - } - - private class InternalDeviceStatusTracker implements SetEventListener<DeviceId> { - @Override - public void event(SetEvent<DeviceId> event) { - final DeviceId deviceId = event.entry(); - final Device device = devices.get(deviceId); - if (device != null) { - notifyDelegate(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device)); - } else { - pendingAvailableChangeUpdates.add(deviceId); - } - } - } - - private class InternalDeviceChangeEventListener - implements EventuallyConsistentMapListener<DeviceKey, DeviceDescription> { - @Override - public void event(EventuallyConsistentMapEvent<DeviceKey, DeviceDescription> event) { - DeviceId deviceId = event.key().deviceId(); - ProviderId providerId = event.key().providerId(); - if (event.type() == PUT) { - notifyDelegate(refreshDeviceCache(providerId, deviceId)); - if (pendingAvailableChangeUpdates.remove(deviceId)) { - notifyDelegate(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, devices.get(deviceId))); - } - } else if (event.type() == REMOVE) { - notifyDelegate(purgeDeviceCache(deviceId)); - } - } - } - - private class InternalPortChangeEventListener - implements EventuallyConsistentMapListener<PortKey, PortDescription> { - @Override - public void event(EventuallyConsistentMapEvent<PortKey, PortDescription> event) { - DeviceId deviceId = event.key().deviceId(); - ProviderId providerId = event.key().providerId(); - PortNumber portNumber = event.key().portNumber(); - if (event.type() == PUT) { - if (devices.containsKey(deviceId)) { - List<DeviceEvent> events = refreshDevicePortCache(providerId, deviceId, Optional.of(portNumber)); - for (DeviceEvent deviceEvent : events) { - notifyDelegate(deviceEvent); - } - } - } else if (event.type() == REMOVE) { - log.warn("Unexpected port removed event"); - } - } - } - - private class InternalPortStatsListener - implements EventuallyConsistentMapListener<DeviceId, Map<PortNumber, PortStatistics>> { - @Override - public void event(EventuallyConsistentMapEvent<DeviceId, Map<PortNumber, PortStatistics>> event) { - if (event.type() == PUT) { - Device device = devices.get(event.key()); - if (device != null) { - delegate.notify(new DeviceEvent(PORT_STATS_UPDATED, device)); - } - } - } - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java deleted file mode 100644 index a9a9098e..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java +++ /dev/null @@ -1,1672 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import com.google.common.collect.FluentIterable; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -import org.apache.commons.lang3.RandomUtils; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.packet.ChassisId; -import org.onlab.util.KryoNamespace; -import org.onlab.util.NewConcurrentHashMap; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.NodeId; -import org.onosproject.mastership.MastershipService; -import org.onosproject.mastership.MastershipTerm; -import org.onosproject.mastership.MastershipTermService; -import org.onosproject.net.Annotations; -import org.onosproject.net.AnnotationsUtil; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.DefaultDevice; -import org.onosproject.net.DefaultPort; -import org.onosproject.net.Device; -import org.onosproject.net.Device.Type; -import org.onosproject.net.DeviceId; -import org.onosproject.net.MastershipRole; -import org.onosproject.net.OchPort; -import org.onosproject.net.OduCltPort; -import org.onosproject.net.OmsPort; -import org.onosproject.net.Port; -import org.onosproject.net.PortNumber; -import org.onosproject.net.device.DefaultPortStatistics; -import org.onosproject.net.device.DeviceClockService; -import org.onosproject.net.device.DeviceDescription; -import org.onosproject.net.device.DeviceEvent; -import org.onosproject.net.device.DeviceStore; -import org.onosproject.net.device.DeviceStoreDelegate; -import org.onosproject.net.device.OchPortDescription; -import org.onosproject.net.device.OduCltPortDescription; -import org.onosproject.net.device.OmsPortDescription; -import org.onosproject.net.device.PortDescription; -import org.onosproject.net.device.PortStatistics; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.Timestamp; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.cluster.messaging.ClusterMessage; -import org.onosproject.store.cluster.messaging.ClusterMessageHandler; -import org.onosproject.store.cluster.messaging.MessageSubject; -import org.onosproject.store.impl.Timestamped; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.serializers.KryoSerializer; -import org.onosproject.store.serializers.custom.DistributedStoreSerializers; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.EventuallyConsistentMapEvent; -import org.onosproject.store.service.EventuallyConsistentMapListener; -import org.onosproject.store.service.MultiValuedTimestamp; -import org.onosproject.store.service.StorageService; -import org.onosproject.store.service.WallClockTimestamp; -import org.slf4j.Logger; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Predicates.notNull; -import static com.google.common.base.Verify.verify; -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; -import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked; -import static org.onlab.util.Tools.groupedThreads; -import static org.onlab.util.Tools.minPriority; -import static org.onosproject.cluster.ControllerNodeToNodeId.toNodeId; -import static org.onosproject.net.DefaultAnnotations.merge; -import static org.onosproject.net.device.DeviceEvent.Type.*; -import static org.onosproject.store.device.impl.GossipDeviceStoreMessageSubjects.*; -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Manages inventory of infrastructure devices using gossip protocol to distribute - * information. - */ -@Component(immediate = true) -@Service -public class GossipDeviceStore - extends AbstractStore<DeviceEvent, DeviceStoreDelegate> - implements DeviceStore { - - private final Logger log = getLogger(getClass()); - - private static final String DEVICE_NOT_FOUND = "Device with ID %s not found"; - // Timeout in milliseconds to process device or ports on remote master node - private static final int REMOTE_MASTER_TIMEOUT = 1000; - - // innerMap is used to lock a Device, thus instance should never be replaced. - // collection of Description given from various providers - private final ConcurrentMap<DeviceId, Map<ProviderId, DeviceDescriptions>> - deviceDescs = Maps.newConcurrentMap(); - - // cache of Device and Ports generated by compositing descriptions from providers - private final ConcurrentMap<DeviceId, Device> devices = Maps.newConcurrentMap(); - private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, Port>> devicePorts = Maps.newConcurrentMap(); - - private EventuallyConsistentMap<DeviceId, Map<PortNumber, PortStatistics>> devicePortStats; - private EventuallyConsistentMap<DeviceId, Map<PortNumber, PortStatistics>> devicePortDeltaStats; - private final EventuallyConsistentMapListener<DeviceId, Map<PortNumber, PortStatistics>> - portStatsListener = new InternalPortStatsListener(); - - // to be updated under Device lock - private final Map<DeviceId, Timestamp> offline = Maps.newHashMap(); - private final Map<DeviceId, Timestamp> removalRequest = Maps.newHashMap(); - - // available(=UP) devices - private final Set<DeviceId> availableDevices = Sets.newConcurrentHashSet(); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected DeviceClockService deviceClockService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterCommunicationService clusterCommunicator; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipService mastershipService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipTermService termService; - - - protected static final KryoSerializer SERIALIZER = new KryoSerializer() { - @Override - protected void setupKryoPool() { - serializerPool = KryoNamespace.newBuilder() - .register(DistributedStoreSerializers.STORE_COMMON) - .nextId(DistributedStoreSerializers.STORE_CUSTOM_BEGIN) - .register(new InternalDeviceEventSerializer(), InternalDeviceEvent.class) - .register(new InternalDeviceOfflineEventSerializer(), InternalDeviceOfflineEvent.class) - .register(InternalDeviceRemovedEvent.class) - .register(new InternalPortEventSerializer(), InternalPortEvent.class) - .register(new InternalPortStatusEventSerializer(), InternalPortStatusEvent.class) - .register(DeviceAntiEntropyAdvertisement.class) - .register(DeviceFragmentId.class) - .register(PortFragmentId.class) - .register(DeviceInjectedEvent.class) - .register(PortInjectedEvent.class) - .build(); - } - }; - - private ExecutorService executor; - - private ScheduledExecutorService backgroundExecutor; - - // TODO make these anti-entropy parameters configurable - private long initialDelaySec = 5; - private long periodSec = 5; - - @Activate - public void activate() { - executor = Executors.newCachedThreadPool(groupedThreads("onos/device", "fg-%d")); - - backgroundExecutor = - newSingleThreadScheduledExecutor(minPriority(groupedThreads("onos/device", "bg-%d"))); - - clusterCommunicator.addSubscriber( - GossipDeviceStoreMessageSubjects.DEVICE_UPDATE, new InternalDeviceEventListener(), executor); - clusterCommunicator.addSubscriber( - GossipDeviceStoreMessageSubjects.DEVICE_OFFLINE, - new InternalDeviceOfflineEventListener(), - executor); - clusterCommunicator.addSubscriber(DEVICE_REMOVE_REQ, - new InternalRemoveRequestListener(), - executor); - clusterCommunicator.addSubscriber( - GossipDeviceStoreMessageSubjects.DEVICE_REMOVED, new InternalDeviceRemovedEventListener(), executor); - clusterCommunicator.addSubscriber( - GossipDeviceStoreMessageSubjects.PORT_UPDATE, new InternalPortEventListener(), executor); - clusterCommunicator.addSubscriber( - GossipDeviceStoreMessageSubjects.PORT_STATUS_UPDATE, new InternalPortStatusEventListener(), executor); - clusterCommunicator.addSubscriber( - GossipDeviceStoreMessageSubjects.DEVICE_ADVERTISE, - new InternalDeviceAdvertisementListener(), - backgroundExecutor); - clusterCommunicator.addSubscriber( - GossipDeviceStoreMessageSubjects.DEVICE_INJECTED, new DeviceInjectedEventListener(), executor); - clusterCommunicator.addSubscriber( - GossipDeviceStoreMessageSubjects.PORT_INJECTED, new PortInjectedEventListener(), executor); - - // start anti-entropy thread - backgroundExecutor.scheduleAtFixedRate(new SendAdvertisementTask(), - initialDelaySec, periodSec, TimeUnit.SECONDS); - - // Create a distributed map for port stats. - KryoNamespace.Builder deviceDataSerializer = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .register(DefaultPortStatistics.class) - .register(DeviceId.class) - .register(MultiValuedTimestamp.class) - .register(WallClockTimestamp.class); - - devicePortStats = storageService.<DeviceId, Map<PortNumber, PortStatistics>>eventuallyConsistentMapBuilder() - .withName("port-stats") - .withSerializer(deviceDataSerializer) - .withAntiEntropyPeriod(5, TimeUnit.SECONDS) - .withTimestampProvider((k, v) -> new WallClockTimestamp()) - .withTombstonesDisabled() - .build(); - devicePortDeltaStats = storageService.<DeviceId, Map<PortNumber, PortStatistics>> - eventuallyConsistentMapBuilder() - .withName("port-stats-delta") - .withSerializer(deviceDataSerializer) - .withAntiEntropyPeriod(5, TimeUnit.SECONDS) - .withTimestampProvider((k, v) -> new WallClockTimestamp()) - .withTombstonesDisabled() - .build(); - devicePortStats.addListener(portStatsListener); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - devicePortStats.destroy(); - devicePortDeltaStats.destroy(); - executor.shutdownNow(); - - backgroundExecutor.shutdownNow(); - try { - if (!backgroundExecutor.awaitTermination(5, TimeUnit.SECONDS)) { - log.error("Timeout during executor shutdown"); - } - } catch (InterruptedException e) { - log.error("Error during executor shutdown", e); - } - - deviceDescs.clear(); - devices.clear(); - devicePorts.clear(); - availableDevices.clear(); - log.info("Stopped"); - } - - @Override - public int getDeviceCount() { - return devices.size(); - } - - @Override - public Iterable<Device> getDevices() { - return Collections.unmodifiableCollection(devices.values()); - } - - @Override - public Iterable<Device> getAvailableDevices() { - return FluentIterable.from(getDevices()) - .filter(input -> isAvailable(input.id())); - } - - @Override - public Device getDevice(DeviceId deviceId) { - return devices.get(deviceId); - } - - @Override - public synchronized DeviceEvent createOrUpdateDevice(ProviderId providerId, - DeviceId deviceId, - DeviceDescription deviceDescription) { - NodeId localNode = clusterService.getLocalNode().id(); - NodeId deviceNode = mastershipService.getMasterFor(deviceId); - - // Process device update only if we're the master, - // otherwise signal the actual master. - DeviceEvent deviceEvent = null; - if (localNode.equals(deviceNode)) { - - final Timestamp newTimestamp = deviceClockService.getTimestamp(deviceId); - final Timestamped<DeviceDescription> deltaDesc = new Timestamped<>(deviceDescription, newTimestamp); - final Timestamped<DeviceDescription> mergedDesc; - final Map<ProviderId, DeviceDescriptions> device = getOrCreateDeviceDescriptionsMap(deviceId); - - synchronized (device) { - deviceEvent = createOrUpdateDeviceInternal(providerId, deviceId, deltaDesc); - mergedDesc = device.get(providerId).getDeviceDesc(); - } - - if (deviceEvent != null) { - log.debug("Notifying peers of a device update topology event for providerId: {} and deviceId: {}", - providerId, deviceId); - notifyPeers(new InternalDeviceEvent(providerId, deviceId, mergedDesc)); - } - - } else { - // FIXME Temporary hack for NPE (ONOS-1171). - // Proper fix is to implement forwarding to master on ConfigProvider - // redo ONOS-490 - if (deviceNode == null) { - // silently ignore - return null; - } - - - DeviceInjectedEvent deviceInjectedEvent = new DeviceInjectedEvent( - providerId, deviceId, deviceDescription); - - // TODO check unicast return value - clusterCommunicator.unicast(deviceInjectedEvent, DEVICE_INJECTED, SERIALIZER::encode, deviceNode); - /* error log: - log.warn("Failed to process injected device id: {} desc: {} " + - "(cluster messaging failed: {})", - deviceId, deviceDescription, e); - */ - } - - return deviceEvent; - } - - private DeviceEvent createOrUpdateDeviceInternal(ProviderId providerId, - DeviceId deviceId, - Timestamped<DeviceDescription> deltaDesc) { - - // Collection of DeviceDescriptions for a Device - Map<ProviderId, DeviceDescriptions> device - = getOrCreateDeviceDescriptionsMap(deviceId); - - synchronized (device) { - // locking per device - - if (isDeviceRemoved(deviceId, deltaDesc.timestamp())) { - log.debug("Ignoring outdated event: {}", deltaDesc); - return null; - } - - DeviceDescriptions descs = getOrCreateProviderDeviceDescriptions(device, providerId, deltaDesc); - - final Device oldDevice = devices.get(deviceId); - final Device newDevice; - - if (deltaDesc == descs.getDeviceDesc() || - deltaDesc.isNewer(descs.getDeviceDesc())) { - // on new device or valid update - descs.putDeviceDesc(deltaDesc); - newDevice = composeDevice(deviceId, device); - } else { - // outdated event, ignored. - return null; - } - if (oldDevice == null) { - // ADD - return createDevice(providerId, newDevice, deltaDesc.timestamp()); - } else { - // UPDATE or ignore (no change or stale) - return updateDevice(providerId, oldDevice, newDevice, deltaDesc.timestamp()); - } - } - } - - // Creates the device and returns the appropriate event if necessary. - // Guarded by deviceDescs value (=Device lock) - private DeviceEvent createDevice(ProviderId providerId, - Device newDevice, Timestamp timestamp) { - - // update composed device cache - Device oldDevice = devices.putIfAbsent(newDevice.id(), newDevice); - verify(oldDevice == null, - "Unexpected Device in cache. PID:%s [old=%s, new=%s]", - providerId, oldDevice, newDevice); - - if (!providerId.isAncillary()) { - markOnline(newDevice.id(), timestamp); - } - - return new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, newDevice, null); - } - - // Updates the device and returns the appropriate event if necessary. - // Guarded by deviceDescs value (=Device lock) - private DeviceEvent updateDevice(ProviderId providerId, - Device oldDevice, - Device newDevice, Timestamp newTimestamp) { - // We allow only certain attributes to trigger update - boolean propertiesChanged = - !Objects.equals(oldDevice.hwVersion(), newDevice.hwVersion()) || - !Objects.equals(oldDevice.swVersion(), newDevice.swVersion()) || - !Objects.equals(oldDevice.providerId(), newDevice.providerId()); - boolean annotationsChanged = - !AnnotationsUtil.isEqual(oldDevice.annotations(), newDevice.annotations()); - - // Primary providers can respond to all changes, but ancillary ones - // should respond only to annotation changes. - DeviceEvent event = null; - if ((providerId.isAncillary() && annotationsChanged) || - (!providerId.isAncillary() && (propertiesChanged || annotationsChanged))) { - boolean replaced = devices.replace(newDevice.id(), oldDevice, newDevice); - if (!replaced) { - verify(replaced, - "Replacing devices cache failed. PID:%s [expected:%s, found:%s, new=%s]", - providerId, oldDevice, devices.get(newDevice.id()) - , newDevice); - } - - event = new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, newDevice, null); - } - - if (!providerId.isAncillary()) { - boolean wasOnline = availableDevices.contains(newDevice.id()); - markOnline(newDevice.id(), newTimestamp); - if (!wasOnline) { - notifyDelegateIfNotNull(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, newDevice, null)); - } - } - return event; - } - - @Override - public DeviceEvent markOffline(DeviceId deviceId) { - final Timestamp timestamp = deviceClockService.getTimestamp(deviceId); - final DeviceEvent event = markOfflineInternal(deviceId, timestamp); - if (event != null) { - log.debug("Notifying peers of a device offline topology event for deviceId: {} {}", - deviceId, timestamp); - notifyPeers(new InternalDeviceOfflineEvent(deviceId, timestamp)); - } - return event; - } - - private DeviceEvent markOfflineInternal(DeviceId deviceId, Timestamp timestamp) { - - Map<ProviderId, DeviceDescriptions> providerDescs - = getOrCreateDeviceDescriptionsMap(deviceId); - - // locking device - synchronized (providerDescs) { - - // accept off-line if given timestamp is newer than - // the latest Timestamp from Primary provider - DeviceDescriptions primDescs = getPrimaryDescriptions(providerDescs); - Timestamp lastTimestamp = primDescs.getLatestTimestamp(); - if (timestamp.compareTo(lastTimestamp) <= 0) { - // outdated event ignore - return null; - } - - offline.put(deviceId, timestamp); - - Device device = devices.get(deviceId); - if (device == null) { - return null; - } - boolean removed = availableDevices.remove(deviceId); - if (removed) { - return new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device, null); - } - return null; - } - } - - /** - * Marks the device as available if the given timestamp is not outdated, - * compared to the time the device has been marked offline. - * - * @param deviceId identifier of the device - * @param timestamp of the event triggering this change. - * @return true if availability change request was accepted and changed the state - */ - // Guarded by deviceDescs value (=Device lock) - private boolean markOnline(DeviceId deviceId, Timestamp timestamp) { - // accept on-line if given timestamp is newer than - // the latest offline request Timestamp - Timestamp offlineTimestamp = offline.get(deviceId); - if (offlineTimestamp == null || - offlineTimestamp.compareTo(timestamp) < 0) { - - offline.remove(deviceId); - return availableDevices.add(deviceId); - } - return false; - } - - @Override - public synchronized List<DeviceEvent> updatePorts(ProviderId providerId, - DeviceId deviceId, - List<PortDescription> portDescriptions) { - - NodeId localNode = clusterService.getLocalNode().id(); - // TODO: It might be negligible, but this will have negative impact to topology discovery performance, - // since it will trigger distributed store read. - // Also, it'll probably be better if side-way communication happened on ConfigurationProvider, etc. - // outside Device subsystem. so that we don't have to modify both Device and Link stores. - // If we don't care much about topology performance, then it might be OK. - NodeId deviceNode = mastershipService.getMasterFor(deviceId); - - // Process port update only if we're the master of the device, - // otherwise signal the actual master. - List<DeviceEvent> deviceEvents = null; - if (localNode.equals(deviceNode)) { - - final Timestamp newTimestamp; - try { - newTimestamp = deviceClockService.getTimestamp(deviceId); - } catch (IllegalStateException e) { - log.info("Timestamp was not available for device {}", deviceId); - log.debug(" discarding {}", portDescriptions); - // Failed to generate timestamp. - - // Possible situation: - // Device connected and became master for short period of time, - // but lost mastership before this instance had the chance to - // retrieve term information. - - // Information dropped here is expected to be recoverable by - // device probing after mastership change - - return Collections.emptyList(); - } - log.debug("timestamp for {} {}", deviceId, newTimestamp); - - final Timestamped<List<PortDescription>> timestampedInput - = new Timestamped<>(portDescriptions, newTimestamp); - final Timestamped<List<PortDescription>> merged; - - final Map<ProviderId, DeviceDescriptions> device = getOrCreateDeviceDescriptionsMap(deviceId); - - synchronized (device) { - deviceEvents = updatePortsInternal(providerId, deviceId, timestampedInput); - final DeviceDescriptions descs = device.get(providerId); - List<PortDescription> mergedList = - FluentIterable.from(portDescriptions) - .transform(input -> - // lookup merged port description - descs.getPortDesc(input.portNumber()).value() - ).toList(); - merged = new Timestamped<>(mergedList, newTimestamp); - } - - if (!deviceEvents.isEmpty()) { - log.debug("Notifying peers of a ports update topology event for providerId: {} and deviceId: {}", - providerId, deviceId); - notifyPeers(new InternalPortEvent(providerId, deviceId, merged)); - } - - } else { - // FIXME Temporary hack for NPE (ONOS-1171). - // Proper fix is to implement forwarding to master on ConfigProvider - // redo ONOS-490 - if (deviceNode == null) { - // silently ignore - return Collections.emptyList(); - } - - PortInjectedEvent portInjectedEvent = new PortInjectedEvent(providerId, deviceId, portDescriptions); - - //TODO check unicast return value - clusterCommunicator.unicast(portInjectedEvent, PORT_INJECTED, SERIALIZER::encode, deviceNode); - /* error log: - log.warn("Failed to process injected ports of device id: {} " + - "(cluster messaging failed: {})", - deviceId, e); - */ - } - - return deviceEvents == null ? Collections.emptyList() : deviceEvents; - } - - private List<DeviceEvent> updatePortsInternal(ProviderId providerId, - DeviceId deviceId, - Timestamped<List<PortDescription>> portDescriptions) { - - Device device = devices.get(deviceId); - checkArgument(device != null, DEVICE_NOT_FOUND, deviceId); - - Map<ProviderId, DeviceDescriptions> descsMap = deviceDescs.get(deviceId); - checkArgument(descsMap != null, DEVICE_NOT_FOUND, deviceId); - - List<DeviceEvent> events = new ArrayList<>(); - synchronized (descsMap) { - - if (isDeviceRemoved(deviceId, portDescriptions.timestamp())) { - log.debug("Ignoring outdated events: {}", portDescriptions); - return Collections.emptyList(); - } - - DeviceDescriptions descs = descsMap.get(providerId); - // every provider must provide DeviceDescription. - checkArgument(descs != null, - "Device description for Device ID %s from Provider %s was not found", - deviceId, providerId); - - Map<PortNumber, Port> ports = getPortMap(deviceId); - - final Timestamp newTimestamp = portDescriptions.timestamp(); - - // Add new ports - Set<PortNumber> processed = new HashSet<>(); - for (PortDescription portDescription : portDescriptions.value()) { - final PortNumber number = portDescription.portNumber(); - processed.add(number); - - final Port oldPort = ports.get(number); - final Port newPort; - - - final Timestamped<PortDescription> existingPortDesc = descs.getPortDesc(number); - if (existingPortDesc == null || - newTimestamp.compareTo(existingPortDesc.timestamp()) >= 0) { - // on new port or valid update - // update description - descs.putPortDesc(new Timestamped<>(portDescription, - portDescriptions.timestamp())); - newPort = composePort(device, number, descsMap); - } else { - // outdated event, ignored. - continue; - } - - events.add(oldPort == null ? - createPort(device, newPort, ports) : - updatePort(device, oldPort, newPort, ports)); - } - - events.addAll(pruneOldPorts(device, ports, processed)); - } - return FluentIterable.from(events).filter(notNull()).toList(); - } - - // Creates a new port based on the port description adds it to the map and - // Returns corresponding event. - // Guarded by deviceDescs value (=Device lock) - private DeviceEvent createPort(Device device, Port newPort, - Map<PortNumber, Port> ports) { - ports.put(newPort.number(), newPort); - return new DeviceEvent(PORT_ADDED, device, newPort); - } - - // Checks if the specified port requires update and if so, it replaces the - // existing entry in the map and returns corresponding event. - // Guarded by deviceDescs value (=Device lock) - private DeviceEvent updatePort(Device device, Port oldPort, - Port newPort, - Map<PortNumber, Port> ports) { - if (oldPort.isEnabled() != newPort.isEnabled() || - oldPort.type() != newPort.type() || - oldPort.portSpeed() != newPort.portSpeed() || - !AnnotationsUtil.isEqual(oldPort.annotations(), newPort.annotations())) { - ports.put(oldPort.number(), newPort); - return new DeviceEvent(PORT_UPDATED, device, newPort); - } - return null; - } - - // Prunes the specified list of ports based on which ports are in the - // processed list and returns list of corresponding events. - // Guarded by deviceDescs value (=Device lock) - private List<DeviceEvent> pruneOldPorts(Device device, - Map<PortNumber, Port> ports, - Set<PortNumber> processed) { - List<DeviceEvent> events = new ArrayList<>(); - Iterator<Entry<PortNumber, Port>> iterator = ports.entrySet().iterator(); - while (iterator.hasNext()) { - Entry<PortNumber, Port> e = iterator.next(); - PortNumber portNumber = e.getKey(); - if (!processed.contains(portNumber)) { - events.add(new DeviceEvent(PORT_REMOVED, device, e.getValue())); - iterator.remove(); - } - } - return events; - } - - // Gets the map of ports for the specified device; if one does not already - // exist, it creates and registers a new one. - private ConcurrentMap<PortNumber, Port> getPortMap(DeviceId deviceId) { - return createIfAbsentUnchecked(devicePorts, deviceId, - NewConcurrentHashMap.<PortNumber, Port>ifNeeded()); - } - - private Map<ProviderId, DeviceDescriptions> getOrCreateDeviceDescriptionsMap( - DeviceId deviceId) { - Map<ProviderId, DeviceDescriptions> r; - r = deviceDescs.get(deviceId); - if (r == null) { - r = new HashMap<>(); - final Map<ProviderId, DeviceDescriptions> concurrentlyAdded; - concurrentlyAdded = deviceDescs.putIfAbsent(deviceId, r); - if (concurrentlyAdded != null) { - r = concurrentlyAdded; - } - } - return r; - } - - // Guarded by deviceDescs value (=Device lock) - private DeviceDescriptions getOrCreateProviderDeviceDescriptions( - Map<ProviderId, DeviceDescriptions> device, - ProviderId providerId, Timestamped<DeviceDescription> deltaDesc) { - synchronized (device) { - DeviceDescriptions r = device.get(providerId); - if (r == null) { - r = new DeviceDescriptions(deltaDesc); - device.put(providerId, r); - } - return r; - } - } - - @Override - public synchronized DeviceEvent updatePortStatus(ProviderId providerId, - DeviceId deviceId, - PortDescription portDescription) { - final Timestamp newTimestamp; - try { - newTimestamp = deviceClockService.getTimestamp(deviceId); - } catch (IllegalStateException e) { - log.info("Timestamp was not available for device {}", deviceId); - log.debug(" discarding {}", portDescription); - // Failed to generate timestamp. Ignoring. - // See updatePorts comment - return null; - } - final Timestamped<PortDescription> deltaDesc - = new Timestamped<>(portDescription, newTimestamp); - final DeviceEvent event; - final Timestamped<PortDescription> mergedDesc; - final Map<ProviderId, DeviceDescriptions> device = getOrCreateDeviceDescriptionsMap(deviceId); - synchronized (device) { - event = updatePortStatusInternal(providerId, deviceId, deltaDesc); - mergedDesc = device.get(providerId) - .getPortDesc(portDescription.portNumber()); - } - if (event != null) { - log.debug("Notifying peers of a port status update topology event for providerId: {} and deviceId: {}", - providerId, deviceId); - notifyPeers(new InternalPortStatusEvent(providerId, deviceId, mergedDesc)); - } - return event; - } - - private DeviceEvent updatePortStatusInternal(ProviderId providerId, DeviceId deviceId, - Timestamped<PortDescription> deltaDesc) { - Device device = devices.get(deviceId); - checkArgument(device != null, DEVICE_NOT_FOUND, deviceId); - - Map<ProviderId, DeviceDescriptions> descsMap = deviceDescs.get(deviceId); - checkArgument(descsMap != null, DEVICE_NOT_FOUND, deviceId); - - synchronized (descsMap) { - - if (isDeviceRemoved(deviceId, deltaDesc.timestamp())) { - log.debug("Ignoring outdated event: {}", deltaDesc); - return null; - } - - DeviceDescriptions descs = descsMap.get(providerId); - // assuming all providers must to give DeviceDescription - verify(descs != null, - "Device description for Device ID %s from Provider %s was not found", - deviceId, providerId); - - ConcurrentMap<PortNumber, Port> ports = getPortMap(deviceId); - final PortNumber number = deltaDesc.value().portNumber(); - final Port oldPort = ports.get(number); - final Port newPort; - - final Timestamped<PortDescription> existingPortDesc = descs.getPortDesc(number); - if (existingPortDesc == null || - deltaDesc.isNewer(existingPortDesc)) { - // on new port or valid update - // update description - descs.putPortDesc(deltaDesc); - newPort = composePort(device, number, descsMap); - } else { - // same or outdated event, ignored. - log.trace("ignore same or outdated {} >= {}", existingPortDesc, deltaDesc); - return null; - } - - if (oldPort == null) { - return createPort(device, newPort, ports); - } else { - return updatePort(device, oldPort, newPort, ports); - } - } - } - - @Override - public List<Port> getPorts(DeviceId deviceId) { - Map<PortNumber, Port> ports = devicePorts.get(deviceId); - if (ports == null) { - return Collections.emptyList(); - } - return ImmutableList.copyOf(ports.values()); - } - - @Override - public DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId, - Collection<PortStatistics> newStatsCollection) { - - Map<PortNumber, PortStatistics> prvStatsMap = devicePortStats.get(deviceId); - Map<PortNumber, PortStatistics> newStatsMap = Maps.newHashMap(); - Map<PortNumber, PortStatistics> deltaStatsMap = Maps.newHashMap(); - - if (prvStatsMap != null) { - for (PortStatistics newStats : newStatsCollection) { - PortNumber port = PortNumber.portNumber(newStats.port()); - PortStatistics prvStats = prvStatsMap.get(port); - DefaultPortStatistics.Builder builder = DefaultPortStatistics.builder(); - PortStatistics deltaStats = builder.build(); - if (prvStats != null) { - deltaStats = calcDeltaStats(deviceId, prvStats, newStats); - } - deltaStatsMap.put(port, deltaStats); - newStatsMap.put(port, newStats); - } - } else { - for (PortStatistics newStats : newStatsCollection) { - PortNumber port = PortNumber.portNumber(newStats.port()); - newStatsMap.put(port, newStats); - } - } - devicePortDeltaStats.put(deviceId, deltaStatsMap); - devicePortStats.put(deviceId, newStatsMap); - // DeviceEvent returns null because of InternalPortStatsListener usage - return null; - } - - /** - * Calculate delta statistics by subtracting previous from new statistics. - * - * @param deviceId device identifier - * @param prvStats previous port statistics - * @param newStats new port statistics - * @return PortStatistics - */ - public PortStatistics calcDeltaStats(DeviceId deviceId, PortStatistics prvStats, PortStatistics newStats) { - // calculate time difference - long deltaStatsSec, deltaStatsNano; - if (newStats.durationNano() < prvStats.durationNano()) { - deltaStatsNano = newStats.durationNano() - prvStats.durationNano() + TimeUnit.SECONDS.toNanos(1); - deltaStatsSec = newStats.durationSec() - prvStats.durationSec() - 1L; - } else { - deltaStatsNano = newStats.durationNano() - prvStats.durationNano(); - deltaStatsSec = newStats.durationSec() - prvStats.durationSec(); - } - DefaultPortStatistics.Builder builder = DefaultPortStatistics.builder(); - DefaultPortStatistics deltaStats = builder.setDeviceId(deviceId) - .setPort(newStats.port()) - .setPacketsReceived(newStats.packetsReceived() - prvStats.packetsReceived()) - .setPacketsSent(newStats.packetsSent() - prvStats.packetsSent()) - .setBytesReceived(newStats.bytesReceived() - prvStats.bytesReceived()) - .setBytesSent(newStats.bytesSent() - prvStats.bytesSent()) - .setPacketsRxDropped(newStats.packetsRxDropped() - prvStats.packetsRxDropped()) - .setPacketsTxDropped(newStats.packetsTxDropped() - prvStats.packetsTxDropped()) - .setPacketsRxErrors(newStats.packetsRxErrors() - prvStats.packetsRxErrors()) - .setPacketsTxErrors(newStats.packetsTxErrors() - prvStats.packetsTxErrors()) - .setDurationSec(deltaStatsSec) - .setDurationNano(deltaStatsNano) - .build(); - return deltaStats; - } - - @Override - public List<PortStatistics> getPortStatistics(DeviceId deviceId) { - Map<PortNumber, PortStatistics> portStats = devicePortStats.get(deviceId); - if (portStats == null) { - return Collections.emptyList(); - } - return ImmutableList.copyOf(portStats.values()); - } - - @Override - public List<PortStatistics> getPortDeltaStatistics(DeviceId deviceId) { - Map<PortNumber, PortStatistics> portStats = devicePortDeltaStats.get(deviceId); - if (portStats == null) { - return Collections.emptyList(); - } - return ImmutableList.copyOf(portStats.values()); - } - - @Override - public Port getPort(DeviceId deviceId, PortNumber portNumber) { - Map<PortNumber, Port> ports = devicePorts.get(deviceId); - return ports == null ? null : ports.get(portNumber); - } - - @Override - public boolean isAvailable(DeviceId deviceId) { - return availableDevices.contains(deviceId); - } - - @Override - public synchronized DeviceEvent removeDevice(DeviceId deviceId) { - final NodeId myId = clusterService.getLocalNode().id(); - NodeId master = mastershipService.getMasterFor(deviceId); - - // if there exist a master, forward - // if there is no master, try to become one and process - - boolean relinquishAtEnd = false; - if (master == null) { - final MastershipRole myRole = mastershipService.getLocalRole(deviceId); - if (myRole != MastershipRole.NONE) { - relinquishAtEnd = true; - } - log.debug("Temporarily requesting role for {} to remove", deviceId); - mastershipService.requestRoleFor(deviceId); - MastershipTerm term = termService.getMastershipTerm(deviceId); - if (term != null && myId.equals(term.master())) { - master = myId; - } - } - - if (!myId.equals(master)) { - log.debug("{} has control of {}, forwarding remove request", - master, deviceId); - - // TODO check unicast return value - clusterCommunicator.unicast(deviceId, DEVICE_REMOVE_REQ, SERIALIZER::encode, master); - /* error log: - log.error("Failed to forward {} remove request to {}", deviceId, master, e); - */ - - // event will be triggered after master processes it. - return null; - } - - // I have control.. - - Timestamp timestamp = deviceClockService.getTimestamp(deviceId); - DeviceEvent event = removeDeviceInternal(deviceId, timestamp); - if (event != null) { - log.debug("Notifying peers of a device removed topology event for deviceId: {}", - deviceId); - notifyPeers(new InternalDeviceRemovedEvent(deviceId, timestamp)); - } - if (relinquishAtEnd) { - log.debug("Relinquishing temporary role acquired for {}", deviceId); - mastershipService.relinquishMastership(deviceId); - } - return event; - } - - private DeviceEvent removeDeviceInternal(DeviceId deviceId, - Timestamp timestamp) { - - Map<ProviderId, DeviceDescriptions> descs = getOrCreateDeviceDescriptionsMap(deviceId); - synchronized (descs) { - // accept removal request if given timestamp is newer than - // the latest Timestamp from Primary provider - DeviceDescriptions primDescs = getPrimaryDescriptions(descs); - if (primDescs == null) { - return null; - } - - Timestamp lastTimestamp = primDescs.getLatestTimestamp(); - if (timestamp.compareTo(lastTimestamp) <= 0) { - // outdated event ignore - return null; - } - removalRequest.put(deviceId, timestamp); - - Device device = devices.remove(deviceId); - // should DEVICE_REMOVED carry removed ports? - Map<PortNumber, Port> ports = devicePorts.get(deviceId); - if (ports != null) { - ports.clear(); - } - markOfflineInternal(deviceId, timestamp); - descs.clear(); - return device == null ? null : - new DeviceEvent(DeviceEvent.Type.DEVICE_REMOVED, device, null); - } - } - - /** - * Checks if given timestamp is superseded by removal request - * with more recent timestamp. - * - * @param deviceId identifier of a device - * @param timestampToCheck timestamp of an event to check - * @return true if device is already removed - */ - private boolean isDeviceRemoved(DeviceId deviceId, Timestamp timestampToCheck) { - Timestamp removalTimestamp = removalRequest.get(deviceId); - if (removalTimestamp != null && - removalTimestamp.compareTo(timestampToCheck) >= 0) { - // removalRequest is more recent - return true; - } - return false; - } - - /** - * Returns a Device, merging description given from multiple Providers. - * - * @param deviceId device identifier - * @param providerDescs Collection of Descriptions from multiple providers - * @return Device instance - */ - private Device composeDevice(DeviceId deviceId, - Map<ProviderId, DeviceDescriptions> providerDescs) { - - checkArgument(!providerDescs.isEmpty(), "No device descriptions supplied"); - - ProviderId primary = pickPrimaryPid(providerDescs); - - DeviceDescriptions desc = providerDescs.get(primary); - - final DeviceDescription base = desc.getDeviceDesc().value(); - Type type = base.type(); - String manufacturer = base.manufacturer(); - String hwVersion = base.hwVersion(); - String swVersion = base.swVersion(); - String serialNumber = base.serialNumber(); - ChassisId chassisId = base.chassisId(); - DefaultAnnotations annotations = DefaultAnnotations.builder().build(); - annotations = merge(annotations, base.annotations()); - - for (Entry<ProviderId, DeviceDescriptions> e : providerDescs.entrySet()) { - if (e.getKey().equals(primary)) { - continue; - } - // Note: should keep track of Description timestamp in the future - // and only merge conflicting keys when timestamp is newer. - // Currently assuming there will never be a key conflict between - // providers - - // annotation merging. not so efficient, should revisit later - annotations = merge(annotations, e.getValue().getDeviceDesc().value().annotations()); - } - - return new DefaultDevice(primary, deviceId, type, manufacturer, - hwVersion, swVersion, serialNumber, - chassisId, annotations); - } - - private Port buildTypedPort(Device device, PortNumber number, boolean isEnabled, - PortDescription description, Annotations annotations) { - switch (description.type()) { - case OMS: - OmsPortDescription omsDesc = (OmsPortDescription) description; - return new OmsPort(device, number, isEnabled, omsDesc.minFrequency(), - omsDesc.maxFrequency(), omsDesc.grid(), annotations); - case OCH: - OchPortDescription ochDesc = (OchPortDescription) description; - return new OchPort(device, number, isEnabled, ochDesc.signalType(), - ochDesc.isTunable(), ochDesc.lambda(), annotations); - case ODUCLT: - OduCltPortDescription oduDesc = (OduCltPortDescription) description; - return new OduCltPort(device, number, isEnabled, oduDesc.signalType(), annotations); - default: - return new DefaultPort(device, number, isEnabled, description.type(), - description.portSpeed(), annotations); - } - } - - /** - * Returns a Port, merging description given from multiple Providers. - * - * @param device device the port is on - * @param number port number - * @param descsMap Collection of Descriptions from multiple providers - * @return Port instance - */ - private Port composePort(Device device, PortNumber number, - Map<ProviderId, DeviceDescriptions> descsMap) { - - ProviderId primary = pickPrimaryPid(descsMap); - DeviceDescriptions primDescs = descsMap.get(primary); - // if no primary, assume not enabled - boolean isEnabled = false; - DefaultAnnotations annotations = DefaultAnnotations.builder().build(); - Timestamp newest = null; - final Timestamped<PortDescription> portDesc = primDescs.getPortDesc(number); - if (portDesc != null) { - isEnabled = portDesc.value().isEnabled(); - annotations = merge(annotations, portDesc.value().annotations()); - newest = portDesc.timestamp(); - } - Port updated = null; - for (Entry<ProviderId, DeviceDescriptions> e : descsMap.entrySet()) { - if (e.getKey().equals(primary)) { - continue; - } - // Note: should keep track of Description timestamp in the future - // and only merge conflicting keys when timestamp is newer. - // Currently assuming there will never be a key conflict between - // providers - - // annotation merging. not so efficient, should revisit later - final Timestamped<PortDescription> otherPortDesc = e.getValue().getPortDesc(number); - if (otherPortDesc != null) { - if (newest != null && newest.isNewerThan(otherPortDesc.timestamp())) { - continue; - } - annotations = merge(annotations, otherPortDesc.value().annotations()); - PortDescription other = otherPortDesc.value(); - updated = buildTypedPort(device, number, isEnabled, other, annotations); - newest = otherPortDesc.timestamp(); - } - } - if (portDesc == null) { - return updated == null ? new DefaultPort(device, number, false, annotations) : updated; - } - PortDescription current = portDesc.value(); - return updated == null - ? buildTypedPort(device, number, isEnabled, current, annotations) - : updated; - } - - /** - * @return primary ProviderID, or randomly chosen one if none exists - */ - private ProviderId pickPrimaryPid( - Map<ProviderId, DeviceDescriptions> providerDescs) { - ProviderId fallBackPrimary = null; - for (Entry<ProviderId, DeviceDescriptions> e : providerDescs.entrySet()) { - if (!e.getKey().isAncillary()) { - return e.getKey(); - } else if (fallBackPrimary == null) { - // pick randomly as a fallback in case there is no primary - fallBackPrimary = e.getKey(); - } - } - return fallBackPrimary; - } - - private DeviceDescriptions getPrimaryDescriptions( - Map<ProviderId, DeviceDescriptions> providerDescs) { - ProviderId pid = pickPrimaryPid(providerDescs); - return providerDescs.get(pid); - } - - private void unicastMessage(NodeId recipient, MessageSubject subject, Object event) throws IOException { - clusterCommunicator.unicast(event, subject, SERIALIZER::encode, recipient); - } - - private void broadcastMessage(MessageSubject subject, Object event) { - clusterCommunicator.broadcast(event, subject, SERIALIZER::encode); - } - - private void notifyPeers(InternalDeviceEvent event) { - broadcastMessage(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE, event); - } - - private void notifyPeers(InternalDeviceOfflineEvent event) { - broadcastMessage(GossipDeviceStoreMessageSubjects.DEVICE_OFFLINE, event); - } - - private void notifyPeers(InternalDeviceRemovedEvent event) { - broadcastMessage(GossipDeviceStoreMessageSubjects.DEVICE_REMOVED, event); - } - - private void notifyPeers(InternalPortEvent event) { - broadcastMessage(GossipDeviceStoreMessageSubjects.PORT_UPDATE, event); - } - - private void notifyPeers(InternalPortStatusEvent event) { - broadcastMessage(GossipDeviceStoreMessageSubjects.PORT_STATUS_UPDATE, event); - } - - private void notifyPeer(NodeId recipient, InternalDeviceEvent event) { - try { - unicastMessage(recipient, GossipDeviceStoreMessageSubjects.DEVICE_UPDATE, event); - } catch (IOException e) { - log.error("Failed to send" + event + " to " + recipient, e); - } - } - - private void notifyPeer(NodeId recipient, InternalDeviceOfflineEvent event) { - try { - unicastMessage(recipient, GossipDeviceStoreMessageSubjects.DEVICE_OFFLINE, event); - } catch (IOException e) { - log.error("Failed to send" + event + " to " + recipient, e); - } - } - - private void notifyPeer(NodeId recipient, InternalDeviceRemovedEvent event) { - try { - unicastMessage(recipient, GossipDeviceStoreMessageSubjects.DEVICE_REMOVED, event); - } catch (IOException e) { - log.error("Failed to send" + event + " to " + recipient, e); - } - } - - private void notifyPeer(NodeId recipient, InternalPortEvent event) { - try { - unicastMessage(recipient, GossipDeviceStoreMessageSubjects.PORT_UPDATE, event); - } catch (IOException e) { - log.error("Failed to send" + event + " to " + recipient, e); - } - } - - private void notifyPeer(NodeId recipient, InternalPortStatusEvent event) { - try { - unicastMessage(recipient, GossipDeviceStoreMessageSubjects.PORT_STATUS_UPDATE, event); - } catch (IOException e) { - log.error("Failed to send" + event + " to " + recipient, e); - } - } - - private DeviceAntiEntropyAdvertisement createAdvertisement() { - final NodeId self = clusterService.getLocalNode().id(); - - final int numDevices = deviceDescs.size(); - Map<DeviceFragmentId, Timestamp> adDevices = new HashMap<>(numDevices); - final int portsPerDevice = 8; // random factor to minimize reallocation - Map<PortFragmentId, Timestamp> adPorts = new HashMap<>(numDevices * portsPerDevice); - Map<DeviceId, Timestamp> adOffline = new HashMap<>(numDevices); - - deviceDescs.forEach((deviceId, devDescs) -> { - - // for each Device... - synchronized (devDescs) { - - // send device offline timestamp - Timestamp lOffline = this.offline.get(deviceId); - if (lOffline != null) { - adOffline.put(deviceId, lOffline); - } - - for (Entry<ProviderId, DeviceDescriptions> - prov : devDescs.entrySet()) { - - // for each Provider Descriptions... - final ProviderId provId = prov.getKey(); - final DeviceDescriptions descs = prov.getValue(); - - adDevices.put(new DeviceFragmentId(deviceId, provId), - descs.getDeviceDesc().timestamp()); - - for (Entry<PortNumber, Timestamped<PortDescription>> - portDesc : descs.getPortDescs().entrySet()) { - - final PortNumber number = portDesc.getKey(); - adPorts.put(new PortFragmentId(deviceId, provId, number), - portDesc.getValue().timestamp()); - } - } - } - }); - - return new DeviceAntiEntropyAdvertisement(self, adDevices, adPorts, adOffline); - } - - /** - * Responds to anti-entropy advertisement message. - * <p/> - * Notify sender about out-dated information using regular replication message. - * Send back advertisement to sender if not in sync. - * - * @param advertisement to respond to - */ - private void handleAdvertisement(DeviceAntiEntropyAdvertisement advertisement) { - - final NodeId sender = advertisement.sender(); - - Map<DeviceFragmentId, Timestamp> devAds = new HashMap<>(advertisement.deviceFingerPrints()); - Map<PortFragmentId, Timestamp> portAds = new HashMap<>(advertisement.ports()); - Map<DeviceId, Timestamp> offlineAds = new HashMap<>(advertisement.offline()); - - // Fragments to request - Collection<DeviceFragmentId> reqDevices = new ArrayList<>(); - Collection<PortFragmentId> reqPorts = new ArrayList<>(); - - for (Entry<DeviceId, Map<ProviderId, DeviceDescriptions>> de : deviceDescs.entrySet()) { - final DeviceId deviceId = de.getKey(); - final Map<ProviderId, DeviceDescriptions> lDevice = de.getValue(); - - synchronized (lDevice) { - // latestTimestamp across provider - // Note: can be null initially - Timestamp localLatest = offline.get(deviceId); - - // handle device Ads - for (Entry<ProviderId, DeviceDescriptions> prov : lDevice.entrySet()) { - final ProviderId provId = prov.getKey(); - final DeviceDescriptions lDeviceDescs = prov.getValue(); - - final DeviceFragmentId devFragId = new DeviceFragmentId(deviceId, provId); - - - Timestamped<DeviceDescription> lProvDevice = lDeviceDescs.getDeviceDesc(); - Timestamp advDevTimestamp = devAds.get(devFragId); - - if (advDevTimestamp == null || lProvDevice.isNewerThan( - advDevTimestamp)) { - // remote does not have it or outdated, suggest - notifyPeer(sender, new InternalDeviceEvent(provId, deviceId, lProvDevice)); - } else if (!lProvDevice.timestamp().equals(advDevTimestamp)) { - // local is outdated, request - reqDevices.add(devFragId); - } - - // handle port Ads - for (Entry<PortNumber, Timestamped<PortDescription>> - pe : lDeviceDescs.getPortDescs().entrySet()) { - - final PortNumber num = pe.getKey(); - final Timestamped<PortDescription> lPort = pe.getValue(); - - final PortFragmentId portFragId = new PortFragmentId(deviceId, provId, num); - - Timestamp advPortTimestamp = portAds.get(portFragId); - if (advPortTimestamp == null || lPort.isNewerThan( - advPortTimestamp)) { - // remote does not have it or outdated, suggest - notifyPeer(sender, new InternalPortStatusEvent(provId, deviceId, lPort)); - } else if (!lPort.timestamp().equals(advPortTimestamp)) { - // local is outdated, request - log.trace("need update {} < {}", lPort.timestamp(), advPortTimestamp); - reqPorts.add(portFragId); - } - - // remove port Ad already processed - portAds.remove(portFragId); - } // end local port loop - - // remove device Ad already processed - devAds.remove(devFragId); - - // find latest and update - final Timestamp providerLatest = lDeviceDescs.getLatestTimestamp(); - if (localLatest == null || - providerLatest.compareTo(localLatest) > 0) { - localLatest = providerLatest; - } - } // end local provider loop - - // checking if remote timestamp is more recent. - Timestamp rOffline = offlineAds.get(deviceId); - if (rOffline != null && - rOffline.compareTo(localLatest) > 0) { - // remote offline timestamp suggests that the - // device is off-line - markOfflineInternal(deviceId, rOffline); - } - - Timestamp lOffline = offline.get(deviceId); - if (lOffline != null && rOffline == null) { - // locally offline, but remote is online, suggest offline - notifyPeer(sender, new InternalDeviceOfflineEvent(deviceId, lOffline)); - } - - // remove device offline Ad already processed - offlineAds.remove(deviceId); - } // end local device loop - } // device lock - - // If there is any Ads left, request them - log.trace("Ads left {}, {}", devAds, portAds); - reqDevices.addAll(devAds.keySet()); - reqPorts.addAll(portAds.keySet()); - - if (reqDevices.isEmpty() && reqPorts.isEmpty()) { - log.trace("Nothing to request to remote peer {}", sender); - return; - } - - log.debug("Need to sync {} {}", reqDevices, reqPorts); - - // 2-way Anti-Entropy for now - try { - unicastMessage(sender, DEVICE_ADVERTISE, createAdvertisement()); - } catch (IOException e) { - log.error("Failed to send response advertisement to " + sender, e); - } - -// Sketch of 3-way Anti-Entropy -// DeviceAntiEntropyRequest request = new DeviceAntiEntropyRequest(self, reqDevices, reqPorts); -// ClusterMessage message = new ClusterMessage( -// clusterService.getLocalNode().id(), -// GossipDeviceStoreMessageSubjects.DEVICE_REQUEST, -// SERIALIZER.encode(request)); -// -// try { -// clusterCommunicator.unicast(message, advertisement.sender()); -// } catch (IOException e) { -// log.error("Failed to send advertisement reply to " -// + advertisement.sender(), e); -// } - } - - private void notifyDelegateIfNotNull(DeviceEvent event) { - if (event != null) { - notifyDelegate(event); - } - } - - private final class SendAdvertisementTask implements Runnable { - - @Override - public void run() { - if (Thread.currentThread().isInterrupted()) { - log.debug("Interrupted, quitting"); - return; - } - - try { - final NodeId self = clusterService.getLocalNode().id(); - Set<ControllerNode> nodes = clusterService.getNodes(); - - ImmutableList<NodeId> nodeIds = FluentIterable.from(nodes) - .transform(toNodeId()) - .toList(); - - if (nodeIds.size() == 1 && nodeIds.get(0).equals(self)) { - log.trace("No other peers in the cluster."); - return; - } - - NodeId peer; - do { - int idx = RandomUtils.nextInt(0, nodeIds.size()); - peer = nodeIds.get(idx); - } while (peer.equals(self)); - - DeviceAntiEntropyAdvertisement ad = createAdvertisement(); - - if (Thread.currentThread().isInterrupted()) { - log.debug("Interrupted, quitting"); - return; - } - - try { - unicastMessage(peer, DEVICE_ADVERTISE, ad); - } catch (IOException e) { - log.debug("Failed to send anti-entropy advertisement to {}", peer); - return; - } - } catch (Exception e) { - // catch all Exception to avoid Scheduled task being suppressed. - log.error("Exception thrown while sending advertisement", e); - } - } - } - - private final class InternalDeviceEventListener - implements ClusterMessageHandler { - @Override - public void handle(ClusterMessage message) { - log.debug("Received device update event from peer: {}", message.sender()); - InternalDeviceEvent event = SERIALIZER.decode(message.payload()); - - ProviderId providerId = event.providerId(); - DeviceId deviceId = event.deviceId(); - Timestamped<DeviceDescription> deviceDescription = event.deviceDescription(); - - try { - notifyDelegateIfNotNull(createOrUpdateDeviceInternal(providerId, deviceId, deviceDescription)); - } catch (Exception e) { - log.warn("Exception thrown handling device update", e); - } - } - } - - private final class InternalDeviceOfflineEventListener - implements ClusterMessageHandler { - @Override - public void handle(ClusterMessage message) { - log.debug("Received device offline event from peer: {}", message.sender()); - InternalDeviceOfflineEvent event = SERIALIZER.decode(message.payload()); - - DeviceId deviceId = event.deviceId(); - Timestamp timestamp = event.timestamp(); - - try { - notifyDelegateIfNotNull(markOfflineInternal(deviceId, timestamp)); - } catch (Exception e) { - log.warn("Exception thrown handling device offline", e); - } - } - } - - private final class InternalRemoveRequestListener - implements ClusterMessageHandler { - @Override - public void handle(ClusterMessage message) { - log.debug("Received device remove request from peer: {}", message.sender()); - DeviceId did = SERIALIZER.decode(message.payload()); - - try { - removeDevice(did); - } catch (Exception e) { - log.warn("Exception thrown handling device remove", e); - } - } - } - - private final class InternalDeviceRemovedEventListener - implements ClusterMessageHandler { - @Override - public void handle(ClusterMessage message) { - log.debug("Received device removed event from peer: {}", message.sender()); - InternalDeviceRemovedEvent event = SERIALIZER.decode(message.payload()); - - DeviceId deviceId = event.deviceId(); - Timestamp timestamp = event.timestamp(); - - try { - notifyDelegateIfNotNull(removeDeviceInternal(deviceId, timestamp)); - } catch (Exception e) { - log.warn("Exception thrown handling device removed", e); - } - } - } - - private final class InternalPortEventListener - implements ClusterMessageHandler { - @Override - public void handle(ClusterMessage message) { - - log.debug("Received port update event from peer: {}", message.sender()); - InternalPortEvent event = SERIALIZER.decode(message.payload()); - - ProviderId providerId = event.providerId(); - DeviceId deviceId = event.deviceId(); - Timestamped<List<PortDescription>> portDescriptions = event.portDescriptions(); - - if (getDevice(deviceId) == null) { - log.debug("{} not found on this node yet, ignoring.", deviceId); - // Note: dropped information will be recovered by anti-entropy - return; - } - - try { - notifyDelegate(updatePortsInternal(providerId, deviceId, portDescriptions)); - } catch (Exception e) { - log.warn("Exception thrown handling port update", e); - } - } - } - - private final class InternalPortStatusEventListener - implements ClusterMessageHandler { - @Override - public void handle(ClusterMessage message) { - - log.debug("Received port status update event from peer: {}", message.sender()); - InternalPortStatusEvent event = SERIALIZER.decode(message.payload()); - - ProviderId providerId = event.providerId(); - DeviceId deviceId = event.deviceId(); - Timestamped<PortDescription> portDescription = event.portDescription(); - - if (getDevice(deviceId) == null) { - log.debug("{} not found on this node yet, ignoring.", deviceId); - // Note: dropped information will be recovered by anti-entropy - return; - } - - try { - notifyDelegateIfNotNull(updatePortStatusInternal(providerId, deviceId, portDescription)); - } catch (Exception e) { - log.warn("Exception thrown handling port update", e); - } - } - } - - private final class InternalDeviceAdvertisementListener - implements ClusterMessageHandler { - @Override - public void handle(ClusterMessage message) { - log.trace("Received Device Anti-Entropy advertisement from peer: {}", message.sender()); - DeviceAntiEntropyAdvertisement advertisement = SERIALIZER.decode(message.payload()); - try { - handleAdvertisement(advertisement); - } catch (Exception e) { - log.warn("Exception thrown handling Device advertisements.", e); - } - } - } - - private final class DeviceInjectedEventListener - implements ClusterMessageHandler { - @Override - public void handle(ClusterMessage message) { - log.debug("Received injected device event from peer: {}", message.sender()); - DeviceInjectedEvent event = SERIALIZER.decode(message.payload()); - - ProviderId providerId = event.providerId(); - DeviceId deviceId = event.deviceId(); - DeviceDescription deviceDescription = event.deviceDescription(); - if (!deviceClockService.isTimestampAvailable(deviceId)) { - // workaround for ONOS-1208 - log.warn("Not ready to accept update. Dropping {}", deviceDescription); - return; - } - - try { - createOrUpdateDevice(providerId, deviceId, deviceDescription); - } catch (Exception e) { - log.warn("Exception thrown handling device injected event.", e); - } - } - } - - private final class PortInjectedEventListener - implements ClusterMessageHandler { - @Override - public void handle(ClusterMessage message) { - log.debug("Received injected port event from peer: {}", message.sender()); - PortInjectedEvent event = SERIALIZER.decode(message.payload()); - - ProviderId providerId = event.providerId(); - DeviceId deviceId = event.deviceId(); - List<PortDescription> portDescriptions = event.portDescriptions(); - if (!deviceClockService.isTimestampAvailable(deviceId)) { - // workaround for ONOS-1208 - log.warn("Not ready to accept update. Dropping {}", portDescriptions); - return; - } - - try { - updatePorts(providerId, deviceId, portDescriptions); - } catch (Exception e) { - log.warn("Exception thrown handling port injected event.", e); - } - } - } - - private class InternalPortStatsListener - implements EventuallyConsistentMapListener<DeviceId, Map<PortNumber, PortStatistics>> { - @Override - public void event(EventuallyConsistentMapEvent<DeviceId, Map<PortNumber, PortStatistics>> event) { - if (event.type() == PUT) { - Device device = devices.get(event.key()); - if (device != null) { - delegate.notify(new DeviceEvent(PORT_STATS_UPDATED, device)); - } - } - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStoreMessageSubjects.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStoreMessageSubjects.java deleted file mode 100644 index 554faf91..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStoreMessageSubjects.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import org.onosproject.store.cluster.messaging.MessageSubject; - -/** - * MessageSubjects used by GossipDeviceStore peer-peer communication. - */ -public final class GossipDeviceStoreMessageSubjects { - - private GossipDeviceStoreMessageSubjects() {} - - public static final MessageSubject DEVICE_UPDATE = new MessageSubject("peer-device-update"); - public static final MessageSubject DEVICE_OFFLINE = new MessageSubject("peer-device-offline"); - public static final MessageSubject DEVICE_REMOVE_REQ = new MessageSubject("peer-device-remove-request"); - public static final MessageSubject DEVICE_REMOVED = new MessageSubject("peer-device-removed"); - public static final MessageSubject PORT_UPDATE = new MessageSubject("peer-port-update"); - public static final MessageSubject PORT_STATUS_UPDATE = new MessageSubject("peer-port-status-update"); - - public static final MessageSubject DEVICE_ADVERTISE = new MessageSubject("peer-device-advertisements"); - // to be used with 3-way anti-entropy process - public static final MessageSubject DEVICE_REQUEST = new MessageSubject("peer-device-request"); - - // Network elements injected (not discovered) by ConfigProvider - public static final MessageSubject DEVICE_INJECTED = new MessageSubject("peer-device-injected"); - public static final MessageSubject PORT_INJECTED = new MessageSubject("peer-port-injected"); -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceEvent.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceEvent.java deleted file mode 100644 index 6916a3ed..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceEvent.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import org.onosproject.net.DeviceId; -import org.onosproject.net.device.DeviceDescription; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.impl.Timestamped; - -import com.google.common.base.MoreObjects; - -/** - * Information published by GossipDeviceStore to notify peers of a device - * change event. - */ -public class InternalDeviceEvent { - - private final ProviderId providerId; - private final DeviceId deviceId; - private final Timestamped<DeviceDescription> deviceDescription; - - protected InternalDeviceEvent( - ProviderId providerId, - DeviceId deviceId, - Timestamped<DeviceDescription> deviceDescription) { - this.providerId = providerId; - this.deviceId = deviceId; - this.deviceDescription = deviceDescription; - } - - public DeviceId deviceId() { - return deviceId; - } - - public ProviderId providerId() { - return providerId; - } - - public Timestamped<DeviceDescription> deviceDescription() { - return deviceDescription; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("providerId", providerId) - .add("deviceId", deviceId) - .add("deviceDescription", deviceDescription) - .toString(); - } - - // for serializer - protected InternalDeviceEvent() { - this.providerId = null; - this.deviceId = null; - this.deviceDescription = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceEventSerializer.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceEventSerializer.java deleted file mode 100644 index d5fbde7e..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceEventSerializer.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import org.onosproject.net.DeviceId; -import org.onosproject.net.device.DeviceDescription; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.impl.Timestamped; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link InternalDeviceEvent}. - */ -public class InternalDeviceEventSerializer extends Serializer<InternalDeviceEvent> { - - /** - * Creates a serializer for {@link InternalDeviceEvent}. - */ - public InternalDeviceEventSerializer() { - // does not accept null - super(false); - } - - @Override - public void write(Kryo kryo, Output output, InternalDeviceEvent event) { - kryo.writeClassAndObject(output, event.providerId()); - kryo.writeClassAndObject(output, event.deviceId()); - kryo.writeClassAndObject(output, event.deviceDescription()); - } - - @Override - public InternalDeviceEvent read(Kryo kryo, Input input, - Class<InternalDeviceEvent> type) { - ProviderId providerId = (ProviderId) kryo.readClassAndObject(input); - DeviceId deviceId = (DeviceId) kryo.readClassAndObject(input); - - @SuppressWarnings("unchecked") - Timestamped<DeviceDescription> deviceDescription - = (Timestamped<DeviceDescription>) kryo.readClassAndObject(input); - - return new InternalDeviceEvent(providerId, deviceId, deviceDescription); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceOfflineEvent.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceOfflineEvent.java deleted file mode 100644 index 0546c139..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceOfflineEvent.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import org.onosproject.net.DeviceId; -import org.onosproject.store.Timestamp; - -import com.google.common.base.MoreObjects; - -/** - * Information published by GossipDeviceStore to notify peers of a device - * going offline. - */ -public class InternalDeviceOfflineEvent { - - private final DeviceId deviceId; - private final Timestamp timestamp; - - /** - * Creates a InternalDeviceOfflineEvent. - * @param deviceId identifier of device going offline. - * @param timestamp timestamp of when the device went offline. - */ - public InternalDeviceOfflineEvent(DeviceId deviceId, Timestamp timestamp) { - this.deviceId = deviceId; - this.timestamp = timestamp; - } - - public DeviceId deviceId() { - return deviceId; - } - - public Timestamp timestamp() { - return timestamp; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("deviceId", deviceId) - .add("timestamp", timestamp) - .toString(); - } - - // for serializer - @SuppressWarnings("unused") - private InternalDeviceOfflineEvent() { - deviceId = null; - timestamp = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceOfflineEventSerializer.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceOfflineEventSerializer.java deleted file mode 100644 index 7f3c7bcf..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceOfflineEventSerializer.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import org.onosproject.net.DeviceId; -import org.onosproject.store.Timestamp; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link InternalDeviceOfflineEvent}. - */ -public class InternalDeviceOfflineEventSerializer extends Serializer<InternalDeviceOfflineEvent> { - - /** - * Creates a serializer for {@link InternalDeviceOfflineEvent}. - */ - public InternalDeviceOfflineEventSerializer() { - // does not accept null - super(false); - } - - @Override - public void write(Kryo kryo, Output output, InternalDeviceOfflineEvent event) { - kryo.writeClassAndObject(output, event.deviceId()); - kryo.writeClassAndObject(output, event.timestamp()); - } - - @Override - public InternalDeviceOfflineEvent read(Kryo kryo, Input input, - Class<InternalDeviceOfflineEvent> type) { - DeviceId deviceId = (DeviceId) kryo.readClassAndObject(input); - Timestamp timestamp = (Timestamp) kryo.readClassAndObject(input); - - return new InternalDeviceOfflineEvent(deviceId, timestamp); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceRemovedEvent.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceRemovedEvent.java deleted file mode 100644 index e9f4f06a..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalDeviceRemovedEvent.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import org.onosproject.net.DeviceId; -import org.onosproject.store.Timestamp; - -import com.google.common.base.MoreObjects; - -/** - * Information published by GossipDeviceStore to notify peers of a device - * being administratively removed. - */ -public class InternalDeviceRemovedEvent { - - private final DeviceId deviceId; - private final Timestamp timestamp; - - /** - * Creates a InternalDeviceRemovedEvent. - * @param deviceId identifier of the removed device. - * @param timestamp timestamp of when the device was administratively removed. - */ - public InternalDeviceRemovedEvent(DeviceId deviceId, Timestamp timestamp) { - this.deviceId = deviceId; - this.timestamp = timestamp; - } - - public DeviceId deviceId() { - return deviceId; - } - - public Timestamp timestamp() { - return timestamp; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("deviceId", deviceId) - .add("timestamp", timestamp) - .toString(); - } - - // for serializer - @SuppressWarnings("unused") - private InternalDeviceRemovedEvent() { - deviceId = null; - timestamp = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalPortEvent.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalPortEvent.java deleted file mode 100644 index f92fb115..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalPortEvent.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import java.util.List; - -import org.onosproject.net.DeviceId; -import org.onosproject.net.device.PortDescription; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.impl.Timestamped; - -import com.google.common.base.MoreObjects; - -/** - * Information published by GossipDeviceStore to notify peers of a port - * change event. - */ -public class InternalPortEvent { - - private final ProviderId providerId; - private final DeviceId deviceId; - private final Timestamped<List<PortDescription>> portDescriptions; - - protected InternalPortEvent( - ProviderId providerId, - DeviceId deviceId, - Timestamped<List<PortDescription>> portDescriptions) { - this.providerId = providerId; - this.deviceId = deviceId; - this.portDescriptions = portDescriptions; - } - - public DeviceId deviceId() { - return deviceId; - } - - public ProviderId providerId() { - return providerId; - } - - public Timestamped<List<PortDescription>> portDescriptions() { - return portDescriptions; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("providerId", providerId) - .add("deviceId", deviceId) - .add("portDescriptions", portDescriptions) - .toString(); - } - - // for serializer - protected InternalPortEvent() { - this.providerId = null; - this.deviceId = null; - this.portDescriptions = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalPortEventSerializer.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalPortEventSerializer.java deleted file mode 100644 index 0acd703f..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalPortEventSerializer.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import java.util.List; - -import org.onosproject.net.DeviceId; -import org.onosproject.net.device.PortDescription; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.impl.Timestamped; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link InternalPortEvent}. - */ -public class InternalPortEventSerializer extends Serializer<InternalPortEvent> { - - /** - * Creates a serializer for {@link InternalPortEvent}. - */ - public InternalPortEventSerializer() { - // does not accept null - super(false); - } - - @Override - public void write(Kryo kryo, Output output, InternalPortEvent event) { - kryo.writeClassAndObject(output, event.providerId()); - kryo.writeClassAndObject(output, event.deviceId()); - kryo.writeClassAndObject(output, event.portDescriptions()); - } - - @Override - public InternalPortEvent read(Kryo kryo, Input input, - Class<InternalPortEvent> type) { - ProviderId providerId = (ProviderId) kryo.readClassAndObject(input); - DeviceId deviceId = (DeviceId) kryo.readClassAndObject(input); - - @SuppressWarnings("unchecked") - Timestamped<List<PortDescription>> portDescriptions - = (Timestamped<List<PortDescription>>) kryo.readClassAndObject(input); - - return new InternalPortEvent(providerId, deviceId, portDescriptions); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalPortStatusEvent.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalPortStatusEvent.java deleted file mode 100644 index f1781693..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalPortStatusEvent.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import org.onosproject.net.DeviceId; -import org.onosproject.net.device.PortDescription; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.impl.Timestamped; - -import com.google.common.base.MoreObjects; - -/** - * Information published by GossipDeviceStore to notify peers of a port - * status change event. - */ -public class InternalPortStatusEvent { - - private final ProviderId providerId; - private final DeviceId deviceId; - private final Timestamped<PortDescription> portDescription; - - protected InternalPortStatusEvent( - ProviderId providerId, - DeviceId deviceId, - Timestamped<PortDescription> portDescription) { - this.providerId = providerId; - this.deviceId = deviceId; - this.portDescription = portDescription; - } - - public DeviceId deviceId() { - return deviceId; - } - - public ProviderId providerId() { - return providerId; - } - - public Timestamped<PortDescription> portDescription() { - return portDescription; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("providerId", providerId) - .add("deviceId", deviceId) - .add("portDescription", portDescription) - .toString(); - } - - // for serializer - protected InternalPortStatusEvent() { - this.providerId = null; - this.deviceId = null; - this.portDescription = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalPortStatusEventSerializer.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalPortStatusEventSerializer.java deleted file mode 100644 index 32ee3915..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/InternalPortStatusEventSerializer.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import org.onosproject.net.DeviceId; -import org.onosproject.net.device.PortDescription; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.impl.Timestamped; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link InternalPortStatusEvent}. - */ -public class InternalPortStatusEventSerializer extends Serializer<InternalPortStatusEvent> { - - /** - * Creates a serializer for {@link InternalPortStatusEvent}. - */ - public InternalPortStatusEventSerializer() { - // does not accept null - super(false); - } - - @Override - public void write(Kryo kryo, Output output, InternalPortStatusEvent event) { - kryo.writeClassAndObject(output, event.providerId()); - kryo.writeClassAndObject(output, event.deviceId()); - kryo.writeClassAndObject(output, event.portDescription()); - } - - @Override - public InternalPortStatusEvent read(Kryo kryo, Input input, - Class<InternalPortStatusEvent> type) { - ProviderId providerId = (ProviderId) kryo.readClassAndObject(input); - DeviceId deviceId = (DeviceId) kryo.readClassAndObject(input); - @SuppressWarnings("unchecked") - Timestamped<PortDescription> portDescription = (Timestamped<PortDescription>) kryo.readClassAndObject(input); - - return new InternalPortStatusEvent(providerId, deviceId, portDescription); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/PortFragmentId.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/PortFragmentId.java deleted file mode 100644 index 1ff05198..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/PortFragmentId.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import java.util.Objects; - -import org.onosproject.net.DeviceId; -import org.onosproject.net.PortNumber; -import org.onosproject.net.provider.ProviderId; - -import com.google.common.base.MoreObjects; - -/** - * Identifier for PortDescription from a Provider. - */ -public final class PortFragmentId { - public final ProviderId providerId; - public final DeviceId deviceId; - public final PortNumber portNumber; - - public PortFragmentId(DeviceId deviceId, ProviderId providerId, - PortNumber portNumber) { - this.providerId = providerId; - this.deviceId = deviceId; - this.portNumber = portNumber; - } - - @Override - public int hashCode() { - return Objects.hash(providerId, deviceId, portNumber); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof PortFragmentId)) { - return false; - } - PortFragmentId that = (PortFragmentId) obj; - return Objects.equals(this.deviceId, that.deviceId) && - Objects.equals(this.portNumber, that.portNumber) && - Objects.equals(this.providerId, that.providerId); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("providerId", providerId) - .add("deviceId", deviceId) - .add("portNumber", portNumber) - .toString(); - } - - // for serializer - @SuppressWarnings("unused") - private PortFragmentId() { - this.providerId = null; - this.deviceId = null; - this.portNumber = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/PortInjectedEvent.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/PortInjectedEvent.java deleted file mode 100644 index 971f53db..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/PortInjectedEvent.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import com.google.common.base.MoreObjects; -import org.onosproject.net.DeviceId; -import org.onosproject.net.device.PortDescription; -import org.onosproject.net.provider.ProviderId; - -import java.util.List; - -public class PortInjectedEvent { - - private ProviderId providerId; - private DeviceId deviceId; - private List<PortDescription> portDescriptions; - - protected PortInjectedEvent(ProviderId providerId, DeviceId deviceId, List<PortDescription> portDescriptions) { - this.providerId = providerId; - this.deviceId = deviceId; - this.portDescriptions = portDescriptions; - } - - public DeviceId deviceId() { - return deviceId; - } - - public ProviderId providerId() { - return providerId; - } - - public List<PortDescription> portDescriptions() { - return portDescriptions; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("providerId", providerId) - .add("deviceId", deviceId) - .add("portDescriptions", portDescriptions) - .toString(); - } - - // for serializer - protected PortInjectedEvent() { - this.providerId = null; - this.deviceId = null; - this.portDescriptions = null; - } - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/PortKey.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/PortKey.java deleted file mode 100644 index 62b09952..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/PortKey.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import java.util.Objects; - -import org.onosproject.net.DeviceId; -import org.onosproject.net.PortNumber; -import org.onosproject.net.provider.ProviderId; - -import com.google.common.base.MoreObjects; - -/** - * Key for PortDescriptions in ECDeviceStore. - */ -public class PortKey { - private final ProviderId providerId; - private final DeviceId deviceId; - private final PortNumber portNumber; - - public PortKey(ProviderId providerId, DeviceId deviceId, PortNumber portNumber) { - this.providerId = providerId; - this.deviceId = deviceId; - this.portNumber = portNumber; - } - - public ProviderId providerId() { - return providerId; - } - - public DeviceId deviceId() { - return deviceId; - } - - public PortNumber portNumber() { - return portNumber; - } - - @Override - public int hashCode() { - return Objects.hash(providerId, deviceId, portNumber); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof PortKey)) { - return false; - } - PortKey that = (PortKey) obj; - return Objects.equals(this.deviceId, that.deviceId) && - Objects.equals(this.providerId, that.providerId) && - Objects.equals(this.portNumber, that.portNumber); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("providerId", providerId) - .add("deviceId", deviceId) - .add("portNumber", portNumber) - .toString(); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/package-info.java deleted file mode 100644 index 29df62ec..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of distributed device store using p2p synchronization protocol. - */ -package org.onosproject.store.device.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/AntiEntropyAdvertisement.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/AntiEntropyAdvertisement.java deleted file mode 100644 index d783fe22..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/AntiEntropyAdvertisement.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.ecmap; - -import com.google.common.base.MoreObjects; -import com.google.common.collect.ImmutableMap; - -import org.onosproject.cluster.NodeId; - -import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Anti-entropy advertisement message for eventually consistent map. - */ -public class AntiEntropyAdvertisement<K> { - - private final NodeId sender; - private final Map<K, MapValue.Digest> digest; - - /** - * Creates a new anti entropy advertisement message. - * - * @param sender the sender's node ID - * @param digest for map entries - */ - public AntiEntropyAdvertisement(NodeId sender, - Map<K, MapValue.Digest> digest) { - this.sender = checkNotNull(sender); - this.digest = ImmutableMap.copyOf(checkNotNull(digest)); - } - - /** - * Returns the sender's node ID. - * - * @return the sender's node ID - */ - public NodeId sender() { - return sender; - } - - /** - * Returns the digest for map entries. - * - * @return mapping from key to associated digest - */ - public Map<K, MapValue.Digest> digest() { - return digest; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("sender", sender) - .add("totalEntries", digest.size()) - .toString(); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapBuilderImpl.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapBuilderImpl.java deleted file mode 100644 index eb98c829..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapBuilderImpl.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.ecmap; - -import org.onlab.util.KryoNamespace; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.NodeId; -import org.onosproject.persistence.PersistenceService; -import org.onosproject.store.Timestamp; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.EventuallyConsistentMapBuilder; - -import java.util.Collection; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.function.BiFunction; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Eventually consistent map builder. - */ -public class EventuallyConsistentMapBuilderImpl<K, V> - implements EventuallyConsistentMapBuilder<K, V> { - private final ClusterService clusterService; - private final ClusterCommunicationService clusterCommunicator; - - private String name; - private KryoNamespace.Builder serializerBuilder; - private ExecutorService eventExecutor; - private ExecutorService communicationExecutor; - private ScheduledExecutorService backgroundExecutor; - private BiFunction<K, V, Timestamp> timestampProvider; - private BiFunction<K, V, Collection<NodeId>> peerUpdateFunction; - private boolean tombstonesDisabled = false; - private long antiEntropyPeriod = 5; - private TimeUnit antiEntropyTimeUnit = TimeUnit.SECONDS; - private boolean convergeFaster = false; - private boolean persistent = false; - private boolean persistentMap = false; - private final PersistenceService persistenceService; - - /** - * Creates a new eventually consistent map builder. - * - * @param clusterService cluster service - * @param clusterCommunicator cluster communication service - */ - public EventuallyConsistentMapBuilderImpl(ClusterService clusterService, - ClusterCommunicationService clusterCommunicator, - PersistenceService persistenceService) { - this.persistenceService = persistenceService; - this.clusterService = checkNotNull(clusterService); - this.clusterCommunicator = checkNotNull(clusterCommunicator); - } - - @Override - public EventuallyConsistentMapBuilder<K, V> withName(String name) { - this.name = checkNotNull(name); - return this; - } - - @Override - public EventuallyConsistentMapBuilder<K, V> withSerializer( - KryoNamespace.Builder serializerBuilder) { - this.serializerBuilder = checkNotNull(serializerBuilder); - return this; - } - - @Override - public EventuallyConsistentMapBuilder<K, V> withTimestampProvider( - BiFunction<K, V, Timestamp> timestampProvider) { - this.timestampProvider = checkNotNull(timestampProvider); - return this; - } - - @Override - public EventuallyConsistentMapBuilder<K, V> withEventExecutor(ExecutorService executor) { - this.eventExecutor = checkNotNull(executor); - return this; - } - - @Override - public EventuallyConsistentMapBuilder<K, V> withCommunicationExecutor( - ExecutorService executor) { - communicationExecutor = checkNotNull(executor); - return this; - } - - @Override - public EventuallyConsistentMapBuilder<K, V> withBackgroundExecutor(ScheduledExecutorService executor) { - this.backgroundExecutor = checkNotNull(executor); - return this; - } - - @Override - public EventuallyConsistentMapBuilder<K, V> withPeerUpdateFunction( - BiFunction<K, V, Collection<NodeId>> peerUpdateFunction) { - this.peerUpdateFunction = checkNotNull(peerUpdateFunction); - return this; - } - - @Override - public EventuallyConsistentMapBuilder<K, V> withTombstonesDisabled() { - tombstonesDisabled = true; - return this; - } - - @Override - public EventuallyConsistentMapBuilder<K, V> withAntiEntropyPeriod(long period, TimeUnit unit) { - checkArgument(period > 0, "anti-entropy period must be greater than 0"); - antiEntropyPeriod = period; - antiEntropyTimeUnit = checkNotNull(unit); - return this; - } - - @Override - public EventuallyConsistentMapBuilder<K, V> withFasterConvergence() { - convergeFaster = true; - return this; - } - - @Override - public EventuallyConsistentMapBuilder<K, V> withPersistence() { - checkNotNull(this.persistenceService); - persistent = true; - return this; - } - - @Override - public EventuallyConsistentMap<K, V> build() { - checkNotNull(name, "name is a mandatory parameter"); - checkNotNull(serializerBuilder, "serializerBuilder is a mandatory parameter"); - checkNotNull(timestampProvider, "timestampProvider is a mandatory parameter"); - - return new EventuallyConsistentMapImpl<>(name, - clusterService, - clusterCommunicator, - serializerBuilder, - timestampProvider, - peerUpdateFunction, - eventExecutor, - communicationExecutor, - backgroundExecutor, - tombstonesDisabled, - antiEntropyPeriod, - antiEntropyTimeUnit, - convergeFaster, - persistent, - persistenceService); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapImpl.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapImpl.java deleted file mode 100644 index b5ea52e0..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapImpl.java +++ /dev/null @@ -1,679 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.ecmap; - -import com.google.common.collect.Collections2; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import org.apache.commons.lang3.tuple.Pair; -import org.onlab.util.AbstractAccumulator; -import org.onlab.util.KryoNamespace; -import org.onlab.util.SlidingWindowCounter; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.NodeId; -import org.onosproject.persistence.PersistenceService; -import org.onosproject.store.Timestamp; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.cluster.messaging.MessageSubject; -import org.onosproject.store.impl.LogicalTimestamp; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.serializers.KryoSerializer; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.EventuallyConsistentMapEvent; -import org.onosproject.store.service.EventuallyConsistentMapListener; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.WallClockTimestamp; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.Timer; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiFunction; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; -import static org.onlab.util.BoundedThreadPool.newFixedThreadPool; -import static org.onlab.util.Tools.groupedThreads; -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT; -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE; - -/** - * Distributed Map implementation which uses optimistic replication and gossip - * based techniques to provide an eventually consistent data store. - */ -public class EventuallyConsistentMapImpl<K, V> - implements EventuallyConsistentMap<K, V> { - - private static final Logger log = LoggerFactory.getLogger(EventuallyConsistentMapImpl.class); - - private final Map<K, MapValue<V>> items; - - private final ClusterService clusterService; - private final ClusterCommunicationService clusterCommunicator; - private final KryoSerializer serializer; - private final NodeId localNodeId; - private final PersistenceService persistenceService; - - private final BiFunction<K, V, Timestamp> timestampProvider; - - private final MessageSubject updateMessageSubject; - private final MessageSubject antiEntropyAdvertisementSubject; - - private final Set<EventuallyConsistentMapListener<K, V>> listeners - = Sets.newCopyOnWriteArraySet(); - - private final ExecutorService executor; - private final ScheduledExecutorService backgroundExecutor; - private final BiFunction<K, V, Collection<NodeId>> peerUpdateFunction; - - private final ExecutorService communicationExecutor; - private final Map<NodeId, EventAccumulator> senderPending; - - private final String mapName; - - private volatile boolean destroyed = false; - private static final String ERROR_DESTROYED = " map is already destroyed"; - private final String destroyedMessage; - - private static final String ERROR_NULL_KEY = "Key cannot be null"; - private static final String ERROR_NULL_VALUE = "Null values are not allowed"; - - private final long initialDelaySec = 5; - private final boolean lightweightAntiEntropy; - private final boolean tombstonesDisabled; - - private static final int WINDOW_SIZE = 5; - private static final int HIGH_LOAD_THRESHOLD = 0; - private static final int LOAD_WINDOW = 2; - private SlidingWindowCounter counter = new SlidingWindowCounter(WINDOW_SIZE); - - private final boolean persistent; - - private static final String PERSISTENT_LOCAL_MAP_NAME = "itemsMap"; - - - /** - * Creates a new eventually consistent map shared amongst multiple instances. - * <p> - * See {@link org.onosproject.store.service.EventuallyConsistentMapBuilder} - * for more description of the parameters expected by the map. - * </p> - * - * @param mapName a String identifier for the map. - * @param clusterService the cluster service - * @param clusterCommunicator the cluster communications service - * @param serializerBuilder a Kryo namespace builder that can serialize - * both K and V - * @param timestampProvider provider of timestamps for K and V - * @param peerUpdateFunction function that provides a set of nodes to immediately - * update to when there writes to the map - * @param eventExecutor executor to use for processing incoming - * events from peers - * @param communicationExecutor executor to use for sending events to peers - * @param backgroundExecutor executor to use for background anti-entropy - * tasks - * @param tombstonesDisabled true if this map should not maintain - * tombstones - * @param antiEntropyPeriod period that the anti-entropy task should run - * @param antiEntropyTimeUnit time unit for anti-entropy period - * @param convergeFaster make anti-entropy try to converge faster - * @param persistent persist data to disk - */ - EventuallyConsistentMapImpl(String mapName, - ClusterService clusterService, - ClusterCommunicationService clusterCommunicator, - KryoNamespace.Builder serializerBuilder, - BiFunction<K, V, Timestamp> timestampProvider, - BiFunction<K, V, Collection<NodeId>> peerUpdateFunction, - ExecutorService eventExecutor, - ExecutorService communicationExecutor, - ScheduledExecutorService backgroundExecutor, - boolean tombstonesDisabled, - long antiEntropyPeriod, - TimeUnit antiEntropyTimeUnit, - boolean convergeFaster, - boolean persistent, - PersistenceService persistenceService) { - this.mapName = mapName; - this.serializer = createSerializer(serializerBuilder); - this.persistenceService = persistenceService; - this.persistent = - persistent; - if (persistent) { - items = this.persistenceService.<K, MapValue<V>>persistentMapBuilder() - .withName(PERSISTENT_LOCAL_MAP_NAME) - .withSerializer(new Serializer() { - - @Override - public <T> byte[] encode(T object) { - return EventuallyConsistentMapImpl.this.serializer.encode(object); - } - - @Override - public <T> T decode(byte[] bytes) { - return EventuallyConsistentMapImpl.this.serializer.decode(bytes); - } - }) - .build(); - } else { - items = Maps.newConcurrentMap(); - } - senderPending = Maps.newConcurrentMap(); - destroyedMessage = mapName + ERROR_DESTROYED; - - this.clusterService = clusterService; - this.clusterCommunicator = clusterCommunicator; - this.localNodeId = clusterService.getLocalNode().id(); - - this.timestampProvider = timestampProvider; - - if (peerUpdateFunction != null) { - this.peerUpdateFunction = peerUpdateFunction; - } else { - this.peerUpdateFunction = (key, value) -> clusterService.getNodes().stream() - .map(ControllerNode::id) - .filter(nodeId -> !nodeId.equals(localNodeId)) - .collect(Collectors.toList()); - } - - if (eventExecutor != null) { - this.executor = eventExecutor; - } else { - // should be a normal executor; it's used for receiving messages - this.executor = - Executors.newFixedThreadPool(8, groupedThreads("onos/ecm", mapName + "-fg-%d")); - } - - if (communicationExecutor != null) { - this.communicationExecutor = communicationExecutor; - } else { - // sending executor; should be capped - //TODO this probably doesn't need to be bounded anymore - this.communicationExecutor = - newFixedThreadPool(8, groupedThreads("onos/ecm", mapName + "-publish-%d")); - } - - - if (backgroundExecutor != null) { - this.backgroundExecutor = backgroundExecutor; - } else { - this.backgroundExecutor = - newSingleThreadScheduledExecutor(groupedThreads("onos/ecm", mapName + "-bg-%d")); - } - - // start anti-entropy thread - this.backgroundExecutor.scheduleAtFixedRate(this::sendAdvertisement, - initialDelaySec, antiEntropyPeriod, - antiEntropyTimeUnit); - - updateMessageSubject = new MessageSubject("ecm-" + mapName + "-update"); - clusterCommunicator.addSubscriber(updateMessageSubject, - serializer::decode, - this::processUpdates, - this.executor); - - antiEntropyAdvertisementSubject = new MessageSubject("ecm-" + mapName + "-anti-entropy"); - clusterCommunicator.addSubscriber(antiEntropyAdvertisementSubject, - serializer::decode, - this::handleAntiEntropyAdvertisement, - this.backgroundExecutor); - - this.tombstonesDisabled = tombstonesDisabled; - this.lightweightAntiEntropy = !convergeFaster; - } - - private KryoSerializer createSerializer(KryoNamespace.Builder builder) { - return new KryoSerializer() { - @Override - protected void setupKryoPool() { - // Add the map's internal helper classes to the user-supplied serializer - serializerPool = builder - .register(KryoNamespaces.BASIC) - .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID) - .register(LogicalTimestamp.class) - .register(WallClockTimestamp.class) - .register(AntiEntropyAdvertisement.class) - .register(UpdateEntry.class) - .register(MapValue.class) - .register(MapValue.Digest.class) - .build(); - } - }; - } - - @Override - public int size() { - checkState(!destroyed, destroyedMessage); - // TODO: Maintain a separate counter for tracking live elements in map. - return Maps.filterValues(items, MapValue::isAlive).size(); - } - - @Override - public boolean isEmpty() { - checkState(!destroyed, destroyedMessage); - return size() == 0; - } - - @Override - public boolean containsKey(K key) { - checkState(!destroyed, destroyedMessage); - checkNotNull(key, ERROR_NULL_KEY); - return get(key) != null; - } - - @Override - public boolean containsValue(V value) { - checkState(!destroyed, destroyedMessage); - checkNotNull(value, ERROR_NULL_VALUE); - return items.values() - .stream() - .filter(MapValue::isAlive) - .anyMatch(v -> value.equals(v.get())); - } - - @Override - public V get(K key) { - checkState(!destroyed, destroyedMessage); - checkNotNull(key, ERROR_NULL_KEY); - - MapValue<V> value = items.get(key); - return (value == null || value.isTombstone()) ? null : value.get(); - } - - @Override - public void put(K key, V value) { - checkState(!destroyed, destroyedMessage); - checkNotNull(key, ERROR_NULL_KEY); - checkNotNull(value, ERROR_NULL_VALUE); - - MapValue<V> newValue = new MapValue<>(value, timestampProvider.apply(key, value)); - if (putInternal(key, newValue)) { - notifyPeers(new UpdateEntry<>(key, newValue), peerUpdateFunction.apply(key, value)); - notifyListeners(new EventuallyConsistentMapEvent<>(mapName, PUT, key, value)); - } - } - - @Override - public V remove(K key) { - checkState(!destroyed, destroyedMessage); - checkNotNull(key, ERROR_NULL_KEY); - return removeAndNotify(key, null); - } - - @Override - public void remove(K key, V value) { - checkState(!destroyed, destroyedMessage); - checkNotNull(key, ERROR_NULL_KEY); - checkNotNull(value, ERROR_NULL_VALUE); - removeAndNotify(key, value); - } - - private V removeAndNotify(K key, V value) { - Timestamp timestamp = timestampProvider.apply(key, value); - Optional<MapValue<V>> tombstone = tombstonesDisabled || timestamp == null - ? Optional.empty() : Optional.of(MapValue.tombstone(timestamp)); - MapValue<V> previousValue = removeInternal(key, Optional.ofNullable(value), tombstone); - if (previousValue != null) { - notifyPeers(new UpdateEntry<>(key, tombstone.orElse(null)), - peerUpdateFunction.apply(key, previousValue.get())); - if (previousValue.isAlive()) { - notifyListeners(new EventuallyConsistentMapEvent<>(mapName, REMOVE, key, previousValue.get())); - } - } - return previousValue != null ? previousValue.get() : null; - } - - private MapValue<V> removeInternal(K key, Optional<V> value, Optional<MapValue<V>> tombstone) { - checkState(!destroyed, destroyedMessage); - checkNotNull(key, ERROR_NULL_KEY); - checkNotNull(value, ERROR_NULL_VALUE); - tombstone.ifPresent(v -> checkState(v.isTombstone())); - - counter.incrementCount(); - AtomicBoolean updated = new AtomicBoolean(false); - AtomicReference<MapValue<V>> previousValue = new AtomicReference<>(); - items.compute(key, (k, existing) -> { - boolean valueMatches = true; - if (value.isPresent() && existing != null && existing.isAlive()) { - valueMatches = Objects.equals(value.get(), existing.get()); - } - if (existing == null) { - log.trace("ECMap Remove: Existing value for key {} is already null", k); - } - if (valueMatches) { - if (existing == null) { - updated.set(tombstone.isPresent()); - } else { - updated.set(!tombstone.isPresent() || tombstone.get().isNewerThan(existing)); - } - } - if (updated.get()) { - previousValue.set(existing); - return tombstone.orElse(null); - } else { - return existing; - } - }); - return previousValue.get(); - } - - @Override - public V compute(K key, BiFunction<K, V, V> recomputeFunction) { - checkState(!destroyed, destroyedMessage); - checkNotNull(key, ERROR_NULL_KEY); - checkNotNull(recomputeFunction, "Recompute function cannot be null"); - - AtomicBoolean updated = new AtomicBoolean(false); - AtomicReference<MapValue<V>> previousValue = new AtomicReference<>(); - MapValue<V> computedValue = items.compute(key, (k, mv) -> { - previousValue.set(mv); - V newRawValue = recomputeFunction.apply(key, mv == null ? null : mv.get()); - MapValue<V> newValue = new MapValue<>(newRawValue, timestampProvider.apply(key, newRawValue)); - if (mv == null || newValue.isNewerThan(mv)) { - updated.set(true); - return newValue; - } else { - return mv; - } - }); - if (updated.get()) { - notifyPeers(new UpdateEntry<>(key, computedValue), peerUpdateFunction.apply(key, computedValue.get())); - EventuallyConsistentMapEvent.Type updateType = computedValue.isTombstone() ? REMOVE : PUT; - V value = computedValue.isTombstone() - ? previousValue.get() == null ? null : previousValue.get().get() - : computedValue.get(); - if (value != null) { - notifyListeners(new EventuallyConsistentMapEvent<>(mapName, updateType, key, value)); - } - } - return computedValue.get(); - } - - @Override - public void putAll(Map<? extends K, ? extends V> m) { - checkState(!destroyed, destroyedMessage); - m.forEach(this::put); - } - - @Override - public void clear() { - checkState(!destroyed, destroyedMessage); - Maps.filterValues(items, MapValue::isAlive) - .forEach((k, v) -> remove(k)); - } - - @Override - public Set<K> keySet() { - checkState(!destroyed, destroyedMessage); - return Maps.filterValues(items, MapValue::isAlive) - .keySet(); - } - - @Override - public Collection<V> values() { - checkState(!destroyed, destroyedMessage); - return Collections2.transform(Maps.filterValues(items, MapValue::isAlive).values(), MapValue::get); - } - - @Override - public Set<Map.Entry<K, V>> entrySet() { - checkState(!destroyed, destroyedMessage); - return Maps.filterValues(items, MapValue::isAlive) - .entrySet() - .stream() - .map(e -> Pair.of(e.getKey(), e.getValue().get())) - .collect(Collectors.toSet()); - } - - /** - * Returns true if newValue was accepted i.e. map is updated. - * - * @param key key - * @param newValue proposed new value - * @return true if update happened; false if map already contains a more recent value for the key - */ - private boolean putInternal(K key, MapValue<V> newValue) { - checkState(!destroyed, destroyedMessage); - checkNotNull(key, ERROR_NULL_KEY); - checkNotNull(newValue, ERROR_NULL_VALUE); - checkState(newValue.isAlive()); - counter.incrementCount(); - AtomicBoolean updated = new AtomicBoolean(false); - items.compute(key, (k, existing) -> { - if (existing == null || newValue.isNewerThan(existing)) { - updated.set(true); - return newValue; - } - return existing; - }); - return updated.get(); - } - - @Override - public void addListener(EventuallyConsistentMapListener<K, V> listener) { - checkState(!destroyed, destroyedMessage); - - listeners.add(checkNotNull(listener)); - } - - @Override - public void removeListener(EventuallyConsistentMapListener<K, V> listener) { - checkState(!destroyed, destroyedMessage); - - listeners.remove(checkNotNull(listener)); - } - - @Override - public void destroy() { - destroyed = true; - - executor.shutdown(); - backgroundExecutor.shutdown(); - communicationExecutor.shutdown(); - - listeners.clear(); - - clusterCommunicator.removeSubscriber(updateMessageSubject); - clusterCommunicator.removeSubscriber(antiEntropyAdvertisementSubject); - } - - private void notifyListeners(EventuallyConsistentMapEvent<K, V> event) { - listeners.forEach(listener -> listener.event(event)); - } - - private void notifyPeers(UpdateEntry<K, V> event, Collection<NodeId> peers) { - queueUpdate(event, peers); - } - - private void queueUpdate(UpdateEntry<K, V> event, Collection<NodeId> peers) { - if (peers == null) { - // we have no friends :( - return; - } - peers.forEach(node -> - senderPending.computeIfAbsent(node, unusedKey -> new EventAccumulator(node)).add(event) - ); - } - - private boolean underHighLoad() { - return counter.get(LOAD_WINDOW) > HIGH_LOAD_THRESHOLD; - } - - private void sendAdvertisement() { - try { - if (underHighLoad() || destroyed) { - return; - } - pickRandomActivePeer().ifPresent(this::sendAdvertisementToPeer); - } catch (Exception e) { - // Catch all exceptions to avoid scheduled task being suppressed. - log.error("Exception thrown while sending advertisement", e); - } - } - - private Optional<NodeId> pickRandomActivePeer() { - List<NodeId> activePeers = clusterService.getNodes() - .stream() - .map(ControllerNode::id) - .filter(id -> !localNodeId.equals(id)) - .filter(id -> clusterService.getState(id) == ControllerNode.State.ACTIVE) - .collect(Collectors.toList()); - Collections.shuffle(activePeers); - return activePeers.isEmpty() ? Optional.empty() : Optional.of(activePeers.get(0)); - } - - private void sendAdvertisementToPeer(NodeId peer) { - clusterCommunicator.unicast(createAdvertisement(), - antiEntropyAdvertisementSubject, - serializer::encode, - peer) - .whenComplete((result, error) -> { - if (error != null) { - log.debug("Failed to send anti-entropy advertisement to {}", peer, error); - } - }); - } - - private AntiEntropyAdvertisement<K> createAdvertisement() { - return new AntiEntropyAdvertisement<K>(localNodeId, - ImmutableMap.copyOf(Maps.transformValues(items, MapValue::digest))); - } - - private void handleAntiEntropyAdvertisement(AntiEntropyAdvertisement<K> ad) { - if (destroyed || underHighLoad()) { - return; - } - try { - if (log.isTraceEnabled()) { - log.trace("Received anti-entropy advertisement from {} for {} with {} entries in it", - mapName, ad.sender(), ad.digest().size()); - } - antiEntropyCheckLocalItems(ad).forEach(this::notifyListeners); - - if (!lightweightAntiEntropy) { - // if remote ad has any entries that the local copy is missing, actively sync - // TODO: Missing keys is not the way local copy can be behind. - if (Sets.difference(ad.digest().keySet(), items.keySet()).size() > 0) { - // TODO: Send ad for missing keys and for entries that are stale - sendAdvertisementToPeer(ad.sender()); - } - } - } catch (Exception e) { - log.warn("Error handling anti-entropy advertisement", e); - } - } - - /** - * Processes anti-entropy ad from peer by taking following actions: - * 1. If peer has an old entry, updates peer. - * 2. If peer indicates an entry is removed and has a more recent - * timestamp than the local entry, update local state. - */ - private List<EventuallyConsistentMapEvent<K, V>> antiEntropyCheckLocalItems( - AntiEntropyAdvertisement<K> ad) { - final List<EventuallyConsistentMapEvent<K, V>> externalEvents = Lists.newLinkedList(); - final NodeId sender = ad.sender(); - items.forEach((key, localValue) -> { - MapValue.Digest remoteValueDigest = ad.digest().get(key); - if (remoteValueDigest == null || localValue.isNewerThan(remoteValueDigest.timestamp())) { - // local value is more recent, push to sender - queueUpdate(new UpdateEntry<>(key, localValue), ImmutableList.of(sender)); - } - if (remoteValueDigest != null - && remoteValueDigest.isNewerThan(localValue.digest()) - && remoteValueDigest.isTombstone()) { - MapValue<V> tombstone = MapValue.tombstone(remoteValueDigest.timestamp()); - MapValue<V> previousValue = removeInternal(key, - Optional.empty(), - Optional.of(tombstone)); - if (previousValue != null && previousValue.isAlive()) { - externalEvents.add(new EventuallyConsistentMapEvent<>(mapName, REMOVE, key, previousValue.get())); - } - } - }); - return externalEvents; - } - - private void processUpdates(Collection<UpdateEntry<K, V>> updates) { - if (destroyed) { - return; - } - updates.forEach(update -> { - final K key = update.key(); - final MapValue<V> value = update.value(); - if (value == null || value.isTombstone()) { - MapValue<V> previousValue = removeInternal(key, Optional.empty(), Optional.ofNullable(value)); - if (previousValue != null && previousValue.isAlive()) { - notifyListeners(new EventuallyConsistentMapEvent<>(mapName, REMOVE, key, previousValue.get())); - } - } else if (putInternal(key, value)) { - notifyListeners(new EventuallyConsistentMapEvent<>(mapName, PUT, key, value.get())); - } - }); - } - - // TODO pull this into the class if this gets pulled out... - private static final int DEFAULT_MAX_EVENTS = 1000; - private static final int DEFAULT_MAX_IDLE_MS = 10; - private static final int DEFAULT_MAX_BATCH_MS = 50; - private static final Timer TIMER = new Timer("onos-ecm-sender-events"); - - private final class EventAccumulator extends AbstractAccumulator<UpdateEntry<K, V>> { - - private final NodeId peer; - - private EventAccumulator(NodeId peer) { - super(TIMER, DEFAULT_MAX_EVENTS, DEFAULT_MAX_BATCH_MS, DEFAULT_MAX_IDLE_MS); - this.peer = peer; - } - - @Override - public void processItems(List<UpdateEntry<K, V>> items) { - Map<K, UpdateEntry<K, V>> map = Maps.newHashMap(); - items.forEach(item -> map.compute(item.key(), (key, existing) -> - item.isNewerThan(existing) ? item : existing)); - communicationExecutor.submit(() -> { - clusterCommunicator.unicast(ImmutableList.copyOf(map.values()), - updateMessageSubject, - serializer::encode, - peer) - .whenComplete((result, error) -> { - if (error != null) { - log.debug("Failed to send to {}", peer, error); - } - }); - }); - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapDbPersistentStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapDbPersistentStore.java deleted file mode 100644 index f5ce47fc..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapDbPersistentStore.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.ecmap; - -import org.mapdb.DB; -import org.mapdb.DBMaker; -import org.mapdb.Hasher; -import org.mapdb.Serializer; -import org.onosproject.store.serializers.KryoSerializer; - -import java.io.File; -import java.util.Map; -import java.util.concurrent.ExecutorService; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * MapDB based implementation of a persistent store. - */ -class MapDbPersistentStore<K, V> implements PersistentStore<K, V> { - - private final ExecutorService executor; - private final KryoSerializer serializer; - - private final DB database; - - private final Map<byte[], byte[]> items; - - /** - * Creates a new MapDB based persistent store. - * - * @param filename filename of the database on disk - * @param executor executor to use for tasks that write to the disk - * @param serializer serializer for keys and values - */ - MapDbPersistentStore(String filename, ExecutorService executor, - KryoSerializer serializer) { - this.executor = checkNotNull(executor); - this.serializer = checkNotNull(serializer); - - File databaseFile = new File(filename); - - database = DBMaker.newFileDB(databaseFile).make(); - - items = database.createHashMap("items") - .keySerializer(Serializer.BYTE_ARRAY) - .valueSerializer(Serializer.BYTE_ARRAY) - .hasher(Hasher.BYTE_ARRAY) - .makeOrGet(); - } - - @Override - public void readInto(Map<K, MapValue<V>> items) { - this.items.forEach((keyBytes, valueBytes) -> - items.put(serializer.decode(keyBytes), - serializer.decode(valueBytes))); - } - - @Override - public void update(K key, MapValue<V> value) { - executor.submit(() -> updateInternal(key, value)); - } - - @Override - public void remove(K key) { - executor.submit(() -> removeInternal(key)); - } - - private void updateInternal(K key, MapValue<V> newValue) { - byte[] keyBytes = serializer.encode(key); - - items.compute(keyBytes, (k, existingBytes) -> { - MapValue<V> existing = existingBytes == null ? null : - serializer.decode(existingBytes); - if (existing == null || newValue.isNewerThan(existing)) { - return serializer.encode(newValue); - } else { - return existingBytes; - } - }); - database.commit(); - } - - private void removeInternal(K key) { - byte[] keyBytes = serializer.encode(key); - items.remove(keyBytes); - database.commit(); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapValue.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapValue.java deleted file mode 100644 index bb69b472..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapValue.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.ecmap; - -import org.onosproject.store.Timestamp; - -import com.google.common.base.MoreObjects; -import com.google.common.base.Objects; - -/** - * Representation of a value in EventuallyConsistentMap. - * - * @param <V> value type - */ -public class MapValue<V> implements Comparable<MapValue<V>> { - private final Timestamp timestamp; - private final V value; - - /** - * Creates a tombstone value with the specified timestamp. - * @param timestamp timestamp for tombstone - * @return tombstone MapValue - * - * @param <U> value type - */ - public static <U> MapValue<U> tombstone(Timestamp timestamp) { - return new MapValue<>(null, timestamp); - } - - public MapValue(V value, Timestamp timestamp) { - this.value = value; - this.timestamp = timestamp; - } - - public boolean isTombstone() { - return value == null; - } - - public boolean isAlive() { - return value != null; - } - - public Timestamp timestamp() { - return timestamp; - } - - public V get() { - return value; - } - - @Override - public int compareTo(MapValue<V> o) { - return this.timestamp.compareTo(o.timestamp); - } - - public boolean isNewerThan(MapValue<V> other) { - return timestamp.isNewerThan(other.timestamp); - } - - public boolean isNewerThan(Timestamp timestamp) { - return this.timestamp.isNewerThan(timestamp); - } - - public Digest digest() { - return new Digest(timestamp, isTombstone()); - } - - @Override - public int hashCode() { - return Objects.hashCode(timestamp, value); - } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object other) { - if (other instanceof MapValue) { - MapValue<V> that = (MapValue<V>) other; - return Objects.equal(this.timestamp, that.timestamp) && - Objects.equal(this.value, that.value); - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("timestamp", timestamp) - .add("value", value) - .toString(); - } - - @SuppressWarnings("unused") - private MapValue() { - this.timestamp = null; - this.value = null; - } - - /** - * Digest or summary of a MapValue for use during Anti-Entropy exchanges. - */ - public static class Digest { - private final Timestamp timestamp; - private final boolean isTombstone; - - public Digest(Timestamp timestamp, boolean isTombstone) { - this.timestamp = timestamp; - this.isTombstone = isTombstone; - } - - public Timestamp timestamp() { - return timestamp; - } - - public boolean isTombstone() { - return isTombstone; - } - - public boolean isNewerThan(Digest other) { - return timestamp.isNewerThan(other.timestamp); - } - - @Override - public int hashCode() { - return Objects.hashCode(timestamp, isTombstone); - } - - @Override - public boolean equals(Object other) { - if (other instanceof Digest) { - Digest that = (Digest) other; - return Objects.equal(this.timestamp, that.timestamp) && - Objects.equal(this.isTombstone, that.isTombstone); - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("timestamp", timestamp) - .add("isTombstone", isTombstone) - .toString(); - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/PersistentStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/PersistentStore.java deleted file mode 100644 index e85987a7..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/PersistentStore.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.ecmap; - -import java.util.Map; - -/** - * A persistent store for an eventually consistent map. - */ -interface PersistentStore<K, V> { - - /** - * Read the contents of the disk into the given maps. - * - * @param items items map - */ - void readInto(Map<K, MapValue<V>> items); - - /** - * Updates a key,value pair in the persistent store. - * - * @param key the key - * @param value the value - */ - void update(K key, MapValue<V> value); - - /** - * Removes a key from persistent store. - * - * @param key the key to remove - */ - void remove(K key); -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/UpdateEntry.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/UpdateEntry.java deleted file mode 100644 index 53683b98..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/UpdateEntry.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.ecmap; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.base.MoreObjects; - -/** - * Describes a single update event in an EventuallyConsistentMap. - */ -final class UpdateEntry<K, V> { - private final K key; - private final MapValue<V> value; - - /** - * Creates a new update entry. - * - * @param key key of the entry - * @param value value of the entry - */ - public UpdateEntry(K key, MapValue<V> value) { - this.key = checkNotNull(key); - this.value = value; - } - - /** - * Returns the key. - * - * @return the key - */ - public K key() { - return key; - } - - /** - * Returns the value of the entry. - * - * @return the value - */ - public MapValue<V> value() { - return value; - } - - /** - * Returns if this entry is newer than other entry. - * @param other other entry - * @return true if this entry is newer; false otherwise - */ - public boolean isNewerThan(UpdateEntry<K, V> other) { - return other == null || other.value == null || (value != null && value.isNewerThan(other.value)); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("key", key()) - .add("value", value) - .toString(); - } - - @SuppressWarnings("unused") - private UpdateEntry() { - this.key = null; - this.value = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/package-info.java deleted file mode 100644 index 81fd2868..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Distributed map with eventually-consistent update semantics and gossip - * based anti-entropy mechanism. - */ -package org.onosproject.store.ecmap;
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/ReplicaInfo.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/ReplicaInfo.java deleted file mode 100644 index 6011c16c..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/ReplicaInfo.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.flow; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.Collections; -import java.util.List; - -import org.onosproject.cluster.NodeId; - -import com.google.common.base.Objects; -import com.google.common.base.Optional; - -/** - * Class to represent placement information about Master/Backup copy. - */ -public final class ReplicaInfo { - - private final Optional<NodeId> master; - private final List<NodeId> backups; - - /** - * Creates a ReplicaInfo instance. - * - * @param master NodeId of the node where the master copy should be - * @param backups list of NodeId, where backup copies should be placed - */ - public ReplicaInfo(NodeId master, List<NodeId> backups) { - this.master = Optional.fromNullable(master); - this.backups = checkNotNull(backups); - } - - /** - * Returns the NodeId, if there is a Node where the master copy should be. - * - * @return NodeId, where the master copy should be placed - */ - public Optional<NodeId> master() { - return master; - } - - /** - * Returns the collection of NodeId, where backup copies should be placed. - * - * @return collection of NodeId, where backup copies should be placed - */ - public List<NodeId> backups() { - return backups; - } - - @Override - public int hashCode() { - return Objects.hashCode(master, backups); - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof ReplicaInfo)) { - return false; - } - ReplicaInfo that = (ReplicaInfo) other; - return Objects.equal(this.master, that.master) && - Objects.equal(this.backups, that.backups); - } - - // for Serializer - private ReplicaInfo() { - this.master = Optional.absent(); - this.backups = Collections.emptyList(); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/ReplicaInfoEvent.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/ReplicaInfoEvent.java deleted file mode 100644 index 962fe8f4..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/ReplicaInfoEvent.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.flow; - -import static com.google.common.base.Preconditions.checkNotNull; - -import org.onosproject.event.AbstractEvent; -import org.onosproject.net.DeviceId; - -/** - * Describes a device replicainfo event. - */ -public class ReplicaInfoEvent extends AbstractEvent<ReplicaInfoEvent.Type, DeviceId> { - - private final ReplicaInfo replicaInfo; - - /** - * Types of Replica info event. - */ - public enum Type { - /** - * Event to notify that master placement should be changed. - */ - MASTER_CHANGED, - // - BACKUPS_CHANGED, - } - - - /** - * Creates an event of a given type and for the specified device, - * and replica info. - * - * @param type replicainfo event type - * @param device event device subject - * @param replicaInfo replicainfo - */ - public ReplicaInfoEvent(Type type, DeviceId device, ReplicaInfo replicaInfo) { - super(type, device); - this.replicaInfo = checkNotNull(replicaInfo); - } - - /** - * Returns the current replica information for the subject. - * - * @return replica information for the subject - */ - public ReplicaInfo replicaInfo() { - return replicaInfo; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/ReplicaInfoEventListener.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/ReplicaInfoEventListener.java deleted file mode 100644 index b6761d1d..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/ReplicaInfoEventListener.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.flow; - -import org.onosproject.event.EventListener; - -/** - * Entity capable of receiving Replica placement information-related events. - */ -public interface ReplicaInfoEventListener extends EventListener<ReplicaInfoEvent> { - -} - diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/ReplicaInfoService.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/ReplicaInfoService.java deleted file mode 100644 index bf60f931..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/ReplicaInfoService.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.flow; - -import org.onosproject.net.DeviceId; - -/** - * Service to return where the replica should be placed. - */ -public interface ReplicaInfoService { - - // returns where it should be. - /** - * Returns the placement information for given Device. - * - * @param deviceId identifier of the device - * @return placement information - */ - ReplicaInfo getReplicaInfoFor(DeviceId deviceId); - - /** - * Adds the specified replica placement info change listener. - * - * @param listener the replica placement info change listener - */ - void addListener(ReplicaInfoEventListener listener); - - /** - * Removes the specified replica placement info change listener. - * - * @param listener the replica placement info change listener - */ - void removeListener(ReplicaInfoEventListener listener); - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/FlowStoreMessageSubjects.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/FlowStoreMessageSubjects.java deleted file mode 100644 index 041053cf..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/FlowStoreMessageSubjects.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.flow.impl; - -import org.onosproject.store.cluster.messaging.MessageSubject; - -/** - * MessageSubjects used by DistributedFlowRuleStore peer-peer communication. - */ -public final class FlowStoreMessageSubjects { - private FlowStoreMessageSubjects() {} - - public static final MessageSubject APPLY_BATCH_FLOWS - = new MessageSubject("peer-forward-apply-batch"); - - public static final MessageSubject GET_FLOW_ENTRY - = new MessageSubject("peer-forward-get-flow-entry"); - - public static final MessageSubject GET_DEVICE_FLOW_ENTRIES - = new MessageSubject("peer-forward-get-device-flow-entries"); - - public static final MessageSubject REMOVE_FLOW_ENTRY - = new MessageSubject("peer-forward-remove-flow-entry"); - - public static final MessageSubject REMOTE_APPLY_COMPLETED - = new MessageSubject("peer-apply-completed"); - - public static final MessageSubject FLOW_TABLE_BACKUP - = new MessageSubject("peer-flow-table-backup"); -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/NewDistributedFlowRuleStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/NewDistributedFlowRuleStore.java deleted file mode 100644 index 1695e5ff..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/NewDistributedFlowRuleStore.java +++ /dev/null @@ -1,880 +0,0 @@ - /* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.flow.impl; - -import com.google.common.base.Objects; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.common.util.concurrent.Futures; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Modified; -import org.apache.felix.scr.annotations.Property; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onlab.util.Tools; -import org.onosproject.cfg.ComponentConfigService; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.NodeId; -import org.onosproject.core.CoreService; -import org.onosproject.core.IdGenerator; -import org.onosproject.mastership.MastershipService; -import org.onosproject.net.DeviceId; -import org.onosproject.net.device.DeviceService; -import org.onosproject.net.flow.CompletedBatchOperation; -import org.onosproject.net.flow.DefaultFlowEntry; -import org.onosproject.net.flow.FlowEntry; -import org.onosproject.net.flow.FlowEntry.FlowEntryState; -import org.onosproject.net.flow.FlowId; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleBatchEntry; -import org.onosproject.net.flow.FlowRuleBatchEntry.FlowRuleOperation; -import org.onosproject.net.flow.FlowRuleBatchEvent; -import org.onosproject.net.flow.FlowRuleBatchOperation; -import org.onosproject.net.flow.FlowRuleBatchRequest; -import org.onosproject.net.flow.FlowRuleEvent; -import org.onosproject.net.flow.FlowRuleEvent.Type; -import org.onosproject.net.flow.FlowRuleService; -import org.onosproject.net.flow.FlowRuleStore; -import org.onosproject.net.flow.FlowRuleStoreDelegate; -import org.onosproject.net.flow.StoredFlowEntry; -import org.onosproject.net.flow.TableStatisticsEntry; -import org.onosproject.persistence.PersistenceService; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.cluster.messaging.ClusterMessage; -import org.onosproject.store.cluster.messaging.ClusterMessageHandler; -import org.onosproject.store.flow.ReplicaInfoEvent; -import org.onosproject.store.flow.ReplicaInfoEventListener; -import org.onosproject.store.flow.ReplicaInfoService; -import org.onosproject.store.impl.MastershipBasedTimestamp; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.serializers.KryoSerializer; -import org.onosproject.store.serializers.StoreSerializer; -import org.onosproject.store.serializers.custom.DistributedStoreSerializers; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.EventuallyConsistentMapEvent; -import org.onosproject.store.service.EventuallyConsistentMapListener; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.StorageService; -import org.onosproject.store.service.WallClockTimestamp; -import org.osgi.service.component.ComponentContext; -import org.slf4j.Logger; - -import java.util.Collections; -import java.util.Dictionary; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; - -import static com.google.common.base.Strings.isNullOrEmpty; -import static org.onlab.util.Tools.get; -import static org.onlab.util.Tools.groupedThreads; -import static org.onosproject.net.flow.FlowRuleEvent.Type.RULE_REMOVED; -import static org.onosproject.store.flow.impl.FlowStoreMessageSubjects.*; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Manages inventory of flow rules using a distributed state management protocol. - */ -@Component(immediate = true, enabled = true) -@Service -public class NewDistributedFlowRuleStore - extends AbstractStore<FlowRuleBatchEvent, FlowRuleStoreDelegate> - implements FlowRuleStore { - - private final Logger log = getLogger(getClass()); - - private static final int MESSAGE_HANDLER_THREAD_POOL_SIZE = 8; - private static final boolean DEFAULT_BACKUP_ENABLED = true; - private static final boolean DEFAULT_PERSISTENCE_ENABLED = false; - private static final int DEFAULT_BACKUP_PERIOD_MILLIS = 2000; - private static final long FLOW_RULE_STORE_TIMEOUT_MILLIS = 5000; - // number of devices whose flow entries will be backed up in one communication round - private static final int FLOW_TABLE_BACKUP_BATCH_SIZE = 1; - - @Property(name = "msgHandlerPoolSize", intValue = MESSAGE_HANDLER_THREAD_POOL_SIZE, - label = "Number of threads in the message handler pool") - private int msgHandlerPoolSize = MESSAGE_HANDLER_THREAD_POOL_SIZE; - - @Property(name = "backupEnabled", boolValue = DEFAULT_BACKUP_ENABLED, - label = "Indicates whether backups are enabled or not") - private boolean backupEnabled = DEFAULT_BACKUP_ENABLED; - - @Property(name = "backupPeriod", intValue = DEFAULT_BACKUP_PERIOD_MILLIS, - label = "Delay in ms between successive backup runs") - private int backupPeriod = DEFAULT_BACKUP_PERIOD_MILLIS; - @Property(name = "persistenceEnabled", boolValue = false, - label = "Indicates whether or not changes in the flow table should be persisted to disk.") - private boolean persistenceEnabled = DEFAULT_PERSISTENCE_ENABLED; - - private InternalFlowTable flowTable = new InternalFlowTable(); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ReplicaInfoService replicaInfoManager; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterCommunicationService clusterCommunicator; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected DeviceService deviceService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected CoreService coreService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ComponentConfigService configService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipService mastershipService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected PersistenceService persistenceService; - - private Map<Long, NodeId> pendingResponses = Maps.newConcurrentMap(); - private ExecutorService messageHandlingExecutor; - - private ScheduledFuture<?> backupTask; - private final ScheduledExecutorService backupSenderExecutor = - Executors.newSingleThreadScheduledExecutor(groupedThreads("onos/flow", "backup-sender")); - - private EventuallyConsistentMap<DeviceId, List<TableStatisticsEntry>> deviceTableStats; - private final EventuallyConsistentMapListener<DeviceId, List<TableStatisticsEntry>> tableStatsListener = - new InternalTableStatsListener(); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - protected static final StoreSerializer SERIALIZER = new KryoSerializer() { - @Override - protected void setupKryoPool() { - serializerPool = KryoNamespace.newBuilder() - .register(DistributedStoreSerializers.STORE_COMMON) - .nextId(DistributedStoreSerializers.STORE_CUSTOM_BEGIN) - .build(); - } - }; - - protected static final KryoNamespace.Builder SERIALIZER_BUILDER = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .register(MastershipBasedTimestamp.class); - - - private IdGenerator idGenerator; - private NodeId local; - - @Activate - public void activate(ComponentContext context) { - configService.registerProperties(getClass()); - - idGenerator = coreService.getIdGenerator(FlowRuleService.FLOW_OP_TOPIC); - - local = clusterService.getLocalNode().id(); - - messageHandlingExecutor = Executors.newFixedThreadPool( - msgHandlerPoolSize, groupedThreads("onos/store/flow", "message-handlers")); - - registerMessageHandlers(messageHandlingExecutor); - - if (backupEnabled) { - replicaInfoManager.addListener(flowTable); - backupTask = backupSenderExecutor.scheduleWithFixedDelay( - flowTable::backup, - 0, - backupPeriod, - TimeUnit.MILLISECONDS); - } - - deviceTableStats = storageService.<DeviceId, List<TableStatisticsEntry>>eventuallyConsistentMapBuilder() - .withName("onos-flow-table-stats") - .withSerializer(SERIALIZER_BUILDER) - .withAntiEntropyPeriod(5, TimeUnit.SECONDS) - .withTimestampProvider((k, v) -> new WallClockTimestamp()) - .withTombstonesDisabled() - .build(); - deviceTableStats.addListener(tableStatsListener); - - logConfig("Started"); - } - - @Deactivate - public void deactivate(ComponentContext context) { - if (backupEnabled) { - replicaInfoManager.removeListener(flowTable); - backupTask.cancel(true); - } - configService.unregisterProperties(getClass(), false); - unregisterMessageHandlers(); - deviceTableStats.removeListener(tableStatsListener); - deviceTableStats.destroy(); - messageHandlingExecutor.shutdownNow(); - backupSenderExecutor.shutdownNow(); - log.info("Stopped"); - } - - @SuppressWarnings("rawtypes") - @Modified - public void modified(ComponentContext context) { - if (context == null) { - backupEnabled = DEFAULT_BACKUP_ENABLED; - logConfig("Default config"); - return; - } - - Dictionary properties = context.getProperties(); - int newPoolSize; - boolean newBackupEnabled; - int newBackupPeriod; - try { - String s = get(properties, "msgHandlerPoolSize"); - newPoolSize = isNullOrEmpty(s) ? msgHandlerPoolSize : Integer.parseInt(s.trim()); - - s = get(properties, "backupEnabled"); - newBackupEnabled = isNullOrEmpty(s) ? backupEnabled : Boolean.parseBoolean(s.trim()); - - s = get(properties, "backupPeriod"); - newBackupPeriod = isNullOrEmpty(s) ? backupPeriod : Integer.parseInt(s.trim()); - - } catch (NumberFormatException | ClassCastException e) { - newPoolSize = MESSAGE_HANDLER_THREAD_POOL_SIZE; - newBackupEnabled = DEFAULT_BACKUP_ENABLED; - newBackupPeriod = DEFAULT_BACKUP_PERIOD_MILLIS; - } - - boolean restartBackupTask = false; - if (newBackupEnabled != backupEnabled) { - backupEnabled = newBackupEnabled; - if (!backupEnabled) { - replicaInfoManager.removeListener(flowTable); - if (backupTask != null) { - backupTask.cancel(false); - backupTask = null; - } - } else { - replicaInfoManager.addListener(flowTable); - } - restartBackupTask = backupEnabled; - } - if (newBackupPeriod != backupPeriod) { - backupPeriod = newBackupPeriod; - restartBackupTask = backupEnabled; - } - if (restartBackupTask) { - if (backupTask != null) { - // cancel previously running task - backupTask.cancel(false); - } - backupTask = backupSenderExecutor.scheduleWithFixedDelay( - flowTable::backup, - 0, - backupPeriod, - TimeUnit.MILLISECONDS); - } - if (newPoolSize != msgHandlerPoolSize) { - msgHandlerPoolSize = newPoolSize; - ExecutorService oldMsgHandler = messageHandlingExecutor; - messageHandlingExecutor = Executors.newFixedThreadPool( - msgHandlerPoolSize, groupedThreads("onos/store/flow", "message-handlers")); - - // replace previously registered handlers. - registerMessageHandlers(messageHandlingExecutor); - oldMsgHandler.shutdown(); - } - logConfig("Reconfigured"); - } - - private void registerMessageHandlers(ExecutorService executor) { - - clusterCommunicator.addSubscriber(APPLY_BATCH_FLOWS, new OnStoreBatch(), executor); - clusterCommunicator.<FlowRuleBatchEvent>addSubscriber( - REMOTE_APPLY_COMPLETED, SERIALIZER::decode, this::notifyDelegate, executor); - clusterCommunicator.addSubscriber( - GET_FLOW_ENTRY, SERIALIZER::decode, flowTable::getFlowEntry, SERIALIZER::encode, executor); - clusterCommunicator.addSubscriber( - GET_DEVICE_FLOW_ENTRIES, SERIALIZER::decode, flowTable::getFlowEntries, SERIALIZER::encode, executor); - clusterCommunicator.addSubscriber( - REMOVE_FLOW_ENTRY, SERIALIZER::decode, this::removeFlowRuleInternal, SERIALIZER::encode, executor); - clusterCommunicator.addSubscriber( - REMOVE_FLOW_ENTRY, SERIALIZER::decode, this::removeFlowRuleInternal, SERIALIZER::encode, executor); - clusterCommunicator.addSubscriber( - FLOW_TABLE_BACKUP, SERIALIZER::decode, flowTable::onBackupReceipt, SERIALIZER::encode, executor); - } - - private void unregisterMessageHandlers() { - clusterCommunicator.removeSubscriber(REMOVE_FLOW_ENTRY); - clusterCommunicator.removeSubscriber(GET_DEVICE_FLOW_ENTRIES); - clusterCommunicator.removeSubscriber(GET_FLOW_ENTRY); - clusterCommunicator.removeSubscriber(APPLY_BATCH_FLOWS); - clusterCommunicator.removeSubscriber(REMOTE_APPLY_COMPLETED); - clusterCommunicator.removeSubscriber(FLOW_TABLE_BACKUP); - } - - private void logConfig(String prefix) { - log.info("{} with msgHandlerPoolSize = {}; backupEnabled = {}, backupPeriod = {}", - prefix, msgHandlerPoolSize, backupEnabled, backupPeriod); - } - - // This is not a efficient operation on a distributed sharded - // flow store. We need to revisit the need for this operation or at least - // make it device specific. - @Override - public int getFlowRuleCount() { - AtomicInteger sum = new AtomicInteger(0); - deviceService.getDevices().forEach(device -> sum.addAndGet(Iterables.size(getFlowEntries(device.id())))); - return sum.get(); - } - - @Override - public FlowEntry getFlowEntry(FlowRule rule) { - NodeId master = mastershipService.getMasterFor(rule.deviceId()); - - if (master == null) { - log.debug("Failed to getFlowEntry: No master for {}", rule.deviceId()); - return null; - } - - if (Objects.equal(local, master)) { - return flowTable.getFlowEntry(rule); - } - - log.trace("Forwarding getFlowEntry to {}, which is the primary (master) for device {}", - master, rule.deviceId()); - - return Tools.futureGetOrElse(clusterCommunicator.sendAndReceive(rule, - FlowStoreMessageSubjects.GET_FLOW_ENTRY, - SERIALIZER::encode, - SERIALIZER::decode, - master), - FLOW_RULE_STORE_TIMEOUT_MILLIS, - TimeUnit.MILLISECONDS, - null); - } - - @Override - public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) { - NodeId master = mastershipService.getMasterFor(deviceId); - - if (master == null) { - log.debug("Failed to getFlowEntries: No master for {}", deviceId); - return Collections.emptyList(); - } - - if (Objects.equal(local, master)) { - return flowTable.getFlowEntries(deviceId); - } - - log.trace("Forwarding getFlowEntries to {}, which is the primary (master) for device {}", - master, deviceId); - - return Tools.futureGetOrElse(clusterCommunicator.sendAndReceive(deviceId, - FlowStoreMessageSubjects.GET_DEVICE_FLOW_ENTRIES, - SERIALIZER::encode, - SERIALIZER::decode, - master), - FLOW_RULE_STORE_TIMEOUT_MILLIS, - TimeUnit.MILLISECONDS, - Collections.emptyList()); - } - - @Override - public void storeFlowRule(FlowRule rule) { - storeBatch(new FlowRuleBatchOperation( - Collections.singletonList(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule)), - rule.deviceId(), idGenerator.getNewId())); - } - - @Override - public void storeBatch(FlowRuleBatchOperation operation) { - if (operation.getOperations().isEmpty()) { - notifyDelegate(FlowRuleBatchEvent.completed( - new FlowRuleBatchRequest(operation.id(), Collections.emptySet()), - new CompletedBatchOperation(true, Collections.emptySet(), operation.deviceId()))); - return; - } - - DeviceId deviceId = operation.deviceId(); - NodeId master = mastershipService.getMasterFor(deviceId); - - if (master == null) { - log.warn("No master for {} : flows will be marked for removal", deviceId); - - updateStoreInternal(operation); - - notifyDelegate(FlowRuleBatchEvent.completed( - new FlowRuleBatchRequest(operation.id(), Collections.emptySet()), - new CompletedBatchOperation(true, Collections.emptySet(), operation.deviceId()))); - return; - } - - if (Objects.equal(local, master)) { - storeBatchInternal(operation); - return; - } - - log.trace("Forwarding storeBatch to {}, which is the primary (master) for device {}", - master, deviceId); - - clusterCommunicator.unicast(operation, - APPLY_BATCH_FLOWS, - SERIALIZER::encode, - master) - .whenComplete((result, error) -> { - if (error != null) { - log.warn("Failed to storeBatch: {} to {}", operation, master, error); - - Set<FlowRule> allFailures = operation.getOperations() - .stream() - .map(op -> op.target()) - .collect(Collectors.toSet()); - - notifyDelegate(FlowRuleBatchEvent.completed( - new FlowRuleBatchRequest(operation.id(), Collections.emptySet()), - new CompletedBatchOperation(false, allFailures, deviceId))); - } - }); - } - - private void storeBatchInternal(FlowRuleBatchOperation operation) { - - final DeviceId did = operation.deviceId(); - //final Collection<FlowEntry> ft = flowTable.getFlowEntries(did); - Set<FlowRuleBatchEntry> currentOps = updateStoreInternal(operation); - if (currentOps.isEmpty()) { - batchOperationComplete(FlowRuleBatchEvent.completed( - new FlowRuleBatchRequest(operation.id(), Collections.emptySet()), - new CompletedBatchOperation(true, Collections.emptySet(), did))); - return; - } - - notifyDelegate(FlowRuleBatchEvent.requested(new - FlowRuleBatchRequest(operation.id(), - currentOps), operation.deviceId())); - } - - private Set<FlowRuleBatchEntry> updateStoreInternal(FlowRuleBatchOperation operation) { - return operation.getOperations().stream().map( - op -> { - StoredFlowEntry entry; - switch (op.operator()) { - case ADD: - entry = new DefaultFlowEntry(op.target()); - // always add requested FlowRule - // Note: 2 equal FlowEntry may have different treatment - flowTable.remove(entry.deviceId(), entry); - flowTable.add(entry); - - return op; - case REMOVE: - entry = flowTable.getFlowEntry(op.target()); - if (entry != null) { - entry.setState(FlowEntryState.PENDING_REMOVE); - return op; - } - break; - case MODIFY: - //TODO: figure this out at some point - break; - default: - log.warn("Unknown flow operation operator: {}", op.operator()); - } - return null; - } - ).filter(op -> op != null).collect(Collectors.toSet()); - } - - @Override - public void deleteFlowRule(FlowRule rule) { - storeBatch( - new FlowRuleBatchOperation( - Collections.singletonList( - new FlowRuleBatchEntry( - FlowRuleOperation.REMOVE, - rule)), rule.deviceId(), idGenerator.getNewId())); - } - - @Override - public FlowRuleEvent addOrUpdateFlowRule(FlowEntry rule) { - NodeId master = mastershipService.getMasterFor(rule.deviceId()); - if (Objects.equal(local, master)) { - return addOrUpdateFlowRuleInternal(rule); - } - - log.warn("Tried to update FlowRule {} state," - + " while the Node was not the master.", rule); - return null; - } - - private FlowRuleEvent addOrUpdateFlowRuleInternal(FlowEntry rule) { - // check if this new rule is an update to an existing entry - StoredFlowEntry stored = flowTable.getFlowEntry(rule); - if (stored != null) { - stored.setBytes(rule.bytes()); - stored.setLife(rule.life()); - stored.setPackets(rule.packets()); - if (stored.state() == FlowEntryState.PENDING_ADD) { - stored.setState(FlowEntryState.ADDED); - return new FlowRuleEvent(Type.RULE_ADDED, rule); - } - return new FlowRuleEvent(Type.RULE_UPDATED, rule); - } - - // TODO: Confirm if this behavior is correct. See SimpleFlowRuleStore - // TODO: also update backup if the behavior is correct. - flowTable.add(rule); - return null; - } - - @Override - public FlowRuleEvent removeFlowRule(FlowEntry rule) { - final DeviceId deviceId = rule.deviceId(); - NodeId master = mastershipService.getMasterFor(deviceId); - - if (Objects.equal(local, master)) { - // bypass and handle it locally - return removeFlowRuleInternal(rule); - } - - if (master == null) { - log.warn("Failed to removeFlowRule: No master for {}", deviceId); - // TODO: revisit if this should be null (="no-op") or Exception - return null; - } - - log.trace("Forwarding removeFlowRule to {}, which is the master for device {}", - master, deviceId); - - return Futures.get(clusterCommunicator.sendAndReceive( - rule, - REMOVE_FLOW_ENTRY, - SERIALIZER::encode, - SERIALIZER::decode, - master), - FLOW_RULE_STORE_TIMEOUT_MILLIS, - TimeUnit.MILLISECONDS, - RuntimeException.class); - } - - private FlowRuleEvent removeFlowRuleInternal(FlowEntry rule) { - final DeviceId deviceId = rule.deviceId(); - // This is where one could mark a rule as removed and still keep it in the store. - final boolean removed = flowTable.remove(deviceId, rule); //flowEntries.remove(deviceId, rule); - return removed ? new FlowRuleEvent(RULE_REMOVED, rule) : null; - } - - @Override - public void batchOperationComplete(FlowRuleBatchEvent event) { - //FIXME: need a per device pending response - NodeId nodeId = pendingResponses.remove(event.subject().batchId()); - if (nodeId == null) { - notifyDelegate(event); - } else { - // TODO check unicast return value - clusterCommunicator.unicast(event, REMOTE_APPLY_COMPLETED, SERIALIZER::encode, nodeId); - //error log: log.warn("Failed to respond to peer for batch operation result"); - } - } - - private final class OnStoreBatch implements ClusterMessageHandler { - - @Override - public void handle(final ClusterMessage message) { - FlowRuleBatchOperation operation = SERIALIZER.decode(message.payload()); - log.debug("received batch request {}", operation); - - final DeviceId deviceId = operation.deviceId(); - NodeId master = mastershipService.getMasterFor(deviceId); - if (!Objects.equal(local, master)) { - Set<FlowRule> failures = new HashSet<>(operation.size()); - for (FlowRuleBatchEntry op : operation.getOperations()) { - failures.add(op.target()); - } - CompletedBatchOperation allFailed = new CompletedBatchOperation(false, failures, deviceId); - // This node is no longer the master, respond as all failed. - // TODO: we might want to wrap response in envelope - // to distinguish sw programming failure and hand over - // it make sense in the latter case to retry immediately. - message.respond(SERIALIZER.encode(allFailed)); - return; - } - - pendingResponses.put(operation.id(), message.sender()); - storeBatchInternal(operation); - } - } - - private class InternalFlowTable implements ReplicaInfoEventListener { - - private final Map<DeviceId, Map<FlowId, Set<StoredFlowEntry>>> - flowEntries = Maps.newConcurrentMap(); - - private final Map<DeviceId, Long> lastBackupTimes = Maps.newConcurrentMap(); - private final Map<DeviceId, Long> lastUpdateTimes = Maps.newConcurrentMap(); - private final Map<DeviceId, NodeId> lastBackupNodes = Maps.newConcurrentMap(); - - @Override - public void event(ReplicaInfoEvent event) { - if (!backupEnabled) { - return; - } - if (event.type() == ReplicaInfoEvent.Type.BACKUPS_CHANGED) { - DeviceId deviceId = event.subject(); - NodeId master = mastershipService.getMasterFor(deviceId); - if (!Objects.equal(local, master)) { - // ignore since this event is for a device this node does not manage. - return; - } - NodeId newBackupNode = getBackupNode(deviceId); - NodeId currentBackupNode = lastBackupNodes.get(deviceId); - if (Objects.equal(newBackupNode, currentBackupNode)) { - // ignore since backup location hasn't changed. - return; - } - if (currentBackupNode != null && newBackupNode == null) { - // Current backup node is most likely down and no alternate backup node - // has been chosen. Clear current backup location so that we can resume - // backups when either current backup comes online or a different backup node - // is chosen. - log.warn("Lost backup location {} for deviceId {} and no alternate backup node exists. " - + "Flows can be lost if the master goes down", currentBackupNode, deviceId); - lastBackupNodes.remove(deviceId); - lastBackupTimes.remove(deviceId); - return; - // TODO: Pick any available node as backup and ensure hand-off occurs when - // a new master is elected. - } - log.debug("Backup location for {} has changed from {} to {}.", - deviceId, currentBackupNode, newBackupNode); - backupSenderExecutor.schedule(() -> backupFlowEntries(newBackupNode, Sets.newHashSet(deviceId)), - 0, - TimeUnit.SECONDS); - } - } - - private void sendBackups(NodeId nodeId, Set<DeviceId> deviceIds) { - // split up the devices into smaller batches and send them separately. - Iterables.partition(deviceIds, FLOW_TABLE_BACKUP_BATCH_SIZE) - .forEach(ids -> backupFlowEntries(nodeId, Sets.newHashSet(ids))); - } - - private void backupFlowEntries(NodeId nodeId, Set<DeviceId> deviceIds) { - if (deviceIds.isEmpty()) { - return; - } - log.debug("Sending flowEntries for devices {} to {} as backup.", deviceIds, nodeId); - Map<DeviceId, Map<FlowId, Set<StoredFlowEntry>>> deviceFlowEntries = - Maps.newConcurrentMap(); - deviceIds.forEach(id -> deviceFlowEntries.put(id, ImmutableMap.copyOf(getFlowTable(id)))); - clusterCommunicator.<Map<DeviceId, Map<FlowId, Set<StoredFlowEntry>>>, Set<DeviceId>>sendAndReceive( - deviceFlowEntries, - FLOW_TABLE_BACKUP, - SERIALIZER::encode, - SERIALIZER::decode, - nodeId) - .whenComplete((backedupDevices, error) -> { - Set<DeviceId> devicesNotBackedup = error != null ? - deviceFlowEntries.keySet() : - Sets.difference(deviceFlowEntries.keySet(), backedupDevices); - if (devicesNotBackedup.size() > 0) { - log.warn("Failed to backup devices: {}. Reason: {}", - devicesNotBackedup, error.getMessage()); - } - if (backedupDevices != null) { - backedupDevices.forEach(id -> { - lastBackupTimes.put(id, System.currentTimeMillis()); - lastBackupNodes.put(id, nodeId); - }); - } - }); - } - - /** - * Returns the flow table for specified device. - * - * @param deviceId identifier of the device - * @return Map representing Flow Table of given device. - */ - private Map<FlowId, Set<StoredFlowEntry>> getFlowTable(DeviceId deviceId) { - if (persistenceEnabled) { - return flowEntries.computeIfAbsent(deviceId, id -> persistenceService - .<FlowId, Set<StoredFlowEntry>>persistentMapBuilder() - .withName("FlowTable:" + deviceId.toString()) - .withSerializer(new Serializer() { - @Override - public <T> byte[] encode(T object) { - return SERIALIZER.encode(object); - } - - @Override - public <T> T decode(byte[] bytes) { - return SERIALIZER.decode(bytes); - } - }) - .build()); - } else { - return flowEntries.computeIfAbsent(deviceId, id -> Maps.newConcurrentMap()); - } - } - - private Set<StoredFlowEntry> getFlowEntriesInternal(DeviceId deviceId, FlowId flowId) { - return getFlowTable(deviceId).computeIfAbsent(flowId, id -> Sets.newCopyOnWriteArraySet()); - } - - private StoredFlowEntry getFlowEntryInternal(FlowRule rule) { - Set<StoredFlowEntry> flowEntries = getFlowEntriesInternal(rule.deviceId(), rule.id()); - return flowEntries.stream() - .filter(entry -> Objects.equal(entry, rule)) - .findAny() - .orElse(null); - } - - private Set<FlowEntry> getFlowEntriesInternal(DeviceId deviceId) { - Set<FlowEntry> result = Sets.newHashSet(); - getFlowTable(deviceId).values().forEach(result::addAll); - return result; - } - - public StoredFlowEntry getFlowEntry(FlowRule rule) { - return getFlowEntryInternal(rule); - } - - public Set<FlowEntry> getFlowEntries(DeviceId deviceId) { - return getFlowEntriesInternal(deviceId); - } - - public void add(FlowEntry rule) { - getFlowEntriesInternal(rule.deviceId(), rule.id()).add((StoredFlowEntry) rule); - lastUpdateTimes.put(rule.deviceId(), System.currentTimeMillis()); - } - - public boolean remove(DeviceId deviceId, FlowEntry rule) { - try { - return getFlowEntriesInternal(deviceId, rule.id()).remove(rule); - } finally { - lastUpdateTimes.put(deviceId, System.currentTimeMillis()); - } - } - - private NodeId getBackupNode(DeviceId deviceId) { - List<NodeId> deviceStandbys = replicaInfoManager.getReplicaInfoFor(deviceId).backups(); - // pick the standby which is most likely to become next master - return deviceStandbys.isEmpty() ? null : deviceStandbys.get(0); - } - - private void backup() { - if (!backupEnabled) { - return; - } - try { - // determine the set of devices that we need to backup during this run. - Set<DeviceId> devicesToBackup = mastershipService.getDevicesOf(local) - .stream() - .filter(deviceId -> { - Long lastBackupTime = lastBackupTimes.get(deviceId); - Long lastUpdateTime = lastUpdateTimes.get(deviceId); - NodeId lastBackupNode = lastBackupNodes.get(deviceId); - NodeId newBackupNode = getBackupNode(deviceId); - return lastBackupTime == null - || !Objects.equal(lastBackupNode, newBackupNode) - || (lastUpdateTime != null && lastUpdateTime > lastBackupTime); - }) - .collect(Collectors.toSet()); - - // compute a mapping from node to the set of devices whose flow entries it should backup - Map<NodeId, Set<DeviceId>> devicesToBackupByNode = Maps.newHashMap(); - devicesToBackup.forEach(deviceId -> { - NodeId backupLocation = getBackupNode(deviceId); - if (backupLocation != null) { - devicesToBackupByNode.computeIfAbsent(backupLocation, nodeId -> Sets.newHashSet()) - .add(deviceId); - } - }); - // send the device flow entries to their respective backup nodes - devicesToBackupByNode.forEach(this::sendBackups); - } catch (Exception e) { - log.error("Backup failed.", e); - } - } - - private Set<DeviceId> onBackupReceipt(Map<DeviceId, Map<FlowId, Set<StoredFlowEntry>>> flowTables) { - log.debug("Received flowEntries for {} to backup", flowTables.keySet()); - Set<DeviceId> backedupDevices = Sets.newHashSet(); - try { - flowTables.forEach((deviceId, deviceFlowTable) -> { - // Only process those devices are that not managed by the local node. - if (!Objects.equal(local, mastershipService.getMasterFor(deviceId))) { - Map<FlowId, Set<StoredFlowEntry>> backupFlowTable = getFlowTable(deviceId); - backupFlowTable.clear(); - backupFlowTable.putAll(deviceFlowTable); - backedupDevices.add(deviceId); - } - }); - } catch (Exception e) { - log.warn("Failure processing backup request", e); - } - return backedupDevices; - } - } - - @Override - public FlowRuleEvent updateTableStatistics(DeviceId deviceId, - List<TableStatisticsEntry> tableStats) { - deviceTableStats.put(deviceId, tableStats); - return null; - } - - @Override - public Iterable<TableStatisticsEntry> getTableStatistics(DeviceId deviceId) { - NodeId master = mastershipService.getMasterFor(deviceId); - - if (master == null) { - log.debug("Failed to getTableStats: No master for {}", deviceId); - return Collections.emptyList(); - } - - List<TableStatisticsEntry> tableStats = deviceTableStats.get(deviceId); - if (tableStats == null) { - return Collections.emptyList(); - } - return ImmutableList.copyOf(tableStats); - } - - private class InternalTableStatsListener - implements EventuallyConsistentMapListener<DeviceId, List<TableStatisticsEntry>> { - @Override - public void event(EventuallyConsistentMapEvent<DeviceId, - List<TableStatisticsEntry>> event) { - //TODO: Generate an event to listeners (do we need?) - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/ReplicaInfoManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/ReplicaInfoManager.java deleted file mode 100644 index ebb487bf..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/ReplicaInfoManager.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.flow.impl; - -import com.google.common.collect.ImmutableList; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onosproject.cluster.NodeId; -import org.onosproject.cluster.RoleInfo; -import org.onosproject.event.EventDeliveryService; -import org.onosproject.event.ListenerRegistry; -import org.onosproject.mastership.MastershipEvent; -import org.onosproject.mastership.MastershipListener; -import org.onosproject.mastership.MastershipService; -import org.onosproject.net.DeviceId; -import org.onosproject.store.flow.ReplicaInfo; -import org.onosproject.store.flow.ReplicaInfoEvent; -import org.onosproject.store.flow.ReplicaInfoEventListener; -import org.onosproject.store.flow.ReplicaInfoService; -import org.slf4j.Logger; - -import java.util.Collections; -import java.util.List; -import static com.google.common.base.Preconditions.checkNotNull; -import static org.onosproject.store.flow.ReplicaInfoEvent.Type.BACKUPS_CHANGED; -import static org.onosproject.store.flow.ReplicaInfoEvent.Type.MASTER_CHANGED; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Manages replica placement information. - */ -@Component(immediate = true) -@Service -public class ReplicaInfoManager implements ReplicaInfoService { - - private final Logger log = getLogger(getClass()); - - private final MastershipListener mastershipListener = new InternalMastershipListener(); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected EventDeliveryService eventDispatcher; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipService mastershipService; - - protected final ListenerRegistry<ReplicaInfoEvent, ReplicaInfoEventListener> - listenerRegistry = new ListenerRegistry<>(); - - @Activate - public void activate() { - eventDispatcher.addSink(ReplicaInfoEvent.class, listenerRegistry); - mastershipService.addListener(mastershipListener); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - eventDispatcher.removeSink(ReplicaInfoEvent.class); - mastershipService.removeListener(mastershipListener); - log.info("Stopped"); - } - - @Override - public ReplicaInfo getReplicaInfoFor(DeviceId deviceId) { - return buildFromRoleInfo(mastershipService.getNodesFor(deviceId)); - } - - @Override - public void addListener(ReplicaInfoEventListener listener) { - listenerRegistry.addListener(checkNotNull(listener)); - } - - @Override - public void removeListener(ReplicaInfoEventListener listener) { - listenerRegistry.removeListener(checkNotNull(listener)); - } - - private static ReplicaInfo buildFromRoleInfo(RoleInfo roles) { - List<NodeId> backups = roles.backups() == null ? - Collections.emptyList() : ImmutableList.copyOf(roles.backups()); - return new ReplicaInfo(roles.master(), backups); - } - - final class InternalMastershipListener implements MastershipListener { - - @Override - public void event(MastershipEvent event) { - final ReplicaInfo replicaInfo = buildFromRoleInfo(event.roleInfo()); - switch (event.type()) { - case MASTER_CHANGED: - eventDispatcher.post(new ReplicaInfoEvent(MASTER_CHANGED, - event.subject(), - replicaInfo)); - break; - case BACKUPS_CHANGED: - eventDispatcher.post(new ReplicaInfoEvent(BACKUPS_CHANGED, - event.subject(), - replicaInfo)); - break; - default: - break; - } - } - } - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/package-info.java deleted file mode 100644 index b3de23db..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of the distributed flow rule store using p2p synchronization - * protocol. - */ -package org.onosproject.store.flow.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/package-info.java deleted file mode 100644 index 10dd24e3..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Definitions of events and messages pertaining to replication of flow entries. - */ -package org.onosproject.store.flow; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flowobjective/impl/DistributedFlowObjectiveStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flowobjective/impl/DistributedFlowObjectiveStore.java deleted file mode 100644 index e8ea24fa..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flowobjective/impl/DistributedFlowObjectiveStore.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.flowobjective.impl; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onosproject.net.behaviour.DefaultNextGroup; -import org.onosproject.net.behaviour.NextGroup; -import org.onosproject.net.flowobjective.FlowObjectiveStore; -import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate; -import org.onosproject.net.flowobjective.ObjectiveEvent; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.service.AtomicCounter; -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.StorageService; -import org.onosproject.store.service.Versioned; -import org.slf4j.Logger; - -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Manages the inventory of created next groups. - */ -@Component(immediate = true, enabled = true) -@Service -public class DistributedFlowObjectiveStore - extends AbstractStore<ObjectiveEvent, FlowObjectiveStoreDelegate> - implements FlowObjectiveStore { - - private final Logger log = getLogger(getClass()); - - private ConsistentMap<Integer, byte[]> nextGroups; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - private AtomicCounter nextIds; - - @Activate - public void activate() { - nextGroups = storageService.<Integer, byte[]>consistentMapBuilder() - .withName("flowobjective-groups") - .withSerializer(Serializer.using( - new KryoNamespace.Builder() - .register(byte[].class) - .register(Versioned.class) - .build())) - .build(); - - nextIds = storageService.atomicCounterBuilder() - .withName("next-objective-counter") - .build(); - - log.info("Started"); - } - - - @Deactivate - public void deactivate() { - log.info("Stopped"); - } - - - @Override - public void putNextGroup(Integer nextId, NextGroup group) { - nextGroups.putIfAbsent(nextId, group.data()); - notifyDelegate(new ObjectiveEvent(ObjectiveEvent.Type.ADD, nextId)); - } - - @Override - public NextGroup getNextGroup(Integer nextId) { - Versioned<byte[]> versionGroup = nextGroups.get(nextId); - if (versionGroup != null) { - return new DefaultNextGroup(versionGroup.value()); - } - return null; - } - - @Override - public int allocateNextId() { - return (int) nextIds.incrementAndGet(); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flowobjective/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flowobjective/impl/package-info.java deleted file mode 100644 index 49acd878..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flowobjective/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of distributed store for the flow objective state. - */ -package org.onosproject.store.flowobjective.impl;
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java deleted file mode 100644 index cc32a735..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java +++ /dev/null @@ -1,1264 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.group.impl; - -import com.google.common.collect.FluentIterable; -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onlab.util.NewConcurrentHashMap; -import org.onosproject.cluster.ClusterService; -import org.onosproject.core.DefaultGroupId; -import org.onosproject.core.GroupId; -import org.onosproject.mastership.MastershipService; -import org.onosproject.net.DeviceId; -import org.onosproject.net.MastershipRole; -import org.onosproject.net.group.DefaultGroup; -import org.onosproject.net.group.DefaultGroupBucket; -import org.onosproject.net.group.DefaultGroupDescription; -import org.onosproject.net.group.DefaultGroupKey; -import org.onosproject.net.group.Group; -import org.onosproject.net.group.Group.GroupState; -import org.onosproject.net.group.GroupBucket; -import org.onosproject.net.group.GroupBuckets; -import org.onosproject.net.group.GroupDescription; -import org.onosproject.net.group.GroupEvent; -import org.onosproject.net.group.GroupEvent.Type; -import org.onosproject.net.group.GroupKey; -import org.onosproject.net.group.GroupOperation; -import org.onosproject.net.group.GroupStore; -import org.onosproject.net.group.GroupStoreDelegate; -import org.onosproject.net.group.StoredGroupBucketEntry; -import org.onosproject.net.group.StoredGroupEntry; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.service.MultiValuedTimestamp; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.EventuallyConsistentMapBuilder; -import org.onosproject.store.service.EventuallyConsistentMapEvent; -import org.onosproject.store.service.EventuallyConsistentMapListener; -import org.onosproject.store.service.StorageService; -import org.slf4j.Logger; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.stream.Collectors; - -import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked; -import static org.onlab.util.Tools.groupedThreads; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Manages inventory of group entries using trivial in-memory implementation. - */ -@Component(immediate = true) -@Service -public class DistributedGroupStore - extends AbstractStore<GroupEvent, GroupStoreDelegate> - implements GroupStore { - - private final Logger log = getLogger(getClass()); - - private final int dummyId = 0xffffffff; - private final GroupId dummyGroupId = new DefaultGroupId(dummyId); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterCommunicationService clusterCommunicator; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipService mastershipService; - - // Per device group table with (device id + app cookie) as key - private EventuallyConsistentMap<GroupStoreKeyMapKey, - StoredGroupEntry> groupStoreEntriesByKey = null; - // Per device group table with (device id + group id) as key - private final ConcurrentMap<DeviceId, ConcurrentMap<GroupId, StoredGroupEntry>> - groupEntriesById = new ConcurrentHashMap<>(); - private EventuallyConsistentMap<GroupStoreKeyMapKey, - StoredGroupEntry> auditPendingReqQueue = null; - private final ConcurrentMap<DeviceId, ConcurrentMap<GroupId, Group>> - extraneousGroupEntriesById = new ConcurrentHashMap<>(); - private ExecutorService messageHandlingExecutor; - private static final int MESSAGE_HANDLER_THREAD_POOL_SIZE = 1; - - private final HashMap<DeviceId, Boolean> deviceAuditStatus = new HashMap<>(); - - private final AtomicInteger groupIdGen = new AtomicInteger(); - - private KryoNamespace.Builder kryoBuilder = null; - - private final AtomicLong sequenceNumber = new AtomicLong(0); - - private KryoNamespace clusterMsgSerializer; - - @Activate - public void activate() { - kryoBuilder = new KryoNamespace.Builder() - .register(KryoNamespaces.API) - .register(DefaultGroup.class, - DefaultGroupBucket.class, - DefaultGroupDescription.class, - DefaultGroupKey.class, - GroupDescription.Type.class, - Group.GroupState.class, - GroupBuckets.class, - DefaultGroupId.class, - GroupStoreMessage.class, - GroupStoreMessage.Type.class, - UpdateType.class, - GroupStoreMessageSubjects.class, - MultiValuedTimestamp.class, - GroupStoreKeyMapKey.class, - GroupStoreIdMapKey.class, - GroupStoreMapKey.class - ); - - clusterMsgSerializer = kryoBuilder.build(); - - messageHandlingExecutor = Executors. - newFixedThreadPool(MESSAGE_HANDLER_THREAD_POOL_SIZE, - groupedThreads("onos/store/group", - "message-handlers")); - - clusterCommunicator.addSubscriber(GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST, - clusterMsgSerializer::deserialize, - this::process, - messageHandlingExecutor); - - log.debug("Creating EC map groupstorekeymap"); - EventuallyConsistentMapBuilder<GroupStoreKeyMapKey, StoredGroupEntry> - keyMapBuilder = storageService.eventuallyConsistentMapBuilder(); - - groupStoreEntriesByKey = keyMapBuilder - .withName("groupstorekeymap") - .withSerializer(kryoBuilder) - .withTimestampProvider((k, v) -> new MultiValuedTimestamp<>(System.currentTimeMillis(), - sequenceNumber.getAndIncrement())) - .build(); - groupStoreEntriesByKey.addListener(new GroupStoreKeyMapListener()); - log.debug("Current size of groupstorekeymap:{}", - groupStoreEntriesByKey.size()); - - log.debug("Creating EC map pendinggroupkeymap"); - EventuallyConsistentMapBuilder<GroupStoreKeyMapKey, StoredGroupEntry> - auditMapBuilder = storageService.eventuallyConsistentMapBuilder(); - - auditPendingReqQueue = auditMapBuilder - .withName("pendinggroupkeymap") - .withSerializer(kryoBuilder) - .withTimestampProvider((k, v) -> new MultiValuedTimestamp<>(System.currentTimeMillis(), - sequenceNumber.getAndIncrement())) - .build(); - log.debug("Current size of pendinggroupkeymap:{}", - auditPendingReqQueue.size()); - - log.info("Started"); - } - - @Deactivate - public void deactivate() { - clusterCommunicator.removeSubscriber(GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST); - groupStoreEntriesByKey.destroy(); - auditPendingReqQueue.destroy(); - log.info("Stopped"); - } - - private static NewConcurrentHashMap<GroupId, Group> - lazyEmptyExtraneousGroupIdTable() { - return NewConcurrentHashMap.<GroupId, Group>ifNeeded(); - } - - private static NewConcurrentHashMap<GroupId, StoredGroupEntry> - lazyEmptyGroupIdTable() { - return NewConcurrentHashMap.<GroupId, StoredGroupEntry>ifNeeded(); - } - - /** - * Returns the group store eventual consistent key map. - * - * @return Map representing group key table. - */ - private EventuallyConsistentMap<GroupStoreKeyMapKey, StoredGroupEntry> - getGroupStoreKeyMap() { - return groupStoreEntriesByKey; - } - - /** - * Returns the group id table for specified device. - * - * @param deviceId identifier of the device - * @return Map representing group key table of given device. - */ - private ConcurrentMap<GroupId, StoredGroupEntry> getGroupIdTable(DeviceId deviceId) { - return createIfAbsentUnchecked(groupEntriesById, - deviceId, lazyEmptyGroupIdTable()); - } - - /** - * Returns the pending group request table. - * - * @return Map representing group key table. - */ - private EventuallyConsistentMap<GroupStoreKeyMapKey, StoredGroupEntry> - getPendingGroupKeyTable() { - return auditPendingReqQueue; - } - - /** - * Returns the extraneous group id table for specified device. - * - * @param deviceId identifier of the device - * @return Map representing group key table of given device. - */ - private ConcurrentMap<GroupId, Group> - getExtraneousGroupIdTable(DeviceId deviceId) { - return createIfAbsentUnchecked(extraneousGroupEntriesById, - deviceId, - lazyEmptyExtraneousGroupIdTable()); - } - - /** - * Returns the number of groups for the specified device in the store. - * - * @return number of groups for the specified device - */ - @Override - public int getGroupCount(DeviceId deviceId) { - return (getGroups(deviceId) != null) ? - Iterables.size(getGroups(deviceId)) : 0; - } - - /** - * Returns the groups associated with a device. - * - * @param deviceId the device ID - * - * @return the group entries - */ - @Override - public Iterable<Group> getGroups(DeviceId deviceId) { - // flatten and make iterator unmodifiable - return FluentIterable.from(getGroupStoreKeyMap().values()) - .filter(input -> input.deviceId().equals(deviceId)) - .transform(input -> input); - } - - private Iterable<StoredGroupEntry> getStoredGroups(DeviceId deviceId) { - // flatten and make iterator unmodifiable - return FluentIterable.from(getGroupStoreKeyMap().values()) - .filter(input -> input.deviceId().equals(deviceId)); - } - - /** - * Returns the stored group entry. - * - * @param deviceId the device ID - * @param appCookie the group key - * - * @return a group associated with the key - */ - @Override - public Group getGroup(DeviceId deviceId, GroupKey appCookie) { - return getStoredGroupEntry(deviceId, appCookie); - } - - private StoredGroupEntry getStoredGroupEntry(DeviceId deviceId, - GroupKey appCookie) { - return getGroupStoreKeyMap().get(new GroupStoreKeyMapKey(deviceId, - appCookie)); - } - - @Override - public Group getGroup(DeviceId deviceId, GroupId groupId) { - return getStoredGroupEntry(deviceId, groupId); - } - - private StoredGroupEntry getStoredGroupEntry(DeviceId deviceId, - GroupId groupId) { - return getGroupIdTable(deviceId).get(groupId); - } - - private int getFreeGroupIdValue(DeviceId deviceId) { - int freeId = groupIdGen.incrementAndGet(); - - while (true) { - Group existing = getGroup(deviceId, new DefaultGroupId(freeId)); - if (existing == null) { - existing = ( - extraneousGroupEntriesById.get(deviceId) != null) ? - extraneousGroupEntriesById.get(deviceId). - get(new DefaultGroupId(freeId)) : - null; - } - if (existing != null) { - freeId = groupIdGen.incrementAndGet(); - } else { - break; - } - } - log.debug("getFreeGroupIdValue: Next Free ID is {}", freeId); - return freeId; - } - - /** - * Stores a new group entry using the information from group description. - * - * @param groupDesc group description to be used to create group entry - */ - @Override - public void storeGroupDescription(GroupDescription groupDesc) { - log.debug("In storeGroupDescription"); - // Check if a group is existing with the same key - Group existingGroup = getGroup(groupDesc.deviceId(), groupDesc.appCookie()); - if (existingGroup != null) { - log.warn("Group already exists with the same key {} in dev:{} with id:0x{}", - groupDesc.appCookie(), groupDesc.deviceId(), - Integer.toHexString(existingGroup.id().id())); - return; - } - - // Check if group to be created by a remote instance - if (mastershipService.getLocalRole(groupDesc.deviceId()) != MastershipRole.MASTER) { - log.debug("storeGroupDescription: Device {} local role is not MASTER", - groupDesc.deviceId()); - if (mastershipService.getMasterFor(groupDesc.deviceId()) == null) { - log.error("No Master for device {}..." - + "Can not perform add group operation", - groupDesc.deviceId()); - //TODO: Send Group operation failure event - return; - } - GroupStoreMessage groupOp = GroupStoreMessage. - createGroupAddRequestMsg(groupDesc.deviceId(), - groupDesc); - - clusterCommunicator.unicast(groupOp, - GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST, - clusterMsgSerializer::serialize, - mastershipService.getMasterFor(groupDesc.deviceId())).whenComplete((result, error) -> { - if (error != null) { - log.warn("Failed to send request to master: {} to {}", - groupOp, - mastershipService.getMasterFor(groupDesc.deviceId())); - //TODO: Send Group operation failure event - } else { - log.debug("Sent Group operation request for device {} " - + "to remote MASTER {}", - groupDesc.deviceId(), - mastershipService.getMasterFor(groupDesc.deviceId())); - } - }); - return; - } - - log.debug("Store group for device {} is getting handled locally", - groupDesc.deviceId()); - storeGroupDescriptionInternal(groupDesc); - } - - private Group getMatchingExtraneousGroupbyId(DeviceId deviceId, Integer groupId) { - ConcurrentMap<GroupId, Group> extraneousMap = - extraneousGroupEntriesById.get(deviceId); - if (extraneousMap == null) { - return null; - } - return extraneousMap.get(new DefaultGroupId(groupId)); - } - - private Group getMatchingExtraneousGroupbyBuckets(DeviceId deviceId, - GroupBuckets buckets) { - ConcurrentMap<GroupId, Group> extraneousMap = - extraneousGroupEntriesById.get(deviceId); - if (extraneousMap == null) { - return null; - } - - for (Group extraneousGroup:extraneousMap.values()) { - if (extraneousGroup.buckets().equals(buckets)) { - return extraneousGroup; - } - } - return null; - } - - private void storeGroupDescriptionInternal(GroupDescription groupDesc) { - // Check if a group is existing with the same key - if (getGroup(groupDesc.deviceId(), groupDesc.appCookie()) != null) { - return; - } - - if (deviceAuditStatus.get(groupDesc.deviceId()) == null) { - // Device group audit has not completed yet - // Add this group description to pending group key table - // Create a group entry object with Dummy Group ID - log.debug("storeGroupDescriptionInternal: Device {} AUDIT pending...Queuing Group ADD request", - groupDesc.deviceId()); - StoredGroupEntry group = new DefaultGroup(dummyGroupId, groupDesc); - group.setState(GroupState.WAITING_AUDIT_COMPLETE); - EventuallyConsistentMap<GroupStoreKeyMapKey, StoredGroupEntry> pendingKeyTable = - getPendingGroupKeyTable(); - pendingKeyTable.put(new GroupStoreKeyMapKey(groupDesc.deviceId(), - groupDesc.appCookie()), - group); - return; - } - - Group matchingExtraneousGroup = null; - if (groupDesc.givenGroupId() != null) { - //Check if there is a extraneous group existing with the same Id - matchingExtraneousGroup = getMatchingExtraneousGroupbyId( - groupDesc.deviceId(), groupDesc.givenGroupId()); - if (matchingExtraneousGroup != null) { - log.debug("storeGroupDescriptionInternal: Matching extraneous group found in Device {} for group id {}", - groupDesc.deviceId(), - groupDesc.givenGroupId()); - //Check if the group buckets matches with user provided buckets - if (matchingExtraneousGroup.buckets().equals(groupDesc.buckets())) { - //Group is already existing with the same buckets and Id - // Create a group entry object - log.debug("storeGroupDescriptionInternal: Buckets also matching in Device {} for group id {}", - groupDesc.deviceId(), - groupDesc.givenGroupId()); - StoredGroupEntry group = new DefaultGroup( - matchingExtraneousGroup.id(), groupDesc); - // Insert the newly created group entry into key and id maps - getGroupStoreKeyMap(). - put(new GroupStoreKeyMapKey(groupDesc.deviceId(), - groupDesc.appCookie()), group); - // Ensure it also inserted into group id based table to - // avoid any chances of duplication in group id generation - getGroupIdTable(groupDesc.deviceId()). - put(matchingExtraneousGroup.id(), group); - addOrUpdateGroupEntry(matchingExtraneousGroup); - removeExtraneousGroupEntry(matchingExtraneousGroup); - return; - } else { - //Group buckets are not matching. Update group - //with user provided buckets. - //TODO - log.debug("storeGroupDescriptionInternal: Buckets are not matching in Device {} for group id {}", - groupDesc.deviceId(), - groupDesc.givenGroupId()); - } - } - } else { - //Check if there is an extraneous group with user provided buckets - matchingExtraneousGroup = getMatchingExtraneousGroupbyBuckets( - groupDesc.deviceId(), groupDesc.buckets()); - if (matchingExtraneousGroup != null) { - //Group is already existing with the same buckets. - //So reuse this group. - log.debug("storeGroupDescriptionInternal: Matching extraneous group found in Device {}", - groupDesc.deviceId()); - //Create a group entry object - StoredGroupEntry group = new DefaultGroup( - matchingExtraneousGroup.id(), groupDesc); - // Insert the newly created group entry into key and id maps - getGroupStoreKeyMap(). - put(new GroupStoreKeyMapKey(groupDesc.deviceId(), - groupDesc.appCookie()), group); - // Ensure it also inserted into group id based table to - // avoid any chances of duplication in group id generation - getGroupIdTable(groupDesc.deviceId()). - put(matchingExtraneousGroup.id(), group); - addOrUpdateGroupEntry(matchingExtraneousGroup); - removeExtraneousGroupEntry(matchingExtraneousGroup); - return; - } else { - //TODO: Check if there are any empty groups that can be used here - log.debug("storeGroupDescriptionInternal: No matching extraneous groups found in Device {}", - groupDesc.deviceId()); - } - } - - GroupId id = null; - if (groupDesc.givenGroupId() == null) { - // Get a new group identifier - id = new DefaultGroupId(getFreeGroupIdValue(groupDesc.deviceId())); - } else { - id = new DefaultGroupId(groupDesc.givenGroupId()); - } - // Create a group entry object - StoredGroupEntry group = new DefaultGroup(id, groupDesc); - // Insert the newly created group entry into key and id maps - getGroupStoreKeyMap(). - put(new GroupStoreKeyMapKey(groupDesc.deviceId(), - groupDesc.appCookie()), group); - // Ensure it also inserted into group id based table to - // avoid any chances of duplication in group id generation - getGroupIdTable(groupDesc.deviceId()). - put(id, group); - log.debug("storeGroupDescriptionInternal: Processing Group ADD request for Id {} in device {}", - id, - groupDesc.deviceId()); - notifyDelegate(new GroupEvent(GroupEvent.Type.GROUP_ADD_REQUESTED, - group)); - } - - /** - * Updates the existing group entry with the information - * from group description. - * - * @param deviceId the device ID - * @param oldAppCookie the current group key - * @param type update type - * @param newBuckets group buckets for updates - * @param newAppCookie optional new group key - */ - @Override - public void updateGroupDescription(DeviceId deviceId, - GroupKey oldAppCookie, - UpdateType type, - GroupBuckets newBuckets, - GroupKey newAppCookie) { - // Check if group update to be done by a remote instance - if (mastershipService.getMasterFor(deviceId) != null && - mastershipService.getLocalRole(deviceId) != MastershipRole.MASTER) { - log.debug("updateGroupDescription: Device {} local role is not MASTER", - deviceId); - if (mastershipService.getMasterFor(deviceId) == null) { - log.error("No Master for device {}..." - + "Can not perform update group operation", - deviceId); - //TODO: Send Group operation failure event - return; - } - GroupStoreMessage groupOp = GroupStoreMessage. - createGroupUpdateRequestMsg(deviceId, - oldAppCookie, - type, - newBuckets, - newAppCookie); - - clusterCommunicator.unicast(groupOp, - GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST, - clusterMsgSerializer::serialize, - mastershipService.getMasterFor(deviceId)).whenComplete((result, error) -> { - if (error != null) { - log.warn("Failed to send request to master: {} to {}", - groupOp, - mastershipService.getMasterFor(deviceId), error); - } - //TODO: Send Group operation failure event - }); - return; - } - log.debug("updateGroupDescription for device {} is getting handled locally", - deviceId); - updateGroupDescriptionInternal(deviceId, - oldAppCookie, - type, - newBuckets, - newAppCookie); - } - - private void updateGroupDescriptionInternal(DeviceId deviceId, - GroupKey oldAppCookie, - UpdateType type, - GroupBuckets newBuckets, - GroupKey newAppCookie) { - // Check if a group is existing with the provided key - Group oldGroup = getGroup(deviceId, oldAppCookie); - if (oldGroup == null) { - log.warn("updateGroupDescriptionInternal: Group not found...strange"); - return; - } - - List<GroupBucket> newBucketList = getUpdatedBucketList(oldGroup, - type, - newBuckets); - if (newBucketList != null) { - // Create a new group object from the old group - GroupBuckets updatedBuckets = new GroupBuckets(newBucketList); - GroupKey newCookie = (newAppCookie != null) ? newAppCookie : oldAppCookie; - GroupDescription updatedGroupDesc = new DefaultGroupDescription( - oldGroup.deviceId(), - oldGroup.type(), - updatedBuckets, - newCookie, - oldGroup.givenGroupId(), - oldGroup.appId()); - StoredGroupEntry newGroup = new DefaultGroup(oldGroup.id(), - updatedGroupDesc); - log.debug("updateGroupDescriptionInternal: group entry {} in device {} moving from {} to PENDING_UPDATE", - oldGroup.id(), - oldGroup.deviceId(), - oldGroup.state()); - newGroup.setState(GroupState.PENDING_UPDATE); - newGroup.setLife(oldGroup.life()); - newGroup.setPackets(oldGroup.packets()); - newGroup.setBytes(oldGroup.bytes()); - //Update the group entry in groupkey based map. - //Update to groupid based map will happen in the - //groupkey based map update listener - log.debug("updateGroupDescriptionInternal with type {}: Group updated with buckets", - type); - getGroupStoreKeyMap(). - put(new GroupStoreKeyMapKey(newGroup.deviceId(), - newGroup.appCookie()), newGroup); - notifyDelegate(new GroupEvent(Type.GROUP_UPDATE_REQUESTED, newGroup)); - } else { - log.warn("updateGroupDescriptionInternal with type {}: No " - + "change in the buckets in update", type); - } - } - - private List<GroupBucket> getUpdatedBucketList(Group oldGroup, - UpdateType type, - GroupBuckets buckets) { - GroupBuckets oldBuckets = oldGroup.buckets(); - List<GroupBucket> newBucketList = new ArrayList<>(oldBuckets.buckets()); - boolean groupDescUpdated = false; - - if (type == UpdateType.ADD) { - // Check if the any of the new buckets are part of - // the old bucket list - for (GroupBucket addBucket:buckets.buckets()) { - if (!newBucketList.contains(addBucket)) { - newBucketList.add(addBucket); - groupDescUpdated = true; - } - } - } else if (type == UpdateType.REMOVE) { - // Check if the to be removed buckets are part of the - // old bucket list - for (GroupBucket removeBucket:buckets.buckets()) { - if (newBucketList.contains(removeBucket)) { - newBucketList.remove(removeBucket); - groupDescUpdated = true; - } - } - } - - if (groupDescUpdated) { - return newBucketList; - } else { - return null; - } - } - - /** - * Triggers deleting the existing group entry. - * - * @param deviceId the device ID - * @param appCookie the group key - */ - @Override - public void deleteGroupDescription(DeviceId deviceId, - GroupKey appCookie) { - // Check if group to be deleted by a remote instance - if (mastershipService. - getLocalRole(deviceId) != MastershipRole.MASTER) { - log.debug("deleteGroupDescription: Device {} local role is not MASTER", - deviceId); - if (mastershipService.getMasterFor(deviceId) == null) { - log.error("No Master for device {}..." - + "Can not perform delete group operation", - deviceId); - //TODO: Send Group operation failure event - return; - } - GroupStoreMessage groupOp = GroupStoreMessage. - createGroupDeleteRequestMsg(deviceId, - appCookie); - - clusterCommunicator.unicast(groupOp, - GroupStoreMessageSubjects.REMOTE_GROUP_OP_REQUEST, - clusterMsgSerializer::serialize, - mastershipService.getMasterFor(deviceId)).whenComplete((result, error) -> { - if (error != null) { - log.warn("Failed to send request to master: {} to {}", - groupOp, - mastershipService.getMasterFor(deviceId), error); - } - //TODO: Send Group operation failure event - }); - return; - } - log.debug("deleteGroupDescription in device {} is getting handled locally", - deviceId); - deleteGroupDescriptionInternal(deviceId, appCookie); - } - - private void deleteGroupDescriptionInternal(DeviceId deviceId, - GroupKey appCookie) { - // Check if a group is existing with the provided key - StoredGroupEntry existing = getStoredGroupEntry(deviceId, appCookie); - if (existing == null) { - return; - } - - log.debug("deleteGroupDescriptionInternal: group entry {} in device {} moving from {} to PENDING_DELETE", - existing.id(), - existing.deviceId(), - existing.state()); - synchronized (existing) { - existing.setState(GroupState.PENDING_DELETE); - } - log.debug("deleteGroupDescriptionInternal: in device {} issuing GROUP_REMOVE_REQUESTED", - deviceId); - notifyDelegate(new GroupEvent(Type.GROUP_REMOVE_REQUESTED, existing)); - } - - /** - * Stores a new group entry, or updates an existing entry. - * - * @param group group entry - */ - @Override - public void addOrUpdateGroupEntry(Group group) { - // check if this new entry is an update to an existing entry - StoredGroupEntry existing = getStoredGroupEntry(group.deviceId(), - group.id()); - GroupEvent event = null; - - if (existing != null) { - log.debug("addOrUpdateGroupEntry: updating group entry {} in device {}", - group.id(), - group.deviceId()); - synchronized (existing) { - for (GroupBucket bucket:group.buckets().buckets()) { - Optional<GroupBucket> matchingBucket = - existing.buckets().buckets() - .stream() - .filter((existingBucket)->(existingBucket.equals(bucket))) - .findFirst(); - if (matchingBucket.isPresent()) { - ((StoredGroupBucketEntry) matchingBucket. - get()).setPackets(bucket.packets()); - ((StoredGroupBucketEntry) matchingBucket. - get()).setBytes(bucket.bytes()); - } else { - log.warn("addOrUpdateGroupEntry: No matching " - + "buckets to update stats"); - } - } - existing.setLife(group.life()); - existing.setPackets(group.packets()); - existing.setBytes(group.bytes()); - if ((existing.state() == GroupState.PENDING_ADD) || - (existing.state() == GroupState.PENDING_ADD_RETRY)) { - log.debug("addOrUpdateGroupEntry: group entry {} in device {} moving from {} to ADDED", - existing.id(), - existing.deviceId(), - existing.state()); - existing.setState(GroupState.ADDED); - existing.setIsGroupStateAddedFirstTime(true); - event = new GroupEvent(Type.GROUP_ADDED, existing); - } else { - log.debug("addOrUpdateGroupEntry: group entry {} in device {} moving from {} to ADDED", - existing.id(), - existing.deviceId(), - GroupState.PENDING_UPDATE); - existing.setState(GroupState.ADDED); - existing.setIsGroupStateAddedFirstTime(false); - event = new GroupEvent(Type.GROUP_UPDATED, existing); - } - //Re-PUT map entries to trigger map update events - getGroupStoreKeyMap(). - put(new GroupStoreKeyMapKey(existing.deviceId(), - existing.appCookie()), existing); - } - } else { - log.warn("addOrUpdateGroupEntry: Group update " - + "happening for a non-existing entry in the map"); - } - - if (event != null) { - notifyDelegate(event); - } - } - - /** - * Removes the group entry from store. - * - * @param group group entry - */ - @Override - public void removeGroupEntry(Group group) { - StoredGroupEntry existing = getStoredGroupEntry(group.deviceId(), - group.id()); - - if (existing != null) { - log.debug("removeGroupEntry: removing group entry {} in device {}", - group.id(), - group.deviceId()); - //Removal from groupid based map will happen in the - //map update listener - getGroupStoreKeyMap().remove(new GroupStoreKeyMapKey(existing.deviceId(), - existing.appCookie())); - notifyDelegate(new GroupEvent(Type.GROUP_REMOVED, existing)); - } else { - log.warn("removeGroupEntry for {} in device{} is " - + "not existing in our maps", - group.id(), - group.deviceId()); - } - } - - @Override - public void deviceInitialAuditCompleted(DeviceId deviceId, - boolean completed) { - synchronized (deviceAuditStatus) { - if (completed) { - log.debug("AUDIT completed for device {}", - deviceId); - deviceAuditStatus.put(deviceId, true); - // Execute all pending group requests - List<StoredGroupEntry> pendingGroupRequests = - getPendingGroupKeyTable().values() - .stream() - .filter(g-> g.deviceId().equals(deviceId)) - .collect(Collectors.toList()); - log.debug("processing pending group add requests for device {} and number of pending requests {}", - deviceId, - pendingGroupRequests.size()); - for (Group group:pendingGroupRequests) { - GroupDescription tmp = new DefaultGroupDescription( - group.deviceId(), - group.type(), - group.buckets(), - group.appCookie(), - group.givenGroupId(), - group.appId()); - storeGroupDescriptionInternal(tmp); - getPendingGroupKeyTable(). - remove(new GroupStoreKeyMapKey(deviceId, group.appCookie())); - } - } else { - Boolean audited = deviceAuditStatus.get(deviceId); - if (audited != null && audited) { - log.debug("Clearing AUDIT status for device {}", deviceId); - deviceAuditStatus.put(deviceId, false); - } - } - } - } - - @Override - public boolean deviceInitialAuditStatus(DeviceId deviceId) { - synchronized (deviceAuditStatus) { - Boolean audited = deviceAuditStatus.get(deviceId); - return audited != null && audited; - } - } - - @Override - public void groupOperationFailed(DeviceId deviceId, GroupOperation operation) { - - StoredGroupEntry existing = getStoredGroupEntry(deviceId, - operation.groupId()); - - if (existing == null) { - log.warn("No group entry with ID {} found ", operation.groupId()); - return; - } - - log.warn("groupOperationFailed: group operation {} failed" - + "for group {} in device {}", - operation.opType(), - existing.id(), - existing.deviceId()); - switch (operation.opType()) { - case ADD: - if (existing.state() == GroupState.PENDING_ADD) { - //TODO: Need to add support for passing the group - //operation failure reason from group provider. - //If the error type is anything other than GROUP_EXISTS, - //then the GROUP_ADD_FAILED event should be raised even - //in PENDING_ADD_RETRY state also. - notifyDelegate(new GroupEvent(Type.GROUP_ADD_FAILED, existing)); - log.warn("groupOperationFailed: cleaningup " - + "group {} from store in device {}....", - existing.id(), - existing.deviceId()); - //Removal from groupid based map will happen in the - //map update listener - getGroupStoreKeyMap().remove(new GroupStoreKeyMapKey(existing.deviceId(), - existing.appCookie())); - } - break; - case MODIFY: - notifyDelegate(new GroupEvent(Type.GROUP_UPDATE_FAILED, existing)); - break; - case DELETE: - notifyDelegate(new GroupEvent(Type.GROUP_REMOVE_FAILED, existing)); - break; - default: - log.warn("Unknown group operation type {}", operation.opType()); - } - } - - @Override - public void addOrUpdateExtraneousGroupEntry(Group group) { - log.debug("add/update extraneous group entry {} in device {}", - group.id(), - group.deviceId()); - ConcurrentMap<GroupId, Group> extraneousIdTable = - getExtraneousGroupIdTable(group.deviceId()); - extraneousIdTable.put(group.id(), group); - // Don't remove the extraneous groups, instead re-use it when - // a group request comes with the same set of buckets - } - - @Override - public void removeExtraneousGroupEntry(Group group) { - log.debug("remove extraneous group entry {} of device {} from store", - group.id(), - group.deviceId()); - ConcurrentMap<GroupId, Group> extraneousIdTable = - getExtraneousGroupIdTable(group.deviceId()); - extraneousIdTable.remove(group.id()); - } - - @Override - public Iterable<Group> getExtraneousGroups(DeviceId deviceId) { - // flatten and make iterator unmodifiable - return FluentIterable.from( - getExtraneousGroupIdTable(deviceId).values()); - } - - /** - * Map handler to receive any events when the group key map is updated. - */ - private class GroupStoreKeyMapListener implements - EventuallyConsistentMapListener<GroupStoreKeyMapKey, StoredGroupEntry> { - - @Override - public void event(EventuallyConsistentMapEvent<GroupStoreKeyMapKey, - StoredGroupEntry> mapEvent) { - GroupEvent groupEvent = null; - GroupStoreKeyMapKey key = mapEvent.key(); - StoredGroupEntry group = mapEvent.value(); - if ((key == null) && (group == null)) { - log.error("GroupStoreKeyMapListener: Received " - + "event {} with null entry", mapEvent.type()); - return; - } else if (group == null) { - group = getGroupIdTable(key.deviceId()).values() - .stream() - .filter((storedGroup) -> (storedGroup.appCookie().equals(key.appCookie))) - .findFirst().get(); - if (group == null) { - log.error("GroupStoreKeyMapListener: Received " - + "event {} with null entry... can not process", mapEvent.type()); - return; - } - } - log.trace("received groupid map event {} for id {} in device {}", - mapEvent.type(), - group.id(), - key.deviceId()); - if (mapEvent.type() == EventuallyConsistentMapEvent.Type.PUT) { - // Update the group ID table - getGroupIdTable(group.deviceId()).put(group.id(), group); - if (mapEvent.value().state() == Group.GroupState.ADDED) { - if (mapEvent.value().isGroupStateAddedFirstTime()) { - groupEvent = new GroupEvent(Type.GROUP_ADDED, - mapEvent.value()); - log.trace("Received first time GROUP_ADDED state update for id {} in device {}", - group.id(), - group.deviceId()); - } else { - groupEvent = new GroupEvent(Type.GROUP_UPDATED, - mapEvent.value()); - log.trace("Received following GROUP_ADDED state update for id {} in device {}", - group.id(), - group.deviceId()); - } - } - } else if (mapEvent.type() == EventuallyConsistentMapEvent.Type.REMOVE) { - groupEvent = new GroupEvent(Type.GROUP_REMOVED, group); - // Remove the entry from the group ID table - getGroupIdTable(group.deviceId()).remove(group.id(), group); - } - - if (groupEvent != null) { - notifyDelegate(groupEvent); - } - } - } - - private void process(GroupStoreMessage groupOp) { - log.debug("Received remote group operation {} request for device {}", - groupOp.type(), - groupOp.deviceId()); - if (!mastershipService.isLocalMaster(groupOp.deviceId())) { - log.warn("This node is not MASTER for device {}", groupOp.deviceId()); - return; - } - if (groupOp.type() == GroupStoreMessage.Type.ADD) { - storeGroupDescriptionInternal(groupOp.groupDesc()); - } else if (groupOp.type() == GroupStoreMessage.Type.UPDATE) { - updateGroupDescriptionInternal(groupOp.deviceId(), - groupOp.appCookie(), - groupOp.updateType(), - groupOp.updateBuckets(), - groupOp.newAppCookie()); - } else if (groupOp.type() == GroupStoreMessage.Type.DELETE) { - deleteGroupDescriptionInternal(groupOp.deviceId(), - groupOp.appCookie()); - } - } - - /** - * Flattened map key to be used to store group entries. - */ - protected static class GroupStoreMapKey { - private final DeviceId deviceId; - - public GroupStoreMapKey(DeviceId deviceId) { - this.deviceId = deviceId; - } - - public DeviceId deviceId() { - return deviceId; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof GroupStoreMapKey)) { - return false; - } - GroupStoreMapKey that = (GroupStoreMapKey) o; - return this.deviceId.equals(that.deviceId); - } - - @Override - public int hashCode() { - int result = 17; - - result = 31 * result + Objects.hash(this.deviceId); - - return result; - } - } - - protected static class GroupStoreKeyMapKey extends GroupStoreMapKey { - private final GroupKey appCookie; - public GroupStoreKeyMapKey(DeviceId deviceId, - GroupKey appCookie) { - super(deviceId); - this.appCookie = appCookie; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof GroupStoreKeyMapKey)) { - return false; - } - GroupStoreKeyMapKey that = (GroupStoreKeyMapKey) o; - return (super.equals(that) && - this.appCookie.equals(that.appCookie)); - } - - @Override - public int hashCode() { - int result = 17; - - result = 31 * result + super.hashCode() + Objects.hash(this.appCookie); - - return result; - } - } - - protected static class GroupStoreIdMapKey extends GroupStoreMapKey { - private final GroupId groupId; - public GroupStoreIdMapKey(DeviceId deviceId, - GroupId groupId) { - super(deviceId); - this.groupId = groupId; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof GroupStoreIdMapKey)) { - return false; - } - GroupStoreIdMapKey that = (GroupStoreIdMapKey) o; - return (super.equals(that) && - this.groupId.equals(that.groupId)); - } - - @Override - public int hashCode() { - int result = 17; - - result = 31 * result + super.hashCode() + Objects.hash(this.groupId); - - return result; - } - } - - @Override - public void pushGroupMetrics(DeviceId deviceId, - Collection<Group> groupEntries) { - boolean deviceInitialAuditStatus = - deviceInitialAuditStatus(deviceId); - Set<Group> southboundGroupEntries = - Sets.newHashSet(groupEntries); - Set<StoredGroupEntry> storedGroupEntries = - Sets.newHashSet(getStoredGroups(deviceId)); - Set<Group> extraneousStoredEntries = - Sets.newHashSet(getExtraneousGroups(deviceId)); - - log.trace("pushGroupMetrics: Displaying all ({}) southboundGroupEntries for device {}", - southboundGroupEntries.size(), - deviceId); - for (Iterator<Group> it = southboundGroupEntries.iterator(); it.hasNext();) { - Group group = it.next(); - log.trace("Group {} in device {}", group, deviceId); - } - - log.trace("Displaying all ({}) stored group entries for device {}", - storedGroupEntries.size(), - deviceId); - for (Iterator<StoredGroupEntry> it1 = storedGroupEntries.iterator(); - it1.hasNext();) { - Group group = it1.next(); - log.trace("Stored Group {} for device {}", group, deviceId); - } - - for (Iterator<Group> it2 = southboundGroupEntries.iterator(); it2.hasNext();) { - Group group = it2.next(); - if (storedGroupEntries.remove(group)) { - // we both have the group, let's update some info then. - log.trace("Group AUDIT: group {} exists in both planes for device {}", - group.id(), deviceId); - groupAdded(group); - it2.remove(); - } - } - for (Group group : southboundGroupEntries) { - if (getGroup(group.deviceId(), group.id()) != null) { - // There is a group existing with the same id - // It is possible that group update is - // in progress while we got a stale info from switch - if (!storedGroupEntries.remove(getGroup( - group.deviceId(), group.id()))) { - log.warn("Group AUDIT: Inconsistent state:" - + "Group exists in ID based table while " - + "not present in key based table"); - } - } else { - // there are groups in the switch that aren't in the store - log.debug("Group AUDIT: extraneous group {} exists in data plane for device {}", - group.id(), deviceId); - extraneousStoredEntries.remove(group); - extraneousGroup(group); - } - } - for (Group group : storedGroupEntries) { - // there are groups in the store that aren't in the switch - log.debug("Group AUDIT: group {} missing in data plane for device {}", - group.id(), deviceId); - groupMissing(group); - } - for (Group group : extraneousStoredEntries) { - // there are groups in the extraneous store that - // aren't in the switch - log.debug("Group AUDIT: clearing extransoeus group {} from store for device {}", - group.id(), deviceId); - removeExtraneousGroupEntry(group); - } - - if (!deviceInitialAuditStatus) { - log.debug("Group AUDIT: Setting device {} initial AUDIT completed", - deviceId); - deviceInitialAuditCompleted(deviceId, true); - } - } - - private void groupMissing(Group group) { - switch (group.state()) { - case PENDING_DELETE: - log.debug("Group {} delete confirmation from device {}", - group, group.deviceId()); - removeGroupEntry(group); - break; - case ADDED: - case PENDING_ADD: - case PENDING_ADD_RETRY: - case PENDING_UPDATE: - log.debug("Group {} is in store but not on device {}", - group, group.deviceId()); - StoredGroupEntry existing = - getStoredGroupEntry(group.deviceId(), group.id()); - log.debug("groupMissing: group entry {} in device {} moving from {} to PENDING_ADD_RETRY", - existing.id(), - existing.deviceId(), - existing.state()); - existing.setState(Group.GroupState.PENDING_ADD_RETRY); - //Re-PUT map entries to trigger map update events - getGroupStoreKeyMap(). - put(new GroupStoreKeyMapKey(existing.deviceId(), - existing.appCookie()), existing); - notifyDelegate(new GroupEvent(GroupEvent.Type.GROUP_ADD_REQUESTED, - group)); - break; - default: - log.debug("Group {} has not been installed.", group); - break; - } - } - - private void extraneousGroup(Group group) { - log.debug("Group {} is on device {} but not in store.", - group, group.deviceId()); - addOrUpdateExtraneousGroupEntry(group); - } - - private void groupAdded(Group group) { - log.trace("Group {} Added or Updated in device {}", - group, group.deviceId()); - addOrUpdateGroupEntry(group); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/GroupStoreMessage.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/GroupStoreMessage.java deleted file mode 100644 index b82754b9..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/GroupStoreMessage.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.group.impl; - -import org.onosproject.net.DeviceId; -import org.onosproject.net.group.GroupBuckets; -import org.onosproject.net.group.GroupDescription; -import org.onosproject.net.group.GroupKey; -import org.onosproject.net.group.GroupStore.UpdateType; - -/** - * Format of the Group store message that is used to - * communicate with the peer nodes in the cluster. - */ -public final class GroupStoreMessage { - private final DeviceId deviceId; - private final GroupKey appCookie; - private final GroupDescription groupDesc; - private final UpdateType updateType; - private final GroupBuckets updateBuckets; - private final GroupKey newAppCookie; - private final Type type; - - /** - * Type of group store request. - */ - public enum Type { - ADD, - UPDATE, - DELETE - } - - private GroupStoreMessage(Type type, - DeviceId deviceId, - GroupKey appCookie, - GroupDescription groupDesc, - UpdateType updateType, - GroupBuckets updateBuckets, - GroupKey newAppCookie) { - this.type = type; - this.deviceId = deviceId; - this.appCookie = appCookie; - this.groupDesc = groupDesc; - this.updateType = updateType; - this.updateBuckets = updateBuckets; - this.newAppCookie = newAppCookie; - } - - /** - * Creates a group store message for group ADD request. - * - * @param deviceId device identifier in which group to be added - * @param desc group creation parameters - * @return constructed group store message - */ - public static GroupStoreMessage createGroupAddRequestMsg(DeviceId deviceId, - GroupDescription desc) { - return new GroupStoreMessage(Type.ADD, - deviceId, - null, - desc, - null, - null, - null); - } - - /** - * Creates a group store message for group UPDATE request. - * - * @param deviceId the device ID - * @param appCookie the current group key - * @param updateType update (add or delete) type - * @param updateBuckets group buckets for updates - * @param newAppCookie optional new group key - * @return constructed group store message - */ - public static GroupStoreMessage createGroupUpdateRequestMsg(DeviceId deviceId, - GroupKey appCookie, - UpdateType updateType, - GroupBuckets updateBuckets, - GroupKey newAppCookie) { - return new GroupStoreMessage(Type.UPDATE, - deviceId, - appCookie, - null, - updateType, - updateBuckets, - newAppCookie); - } - - /** - * Creates a group store message for group DELETE request. - * - * @param deviceId the device ID - * @param appCookie the group key - * @return constructed group store message - */ - public static GroupStoreMessage createGroupDeleteRequestMsg(DeviceId deviceId, - GroupKey appCookie) { - return new GroupStoreMessage(Type.DELETE, - deviceId, - appCookie, - null, - null, - null, - null); - } - - /** - * Returns the device identifier of this group request. - * - * @return device identifier - */ - public DeviceId deviceId() { - return deviceId; - } - - /** - * Returns the application cookie associated with this group request. - * - * @return application cookie - */ - public GroupKey appCookie() { - return appCookie; - } - - /** - * Returns the group create parameters associated with this group request. - * - * @return group create parameters - */ - public GroupDescription groupDesc() { - return groupDesc; - } - - /** - * Returns the group buckets to be updated as part of this group request. - * - * @return group buckets to be updated - */ - public GroupBuckets updateBuckets() { - return updateBuckets; - } - - /** - * Returns the update group operation type. - * - * @return update operation type - */ - public UpdateType updateType() { - return updateType; - } - - /** - * Returns the new application cookie associated with this group operation. - * - * @return new application cookie - */ - public GroupKey newAppCookie() { - return newAppCookie; - } - - /** - * Returns the type of this group operation. - * - * @return group message type - */ - public Type type() { - return type; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/GroupStoreMessageSubjects.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/GroupStoreMessageSubjects.java deleted file mode 100644 index dbee22c7..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/GroupStoreMessageSubjects.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.group.impl; - -import org.onosproject.store.cluster.messaging.MessageSubject; - -/** - * MessageSubjects used by DistributedGroupRuleStore peer-peer communication. - */ -public final class GroupStoreMessageSubjects { - private GroupStoreMessageSubjects() {} - - public static final MessageSubject REMOTE_GROUP_OP_REQUEST - = new MessageSubject("peer-forward-group-op-req"); -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/package-info.java deleted file mode 100644 index 35e3b251..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/group/impl/package-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * Implementation of the group store. - */ -package org.onosproject.store.group.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java deleted file mode 100644 index 836a3c22..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.host.impl; - -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.packet.IpAddress; -import org.onlab.packet.MacAddress; -import org.onlab.packet.VlanId; -import org.onlab.util.KryoNamespace; -import org.onosproject.net.Annotations; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.DefaultHost; -import org.onosproject.net.DeviceId; -import org.onosproject.net.Host; -import org.onosproject.net.HostId; -import org.onosproject.net.HostLocation; -import org.onosproject.net.host.HostDescription; -import org.onosproject.net.host.HostEvent; -import org.onosproject.net.host.HostStore; -import org.onosproject.net.host.HostStoreDelegate; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.MapEvent; -import org.onosproject.store.service.MapEventListener; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.StorageService; -import org.slf4j.Logger; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static org.onosproject.net.DefaultAnnotations.merge; -import static org.onosproject.net.host.HostEvent.Type.*; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Manages the inventory of hosts using a {@code EventuallyConsistentMap}. - */ -@Component(immediate = true) -@Service -public class DistributedHostStore - extends AbstractStore<HostEvent, HostStoreDelegate> - implements HostStore { - - private final Logger log = getLogger(getClass()); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - private ConsistentMap<HostId, DefaultHost> host; - private Map<HostId, DefaultHost> hosts; - - private final ConcurrentHashMap<HostId, DefaultHost> prevHosts = - new ConcurrentHashMap<>(); - - private MapEventListener<HostId, DefaultHost> hostLocationTracker = - new HostLocationTracker(); - - @Activate - public void activate() { - KryoNamespace.Builder hostSerializer = KryoNamespace.newBuilder() - .register(KryoNamespaces.API); - - host = storageService.<HostId, DefaultHost>consistentMapBuilder() - .withName("onos-hosts") - .withRelaxedReadConsistency() - .withSerializer(Serializer.using(hostSerializer.build())) - .build(); - - hosts = host.asJavaMap(); - - host.addListener(hostLocationTracker); - - log.info("Started"); - } - - @Deactivate - public void deactivate() { - host.removeListener(hostLocationTracker); - prevHosts.clear(); - - log.info("Stopped"); - } - - // TODO No longer need to return HostEvent - @Override - public HostEvent createOrUpdateHost(ProviderId providerId, - HostId hostId, - HostDescription hostDescription, - boolean replaceIPs) { - // TODO: We need a way to detect conflicting changes and abort update. - // (BOC) Compute might do this for us. - - hosts.compute(hostId, (id, existingHost) -> { - HostLocation location = hostDescription.location(); - - final Set<IpAddress> addresses; - if (existingHost == null || replaceIPs) { - addresses = ImmutableSet.copyOf(hostDescription.ipAddress()); - } else { - addresses = Sets.newHashSet(existingHost.ipAddresses()); - addresses.addAll(hostDescription.ipAddress()); - } - - final Annotations annotations; - if (existingHost != null) { - annotations = merge((DefaultAnnotations) existingHost.annotations(), - hostDescription.annotations()); - } else { - annotations = hostDescription.annotations(); - } - - return new DefaultHost(providerId, - hostId, - hostDescription.hwAddress(), - hostDescription.vlan(), - location, - addresses, - annotations); - }); - - return null; - } - - // TODO No longer need to return HostEvent - @Override - public HostEvent removeHost(HostId hostId) { - hosts.remove(hostId); - return null; - } - - // TODO No longer need to return HostEvent - @Override - public HostEvent removeIp(HostId hostId, IpAddress ipAddress) { - hosts.compute(hostId, (id, existingHost) -> { - if (existingHost != null) { - checkState(Objects.equals(hostId.mac(), existingHost.mac()), - "Existing and new MAC addresses differ."); - checkState(Objects.equals(hostId.vlanId(), existingHost.vlan()), - "Existing and new VLANs differ."); - - Set<IpAddress> addresses = existingHost.ipAddresses(); - if (addresses != null && addresses.contains(ipAddress)) { - addresses = new HashSet<>(existingHost.ipAddresses()); - addresses.remove(ipAddress); - return new DefaultHost(existingHost.providerId(), - hostId, - existingHost.mac(), - existingHost.vlan(), - existingHost.location(), - ImmutableSet.copyOf(addresses), - existingHost.annotations()); - } else { - return existingHost; - } - } - return null; - }); - return null; - } - - @Override - public int getHostCount() { - return hosts.size(); - } - - @Override - public Iterable<Host> getHosts() { - return ImmutableSet.copyOf(hosts.values()); - } - - @Override - public Host getHost(HostId hostId) { - return hosts.get(hostId); - } - - @Override - public Set<Host> getHosts(VlanId vlanId) { - return filter(hosts.values(), host -> Objects.equals(host.vlan(), vlanId)); - } - - @Override - public Set<Host> getHosts(MacAddress mac) { - return filter(hosts.values(), host -> Objects.equals(host.mac(), mac)); - } - - @Override - public Set<Host> getHosts(IpAddress ip) { - return filter(hosts.values(), host -> host.ipAddresses().contains(ip)); - } - - @Override - public Set<Host> getConnectedHosts(ConnectPoint connectPoint) { - Set<Host> filtered = hosts.entrySet().stream() - .filter(entry -> entry.getValue().location().equals(connectPoint)) - .map(Map.Entry::getValue) - .collect(Collectors.toSet()); - return ImmutableSet.copyOf(filtered); - } - - @Override - public Set<Host> getConnectedHosts(DeviceId deviceId) { - Set<Host> filtered = hosts.entrySet().stream() - .filter(entry -> entry.getValue().location().deviceId().equals(deviceId)) - .map(Map.Entry::getValue) - .collect(Collectors.toSet()); - return ImmutableSet.copyOf(filtered); - } - - private Set<Host> filter(Collection<DefaultHost> collection, Predicate<DefaultHost> predicate) { - return collection.stream().filter(predicate).collect(Collectors.toSet()); - } - - private class HostLocationTracker implements MapEventListener<HostId, DefaultHost> { - @Override - public void event(MapEvent<HostId, DefaultHost> event) { - DefaultHost host = checkNotNull(event.value().value()); - if (event.type() == MapEvent.Type.INSERT) { - Host prevHost = prevHosts.put(host.id(), host); - if (prevHost == null) { - notifyDelegate(new HostEvent(HOST_ADDED, host)); - } else if (!Objects.equals(prevHost.location(), host.location())) { - notifyDelegate(new HostEvent(HOST_MOVED, host, prevHost)); - } else if (!Objects.equals(prevHost, host)) { - notifyDelegate(new HostEvent(HOST_UPDATED, host, prevHost)); - } - } else if (event.type() == MapEvent.Type.REMOVE) { - if (prevHosts.remove(host.id()) != null) { - notifyDelegate(new HostEvent(HOST_REMOVED, host)); - } - } - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/package-info.java deleted file mode 100644 index 635b1131..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of the distributed host store using p2p synchronization protocol. - */ -package org.onosproject.store.host.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/LogicalTimestamp.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/LogicalTimestamp.java deleted file mode 100644 index dfee9980..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/LogicalTimestamp.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.impl; - -import static com.google.common.base.Preconditions.checkArgument; - -import java.util.Objects; - -import org.onosproject.store.Timestamp; - -import com.google.common.base.MoreObjects; -import com.google.common.collect.ComparisonChain; - -/** - * Timestamp based on logical sequence value. - * <p> - * LogicalTimestamps are ordered by their sequence values. - */ -public class LogicalTimestamp implements Timestamp { - - private final long value; - - public LogicalTimestamp(long value) { - this.value = value; - } - - @Override - public int compareTo(Timestamp o) { - checkArgument(o instanceof LogicalTimestamp, - "Must be LogicalTimestamp", o); - LogicalTimestamp that = (LogicalTimestamp) o; - - return ComparisonChain.start() - .compare(this.value, that.value) - .result(); - } - - @Override - public int hashCode() { - return Long.hashCode(value); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof LogicalTimestamp)) { - return false; - } - LogicalTimestamp that = (LogicalTimestamp) obj; - return Objects.equals(this.value, that.value); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("value", value) - .toString(); - } - - /** - * Returns the sequence value. - * - * @return sequence value - */ - public long value() { - return this.value; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/MastershipBasedTimestamp.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/MastershipBasedTimestamp.java deleted file mode 100644 index 15b3c3c6..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/MastershipBasedTimestamp.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.impl; - -import static com.google.common.base.Preconditions.checkArgument; - -import java.util.Objects; - -import org.onosproject.store.Timestamp; - -import com.google.common.base.MoreObjects; -import com.google.common.collect.ComparisonChain; - -/** - * A logical timestamp that derives its value from two things: - * <ul> - * <li> The current mastership term of the device.</li> - * <li> The value of the counter used for tracking topology events observed from - * the device during that current time of a device. </li> - * </ul> - */ -public final class MastershipBasedTimestamp implements Timestamp { - - private final long termNumber; - private final long sequenceNumber; - - /** - * Default version tuple. - * - * @param termNumber the mastership termNumber - * @param sequenceNumber the sequenceNumber number within the termNumber - */ - public MastershipBasedTimestamp(long termNumber, long sequenceNumber) { - this.termNumber = termNumber; - this.sequenceNumber = sequenceNumber; - } - - @Override - public int compareTo(Timestamp o) { - checkArgument(o instanceof MastershipBasedTimestamp, - "Must be MastershipBasedTimestamp", o); - MastershipBasedTimestamp that = (MastershipBasedTimestamp) o; - - return ComparisonChain.start() - .compare(this.termNumber, that.termNumber) - .compare(this.sequenceNumber, that.sequenceNumber) - .result(); - } - - @Override - public int hashCode() { - return Objects.hash(termNumber, sequenceNumber); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof MastershipBasedTimestamp)) { - return false; - } - MastershipBasedTimestamp that = (MastershipBasedTimestamp) obj; - return Objects.equals(this.termNumber, that.termNumber) && - Objects.equals(this.sequenceNumber, that.sequenceNumber); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("termNumber", termNumber) - .add("sequenceNumber", sequenceNumber) - .toString(); - } - - /** - * Returns the termNumber. - * - * @return termNumber - */ - public long termNumber() { - return termNumber; - } - - /** - * Returns the sequenceNumber number. - * - * @return sequenceNumber - */ - public long sequenceNumber() { - return sequenceNumber; - } - - // Default constructor for serialization - - /** - * @deprecated in Cardinal Release - */ - @Deprecated - protected MastershipBasedTimestamp() { - this.termNumber = -1; - this.sequenceNumber = -1; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/Timestamped.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/Timestamped.java deleted file mode 100644 index ae7267b8..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/Timestamped.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.impl; - -import com.google.common.base.MoreObjects; -import org.onosproject.store.Timestamp; - -import java.util.Objects; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Wrapper class to store Timestamped value. - * - * @param <T> Timestamped value type - */ -public final class Timestamped<T> { - - private final Timestamp timestamp; - private final T value; - - /** - * Creates a time stamped value. - * - * @param value to be timestamp - * @param timestamp the timestamp - */ - public Timestamped(T value, Timestamp timestamp) { - this.value = checkNotNull(value); - this.timestamp = checkNotNull(timestamp); - } - - /** - * Returns the value. - * - * @return value - */ - public T value() { - return value; - } - - /** - * Returns the time stamp. - * - * @return time stamp - */ - public Timestamp timestamp() { - return timestamp; - } - - /** - * Tests if this timestamped value is newer than the other. - * - * @param other timestamped value - * @return true if this instance is newer. - */ - public boolean isNewer(Timestamped<T> other) { - return isNewerThan(checkNotNull(other).timestamp()); - } - - /** - * Tests if this timestamp is newer than the specified timestamp. - * - * @param other timestamp to compare against - * @return true if this instance is newer - */ - public boolean isNewerThan(Timestamp other) { - return timestamp.isNewerThan(other); - } - - @Override - public int hashCode() { - return timestamp.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof Timestamped)) { - return false; - } - @SuppressWarnings("unchecked") - Timestamped<T> that = (Timestamped<T>) obj; - return Objects.equals(this.timestamp, that.timestamp); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("timestamp", timestamp) - .add("value", value) - .toString(); - } - - // Default constructor for serialization - /** - * @deprecated in Cardinal Release - */ - @Deprecated - private Timestamped() { - this.value = null; - this.timestamp = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/package-info.java deleted file mode 100644 index 03786fac..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Common facilities for use by various distributed stores. - */ -package org.onosproject.store.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/GossipIntentStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/GossipIntentStore.java deleted file mode 100644 index 1e5db99c..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/GossipIntentStore.java +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.intent.impl; - -import com.google.common.collect.ImmutableList; - -import org.apache.commons.lang.math.RandomUtils; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.NodeId; -import org.onosproject.net.intent.Intent; -import org.onosproject.net.intent.IntentData; -import org.onosproject.net.intent.IntentEvent; -import org.onosproject.net.intent.IntentState; -import org.onosproject.net.intent.IntentStore; -import org.onosproject.net.intent.IntentStoreDelegate; -import org.onosproject.net.intent.Key; -import org.onosproject.net.intent.PartitionService; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.service.MultiValuedTimestamp; -import org.onosproject.store.service.WallClockTimestamp; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.EventuallyConsistentMapEvent; -import org.onosproject.store.service.EventuallyConsistentMapListener; -import org.onosproject.store.service.StorageService; -import org.slf4j.Logger; - -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicLong; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.onosproject.net.intent.IntentState.PURGE_REQ; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Manages inventory of Intents in a distributed data store that uses optimistic - * replication and gossip based techniques. - */ -//FIXME we should listen for leadership changes. if the local instance has just -// ... become a leader, scan the pending map and process those -@Component(immediate = true, enabled = true) -@Service -public class GossipIntentStore - extends AbstractStore<IntentEvent, IntentStoreDelegate> - implements IntentStore { - - private final Logger log = getLogger(getClass()); - - // Map of intent key => current intent state - private EventuallyConsistentMap<Key, IntentData> currentMap; - - // Map of intent key => pending intent operation - private EventuallyConsistentMap<Key, IntentData> pendingMap; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected PartitionService partitionService; - - private final AtomicLong sequenceNumber = new AtomicLong(0); - - @Activate - public void activate() { - KryoNamespace.Builder intentSerializer = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .register(IntentData.class) - .register(MultiValuedTimestamp.class) - .register(WallClockTimestamp.class); - - currentMap = storageService.<Key, IntentData>eventuallyConsistentMapBuilder() - .withName("intent-current") - .withSerializer(intentSerializer) - .withTimestampProvider((key, intentData) -> - new MultiValuedTimestamp<>(intentData.version(), - sequenceNumber.getAndIncrement())) - .withPeerUpdateFunction((key, intentData) -> getPeerNodes(key, intentData)) - .build(); - - pendingMap = storageService.<Key, IntentData>eventuallyConsistentMapBuilder() - .withName("intent-pending") - .withSerializer(intentSerializer) - .withTimestampProvider((key, intentData) -> new MultiValuedTimestamp<>(intentData.version(), - System.nanoTime())) - .withPeerUpdateFunction((key, intentData) -> getPeerNodes(key, intentData)) - .build(); - - currentMap.addListener(new InternalCurrentListener()); - pendingMap.addListener(new InternalPendingListener()); - - log.info("Started"); - } - - @Deactivate - public void deactivate() { - currentMap.destroy(); - pendingMap.destroy(); - - log.info("Stopped"); - } - - @Override - public long getIntentCount() { - return currentMap.size(); - } - - @Override - public Iterable<Intent> getIntents() { - return currentMap.values().stream() - .map(IntentData::intent) - .collect(Collectors.toList()); - } - - @Override - public Iterable<IntentData> getIntentData(boolean localOnly, long olderThan) { - if (localOnly || olderThan > 0) { - long now = System.currentTimeMillis(); - final WallClockTimestamp time = new WallClockTimestamp(now - olderThan); - return currentMap.values().stream() - .filter(data -> data.version().isOlderThan(time) && - (!localOnly || isMaster(data.key()))) - .collect(Collectors.toList()); - } - return currentMap.values(); - } - - @Override - public IntentState getIntentState(Key intentKey) { - IntentData data = currentMap.get(intentKey); - if (data != null) { - return data.state(); - } - return null; - } - - @Override - public List<Intent> getInstallableIntents(Key intentKey) { - IntentData data = currentMap.get(intentKey); - if (data != null) { - return data.installables(); - } - return null; - } - - - - @Override - public void write(IntentData newData) { - checkNotNull(newData); - - IntentData currentData = currentMap.get(newData.key()); - if (IntentData.isUpdateAcceptable(currentData, newData)) { - // Only the master is modifying the current state. Therefore assume - // this always succeeds - if (newData.state() == PURGE_REQ) { - currentMap.remove(newData.key(), currentData); - } else { - currentMap.put(newData.key(), new IntentData(newData)); - } - - // if current.put succeeded - pendingMap.remove(newData.key(), newData); - } - } - - private Collection<NodeId> getPeerNodes(Key key, IntentData data) { - NodeId master = partitionService.getLeader(key); - NodeId origin = (data != null) ? data.origin() : null; - if (data != null && (master == null || origin == null)) { - log.debug("Intent {} missing master and/or origin; master = {}, origin = {}", - key, master, origin); - } - - NodeId me = clusterService.getLocalNode().id(); - boolean isMaster = Objects.equals(master, me); - boolean isOrigin = Objects.equals(origin, me); - if (isMaster && isOrigin) { - return getRandomNode(); - } else if (isMaster) { - return origin != null ? ImmutableList.of(origin) : getRandomNode(); - } else if (isOrigin) { - return master != null ? ImmutableList.of(master) : getRandomNode(); - } else { - log.warn("No master or origin for intent {}", key); - return master != null ? ImmutableList.of(master) : getRandomNode(); - } - } - - private List<NodeId> getRandomNode() { - NodeId me = clusterService.getLocalNode().id(); - List<NodeId> nodes = clusterService.getNodes().stream() - .map(ControllerNode::id) - .filter(node -> !Objects.equals(node, me)) - .collect(Collectors.toList()); - if (nodes.size() == 0) { - return null; - } - return ImmutableList.of(nodes.get(RandomUtils.nextInt(nodes.size()))); - } - - @Override - public void batchWrite(Iterable<IntentData> updates) { - updates.forEach(this::write); - } - - @Override - public Intent getIntent(Key key) { - IntentData data = currentMap.get(key); - if (data != null) { - return data.intent(); - } - return null; - } - - @Override - public IntentData getIntentData(Key key) { - IntentData current = currentMap.get(key); - if (current == null) { - return null; - } - return new IntentData(current); - } - - @Override - public void addPending(IntentData data) { - checkNotNull(data); - - if (data.version() == null) { - data.setVersion(new WallClockTimestamp()); - } - data.setOrigin(clusterService.getLocalNode().id()); - pendingMap.put(data.key(), new IntentData(data)); - } - - @Override - public boolean isMaster(Key intentKey) { - return partitionService.isMine(intentKey); - } - - @Override - public Iterable<Intent> getPending() { - return pendingMap.values().stream() - .map(IntentData::intent) - .collect(Collectors.toList()); - } - - @Override - public Iterable<IntentData> getPendingData() { - return pendingMap.values(); - } - - @Override - public Iterable<IntentData> getPendingData(boolean localOnly, long olderThan) { - long now = System.currentTimeMillis(); - final WallClockTimestamp time = new WallClockTimestamp(now - olderThan); - return pendingMap.values().stream() - .filter(data -> data.version().isOlderThan(time) && - (!localOnly || isMaster(data.key()))) - .collect(Collectors.toList()); - } - - private void notifyDelegateIfNotNull(IntentEvent event) { - if (event != null) { - notifyDelegate(event); - } - } - - private final class InternalCurrentListener implements - EventuallyConsistentMapListener<Key, IntentData> { - @Override - public void event(EventuallyConsistentMapEvent<Key, IntentData> event) { - IntentData intentData = event.value(); - - if (event.type() == EventuallyConsistentMapEvent.Type.PUT) { - // The current intents map has been updated. If we are master for - // this intent's partition, notify the Manager that it should - // emit notifications about updated tracked resources. - if (delegate != null && isMaster(event.value().intent().key())) { - delegate.onUpdate(new IntentData(intentData)); // copy for safety, likely unnecessary - } - notifyDelegateIfNotNull(IntentEvent.getEvent(intentData)); - } - } - } - - private final class InternalPendingListener implements - EventuallyConsistentMapListener<Key, IntentData> { - @Override - public void event( - EventuallyConsistentMapEvent<Key, IntentData> event) { - if (event.type() == EventuallyConsistentMapEvent.Type.PUT) { - // The pending intents map has been updated. If we are master for - // this intent's partition, notify the Manager that it should do - // some work. - if (isMaster(event.value().intent().key())) { - if (delegate != null) { - delegate.process(new IntentData(event.value())); - } - } - - notifyDelegateIfNotNull(IntentEvent.getEvent(event.value())); - } - } - } - -} - diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/PartitionId.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/PartitionId.java deleted file mode 100644 index f6cd198f..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/PartitionId.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.intent.impl; - -import com.google.common.base.MoreObjects; - -import java.util.Objects; - -/** - * Identifies a partition of the intent keyspace which will be assigned to and - * processed by a single ONOS instance at a time. - */ -public class PartitionId { - private final int id; - - /** - * Creates a new partition ID. - * - * @param id the partition ID - */ - PartitionId(int id) { - this.id = id; - } - - /** - * Returns the integer ID value. - * - * @return ID value - */ - public int value() { - return id; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof PartitionId)) { - return false; - } - - PartitionId that = (PartitionId) o; - return Objects.equals(this.id, that.id); - } - - @Override - public int hashCode() { - return id; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("partition ID", id) - .toString(); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/PartitionManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/PartitionManager.java deleted file mode 100644 index 09108d28..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/PartitionManager.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.intent.impl; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onosproject.cluster.ClusterEvent; -import org.onosproject.cluster.ClusterEventListener; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.Leadership; -import org.onosproject.cluster.LeadershipEvent; -import org.onosproject.cluster.LeadershipEventListener; -import org.onosproject.cluster.LeadershipService; -import org.onosproject.cluster.NodeId; -import org.onosproject.event.EventDeliveryService; -import org.onosproject.event.ListenerRegistry; -import org.onosproject.net.intent.Key; -import org.onosproject.net.intent.PartitionEvent; -import org.onosproject.net.intent.PartitionEventListener; -import org.onosproject.net.intent.PartitionService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; -import java.util.Objects; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Collectors; - -/** - * Manages the assignment of intent keyspace partitions to instances. - */ -@Component(immediate = true) -@Service -public class PartitionManager implements PartitionService { - - private static final Logger log = LoggerFactory.getLogger(PartitionManager.class); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected LeadershipService leadershipService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected EventDeliveryService eventDispatcher; - - protected final AtomicBoolean rebalanceScheduled = new AtomicBoolean(false); - - static final int NUM_PARTITIONS = 14; - private static final int BACKOFF_TIME = 2; - private static final int CHECK_PARTITION_BALANCE_PERIOD_SEC = 10; - private static final int RETRY_AFTER_DELAY_SEC = 5; - - private static final String ELECTION_PREFIX = "intent-partition-"; - - private ListenerRegistry<PartitionEvent, PartitionEventListener> listenerRegistry; - private LeadershipEventListener leaderListener = new InternalLeadershipListener(); - private ClusterEventListener clusterListener = new InternalClusterEventListener(); - - private ScheduledExecutorService executor = Executors - .newScheduledThreadPool(1); - - @Activate - public void activate() { - leadershipService.addListener(leaderListener); - clusterService.addListener(clusterListener); - - listenerRegistry = new ListenerRegistry<>(); - eventDispatcher.addSink(PartitionEvent.class, listenerRegistry); - - for (int i = 0; i < NUM_PARTITIONS; i++) { - leadershipService.runForLeadership(getPartitionPath(i)); - } - - executor.scheduleAtFixedRate(() -> scheduleRebalance(0), 0, - CHECK_PARTITION_BALANCE_PERIOD_SEC, TimeUnit.SECONDS); - } - - @Deactivate - public void deactivate() { - executor.shutdownNow(); - - eventDispatcher.removeSink(PartitionEvent.class); - leadershipService.removeListener(leaderListener); - clusterService.removeListener(clusterListener); - } - - /** - * Sets the specified executor to be used for scheduling background tasks. - * - * @param executor scheduled executor service for background tasks - * @return this PartitionManager - */ - public PartitionManager withScheduledExecutor(ScheduledExecutorService executor) { - this.executor = executor; - return this; - } - - private String getPartitionPath(int i) { - return ELECTION_PREFIX + i; - } - - private String getPartitionPath(PartitionId id) { - return getPartitionPath(id.value()); - } - - private PartitionId getPartitionForKey(Key intentKey) { - int partition = Math.abs((int) intentKey.hash()) % NUM_PARTITIONS; - //TODO investigate Guava consistent hash method - // ... does it add significant computational complexity? is it worth it? - //int partition = consistentHash(intentKey.hash(), NUM_PARTITIONS); - PartitionId id = new PartitionId(partition); - return id; - } - - @Override - public boolean isMine(Key intentKey) { - return Objects.equals(leadershipService.getLeader(getPartitionPath(getPartitionForKey(intentKey))), - clusterService.getLocalNode().id()); - } - - @Override - public NodeId getLeader(Key intentKey) { - return leadershipService.getLeader(getPartitionPath(getPartitionForKey(intentKey))); - } - - @Override - public void addListener(PartitionEventListener listener) { - listenerRegistry.addListener(listener); - } - - @Override - public void removeListener(PartitionEventListener listener) { - listenerRegistry.removeListener(listener); - } - - protected void doRebalance() { - rebalanceScheduled.set(false); - try { - rebalance(); - } catch (Exception e) { - log.warn("Exception caught during rebalance task. Will retry in " + RETRY_AFTER_DELAY_SEC + " seconds", e); - scheduleRebalance(RETRY_AFTER_DELAY_SEC); - } - } - - /** - * Determine whether we have more than our fair share of partitions, and if - * so, relinquish leadership of some of them for a little while to let - * other instances take over. - */ - private void rebalance() { - int activeNodes = (int) clusterService.getNodes() - .stream() - .filter(node -> ControllerNode.State.ACTIVE == clusterService.getState(node.id())) - .count(); - - int myShare = (int) Math.ceil((double) NUM_PARTITIONS / activeNodes); - - List<Leadership> myPartitions = leadershipService.getLeaderBoard().values() - .stream() - .filter(l -> clusterService.getLocalNode().id().equals(l.leader())) - .filter(l -> l.topic().startsWith(ELECTION_PREFIX)) - .collect(Collectors.toList()); - - int relinquish = myPartitions.size() - myShare; - - if (relinquish <= 0) { - return; - } - - for (int i = 0; i < relinquish; i++) { - String topic = myPartitions.get(i).topic(); - leadershipService.withdraw(topic); - - executor.schedule(() -> recontest(topic), - BACKOFF_TIME, TimeUnit.SECONDS); - } - } - - private void scheduleRebalance(int afterDelaySec) { - if (rebalanceScheduled.compareAndSet(false, true)) { - executor.schedule(this::doRebalance, afterDelaySec, TimeUnit.SECONDS); - } - } - - /** - * Try and recontest for leadership of a partition. - * - * @param path topic name to recontest - */ - private void recontest(String path) { - leadershipService.runForLeadership(path); - } - - private final class InternalLeadershipListener implements LeadershipEventListener { - - @Override - public void event(LeadershipEvent event) { - Leadership leadership = event.subject(); - - if (Objects.equals(leadership.leader(), clusterService.getLocalNode().id()) && - leadership.topic().startsWith(ELECTION_PREFIX)) { - - // See if we need to let some partitions go - scheduleRebalance(0); - - eventDispatcher.post(new PartitionEvent(PartitionEvent.Type.LEADER_CHANGED, - leadership.topic())); - } - } - } - - private final class InternalClusterEventListener implements - ClusterEventListener { - - @Override - public void event(ClusterEvent event) { - scheduleRebalance(0); - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/package-info.java deleted file mode 100644 index a8db8ff2..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of distributed intent store. - */ -package org.onosproject.store.intent.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/ECLinkStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/ECLinkStore.java deleted file mode 100644 index 243caf80..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/ECLinkStore.java +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.link.impl; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.onosproject.net.DefaultAnnotations.merge; -import static org.onosproject.net.DefaultAnnotations.union; -import static org.onosproject.net.Link.State.ACTIVE; -import static org.onosproject.net.Link.State.INACTIVE; -import static org.onosproject.net.Link.Type.DIRECT; -import static org.onosproject.net.Link.Type.INDIRECT; -import static org.onosproject.net.LinkKey.linkKey; -import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED; -import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED; -import static org.onosproject.net.link.LinkEvent.Type.LINK_UPDATED; -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT; -import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE; -import static org.slf4j.LoggerFactory.getLogger; - -import java.util.Collection; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onlab.util.SharedExecutors; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.NodeId; -import org.onosproject.mastership.MastershipService; -import org.onosproject.net.AnnotationKeys; -import org.onosproject.net.AnnotationsUtil; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.DefaultLink; -import org.onosproject.net.DeviceId; -import org.onosproject.net.Link; -import org.onosproject.net.LinkKey; -import org.onosproject.net.Link.Type; -import org.onosproject.net.device.DeviceClockService; -import org.onosproject.net.link.DefaultLinkDescription; -import org.onosproject.net.link.LinkDescription; -import org.onosproject.net.link.LinkEvent; -import org.onosproject.net.link.LinkStore; -import org.onosproject.net.link.LinkStoreDelegate; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.cluster.messaging.MessageSubject; -import org.onosproject.store.impl.MastershipBasedTimestamp; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.serializers.KryoSerializer; -import org.onosproject.store.serializers.custom.DistributedStoreSerializers; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.EventuallyConsistentMapEvent; -import org.onosproject.store.service.EventuallyConsistentMapListener; -import org.onosproject.store.service.StorageService; -import org.slf4j.Logger; - -import com.google.common.collect.Iterables; -import com.google.common.collect.Maps; -import com.google.common.util.concurrent.Futures; - -/** - * Manages the inventory of links using a {@code EventuallyConsistentMap}. - */ -@Component(immediate = true, enabled = true) -@Service -public class ECLinkStore - extends AbstractStore<LinkEvent, LinkStoreDelegate> - implements LinkStore { - - private final Logger log = getLogger(getClass()); - - private final Map<LinkKey, Link> links = Maps.newConcurrentMap(); - private EventuallyConsistentMap<Provided<LinkKey>, LinkDescription> linkDescriptions; - - private static final MessageSubject LINK_INJECT_MESSAGE = new MessageSubject("inject-link-request"); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipService mastershipService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected DeviceClockService deviceClockService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterCommunicationService clusterCommunicator; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - private EventuallyConsistentMapListener<Provided<LinkKey>, LinkDescription> linkTracker = - new InternalLinkTracker(); - - protected static final KryoSerializer SERIALIZER = new KryoSerializer() { - @Override - protected void setupKryoPool() { - serializerPool = KryoNamespace.newBuilder() - .register(DistributedStoreSerializers.STORE_COMMON) - .nextId(DistributedStoreSerializers.STORE_CUSTOM_BEGIN) - .register(Provided.class) - .build(); - } - }; - - @Activate - public void activate() { - KryoNamespace.Builder serializer = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .register(MastershipBasedTimestamp.class) - .register(Provided.class); - - linkDescriptions = storageService.<Provided<LinkKey>, LinkDescription>eventuallyConsistentMapBuilder() - .withName("onos-link-descriptions") - .withSerializer(serializer) - .withTimestampProvider((k, v) -> { - try { - return v == null ? null : deviceClockService.getTimestamp(v.dst().deviceId()); - } catch (IllegalStateException e) { - return null; - } - }).build(); - - clusterCommunicator.addSubscriber(LINK_INJECT_MESSAGE, - SERIALIZER::decode, - this::injectLink, - SERIALIZER::encode, - SharedExecutors.getPoolThreadExecutor()); - - linkDescriptions.addListener(linkTracker); - - log.info("Started"); - } - - @Deactivate - public void deactivate() { - linkDescriptions.removeListener(linkTracker); - linkDescriptions.destroy(); - links.clear(); - clusterCommunicator.removeSubscriber(LINK_INJECT_MESSAGE); - - log.info("Stopped"); - } - - @Override - public int getLinkCount() { - return links.size(); - } - - @Override - public Iterable<Link> getLinks() { - return links.values(); - } - - @Override - public Set<Link> getDeviceEgressLinks(DeviceId deviceId) { - return filter(links.values(), link -> deviceId.equals(link.src().deviceId())); - } - - @Override - public Set<Link> getDeviceIngressLinks(DeviceId deviceId) { - return filter(links.values(), link -> deviceId.equals(link.dst().deviceId())); - } - - @Override - public Link getLink(ConnectPoint src, ConnectPoint dst) { - return links.get(linkKey(src, dst)); - } - - @Override - public Set<Link> getEgressLinks(ConnectPoint src) { - return filter(links.values(), link -> src.equals(link.src())); - } - - @Override - public Set<Link> getIngressLinks(ConnectPoint dst) { - return filter(links.values(), link -> dst.equals(link.dst())); - } - - @Override - public LinkEvent createOrUpdateLink(ProviderId providerId, - LinkDescription linkDescription) { - final DeviceId dstDeviceId = linkDescription.dst().deviceId(); - final NodeId dstNodeId = mastershipService.getMasterFor(dstDeviceId); - - // Process link update only if we're the master of the destination node, - // otherwise signal the actual master. - if (clusterService.getLocalNode().id().equals(dstNodeId)) { - LinkKey linkKey = linkKey(linkDescription.src(), linkDescription.dst()); - Provided<LinkKey> internalLinkKey = getProvided(linkKey, providerId); - if (internalLinkKey == null) { - return null; - } - linkDescriptions.compute(internalLinkKey, (k, v) -> createOrUpdateLinkInternal(v , linkDescription)); - return refreshLinkCache(linkKey); - } else { - if (dstNodeId == null) { - return null; - } - return Futures.getUnchecked(clusterCommunicator.sendAndReceive(new Provided<>(linkDescription, providerId), - LINK_INJECT_MESSAGE, - SERIALIZER::encode, - SERIALIZER::decode, - dstNodeId)); - } - } - - private Provided<LinkKey> getProvided(LinkKey linkKey, ProviderId provId) { - ProviderId bpid = getBaseProviderId(linkKey); - if (provId == null) { - // The LinkService didn't know who this LinkKey belongs to. - // A fix is to either modify the getProvider() in LinkService classes - // or expose the contents of linkDescriptions to the LinkService. - return (bpid == null) ? null : new Provided<>(linkKey, bpid); - } else { - return new Provided<>(linkKey, provId); - } - } - - private LinkDescription createOrUpdateLinkInternal(LinkDescription current, LinkDescription updated) { - if (current != null) { - // we only allow transition from INDIRECT -> DIRECT - return new DefaultLinkDescription( - current.src(), - current.dst(), - current.type() == DIRECT ? DIRECT : updated.type(), - union(current.annotations(), updated.annotations())); - } - return updated; - } - - private LinkEvent refreshLinkCache(LinkKey linkKey) { - AtomicReference<LinkEvent.Type> eventType = new AtomicReference<>(); - Link link = links.compute(linkKey, (key, existingLink) -> { - Link newLink = composeLink(linkKey); - if (existingLink == null) { - eventType.set(LINK_ADDED); - return newLink; - } else if (existingLink.state() != newLink.state() || - (existingLink.type() == INDIRECT && newLink.type() == DIRECT) || - !AnnotationsUtil.isEqual(existingLink.annotations(), newLink.annotations())) { - eventType.set(LINK_UPDATED); - return newLink; - } else { - return existingLink; - } - }); - return eventType.get() != null ? new LinkEvent(eventType.get(), link) : null; - } - - private Set<ProviderId> getAllProviders(LinkKey linkKey) { - return linkDescriptions.keySet() - .stream() - .filter(key -> key.key().equals(linkKey)) - .map(key -> key.providerId()) - .collect(Collectors.toSet()); - } - - private ProviderId getBaseProviderId(LinkKey linkKey) { - Set<ProviderId> allProviders = getAllProviders(linkKey); - if (allProviders.size() > 0) { - return allProviders.stream() - .filter(p -> !p.isAncillary()) - .findFirst() - .orElse(Iterables.getFirst(allProviders, null)); - } - return null; - } - - private Link composeLink(LinkKey linkKey) { - - ProviderId baseProviderId = checkNotNull(getBaseProviderId(linkKey)); - LinkDescription base = linkDescriptions.get(new Provided<>(linkKey, baseProviderId)); - - ConnectPoint src = base.src(); - ConnectPoint dst = base.dst(); - Type type = base.type(); - AtomicReference<DefaultAnnotations> annotations = new AtomicReference<>(DefaultAnnotations.builder().build()); - annotations.set(merge(annotations.get(), base.annotations())); - - getAllProviders(linkKey).stream() - .map(p -> new Provided<>(linkKey, p)) - .forEach(key -> { - annotations.set(merge(annotations.get(), - linkDescriptions.get(key).annotations())); - }); - - boolean isDurable = Objects.equals(annotations.get().value(AnnotationKeys.DURABLE), "true"); - return new DefaultLink(baseProviderId, src, dst, type, ACTIVE, isDurable, annotations.get()); - } - - // Updates, if necessary the specified link and returns the appropriate event. - // Guarded by linkDescs value (=locking each Link) - private LinkEvent updateLink(LinkKey key, Link oldLink, Link newLink) { - // Note: INDIRECT -> DIRECT transition only - // so that BDDP discovered Link will not overwrite LDDP Link - if (oldLink.state() != newLink.state() || - (oldLink.type() == INDIRECT && newLink.type() == DIRECT) || - !AnnotationsUtil.isEqual(oldLink.annotations(), newLink.annotations())) { - - links.put(key, newLink); - return new LinkEvent(LINK_UPDATED, newLink); - } - return null; - } - - @Override - public LinkEvent removeOrDownLink(ConnectPoint src, ConnectPoint dst) { - Link link = getLink(src, dst); - if (link == null) { - return null; - } - - if (link.isDurable()) { - // FIXME: this will not sync link state!!! - return link.state() == INACTIVE ? null : - updateLink(linkKey(link.src(), link.dst()), link, - new DefaultLink(link.providerId(), - link.src(), link.dst(), - link.type(), INACTIVE, - link.isDurable(), - link.annotations())); - } - return removeLink(src, dst); - } - - @Override - public LinkEvent removeLink(ConnectPoint src, ConnectPoint dst) { - final LinkKey linkKey = LinkKey.linkKey(src, dst); - ProviderId primaryProviderId = getBaseProviderId(linkKey); - // Stop if there is no base provider. - if (primaryProviderId == null) { - return null; - } - LinkDescription removedLinkDescription = - linkDescriptions.remove(new Provided<>(linkKey, primaryProviderId)); - if (removedLinkDescription != null) { - return purgeLinkCache(linkKey); - } - return null; - } - - private LinkEvent purgeLinkCache(LinkKey linkKey) { - Link removedLink = links.remove(linkKey); - if (removedLink != null) { - getAllProviders(linkKey).forEach(p -> linkDescriptions.remove(new Provided<>(linkKey, p))); - return new LinkEvent(LINK_REMOVED, removedLink); - } - return null; - } - - private Set<Link> filter(Collection<Link> links, Predicate<Link> predicate) { - return links.stream().filter(predicate).collect(Collectors.toSet()); - } - - private LinkEvent injectLink(Provided<LinkDescription> linkInjectRequest) { - log.trace("Received request to inject link {}", linkInjectRequest); - - ProviderId providerId = linkInjectRequest.providerId(); - LinkDescription linkDescription = linkInjectRequest.key(); - - final DeviceId deviceId = linkDescription.dst().deviceId(); - if (!deviceClockService.isTimestampAvailable(deviceId)) { - // workaround for ONOS-1208 - log.warn("Not ready to accept update. Dropping {}", linkInjectRequest); - return null; - } - return createOrUpdateLink(providerId, linkDescription); - } - - private class InternalLinkTracker implements EventuallyConsistentMapListener<Provided<LinkKey>, LinkDescription> { - @Override - public void event(EventuallyConsistentMapEvent<Provided<LinkKey>, LinkDescription> event) { - if (event.type() == PUT) { - notifyDelegate(refreshLinkCache(event.key().key())); - } else if (event.type() == REMOVE) { - notifyDelegate(purgeLinkCache(event.key().key())); - } - } - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/GossipLinkStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/GossipLinkStore.java deleted file mode 100644 index 47aa85c5..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/GossipLinkStore.java +++ /dev/null @@ -1,902 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.link.impl; - -import com.google.common.base.Function; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Multimaps; -import com.google.common.collect.SetMultimap; -import com.google.common.collect.Sets; -import org.apache.commons.lang3.RandomUtils; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.NodeId; -import org.onosproject.mastership.MastershipService; -import org.onosproject.net.AnnotationKeys; -import org.onosproject.net.AnnotationsUtil; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.DefaultLink; -import org.onosproject.net.DeviceId; -import org.onosproject.net.Link; -import org.onosproject.net.Link.Type; -import org.onosproject.net.LinkKey; -import org.onosproject.net.SparseAnnotations; -import org.onosproject.net.device.DeviceClockService; -import org.onosproject.net.link.DefaultLinkDescription; -import org.onosproject.net.link.LinkDescription; -import org.onosproject.net.link.LinkEvent; -import org.onosproject.net.link.LinkStore; -import org.onosproject.net.link.LinkStoreDelegate; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.Timestamp; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.cluster.messaging.ClusterMessage; -import org.onosproject.store.cluster.messaging.ClusterMessageHandler; -import org.onosproject.store.cluster.messaging.MessageSubject; -import org.onosproject.store.impl.Timestamped; -import org.onosproject.store.serializers.KryoSerializer; -import org.onosproject.store.serializers.custom.DistributedStoreSerializers; -import org.slf4j.Logger; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Predicates.notNull; -import static com.google.common.collect.Multimaps.synchronizedSetMultimap; -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; -import static org.onlab.util.Tools.groupedThreads; -import static org.onlab.util.Tools.minPriority; -import static org.onosproject.cluster.ControllerNodeToNodeId.toNodeId; -import static org.onosproject.net.DefaultAnnotations.merge; -import static org.onosproject.net.DefaultAnnotations.union; -import static org.onosproject.net.Link.State.ACTIVE; -import static org.onosproject.net.Link.State.INACTIVE; -import static org.onosproject.net.Link.Type.DIRECT; -import static org.onosproject.net.Link.Type.INDIRECT; -import static org.onosproject.net.LinkKey.linkKey; -import static org.onosproject.net.link.LinkEvent.Type.*; -import static org.onosproject.store.link.impl.GossipLinkStoreMessageSubjects.LINK_ANTI_ENTROPY_ADVERTISEMENT; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Manages inventory of infrastructure links in distributed data store - * that uses optimistic replication and gossip based techniques. - */ -@Component(immediate = true, enabled = false) -@Service -public class GossipLinkStore - extends AbstractStore<LinkEvent, LinkStoreDelegate> - implements LinkStore { - - // Timeout in milliseconds to process links on remote master node - private static final int REMOTE_MASTER_TIMEOUT = 1000; - - private final Logger log = getLogger(getClass()); - - // Link inventory - private final ConcurrentMap<LinkKey, Map<ProviderId, Timestamped<LinkDescription>>> linkDescs = - new ConcurrentHashMap<>(); - - // Link instance cache - private final ConcurrentMap<LinkKey, Link> links = new ConcurrentHashMap<>(); - - // Egress and ingress link sets - private final SetMultimap<DeviceId, LinkKey> srcLinks = createSynchronizedHashMultiMap(); - private final SetMultimap<DeviceId, LinkKey> dstLinks = createSynchronizedHashMultiMap(); - - // Remove links - private final Map<LinkKey, Timestamp> removedLinks = new ConcurrentHashMap<>(); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected DeviceClockService deviceClockService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterCommunicationService clusterCommunicator; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipService mastershipService; - - protected static final KryoSerializer SERIALIZER = new KryoSerializer() { - @Override - protected void setupKryoPool() { - serializerPool = KryoNamespace.newBuilder() - .register(DistributedStoreSerializers.STORE_COMMON) - .nextId(DistributedStoreSerializers.STORE_CUSTOM_BEGIN) - .register(InternalLinkEvent.class) - .register(InternalLinkRemovedEvent.class) - .register(LinkAntiEntropyAdvertisement.class) - .register(LinkFragmentId.class) - .register(LinkInjectedEvent.class) - .build(); - } - }; - - private ExecutorService executor; - - private ScheduledExecutorService backgroundExecutors; - - @Activate - public void activate() { - - executor = Executors.newCachedThreadPool(groupedThreads("onos/link", "fg-%d")); - - backgroundExecutors = - newSingleThreadScheduledExecutor(minPriority(groupedThreads("onos/link", "bg-%d"))); - - clusterCommunicator.addSubscriber( - GossipLinkStoreMessageSubjects.LINK_UPDATE, - new InternalLinkEventListener(), executor); - clusterCommunicator.addSubscriber( - GossipLinkStoreMessageSubjects.LINK_REMOVED, - new InternalLinkRemovedEventListener(), executor); - clusterCommunicator.addSubscriber( - GossipLinkStoreMessageSubjects.LINK_ANTI_ENTROPY_ADVERTISEMENT, - new InternalLinkAntiEntropyAdvertisementListener(), backgroundExecutors); - clusterCommunicator.addSubscriber( - GossipLinkStoreMessageSubjects.LINK_INJECTED, - new LinkInjectedEventListener(), executor); - - long initialDelaySec = 5; - long periodSec = 5; - // start anti-entropy thread - backgroundExecutors.scheduleAtFixedRate(new SendAdvertisementTask(), - initialDelaySec, periodSec, TimeUnit.SECONDS); - - log.info("Started"); - } - - @Deactivate - public void deactivate() { - - executor.shutdownNow(); - - backgroundExecutors.shutdownNow(); - try { - if (!backgroundExecutors.awaitTermination(5, TimeUnit.SECONDS)) { - log.error("Timeout during executor shutdown"); - } - } catch (InterruptedException e) { - log.error("Error during executor shutdown", e); - } - - linkDescs.clear(); - links.clear(); - srcLinks.clear(); - dstLinks.clear(); - log.info("Stopped"); - } - - @Override - public int getLinkCount() { - return links.size(); - } - - @Override - public Iterable<Link> getLinks() { - return Collections.unmodifiableCollection(links.values()); - } - - @Override - public Set<Link> getDeviceEgressLinks(DeviceId deviceId) { - // lock for iteration - synchronized (srcLinks) { - return FluentIterable.from(srcLinks.get(deviceId)) - .transform(lookupLink()) - .filter(notNull()) - .toSet(); - } - } - - @Override - public Set<Link> getDeviceIngressLinks(DeviceId deviceId) { - // lock for iteration - synchronized (dstLinks) { - return FluentIterable.from(dstLinks.get(deviceId)) - .transform(lookupLink()) - .filter(notNull()) - .toSet(); - } - } - - @Override - public Link getLink(ConnectPoint src, ConnectPoint dst) { - return links.get(linkKey(src, dst)); - } - - @Override - public Set<Link> getEgressLinks(ConnectPoint src) { - Set<Link> egress = new HashSet<>(); - // - // Change `srcLinks` to ConcurrentMap<DeviceId, (Concurrent)Set> - // to remove this synchronized block, if we hit performance issue. - // SetMultiMap#get returns wrapped collection to provide modifiable-view. - // And the wrapped collection is not concurrent access safe. - // - // Our use case here does not require returned collection to be modifiable, - // so the wrapped collection forces us to lock the whole multiset, - // for benefit we don't need. - // - // Same applies to `dstLinks` - synchronized (srcLinks) { - for (LinkKey linkKey : srcLinks.get(src.deviceId())) { - if (linkKey.src().equals(src)) { - Link link = links.get(linkKey); - if (link != null) { - egress.add(link); - } else { - log.debug("Egress link for {} was null, skipped", linkKey); - } - } - } - } - return egress; - } - - @Override - public Set<Link> getIngressLinks(ConnectPoint dst) { - Set<Link> ingress = new HashSet<>(); - synchronized (dstLinks) { - for (LinkKey linkKey : dstLinks.get(dst.deviceId())) { - if (linkKey.dst().equals(dst)) { - Link link = links.get(linkKey); - if (link != null) { - ingress.add(link); - } else { - log.debug("Ingress link for {} was null, skipped", linkKey); - } - } - } - } - return ingress; - } - - @Override - public LinkEvent createOrUpdateLink(ProviderId providerId, - LinkDescription linkDescription) { - - final DeviceId dstDeviceId = linkDescription.dst().deviceId(); - final NodeId localNode = clusterService.getLocalNode().id(); - final NodeId dstNode = mastershipService.getMasterFor(dstDeviceId); - - // Process link update only if we're the master of the destination node, - // otherwise signal the actual master. - LinkEvent linkEvent = null; - if (localNode.equals(dstNode)) { - - Timestamp newTimestamp = deviceClockService.getTimestamp(dstDeviceId); - - final Timestamped<LinkDescription> deltaDesc = new Timestamped<>(linkDescription, newTimestamp); - - LinkKey key = linkKey(linkDescription.src(), linkDescription.dst()); - final Timestamped<LinkDescription> mergedDesc; - Map<ProviderId, Timestamped<LinkDescription>> map = getOrCreateLinkDescriptions(key); - - synchronized (map) { - linkEvent = createOrUpdateLinkInternal(providerId, deltaDesc); - mergedDesc = map.get(providerId); - } - - if (linkEvent != null) { - log.debug("Notifying peers of a link update topology event from providerId: " - + "{} between src: {} and dst: {}", - providerId, linkDescription.src(), linkDescription.dst()); - notifyPeers(new InternalLinkEvent(providerId, mergedDesc)); - } - - } else { - // FIXME Temporary hack for NPE (ONOS-1171). - // Proper fix is to implement forwarding to master on ConfigProvider - // redo ONOS-490 - if (dstNode == null) { - // silently ignore - return null; - } - - - LinkInjectedEvent linkInjectedEvent = new LinkInjectedEvent(providerId, linkDescription); - - // TODO check unicast return value - clusterCommunicator.unicast(linkInjectedEvent, - GossipLinkStoreMessageSubjects.LINK_INJECTED, - SERIALIZER::encode, - dstNode); - } - - return linkEvent; - } - - @Override - public LinkEvent removeOrDownLink(ConnectPoint src, ConnectPoint dst) { - Link link = getLink(src, dst); - if (link == null) { - return null; - } - - if (link.isDurable()) { - // FIXME: this is not the right thing to call for the gossip store; will not sync link state!!! - return link.state() == INACTIVE ? null : - updateLink(linkKey(link.src(), link.dst()), link, - new DefaultLink(link.providerId(), - link.src(), link.dst(), - link.type(), INACTIVE, - link.isDurable(), - link.annotations())); - } - return removeLink(src, dst); - } - - private LinkEvent createOrUpdateLinkInternal( - ProviderId providerId, - Timestamped<LinkDescription> linkDescription) { - - final LinkKey key = linkKey(linkDescription.value().src(), - linkDescription.value().dst()); - Map<ProviderId, Timestamped<LinkDescription>> descs = getOrCreateLinkDescriptions(key); - - synchronized (descs) { - // if the link was previously removed, we should proceed if and - // only if this request is more recent. - Timestamp linkRemovedTimestamp = removedLinks.get(key); - if (linkRemovedTimestamp != null) { - if (linkDescription.isNewerThan(linkRemovedTimestamp)) { - removedLinks.remove(key); - } else { - log.trace("Link {} was already removed ignoring.", key); - return null; - } - } - - final Link oldLink = links.get(key); - // update description - createOrUpdateLinkDescription(descs, providerId, linkDescription); - final Link newLink = composeLink(descs); - if (oldLink == null) { - return createLink(key, newLink); - } - return updateLink(key, oldLink, newLink); - } - } - - // Guarded by linkDescs value (=locking each Link) - private Timestamped<LinkDescription> createOrUpdateLinkDescription( - Map<ProviderId, Timestamped<LinkDescription>> descs, - ProviderId providerId, - Timestamped<LinkDescription> linkDescription) { - - // merge existing annotations - Timestamped<LinkDescription> existingLinkDescription = descs.get(providerId); - if (existingLinkDescription != null && existingLinkDescription.isNewer(linkDescription)) { - log.trace("local info is more up-to-date, ignoring {}.", linkDescription); - return null; - } - Timestamped<LinkDescription> newLinkDescription = linkDescription; - if (existingLinkDescription != null) { - // we only allow transition from INDIRECT -> DIRECT - final Type newType; - if (existingLinkDescription.value().type() == DIRECT) { - newType = DIRECT; - } else { - newType = linkDescription.value().type(); - } - SparseAnnotations merged = union(existingLinkDescription.value().annotations(), - linkDescription.value().annotations()); - newLinkDescription = new Timestamped<>( - new DefaultLinkDescription( - linkDescription.value().src(), - linkDescription.value().dst(), - newType, merged), - linkDescription.timestamp()); - } - return descs.put(providerId, newLinkDescription); - } - - // Creates and stores the link and returns the appropriate event. - // Guarded by linkDescs value (=locking each Link) - private LinkEvent createLink(LinkKey key, Link newLink) { - links.put(key, newLink); - srcLinks.put(newLink.src().deviceId(), key); - dstLinks.put(newLink.dst().deviceId(), key); - return new LinkEvent(LINK_ADDED, newLink); - } - - // Updates, if necessary the specified link and returns the appropriate event. - // Guarded by linkDescs value (=locking each Link) - private LinkEvent updateLink(LinkKey key, Link oldLink, Link newLink) { - // Note: INDIRECT -> DIRECT transition only - // so that BDDP discovered Link will not overwrite LDDP Link - if (oldLink.state() != newLink.state() || - (oldLink.type() == INDIRECT && newLink.type() == DIRECT) || - !AnnotationsUtil.isEqual(oldLink.annotations(), newLink.annotations())) { - - links.put(key, newLink); - // strictly speaking following can be omitted - srcLinks.put(oldLink.src().deviceId(), key); - dstLinks.put(oldLink.dst().deviceId(), key); - return new LinkEvent(LINK_UPDATED, newLink); - } - return null; - } - - @Override - public LinkEvent removeLink(ConnectPoint src, ConnectPoint dst) { - final LinkKey key = linkKey(src, dst); - - DeviceId dstDeviceId = dst.deviceId(); - Timestamp timestamp = null; - try { - timestamp = deviceClockService.getTimestamp(dstDeviceId); - } catch (IllegalStateException e) { - log.debug("Failed to remove link {}, was not the master", key); - // there are times when this is called before mastership - // handoff correctly completes. - return null; - } - - LinkEvent event = removeLinkInternal(key, timestamp); - - if (event != null) { - log.debug("Notifying peers of a link removed topology event for a link " - + "between src: {} and dst: {}", src, dst); - notifyPeers(new InternalLinkRemovedEvent(key, timestamp)); - } - return event; - } - - private static Timestamped<LinkDescription> getPrimaryDescription( - Map<ProviderId, Timestamped<LinkDescription>> linkDescriptions) { - - synchronized (linkDescriptions) { - for (Entry<ProviderId, Timestamped<LinkDescription>> - e : linkDescriptions.entrySet()) { - - if (!e.getKey().isAncillary()) { - return e.getValue(); - } - } - } - return null; - } - - - // TODO: consider slicing out as Timestamp utils - /** - * Checks is timestamp is more recent than timestamped object. - * - * @param timestamp to check if this is more recent then other - * @param timestamped object to be tested against - * @return true if {@code timestamp} is more recent than {@code timestamped} - * or {@code timestamped is null} - */ - private static boolean isMoreRecent(Timestamp timestamp, Timestamped<?> timestamped) { - checkNotNull(timestamp); - if (timestamped == null) { - return true; - } - return timestamp.compareTo(timestamped.timestamp()) > 0; - } - - private LinkEvent removeLinkInternal(LinkKey key, Timestamp timestamp) { - Map<ProviderId, Timestamped<LinkDescription>> linkDescriptions - = getOrCreateLinkDescriptions(key); - - synchronized (linkDescriptions) { - if (linkDescriptions.isEmpty()) { - // never seen such link before. keeping timestamp for record - removedLinks.put(key, timestamp); - return null; - } - // accept removal request if given timestamp is newer than - // the latest Timestamp from Primary provider - Timestamped<LinkDescription> prim = getPrimaryDescription(linkDescriptions); - if (!isMoreRecent(timestamp, prim)) { - // outdated remove request, ignore - return null; - } - removedLinks.put(key, timestamp); - Link link = links.remove(key); - linkDescriptions.clear(); - if (link != null) { - srcLinks.remove(link.src().deviceId(), key); - dstLinks.remove(link.dst().deviceId(), key); - return new LinkEvent(LINK_REMOVED, link); - } - return null; - } - } - - /** - * Creates concurrent readable, synchronized HashMultimap. - * - * @return SetMultimap - */ - private static <K, V> SetMultimap<K, V> createSynchronizedHashMultiMap() { - return synchronizedSetMultimap( - Multimaps.newSetMultimap(new ConcurrentHashMap<>(), - () -> Sets.newConcurrentHashSet())); - } - - /** - * @return primary ProviderID, or randomly chosen one if none exists - */ - private static ProviderId pickBaseProviderId( - Map<ProviderId, Timestamped<LinkDescription>> linkDescriptions) { - - ProviderId fallBackPrimary = null; - for (Entry<ProviderId, Timestamped<LinkDescription>> e : linkDescriptions.entrySet()) { - if (!e.getKey().isAncillary()) { - // found primary - return e.getKey(); - } else if (fallBackPrimary == null) { - // pick randomly as a fallback in case there is no primary - fallBackPrimary = e.getKey(); - } - } - return fallBackPrimary; - } - - // Guarded by linkDescs value (=locking each Link) - private Link composeLink(Map<ProviderId, Timestamped<LinkDescription>> descs) { - ProviderId baseProviderId = pickBaseProviderId(descs); - Timestamped<LinkDescription> base = descs.get(baseProviderId); - - ConnectPoint src = base.value().src(); - ConnectPoint dst = base.value().dst(); - Type type = base.value().type(); - DefaultAnnotations annotations = DefaultAnnotations.builder().build(); - annotations = merge(annotations, base.value().annotations()); - - for (Entry<ProviderId, Timestamped<LinkDescription>> e : descs.entrySet()) { - if (baseProviderId.equals(e.getKey())) { - continue; - } - - // Note: In the long run we should keep track of Description timestamp - // and only merge conflicting keys when timestamp is newer - // Currently assuming there will never be a key conflict between - // providers - - // annotation merging. not so efficient, should revisit later - annotations = merge(annotations, e.getValue().value().annotations()); - } - - boolean isDurable = Objects.equals(annotations.value(AnnotationKeys.DURABLE), "true"); - return new DefaultLink(baseProviderId, src, dst, type, ACTIVE, isDurable, annotations); - } - - private Map<ProviderId, Timestamped<LinkDescription>> getOrCreateLinkDescriptions(LinkKey key) { - Map<ProviderId, Timestamped<LinkDescription>> r; - r = linkDescs.get(key); - if (r != null) { - return r; - } - r = new HashMap<>(); - final Map<ProviderId, Timestamped<LinkDescription>> concurrentlyAdded; - concurrentlyAdded = linkDescs.putIfAbsent(key, r); - if (concurrentlyAdded != null) { - return concurrentlyAdded; - } else { - return r; - } - } - - private final Function<LinkKey, Link> lookupLink = new LookupLink(); - - /** - * Returns a Function to lookup Link instance using LinkKey from cache. - * - * @return lookup link function - */ - private Function<LinkKey, Link> lookupLink() { - return lookupLink; - } - - private final class LookupLink implements Function<LinkKey, Link> { - @Override - public Link apply(LinkKey input) { - if (input == null) { - return null; - } else { - return links.get(input); - } - } - } - - private void notifyDelegateIfNotNull(LinkEvent event) { - if (event != null) { - notifyDelegate(event); - } - } - - private void broadcastMessage(MessageSubject subject, Object event) { - clusterCommunicator.broadcast(event, subject, SERIALIZER::encode); - } - - private void unicastMessage(NodeId recipient, MessageSubject subject, Object event) throws IOException { - clusterCommunicator.unicast(event, subject, SERIALIZER::encode, recipient); - } - - private void notifyPeers(InternalLinkEvent event) { - broadcastMessage(GossipLinkStoreMessageSubjects.LINK_UPDATE, event); - } - - private void notifyPeers(InternalLinkRemovedEvent event) { - broadcastMessage(GossipLinkStoreMessageSubjects.LINK_REMOVED, event); - } - - // notify peer, silently ignoring error - private void notifyPeer(NodeId peer, InternalLinkEvent event) { - try { - unicastMessage(peer, GossipLinkStoreMessageSubjects.LINK_UPDATE, event); - } catch (IOException e) { - log.debug("Failed to notify peer {} with message {}", peer, event); - } - } - - // notify peer, silently ignoring error - private void notifyPeer(NodeId peer, InternalLinkRemovedEvent event) { - try { - unicastMessage(peer, GossipLinkStoreMessageSubjects.LINK_REMOVED, event); - } catch (IOException e) { - log.debug("Failed to notify peer {} with message {}", peer, event); - } - } - - private final class SendAdvertisementTask implements Runnable { - - @Override - public void run() { - if (Thread.currentThread().isInterrupted()) { - log.debug("Interrupted, quitting"); - return; - } - - try { - final NodeId self = clusterService.getLocalNode().id(); - Set<ControllerNode> nodes = clusterService.getNodes(); - - ImmutableList<NodeId> nodeIds = FluentIterable.from(nodes) - .transform(toNodeId()) - .toList(); - - if (nodeIds.size() == 1 && nodeIds.get(0).equals(self)) { - log.trace("No other peers in the cluster."); - return; - } - - NodeId peer; - do { - int idx = RandomUtils.nextInt(0, nodeIds.size()); - peer = nodeIds.get(idx); - } while (peer.equals(self)); - - LinkAntiEntropyAdvertisement ad = createAdvertisement(); - - if (Thread.currentThread().isInterrupted()) { - log.debug("Interrupted, quitting"); - return; - } - - try { - unicastMessage(peer, LINK_ANTI_ENTROPY_ADVERTISEMENT, ad); - } catch (IOException e) { - log.debug("Failed to send anti-entropy advertisement to {}", peer); - return; - } - } catch (Exception e) { - // catch all Exception to avoid Scheduled task being suppressed. - log.error("Exception thrown while sending advertisement", e); - } - } - } - - private LinkAntiEntropyAdvertisement createAdvertisement() { - final NodeId self = clusterService.getLocalNode().id(); - - Map<LinkFragmentId, Timestamp> linkTimestamps = new HashMap<>(linkDescs.size()); - Map<LinkKey, Timestamp> linkTombstones = new HashMap<>(removedLinks.size()); - - linkDescs.forEach((linkKey, linkDesc) -> { - synchronized (linkDesc) { - for (Map.Entry<ProviderId, Timestamped<LinkDescription>> e : linkDesc.entrySet()) { - linkTimestamps.put(new LinkFragmentId(linkKey, e.getKey()), e.getValue().timestamp()); - } - } - }); - - linkTombstones.putAll(removedLinks); - - return new LinkAntiEntropyAdvertisement(self, linkTimestamps, linkTombstones); - } - - private void handleAntiEntropyAdvertisement(LinkAntiEntropyAdvertisement ad) { - - final NodeId sender = ad.sender(); - boolean localOutdated = false; - - for (Entry<LinkKey, Map<ProviderId, Timestamped<LinkDescription>>> - l : linkDescs.entrySet()) { - - final LinkKey key = l.getKey(); - final Map<ProviderId, Timestamped<LinkDescription>> link = l.getValue(); - synchronized (link) { - Timestamp localLatest = removedLinks.get(key); - - for (Entry<ProviderId, Timestamped<LinkDescription>> p : link.entrySet()) { - final ProviderId providerId = p.getKey(); - final Timestamped<LinkDescription> pDesc = p.getValue(); - - final LinkFragmentId fragId = new LinkFragmentId(key, providerId); - // remote - Timestamp remoteTimestamp = ad.linkTimestamps().get(fragId); - if (remoteTimestamp == null) { - remoteTimestamp = ad.linkTombstones().get(key); - } - if (remoteTimestamp == null || - pDesc.isNewerThan(remoteTimestamp)) { - // I have more recent link description. update peer. - notifyPeer(sender, new InternalLinkEvent(providerId, pDesc)); - } else { - final Timestamp remoteLive = ad.linkTimestamps().get(fragId); - if (remoteLive != null && - remoteLive.compareTo(pDesc.timestamp()) > 0) { - // I have something outdated - localOutdated = true; - } - } - - // search local latest along the way - if (localLatest == null || - pDesc.isNewerThan(localLatest)) { - localLatest = pDesc.timestamp(); - } - } - // Tests if remote remove is more recent then local latest. - final Timestamp remoteRemove = ad.linkTombstones().get(key); - if (remoteRemove != null) { - if (localLatest != null && - localLatest.compareTo(remoteRemove) < 0) { - // remote remove is more recent - notifyDelegateIfNotNull(removeLinkInternal(key, remoteRemove)); - } - } - } - } - - // populate remove info if not known locally - for (Entry<LinkKey, Timestamp> remoteRm : ad.linkTombstones().entrySet()) { - final LinkKey key = remoteRm.getKey(); - final Timestamp remoteRemove = remoteRm.getValue(); - // relying on removeLinkInternal to ignore stale info - notifyDelegateIfNotNull(removeLinkInternal(key, remoteRemove)); - } - - if (localOutdated) { - // send back advertisement to speed up convergence - try { - unicastMessage(sender, LINK_ANTI_ENTROPY_ADVERTISEMENT, - createAdvertisement()); - } catch (IOException e) { - log.debug("Failed to send back active advertisement"); - } - } - } - - private final class InternalLinkEventListener - implements ClusterMessageHandler { - @Override - public void handle(ClusterMessage message) { - - log.trace("Received link event from peer: {}", message.sender()); - InternalLinkEvent event = SERIALIZER.decode(message.payload()); - - ProviderId providerId = event.providerId(); - Timestamped<LinkDescription> linkDescription = event.linkDescription(); - - try { - notifyDelegateIfNotNull(createOrUpdateLinkInternal(providerId, linkDescription)); - } catch (Exception e) { - log.warn("Exception thrown handling link event", e); - } - } - } - - private final class InternalLinkRemovedEventListener - implements ClusterMessageHandler { - @Override - public void handle(ClusterMessage message) { - - log.trace("Received link removed event from peer: {}", message.sender()); - InternalLinkRemovedEvent event = SERIALIZER.decode(message.payload()); - - LinkKey linkKey = event.linkKey(); - Timestamp timestamp = event.timestamp(); - - try { - notifyDelegateIfNotNull(removeLinkInternal(linkKey, timestamp)); - } catch (Exception e) { - log.warn("Exception thrown handling link removed", e); - } - } - } - - private final class InternalLinkAntiEntropyAdvertisementListener - implements ClusterMessageHandler { - - @Override - public void handle(ClusterMessage message) { - log.trace("Received Link Anti-Entropy advertisement from peer: {}", message.sender()); - LinkAntiEntropyAdvertisement advertisement = SERIALIZER.decode(message.payload()); - try { - handleAntiEntropyAdvertisement(advertisement); - } catch (Exception e) { - log.warn("Exception thrown while handling Link advertisements", e); - throw e; - } - } - } - - private final class LinkInjectedEventListener - implements ClusterMessageHandler { - @Override - public void handle(ClusterMessage message) { - - log.trace("Received injected link event from peer: {}", message.sender()); - LinkInjectedEvent linkInjectedEvent = SERIALIZER.decode(message.payload()); - - ProviderId providerId = linkInjectedEvent.providerId(); - LinkDescription linkDescription = linkInjectedEvent.linkDescription(); - - final DeviceId deviceId = linkDescription.dst().deviceId(); - if (!deviceClockService.isTimestampAvailable(deviceId)) { - // workaround for ONOS-1208 - log.warn("Not ready to accept update. Dropping {}", linkDescription); - return; - } - - try { - createOrUpdateLink(providerId, linkDescription); - } catch (Exception e) { - log.warn("Exception thrown while handling link injected event", e); - } - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/GossipLinkStoreMessageSubjects.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/GossipLinkStoreMessageSubjects.java deleted file mode 100644 index e0e1dda3..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/GossipLinkStoreMessageSubjects.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.link.impl; - - import org.onosproject.store.cluster.messaging.MessageSubject; - -/** - * MessageSubjects used by GossipLinkStore peer-peer communication. - */ -public final class GossipLinkStoreMessageSubjects { - - private GossipLinkStoreMessageSubjects() {} - - public static final MessageSubject LINK_UPDATE = - new MessageSubject("peer-link-update"); - public static final MessageSubject LINK_REMOVED = - new MessageSubject("peer-link-removed"); - public static final MessageSubject LINK_ANTI_ENTROPY_ADVERTISEMENT = - new MessageSubject("link-enti-entropy-advertisement"); - public static final MessageSubject LINK_INJECTED = - new MessageSubject("peer-link-injected"); -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/InternalLinkEvent.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/InternalLinkEvent.java deleted file mode 100644 index 2319f274..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/InternalLinkEvent.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.link.impl; - -import com.google.common.base.MoreObjects; - -import org.onosproject.net.link.LinkDescription; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.impl.Timestamped; - -/** - * Information published by GossipDeviceStore to notify peers of a device - * change event. - */ -public class InternalLinkEvent { - - private final ProviderId providerId; - private final Timestamped<LinkDescription> linkDescription; - - protected InternalLinkEvent( - ProviderId providerId, - Timestamped<LinkDescription> linkDescription) { - this.providerId = providerId; - this.linkDescription = linkDescription; - } - - public ProviderId providerId() { - return providerId; - } - - public Timestamped<LinkDescription> linkDescription() { - return linkDescription; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("providerId", providerId) - .add("linkDescription", linkDescription) - .toString(); - } - - // for serializer - protected InternalLinkEvent() { - this.providerId = null; - this.linkDescription = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/InternalLinkRemovedEvent.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/InternalLinkRemovedEvent.java deleted file mode 100644 index 9d867203..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/InternalLinkRemovedEvent.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.link.impl; - -import org.onosproject.net.LinkKey; -import org.onosproject.store.Timestamp; - -import com.google.common.base.MoreObjects; - -/** - * Information published by GossipLinkStore to notify peers of a link - * being removed. - */ -public class InternalLinkRemovedEvent { - - private final LinkKey linkKey; - private final Timestamp timestamp; - - /** - * Creates a InternalLinkRemovedEvent. - * @param linkKey identifier of the removed link. - * @param timestamp timestamp of when the link was removed. - */ - public InternalLinkRemovedEvent(LinkKey linkKey, Timestamp timestamp) { - this.linkKey = linkKey; - this.timestamp = timestamp; - } - - public LinkKey linkKey() { - return linkKey; - } - - public Timestamp timestamp() { - return timestamp; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("linkKey", linkKey) - .add("timestamp", timestamp) - .toString(); - } - - // for serializer - @SuppressWarnings("unused") - private InternalLinkRemovedEvent() { - linkKey = null; - timestamp = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/LinkAntiEntropyAdvertisement.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/LinkAntiEntropyAdvertisement.java deleted file mode 100644 index 73c1042e..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/LinkAntiEntropyAdvertisement.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.link.impl; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.Map; - -import org.onosproject.cluster.NodeId; -import org.onosproject.net.LinkKey; -import org.onosproject.store.Timestamp; - -/** - * Link AE Advertisement message. - */ -public class LinkAntiEntropyAdvertisement { - - private final NodeId sender; - private final Map<LinkFragmentId, Timestamp> linkTimestamps; - private final Map<LinkKey, Timestamp> linkTombstones; - - - public LinkAntiEntropyAdvertisement(NodeId sender, - Map<LinkFragmentId, Timestamp> linkTimestamps, - Map<LinkKey, Timestamp> linkTombstones) { - this.sender = checkNotNull(sender); - this.linkTimestamps = checkNotNull(linkTimestamps); - this.linkTombstones = checkNotNull(linkTombstones); - } - - public NodeId sender() { - return sender; - } - - public Map<LinkFragmentId, Timestamp> linkTimestamps() { - return linkTimestamps; - } - - public Map<LinkKey, Timestamp> linkTombstones() { - return linkTombstones; - } - - // For serializer - @SuppressWarnings("unused") - private LinkAntiEntropyAdvertisement() { - this.sender = null; - this.linkTimestamps = null; - this.linkTombstones = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/LinkFragmentId.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/LinkFragmentId.java deleted file mode 100644 index af7ce4fc..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/LinkFragmentId.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.link.impl; - -import java.util.Objects; - -import org.onosproject.net.LinkKey; -import org.onosproject.net.provider.ProviderId; - -import com.google.common.base.MoreObjects; - -/** - * Identifier for LinkDescription from a Provider. - */ -public final class LinkFragmentId { - public final ProviderId providerId; - public final LinkKey linkKey; - - public LinkFragmentId(LinkKey linkKey, ProviderId providerId) { - this.providerId = providerId; - this.linkKey = linkKey; - } - - public LinkKey linkKey() { - return linkKey; - } - - public ProviderId providerId() { - return providerId; - } - - @Override - public int hashCode() { - return Objects.hash(providerId, linkKey); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof LinkFragmentId)) { - return false; - } - LinkFragmentId that = (LinkFragmentId) obj; - return Objects.equals(this.linkKey, that.linkKey) && - Objects.equals(this.providerId, that.providerId); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("providerId", providerId) - .add("linkKey", linkKey) - .toString(); - } - - // for serializer - @SuppressWarnings("unused") - private LinkFragmentId() { - this.providerId = null; - this.linkKey = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/LinkInjectedEvent.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/LinkInjectedEvent.java deleted file mode 100644 index b353208d..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/LinkInjectedEvent.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.link.impl; - -import com.google.common.base.MoreObjects; -import org.onosproject.net.link.LinkDescription; -import org.onosproject.net.provider.ProviderId; - -public class LinkInjectedEvent { - - ProviderId providerId; - LinkDescription linkDescription; - - public LinkInjectedEvent(ProviderId providerId, LinkDescription linkDescription) { - this.providerId = providerId; - this.linkDescription = linkDescription; - } - - public ProviderId providerId() { - return providerId; - } - - public LinkDescription linkDescription() { - return linkDescription; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("providerId", providerId) - .add("linkDescription", linkDescription) - .toString(); - } - - // for serializer - protected LinkInjectedEvent() { - this.providerId = null; - this.linkDescription = null; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/Provided.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/Provided.java deleted file mode 100644 index b5b9e644..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/Provided.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.link.impl; - -import java.util.Objects; - -import org.onosproject.net.provider.ProviderId; - -import com.google.common.base.MoreObjects; - -/** - * Encapsulation of a provider supplied key. - * - * @param <K> key - */ -public class Provided<K> { - private final K key; - private final ProviderId providerId; - - public Provided(K key, ProviderId providerId) { - this.key = key; - this.providerId = providerId; - } - - public ProviderId providerId() { - return providerId; - } - - public K key() { - return key; - } - - @Override - public int hashCode() { - return Objects.hash(key, providerId); - } - - @Override - public boolean equals(Object other) { - if (other instanceof Provided) { - Provided<K> that = (Provided) other; - return Objects.equals(key, that.key) && - Objects.equals(providerId, that.providerId); - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("key", key) - .add("providerId", providerId) - .toString(); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/package-info.java deleted file mode 100644 index 97f2ccae..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/link/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of distributed link store using p2p synchronization protocol. - */ -package org.onosproject.store.link.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/mastership/impl/ConsistentDeviceMastershipStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/mastership/impl/ConsistentDeviceMastershipStore.java deleted file mode 100644 index c6fc6933..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/mastership/impl/ConsistentDeviceMastershipStore.java +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.mastership.impl; - -import static org.onlab.util.Tools.groupedThreads; -import static org.onlab.util.Tools.futureGetOrElse; -import static org.onosproject.mastership.MastershipEvent.Type.BACKUPS_CHANGED; -import static org.onosproject.mastership.MastershipEvent.Type.MASTER_CHANGED; -import static org.slf4j.LoggerFactory.getLogger; -import static com.google.common.base.Preconditions.checkArgument; - -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.Leadership; -import org.onosproject.cluster.LeadershipEvent; -import org.onosproject.cluster.LeadershipEventListener; -import org.onosproject.cluster.LeadershipService; -import org.onosproject.cluster.NodeId; -import org.onosproject.cluster.RoleInfo; -import org.onosproject.mastership.MastershipEvent; -import org.onosproject.mastership.MastershipStore; -import org.onosproject.mastership.MastershipStoreDelegate; -import org.onosproject.mastership.MastershipTerm; -import org.onosproject.net.DeviceId; -import org.onosproject.net.MastershipRole; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.cluster.messaging.MessageSubject; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.serializers.KryoSerializer; -import org.onosproject.store.serializers.StoreSerializer; -import org.slf4j.Logger; - -import com.google.common.base.Objects; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -/** - * Implementation of the MastershipStore on top of Leadership Service. - */ -@Component(immediate = true, enabled = true) -@Service -public class ConsistentDeviceMastershipStore - extends AbstractStore<MastershipEvent, MastershipStoreDelegate> - implements MastershipStore { - - private final Logger log = getLogger(getClass()); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected LeadershipService leadershipService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterCommunicationService clusterCommunicator; - - private NodeId localNodeId; - private final Set<DeviceId> connectedDevices = Sets.newHashSet(); - - private static final MessageSubject ROLE_RELINQUISH_SUBJECT = - new MessageSubject("mastership-store-device-role-relinquish"); - private static final MessageSubject TRANSITION_FROM_MASTER_TO_STANDBY_SUBJECT = - new MessageSubject("mastership-store-device-mastership-relinquish"); - - private static final Pattern DEVICE_MASTERSHIP_TOPIC_PATTERN = - Pattern.compile("device:(.*)"); - - private ExecutorService messageHandlingExecutor; - private ScheduledExecutorService transferExecutor; - private final LeadershipEventListener leadershipEventListener = - new InternalDeviceMastershipEventListener(); - - private static final String NODE_ID_NULL = "Node ID cannot be null"; - private static final String DEVICE_ID_NULL = "Device ID cannot be null"; - private static final int WAIT_BEFORE_MASTERSHIP_HANDOFF_MILLIS = 3000; - - public static final StoreSerializer SERIALIZER = new KryoSerializer() { - @Override - protected void setupKryoPool() { - serializerPool = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .register(MastershipRole.class) - .register(MastershipEvent.class) - .register(MastershipEvent.Type.class) - .build(); - } - }; - - @Activate - public void activate() { - messageHandlingExecutor = - Executors.newSingleThreadExecutor( - groupedThreads("onos/store/device/mastership", "message-handler")); - transferExecutor = - Executors.newSingleThreadScheduledExecutor( - groupedThreads("onos/store/device/mastership", "mastership-transfer-executor")); - clusterCommunicator.addSubscriber(ROLE_RELINQUISH_SUBJECT, - SERIALIZER::decode, - this::relinquishLocalRole, - SERIALIZER::encode, - messageHandlingExecutor); - clusterCommunicator.addSubscriber(TRANSITION_FROM_MASTER_TO_STANDBY_SUBJECT, - SERIALIZER::decode, - this::transitionFromMasterToStandby, - SERIALIZER::encode, - messageHandlingExecutor); - localNodeId = clusterService.getLocalNode().id(); - leadershipService.addListener(leadershipEventListener); - - log.info("Started"); - } - - @Deactivate - public void deactivate() { - clusterCommunicator.removeSubscriber(ROLE_RELINQUISH_SUBJECT); - clusterCommunicator.removeSubscriber(TRANSITION_FROM_MASTER_TO_STANDBY_SUBJECT); - messageHandlingExecutor.shutdown(); - transferExecutor.shutdown(); - leadershipService.removeListener(leadershipEventListener); - - log.info("Stopped"); - } - - @Override - public CompletableFuture<MastershipRole> requestRole(DeviceId deviceId) { - checkArgument(deviceId != null, DEVICE_ID_NULL); - - String leadershipTopic = createDeviceMastershipTopic(deviceId); - if (connectedDevices.add(deviceId)) { - return leadershipService.runForLeadership(leadershipTopic) - .thenApply(leadership -> { - return Objects.equal(localNodeId, leadership.leader()) - ? MastershipRole.MASTER : MastershipRole.STANDBY; - }); - } else { - NodeId leader = leadershipService.getLeader(leadershipTopic); - if (Objects.equal(localNodeId, leader)) { - return CompletableFuture.completedFuture(MastershipRole.MASTER); - } else { - return CompletableFuture.completedFuture(MastershipRole.STANDBY); - } - } - } - - @Override - public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) { - checkArgument(nodeId != null, NODE_ID_NULL); - checkArgument(deviceId != null, DEVICE_ID_NULL); - - String leadershipTopic = createDeviceMastershipTopic(deviceId); - NodeId leader = leadershipService.getLeader(leadershipTopic); - if (Objects.equal(nodeId, leader)) { - return MastershipRole.MASTER; - } - return leadershipService.getCandidates(leadershipTopic).contains(nodeId) ? - MastershipRole.STANDBY : MastershipRole.NONE; - } - - @Override - public NodeId getMaster(DeviceId deviceId) { - checkArgument(deviceId != null, DEVICE_ID_NULL); - - String leadershipTopic = createDeviceMastershipTopic(deviceId); - return leadershipService.getLeader(leadershipTopic); - } - - @Override - public RoleInfo getNodes(DeviceId deviceId) { - checkArgument(deviceId != null, DEVICE_ID_NULL); - - Map<NodeId, MastershipRole> roles = Maps.newHashMap(); - clusterService - .getNodes() - .forEach((node) -> roles.put(node.id(), getRole(node.id(), deviceId))); - - NodeId master = null; - final List<NodeId> standbys = Lists.newLinkedList(); - - List<NodeId> candidates = leadershipService.getCandidates(createDeviceMastershipTopic(deviceId)); - - for (Map.Entry<NodeId, MastershipRole> entry : roles.entrySet()) { - if (entry.getValue() == MastershipRole.MASTER) { - master = entry.getKey(); - } else if (entry.getValue() == MastershipRole.STANDBY) { - standbys.add(entry.getKey()); - } - } - - List<NodeId> sortedStandbyList = candidates.stream().filter(standbys::contains).collect(Collectors.toList()); - - return new RoleInfo(master, sortedStandbyList); - } - - @Override - public Set<DeviceId> getDevices(NodeId nodeId) { - checkArgument(nodeId != null, NODE_ID_NULL); - - return leadershipService - .ownedTopics(nodeId) - .stream() - .filter(this::isDeviceMastershipTopic) - .map(this::extractDeviceIdFromTopic) - .collect(Collectors.toSet()); - } - - @Override - public CompletableFuture<MastershipEvent> setMaster(NodeId nodeId, DeviceId deviceId) { - checkArgument(nodeId != null, NODE_ID_NULL); - checkArgument(deviceId != null, DEVICE_ID_NULL); - - NodeId currentMaster = getMaster(deviceId); - if (nodeId.equals(currentMaster)) { - return CompletableFuture.completedFuture(null); - } else { - String leadershipTopic = createDeviceMastershipTopic(deviceId); - List<NodeId> candidates = leadershipService.getCandidates(leadershipTopic); - if (candidates.isEmpty()) { - return CompletableFuture.completedFuture(null); - } - if (leadershipService.makeTopCandidate(leadershipTopic, nodeId)) { - CompletableFuture<MastershipEvent> result = new CompletableFuture<>(); - // There is brief wait before we step down from mastership. - // This is to ensure any work that happens when standby preference - // order changes can complete. For example: flow entries need to be backed - // to the new top standby (ONOS-1883) - // FIXME: This potentially introduces a race-condition. - // Right now role changes are only forced via CLI. - transferExecutor.schedule(() -> { - result.complete(transitionFromMasterToStandby(deviceId)); - }, WAIT_BEFORE_MASTERSHIP_HANDOFF_MILLIS, TimeUnit.MILLISECONDS); - return result; - } else { - log.warn("Failed to promote {} to mastership for {}", nodeId, deviceId); - } - } - return CompletableFuture.completedFuture(null); - } - - @Override - public MastershipTerm getTermFor(DeviceId deviceId) { - checkArgument(deviceId != null, DEVICE_ID_NULL); - - String leadershipTopic = createDeviceMastershipTopic(deviceId); - Leadership leadership = leadershipService.getLeadership(leadershipTopic); - return leadership != null ? MastershipTerm.of(leadership.leader(), leadership.epoch()) : null; - } - - @Override - public CompletableFuture<MastershipEvent> setStandby(NodeId nodeId, DeviceId deviceId) { - checkArgument(nodeId != null, NODE_ID_NULL); - checkArgument(deviceId != null, DEVICE_ID_NULL); - - NodeId currentMaster = getMaster(deviceId); - if (!nodeId.equals(currentMaster)) { - return CompletableFuture.completedFuture(null); - } - - String leadershipTopic = createDeviceMastershipTopic(deviceId); - List<NodeId> candidates = leadershipService.getCandidates(leadershipTopic); - - NodeId newMaster = candidates.stream() - .filter(candidate -> !Objects.equal(nodeId, candidate)) - .findFirst() - .orElse(null); - log.info("Transitioning to role {} for {}. Next master: {}", - newMaster != null ? MastershipRole.STANDBY : MastershipRole.NONE, deviceId, newMaster); - - if (newMaster != null) { - return setMaster(newMaster, deviceId); - } - return relinquishRole(nodeId, deviceId); - } - - @Override - public CompletableFuture<MastershipEvent> relinquishRole(NodeId nodeId, DeviceId deviceId) { - checkArgument(nodeId != null, NODE_ID_NULL); - checkArgument(deviceId != null, DEVICE_ID_NULL); - - if (nodeId.equals(localNodeId)) { - return relinquishLocalRole(deviceId); - } - - log.debug("Forwarding request to relinquish " - + "role for device {} to {}", deviceId, nodeId); - return clusterCommunicator.sendAndReceive( - deviceId, - ROLE_RELINQUISH_SUBJECT, - SERIALIZER::encode, - SERIALIZER::decode, - nodeId); - } - - private CompletableFuture<MastershipEvent> relinquishLocalRole(DeviceId deviceId) { - checkArgument(deviceId != null, DEVICE_ID_NULL); - - // Check if this node is can be managed by this node. - if (!connectedDevices.contains(deviceId)) { - return CompletableFuture.completedFuture(null); - } - - String leadershipTopic = createDeviceMastershipTopic(deviceId); - NodeId currentLeader = leadershipService.getLeader(leadershipTopic); - - MastershipEvent.Type eventType = Objects.equal(currentLeader, localNodeId) - ? MastershipEvent.Type.MASTER_CHANGED - : MastershipEvent.Type.BACKUPS_CHANGED; - - connectedDevices.remove(deviceId); - return leadershipService.withdraw(leadershipTopic) - .thenApply(v -> new MastershipEvent(eventType, deviceId, getNodes(deviceId))); - } - - private MastershipEvent transitionFromMasterToStandby(DeviceId deviceId) { - checkArgument(deviceId != null, DEVICE_ID_NULL); - - NodeId currentMaster = getMaster(deviceId); - if (currentMaster == null) { - return null; - } - - if (!currentMaster.equals(localNodeId)) { - log.info("Forwarding request to relinquish " - + "mastership for device {} to {}", deviceId, currentMaster); - return futureGetOrElse(clusterCommunicator.sendAndReceive( - deviceId, - TRANSITION_FROM_MASTER_TO_STANDBY_SUBJECT, - SERIALIZER::encode, - SERIALIZER::decode, - currentMaster), null); - } - - return leadershipService.stepdown(createDeviceMastershipTopic(deviceId)) - ? new MastershipEvent(MastershipEvent.Type.MASTER_CHANGED, deviceId, getNodes(deviceId)) : null; - } - - @Override - public void relinquishAllRole(NodeId nodeId) { - // Noop. LeadershipService already takes care of detecting and purging deadlocks. - } - - private class InternalDeviceMastershipEventListener implements LeadershipEventListener { - @Override - public void event(LeadershipEvent event) { - Leadership leadership = event.subject(); - if (!isDeviceMastershipTopic(leadership.topic())) { - return; - } - DeviceId deviceId = extractDeviceIdFromTopic(leadership.topic()); - switch (event.type()) { - case LEADER_ELECTED: - notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, getNodes(deviceId))); - break; - case LEADER_REELECTED: - // There is no concept of leader re-election in the new distributed leadership manager. - throw new IllegalStateException("Unexpected event type"); - case LEADER_BOOTED: - notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, getNodes(deviceId))); - break; - case CANDIDATES_CHANGED: - notifyDelegate(new MastershipEvent(BACKUPS_CHANGED, deviceId, getNodes(deviceId))); - break; - default: - return; - } - } - } - - private String createDeviceMastershipTopic(DeviceId deviceId) { - return String.format("device:%s", deviceId.toString()); - } - - private DeviceId extractDeviceIdFromTopic(String topic) { - Matcher m = DEVICE_MASTERSHIP_TOPIC_PATTERN.matcher(topic); - if (m.matches()) { - return DeviceId.deviceId(m.group(1)); - } else { - throw new IllegalArgumentException("Invalid device mastership topic: " + topic); - } - } - - private boolean isDeviceMastershipTopic(String topic) { - Matcher m = DEVICE_MASTERSHIP_TOPIC_PATTERN.matcher(topic); - return m.matches(); - } - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/mastership/impl/RoleValue.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/mastership/impl/RoleValue.java deleted file mode 100644 index 5a38a34a..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/mastership/impl/RoleValue.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.mastership.impl; - -import static org.onosproject.net.MastershipRole.MASTER; -import static org.onosproject.net.MastershipRole.NONE; -import static org.onosproject.net.MastershipRole.STANDBY; - -import java.util.Collections; -import java.util.EnumMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.onosproject.cluster.NodeId; -import org.onosproject.cluster.RoleInfo; -import org.onosproject.net.MastershipRole; - -import com.google.common.base.MoreObjects; -import com.google.common.base.MoreObjects.ToStringHelper; -import com.google.common.collect.Lists; - -/** - * A structure that holds node mastership roles associated with a - * {@link org.onosproject.net.DeviceId}. This structure needs to be locked through IMap. - */ -final class RoleValue { - - protected final Map<MastershipRole, List<NodeId>> value = new EnumMap<>(MastershipRole.class); - - /** - * Constructs empty RoleValue. - */ - public RoleValue() { - value.put(MastershipRole.MASTER, new LinkedList<>()); - value.put(MastershipRole.STANDBY, new LinkedList<>()); - value.put(MastershipRole.NONE, new LinkedList<>()); - } - - /** - * Constructs copy of specified RoleValue. - * - * @param original original to create copy from - */ - public RoleValue(final RoleValue original) { - value.put(MASTER, Lists.newLinkedList(original.value.get(MASTER))); - value.put(STANDBY, Lists.newLinkedList(original.value.get(STANDBY))); - value.put(NONE, Lists.newLinkedList(original.value.get(NONE))); - } - - // exposing internals for serialization purpose only - Map<MastershipRole, List<NodeId>> value() { - return Collections.unmodifiableMap(value); - } - - public List<NodeId> nodesOfRole(MastershipRole type) { - return value.get(type); - } - - /** - * Returns the first node to match the MastershipRole, or if there - * are none, null. - * - * @param type the role - * @return a node ID or null - */ - public NodeId get(MastershipRole type) { - return value.get(type).isEmpty() ? null : value.get(type).get(0); - } - - public boolean contains(MastershipRole type, NodeId nodeId) { - return value.get(type).contains(nodeId); - } - - public MastershipRole getRole(NodeId nodeId) { - if (contains(MASTER, nodeId)) { - return MASTER; - } - if (contains(STANDBY, nodeId)) { - return STANDBY; - } - return NONE; - } - - /** - * Associates a node to a certain role. - * - * @param type the role - * @param nodeId the node ID of the node to associate - * @return true if modified - */ - public boolean add(MastershipRole type, NodeId nodeId) { - List<NodeId> nodes = value.get(type); - - if (!nodes.contains(nodeId)) { - return nodes.add(nodeId); - } - return false; - } - - /** - * Removes a node from a certain role. - * - * @param type the role - * @param nodeId the ID of the node to remove - * @return true if modified - */ - public boolean remove(MastershipRole type, NodeId nodeId) { - List<NodeId> nodes = value.get(type); - if (!nodes.isEmpty()) { - return nodes.remove(nodeId); - } else { - return false; - } - } - - /** - * Reassigns a node from one role to another. If the node was not of the - * old role, it will still be assigned the new role. - * - * @param nodeId the Node ID of node changing roles - * @param from the old role - * @param to the new role - * @return true if modified - */ - public boolean reassign(NodeId nodeId, MastershipRole from, MastershipRole to) { - boolean modified = remove(from, nodeId); - modified |= add(to, nodeId); - return modified; - } - - /** - * Replaces a node in one role with another node. Even if there is no node to - * replace, the new node is associated to the role. - * - * @param from the old NodeId to replace - * @param to the new NodeId - * @param type the role associated with the old NodeId - * @return true if modified - */ - public boolean replace(NodeId from, NodeId to, MastershipRole type) { - boolean modified = remove(type, from); - modified |= add(type, to); - return modified; - } - - /** - * Summarizes this RoleValue as a RoleInfo. Note that master and/or backups - * may be empty, so the values should be checked for safety. - * - * @return the RoleInfo. - */ - public RoleInfo roleInfo() { - return new RoleInfo( - get(MastershipRole.MASTER), nodesOfRole(MastershipRole.STANDBY)); - } - - @Override - public String toString() { - ToStringHelper helper = MoreObjects.toStringHelper(this.getClass()); - for (Map.Entry<MastershipRole, List<NodeId>> el : value.entrySet()) { - helper.add(el.getKey().toString(), el.getValue()); - } - return helper.toString(); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/mastership/impl/RoleValueSerializer.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/mastership/impl/RoleValueSerializer.java deleted file mode 100644 index c81ea7f9..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/mastership/impl/RoleValueSerializer.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.mastership.impl; - -import java.util.List; -import java.util.Map; - -import org.onosproject.cluster.NodeId; -import org.onosproject.net.MastershipRole; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Serializer for RoleValues used by {@link org.onosproject.mastership.MastershipStore}. - */ -public class RoleValueSerializer extends Serializer<RoleValue> { - - //RoleValues are assumed to hold a Map of MastershipRoles (an enum) - //to a List of NodeIds. - - @Override - public RoleValue read(Kryo kryo, Input input, Class<RoleValue> type) { - RoleValue rv = new RoleValue(); - int size = input.readInt(); - for (int i = 0; i < size; i++) { - MastershipRole role = MastershipRole.values()[input.readInt()]; - int s = input.readInt(); - for (int j = 0; j < s; j++) { - rv.add(role, new NodeId(input.readString())); - } - } - return rv; - } - - @Override - public void write(Kryo kryo, Output output, RoleValue type) { - final Map<MastershipRole, List<NodeId>> map = type.value(); - output.writeInt(map.size()); - - for (Map.Entry<MastershipRole, List<NodeId>> el : map.entrySet()) { - output.writeInt(el.getKey().ordinal()); - - List<NodeId> nodes = el.getValue(); - output.writeInt(nodes.size()); - for (NodeId n : nodes) { - output.writeString(n.toString()); - } - } - } - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/mastership/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/mastership/impl/package-info.java deleted file mode 100644 index 40ff6f76..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/mastership/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of a distributed mastership store using Hazelcast. - */ -package org.onosproject.store.mastership.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java deleted file mode 100644 index 0335ba5d..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.newresource.impl; - -import com.google.common.annotations.Beta; -import com.google.common.collect.ImmutableList; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onosproject.net.newresource.ResourceConsumer; -import org.onosproject.net.newresource.ResourceEvent; -import org.onosproject.net.newresource.ResourcePath; -import org.onosproject.net.newresource.ResourceStore; -import org.onosproject.net.newresource.ResourceStoreDelegate; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.StorageService; -import org.onosproject.store.service.TransactionContext; -import org.onosproject.store.service.TransactionalMap; -import org.onosproject.store.service.Versioned; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static org.onosproject.net.newresource.ResourceEvent.Type.*; - -/** - * Implementation of ResourceStore using TransactionalMap. - */ -@Component(immediate = true) -@Service -@Beta -public class ConsistentResourceStore extends AbstractStore<ResourceEvent, ResourceStoreDelegate> - implements ResourceStore { - private static final Logger log = LoggerFactory.getLogger(ConsistentResourceStore.class); - - private static final String CONSUMER_MAP = "onos-resource-consumers"; - private static final String CHILD_MAP = "onos-resource-children"; - private static final Serializer SERIALIZER = Serializer.using( - Arrays.asList(KryoNamespaces.BASIC, KryoNamespaces.API)); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService service; - - private ConsistentMap<ResourcePath, ResourceConsumer> consumerMap; - private ConsistentMap<ResourcePath, List<ResourcePath>> childMap; - - @Activate - public void activate() { - consumerMap = service.<ResourcePath, ResourceConsumer>consistentMapBuilder() - .withName(CONSUMER_MAP) - .withSerializer(SERIALIZER) - .build(); - childMap = service.<ResourcePath, List<ResourcePath>>consistentMapBuilder() - .withName(CHILD_MAP) - .withSerializer(SERIALIZER) - .build(); - - childMap.put(ResourcePath.ROOT, ImmutableList.of()); - } - - @Override - public Optional<ResourceConsumer> getConsumer(ResourcePath resource) { - checkNotNull(resource); - - Versioned<ResourceConsumer> consumer = consumerMap.get(resource); - if (consumer == null) { - return Optional.empty(); - } - - return Optional.of(consumer.value()); - } - - @Override - public boolean register(List<ResourcePath> resources) { - checkNotNull(resources); - - TransactionContext tx = service.transactionContextBuilder().build(); - tx.begin(); - - TransactionalMap<ResourcePath, List<ResourcePath>> childTxMap = - tx.getTransactionalMap(CHILD_MAP, SERIALIZER); - - Map<ResourcePath, List<ResourcePath>> resourceMap = resources.stream() - .filter(x -> x.parent().isPresent()) - .collect(Collectors.groupingBy(x -> x.parent().get())); - - for (Map.Entry<ResourcePath, List<ResourcePath>> entry: resourceMap.entrySet()) { - if (!isRegistered(childTxMap, entry.getKey())) { - return abortTransaction(tx); - } - - if (!appendValues(childTxMap, entry.getKey(), entry.getValue())) { - return abortTransaction(tx); - } - } - - boolean success = tx.commit(); - if (success) { - List<ResourceEvent> events = resources.stream() - .filter(x -> x.parent().isPresent()) - .map(x -> new ResourceEvent(RESOURCE_ADDED, x)) - .collect(Collectors.toList()); - notifyDelegate(events); - } - return success; - } - - @Override - public boolean unregister(List<ResourcePath> resources) { - checkNotNull(resources); - - TransactionContext tx = service.transactionContextBuilder().build(); - tx.begin(); - - TransactionalMap<ResourcePath, List<ResourcePath>> childTxMap = - tx.getTransactionalMap(CHILD_MAP, SERIALIZER); - TransactionalMap<ResourcePath, ResourceConsumer> consumerTxMap = - tx.getTransactionalMap(CONSUMER_MAP, SERIALIZER); - - Map<ResourcePath, List<ResourcePath>> resourceMap = resources.stream() - .filter(x -> x.parent().isPresent()) - .collect(Collectors.groupingBy(x -> x.parent().get())); - - // even if one of the resources is allocated to a consumer, - // all unregistrations are regarded as failure - for (Map.Entry<ResourcePath, List<ResourcePath>> entry: resourceMap.entrySet()) { - if (entry.getValue().stream().anyMatch(x -> consumerTxMap.get(x) != null)) { - return abortTransaction(tx); - } - - if (!removeValues(childTxMap, entry.getKey(), entry.getValue())) { - return abortTransaction(tx); - } - } - - boolean success = tx.commit(); - if (success) { - List<ResourceEvent> events = resources.stream() - .filter(x -> x.parent().isPresent()) - .map(x -> new ResourceEvent(RESOURCE_REMOVED, x)) - .collect(Collectors.toList()); - notifyDelegate(events); - } - return success; - } - - @Override - public boolean allocate(List<ResourcePath> resources, ResourceConsumer consumer) { - checkNotNull(resources); - checkNotNull(consumer); - - TransactionContext tx = service.transactionContextBuilder().build(); - tx.begin(); - - TransactionalMap<ResourcePath, List<ResourcePath>> childTxMap = - tx.getTransactionalMap(CHILD_MAP, SERIALIZER); - TransactionalMap<ResourcePath, ResourceConsumer> consumerTxMap = - tx.getTransactionalMap(CONSUMER_MAP, SERIALIZER); - - for (ResourcePath resource: resources) { - if (!isRegistered(childTxMap, resource)) { - return abortTransaction(tx); - } - - ResourceConsumer oldValue = consumerTxMap.put(resource, consumer); - if (oldValue != null) { - return abortTransaction(tx); - } - } - - return tx.commit(); - } - - @Override - public boolean release(List<ResourcePath> resources, List<ResourceConsumer> consumers) { - checkNotNull(resources); - checkNotNull(consumers); - checkArgument(resources.size() == consumers.size()); - - TransactionContext tx = service.transactionContextBuilder().build(); - tx.begin(); - - TransactionalMap<ResourcePath, ResourceConsumer> consumerTxMap = - tx.getTransactionalMap(CONSUMER_MAP, SERIALIZER); - Iterator<ResourcePath> resourceIte = resources.iterator(); - Iterator<ResourceConsumer> consumerIte = consumers.iterator(); - - while (resourceIte.hasNext() && consumerIte.hasNext()) { - ResourcePath resource = resourceIte.next(); - ResourceConsumer consumer = consumerIte.next(); - - // if this single release fails (because the resource is allocated to another consumer, - // the whole release fails - if (!consumerTxMap.remove(resource, consumer)) { - return abortTransaction(tx); - } - } - - return tx.commit(); - } - - @Override - public Collection<ResourcePath> getResources(ResourceConsumer consumer) { - checkNotNull(consumer); - - // NOTE: getting all entries may become performance bottleneck - // TODO: revisit for better backend data structure - return consumerMap.entrySet().stream() - .filter(x -> x.getValue().value().equals(consumer)) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); - } - - @Override - public Collection<ResourcePath> getChildResources(ResourcePath parent) { - checkNotNull(parent); - - Versioned<List<ResourcePath>> children = childMap.get(parent); - if (children == null) { - return Collections.emptyList(); - } - - return children.value(); - } - - @Override - public <T> Collection<ResourcePath> getAllocatedResources(ResourcePath parent, Class<T> cls) { - checkNotNull(parent); - checkNotNull(cls); - - Versioned<List<ResourcePath>> children = childMap.get(parent); - if (children == null) { - return Collections.emptyList(); - } - - return children.value().stream() - .filter(x -> x.last().getClass().equals(cls)) - .filter(consumerMap::containsKey) - .collect(Collectors.toList()); - } - - /** - * Abort the transaction. - * - * @param tx transaction context - * @return always false - */ - private boolean abortTransaction(TransactionContext tx) { - tx.abort(); - return false; - } - - /** - * Appends the values to the existing values associated with the specified key. - * If the map already has all the given values, appending will not happen. - * - * @param map map holding multiple values for a key - * @param key key specifying values - * @param values values to be appended - * @param <K> type of the key - * @param <V> type of the element of the list - * @return true if the operation succeeds, false otherwise. - */ - private <K, V> boolean appendValues(TransactionalMap<K, List<V>> map, K key, List<V> values) { - List<V> oldValues = map.putIfAbsent(key, new ArrayList<>(values)); - if (oldValues == null) { - return true; - } - - LinkedHashSet<V> oldSet = new LinkedHashSet<>(oldValues); - if (oldSet.containsAll(values)) { - // don't write to map because all values are already stored - return true; - } - - oldSet.addAll(values); - return map.replace(key, oldValues, new ArrayList<>(oldSet)); - } - - /** - * Removes the values from the existing values associated with the specified key. - * If the map doesn't contain the given values, removal will not happen. - * - * @param map map holding multiple values for a key - * @param key key specifying values - * @param values values to be removed - * @param <K> type of the key - * @param <V> type of the element of the list - * @return true if the operation succeeds, false otherwise - */ - private <K, V> boolean removeValues(TransactionalMap<K, List<V>> map, K key, List<V> values) { - List<V> oldValues = map.get(key); - if (oldValues == null) { - map.put(key, new ArrayList<>()); - return true; - } - - LinkedHashSet<V> oldSet = new LinkedHashSet<>(oldValues); - if (values.stream().allMatch(x -> !oldSet.contains(x))) { - // don't write map because none of the values are stored - return true; - } - - oldSet.removeAll(values); - return map.replace(key, oldValues, new ArrayList<>(oldSet)); - } - - /** - * Checks if the specified resource is registered as a child of a resource in the map. - * - * @param map map storing parent - child relationship of resources - * @param resource resource to be checked - * @return true if the resource is registered, false otherwise. - */ - private boolean isRegistered(TransactionalMap<ResourcePath, List<ResourcePath>> map, ResourcePath resource) { - // root is always regarded to be registered - if (!resource.parent().isPresent()) { - return true; - } - - List<ResourcePath> value = map.get(resource.parent().get()); - return value != null && value.contains(resource); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/package-info.java deleted file mode 100644 index 330d56c3..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of the network resource distributed store. - */ -package org.onosproject.store.newresource.impl;
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/packet/impl/DistributedPacketStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/packet/impl/DistributedPacketStore.java deleted file mode 100644 index 3865a779..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/packet/impl/DistributedPacketStore.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.packet.impl; - -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.NodeId; -import org.onosproject.mastership.MastershipService; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.packet.OutboundPacket; -import org.onosproject.net.packet.PacketEvent; -import org.onosproject.net.packet.PacketEvent.Type; -import org.onosproject.net.packet.PacketRequest; -import org.onosproject.net.packet.PacketStore; -import org.onosproject.net.packet.PacketStoreDelegate; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.cluster.messaging.MessageSubject; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.serializers.KryoSerializer; -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.ConsistentMapException; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.StorageService; -import org.slf4j.Logger; - -import java.util.List; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.onlab.util.Tools.groupedThreads; -import static org.onlab.util.Tools.retryable; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Distributed packet store implementation allowing packets to be sent to - * remote instances. - */ -@Component(immediate = true) -@Service -public class DistributedPacketStore - extends AbstractStore<PacketEvent, PacketStoreDelegate> - implements PacketStore { - - private final Logger log = getLogger(getClass()); - - private static final int MAX_BACKOFF = 10; - - // TODO: make this configurable. - private static final int MESSAGE_HANDLER_THREAD_POOL_SIZE = 4; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipService mastershipService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterCommunicationService communicationService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - private PacketRequestTracker tracker; - - private static final MessageSubject PACKET_OUT_SUBJECT = - new MessageSubject("packet-out"); - - private static final KryoSerializer SERIALIZER = new KryoSerializer() { - @Override - protected void setupKryoPool() { - serializerPool = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID) - .build(); - } - }; - - private ExecutorService messageHandlingExecutor; - - @Activate - public void activate() { - messageHandlingExecutor = Executors.newFixedThreadPool( - MESSAGE_HANDLER_THREAD_POOL_SIZE, - groupedThreads("onos/store/packet", "message-handlers")); - - communicationService.<OutboundPacket>addSubscriber(PACKET_OUT_SUBJECT, - SERIALIZER::decode, - packet -> notifyDelegate(new PacketEvent(Type.EMIT, packet)), - messageHandlingExecutor); - - tracker = new PacketRequestTracker(); - - log.info("Started"); - } - - @Deactivate - public void deactivate() { - communicationService.removeSubscriber(PACKET_OUT_SUBJECT); - messageHandlingExecutor.shutdown(); - tracker = null; - log.info("Stopped"); - } - - @Override - public void emit(OutboundPacket packet) { - NodeId myId = clusterService.getLocalNode().id(); - NodeId master = mastershipService.getMasterFor(packet.sendThrough()); - - if (master == null) { - return; - } - - if (myId.equals(master)) { - notifyDelegate(new PacketEvent(Type.EMIT, packet)); - return; - } - - communicationService.unicast(packet, PACKET_OUT_SUBJECT, SERIALIZER::encode, master) - .whenComplete((r, error) -> { - if (error != null) { - log.warn("Failed to send packet-out to {}", master, error); - } - }); - } - - @Override - public void requestPackets(PacketRequest request) { - tracker.add(request); - } - - @Override - public void cancelPackets(PacketRequest request) { - tracker.remove(request); - } - - @Override - public List<PacketRequest> existingRequests() { - return tracker.requests(); - } - - private final class PacketRequestTracker { - - private ConsistentMap<TrafficSelector, Set<PacketRequest>> requests; - - private PacketRequestTracker() { - requests = storageService.<TrafficSelector, Set<PacketRequest>>consistentMapBuilder() - .withName("onos-packet-requests") - .withPartitionsDisabled() - .withSerializer(Serializer.using(KryoNamespaces.API)) - .build(); - } - - private void add(PacketRequest request) { - AtomicBoolean firstRequest = - retryable(this::addInternal, ConsistentMapException.class, - 3, MAX_BACKOFF).apply(request); - if (firstRequest.get() && delegate != null) { - // The instance that makes the first request will push to all devices - delegate.requestPackets(request); - } - } - - private AtomicBoolean addInternal(PacketRequest request) { - AtomicBoolean firstRequest = new AtomicBoolean(false); - requests.compute(request.selector(), (s, existingRequests) -> { - if (existingRequests == null) { - firstRequest.set(true); - return ImmutableSet.of(request); - } else if (!existingRequests.contains(request)) { - return ImmutableSet.<PacketRequest>builder() - .addAll(existingRequests) - .add(request) - .build(); - } else { - return existingRequests; - } - }); - return firstRequest; - } - - private void remove(PacketRequest request) { - AtomicBoolean removedLast = - retryable(this::removeInternal, ConsistentMapException.class, - 3, MAX_BACKOFF).apply(request); - if (removedLast.get() && delegate != null) { - // The instance that removes the last request will remove from all devices - delegate.cancelPackets(request); - } - } - - private AtomicBoolean removeInternal(PacketRequest request) { - AtomicBoolean removedLast = new AtomicBoolean(false); - requests.computeIfPresent(request.selector(), (s, existingRequests) -> { - if (existingRequests.contains(request)) { - Set<PacketRequest> newRequests = Sets.newHashSet(existingRequests); - newRequests.remove(request); - if (newRequests.size() > 0) { - return ImmutableSet.copyOf(newRequests); - } else { - removedLast.set(true); - return null; - } - } else { - return existingRequests; - } - }); - return removedLast; - } - - private List<PacketRequest> requests() { - List<PacketRequest> list = Lists.newArrayList(); - requests.values().forEach(v -> list.addAll(v.value())); - list.sort((o1, o2) -> o1.priority().priorityValue() - o2.priority().priorityValue()); - return list; - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/packet/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/packet/impl/package-info.java deleted file mode 100644 index 43282583..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/packet/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of distributed packet store. - */ -package org.onosproject.store.packet.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/DistributedProxyArpStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/DistributedProxyArpStore.java deleted file mode 100644 index 4d7e7f33..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/DistributedProxyArpStore.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.proxyarp.impl; - -import com.google.common.collect.Maps; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.NodeId; -import org.onosproject.mastership.MastershipService; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.Host; -import org.onosproject.net.HostId; -import org.onosproject.net.host.HostEvent; -import org.onosproject.net.host.HostListener; -import org.onosproject.net.host.HostService; -import org.onosproject.net.proxyarp.ProxyArpStore; -import org.onosproject.net.proxyarp.ProxyArpStoreDelegate; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.cluster.messaging.MessageSubject; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.serializers.KryoSerializer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.nio.ByteBuffer; -import java.util.Map; -import java.util.concurrent.ExecutorService; - -import static org.onlab.util.BoundedThreadPool.newFixedThreadPool; -import static org.onlab.util.Tools.groupedThreads; - -/** - * Implementation of proxy ARP distribution mechanism. - */ -@Component(immediate = true) -@Service -public class DistributedProxyArpStore implements ProxyArpStore { - - private Logger log = LoggerFactory.getLogger(getClass()); - - private static final MessageSubject ARP_RESPONSE_MESSAGE = - new MessageSubject("onos-arp-response"); - - protected final KryoSerializer serializer = new KryoSerializer() { - @Override - protected void setupKryoPool() { - serializerPool = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .register(ArpResponseMessage.class) - .register(ByteBuffer.class) - .build(); - } - }; - - private ProxyArpStoreDelegate delegate; - - private Map<HostId, ArpResponseMessage> pendingMessages = Maps.newConcurrentMap(); - - private ExecutorService executor = - newFixedThreadPool(4, groupedThreads("onos/arp", "sender-%d")); - - private NodeId localNodeId; - - private HostListener hostListener = new InternalHostListener(); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipService mastershipService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterCommunicationService commService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected HostService hostService; - - - @Activate - protected void activate() { - localNodeId = clusterService.getLocalNode().id(); - hostService.addListener(hostListener); - commService.addSubscriber(ARP_RESPONSE_MESSAGE, serializer::decode, - this::processArpResponse, executor); - log.info("Started"); - } - - @Deactivate - protected void deactivate() { - commService.removeSubscriber(ARP_RESPONSE_MESSAGE); - hostService.removeListener(hostListener); - log.info("Stopped"); - } - - @Override - public void forward(ConnectPoint outPort, Host subject, ByteBuffer packet) { - /*NodeId nodeId = mastershipService.getMasterFor(outPort.deviceId()); - if (nodeId.equals(localNodeId)) { - if (delegate != null) { - delegate.emitResponse(outPort, packet); - } - } else { - log.info("Forwarding ARP response from {} to {}", subject.id(), outPort); - commService.unicast(new ArpResponseMessage(outPort, subject, packet.array()), - ARP_RESPONSE_MESSAGE, serializer::encode, nodeId); - }*/ - //FIXME: Code above may be unnecessary and therefore cluster messaging - // and pendingMessages could be pruned as well. - delegate.emitResponse(outPort, packet); - } - - @Override - public void setDelegate(ProxyArpStoreDelegate delegate) { - this.delegate = delegate; - } - - // Processes the incoming ARP response message. - private void processArpResponse(ArpResponseMessage msg) { - pendingMessages.put(msg.subject.id(), msg); - if (hostService.getHost(msg.subject.id()) != null) { - checkPendingArps(msg.subject.id()); - } - // FIXME: figure out pruning so stuff does not build up - } - - // Checks for pending ARP response message for the specified host. - // If one exists, emit response via delegate. - private void checkPendingArps(HostId id) { - ArpResponseMessage msg = pendingMessages.remove(id); - if (msg != null && delegate != null) { - log.info("Emitting ARP response from {} to {}", id, msg.outPort); - delegate.emitResponse(msg.outPort, ByteBuffer.wrap(msg.packet)); - } - } - - // Message carrying an ARP response. - private static class ArpResponseMessage { - private ConnectPoint outPort; - private Host subject; - private byte[] packet; - - public ArpResponseMessage(ConnectPoint outPort, Host subject, byte[] packet) { - this.outPort = outPort; - this.subject = subject; - this.packet = packet; - } - - private ArpResponseMessage() { - } - } - - private class InternalHostListener implements HostListener { - @Override - public void event(HostEvent event) { - checkPendingArps(event.subject().id()); - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/package-info.java deleted file mode 100644 index e3675524..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of proxy ARP distribution mechanism. - */ -package org.onosproject.store.proxyarp.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentIntentSetMultimap.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentIntentSetMultimap.java deleted file mode 100644 index 8d5a1001..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentIntentSetMultimap.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.resource.impl; - -import com.google.common.annotations.Beta; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onosproject.net.device.DeviceService; -import org.onosproject.net.intent.IntentId; -import org.onosproject.net.resource.device.IntentSetMultimap; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.StorageService; -import org.onosproject.store.service.Versioned; -import org.slf4j.Logger; - -import java.util.HashSet; -import java.util.Set; - -import static org.slf4j.LoggerFactory.getLogger; - -/** - * A collection that maps Intent IDs as keys to values as Intent IDs, - * where each key may associated with multiple values without duplication. - */ -@Component(immediate = true, enabled = true) -@Service -@Beta -public class ConsistentIntentSetMultimap implements IntentSetMultimap { - private final Logger log = getLogger(getClass()); - - private static final String INTENT_MAPPING = "IntentMapping"; - - private static final Serializer SERIALIZER = Serializer.using(KryoNamespaces.API); - - private ConsistentMap<IntentId, Set<IntentId>> intentMapping; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected DeviceService deviceService; - - @Activate - public void activate() { - intentMapping = storageService.<IntentId, Set<IntentId>>consistentMapBuilder() - .withName(INTENT_MAPPING) - .withSerializer(SERIALIZER) - .build(); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - log.info("Stopped"); - } - - @Override - public Set<IntentId> getMapping(IntentId intentId) { - Versioned<Set<IntentId>> result = intentMapping.get(intentId); - - if (result != null) { - return result.value(); - } - - return null; - } - - @Override - public boolean allocateMapping(IntentId keyIntentId, IntentId valIntentId) { - Versioned<Set<IntentId>> versionedIntents = intentMapping.get(keyIntentId); - - if (versionedIntents == null) { - Set<IntentId> newSet = new HashSet<>(); - newSet.add(valIntentId); - intentMapping.put(keyIntentId, newSet); - } else { - versionedIntents.value().add(valIntentId); - } - - return true; - } - - @Override - public void releaseMapping(IntentId intentId) { - for (IntentId intent : intentMapping.keySet()) { - // TODO: optimize by checking for identical src & dst - Set<IntentId> mapping = intentMapping.get(intent).value(); - if (mapping.remove(intentId)) { - return; - } - } - } - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentLinkResourceStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentLinkResourceStore.java deleted file mode 100644 index 351c7a5f..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentLinkResourceStore.java +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.resource.impl; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Deactivate; -import org.onlab.util.Bandwidth; -import org.onosproject.net.OmsPort; -import org.onosproject.net.device.DeviceService; -import org.slf4j.Logger; -import org.onlab.util.PositionalParameterStringFormatter; -import org.onosproject.net.Link; -import org.onosproject.net.LinkKey; -import org.onosproject.net.Port; -import org.onosproject.net.intent.IntentId; -import org.onosproject.net.resource.link.BandwidthResource; -import org.onosproject.net.resource.link.BandwidthResourceAllocation; -import org.onosproject.net.resource.link.LambdaResource; -import org.onosproject.net.resource.link.LambdaResourceAllocation; -import org.onosproject.net.resource.link.LinkResourceAllocations; -import org.onosproject.net.resource.link.LinkResourceEvent; -import org.onosproject.net.resource.link.LinkResourceStore; -import org.onosproject.net.resource.link.LinkResourceStoreDelegate; -import org.onosproject.net.resource.link.MplsLabel; -import org.onosproject.net.resource.link.MplsLabelResourceAllocation; -import org.onosproject.net.resource.ResourceAllocation; -import org.onosproject.net.resource.ResourceAllocationException; -import org.onosproject.net.resource.ResourceType; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.ConsistentMap; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.StorageService; -import org.onosproject.store.service.TransactionContext; -import org.onosproject.store.service.TransactionalMap; -import org.onosproject.store.service.Versioned; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.slf4j.LoggerFactory.getLogger; -import static org.onosproject.net.AnnotationKeys.BANDWIDTH; - -/** - * Store that manages link resources using Copycat-backed TransactionalMaps. - * - * @deprecated in Emu Release - */ -@Deprecated -@Component(immediate = true, enabled = true) -@Service -public class ConsistentLinkResourceStore extends - AbstractStore<LinkResourceEvent, LinkResourceStoreDelegate> implements - LinkResourceStore { - - private final Logger log = getLogger(getClass()); - - private static final BandwidthResource DEFAULT_BANDWIDTH = new BandwidthResource(Bandwidth.mbps(1_000)); - private static final BandwidthResource EMPTY_BW = new BandwidthResource(Bandwidth.bps(0)); - - // Smallest non-reserved MPLS label - private static final int MIN_UNRESERVED_LABEL = 0x10; - // Max non-reserved MPLS label = 239 - private static final int MAX_UNRESERVED_LABEL = 0xEF; - - // table to store current allocations - /** LinkKey -> List<LinkResourceAllocations>. */ - private static final String LINK_RESOURCE_ALLOCATIONS = "LinkAllocations"; - - /** IntentId -> LinkResourceAllocations. */ - private static final String INTENT_ALLOCATIONS = "LinkIntentAllocations"; - - private static final Serializer SERIALIZER = Serializer.using(KryoNamespaces.API); - - // for reading committed values. - private ConsistentMap<IntentId, LinkResourceAllocations> intentAllocMap; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected DeviceService deviceService; - - @Activate - public void activate() { - intentAllocMap = storageService.<IntentId, LinkResourceAllocations>consistentMapBuilder() - .withName(INTENT_ALLOCATIONS) - .withSerializer(SERIALIZER) - .build(); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - log.info("Stopped"); - } - - private TransactionalMap<IntentId, LinkResourceAllocations> getIntentAllocs(TransactionContext tx) { - return tx.getTransactionalMap(INTENT_ALLOCATIONS, SERIALIZER); - } - - private TransactionalMap<LinkKey, List<LinkResourceAllocations>> getLinkAllocs(TransactionContext tx) { - return tx.getTransactionalMap(LINK_RESOURCE_ALLOCATIONS, SERIALIZER); - } - - private TransactionContext getTxContext() { - return storageService.transactionContextBuilder().build(); - } - - private Set<ResourceAllocation> getResourceCapacity(ResourceType type, Link link) { - switch (type) { - case BANDWIDTH: - return ImmutableSet.of(getBandwidthResourceCapacity(link)); - case LAMBDA: - return getLambdaResourceCapacity(link); - case MPLS_LABEL: - return getMplsResourceCapacity(); - default: - return ImmutableSet.of(); - } - } - - private Set<ResourceAllocation> getLambdaResourceCapacity(Link link) { - Port port = deviceService.getPort(link.src().deviceId(), link.src().port()); - if (!(port instanceof OmsPort)) { - return Collections.emptySet(); - } - - OmsPort omsPort = (OmsPort) port; - Set<ResourceAllocation> allocations = new HashSet<>(); - // Assume fixed grid for now - for (int i = 0; i < omsPort.totalChannels(); i++) { - allocations.add(new LambdaResourceAllocation(LambdaResource.valueOf(i))); - } - return allocations; - } - - private BandwidthResourceAllocation getBandwidthResourceCapacity(Link link) { - - // if Link annotation exist, use them - // if all fails, use DEFAULT_BANDWIDTH - BandwidthResource bandwidth = DEFAULT_BANDWIDTH; - String strBw = link.annotations().value(BANDWIDTH); - if (strBw == null) { - return new BandwidthResourceAllocation(bandwidth); - } - - try { - bandwidth = new BandwidthResource(Bandwidth.mbps(Double.parseDouble(strBw))); - } catch (NumberFormatException e) { - // do nothings, use default bandwidth - bandwidth = DEFAULT_BANDWIDTH; - } - return new BandwidthResourceAllocation(bandwidth); - } - - private Set<ResourceAllocation> getMplsResourceCapacity() { - Set<ResourceAllocation> allocations = new HashSet<>(); - //Ignoring reserved labels of 0 through 15 - for (int i = MIN_UNRESERVED_LABEL; i <= MAX_UNRESERVED_LABEL; i++) { - allocations.add(new MplsLabelResourceAllocation(MplsLabel - .valueOf(i))); - - } - return allocations; - } - - private Map<ResourceType, Set<ResourceAllocation>> getResourceCapacity(Link link) { - Map<ResourceType, Set<ResourceAllocation>> caps = new HashMap<>(); - for (ResourceType type : ResourceType.values()) { - Set<ResourceAllocation> cap = getResourceCapacity(type, link); - caps.put(type, cap); - } - return caps; - } - - @Override - public Set<ResourceAllocation> getFreeResources(Link link) { - TransactionContext tx = getTxContext(); - - tx.begin(); - try { - Map<ResourceType, Set<ResourceAllocation>> freeResources = getFreeResourcesEx(tx, link); - return freeResources.values().stream() - .flatMap(Collection::stream) - .collect(Collectors.toSet()); - } finally { - tx.abort(); - } - } - - private Map<ResourceType, Set<ResourceAllocation>> getFreeResourcesEx(TransactionContext tx, Link link) { - checkNotNull(tx); - checkNotNull(link); - - Map<ResourceType, Set<ResourceAllocation>> free = new HashMap<>(); - final Map<ResourceType, Set<ResourceAllocation>> caps = getResourceCapacity(link); - final List<LinkResourceAllocations> allocations = ImmutableList.copyOf(getAllocations(tx, link)); - - Set<ResourceAllocation> bw = caps.get(ResourceType.BANDWIDTH); - Set<ResourceAllocation> value = getFreeBandwidthResources(link, bw, allocations); - free.put(ResourceType.BANDWIDTH, value); - - Set<ResourceAllocation> lmd = caps.get(ResourceType.LAMBDA); - Set<ResourceAllocation> freeL = getFreeResources(link, lmd, allocations, - LambdaResourceAllocation.class); - free.put(ResourceType.LAMBDA, freeL); - - Set<ResourceAllocation> mpls = caps.get(ResourceType.MPLS_LABEL); - Set<ResourceAllocation> freeLabel = getFreeResources(link, mpls, allocations, - MplsLabelResourceAllocation.class); - free.put(ResourceType.MPLS_LABEL, freeLabel); - - return free; - } - - private Set<ResourceAllocation> getFreeBandwidthResources(Link link, Set<ResourceAllocation> bw, - List<LinkResourceAllocations> allocations) { - if (bw == null || bw.isEmpty()) { - bw = Sets.newHashSet(new BandwidthResourceAllocation(EMPTY_BW)); - } - - BandwidthResourceAllocation cap = (BandwidthResourceAllocation) bw.iterator().next(); - double freeBw = cap.bandwidth().toDouble(); - - // enumerate current allocations, subtracting resources - double allocatedBw = allocations.stream() - .flatMap(x -> x.getResourceAllocation(link).stream()) - .filter(x -> x instanceof BandwidthResourceAllocation) - .map(x -> (BandwidthResourceAllocation) x) - .mapToDouble(x -> x.bandwidth().toDouble()) - .sum(); - freeBw -= allocatedBw; - return Sets.newHashSet( - new BandwidthResourceAllocation(new BandwidthResource(Bandwidth.bps(freeBw)))); - } - - private Set<ResourceAllocation> getFreeResources(Link link, - Set<ResourceAllocation> resources, - List<LinkResourceAllocations> allocations, - Class<? extends ResourceAllocation> cls) { - if (resources == null || resources.isEmpty()) { - // nothing left - return Collections.emptySet(); - } - Set<ResourceAllocation> freeL = resources.stream() - .filter(cls::isInstance) - .collect(Collectors.toSet()); - - // enumerate current allocations, removing resources - List<ResourceAllocation> allocated = allocations.stream() - .flatMap(x -> x.getResourceAllocation(link).stream()) - .filter(cls::isInstance) - .collect(Collectors.toList()); - freeL.removeAll(allocated); - return freeL; - } - - @Override - public void allocateResources(LinkResourceAllocations allocations) { - checkNotNull(allocations); - TransactionContext tx = getTxContext(); - - tx.begin(); - try { - TransactionalMap<IntentId, LinkResourceAllocations> intentAllocs = getIntentAllocs(tx); - intentAllocs.put(allocations.intentId(), allocations); - allocations.links().forEach(link -> allocateLinkResource(tx, link, allocations)); - tx.commit(); - } catch (ResourceAllocationException e) { - log.error("Exception thrown, rolling back", e); - tx.abort(); - } catch (Exception e) { - log.error("Exception thrown, rolling back", e); - tx.abort(); - throw e; - } - } - - private void allocateLinkResource(TransactionContext tx, Link link, - LinkResourceAllocations allocations) { - // requested resources - Set<ResourceAllocation> reqs = allocations.getResourceAllocation(link); - Map<ResourceType, Set<ResourceAllocation>> available = getFreeResourcesEx(tx, link); - for (ResourceAllocation req : reqs) { - Set<ResourceAllocation> avail = available.get(req.type()); - if (req instanceof BandwidthResourceAllocation) { - // check if allocation should be accepted - if (avail.isEmpty()) { - throw new ResourceAllocationException(String.format("There's no Bandwidth resource on %s?", link)); - } - BandwidthResourceAllocation bw = (BandwidthResourceAllocation) avail.iterator().next(); - double bwLeft = bw.bandwidth().toDouble(); - BandwidthResourceAllocation bwReq = ((BandwidthResourceAllocation) req); - bwLeft -= bwReq.bandwidth().toDouble(); - if (bwLeft < 0) { - throw new ResourceAllocationException( - PositionalParameterStringFormatter.format( - "Unable to allocate bandwidth for link {} " - + " requested amount is {} current allocation is {}", - link, - bwReq.bandwidth().toDouble(), - bw)); - } - } else if (req instanceof LambdaResourceAllocation) { - LambdaResourceAllocation lambdaAllocation = (LambdaResourceAllocation) req; - // check if allocation should be accepted - if (!avail.contains(req)) { - // requested lambda was not available - throw new ResourceAllocationException( - PositionalParameterStringFormatter.format( - "Unable to allocate lambda for link {} lambda is {}", - link, - lambdaAllocation.lambda().toInt())); - } - } else if (req instanceof MplsLabelResourceAllocation) { - MplsLabelResourceAllocation mplsAllocation = (MplsLabelResourceAllocation) req; - if (!avail.contains(req)) { - throw new ResourceAllocationException( - PositionalParameterStringFormatter - .format("Unable to allocate MPLS label for link " - + "{} MPLS label is {}", - link, - mplsAllocation - .mplsLabel() - .toString())); - } - } - } - // all requests allocatable => add allocation - final LinkKey linkKey = LinkKey.linkKey(link); - TransactionalMap<LinkKey, List<LinkResourceAllocations>> linkAllocs = getLinkAllocs(tx); - List<LinkResourceAllocations> before = linkAllocs.get(linkKey); - if (before == null) { - List<LinkResourceAllocations> after = new ArrayList<>(); - after.add(allocations); - linkAllocs.putIfAbsent(linkKey, after); - } else { - boolean overlapped = before.stream() - .flatMap(x -> x.getResourceAllocation(link).stream()) - .anyMatch(x -> allocations.getResourceAllocation(link).contains(x)); - if (overlapped) { - throw new ResourceAllocationException( - String.format("Resource allocations are overlapped between %s and %s", - before, allocations) - ); - } - List<LinkResourceAllocations> after = new ArrayList<>(before.size() + 1); - after.addAll(before); - after.add(allocations); - linkAllocs.replace(linkKey, before, after); - } - } - - @Override - public LinkResourceEvent releaseResources(LinkResourceAllocations allocations) { - checkNotNull(allocations); - - final IntentId intentId = allocations.intentId(); - final Collection<Link> links = allocations.links(); - boolean success = false; - do { - TransactionContext tx = getTxContext(); - tx.begin(); - try { - TransactionalMap<IntentId, LinkResourceAllocations> intentAllocs = getIntentAllocs(tx); - intentAllocs.remove(intentId); - - TransactionalMap<LinkKey, List<LinkResourceAllocations>> linkAllocs = getLinkAllocs(tx); - links.forEach(link -> { - final LinkKey linkId = LinkKey.linkKey(link); - - List<LinkResourceAllocations> before = linkAllocs.get(linkId); - if (before == null || before.isEmpty()) { - // something is wrong, but it is already freed - log.warn("There was no resource left to release on {}", linkId); - return; - } - List<LinkResourceAllocations> after = new ArrayList<>(before); - after.remove(allocations); - linkAllocs.replace(linkId, before, after); - }); - success = tx.commit(); - } catch (Exception e) { - log.error("Exception thrown during releaseResource {}", allocations, e); - tx.abort(); - throw e; - } - } while (!success); - - // Issue events to force recompilation of intents. - final List<LinkResourceAllocations> releasedResources = ImmutableList.of(allocations); - return new LinkResourceEvent( - LinkResourceEvent.Type.ADDITIONAL_RESOURCES_AVAILABLE, - releasedResources); - - } - - @Override - public LinkResourceAllocations getAllocations(IntentId intentId) { - checkNotNull(intentId); - Versioned<LinkResourceAllocations> alloc = null; - try { - alloc = intentAllocMap.get(intentId); - } catch (Exception e) { - log.warn("Could not read resource allocation information", e); - } - return alloc == null ? null : alloc.value(); - } - - @Override - public Iterable<LinkResourceAllocations> getAllocations(Link link) { - checkNotNull(link); - TransactionContext tx = getTxContext(); - Iterable<LinkResourceAllocations> res = null; - tx.begin(); - try { - res = getAllocations(tx, link); - } finally { - tx.abort(); - } - return res == null ? Collections.emptyList() : res; - } - - @Override - public Iterable<LinkResourceAllocations> getAllocations() { - try { - Set<LinkResourceAllocations> allocs = - intentAllocMap.values().stream().map(Versioned::value).collect(Collectors.toSet()); - return ImmutableSet.copyOf(allocs); - } catch (Exception e) { - log.warn("Could not read resource allocation information", e); - } - return ImmutableSet.of(); - } - - private Iterable<LinkResourceAllocations> getAllocations(TransactionContext tx, Link link) { - checkNotNull(tx); - checkNotNull(link); - final LinkKey key = LinkKey.linkKey(link); - TransactionalMap<LinkKey, List<LinkResourceAllocations>> linkAllocs = getLinkAllocs(tx); - - List<LinkResourceAllocations> res = linkAllocs.get(key); - if (res != null) { - return res; - } - - res = linkAllocs.putIfAbsent(key, new ArrayList<>()); - if (res == null) { - return Collections.emptyList(); - } else { - return res; - } - } - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/resource/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/resource/impl/package-info.java deleted file mode 100644 index 7c30018d..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/resource/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of distributed packet store. - */ -package org.onosproject.store.resource.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/ClusterMessageSerializer.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/ClusterMessageSerializer.java deleted file mode 100644 index 76bf7984..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/ClusterMessageSerializer.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers.custom; - -import org.onosproject.cluster.NodeId; -import org.onosproject.store.cluster.messaging.ClusterMessage; -import org.onosproject.store.cluster.messaging.MessageSubject; -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -public final class ClusterMessageSerializer extends Serializer<ClusterMessage> { - - /** - * Creates a serializer for {@link ClusterMessage}. - */ - public ClusterMessageSerializer() { - // does not accept null - super(false); - } - - @Override - public void write(Kryo kryo, Output output, ClusterMessage message) { - kryo.writeClassAndObject(output, message.sender()); - kryo.writeClassAndObject(output, message.subject()); - output.writeInt(message.payload().length); - output.writeBytes(message.payload()); - } - - @Override - public ClusterMessage read(Kryo kryo, Input input, - Class<ClusterMessage> type) { - NodeId sender = (NodeId) kryo.readClassAndObject(input); - MessageSubject subject = (MessageSubject) kryo.readClassAndObject(input); - int payloadSize = input.readInt(); - byte[] payload = input.readBytes(payloadSize); - return new ClusterMessage(sender, subject, payload); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/DistributedStoreSerializers.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/DistributedStoreSerializers.java deleted file mode 100644 index 5465b9b4..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/DistributedStoreSerializers.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers.custom; - -import org.onosproject.store.impl.MastershipBasedTimestamp; -import org.onosproject.store.impl.Timestamped; -import org.onosproject.store.service.WallClockTimestamp; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onlab.util.KryoNamespace; - -public final class DistributedStoreSerializers { - - - public static final int STORE_CUSTOM_BEGIN = KryoNamespaces.BEGIN_USER_CUSTOM_ID + 10; - - /** - * KryoNamespace which can serialize ON.lab misc classes. - */ - public static final KryoNamespace STORE_COMMON = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID) - .register(Timestamped.class) - .register(new MastershipBasedTimestampSerializer(), MastershipBasedTimestamp.class) - .register(WallClockTimestamp.class) - .build(); - - // avoid instantiation - private DistributedStoreSerializers() {} -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/MastershipBasedTimestampSerializer.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/MastershipBasedTimestampSerializer.java deleted file mode 100644 index eb1b2b55..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/MastershipBasedTimestampSerializer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers.custom; - -import org.onosproject.store.impl.MastershipBasedTimestamp; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -// To be used if Timestamp ever needs to cross bundle boundary. -/** - * Kryo Serializer for {@link MastershipBasedTimestamp}. - */ -public class MastershipBasedTimestampSerializer extends Serializer<MastershipBasedTimestamp> { - - /** - * Creates a serializer for {@link MastershipBasedTimestamp}. - */ - public MastershipBasedTimestampSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, MastershipBasedTimestamp object) { - output.writeLong(object.termNumber()); - output.writeLong(object.sequenceNumber()); - } - - @Override - public MastershipBasedTimestamp read(Kryo kryo, Input input, Class<MastershipBasedTimestamp> type) { - final long term = input.readLong(); - final long sequence = input.readLong(); - return new MastershipBasedTimestamp(term, sequence); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/MessageSubjectSerializer.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/MessageSubjectSerializer.java deleted file mode 100644 index 7ddee1b9..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/MessageSubjectSerializer.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers.custom; - -import org.onosproject.store.cluster.messaging.MessageSubject; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -public final class MessageSubjectSerializer extends Serializer<MessageSubject> { - - /** - * Creates a serializer for {@link MessageSubject}. - */ - public MessageSubjectSerializer() { - // non-null, immutable - super(false, true); - } - - - @Override - public void write(Kryo kryo, Output output, MessageSubject object) { - output.writeString(object.value()); - } - - @Override - public MessageSubject read(Kryo kryo, Input input, - Class<MessageSubject> type) { - return new MessageSubject(input.readString()); - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/package-info.java deleted file mode 100644 index 5cd4bee6..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/serializers/custom/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Cluster messaging and distributed store serializers. - */ -//FIXME what is the right name for this package? -//FIXME can this be moved to onos-core-serializers? -package org.onosproject.store.serializers.custom; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/statistic/impl/DistributedFlowStatisticStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/statistic/impl/DistributedFlowStatisticStore.java deleted file mode 100644 index 0cd4a831..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/statistic/impl/DistributedFlowStatisticStore.java +++ /dev/null @@ -1,289 +0,0 @@ -/*
- * Copyright 2015 Open Networking Laboratory
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.store.statistic.impl;
-
-import com.google.common.base.Objects;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.Service;
-import org.onlab.util.KryoNamespace;
-import org.onlab.util.Tools;
-import org.onosproject.cluster.ClusterService;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.Instructions;
-import org.onosproject.net.statistic.FlowStatisticStore;
-import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.serializers.KryoSerializer;
-import org.slf4j.Logger;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.store.statistic.impl.StatisticStoreMessageSubjects.GET_CURRENT;
-import static org.onosproject.store.statistic.impl.StatisticStoreMessageSubjects.GET_PREVIOUS;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Maintains flow statistics using RPC calls to collect stats from remote instances
- * on demand.
- */
-@Component(immediate = true)
-@Service
-public class DistributedFlowStatisticStore implements FlowStatisticStore {
- private final Logger log = getLogger(getClass());
-
- // TODO: Make configurable.
- private static final int MESSAGE_HANDLER_THREAD_POOL_SIZE = 4;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected MastershipService mastershipService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ClusterCommunicationService clusterCommunicator;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ClusterService clusterService;
-
- private Map<ConnectPoint, Set<FlowEntry>> previous =
- new ConcurrentHashMap<>();
-
- private Map<ConnectPoint, Set<FlowEntry>> current =
- new ConcurrentHashMap<>();
-
- protected static final KryoSerializer SERIALIZER = new KryoSerializer() {
- @Override
- protected void setupKryoPool() {
- serializerPool = KryoNamespace.newBuilder()
- .register(KryoNamespaces.API)
- .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
- // register this store specific classes here
- .build();
- }
- };
-
- private NodeId local;
- private ExecutorService messageHandlingExecutor;
-
- private static final long STATISTIC_STORE_TIMEOUT_MILLIS = 3000;
-
- @Activate
- public void activate() {
- local = clusterService.getLocalNode().id();
-
- messageHandlingExecutor = Executors.newFixedThreadPool(
- MESSAGE_HANDLER_THREAD_POOL_SIZE,
- groupedThreads("onos/store/statistic", "message-handlers"));
-
- clusterCommunicator.addSubscriber(
- GET_CURRENT, SERIALIZER::decode, this::getCurrentStatisticInternal, SERIALIZER::encode,
- messageHandlingExecutor);
-
- clusterCommunicator.addSubscriber(
- GET_CURRENT, SERIALIZER::decode, this::getPreviousStatisticInternal, SERIALIZER::encode,
- messageHandlingExecutor);
-
- log.info("Started");
- }
-
- @Deactivate
- public void deactivate() {
- clusterCommunicator.removeSubscriber(GET_PREVIOUS);
- clusterCommunicator.removeSubscriber(GET_CURRENT);
- messageHandlingExecutor.shutdown();
- log.info("Stopped");
- }
-
- @Override
- public synchronized void removeFlowStatistic(FlowRule rule) {
- ConnectPoint cp = buildConnectPoint(rule);
- if (cp == null) {
- return;
- }
-
- // remove this rule if present from current map
- current.computeIfPresent(cp, (c, e) -> { e.remove(rule); return e; });
-
- // remove this on if present from previous map
- previous.computeIfPresent(cp, (c, e) -> { e.remove(rule); return e; });
- }
-
- @Override
- public synchronized void addFlowStatistic(FlowEntry rule) {
- ConnectPoint cp = buildConnectPoint(rule);
- if (cp == null) {
- return;
- }
-
- // create one if absent and add this rule
- current.putIfAbsent(cp, new HashSet<>());
- current.computeIfPresent(cp, (c, e) -> { e.add(rule); return e; });
-
- // remove previous one if present
- previous.computeIfPresent(cp, (c, e) -> { e.remove(rule); return e; });
- }
-
- public synchronized void updateFlowStatistic(FlowEntry rule) {
- ConnectPoint cp = buildConnectPoint(rule);
- if (cp == null) {
- return;
- }
-
- Set<FlowEntry> curr = current.get(cp);
- if (curr == null) {
- addFlowStatistic(rule);
- } else {
- Optional<FlowEntry> f = curr.stream().filter(c -> rule.equals(c)).
- findAny();
- if (f.isPresent() && rule.bytes() < f.get().bytes()) {
- log.debug("DistributedFlowStatisticStore:updateFlowStatistic():" +
- " Invalid Flow Update! Will be removed!!" +
- " curr flowId=" + Long.toHexString(rule.id().value()) +
- ", prev flowId=" + Long.toHexString(f.get().id().value()) +
- ", curr bytes=" + rule.bytes() + ", prev bytes=" + f.get().bytes() +
- ", curr life=" + rule.life() + ", prev life=" + f.get().life() +
- ", curr lastSeen=" + rule.lastSeen() + ", prev lastSeen=" + f.get().lastSeen());
- // something is wrong! invalid flow entry, so delete it
- removeFlowStatistic(rule);
- return;
- }
- Set<FlowEntry> prev = previous.get(cp);
- if (prev == null) {
- prev = new HashSet<>();
- previous.put(cp, prev);
- }
-
- // previous one is exist
- if (f.isPresent()) {
- // remove old one and add new one
- prev.remove(rule);
- if (!prev.add(f.get())) {
- log.debug("DistributedFlowStatisticStore:updateFlowStatistic():" +
- " flowId={}, add failed into previous.",
- Long.toHexString(rule.id().value()));
- }
- }
-
- // remove old one and add new one
- curr.remove(rule);
- if (!curr.add(rule)) {
- log.debug("DistributedFlowStatisticStore:updateFlowStatistic():" +
- " flowId={}, add failed into current.",
- Long.toHexString(rule.id().value()));
- }
- }
- }
-
- @Override
- public Set<FlowEntry> getCurrentFlowStatistic(ConnectPoint connectPoint) {
- final DeviceId deviceId = connectPoint.deviceId();
-
- NodeId master = mastershipService.getMasterFor(deviceId);
- if (master == null) {
- log.warn("No master for {}", deviceId);
- return Collections.emptySet();
- }
-
- if (Objects.equal(local, master)) {
- return getCurrentStatisticInternal(connectPoint);
- } else {
- return Tools.futureGetOrElse(clusterCommunicator.sendAndReceive(
- connectPoint,
- GET_CURRENT,
- SERIALIZER::encode,
- SERIALIZER::decode,
- master),
- STATISTIC_STORE_TIMEOUT_MILLIS,
- TimeUnit.MILLISECONDS,
- Collections.emptySet());
- }
- }
-
- private synchronized Set<FlowEntry> getCurrentStatisticInternal(ConnectPoint connectPoint) {
- return current.get(connectPoint);
- }
-
- @Override
- public Set<FlowEntry> getPreviousFlowStatistic(ConnectPoint connectPoint) {
- final DeviceId deviceId = connectPoint.deviceId();
-
- NodeId master = mastershipService.getMasterFor(deviceId);
- if (master == null) {
- log.warn("No master for {}", deviceId);
- return Collections.emptySet();
- }
-
- if (Objects.equal(local, master)) {
- return getPreviousStatisticInternal(connectPoint);
- } else {
- return Tools.futureGetOrElse(clusterCommunicator.sendAndReceive(
- connectPoint,
- GET_PREVIOUS,
- SERIALIZER::encode,
- SERIALIZER::decode,
- master),
- STATISTIC_STORE_TIMEOUT_MILLIS,
- TimeUnit.MILLISECONDS,
- Collections.emptySet());
- }
- }
-
- private synchronized Set<FlowEntry> getPreviousStatisticInternal(ConnectPoint connectPoint) {
- return previous.get(connectPoint);
- }
-
- private ConnectPoint buildConnectPoint(FlowRule rule) {
- PortNumber port = getOutput(rule);
-
- if (port == null) {
- return null;
- }
- ConnectPoint cp = new ConnectPoint(rule.deviceId(), port);
- return cp;
- }
-
- private PortNumber getOutput(FlowRule rule) {
- for (Instruction i : rule.treatment().allInstructions()) {
- if (i.type() == Instruction.Type.OUTPUT) {
- Instructions.OutputInstruction out = (Instructions.OutputInstruction) i;
- return out.port();
- }
- if (i.type() == Instruction.Type.DROP) {
- return PortNumber.P0;
- }
- }
- return null;
- }
-}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/statistic/impl/DistributedStatisticStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/statistic/impl/DistributedStatisticStore.java deleted file mode 100644 index 35bdad14..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/statistic/impl/DistributedStatisticStore.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.statistic.impl; - -import com.google.common.collect.Sets; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onlab.util.Tools; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.NodeId; -import org.onosproject.mastership.MastershipService; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.DeviceId; -import org.onosproject.net.PortNumber; -import org.onosproject.net.flow.FlowEntry; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.instructions.Instruction; -import org.onosproject.net.flow.instructions.Instructions; -import org.onosproject.net.statistic.StatisticStore; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.serializers.KryoSerializer; -import org.slf4j.Logger; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.onlab.util.Tools.groupedThreads; -import static org.onosproject.store.statistic.impl.StatisticStoreMessageSubjects.GET_CURRENT; -import static org.onosproject.store.statistic.impl.StatisticStoreMessageSubjects.GET_PREVIOUS; -import static org.slf4j.LoggerFactory.getLogger; - - -/** - * Maintains statistics using RPC calls to collect stats from remote instances - * on demand. - */ -@Component(immediate = true) -@Service -public class DistributedStatisticStore implements StatisticStore { - - private final Logger log = getLogger(getClass()); - - // TODO: Make configurable. - private static final int MESSAGE_HANDLER_THREAD_POOL_SIZE = 4; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipService mastershipService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterCommunicationService clusterCommunicator; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - private Map<ConnectPoint, InternalStatisticRepresentation> representations = - new ConcurrentHashMap<>(); - - private Map<ConnectPoint, Set<FlowEntry>> previous = - new ConcurrentHashMap<>(); - - private Map<ConnectPoint, Set<FlowEntry>> current = - new ConcurrentHashMap<>(); - - protected static final KryoSerializer SERIALIZER = new KryoSerializer() { - @Override - protected void setupKryoPool() { - serializerPool = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID) - // register this store specific classes here - .build(); - } - }; - - private ExecutorService messageHandlingExecutor; - - private static final long STATISTIC_STORE_TIMEOUT_MILLIS = 3000; - - @Activate - public void activate() { - - messageHandlingExecutor = Executors.newFixedThreadPool( - MESSAGE_HANDLER_THREAD_POOL_SIZE, - groupedThreads("onos/store/statistic", "message-handlers")); - - clusterCommunicator.<ConnectPoint, Set<FlowEntry>>addSubscriber(GET_CURRENT, - SERIALIZER::decode, - this::getCurrentStatisticInternal, - SERIALIZER::encode, - messageHandlingExecutor); - - clusterCommunicator.<ConnectPoint, Set<FlowEntry>>addSubscriber(GET_PREVIOUS, - SERIALIZER::decode, - this::getPreviousStatisticInternal, - SERIALIZER::encode, - messageHandlingExecutor); - - log.info("Started"); - } - - @Deactivate - public void deactivate() { - clusterCommunicator.removeSubscriber(GET_PREVIOUS); - clusterCommunicator.removeSubscriber(GET_CURRENT); - messageHandlingExecutor.shutdown(); - log.info("Stopped"); - } - - @Override - public void prepareForStatistics(FlowRule rule) { - ConnectPoint cp = buildConnectPoint(rule); - if (cp == null) { - return; - } - InternalStatisticRepresentation rep; - synchronized (representations) { - rep = getOrCreateRepresentation(cp); - } - rep.prepare(); - } - - @Override - public synchronized void removeFromStatistics(FlowRule rule) { - ConnectPoint cp = buildConnectPoint(rule); - if (cp == null) { - return; - } - InternalStatisticRepresentation rep = representations.get(cp); - if (rep != null && rep.remove(rule)) { - updatePublishedStats(cp, Collections.emptySet()); - } - Set<FlowEntry> values = current.get(cp); - if (values != null) { - values.remove(rule); - } - values = previous.get(cp); - if (values != null) { - values.remove(rule); - } - - } - - @Override - public void addOrUpdateStatistic(FlowEntry rule) { - ConnectPoint cp = buildConnectPoint(rule); - if (cp == null) { - return; - } - InternalStatisticRepresentation rep = representations.get(cp); - if (rep != null && rep.submit(rule)) { - updatePublishedStats(cp, rep.get()); - } - } - - private synchronized void updatePublishedStats(ConnectPoint cp, - Set<FlowEntry> flowEntries) { - Set<FlowEntry> curr = current.get(cp); - if (curr == null) { - curr = new HashSet<>(); - } - previous.put(cp, curr); - current.put(cp, flowEntries); - - } - - @Override - public Set<FlowEntry> getCurrentStatistic(ConnectPoint connectPoint) { - final DeviceId deviceId = connectPoint.deviceId(); - NodeId master = mastershipService.getMasterFor(deviceId); - if (master == null) { - log.warn("No master for {}", deviceId); - return Collections.emptySet(); - } - if (master.equals(clusterService.getLocalNode().id())) { - return getCurrentStatisticInternal(connectPoint); - } else { - return Tools.futureGetOrElse(clusterCommunicator.sendAndReceive( - connectPoint, - GET_CURRENT, - SERIALIZER::encode, - SERIALIZER::decode, - master), - STATISTIC_STORE_TIMEOUT_MILLIS, - TimeUnit.MILLISECONDS, - Collections.emptySet()); - } - - } - - private synchronized Set<FlowEntry> getCurrentStatisticInternal(ConnectPoint connectPoint) { - return current.get(connectPoint); - } - - @Override - public Set<FlowEntry> getPreviousStatistic(ConnectPoint connectPoint) { - final DeviceId deviceId = connectPoint.deviceId(); - NodeId master = mastershipService.getMasterFor(deviceId); - if (master == null) { - log.warn("No master for {}", deviceId); - return Collections.emptySet(); - } - if (master.equals(clusterService.getLocalNode().id())) { - return getPreviousStatisticInternal(connectPoint); - } else { - return Tools.futureGetOrElse(clusterCommunicator.sendAndReceive( - connectPoint, - GET_PREVIOUS, - SERIALIZER::encode, - SERIALIZER::decode, - master), - STATISTIC_STORE_TIMEOUT_MILLIS, - TimeUnit.MILLISECONDS, - Collections.emptySet()); - } - } - - private synchronized Set<FlowEntry> getPreviousStatisticInternal(ConnectPoint connectPoint) { - return previous.get(connectPoint); - } - - private InternalStatisticRepresentation getOrCreateRepresentation(ConnectPoint cp) { - - if (representations.containsKey(cp)) { - return representations.get(cp); - } else { - InternalStatisticRepresentation rep = new InternalStatisticRepresentation(); - representations.put(cp, rep); - return rep; - } - - } - - private ConnectPoint buildConnectPoint(FlowRule rule) { - PortNumber port = getOutput(rule); - - if (port == null) { - return null; - } - ConnectPoint cp = new ConnectPoint(rule.deviceId(), port); - return cp; - } - - private PortNumber getOutput(FlowRule rule) { - for (Instruction i : rule.treatment().allInstructions()) { - if (i.type() == Instruction.Type.OUTPUT) { - Instructions.OutputInstruction out = (Instructions.OutputInstruction) i; - return out.port(); - } - if (i.type() == Instruction.Type.DROP) { - return PortNumber.P0; - } - } - return null; - } - - private class InternalStatisticRepresentation { - - private final AtomicInteger counter = new AtomicInteger(0); - private final Set<FlowEntry> rules = new HashSet<>(); - - public void prepare() { - counter.incrementAndGet(); - } - - public synchronized boolean remove(FlowRule rule) { - rules.remove(rule); - return counter.decrementAndGet() == 0; - } - - public synchronized boolean submit(FlowEntry rule) { - if (rules.contains(rule)) { - rules.remove(rule); - } - rules.add(rule); - if (counter.get() == 0) { - return true; - } else { - return counter.decrementAndGet() == 0; - } - } - - public synchronized Set<FlowEntry> get() { - counter.set(rules.size()); - return Sets.newHashSet(rules); - } - - - } - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/statistic/impl/StatisticStoreMessageSubjects.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/statistic/impl/StatisticStoreMessageSubjects.java deleted file mode 100644 index cc03c302..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/statistic/impl/StatisticStoreMessageSubjects.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.statistic.impl; - -import org.onosproject.store.cluster.messaging.MessageSubject; - -/** - * MessageSubjects used by DistributedStatisticStore peer-peer communication. - */ -public final class StatisticStoreMessageSubjects { - private StatisticStoreMessageSubjects() {} - public static final MessageSubject GET_CURRENT = - new MessageSubject("peer-return-current"); - public static final MessageSubject GET_PREVIOUS = - new MessageSubject("peer-return-previous"); - -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/statistic/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/statistic/impl/package-info.java deleted file mode 100644 index 49436a9f..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/statistic/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of the statistic store. - */ -package org.onosproject.store.statistic.impl; diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java deleted file mode 100644 index 2641635d..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.topology.impl; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Modified; -import org.apache.felix.scr.annotations.Property; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.graph.GraphPathSearch; -import org.onlab.util.KryoNamespace; -import org.onosproject.cfg.ComponentConfigService; -import org.onosproject.common.DefaultTopology; -import org.onosproject.event.Event; -import org.onosproject.mastership.MastershipService; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.Device; -import org.onosproject.net.DeviceId; -import org.onosproject.net.DisjointPath; -import org.onosproject.net.Link; -import org.onosproject.net.Path; -import org.onosproject.net.device.DeviceService; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.net.topology.ClusterId; -import org.onosproject.net.topology.DefaultGraphDescription; -import org.onosproject.net.topology.GeoDistanceLinkWeight; -import org.onosproject.net.topology.GraphDescription; -import org.onosproject.net.topology.LinkWeight; -import org.onosproject.net.topology.MetricLinkWeight; -import org.onosproject.net.topology.PathAdminService; -import org.onosproject.net.topology.Topology; -import org.onosproject.net.topology.TopologyCluster; -import org.onosproject.net.topology.TopologyEdge; -import org.onosproject.net.topology.TopologyEvent; -import org.onosproject.net.topology.TopologyGraph; -import org.onosproject.net.topology.TopologyStore; -import org.onosproject.net.topology.TopologyStoreDelegate; -import org.onosproject.net.topology.TopologyVertex; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.EventuallyConsistentMapEvent; -import org.onosproject.store.service.EventuallyConsistentMapListener; -import org.onosproject.store.service.LogicalClockService; -import org.onosproject.store.service.StorageService; -import org.osgi.service.component.ComponentContext; -import org.slf4j.Logger; - -import java.util.Collections; -import java.util.Dictionary; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkArgument; -import static org.onlab.util.Tools.get; -import static org.onlab.util.Tools.isNullOrEmpty; -import static org.onosproject.net.topology.TopologyEvent.Type.TOPOLOGY_CHANGED; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Manages inventory of topology snapshots using trivial in-memory - * structures implementation. - * <p> - * Note: This component is not distributed per-se. It runs on every - * instance and feeds off of other distributed stores. - */ -@Component(immediate = true) -@Service -public class DistributedTopologyStore - extends AbstractStore<TopologyEvent, TopologyStoreDelegate> - implements TopologyStore, PathAdminService { - - private final Logger log = getLogger(getClass()); - - private static final String FORMAT = "Settings: linkWeightFunction={}"; - - private volatile DefaultTopology current = - new DefaultTopology(ProviderId.NONE, - new DefaultGraphDescription(0L, System.currentTimeMillis(), - Collections.<Device>emptyList(), - Collections.<Link>emptyList())); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected LogicalClockService clockService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipService mastershipService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ComponentConfigService configService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected DeviceService deviceService; - - private static final String HOP_COUNT = "hopCount"; - private static final String LINK_METRIC = "linkMetric"; - private static final String GEO_DISTANCE = "geoDistance"; - - private static final String DEFAULT_LINK_WEIGHT_FUNCTION = "hopCount"; - @Property(name = "linkWeightFunction", value = DEFAULT_LINK_WEIGHT_FUNCTION, - label = "Default link-weight function: hopCount, linkMetric, geoDistance") - private String linkWeightFunction = DEFAULT_LINK_WEIGHT_FUNCTION; - - // Cluster root to broadcast points bindings to allow convergence to - // a shared broadcast tree; node that is the master of the cluster root - // is the primary. - private EventuallyConsistentMap<DeviceId, Set<ConnectPoint>> broadcastPoints; - - private EventuallyConsistentMapListener<DeviceId, Set<ConnectPoint>> listener = - new InternalBroadcastPointListener(); - - @Activate - protected void activate() { - configService.registerProperties(getClass()); - KryoNamespace.Builder hostSerializer = KryoNamespace.newBuilder() - .register(KryoNamespaces.API); - - broadcastPoints = storageService.<DeviceId, Set<ConnectPoint>>eventuallyConsistentMapBuilder() - .withName("onos-broadcast-trees") - .withSerializer(hostSerializer) - .withTimestampProvider((k, v) -> clockService.getTimestamp()) - .build(); - broadcastPoints.addListener(listener); - log.info("Started"); - } - - @Deactivate - protected void deactivate() { - configService.unregisterProperties(getClass(), false); - broadcastPoints.removeListener(listener); - broadcastPoints.destroy(); - log.info("Stopped"); - } - - @Modified - protected void modified(ComponentContext context) { - Dictionary<?, ?> properties = context.getProperties(); - - String newLinkWeightFunction = get(properties, "linkWeightFunction"); - if (newLinkWeightFunction != null && - !Objects.equals(newLinkWeightFunction, linkWeightFunction)) { - linkWeightFunction = newLinkWeightFunction; - LinkWeight weight = linkWeightFunction.equals(LINK_METRIC) ? - new MetricLinkWeight() : - linkWeightFunction.equals(GEO_DISTANCE) ? - new GeoDistanceLinkWeight(deviceService) : null; - setDefaultLinkWeight(weight); - } - log.info(FORMAT, linkWeightFunction); - } - - @Override - public Topology currentTopology() { - return current; - } - - @Override - public boolean isLatest(Topology topology) { - // Topology is current only if it is the same as our current topology - return topology == current; - } - - @Override - public TopologyGraph getGraph(Topology topology) { - return defaultTopology(topology).getGraph(); - } - - @Override - public Set<TopologyCluster> getClusters(Topology topology) { - return defaultTopology(topology).getClusters(); - } - - @Override - public TopologyCluster getCluster(Topology topology, ClusterId clusterId) { - return defaultTopology(topology).getCluster(clusterId); - } - - @Override - public Set<DeviceId> getClusterDevices(Topology topology, TopologyCluster cluster) { - return defaultTopology(topology).getClusterDevices(cluster); - } - - @Override - public Set<Link> getClusterLinks(Topology topology, TopologyCluster cluster) { - return defaultTopology(topology).getClusterLinks(cluster); - } - - @Override - public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) { - return defaultTopology(topology).getPaths(src, dst); - } - - @Override - public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, - LinkWeight weight) { - return defaultTopology(topology).getPaths(src, dst, weight); - } - - @Override - public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst) { - return defaultTopology(topology).getDisjointPaths(src, dst); - } - - @Override - public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst, - LinkWeight weight) { - return defaultTopology(topology).getDisjointPaths(src, dst, weight); - } - - @Override - public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst, - Map<Link, Object> riskProfile) { - return defaultTopology(topology).getDisjointPaths(src, dst, riskProfile); - } - - @Override - public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst, - LinkWeight weight, Map<Link, Object> riskProfile) { - return defaultTopology(topology).getDisjointPaths(src, dst, weight, riskProfile); - } - - @Override - public boolean isInfrastructure(Topology topology, ConnectPoint connectPoint) { - return defaultTopology(topology).isInfrastructure(connectPoint); - } - - @Override - public boolean isBroadcastPoint(Topology topology, ConnectPoint connectPoint) { - return defaultTopology(topology).isBroadcastPoint(connectPoint); - } - - private boolean isBroadcastPoint(ConnectPoint connectPoint) { - // Any non-infrastructure, i.e. edge points are assumed to be OK. - if (!current.isInfrastructure(connectPoint)) { - return true; - } - - // Find the cluster to which the device belongs. - TopologyCluster cluster = current.getCluster(connectPoint.deviceId()); - checkArgument(cluster != null, "No cluster found for device %s", connectPoint.deviceId()); - - // If the broadcast set is null or empty, or if the point explicitly - // belongs to it, return true; - Set<ConnectPoint> points = broadcastPoints.get(cluster.root().deviceId()); - return isNullOrEmpty(points) || points.contains(connectPoint); - } - - @Override - public TopologyEvent updateTopology(ProviderId providerId, - GraphDescription graphDescription, - List<Event> reasons) { - // First off, make sure that what we're given is indeed newer than - // what we already have. - if (current != null && graphDescription.timestamp() < current.time()) { - return null; - } - - // Have the default topology construct self from the description data. - DefaultTopology newTopology = - new DefaultTopology(providerId, graphDescription, this::isBroadcastPoint); - updateBroadcastPoints(newTopology); - - // Promote the new topology to current and return a ready-to-send event. - synchronized (this) { - current = newTopology; - return new TopologyEvent(TOPOLOGY_CHANGED, current, reasons); - } - } - - private void updateBroadcastPoints(DefaultTopology topology) { - // Remove any broadcast trees rooted by devices for which we are master. - Set<DeviceId> toRemove = broadcastPoints.keySet().stream() - .filter(mastershipService::isLocalMaster) - .collect(Collectors.toSet()); - - // Update the broadcast trees rooted by devices for which we are master. - topology.getClusters().forEach(c -> { - toRemove.remove(c.root().deviceId()); - if (mastershipService.isLocalMaster(c.root().deviceId())) { - broadcastPoints.put(c.root().deviceId(), - topology.broadcastPoints(c.id())); - } - }); - - toRemove.forEach(broadcastPoints::remove); - } - - // Validates the specified topology and returns it as a default - private DefaultTopology defaultTopology(Topology topology) { - checkArgument(topology instanceof DefaultTopology, - "Topology class %s not supported", topology.getClass()); - return (DefaultTopology) topology; - } - - @Override - public void setDefaultLinkWeight(LinkWeight linkWeight) { - DefaultTopology.setDefaultLinkWeight(linkWeight); - } - - @Override - public void setDefaultGraphPathSearch(GraphPathSearch<TopologyVertex, TopologyEdge> graphPathSearch) { - DefaultTopology.setDefaultGraphPathSearch(graphPathSearch); - } - - private class InternalBroadcastPointListener - implements EventuallyConsistentMapListener<DeviceId, Set<ConnectPoint>> { - @Override - public void event(EventuallyConsistentMapEvent<DeviceId, Set<ConnectPoint>> event) { - if (event.type() == EventuallyConsistentMapEvent.Type.PUT) { - if (!event.value().isEmpty()) { - log.info("Cluster rooted at {} has {} broadcast-points; #{}", - event.key(), event.value().size(), event.value().hashCode()); - } - } - } - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/topology/impl/PathKey.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/topology/impl/PathKey.java deleted file mode 100644 index f1c2bdc5..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/topology/impl/PathKey.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.topology.impl; - -import org.onosproject.net.DeviceId; - -import java.util.Objects; - -/** - * Key for filing pre-computed paths between source and destination devices. - */ -class PathKey { - private final DeviceId src; - private final DeviceId dst; - - /** - * Creates a path key from the given source/dest pair. - * @param src source device - * @param dst destination device - */ - PathKey(DeviceId src, DeviceId dst) { - this.src = src; - this.dst = dst; - } - - @Override - public int hashCode() { - return Objects.hash(src, dst); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof PathKey) { - final PathKey other = (PathKey) obj; - return Objects.equals(this.src, other.src) && Objects.equals(this.dst, other.dst); - } - return false; - } -} diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/topology/impl/package-info.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/topology/impl/package-info.java deleted file mode 100644 index d1590793..00000000 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/topology/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementation of distributed topology store using p2p synchronization protocol. - */ -package org.onosproject.store.topology.impl; diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/cluster/StaticClusterService.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/cluster/StaticClusterService.java deleted file mode 100644 index faaf2978..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/cluster/StaticClusterService.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.cluster; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import org.onosproject.cluster.ClusterServiceAdapter; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.ControllerNode.State; -import org.onosproject.cluster.NodeId; - -import com.google.common.collect.Sets; - -public abstract class StaticClusterService extends ClusterServiceAdapter { - - protected final Map<NodeId, ControllerNode> nodes = new HashMap<>(); - protected final Map<NodeId, ControllerNode.State> nodeStates = new HashMap<>(); - protected ControllerNode localNode; - - @Override - public ControllerNode getLocalNode() { - return localNode; - } - - @Override - public Set<ControllerNode> getNodes() { - return Sets.newHashSet(nodes.values()); - } - - @Override - public ControllerNode getNode(NodeId nodeId) { - return nodes.get(nodeId); - } - - @Override - public State getState(NodeId nodeId) { - return nodeStates.get(nodeId); - } - -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/cluster/messaging/impl/ClusterCommunicationManagerTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/cluster/messaging/impl/ClusterCommunicationManagerTest.java deleted file mode 100644 index daeaa12c..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/cluster/messaging/impl/ClusterCommunicationManagerTest.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.cluster.messaging.impl; - -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.onosproject.cluster.DefaultControllerNode; -import org.onosproject.cluster.NodeId; -import org.onosproject.store.cluster.impl.ClusterNodesDelegate; -import org.onlab.packet.IpAddress; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * Tests of the cluster communication manager. - */ -public class ClusterCommunicationManagerTest { - - private static final NodeId N1 = new NodeId("n1"); - private static final NodeId N2 = new NodeId("n2"); - - private static final int P1 = 9881; - private static final int P2 = 9882; - - private static final IpAddress IP = IpAddress.valueOf("127.0.0.1"); - - private ClusterCommunicationManager ccm1; - private ClusterCommunicationManager ccm2; - - private TestDelegate cnd1 = new TestDelegate(); - private TestDelegate cnd2 = new TestDelegate(); - - private DefaultControllerNode node1 = new DefaultControllerNode(N1, IP, P1); - private DefaultControllerNode node2 = new DefaultControllerNode(N2, IP, P2); - - @Before - public void setUp() throws Exception { - - NettyMessagingManager messagingService = new NettyMessagingManager(); - messagingService.activate(); - - ccm1 = new ClusterCommunicationManager(); - ccm1.activate(); - - ccm2 = new ClusterCommunicationManager(); - ccm2.activate(); - -// ccm1.initialize(node1, cnd1); -// ccm2.initialize(node2, cnd2); - } - - @After - public void tearDown() { - ccm1.deactivate(); - ccm2.deactivate(); - } - - @Ignore("FIXME: failing randomly?") - @Test - public void connect() throws Exception { - cnd1.latch = new CountDownLatch(1); - cnd2.latch = new CountDownLatch(1); - -// ccm1.addNode(node2); - validateDelegateEvent(cnd1, Op.DETECTED, node2.id()); - validateDelegateEvent(cnd2, Op.DETECTED, node1.id()); - } - - @Test - @Ignore - public void disconnect() throws Exception { - cnd1.latch = new CountDownLatch(1); - cnd2.latch = new CountDownLatch(1); - -// ccm1.addNode(node2); - validateDelegateEvent(cnd1, Op.DETECTED, node2.id()); - validateDelegateEvent(cnd2, Op.DETECTED, node1.id()); - - cnd1.latch = new CountDownLatch(1); - cnd2.latch = new CountDownLatch(1); - ccm1.deactivate(); -// -// validateDelegateEvent(cnd2, Op.VANISHED, node1.id()); - } - - private void validateDelegateEvent(TestDelegate delegate, Op op, NodeId nodeId) - throws InterruptedException { - assertTrue("did not connect in time", delegate.latch.await(2500, TimeUnit.MILLISECONDS)); - assertEquals("incorrect event", op, delegate.op); - assertEquals("incorrect event node", nodeId, delegate.nodeId); - } - - enum Op { DETECTED, VANISHED, REMOVED } - - private class TestDelegate implements ClusterNodesDelegate { - - Op op; - CountDownLatch latch; - NodeId nodeId; - - @Override - public DefaultControllerNode nodeDetected(NodeId nodeId, IpAddress ip, int tcpPort) { - latch(nodeId, Op.DETECTED); - return new DefaultControllerNode(nodeId, ip, tcpPort); - } - - @Override - public void nodeVanished(NodeId nodeId) { - latch(nodeId, Op.VANISHED); - } - - @Override - public void nodeRemoved(NodeId nodeId) { - latch(nodeId, Op.REMOVED); - } - - private void latch(NodeId nodeId, Op op) { - this.op = op; - this.nodeId = nodeId; - latch.countDown(); - } - } -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/config/impl/DistributedNetworkConfigStoreTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/config/impl/DistributedNetworkConfigStoreTest.java deleted file mode 100644 index 06fe7b37..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/config/impl/DistributedNetworkConfigStoreTest.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.config.impl; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.onosproject.net.config.Config; -import org.onosproject.net.config.ConfigFactory; -import org.onosproject.net.config.SubjectFactory; -import org.onosproject.store.service.TestStorageService; - -import com.fasterxml.jackson.databind.ObjectMapper; - -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; - -public class DistributedNetworkConfigStoreTest { - private DistributedNetworkConfigStore configStore; - - /** - * Sets up the config store and the storage service test harness. - */ - @Before - public void setUp() { - configStore = new DistributedNetworkConfigStore(); - configStore.storageService = new TestStorageService(); - configStore.setDelegate(event -> { }); - configStore.activate(); - } - - /** - * Tears down the config store. - */ - @After - public void tearDown() { - configStore.deactivate(); - } - - /** - * Config class for testing. - */ - public class BasicConfig extends Config<String> { } - - /** - * Config factory class for testing. - */ - public class MockConfigFactory extends ConfigFactory<String, BasicConfig> { - protected MockConfigFactory(SubjectFactory<String> subjectFactory, - Class<BasicConfig> configClass, String configKey) { - super(subjectFactory, configClass, configKey); - } - @Override - public BasicConfig createConfig() { - return new BasicConfig(); - } - } - - /** - * Tests creation, query and removal of a config. - */ - @Test - public void testCreateConfig() { - configStore.addConfigFactory(new MockConfigFactory(null, BasicConfig.class, "config1")); - - configStore.createConfig("config1", BasicConfig.class); - assertThat(configStore.getConfigClasses("config1"), hasSize(1)); - assertThat(configStore.getSubjects(String.class, BasicConfig.class), hasSize(1)); - assertThat(configStore.getSubjects(String.class), hasSize(1)); - - BasicConfig queried = configStore.getConfig("config1", BasicConfig.class); - assertThat(queried, notNullValue()); - - configStore.clearConfig("config1", BasicConfig.class); - assertThat(configStore.getConfigClasses("config1"), hasSize(0)); - assertThat(configStore.getSubjects(String.class, BasicConfig.class), hasSize(0)); - assertThat(configStore.getSubjects(String.class), hasSize(0)); - - BasicConfig queriedAfterClear = configStore.getConfig("config1", BasicConfig.class); - assertThat(queriedAfterClear, nullValue()); - } - - /** - * Tests creation, query and removal of a factory. - */ - @Test - public void testCreateFactory() { - MockConfigFactory mockFactory = new MockConfigFactory(null, BasicConfig.class, "config1"); - - assertThat(configStore.getConfigFactory(BasicConfig.class), nullValue()); - - configStore.addConfigFactory(mockFactory); - assertThat(configStore.getConfigFactory(BasicConfig.class), is(mockFactory)); - - configStore.removeConfigFactory(mockFactory); - assertThat(configStore.getConfigFactory(BasicConfig.class), nullValue()); - } - - /** - * Tests applying a config. - */ - @Test - public void testApplyConfig() { - configStore.addConfigFactory(new MockConfigFactory(null, BasicConfig.class, "config1")); - - configStore.applyConfig("config1", BasicConfig.class, new ObjectMapper().createObjectNode()); - assertThat(configStore.getConfigClasses("config1"), hasSize(1)); - assertThat(configStore.getSubjects(String.class, BasicConfig.class), hasSize(1)); - assertThat(configStore.getSubjects(String.class), hasSize(1)); - } -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMapTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMapTest.java deleted file mode 100644 index 3f6402c5..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMapTest.java +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import static java.util.Collections.unmodifiableCollection; -import static java.util.Collections.unmodifiableSet; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.*; - -import java.util.Collection; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Consumer; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.DefaultApplicationId; -import org.onosproject.store.service.Serializer; -import org.onosproject.store.service.Transaction; -import org.onosproject.store.service.Versioned; - -import com.google.common.base.MoreObjects; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import net.kuujo.copycat.Task; -import net.kuujo.copycat.cluster.Cluster; -import net.kuujo.copycat.resource.ResourceState; - -/** - * - */ -public class DefaultAsyncConsistentMapTest { - - private static final ApplicationId APP_ID = new DefaultApplicationId(42, "what"); - - private static final TestData KEY1A = new TestData("One", "a"); - private static final TestData KEY1B = new TestData("One", "b"); - - private static final TestData VALUE2A = new TestData("Two", "a"); - private static final TestData VALUE2B = new TestData("Two", "b"); - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testKeySet() throws Exception { - DefaultAsyncConsistentMap<TestData, TestData> map; - String name = "map_name"; - Database database = new TestDatabase(); - Serializer serializer = Serializer.forTypes(TestData.class); - - map = new DefaultAsyncConsistentMap<>(name, APP_ID, database, serializer, - false, false, false); - map.put(KEY1A, VALUE2A); - map.put(KEY1B, VALUE2A); - - Set<TestData> set = map.keySet().get(); - assertEquals("Should contain 2 keys", - 2, set.size()); - assertThat(set.contains(KEY1A), is(true)); - assertThat(set.contains(KEY1B), is(true)); - assertThat(set.contains(new TestData("One", "a")), is(true)); - } - - @Test - public void testEntrySet() throws Exception { - DefaultAsyncConsistentMap<TestData, TestData> map; - String name = "map_name"; - Database database = new TestDatabase(); - Serializer serializer = Serializer.forTypes(TestData.class); - - map = new DefaultAsyncConsistentMap<>(name, APP_ID, database, serializer, - false, false, false); - map.put(KEY1A, VALUE2A); - map.put(KEY1B, VALUE2A); - - assertEquals("Should contain 2 entry", - 2, - map.entrySet().get().size()); - } - - /** - * Object to be used as a test data. - * - * {@link Object#equals(Object)} use only part of it's fields. - * - * As a result there can be 2 instances which the - * serialized bytes are not-equal but - * {@link Object#equals(Object)}-wise they are equal. - */ - public static class TestData { - - private final String theKey; - - @SuppressWarnings("unused") - private final String notUsedForEquals; - - public TestData(String theKey, String notUsedForEquals) { - this.theKey = theKey; - this.notUsedForEquals = notUsedForEquals; - } - - @Override - public int hashCode() { - return Objects.hashCode(theKey); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof TestData) { - TestData that = (TestData) obj; - return Objects.equals(this.theKey, that.theKey); - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("theKey", theKey) - .add("notUsedForEquals", notUsedForEquals) - .toString(); - } - } - - /** - * {@link Database} implementation for testing. - * - * There is only 1 backing Map, {@code mapName} will be ignored. - */ - public class TestDatabase implements Database { - - Map<String, Versioned<byte[]>> map = new ConcurrentHashMap<>(); - - @Override - public CompletableFuture<Set<String>> maps() { - return CompletableFuture.completedFuture(ImmutableSet.of()); - } - - @Override - public CompletableFuture<Map<String, Long>> counters() { - return CompletableFuture.completedFuture(ImmutableMap.of()); - } - - @Override - public CompletableFuture<Integer> mapSize(String mapName) { - return CompletableFuture.completedFuture(map.size()); - } - - @Override - public CompletableFuture<Boolean> mapIsEmpty(String mapName) { - return CompletableFuture.completedFuture(map.isEmpty()); - } - - @Override - public CompletableFuture<Boolean> mapContainsKey(String mapName, - String key) { - return CompletableFuture.completedFuture(map.containsKey(key)); - } - - @Override - public CompletableFuture<Boolean> mapContainsValue(String mapName, - byte[] value) { - return CompletableFuture.completedFuture(map.containsValue(value)); - } - - @Override - public CompletableFuture<Versioned<byte[]>> mapGet(String mapName, - String key) { - return CompletableFuture.completedFuture(map.get(key)); - } - - @Override - public synchronized CompletableFuture<Result<UpdateResult<String, byte[]>>> mapUpdate(String mapName, - String key, - Match<byte[]> valueMatch, - Match<Long> versionMatch, - byte[] value) { - - boolean updated = false; - final Versioned<byte[]> oldValue; - final Versioned<byte[]> newValue; - - Versioned<byte[]> old = map.getOrDefault(key, new Versioned<byte[]>(null, 0)); - if (valueMatch.matches(old.value()) && versionMatch.matches(old.version())) { - updated = true; - oldValue = old; - newValue = new Versioned<>(value, old.version() + 1); - map.put(key, newValue); - } else { - updated = false; - oldValue = old; - newValue = old; - } - return CompletableFuture.completedFuture( - Result.ok(new UpdateResult<String, byte[]>(updated, - mapName, key, oldValue, newValue))); - } - - @Override - public CompletableFuture<Result<Void>> mapClear(String mapName) { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture<Set<String>> mapKeySet(String mapName) { - return CompletableFuture.completedFuture(unmodifiableSet(map.keySet())); - } - - @Override - public CompletableFuture<Collection<Versioned<byte[]>>> mapValues(String mapName) { - return CompletableFuture.completedFuture(unmodifiableCollection(map.values())); - } - - @Override - public CompletableFuture<Set<Entry<String, Versioned<byte[]>>>> mapEntrySet(String mapName) { - return CompletableFuture.completedFuture(unmodifiableSet(map.entrySet())); - } - - @Override - public CompletableFuture<Long> counterAddAndGet(String counterName, - long delta) { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture<Long> counterGetAndAdd(String counterName, - long delta) { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture<Void> counterSet(String counterName, - long value) { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture<Boolean> counterCompareAndSet(String counterName, - long expectedValue, - long update) { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture<Long> counterGet(String counterName) { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture<Long> queueSize(String queueName) { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture<Void> queuePush(String queueName, - byte[] entry) { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture<byte[]> queuePop(String queueName) { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture<byte[]> queuePeek(String queueName) { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture<CommitResponse> prepareAndCommit(Transaction transaction) { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture<Boolean> prepare(Transaction transaction) { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture<CommitResponse> commit(Transaction transaction) { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture<Boolean> rollback(Transaction transaction) { - throw new UnsupportedOperationException(); - } - - @Override - public String name() { - return "name"; - } - - @Override - public ResourceState state() { - return ResourceState.HEALTHY; - } - - @Override - public Cluster cluster() { - throw new UnsupportedOperationException(); - } - - @Override - public Database addStartupTask(Task<CompletableFuture<Void>> task) { - throw new UnsupportedOperationException(); - } - - @Override - public Database addShutdownTask(Task<CompletableFuture<Void>> task) { - throw new UnsupportedOperationException(); - } - - @Override - public CompletableFuture<Database> open() { - return CompletableFuture.completedFuture(this); - } - - @Override - public boolean isOpen() { - return true; - } - - @Override - public CompletableFuture<Void> close() { - return CompletableFuture.completedFuture(null); - } - - @Override - public boolean isClosed() { - return false; - } - - @Override - public void registerConsumer(Consumer<StateMachineUpdate> consumer) { - } - - @Override - public void unregisterConsumer(Consumer<StateMachineUpdate> consumer) { - } - } - -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/MatchTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/MatchTest.java deleted file mode 100644 index 952393aa..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/MatchTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertFalse; -import static junit.framework.TestCase.assertTrue; - -import org.junit.Test; - -import com.google.common.base.Objects; - -/** - * Unit tests for Match. - */ -public class MatchTest { - - @Test - public void testMatches() { - Match<String> m1 = Match.any(); - assertTrue(m1.matches(null)); - assertTrue(m1.matches("foo")); - assertTrue(m1.matches("bar")); - - Match<String> m2 = Match.ifNull(); - assertTrue(m2.matches(null)); - assertFalse(m2.matches("foo")); - - Match<String> m3 = Match.ifValue("foo"); - assertFalse(m3.matches(null)); - assertFalse(m3.matches("bar")); - assertTrue(m3.matches("foo")); - } - - @Test - public void testEquals() { - Match<String> m1 = Match.any(); - Match<String> m2 = Match.any(); - Match<String> m3 = Match.ifNull(); - Match<String> m4 = Match.ifValue("bar"); - assertEquals(m1, m2); - assertFalse(Objects.equal(m1, m3)); - assertFalse(Objects.equal(m3, m4)); - } - - @Test - public void testMap() { - Match<String> m1 = Match.ifNull(); - assertEquals(m1.map(s -> "bar"), Match.ifNull()); - Match<String> m2 = Match.ifValue("foo"); - Match<String> m3 = m2.map(s -> "bar"); - assertTrue(m3.matches("bar")); - } -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/ResultTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/ResultTest.java deleted file mode 100644 index 2d329d14..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/ResultTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertFalse; -import static junit.framework.TestCase.assertNull; -import static junit.framework.TestCase.assertTrue; - -import org.junit.Test; - -/** - * Unit tests for Result. - */ -public class ResultTest { - - @Test - public void testLocked() { - Result<String> r = Result.locked(); - assertFalse(r.success()); - assertNull(r.value()); - assertEquals(Result.Status.LOCKED, r.status()); - } - - @Test - public void testOk() { - Result<String> r = Result.ok("foo"); - assertTrue(r.success()); - assertEquals("foo", r.value()); - assertEquals(Result.Status.OK, r.status()); - } - - @Test - public void testEquality() { - Result<String> r1 = Result.ok("foo"); - Result<String> r2 = Result.locked(); - Result<String> r3 = Result.ok("bar"); - Result<String> r4 = Result.ok("foo"); - assertTrue(r1.equals(r4)); - assertFalse(r1.equals(r2)); - assertFalse(r1.equals(r3)); - assertFalse(r2.equals(r3)); - } -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/UpdateResultTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/UpdateResultTest.java deleted file mode 100644 index ab53710b..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/consistent/impl/UpdateResultTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.consistent.impl; - -import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertNull; -import static junit.framework.TestCase.assertTrue; - -import org.junit.Test; -import org.onosproject.store.service.MapEvent; -import org.onosproject.store.service.Versioned; - -/** - * Unit tests for UpdateResult. - */ -public class UpdateResultTest { - - @Test - public void testGetters() { - Versioned<String> oldValue = new Versioned<>("a", 1); - Versioned<String> newValue = new Versioned<>("b", 2); - UpdateResult<String, String> ur = - new UpdateResult<>(true, "foo", "k", oldValue, newValue); - - assertTrue(ur.updated()); - assertEquals("foo", ur.mapName()); - assertEquals("k", ur.key()); - assertEquals(oldValue, ur.oldValue()); - assertEquals(newValue, ur.newValue()); - } - - @Test - public void testToMapEvent() { - Versioned<String> oldValue = new Versioned<>("a", 1); - Versioned<String> newValue = new Versioned<>("b", 2); - UpdateResult<String, String> ur1 = - new UpdateResult<>(true, "foo", "k", oldValue, newValue); - MapEvent<String, String> event1 = ur1.toMapEvent(); - assertEquals(MapEvent.Type.UPDATE, event1.type()); - assertEquals("k", event1.key()); - assertEquals(newValue, event1.value()); - - UpdateResult<String, String> ur2 = - new UpdateResult<>(true, "foo", "k", null, newValue); - MapEvent<String, String> event2 = ur2.toMapEvent(); - assertEquals(MapEvent.Type.INSERT, event2.type()); - assertEquals("k", event2.key()); - assertEquals(newValue, event2.value()); - - UpdateResult<String, String> ur3 = - new UpdateResult<>(true, "foo", "k", oldValue, null); - MapEvent<String, String> event3 = ur3.toMapEvent(); - assertEquals(MapEvent.Type.REMOVE, event3.type()); - assertEquals("k", event3.key()); - assertEquals(oldValue, event3.value()); - - UpdateResult<String, String> ur4 = - new UpdateResult<>(false, "foo", "k", oldValue, oldValue); - assertNull(ur4.toMapEvent()); - } - - @Test - public void testMap() { - Versioned<String> oldValue = new Versioned<>("a", 1); - Versioned<String> newValue = new Versioned<>("b", 2); - UpdateResult<String, String> ur1 = - new UpdateResult<>(true, "foo", "k", oldValue, newValue); - UpdateResult<Integer, Integer> ur2 = ur1.map(s -> s.length(), s -> s.length()); - - assertEquals(ur2.updated(), ur1.updated()); - assertEquals(ur1.mapName(), ur2.mapName()); - assertEquals(new Integer(1), ur2.key()); - assertEquals(oldValue.map(s -> s.length()), ur2.oldValue()); - assertEquals(newValue.map(s -> s.length()), ur2.newValue()); - - UpdateResult<String, String> ur3 = - new UpdateResult<>(true, "foo", "k", null, newValue); - UpdateResult<Integer, Integer> ur4 = ur3.map(s -> s.length(), s -> s.length()); - - assertEquals(ur3.updated(), ur4.updated()); - assertEquals(ur3.mapName(), ur4.mapName()); - assertEquals(new Integer(1), ur4.key()); - assertNull(ur4.oldValue()); - assertEquals(newValue.map(s -> s.length()), ur4.newValue()); - } -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/device/impl/DeviceFragmentIdTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/device/impl/DeviceFragmentIdTest.java deleted file mode 100644 index 191b3bea..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/device/impl/DeviceFragmentIdTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import static org.onosproject.net.DeviceId.deviceId; - -import org.junit.Test; -import org.onosproject.net.DeviceId; -import org.onosproject.net.provider.ProviderId; - -import com.google.common.testing.EqualsTester; - -public class DeviceFragmentIdTest { - - private static final ProviderId PID = new ProviderId("of", "foo"); - private static final ProviderId PIDA = new ProviderId("of", "bar", true); - private static final DeviceId DID1 = deviceId("of:foo"); - private static final DeviceId DID2 = deviceId("of:bar"); - - @Test - public final void testEquals() { - - new EqualsTester() - .addEqualityGroup(new DeviceFragmentId(DID1, PID), - new DeviceFragmentId(DID1, PID)) - .addEqualityGroup(new DeviceFragmentId(DID2, PID), - new DeviceFragmentId(DID2, PID)) - .addEqualityGroup(new DeviceFragmentId(DID1, PIDA), - new DeviceFragmentId(DID1, PIDA)) - .addEqualityGroup(new DeviceFragmentId(DID2, PIDA), - new DeviceFragmentId(DID2, PIDA)) - .testEquals(); - } - -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/device/impl/GossipDeviceStoreTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/device/impl/GossipDeviceStoreTest.java deleted file mode 100644 index 5cbf360a..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/device/impl/GossipDeviceStoreTest.java +++ /dev/null @@ -1,908 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; - -import org.easymock.Capture; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; -import org.onlab.packet.ChassisId; -import org.onlab.packet.IpAddress; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.DefaultControllerNode; -import org.onosproject.cluster.NodeId; -import org.onosproject.mastership.MastershipServiceAdapter; -import org.onosproject.net.Annotations; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.Device; -import org.onosproject.net.DeviceId; -import org.onosproject.net.MastershipRole; -import org.onosproject.net.Port; -import org.onosproject.net.PortNumber; -import org.onosproject.net.SparseAnnotations; -import org.onosproject.net.device.DefaultDeviceDescription; -import org.onosproject.net.device.DefaultPortDescription; -import org.onosproject.net.device.DeviceClockService; -import org.onosproject.net.device.DeviceClockServiceAdapter; -import org.onosproject.net.device.DeviceDescription; -import org.onosproject.net.device.DeviceEvent; -import org.onosproject.net.device.DeviceStore; -import org.onosproject.net.device.DeviceStoreDelegate; -import org.onosproject.net.device.PortDescription; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.Timestamp; -import org.onosproject.store.cluster.StaticClusterService; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.cluster.messaging.ClusterMessage; -import org.onosproject.store.cluster.messaging.ClusterMessageHandler; -import org.onosproject.store.cluster.messaging.MessageSubject; -import org.onosproject.store.consistent.impl.DatabaseManager; -import org.onosproject.store.impl.MastershipBasedTimestamp; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import java.util.function.Function; - -import static java.util.Arrays.asList; -import static org.easymock.EasyMock.*; -import static org.junit.Assert.*; -import static org.onosproject.cluster.ControllerNode.State.ACTIVE; -import static org.onosproject.net.DefaultAnnotations.union; -import static org.onosproject.net.Device.Type.SWITCH; -import static org.onosproject.net.DeviceId.deviceId; -import static org.onosproject.net.device.DeviceEvent.Type.*; - - -// TODO add tests for remote replication -/** - * Test of the gossip based distributed DeviceStore implementation. - */ -public class GossipDeviceStoreTest { - - private static final ProviderId PID = new ProviderId("of", "foo"); - private static final ProviderId PIDA = new ProviderId("of", "bar", true); - private static final DeviceId DID1 = deviceId("of:foo"); - private static final DeviceId DID2 = deviceId("of:bar"); - private static final String MFR = "whitebox"; - private static final String HW = "1.1.x"; - private static final String SW1 = "3.8.1"; - private static final String SW2 = "3.9.5"; - private static final String SN = "43311-12345"; - private static final ChassisId CID = new ChassisId(); - - private static final PortNumber P1 = PortNumber.portNumber(1); - private static final PortNumber P2 = PortNumber.portNumber(2); - private static final PortNumber P3 = PortNumber.portNumber(3); - - private static final SparseAnnotations A1 = DefaultAnnotations.builder() - .set("A1", "a1") - .set("B1", "b1") - .build(); - private static final SparseAnnotations A1_2 = DefaultAnnotations.builder() - .remove("A1") - .set("B3", "b3") - .build(); - private static final SparseAnnotations A2 = DefaultAnnotations.builder() - .set("A2", "a2") - .set("B2", "b2") - .build(); - private static final SparseAnnotations A2_2 = DefaultAnnotations.builder() - .remove("A2") - .set("B4", "b4") - .build(); - - // local node - private static final NodeId NID1 = new NodeId("local"); - private static final ControllerNode ONOS1 = - new DefaultControllerNode(NID1, IpAddress.valueOf("127.0.0.1")); - - // remote node - private static final NodeId NID2 = new NodeId("remote"); - private static final ControllerNode ONOS2 = - new DefaultControllerNode(NID2, IpAddress.valueOf("127.0.0.2")); - private static final List<SparseAnnotations> NO_ANNOTATION = Collections.<SparseAnnotations>emptyList(); - - - private TestGossipDeviceStore testGossipDeviceStore; - private GossipDeviceStore gossipDeviceStore; - private DeviceStore deviceStore; - - private DeviceClockService deviceClockService = new TestDeviceClockService(); - private ClusterCommunicationService clusterCommunicator; - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - } - - - @Before - public void setUp() throws Exception { - clusterCommunicator = createNiceMock(ClusterCommunicationService.class); - clusterCommunicator.addSubscriber(anyObject(MessageSubject.class), - anyObject(ClusterMessageHandler.class), anyObject(ExecutorService.class)); - expectLastCall().anyTimes(); - replay(clusterCommunicator); - ClusterService clusterService = new TestClusterService(); - - testGossipDeviceStore = new TestGossipDeviceStore(deviceClockService, clusterService, clusterCommunicator); - testGossipDeviceStore.mastershipService = new TestMastershipService(); - - TestDatabaseManager testDatabaseManager = new TestDatabaseManager(); - testDatabaseManager.init(clusterService, clusterCommunicator); - testGossipDeviceStore.storageService = testDatabaseManager; - testGossipDeviceStore.deviceClockService = deviceClockService; - - gossipDeviceStore = testGossipDeviceStore; - gossipDeviceStore.activate(); - deviceStore = gossipDeviceStore; - verify(clusterCommunicator); - reset(clusterCommunicator); - } - - @After - public void tearDown() throws Exception { - gossipDeviceStore.deactivate(); - } - - private void putDevice(DeviceId deviceId, String swVersion, - SparseAnnotations... annotations) { - DeviceDescription description = - new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR, - HW, swVersion, SN, CID, annotations); - reset(clusterCommunicator); - clusterCommunicator.<InternalDeviceEvent>broadcast( - anyObject(InternalDeviceEvent.class), anyObject(MessageSubject.class), anyObject(Function.class)); - expectLastCall().anyTimes(); - replay(clusterCommunicator); - deviceStore.createOrUpdateDevice(PID, deviceId, description); - verify(clusterCommunicator); - } - - private void putDeviceAncillary(DeviceId deviceId, String swVersion, - SparseAnnotations... annotations) { - DeviceDescription description = - new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR, - HW, swVersion, SN, CID, annotations); - deviceStore.createOrUpdateDevice(PIDA, deviceId, description); - } - - private static void assertDevice(DeviceId id, String swVersion, Device device) { - assertNotNull(device); - assertEquals(id, device.id()); - assertEquals(MFR, device.manufacturer()); - assertEquals(HW, device.hwVersion()); - assertEquals(swVersion, device.swVersion()); - assertEquals(SN, device.serialNumber()); - } - - /** - * Verifies that Annotations created by merging {@code annotations} is - * equal to actual Annotations. - * - * @param actual Annotations to check - * @param annotations - */ - private static void assertAnnotationsEquals(Annotations actual, SparseAnnotations... annotations) { - SparseAnnotations expected = DefaultAnnotations.builder().build(); - for (SparseAnnotations a : annotations) { - expected = DefaultAnnotations.union(expected, a); - } - assertEquals(expected.keys(), actual.keys()); - for (String key : expected.keys()) { - assertEquals(expected.value(key), actual.value(key)); - } - } - - private static void assertDeviceDescriptionEquals(DeviceDescription expected, - DeviceDescription actual) { - if (expected == actual) { - return; - } - assertEquals(expected.deviceUri(), actual.deviceUri()); - assertEquals(expected.hwVersion(), actual.hwVersion()); - assertEquals(expected.manufacturer(), actual.manufacturer()); - assertEquals(expected.serialNumber(), actual.serialNumber()); - assertEquals(expected.swVersion(), actual.swVersion()); - - assertAnnotationsEquals(actual.annotations(), expected.annotations()); - } - - private static void assertDeviceDescriptionEquals(DeviceDescription expected, - List<SparseAnnotations> expectedAnnotations, - DeviceDescription actual) { - if (expected == actual) { - return; - } - assertEquals(expected.deviceUri(), actual.deviceUri()); - assertEquals(expected.hwVersion(), actual.hwVersion()); - assertEquals(expected.manufacturer(), actual.manufacturer()); - assertEquals(expected.serialNumber(), actual.serialNumber()); - assertEquals(expected.swVersion(), actual.swVersion()); - - assertAnnotationsEquals(actual.annotations(), - expectedAnnotations.toArray(new SparseAnnotations[0])); - } - - @Test - public final void testGetDeviceCount() { - assertEquals("initialy empty", 0, deviceStore.getDeviceCount()); - - putDevice(DID1, SW1); - putDevice(DID2, SW2); - putDevice(DID1, SW1); - - assertEquals("expect 2 uniq devices", 2, deviceStore.getDeviceCount()); - } - - @Test - public final void testGetDevices() { - assertEquals("initialy empty", 0, Iterables.size(deviceStore.getDevices())); - - putDevice(DID1, SW1); - putDevice(DID2, SW2); - putDevice(DID1, SW1); - - assertEquals("expect 2 uniq devices", - 2, Iterables.size(deviceStore.getDevices())); - - Map<DeviceId, Device> devices = new HashMap<>(); - for (Device device : deviceStore.getDevices()) { - devices.put(device.id(), device); - } - - assertDevice(DID1, SW1, devices.get(DID1)); - assertDevice(DID2, SW2, devices.get(DID2)); - - // add case for new node? - } - - @Test - public final void testGetDevice() { - - putDevice(DID1, SW1); - - assertDevice(DID1, SW1, deviceStore.getDevice(DID1)); - assertNull("DID2 shouldn't be there", deviceStore.getDevice(DID2)); - } - - private void assertInternalDeviceEvent(NodeId sender, - DeviceId deviceId, - ProviderId providerId, - DeviceDescription expectedDesc, - Capture<InternalDeviceEvent> actualEvent, - Capture<MessageSubject> actualSubject, - Capture<Function<InternalDeviceEvent, byte[]>> actualEncoder) { - assertTrue(actualEvent.hasCaptured()); - assertTrue(actualSubject.hasCaptured()); - assertTrue(actualEncoder.hasCaptured()); - - assertEquals(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE, - actualSubject.getValue()); - assertEquals(deviceId, actualEvent.getValue().deviceId()); - assertEquals(providerId, actualEvent.getValue().providerId()); - assertDeviceDescriptionEquals(expectedDesc, actualEvent.getValue().deviceDescription().value()); - } - - private void assertInternalDeviceEvent(NodeId sender, - DeviceId deviceId, - ProviderId providerId, - DeviceDescription expectedDesc, - List<SparseAnnotations> expectedAnnotations, - Capture<InternalDeviceEvent> actualEvent, - Capture<MessageSubject> actualSubject, - Capture<Function<InternalDeviceEvent, byte[]>> actualEncoder) { - assertTrue(actualEvent.hasCaptured()); - assertTrue(actualSubject.hasCaptured()); - assertTrue(actualEncoder.hasCaptured()); - - assertEquals(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE, - actualSubject.getValue()); - assertEquals(deviceId, actualEvent.getValue().deviceId()); - assertEquals(providerId, actualEvent.getValue().providerId()); - assertDeviceDescriptionEquals( - expectedDesc, - expectedAnnotations, - actualEvent.getValue().deviceDescription().value()); - } - - @Test - public final void testCreateOrUpdateDevice() throws IOException { - DeviceDescription description = - new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, - HW, SW1, SN, CID); - Capture<InternalDeviceEvent> message = new Capture<>(); - Capture<MessageSubject> subject = new Capture<>(); - Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>(); - - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description); - assertEquals(DEVICE_ADDED, event.type()); - assertDevice(DID1, SW1, event.subject()); - verify(clusterCommunicator); - assertInternalDeviceEvent(NID1, DID1, PID, description, message, subject, encoder); - - - DeviceDescription description2 = - new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, - HW, SW2, SN, CID); - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2); - assertEquals(DEVICE_UPDATED, event2.type()); - assertDevice(DID1, SW2, event2.subject()); - - verify(clusterCommunicator); - assertInternalDeviceEvent(NID1, DID1, PID, description2, message, subject, encoder); - reset(clusterCommunicator); - - assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2)); - } - - @Test - public final void testCreateOrUpdateDeviceAncillary() throws IOException { - // add - DeviceDescription description = - new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, - HW, SW1, SN, CID, A2); - Capture<ClusterMessage> bcast = new Capture<>(); - - Capture<InternalDeviceEvent> message = new Capture<>(); - Capture<MessageSubject> subject = new Capture<>(); - Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>(); - - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - DeviceEvent event = deviceStore.createOrUpdateDevice(PIDA, DID1, description); - assertEquals(DEVICE_ADDED, event.type()); - assertDevice(DID1, SW1, event.subject()); - assertEquals(PIDA, event.subject().providerId()); - assertAnnotationsEquals(event.subject().annotations(), A2); - assertFalse("Ancillary will not bring device up", deviceStore.isAvailable(DID1)); - verify(clusterCommunicator); - assertInternalDeviceEvent(NID1, DID1, PIDA, description, message, subject, encoder); - - // update from primary - DeviceDescription description2 = - new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, - HW, SW2, SN, CID, A1); - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - - DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2); - assertEquals(DEVICE_UPDATED, event2.type()); - assertDevice(DID1, SW2, event2.subject()); - assertEquals(PID, event2.subject().providerId()); - assertAnnotationsEquals(event2.subject().annotations(), A1, A2); - assertTrue(deviceStore.isAvailable(DID1)); - verify(clusterCommunicator); - assertInternalDeviceEvent(NID1, DID1, PID, description2, message, subject, encoder); - - // no-op update from primary - resetCommunicatorExpectingNoBroadcast(message, subject, encoder); - assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2)); - - verify(clusterCommunicator); - assertFalse("no broadcast expected", bcast.hasCaptured()); - - // For now, Ancillary is ignored once primary appears - resetCommunicatorExpectingNoBroadcast(message, subject, encoder); - - assertNull("No change expected", deviceStore.createOrUpdateDevice(PIDA, DID1, description)); - - verify(clusterCommunicator); - assertFalse("no broadcast expected", bcast.hasCaptured()); - - // But, Ancillary annotations will be in effect - DeviceDescription description3 = - new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, - HW, SW1, SN, CID, A2_2); - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - - DeviceEvent event3 = deviceStore.createOrUpdateDevice(PIDA, DID1, description3); - assertEquals(DEVICE_UPDATED, event3.type()); - // basic information will be the one from Primary - assertDevice(DID1, SW2, event3.subject()); - assertEquals(PID, event3.subject().providerId()); - // but annotation from Ancillary will be merged - assertAnnotationsEquals(event3.subject().annotations(), A1, A2, A2_2); - assertTrue(deviceStore.isAvailable(DID1)); - verify(clusterCommunicator); - // note: only annotation from PIDA is sent over the wire - assertInternalDeviceEvent(NID1, DID1, PIDA, description3, - asList(union(A2, A2_2)), message, subject, encoder); - - } - - - @Test - public final void testMarkOffline() { - - putDevice(DID1, SW1); - assertTrue(deviceStore.isAvailable(DID1)); - - Capture<InternalDeviceEvent> message = new Capture<>(); - Capture<MessageSubject> subject = new Capture<>(); - Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>(); - - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - DeviceEvent event = deviceStore.markOffline(DID1); - assertEquals(DEVICE_AVAILABILITY_CHANGED, event.type()); - assertDevice(DID1, SW1, event.subject()); - assertFalse(deviceStore.isAvailable(DID1)); - verify(clusterCommunicator); - // TODO: verify broadcast message - assertTrue(message.hasCaptured()); - - - resetCommunicatorExpectingNoBroadcast(message, subject, encoder); - DeviceEvent event2 = deviceStore.markOffline(DID1); - assertNull("No change, no event", event2); - verify(clusterCommunicator); - assertFalse(message.hasCaptured()); - } - - @Test - public final void testUpdatePorts() { - putDevice(DID1, SW1); - List<PortDescription> pds = Arrays.<PortDescription>asList( - new DefaultPortDescription(P1, true), - new DefaultPortDescription(P2, true) - ); - Capture<InternalDeviceEvent> message = new Capture<>(); - Capture<MessageSubject> subject = new Capture<>(); - Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>(); - - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds); - verify(clusterCommunicator); - // TODO: verify broadcast message - assertTrue(message.hasCaptured()); - - Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2); - for (DeviceEvent event : events) { - assertEquals(PORT_ADDED, event.type()); - assertDevice(DID1, SW1, event.subject()); - assertTrue("PortNumber is one of expected", - expectedPorts.remove(event.port().number())); - assertTrue("Port is enabled", event.port().isEnabled()); - } - assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty()); - - - List<PortDescription> pds2 = Arrays.<PortDescription>asList( - new DefaultPortDescription(P1, false), - new DefaultPortDescription(P2, true), - new DefaultPortDescription(P3, true) - ); - - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - events = deviceStore.updatePorts(PID, DID1, pds2); - verify(clusterCommunicator); - // TODO: verify broadcast message - assertTrue(message.hasCaptured()); - - assertFalse("event should be triggered", events.isEmpty()); - for (DeviceEvent event : events) { - PortNumber num = event.port().number(); - if (P1.equals(num)) { - assertEquals(PORT_UPDATED, event.type()); - assertDevice(DID1, SW1, event.subject()); - assertFalse("Port is disabled", event.port().isEnabled()); - } else if (P2.equals(num)) { - fail("P2 event not expected."); - } else if (P3.equals(num)) { - assertEquals(PORT_ADDED, event.type()); - assertDevice(DID1, SW1, event.subject()); - assertTrue("Port is enabled", event.port().isEnabled()); - } else { - fail("Unknown port number encountered: " + num); - } - } - - List<PortDescription> pds3 = Arrays.<PortDescription>asList( - new DefaultPortDescription(P1, false), - new DefaultPortDescription(P2, true) - ); - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - events = deviceStore.updatePorts(PID, DID1, pds3); - verify(clusterCommunicator); - // TODO: verify broadcast message - assertTrue(message.hasCaptured()); - - assertFalse("event should be triggered", events.isEmpty()); - for (DeviceEvent event : events) { - PortNumber num = event.port().number(); - if (P1.equals(num)) { - fail("P1 event not expected."); - } else if (P2.equals(num)) { - fail("P2 event not expected."); - } else if (P3.equals(num)) { - assertEquals(PORT_REMOVED, event.type()); - assertDevice(DID1, SW1, event.subject()); - assertTrue("Port was enabled", event.port().isEnabled()); - } else { - fail("Unknown port number encountered: " + num); - } - } - } - - @Test - public final void testUpdatePortStatus() { - putDevice(DID1, SW1); - List<PortDescription> pds = Arrays.<PortDescription>asList( - new DefaultPortDescription(P1, true) - ); - deviceStore.updatePorts(PID, DID1, pds); - - Capture<InternalPortStatusEvent> message = new Capture<>(); - Capture<MessageSubject> subject = new Capture<>(); - Capture<Function<InternalPortStatusEvent, byte[]>> encoder = new Capture<>(); - - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - final DefaultPortDescription desc = new DefaultPortDescription(P1, false); - DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, desc); - assertEquals(PORT_UPDATED, event.type()); - assertDevice(DID1, SW1, event.subject()); - assertEquals(P1, event.port().number()); - assertFalse("Port is disabled", event.port().isEnabled()); - verify(clusterCommunicator); - assertInternalPortStatusEvent(NID1, DID1, PID, desc, NO_ANNOTATION, message, subject, encoder); - assertTrue(message.hasCaptured()); - } - - @Test - public final void testUpdatePortStatusAncillary() throws IOException { - putDeviceAncillary(DID1, SW1); - putDevice(DID1, SW1); - List<PortDescription> pds = Arrays.<PortDescription>asList( - new DefaultPortDescription(P1, true, A1) - ); - deviceStore.updatePorts(PID, DID1, pds); - - Capture<InternalPortStatusEvent> message = new Capture<>(); - Capture<MessageSubject> subject = new Capture<>(); - Capture<Function<InternalPortStatusEvent, byte[]>> encoder = new Capture<>(); - - // update port from primary - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - - final DefaultPortDescription desc1 = new DefaultPortDescription(P1, false, A1_2); - DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, desc1); - assertEquals(PORT_UPDATED, event.type()); - assertDevice(DID1, SW1, event.subject()); - assertEquals(P1, event.port().number()); - assertAnnotationsEquals(event.port().annotations(), A1, A1_2); - assertFalse("Port is disabled", event.port().isEnabled()); - verify(clusterCommunicator); - assertInternalPortStatusEvent(NID1, DID1, PID, desc1, asList(A1, A1_2), message, subject, encoder); - assertTrue(message.hasCaptured()); - - // update port from ancillary with no attributes - resetCommunicatorExpectingNoBroadcast(message, subject, encoder); - final DefaultPortDescription desc2 = new DefaultPortDescription(P1, true); - DeviceEvent event2 = deviceStore.updatePortStatus(PIDA, DID1, desc2); - assertNull("Ancillary is ignored if primary exists", event2); - verify(clusterCommunicator); - assertFalse(message.hasCaptured()); - - // but, Ancillary annotation update will be notified - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - final DefaultPortDescription desc3 = new DefaultPortDescription(P1, true, A2); - DeviceEvent event3 = deviceStore.updatePortStatus(PIDA, DID1, desc3); - assertEquals(PORT_UPDATED, event3.type()); - assertDevice(DID1, SW1, event3.subject()); - assertEquals(P1, event3.port().number()); - assertAnnotationsEquals(event3.port().annotations(), A1, A1_2, A2); - assertFalse("Port is disabled", event3.port().isEnabled()); - verify(clusterCommunicator); - assertInternalPortStatusEvent(NID1, DID1, PIDA, desc3, asList(A2), message, subject, encoder); - assertTrue(message.hasCaptured()); - - // port only reported from Ancillary will be notified as down - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - final DefaultPortDescription desc4 = new DefaultPortDescription(P2, true); - DeviceEvent event4 = deviceStore.updatePortStatus(PIDA, DID1, desc4); - assertEquals(PORT_ADDED, event4.type()); - assertDevice(DID1, SW1, event4.subject()); - assertEquals(P2, event4.port().number()); - assertAnnotationsEquals(event4.port().annotations()); - assertFalse("Port is disabled if not given from primary provider", - event4.port().isEnabled()); - verify(clusterCommunicator); - // TODO: verify broadcast message content - assertInternalPortStatusEvent(NID1, DID1, PIDA, desc4, NO_ANNOTATION, message, subject, encoder); - assertTrue(message.hasCaptured()); - } - - private void assertInternalPortStatusEvent(NodeId sender, - DeviceId did, - ProviderId pid, - DefaultPortDescription expectedDesc, - List<SparseAnnotations> expectedAnnotations, - Capture<InternalPortStatusEvent> actualEvent, - Capture<MessageSubject> actualSubject, - Capture<Function<InternalPortStatusEvent, byte[]>> actualEncoder) { - - assertTrue(actualEvent.hasCaptured()); - assertTrue(actualSubject.hasCaptured()); - assertTrue(actualEncoder.hasCaptured()); - - assertEquals(GossipDeviceStoreMessageSubjects.PORT_STATUS_UPDATE, - actualSubject.getValue()); - assertEquals(did, actualEvent.getValue().deviceId()); - assertEquals(pid, actualEvent.getValue().providerId()); - assertPortDescriptionEquals(expectedDesc, expectedAnnotations, - actualEvent.getValue().portDescription().value()); - } - - private void assertPortDescriptionEquals( - PortDescription expectedDesc, - List<SparseAnnotations> expectedAnnotations, - PortDescription actual) { - - assertEquals(expectedDesc.portNumber(), actual.portNumber()); - assertEquals(expectedDesc.isEnabled(), actual.isEnabled()); - - assertAnnotationsEquals(actual.annotations(), - expectedAnnotations.toArray(new SparseAnnotations[0])); - } - - private <T> void resetCommunicatorExpectingNoBroadcast( - Capture<T> message, - Capture<MessageSubject> subject, - Capture<Function<T, byte[]>> encoder) { - message.reset(); - subject.reset(); - encoder.reset(); - reset(clusterCommunicator); - replay(clusterCommunicator); - } - - private <T> void resetCommunicatorExpectingSingleBroadcast( - Capture<T> message, - Capture<MessageSubject> subject, - Capture<Function<T, byte[]>> encoder) { - - message.reset(); - subject.reset(); - encoder.reset(); - reset(clusterCommunicator); - clusterCommunicator.broadcast( - capture(message), - capture(subject), - capture(encoder)); - expectLastCall().once(); - replay(clusterCommunicator); - } - - @Test - public final void testGetPorts() { - putDevice(DID1, SW1); - putDevice(DID2, SW1); - List<PortDescription> pds = Arrays.<PortDescription>asList( - new DefaultPortDescription(P1, true), - new DefaultPortDescription(P2, true) - ); - deviceStore.updatePorts(PID, DID1, pds); - - Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2); - List<Port> ports = deviceStore.getPorts(DID1); - for (Port port : ports) { - assertTrue("Port is enabled", port.isEnabled()); - assertTrue("PortNumber is one of expected", - expectedPorts.remove(port.number())); - } - assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty()); - - - assertTrue("DID2 has no ports", deviceStore.getPorts(DID2).isEmpty()); - } - - @Test - public final void testGetPort() { - putDevice(DID1, SW1); - putDevice(DID2, SW1); - List<PortDescription> pds = Arrays.<PortDescription>asList( - new DefaultPortDescription(P1, true), - new DefaultPortDescription(P2, false) - ); - deviceStore.updatePorts(PID, DID1, pds); - - Port port1 = deviceStore.getPort(DID1, P1); - assertEquals(P1, port1.number()); - assertTrue("Port is enabled", port1.isEnabled()); - - Port port2 = deviceStore.getPort(DID1, P2); - assertEquals(P2, port2.number()); - assertFalse("Port is disabled", port2.isEnabled()); - - Port port3 = deviceStore.getPort(DID1, P3); - assertNull("P3 not expected", port3); - } - - @Test - public final void testRemoveDevice() { - putDevice(DID1, SW1, A1); - List<PortDescription> pds = Arrays.<PortDescription>asList( - new DefaultPortDescription(P1, true, A2) - ); - deviceStore.updatePorts(PID, DID1, pds); - putDevice(DID2, SW1); - - assertEquals(2, deviceStore.getDeviceCount()); - assertEquals(1, deviceStore.getPorts(DID1).size()); - assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations(), A1); - assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations(), A2); - - Capture<InternalDeviceEvent> message = new Capture<>(); - Capture<MessageSubject> subject = new Capture<>(); - Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>(); - - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - - DeviceEvent event = deviceStore.removeDevice(DID1); - assertEquals(DEVICE_REMOVED, event.type()); - assertDevice(DID1, SW1, event.subject()); - - assertEquals(1, deviceStore.getDeviceCount()); - assertEquals(0, deviceStore.getPorts(DID1).size()); - verify(clusterCommunicator); - // TODO: verify broadcast message - assertTrue(message.hasCaptured()); - - // putBack Device, Port w/o annotation - putDevice(DID1, SW1); - List<PortDescription> pds2 = Arrays.<PortDescription>asList( - new DefaultPortDescription(P1, true) - ); - deviceStore.updatePorts(PID, DID1, pds2); - - // annotations should not survive - assertEquals(2, deviceStore.getDeviceCount()); - assertEquals(1, deviceStore.getPorts(DID1).size()); - assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations()); - assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations()); - } - - // If Delegates should be called only on remote events, - // then Simple* should never call them, thus not test required. - // TODO add test for Port events when we have them - @Ignore("Ignore until Delegate spec. is clear.") - @Test - public final void testEvents() throws InterruptedException { - final CountDownLatch addLatch = new CountDownLatch(1); - DeviceStoreDelegate checkAdd = event -> { - assertEquals(DEVICE_ADDED, event.type()); - assertDevice(DID1, SW1, event.subject()); - addLatch.countDown(); - }; - final CountDownLatch updateLatch = new CountDownLatch(1); - DeviceStoreDelegate checkUpdate = event -> { - assertEquals(DEVICE_UPDATED, event.type()); - assertDevice(DID1, SW2, event.subject()); - updateLatch.countDown(); - }; - final CountDownLatch removeLatch = new CountDownLatch(1); - DeviceStoreDelegate checkRemove = event -> { - assertEquals(DEVICE_REMOVED, event.type()); - assertDevice(DID1, SW2, event.subject()); - removeLatch.countDown(); - }; - - DeviceDescription description = - new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, - HW, SW1, SN, CID); - deviceStore.setDelegate(checkAdd); - deviceStore.createOrUpdateDevice(PID, DID1, description); - assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS)); - - - DeviceDescription description2 = - new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, - HW, SW2, SN, CID); - deviceStore.unsetDelegate(checkAdd); - deviceStore.setDelegate(checkUpdate); - deviceStore.createOrUpdateDevice(PID, DID1, description2); - assertTrue("Update event fired", updateLatch.await(1, TimeUnit.SECONDS)); - - deviceStore.unsetDelegate(checkUpdate); - deviceStore.setDelegate(checkRemove); - deviceStore.removeDevice(DID1); - assertTrue("Remove event fired", removeLatch.await(1, TimeUnit.SECONDS)); - } - - private final class TestMastershipService extends MastershipServiceAdapter { - @Override - public NodeId getMasterFor(DeviceId deviceId) { - return NID1; - } - @Override - public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) { - return CompletableFuture.completedFuture(null); - } - } - - private static final class TestGossipDeviceStore extends GossipDeviceStore { - - public TestGossipDeviceStore( - DeviceClockService deviceClockService, - ClusterService clusterService, - ClusterCommunicationService clusterCommunicator) { - this.deviceClockService = deviceClockService; - this.clusterService = clusterService; - this.clusterCommunicator = clusterCommunicator; - } - } - - private static final class TestClusterService extends StaticClusterService { - - public TestClusterService() { - localNode = ONOS1; - nodes.put(NID1, ONOS1); - nodeStates.put(NID1, ACTIVE); - - nodes.put(NID2, ONOS2); - nodeStates.put(NID2, ACTIVE); - } - } - - private final class TestDeviceClockService extends DeviceClockServiceAdapter { - - private final AtomicLong ticker = new AtomicLong(); - - @Override - public Timestamp getTimestamp(DeviceId deviceId) { - if (DID1.equals(deviceId)) { - return new MastershipBasedTimestamp(1, ticker.getAndIncrement()); - } else if (DID2.equals(deviceId)) { - return new MastershipBasedTimestamp(2, ticker.getAndIncrement()); - } else { - throw new IllegalStateException(); - } - } - - @Override - public boolean isTimestampAvailable(DeviceId deviceId) { - return DID1.equals(deviceId) || DID2.equals(deviceId); - } - } - - private class TestDatabaseManager extends DatabaseManager { - void init(ClusterService clusterService, - ClusterCommunicationService clusterCommunicator) { - this.clusterService = clusterService; - this.clusterCommunicator = clusterCommunicator; - } - } -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/device/impl/PortFragmentIdTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/device/impl/PortFragmentIdTest.java deleted file mode 100644 index 5b862520..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/device/impl/PortFragmentIdTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.device.impl; - -import static org.onosproject.net.DeviceId.deviceId; - -import org.junit.Test; -import org.onosproject.net.DeviceId; -import org.onosproject.net.PortNumber; -import org.onosproject.net.provider.ProviderId; - -import com.google.common.testing.EqualsTester; - -public class PortFragmentIdTest { - - private static final ProviderId PID = new ProviderId("of", "foo"); - private static final ProviderId PIDA = new ProviderId("of", "bar", true); - - private static final DeviceId DID1 = deviceId("of:foo"); - private static final DeviceId DID2 = deviceId("of:bar"); - - private static final PortNumber PN1 = PortNumber.portNumber(1); - private static final PortNumber PN2 = PortNumber.portNumber(2); - - @Test - public final void testEquals() { - new EqualsTester() - .addEqualityGroup(new PortFragmentId(DID1, PID, PN1), - new PortFragmentId(DID1, PID, PN1)) - .addEqualityGroup(new PortFragmentId(DID2, PID, PN1), - new PortFragmentId(DID2, PID, PN1)) - .addEqualityGroup(new PortFragmentId(DID1, PIDA, PN1), - new PortFragmentId(DID1, PIDA, PN1)) - .addEqualityGroup(new PortFragmentId(DID2, PIDA, PN1), - new PortFragmentId(DID2, PIDA, PN1)) - - .addEqualityGroup(new PortFragmentId(DID1, PID, PN2), - new PortFragmentId(DID1, PID, PN2)) - .addEqualityGroup(new PortFragmentId(DID2, PID, PN2), - new PortFragmentId(DID2, PID, PN2)) - .addEqualityGroup(new PortFragmentId(DID1, PIDA, PN2), - new PortFragmentId(DID1, PIDA, PN2)) - .addEqualityGroup(new PortFragmentId(DID2, PIDA, PN2), - new PortFragmentId(DID2, PIDA, PN2)) - .testEquals(); - } - -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java deleted file mode 100644 index b74aa370..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java +++ /dev/null @@ -1,914 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.ecmap; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import java.util.function.Consumer; -import java.util.function.Function; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.onlab.packet.IpAddress; -import org.onlab.util.KryoNamespace; -import org.onosproject.cluster.ClusterService; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.DefaultControllerNode; -import org.onosproject.cluster.NodeId; -import org.onosproject.event.AbstractEvent; -import org.onosproject.persistence.PersistenceService; -import org.onosproject.store.Timestamp; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter; -import org.onosproject.store.cluster.messaging.MessageSubject; -import org.onosproject.store.impl.LogicalTimestamp; -import org.onosproject.store.persistence.TestPersistenceService; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.serializers.KryoSerializer; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.EventuallyConsistentMapEvent; -import org.onosproject.store.service.EventuallyConsistentMapListener; -import org.onosproject.store.service.WallClockTimestamp; - -import com.google.common.collect.ComparisonChain; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.util.concurrent.MoreExecutors; - -import static com.google.common.base.Preconditions.checkArgument; -import static junit.framework.TestCase.assertFalse; -import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.eq; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.expectLastCall; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.reset; -import static org.easymock.EasyMock.verify; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * Unit tests for EventuallyConsistentMapImpl. - */ -public class EventuallyConsistentMapImplTest { - - private EventuallyConsistentMap<String, String> ecMap; - - private PersistenceService persistenceService; - private ClusterService clusterService; - private ClusterCommunicationService clusterCommunicator; - private SequentialClockService<String, String> clockService; - - private static final String MAP_NAME = "test"; - private static final MessageSubject UPDATE_MESSAGE_SUBJECT - = new MessageSubject("ecm-" + MAP_NAME + "-update"); - private static final MessageSubject ANTI_ENTROPY_MESSAGE_SUBJECT - = new MessageSubject("ecm-" + MAP_NAME + "-anti-entropy"); - - private static final String KEY1 = "one"; - private static final String KEY2 = "two"; - private static final String VALUE1 = "oneValue"; - private static final String VALUE2 = "twoValue"; - - private final ControllerNode self = - new DefaultControllerNode(new NodeId("local"), IpAddress.valueOf(1)); - - private Consumer<Collection<UpdateEntry<String, String>>> updateHandler; - private Consumer<AntiEntropyAdvertisement<String>> antiEntropyHandler; - - /* - * Serialization is a bit tricky here. We need to serialize in the tests - * to set the expectations, which will use this serializer here, but the - * EventuallyConsistentMap will use its own internal serializer. This means - * this serializer must be set up exactly the same as map's internal - * serializer. - */ - private static final KryoSerializer SERIALIZER = new KryoSerializer() { - @Override - protected void setupKryoPool() { - serializerPool = KryoNamespace.newBuilder() - // Classes we give to the map - .register(KryoNamespaces.API) - .register(TestTimestamp.class) - // Below is the classes that the map internally registers - .register(LogicalTimestamp.class) - .register(WallClockTimestamp.class) - .register(ArrayList.class) - .register(AntiEntropyAdvertisement.class) - .register(HashMap.class) - .register(Optional.class) - .build(); - } - }; - - @Before - public void setUp() throws Exception { - clusterService = createMock(ClusterService.class); - expect(clusterService.getLocalNode()).andReturn(self).anyTimes(); - expect(clusterService.getNodes()).andReturn(ImmutableSet.of(self)).anyTimes(); - replay(clusterService); - - clusterCommunicator = createMock(ClusterCommunicationService.class); - - persistenceService = new TestPersistenceService(); - // Add expectation for adding cluster message subscribers which - // delegate to our ClusterCommunicationService implementation. This - // allows us to get a reference to the map's internal cluster message - // handlers so we can induce events coming in from a peer. - clusterCommunicator.<String>addSubscriber(anyObject(MessageSubject.class), - anyObject(Function.class), anyObject(Consumer.class), anyObject(Executor.class)); - expectLastCall().andDelegateTo(new TestClusterCommunicationService()).times(2); - - replay(clusterCommunicator); - - clockService = new SequentialClockService<>(); - - KryoNamespace.Builder serializer = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .register(TestTimestamp.class); - - ecMap = new EventuallyConsistentMapBuilderImpl<String, String>( - clusterService, clusterCommunicator, persistenceService) - .withName(MAP_NAME) - .withSerializer(serializer) - .withTimestampProvider((k, v) -> clockService.getTimestamp(k, v)) - .withCommunicationExecutor(MoreExecutors.newDirectExecutorService()) - .withPersistence() - .build(); - - // Reset ready for tests to add their own expectations - reset(clusterCommunicator); - } - - @After - public void tearDown() { - reset(clusterCommunicator); - ecMap.destroy(); - } - - @SuppressWarnings("unchecked") - private EventuallyConsistentMapListener<String, String> getListener() { - return createMock(EventuallyConsistentMapListener.class); - } - - @Test - public void testSize() throws Exception { - expectPeerMessage(clusterCommunicator); - - assertEquals(0, ecMap.size()); - ecMap.put(KEY1, VALUE1); - assertEquals(1, ecMap.size()); - ecMap.put(KEY1, VALUE2); - assertEquals(1, ecMap.size()); - ecMap.put(KEY2, VALUE2); - assertEquals(2, ecMap.size()); - for (int i = 0; i < 10; i++) { - ecMap.put("" + i, "" + i); - } - assertEquals(12, ecMap.size()); - ecMap.remove(KEY1); - assertEquals(11, ecMap.size()); - ecMap.remove(KEY1); - assertEquals(11, ecMap.size()); - } - - @Test - public void testIsEmpty() throws Exception { - expectPeerMessage(clusterCommunicator); - - assertTrue(ecMap.isEmpty()); - ecMap.put(KEY1, VALUE1); - assertFalse(ecMap.isEmpty()); - ecMap.remove(KEY1); - assertTrue(ecMap.isEmpty()); - } - - @Test - public void testContainsKey() throws Exception { - expectPeerMessage(clusterCommunicator); - - assertFalse(ecMap.containsKey(KEY1)); - ecMap.put(KEY1, VALUE1); - assertTrue(ecMap.containsKey(KEY1)); - assertFalse(ecMap.containsKey(KEY2)); - ecMap.remove(KEY1); - assertFalse(ecMap.containsKey(KEY1)); - } - - @Test - public void testContainsValue() throws Exception { - expectPeerMessage(clusterCommunicator); - - assertFalse(ecMap.containsValue(VALUE1)); - ecMap.put(KEY1, VALUE1); - assertTrue(ecMap.containsValue(VALUE1)); - assertFalse(ecMap.containsValue(VALUE2)); - ecMap.put(KEY1, VALUE2); - assertFalse(ecMap.containsValue(VALUE1)); - assertTrue(ecMap.containsValue(VALUE2)); - ecMap.remove(KEY1); - assertFalse(ecMap.containsValue(VALUE2)); - } - - @Test - public void testGet() throws Exception { - expectPeerMessage(clusterCommunicator); - - CountDownLatch latch; - - // Local put - assertNull(ecMap.get(KEY1)); - ecMap.put(KEY1, VALUE1); - assertEquals(VALUE1, ecMap.get(KEY1)); - - // Remote put - List<UpdateEntry<String, String>> message - = ImmutableList.of(generatePutMessage(KEY2, VALUE2, clockService.getTimestamp(KEY2, VALUE2))); - - // Create a latch so we know when the put operation has finished - latch = new CountDownLatch(1); - ecMap.addListener(new TestListener(latch)); - - assertNull(ecMap.get(KEY2)); - updateHandler.accept(message); - assertTrue("External listener never got notified of internal event", - latch.await(100, TimeUnit.MILLISECONDS)); - assertEquals(VALUE2, ecMap.get(KEY2)); - - // Local remove - ecMap.remove(KEY2); - assertNull(ecMap.get(KEY2)); - - // Remote remove - message = ImmutableList.of(generateRemoveMessage(KEY1, clockService.getTimestamp(KEY1, VALUE1))); - - // Create a latch so we know when the remove operation has finished - latch = new CountDownLatch(1); - ecMap.addListener(new TestListener(latch)); - - updateHandler.accept(message); - assertTrue("External listener never got notified of internal event", - latch.await(100, TimeUnit.MILLISECONDS)); - assertNull(ecMap.get(KEY1)); - } - - @Test - public void testPut() throws Exception { - // Set up expectations of external events to be sent to listeners during - // the test. These don't use timestamps so we can set them all up at once. - EventuallyConsistentMapListener<String, String> listener - = getListener(); - listener.event(new EventuallyConsistentMapEvent<>( - MAP_NAME, EventuallyConsistentMapEvent.Type.PUT, KEY1, VALUE1)); - listener.event(new EventuallyConsistentMapEvent<>( - MAP_NAME, EventuallyConsistentMapEvent.Type.PUT, KEY1, VALUE2)); - replay(listener); - - ecMap.addListener(listener); - - // Set up expected internal message to be broadcast to peers on first put - expectSpecificMulticastMessage(generatePutMessage(KEY1, VALUE1, clockService - .peekAtNextTimestamp()), UPDATE_MESSAGE_SUBJECT, clusterCommunicator); - - // Put first value - assertNull(ecMap.get(KEY1)); - ecMap.put(KEY1, VALUE1); - assertEquals(VALUE1, ecMap.get(KEY1)); - - verify(clusterCommunicator); - - // Set up expected internal message to be broadcast to peers on second put - expectSpecificMulticastMessage(generatePutMessage( - KEY1, VALUE2, clockService.peekAtNextTimestamp()), UPDATE_MESSAGE_SUBJECT, clusterCommunicator); - - // Update same key to a new value - ecMap.put(KEY1, VALUE2); - assertEquals(VALUE2, ecMap.get(KEY1)); - - verify(clusterCommunicator); - - // Do a put with a older timestamp than the value already there. - // The map data should not be changed and no notifications should be sent. - reset(clusterCommunicator); - replay(clusterCommunicator); - - clockService.turnBackTime(); - ecMap.put(KEY1, VALUE1); - // Value should not have changed. - assertEquals(VALUE2, ecMap.get(KEY1)); - - verify(clusterCommunicator); - - // Check that our listener received the correct events during the test - verify(listener); - } - - @Test - public void testRemove() throws Exception { - // Set up expectations of external events to be sent to listeners during - // the test. These don't use timestamps so we can set them all up at once. - EventuallyConsistentMapListener<String, String> listener - = getListener(); - listener.event(new EventuallyConsistentMapEvent<>( - MAP_NAME, EventuallyConsistentMapEvent.Type.REMOVE, KEY1, VALUE1)); - listener.event(new EventuallyConsistentMapEvent<>( - MAP_NAME, EventuallyConsistentMapEvent.Type.PUT, KEY1, VALUE1)); - listener.event(new EventuallyConsistentMapEvent<>( - MAP_NAME, EventuallyConsistentMapEvent.Type.PUT, KEY2, VALUE2)); - replay(listener); - - ecMap.addListener(listener); - - // Put in an initial value - expectPeerMessage(clusterCommunicator); - ecMap.put(KEY1, VALUE1); - assertEquals(VALUE1, ecMap.get(KEY1)); - - // Remove the value and check the correct internal cluster messages - // are sent - expectSpecificMulticastMessage(generateRemoveMessage(KEY1, clockService.peekAtNextTimestamp()), - UPDATE_MESSAGE_SUBJECT, clusterCommunicator); - - ecMap.remove(KEY1); - assertNull(ecMap.get(KEY1)); - - verify(clusterCommunicator); - - // Remove the same value again. Even though the value is no longer in - // the map, we expect that the tombstone is updated and another remove - // event is sent to the cluster and external listeners. - expectSpecificMulticastMessage(generateRemoveMessage(KEY1, clockService.peekAtNextTimestamp()), - UPDATE_MESSAGE_SUBJECT, clusterCommunicator); - - ecMap.remove(KEY1); - assertNull(ecMap.get(KEY1)); - - verify(clusterCommunicator); - - - // Put in a new value for us to try and remove - expectPeerMessage(clusterCommunicator); - - ecMap.put(KEY2, VALUE2); - - clockService.turnBackTime(); - - // Remove should have no effect, since it has an older timestamp than - // the put. Expect no notifications to be sent out - reset(clusterCommunicator); - replay(clusterCommunicator); - - ecMap.remove(KEY2); - - verify(clusterCommunicator); - - // Check that our listener received the correct events during the test - verify(listener); - } - - @Test - public void testCompute() throws Exception { - // Set up expectations of external events to be sent to listeners during - // the test. These don't use timestamps so we can set them all up at once. - EventuallyConsistentMapListener<String, String> listener - = getListener(); - listener.event(new EventuallyConsistentMapEvent<>( - MAP_NAME, EventuallyConsistentMapEvent.Type.PUT, KEY1, VALUE1)); - listener.event(new EventuallyConsistentMapEvent<>( - MAP_NAME, EventuallyConsistentMapEvent.Type.REMOVE, KEY1, VALUE1)); - listener.event(new EventuallyConsistentMapEvent<>( - MAP_NAME, EventuallyConsistentMapEvent.Type.PUT, KEY2, VALUE2)); - replay(listener); - - ecMap.addListener(listener); - - // Put in an initial value - expectPeerMessage(clusterCommunicator); - ecMap.compute(KEY1, (k, v) -> VALUE1); - assertEquals(VALUE1, ecMap.get(KEY1)); - - // Remove the value and check the correct internal cluster messages - // are sent - expectSpecificMulticastMessage(generateRemoveMessage(KEY1, clockService.peekAtNextTimestamp()), - UPDATE_MESSAGE_SUBJECT, clusterCommunicator); - - ecMap.compute(KEY1, (k, v) -> null); - assertNull(ecMap.get(KEY1)); - - verify(clusterCommunicator); - - // Remove the same value again. Even though the value is no longer in - // the map, we expect that the tombstone is updated and another remove - // event is sent to the cluster and external listeners. - expectSpecificMulticastMessage(generateRemoveMessage(KEY1, clockService.peekAtNextTimestamp()), - UPDATE_MESSAGE_SUBJECT, clusterCommunicator); - - ecMap.compute(KEY1, (k, v) -> null); - assertNull(ecMap.get(KEY1)); - - verify(clusterCommunicator); - - // Put in a new value for us to try and remove - expectPeerMessage(clusterCommunicator); - - ecMap.compute(KEY2, (k, v) -> VALUE2); - - clockService.turnBackTime(); - - // Remove should have no effect, since it has an older timestamp than - // the put. Expect no notifications to be sent out - reset(clusterCommunicator); - replay(clusterCommunicator); - - ecMap.compute(KEY2, (k, v) -> null); - - verify(clusterCommunicator); - - // Check that our listener received the correct events during the test - verify(listener); - } - - @Test - public void testPutAll() throws Exception { - // putAll() with an empty map is a no-op - no messages will be sent - reset(clusterCommunicator); - replay(clusterCommunicator); - - ecMap.putAll(new HashMap<>()); - - verify(clusterCommunicator); - - // Set up the listener with our expected events - EventuallyConsistentMapListener<String, String> listener - = getListener(); - listener.event(new EventuallyConsistentMapEvent<>( - MAP_NAME, EventuallyConsistentMapEvent.Type.PUT, KEY1, VALUE1)); - listener.event(new EventuallyConsistentMapEvent<>( - MAP_NAME, EventuallyConsistentMapEvent.Type.PUT, KEY2, VALUE2)); - replay(listener); - - ecMap.addListener(listener); - - // Expect a multi-update inter-instance message - expectSpecificBroadcastMessage(generatePutMessage(KEY1, VALUE1, KEY2, VALUE2), UPDATE_MESSAGE_SUBJECT, - clusterCommunicator); - - Map<String, String> putAllValues = new HashMap<>(); - putAllValues.put(KEY1, VALUE1); - putAllValues.put(KEY2, VALUE2); - - // Put the values in the map - ecMap.putAll(putAllValues); - - // Check the correct messages and events were sent - verify(clusterCommunicator); - verify(listener); - } - - @Test - public void testClear() throws Exception { - EventuallyConsistentMapListener<String, String> listener - = getListener(); - listener.event(new EventuallyConsistentMapEvent<>( - MAP_NAME, EventuallyConsistentMapEvent.Type.REMOVE, KEY1, VALUE1)); - listener.event(new EventuallyConsistentMapEvent<>( - MAP_NAME, EventuallyConsistentMapEvent.Type.REMOVE, KEY2, VALUE2)); - replay(listener); - - // clear() on an empty map is a no-op - no messages will be sent - reset(clusterCommunicator); - replay(clusterCommunicator); - - assertTrue(ecMap.isEmpty()); - ecMap.clear(); - verify(clusterCommunicator); - - // Put some items in the map - expectPeerMessage(clusterCommunicator); - ecMap.put(KEY1, VALUE1); - ecMap.put(KEY2, VALUE2); - - ecMap.addListener(listener); - expectSpecificBroadcastMessage(generateRemoveMessage(KEY1, KEY2), UPDATE_MESSAGE_SUBJECT, clusterCommunicator); - - ecMap.clear(); - - verify(clusterCommunicator); - verify(listener); - } - - @Test - public void testKeySet() throws Exception { - expectPeerMessage(clusterCommunicator); - - assertTrue(ecMap.keySet().isEmpty()); - - // Generate some keys - Set<String> keys = new HashSet<>(); - for (int i = 1; i <= 10; i++) { - keys.add("" + i); - } - - // Put each key in the map - keys.forEach(k -> ecMap.put(k, "value" + k)); - - // Check keySet() returns the correct value - assertEquals(keys, ecMap.keySet()); - - // Update the value for one of the keys - ecMap.put(keys.iterator().next(), "new-value"); - - // Check the key set is still the same - assertEquals(keys, ecMap.keySet()); - - // Remove a key - String removeKey = keys.iterator().next(); - keys.remove(removeKey); - ecMap.remove(removeKey); - - // Check the key set is still correct - assertEquals(keys, ecMap.keySet()); - } - - @Test - public void testValues() throws Exception { - expectPeerMessage(clusterCommunicator); - - assertTrue(ecMap.values().isEmpty()); - - // Generate some values - Map<String, String> expectedValues = new HashMap<>(); - for (int i = 1; i <= 10; i++) { - expectedValues.put("" + i, "value" + i); - } - - // Add them into the map - expectedValues.entrySet().forEach(e -> ecMap.put(e.getKey(), e.getValue())); - - // Check the values collection is correct - assertEquals(expectedValues.values().size(), ecMap.values().size()); - expectedValues.values().forEach(v -> assertTrue(ecMap.values().contains(v))); - - // Update the value for one of the keys - Map.Entry<String, String> first = expectedValues.entrySet().iterator().next(); - expectedValues.put(first.getKey(), "new-value"); - ecMap.put(first.getKey(), "new-value"); - - // Check the values collection is still correct - assertEquals(expectedValues.values().size(), ecMap.values().size()); - expectedValues.values().forEach(v -> assertTrue(ecMap.values().contains(v))); - - // Remove a key - String removeKey = expectedValues.keySet().iterator().next(); - expectedValues.remove(removeKey); - ecMap.remove(removeKey); - - // Check the values collection is still correct - assertEquals(expectedValues.values().size(), ecMap.values().size()); - expectedValues.values().forEach(v -> assertTrue(ecMap.values().contains(v))); - } - - @Test - public void testEntrySet() throws Exception { - expectPeerMessage(clusterCommunicator); - - assertTrue(ecMap.entrySet().isEmpty()); - - // Generate some values - Map<String, String> expectedValues = new HashMap<>(); - for (int i = 1; i <= 10; i++) { - expectedValues.put("" + i, "value" + i); - } - - // Add them into the map - expectedValues.entrySet().forEach(e -> ecMap.put(e.getKey(), e.getValue())); - - // Check the entry set is correct - assertTrue(entrySetsAreEqual(expectedValues, ecMap.entrySet())); - - // Update the value for one of the keys - Map.Entry<String, String> first = expectedValues.entrySet().iterator().next(); - expectedValues.put(first.getKey(), "new-value"); - ecMap.put(first.getKey(), "new-value"); - - // Check the entry set is still correct - assertTrue(entrySetsAreEqual(expectedValues, ecMap.entrySet())); - - // Remove a key - String removeKey = expectedValues.keySet().iterator().next(); - expectedValues.remove(removeKey); - ecMap.remove(removeKey); - - // Check the entry set is still correct - assertTrue(entrySetsAreEqual(expectedValues, ecMap.entrySet())); - } - - private static boolean entrySetsAreEqual(Map<String, String> expectedMap, Set<Map.Entry<String, String>> actual) { - if (expectedMap.entrySet().size() != actual.size()) { - return false; - } - - for (Map.Entry<String, String> e : actual) { - if (!expectedMap.containsKey(e.getKey())) { - return false; - } - if (!Objects.equals(expectedMap.get(e.getKey()), e.getValue())) { - return false; - } - } - return true; - } - - @Test - public void testDestroy() throws Exception { - clusterCommunicator.removeSubscriber(UPDATE_MESSAGE_SUBJECT); - clusterCommunicator.removeSubscriber(ANTI_ENTROPY_MESSAGE_SUBJECT); - - replay(clusterCommunicator); - - ecMap.destroy(); - - verify(clusterCommunicator); - - try { - ecMap.get(KEY1); - fail("get after destroy should throw exception"); - } catch (IllegalStateException e) { - assertTrue(true); - } - - try { - ecMap.put(KEY1, VALUE1); - fail("put after destroy should throw exception"); - } catch (IllegalStateException e) { - assertTrue(true); - } - } - - private UpdateEntry<String, String> generatePutMessage(String key, String value, Timestamp timestamp) { - return new UpdateEntry<>(key, new MapValue<>(value, timestamp)); - } - - private List<UpdateEntry<String, String>> generatePutMessage( - String key1, String value1, String key2, String value2) { - List<UpdateEntry<String, String>> list = new ArrayList<>(); - - Timestamp timestamp1 = clockService.peek(1); - Timestamp timestamp2 = clockService.peek(2); - - list.add(generatePutMessage(key1, value1, timestamp1)); - list.add(generatePutMessage(key2, value2, timestamp2)); - - return list; - } - - private UpdateEntry<String, String> generateRemoveMessage(String key, Timestamp timestamp) { - return new UpdateEntry<>(key, new MapValue<>(null, timestamp)); - } - - private List<UpdateEntry<String, String>> generateRemoveMessage(String key1, String key2) { - List<UpdateEntry<String, String>> list = new ArrayList<>(); - - Timestamp timestamp1 = clockService.peek(1); - Timestamp timestamp2 = clockService.peek(2); - - list.add(generateRemoveMessage(key1, timestamp1)); - list.add(generateRemoveMessage(key2, timestamp2)); - - return list; - } - - /** - * Sets up a mock ClusterCommunicationService to expect a specific cluster - * message to be broadcast to the cluster. - * - * @param message message we expect to be sent - * @param clusterCommunicator a mock ClusterCommunicationService to set up - */ - //FIXME rename - private static <T> void expectSpecificBroadcastMessage( - T message, - MessageSubject subject, - ClusterCommunicationService clusterCommunicator) { - reset(clusterCommunicator); - clusterCommunicator.<T>multicast(eq(message), eq(subject), anyObject(Function.class), anyObject(Set.class)); - expectLastCall().anyTimes(); - replay(clusterCommunicator); - } - - /** - * Sets up a mock ClusterCommunicationService to expect a specific cluster - * message to be multicast to the cluster. - * - * @param message message we expect to be sent - * @param subject subject we expect to be sent to - * @param clusterCommunicator a mock ClusterCommunicationService to set up - */ - //FIXME rename - private static <T> void expectSpecificMulticastMessage(T message, MessageSubject subject, - ClusterCommunicationService clusterCommunicator) { - reset(clusterCommunicator); - clusterCommunicator.<T>multicast(eq(message), eq(subject), anyObject(Function.class), anyObject(Set.class)); - expectLastCall().anyTimes(); - replay(clusterCommunicator); - } - - - /** - * Sets up a mock ClusterCommunicationService to expect a multicast cluster message - * that is sent to it. This is useful for unit tests where we aren't - * interested in testing the messaging component. - * - * @param clusterCommunicator a mock ClusterCommunicationService to set up - */ - //FIXME rename - private <T> void expectPeerMessage(ClusterCommunicationService clusterCommunicator) { - reset(clusterCommunicator); -// expect(clusterCommunicator.multicast(anyObject(ClusterMessage.class), -// anyObject(Iterable.class))) - expect(clusterCommunicator.<T>unicast( - anyObject(), - anyObject(MessageSubject.class), - anyObject(Function.class), - anyObject(NodeId.class))) - .andReturn(CompletableFuture.completedFuture(null)) - .anyTimes(); - replay(clusterCommunicator); - } - - /** - * Sets up a mock ClusterCommunicationService to expect a broadcast cluster message - * that is sent to it. This is useful for unit tests where we aren't - * interested in testing the messaging component. - * - * @param clusterCommunicator a mock ClusterCommunicationService to set up - */ - private void expectBroadcastMessage(ClusterCommunicationService clusterCommunicator) { - reset(clusterCommunicator); - clusterCommunicator.<AbstractEvent>multicast( - anyObject(AbstractEvent.class), - anyObject(MessageSubject.class), - anyObject(Function.class), - anyObject(Set.class)); - expectLastCall().anyTimes(); - replay(clusterCommunicator); - } - - /** - * ClusterCommunicationService implementation that the map's addSubscriber - * call will delegate to. This means we can get a reference to the - * internal cluster message handler used by the map, so that we can simulate - * events coming in from other instances. - */ - private final class TestClusterCommunicationService - extends ClusterCommunicationServiceAdapter { - - @Override - public <M> void addSubscriber(MessageSubject subject, - Function<byte[], M> decoder, Consumer<M> handler, - Executor executor) { - if (subject.equals(UPDATE_MESSAGE_SUBJECT)) { - updateHandler = (Consumer<Collection<UpdateEntry<String, String>>>) handler; - } else if (subject.equals(ANTI_ENTROPY_MESSAGE_SUBJECT)) { - antiEntropyHandler = (Consumer<AntiEntropyAdvertisement<String>>) handler; - } else { - throw new RuntimeException("Unexpected message subject " + subject.toString()); - } - } - } - - /** - * ClockService implementation that gives out timestamps based on a - * sequential counter. This clock service enables more control over the - * timestamps that are given out, including being able to "turn back time" - * to give out timestamps from the past. - * - * @param <T> Type that the clock service will give out timestamps for - * @param <U> Second type that the clock service will give out values for - */ - private class SequentialClockService<T, U> { - - private static final long INITIAL_VALUE = 1; - private final AtomicLong counter = new AtomicLong(INITIAL_VALUE); - - public Timestamp getTimestamp(T object, U object2) { - return new TestTimestamp(counter.getAndIncrement()); - } - - /** - * Returns what the next timestamp will be without consuming the - * timestamp. This allows test code to set expectations correctly while - * still allowing the CUT to get the same timestamp. - * - * @return timestamp equal to the timestamp that will be returned by the - * next call to {@link #getTimestamp(T, U)}. - */ - public Timestamp peekAtNextTimestamp() { - return peek(1); - } - - /** - * Returns the ith timestamp to be given out in the future without - * consuming the timestamp. For example, i=1 returns the next timestamp, - * i=2 returns the timestamp after that, and so on. - * - * @param i number of the timestamp to peek at - * @return the ith timestamp that will be given out - */ - public Timestamp peek(int i) { - checkArgument(i > 0, "i must be a positive integer"); - - return new TestTimestamp(counter.get() + i - 1); - } - - /** - * Turns the clock back two ticks, so the next call to getTimestamp will - * return an older timestamp than the previous call to getTimestamp. - */ - public void turnBackTime() { - // Not atomic, but should be OK for these tests. - counter.decrementAndGet(); - counter.decrementAndGet(); - } - - } - - /** - * Timestamp implementation where the value of the timestamp can be - * specified explicitly at creation time. - */ - private class TestTimestamp implements Timestamp { - - private final long timestamp; - - /** - * Creates a new timestamp that has the specified value. - * - * @param timestamp value of the timestamp - */ - public TestTimestamp(long timestamp) { - this.timestamp = timestamp; - } - - @Override - public int compareTo(Timestamp o) { - checkArgument(o instanceof TestTimestamp); - TestTimestamp otherTimestamp = (TestTimestamp) o; - return ComparisonChain.start() - .compare(this.timestamp, otherTimestamp.timestamp) - .result(); - } - } - - /** - * EventuallyConsistentMapListener implementation which triggers a latch - * when it receives an event. - */ - private class TestListener implements EventuallyConsistentMapListener<String, String> { - private CountDownLatch latch; - - /** - * Creates a new listener that will trigger the specified latch when it - * receives and event. - * - * @param latch the latch to trigger on events - */ - public TestListener(CountDownLatch latch) { - this.latch = latch; - } - - @Override - public void event(EventuallyConsistentMapEvent<String, String> event) { - latch.countDown(); - } - } -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/MapValueTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/MapValueTest.java deleted file mode 100644 index d6dca9b8..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/MapValueTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.ecmap; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.onosproject.store.Timestamp; -import org.onosproject.store.ecmap.MapValue.Digest; -import org.onosproject.store.impl.LogicalTimestamp; - -/** - * Unit tests for MapValue. - */ -public class MapValueTest { - - @Test - public void testConstruction() { - Timestamp ts = new LogicalTimestamp(10); - MapValue<String> mv = new MapValue<>("foo", ts); - assertEquals("foo", mv.get()); - assertEquals(ts, mv.timestamp()); - assertTrue(mv.isAlive()); - } - - @Test - public void testDigest() { - Timestamp ts = new LogicalTimestamp(10); - MapValue<String> mv = new MapValue<>("foo", ts); - Digest actual = mv.digest(); - Digest expected = new MapValue.Digest(ts, false); - assertEquals(actual, expected); - } - - @Test - public void testComparison() { - Timestamp ts1 = new LogicalTimestamp(9); - Timestamp ts2 = new LogicalTimestamp(10); - Timestamp ts3 = new LogicalTimestamp(11); - MapValue<String> mv1 = new MapValue<>("foo", ts1); - MapValue<String> mv2 = new MapValue<>("foo", ts2); - MapValue<String> mv3 = new MapValue<>("foo", ts3); - assertTrue(mv2.isNewerThan(mv1)); - assertFalse(mv1.isNewerThan(mv3)); - - assertTrue(mv3.isNewerThan(ts2)); - assertFalse(mv1.isNewerThan(ts2)); - - assertTrue(mv1.compareTo(mv2) < 0); - assertTrue(mv1.compareTo(mv1) == 0); - assertTrue(mv3.compareTo(mv2) > 0); - } - - @Test - public void testTombstone() { - Timestamp ts1 = new LogicalTimestamp(9); - MapValue<String> mv = MapValue.tombstone(ts1); - assertTrue(mv.isTombstone()); - assertFalse(mv.isAlive()); - assertNull(mv.get()); - assertEquals(ts1, mv.timestamp()); - } -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/flow/impl/ReplicaInfoManagerTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/flow/impl/ReplicaInfoManagerTest.java deleted file mode 100644 index 76ff8045..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/flow/impl/ReplicaInfoManagerTest.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.flow.impl; - -import com.google.common.base.Optional; -import com.google.common.collect.Maps; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.onosproject.cluster.NodeId; -import org.onosproject.cluster.RoleInfo; -import org.onosproject.common.event.impl.TestEventDispatcher; -import org.onosproject.event.ListenerRegistry; -import org.onosproject.mastership.MastershipEvent; -import org.onosproject.mastership.MastershipEvent.Type; -import org.onosproject.mastership.MastershipListener; -import org.onosproject.mastership.MastershipService; -import org.onosproject.mastership.MastershipServiceAdapter; -import org.onosproject.net.DeviceId; -import org.onosproject.store.flow.ReplicaInfo; -import org.onosproject.store.flow.ReplicaInfoEvent; -import org.onosproject.store.flow.ReplicaInfoEventListener; -import org.onosproject.store.flow.ReplicaInfoService; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class ReplicaInfoManagerTest { - - - private static final DeviceId DID1 = DeviceId.deviceId("of:1"); - private static final DeviceId DID2 = DeviceId.deviceId("of:2"); - private static final NodeId NID1 = new NodeId("foo"); - - private ReplicaInfoManager mgr; - private ReplicaInfoService service; - - private ListenerRegistry<MastershipEvent, MastershipListener> - mastershipListenerRegistry; - private TestEventDispatcher eventDispatcher; - - - @Before - public void setUp() throws Exception { - mastershipListenerRegistry = new ListenerRegistry<>(); - - mgr = new ReplicaInfoManager(); - service = mgr; - - eventDispatcher = new TestEventDispatcher(); - mgr.eventDispatcher = eventDispatcher; - mgr.mastershipService = new TestMastershipService(); - - // register dummy mastership event source - mgr.eventDispatcher.addSink(MastershipEvent.class, mastershipListenerRegistry); - - mgr.activate(); - } - - @After - public void tearDown() throws Exception { - mgr.deactivate(); - } - - @Test - public void testGetReplicaInfoFor() { - ReplicaInfo info1 = service.getReplicaInfoFor(DID1); - assertEquals(Optional.of(NID1), info1.master()); - // backups are always empty for now - assertEquals(Collections.emptyList(), info1.backups()); - - ReplicaInfo info2 = service.getReplicaInfoFor(DID2); - assertEquals("There's no master", Optional.absent(), info2.master()); - // backups are always empty for now - assertEquals(Collections.emptyList(), info2.backups()); - } - - @Test - public void testReplicaInfoEvent() throws InterruptedException { - final CountDownLatch latch = new CountDownLatch(1); - service.addListener(new MasterNodeCheck(latch, DID1, NID1)); - - // fake MastershipEvent - eventDispatcher.post(new MastershipEvent(Type.MASTER_CHANGED, DID1, - new RoleInfo(NID1, new LinkedList<>()))); - - assertTrue(latch.await(1, TimeUnit.SECONDS)); - } - - - private final class MasterNodeCheck implements ReplicaInfoEventListener { - private final CountDownLatch latch; - private Optional<NodeId> expectedMaster; - private DeviceId expectedDevice; - - - MasterNodeCheck(CountDownLatch latch, DeviceId did, - NodeId nid) { - this.latch = latch; - this.expectedMaster = Optional.fromNullable(nid); - this.expectedDevice = did; - } - - @Override - public void event(ReplicaInfoEvent event) { - assertEquals(expectedDevice, event.subject()); - assertEquals(expectedMaster, event.replicaInfo().master()); - // backups are always empty for now - assertEquals(Collections.emptyList(), event.replicaInfo().backups()); - latch.countDown(); - } - } - - - private final class TestMastershipService - extends MastershipServiceAdapter - implements MastershipService { - - private Map<DeviceId, NodeId> masters; - - TestMastershipService() { - masters = Maps.newHashMap(); - masters.put(DID1, NID1); - // DID2 has no master - } - - @Override - public NodeId getMasterFor(DeviceId deviceId) { - return masters.get(deviceId); - } - - @Override - public RoleInfo getNodesFor(DeviceId deviceId) { - return new RoleInfo(masters.get(deviceId), Collections.emptyList()); - } - - @Override - public void addListener(MastershipListener listener) { - mastershipListenerRegistry.addListener(listener); - } - - @Override - public void removeListener(MastershipListener listener) { - mastershipListenerRegistry.removeListener(listener); - } - } - -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/flowobjective/impl/DistributedFlowObjectiveStoreTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/flowobjective/impl/DistributedFlowObjectiveStoreTest.java deleted file mode 100644 index efa226c1..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/flowobjective/impl/DistributedFlowObjectiveStoreTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.flowobjective.impl; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.onosproject.net.behaviour.DefaultNextGroup; -import org.onosproject.net.behaviour.NextGroup; -import org.onosproject.net.flowobjective.FlowObjectiveStore; -import org.onosproject.store.service.TestStorageService; - -import com.google.common.base.Charsets; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; - -/** - * Unit tests for distributed flow objective store. - */ -public class DistributedFlowObjectiveStoreTest { - DistributedFlowObjectiveStore storeImpl; - FlowObjectiveStore store; - - @Before - public void setUp() { - storeImpl = new DistributedFlowObjectiveStore(); - storeImpl.storageService = new TestStorageService(); - storeImpl.activate(); - store = storeImpl; - } - - @After - public void tearDown() { - storeImpl.deactivate(); - } - - @Test - public void testFlowObjectiveStore() { - NextGroup group2 = new DefaultNextGroup("2".getBytes(Charsets.US_ASCII)); - int group1Id = store.allocateNextId(); - int group2Id = store.allocateNextId(); - - NextGroup group1add = store.getNextGroup(group1Id); - assertThat(group1add, nullValue()); - - store.putNextGroup(group2Id, group2); - NextGroup group2Query = store.getNextGroup(group2Id); - assertThat(group2Query.data(), is(group2.data())); - } -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/group/impl/DistributedGroupStoreTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/group/impl/DistributedGroupStoreTest.java deleted file mode 100644 index 560fdb3a..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/group/impl/DistributedGroupStoreTest.java +++ /dev/null @@ -1,420 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.group.impl; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.onlab.junit.TestUtils; -import org.onosproject.core.DefaultGroupId; -import org.onosproject.core.GroupId; -import org.onosproject.mastership.MastershipServiceAdapter; -import org.onosproject.net.DeviceId; -import org.onosproject.net.MastershipRole; -import org.onosproject.net.PortNumber; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.TrafficTreatment; -import org.onosproject.net.group.DefaultGroup; -import org.onosproject.net.group.DefaultGroupBucket; -import org.onosproject.net.group.DefaultGroupDescription; -import org.onosproject.net.group.DefaultGroupKey; -import org.onosproject.net.group.Group; -import org.onosproject.net.group.GroupBucket; -import org.onosproject.net.group.GroupBuckets; -import org.onosproject.net.group.GroupDescription; -import org.onosproject.net.group.GroupEvent; -import org.onosproject.net.group.GroupKey; -import org.onosproject.net.group.GroupOperation; -import org.onosproject.net.group.GroupStore; -import org.onosproject.net.group.GroupStoreDelegate; -import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.TestStorageService; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.common.testing.EqualsTester; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; -import static org.onosproject.net.NetTestTools.APP_ID; -import static org.onosproject.net.NetTestTools.did; - -/** - * Distributed group store test. - */ -public class DistributedGroupStoreTest { - - DeviceId deviceId1 = did("dev1"); - DeviceId deviceId2 = did("dev2"); - GroupId groupId1 = new DefaultGroupId(1); - GroupId groupId2 = new DefaultGroupId(2); - GroupKey groupKey1 = new DefaultGroupKey("abc".getBytes()); - GroupKey groupKey2 = new DefaultGroupKey("def".getBytes()); - - TrafficTreatment treatment = - DefaultTrafficTreatment.emptyTreatment(); - GroupBucket selectGroupBucket = - DefaultGroupBucket.createSelectGroupBucket(treatment); - GroupBucket failoverGroupBucket = - DefaultGroupBucket.createFailoverGroupBucket(treatment, - PortNumber.IN_PORT, groupId1); - - GroupBuckets buckets = new GroupBuckets(ImmutableList.of(selectGroupBucket)); - GroupDescription groupDescription1 = new DefaultGroupDescription( - deviceId1, - GroupDescription.Type.INDIRECT, - buckets, - groupKey1, - groupId1.id(), - APP_ID); - GroupDescription groupDescription2 = new DefaultGroupDescription( - deviceId2, - GroupDescription.Type.INDIRECT, - buckets, - groupKey2, - groupId2.id(), - APP_ID); - - DistributedGroupStore groupStoreImpl; - GroupStore groupStore; - EventuallyConsistentMap auditPendingReqQueue; - - static class MasterOfAll extends MastershipServiceAdapter { - @Override - public MastershipRole getLocalRole(DeviceId deviceId) { - return MastershipRole.MASTER; - } - } - - @Before - public void setUp() throws Exception { - groupStoreImpl = new DistributedGroupStore(); - groupStoreImpl.storageService = new TestStorageService(); - groupStoreImpl.clusterCommunicator = new ClusterCommunicationServiceAdapter(); - groupStoreImpl.mastershipService = new MasterOfAll(); - groupStoreImpl.activate(); - groupStore = groupStoreImpl; - auditPendingReqQueue = - TestUtils.getField(groupStoreImpl, "auditPendingReqQueue"); - } - - @After - public void tearDown() throws Exception { - groupStoreImpl.deactivate(); - } - - /** - * Tests the initial state of the store. - */ - @Test - public void testEmptyStore() { - assertThat(groupStore.getGroupCount(deviceId1), is(0)); - assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue()); - assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue()); - } - - /** - * Tests adding a pending group. - */ - @Test - public void testAddPendingGroup() throws Exception { - // Make sure the pending list starts out empty - assertThat(auditPendingReqQueue.size(), is(0)); - - // Add a new pending group. Make sure that the store remains empty - groupStore.storeGroupDescription(groupDescription1); - assertThat(groupStore.getGroupCount(deviceId1), is(0)); - assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue()); - assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue()); - - // Make sure the group is pending - assertThat(auditPendingReqQueue.size(), is(1)); - - groupStore.deviceInitialAuditCompleted(deviceId1, true); - - // Make sure the group isn't pending anymore - assertThat(auditPendingReqQueue.size(), is(0)); - } - - - /** - * Tests adding and removing a group. - */ - @Test - public void testAddRemoveGroup() throws Exception { - groupStore.deviceInitialAuditCompleted(deviceId1, true); - assertThat(groupStore.deviceInitialAuditStatus(deviceId1), is(true)); - - // Make sure the pending list starts out empty - assertThat(auditPendingReqQueue.size(), is(0)); - - groupStore.storeGroupDescription(groupDescription1); - assertThat(groupStore.getGroupCount(deviceId1), is(1)); - assertThat(groupStore.getGroup(deviceId1, groupId1), notNullValue()); - assertThat(groupStore.getGroup(deviceId1, groupKey1), notNullValue()); - - // Make sure that nothing is pending - assertThat(auditPendingReqQueue.size(), is(0)); - - Group groupById = groupStore.getGroup(deviceId1, groupId1); - Group groupByKey = groupStore.getGroup(deviceId1, groupKey1); - assertThat(groupById, notNullValue()); - assertThat(groupByKey, notNullValue()); - assertThat(groupById, is(groupByKey)); - assertThat(groupById.deviceId(), is(did("dev1"))); - - groupStore.removeGroupEntry(groupById); - - assertThat(groupStore.getGroupCount(deviceId1), is(0)); - assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue()); - assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue()); - - // Make sure that nothing is pending - assertThat(auditPendingReqQueue.size(), is(0)); - } - - /** - * Tests adding and removing a group. - */ - @Test - public void testRemoveGroupDescription() throws Exception { - groupStore.deviceInitialAuditCompleted(deviceId1, true); - - groupStore.storeGroupDescription(groupDescription1); - - groupStore.deleteGroupDescription(deviceId1, groupKey1); - - // Group should still be there, marked for removal - assertThat(groupStore.getGroupCount(deviceId1), is(1)); - Group queriedGroup = groupStore.getGroup(deviceId1, groupId1); - assertThat(queriedGroup.state(), is(Group.GroupState.PENDING_DELETE)); - - } - - /** - * Tests pushing group metrics. - */ - @Test - public void testPushGroupMetrics() { - groupStore.deviceInitialAuditCompleted(deviceId1, true); - groupStore.deviceInitialAuditCompleted(deviceId2, true); - - GroupDescription groupDescription3 = new DefaultGroupDescription( - deviceId1, - GroupDescription.Type.SELECT, - buckets, - new DefaultGroupKey("aaa".getBytes()), - null, - APP_ID); - - groupStore.storeGroupDescription(groupDescription1); - groupStore.storeGroupDescription(groupDescription2); - groupStore.storeGroupDescription(groupDescription3); - Group group1 = groupStore.getGroup(deviceId1, groupId1); - - assertThat(group1, instanceOf(DefaultGroup.class)); - DefaultGroup defaultGroup1 = (DefaultGroup) group1; - defaultGroup1.setPackets(55L); - defaultGroup1.setBytes(66L); - groupStore.pushGroupMetrics(deviceId1, ImmutableList.of(group1)); - - // Make sure the group was updated. - - Group requeryGroup1 = groupStore.getGroup(deviceId1, groupId1); - assertThat(requeryGroup1.packets(), is(55L)); - assertThat(requeryGroup1.bytes(), is(66L)); - - } - - class TestDelegate implements GroupStoreDelegate { - private List<GroupEvent> eventsSeen = new LinkedList<>(); - @Override - public void notify(GroupEvent event) { - eventsSeen.add(event); - } - - public List<GroupEvent> eventsSeen() { - return eventsSeen; - } - - public void resetEvents() { - eventsSeen.clear(); - } - } - - /** - * Tests group operation failed interface. - */ - @Test - public void testGroupOperationFailed() { - TestDelegate delegate = new TestDelegate(); - groupStore.setDelegate(delegate); - groupStore.deviceInitialAuditCompleted(deviceId1, true); - groupStore.deviceInitialAuditCompleted(deviceId2, true); - - groupStore.storeGroupDescription(groupDescription1); - groupStore.storeGroupDescription(groupDescription2); - - List<GroupEvent> eventsAfterAdds = delegate.eventsSeen(); - assertThat(eventsAfterAdds, hasSize(2)); - eventsAfterAdds.stream().forEach(event -> assertThat(event.type(), is(GroupEvent.Type.GROUP_ADD_REQUESTED))); - delegate.resetEvents(); - - GroupOperation opAdd = - GroupOperation.createAddGroupOperation(groupId1, - GroupDescription.Type.INDIRECT, - buckets); - groupStore.groupOperationFailed(deviceId1, opAdd); - - List<GroupEvent> eventsAfterAddFailed = delegate.eventsSeen(); - assertThat(eventsAfterAddFailed, hasSize(2)); - assertThat(eventsAfterAddFailed.get(0).type(), - is(GroupEvent.Type.GROUP_ADD_FAILED)); - assertThat(eventsAfterAddFailed.get(1).type(), - is(GroupEvent.Type.GROUP_REMOVED)); - delegate.resetEvents(); - - GroupOperation opModify = - GroupOperation.createModifyGroupOperation(groupId2, - GroupDescription.Type.INDIRECT, - buckets); - groupStore.groupOperationFailed(deviceId2, opModify); - List<GroupEvent> eventsAfterModifyFailed = delegate.eventsSeen(); - assertThat(eventsAfterModifyFailed, hasSize(1)); - assertThat(eventsAfterModifyFailed.get(0).type(), - is(GroupEvent.Type.GROUP_UPDATE_FAILED)); - delegate.resetEvents(); - - GroupOperation opDelete = - GroupOperation.createDeleteGroupOperation(groupId2, - GroupDescription.Type.INDIRECT); - groupStore.groupOperationFailed(deviceId2, opDelete); - List<GroupEvent> eventsAfterDeleteFailed = delegate.eventsSeen(); - assertThat(eventsAfterDeleteFailed, hasSize(1)); - assertThat(eventsAfterDeleteFailed.get(0).type(), - is(GroupEvent.Type.GROUP_REMOVE_FAILED)); - delegate.resetEvents(); - } - - /** - * Tests extraneous group operations. - */ - @Test - public void testExtraneousOperations() { - ArrayList<Group> extraneous; - groupStore.deviceInitialAuditCompleted(deviceId1, true); - - groupStore.storeGroupDescription(groupDescription1); - Group group1 = groupStore.getGroup(deviceId1, groupId1); - - extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1)); - assertThat(extraneous, hasSize(0)); - - groupStore.addOrUpdateExtraneousGroupEntry(group1); - extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1)); - assertThat(extraneous, hasSize(1)); - - groupStore.removeExtraneousGroupEntry(group1); - extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1)); - assertThat(extraneous, hasSize(0)); - } - - /** - * Tests updating of group descriptions. - */ - @Test - public void testUpdateGroupDescription() { - - GroupBuckets buckets = - new GroupBuckets(ImmutableList.of(failoverGroupBucket)); - - groupStore.deviceInitialAuditCompleted(deviceId1, true); - groupStore.storeGroupDescription(groupDescription1); - - GroupKey newKey = new DefaultGroupKey("123".getBytes()); - groupStore.updateGroupDescription(deviceId1, - groupKey1, - GroupStore.UpdateType.ADD, - buckets, - newKey); - Group group1 = groupStore.getGroup(deviceId1, groupId1); - assertThat(group1.appCookie(), is(newKey)); - assertThat(group1.buckets().buckets(), hasSize(2)); - } - - @Test - public void testEqualsGroupStoreIdMapKey() { - DistributedGroupStore.GroupStoreIdMapKey key1 = - new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId1); - DistributedGroupStore.GroupStoreIdMapKey sameAsKey1 = - new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId1); - DistributedGroupStore.GroupStoreIdMapKey key2 = - new DistributedGroupStore.GroupStoreIdMapKey(deviceId2, groupId1); - DistributedGroupStore.GroupStoreIdMapKey key3 = - new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId2); - - new EqualsTester() - .addEqualityGroup(key1, sameAsKey1) - .addEqualityGroup(key2) - .addEqualityGroup(key3) - .testEquals(); - } - - @Test - public void testEqualsGroupStoreKeyMapKey() { - DistributedGroupStore.GroupStoreKeyMapKey key1 = - new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey1); - DistributedGroupStore.GroupStoreKeyMapKey sameAsKey1 = - new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey1); - DistributedGroupStore.GroupStoreKeyMapKey key2 = - new DistributedGroupStore.GroupStoreKeyMapKey(deviceId2, groupKey1); - DistributedGroupStore.GroupStoreKeyMapKey key3 = - new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey2); - - new EqualsTester() - .addEqualityGroup(key1, sameAsKey1) - .addEqualityGroup(key2) - .addEqualityGroup(key3) - .testEquals(); - } - - @Test - public void testEqualsGroupStoreMapKey() { - DistributedGroupStore.GroupStoreMapKey key1 = - new DistributedGroupStore.GroupStoreMapKey(deviceId1); - DistributedGroupStore.GroupStoreMapKey sameAsKey1 = - new DistributedGroupStore.GroupStoreMapKey(deviceId1); - DistributedGroupStore.GroupStoreMapKey key2 = - new DistributedGroupStore.GroupStoreMapKey(deviceId2); - DistributedGroupStore.GroupStoreMapKey key3 = - new DistributedGroupStore.GroupStoreMapKey(did("dev3")); - - new EqualsTester() - .addEqualityGroup(key1, sameAsKey1) - .addEqualityGroup(key2) - .addEqualityGroup(key3) - .testEquals(); - } -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java deleted file mode 100644 index 0732126d..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.host.impl; - -import junit.framework.TestCase; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.onlab.packet.IpAddress; -import org.onlab.packet.MacAddress; -import org.onosproject.net.Host; -import org.onosproject.net.HostId; -import org.onosproject.net.HostLocation; -import org.onosproject.net.host.DefaultHostDescription; -import org.onosproject.net.host.HostDescription; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.service.TestStorageService; - -import java.util.HashSet; -import java.util.Set; - -/** - * Tests for the ECHostStore. - */ -public class DistributedHostStoreTest extends TestCase { - - private DistributedHostStore ecXHostStore; - - private static final HostId HOSTID = HostId.hostId(MacAddress.valueOf("1a:1a:1a:1a:1a:1a")); - - private static final IpAddress IP1 = IpAddress.valueOf("10.2.0.2"); - private static final IpAddress IP2 = IpAddress.valueOf("10.2.0.3"); - - private static final ProviderId PID = new ProviderId("of", "foo"); - - @Before - public void setUp() { - ecXHostStore = new DistributedHostStore(); - - ecXHostStore.storageService = new TestStorageService(); - ecXHostStore.activate(); - } - - @After - public void tearDown() { - ecXHostStore.deactivate(); - } - - /** - * Tests the removeIp method call. - */ - @Test - public void testRemoveIp() { - Set<IpAddress> ips = new HashSet<>(); - ips.add(IP1); - ips.add(IP2); - - HostDescription description = new DefaultHostDescription(HOSTID.mac(), - HOSTID.vlanId(), - HostLocation.NONE, - ips); - ecXHostStore.createOrUpdateHost(PID, HOSTID, description, false); - ecXHostStore.removeIp(HOSTID, IP1); - Host host = ecXHostStore.getHost(HOSTID); - - assertFalse(host.ipAddresses().contains(IP1)); - assertTrue(host.ipAddresses().contains(IP2)); - } - -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/impl/MastershipBasedTimestampTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/impl/MastershipBasedTimestampTest.java deleted file mode 100644 index eb9d324e..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/impl/MastershipBasedTimestampTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.impl; - -import static org.junit.Assert.*; - -import java.nio.ByteBuffer; - -import org.junit.Test; -import org.onosproject.store.Timestamp; -import org.onosproject.store.serializers.custom.MastershipBasedTimestampSerializer; -import org.onlab.util.KryoNamespace; - -import com.google.common.testing.EqualsTester; - -/** - * Test of {@link MastershipBasedTimestamp}. - */ -public class MastershipBasedTimestampTest { - - private static final Timestamp TS_1_1 = new MastershipBasedTimestamp(1, 1); - private static final Timestamp TS_1_2 = new MastershipBasedTimestamp(1, 2); - private static final Timestamp TS_2_1 = new MastershipBasedTimestamp(2, 1); - private static final Timestamp TS_2_2 = new MastershipBasedTimestamp(2, 2); - - @Test - public final void testBasic() { - final int termNumber = 5; - final int sequenceNumber = 6; - MastershipBasedTimestamp ts = new MastershipBasedTimestamp(termNumber, - sequenceNumber); - - assertEquals(termNumber, ts.termNumber()); - assertEquals(sequenceNumber, ts.sequenceNumber()); - } - - @Test - public final void testCompareTo() { - assertTrue(TS_1_1.compareTo(TS_1_1) == 0); - assertTrue(TS_1_1.compareTo(new MastershipBasedTimestamp(1, 1)) == 0); - - assertTrue(TS_1_1.compareTo(TS_1_2) < 0); - assertTrue(TS_1_2.compareTo(TS_1_1) > 0); - - assertTrue(TS_1_2.compareTo(TS_2_1) < 0); - assertTrue(TS_1_2.compareTo(TS_2_2) < 0); - assertTrue(TS_2_1.compareTo(TS_1_1) > 0); - assertTrue(TS_2_2.compareTo(TS_1_1) > 0); - } - - @Test - public final void testEqualsObject() { - new EqualsTester() - .addEqualityGroup(new MastershipBasedTimestamp(1, 1), - new MastershipBasedTimestamp(1, 1), TS_1_1) - .addEqualityGroup(new MastershipBasedTimestamp(1, 2), - new MastershipBasedTimestamp(1, 2), TS_1_2) - .addEqualityGroup(new MastershipBasedTimestamp(2, 1), - new MastershipBasedTimestamp(2, 1), TS_2_1) - .addEqualityGroup(new MastershipBasedTimestamp(2, 2), - new MastershipBasedTimestamp(2, 2), TS_2_2) - .testEquals(); - } - - @Test - public final void testKryoSerializable() { - final ByteBuffer buffer = ByteBuffer.allocate(1 * 1024 * 1024); - final KryoNamespace kryos = KryoNamespace.newBuilder() - .register(MastershipBasedTimestamp.class) - .build(); - - kryos.serialize(TS_2_1, buffer); - buffer.flip(); - Timestamp copy = kryos.deserialize(buffer); - - new EqualsTester() - .addEqualityGroup(TS_2_1, copy) - .testEquals(); - } - - @Test - public final void testKryoSerializableWithHandcraftedSerializer() { - final ByteBuffer buffer = ByteBuffer.allocate(1 * 1024 * 1024); - final KryoNamespace kryos = KryoNamespace.newBuilder() - .register(new MastershipBasedTimestampSerializer(), MastershipBasedTimestamp.class) - .build(); - - kryos.serialize(TS_1_2, buffer); - buffer.flip(); - Timestamp copy = kryos.deserialize(buffer); - - new EqualsTester() - .addEqualityGroup(TS_1_2, copy) - .testEquals(); - } - -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/impl/TimestampedTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/impl/TimestampedTest.java deleted file mode 100644 index c47eb27a..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/impl/TimestampedTest.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.impl; - -import static org.junit.Assert.*; - -import java.nio.ByteBuffer; - -import org.junit.Test; -import org.onosproject.store.Timestamp; -import org.onlab.util.KryoNamespace; - -import com.google.common.testing.EqualsTester; - -/** - * Test of {@link Timestamped}. - */ -public class TimestampedTest { - - private static final Timestamp TS_1_1 = new MastershipBasedTimestamp(1, 1); - private static final Timestamp TS_1_2 = new MastershipBasedTimestamp(1, 2); - private static final Timestamp TS_2_1 = new MastershipBasedTimestamp(2, 1); - - @Test - public final void testHashCode() { - Timestamped<String> a = new Timestamped<>("a", TS_1_1); - Timestamped<String> b = new Timestamped<>("b", TS_1_1); - assertTrue("value does not impact hashCode", - a.hashCode() == b.hashCode()); - } - - @Test - public final void testEquals() { - Timestamped<String> a = new Timestamped<>("a", TS_1_1); - Timestamped<String> b = new Timestamped<>("b", TS_1_1); - assertTrue("value does not impact equality", - a.equals(b)); - - new EqualsTester() - .addEqualityGroup(new Timestamped<>("a", TS_1_1), - new Timestamped<>("b", TS_1_1), - new Timestamped<>("c", TS_1_1)) - .addEqualityGroup(new Timestamped<>("a", TS_1_2), - new Timestamped<>("b", TS_1_2), - new Timestamped<>("c", TS_1_2)) - .addEqualityGroup(new Timestamped<>("a", TS_2_1), - new Timestamped<>("b", TS_2_1), - new Timestamped<>("c", TS_2_1)) - .testEquals(); - - } - - @Test - public final void testValue() { - final Integer n = 42; - Timestamped<Integer> tsv = new Timestamped<>(n, TS_1_1); - assertSame(n, tsv.value()); - - } - - @Test(expected = NullPointerException.class) - public final void testValueNonNull() { - new Timestamped<>(null, TS_1_1); - } - - @Test(expected = NullPointerException.class) - public final void testTimestampNonNull() { - new Timestamped<>("Foo", null); - } - - @Test - public final void testIsNewer() { - Timestamped<String> a = new Timestamped<>("a", TS_1_2); - Timestamped<String> b = new Timestamped<>("b", TS_1_1); - assertTrue(a.isNewer(b)); - assertFalse(b.isNewer(a)); - } - - @Test - public final void testKryoSerializable() { - final ByteBuffer buffer = ByteBuffer.allocate(1 * 1024 * 1024); - final KryoNamespace kryos = KryoNamespace.newBuilder() - .register(Timestamped.class, - MastershipBasedTimestamp.class) - .build(); - - Timestamped<String> original = new Timestamped<>("foobar", TS_1_1); - kryos.serialize(original, buffer); - buffer.flip(); - Timestamped<String> copy = kryos.deserialize(buffer); - - new EqualsTester() - .addEqualityGroup(original, copy) - .testEquals(); - } -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/GossipIntentStoreTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/GossipIntentStoreTest.java deleted file mode 100644 index a74c3a2f..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/GossipIntentStoreTest.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.intent.impl; - -import java.util.LinkedList; -import java.util.List; -import java.util.stream.IntStream; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.onosproject.cluster.ClusterServiceAdapter; -import org.onosproject.core.IdGenerator; -import org.onosproject.net.intent.HostToHostIntent; -import org.onosproject.net.intent.Intent; -import org.onosproject.net.intent.IntentData; -import org.onosproject.net.intent.IntentState; -import org.onosproject.net.intent.IntentTestsMocks; -import org.onosproject.net.intent.MockIdGenerator; -import org.onosproject.net.intent.PartitionServiceAdapter; -import org.onosproject.store.service.TestStorageService; - -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; -import static org.onosproject.net.NetTestTools.APP_ID; -import static org.onosproject.net.NetTestTools.hid; - -/** - * Gossip Intent Store test using database adapter. - */ -public class GossipIntentStoreTest { - - private GossipIntentStore intentStore; - private IdGenerator idGenerator; - private HostToHostIntent.Builder builder1; - - @Before - public void setUp() { - intentStore = new GossipIntentStore(); - intentStore.storageService = new TestStorageService(); - intentStore.partitionService = new PartitionServiceAdapter(); - intentStore.clusterService = new ClusterServiceAdapter(); - idGenerator = new MockIdGenerator(); - Intent.bindIdGenerator(idGenerator); - builder1 = HostToHostIntent - .builder() - .one(hid("12:34:56:78:91:ab/1")) - .two(hid("12:34:56:78:91:ac/1")) - .appId(APP_ID); - intentStore.activate(); - } - - @After - public void cleanUp() { - intentStore.deactivate(); - Intent.unbindIdGenerator(idGenerator); - } - - /** - * Generates a list of test intent data. - * - * @param count how many intent data objects are needed - * @return list of intent data - */ - private List<IntentData> generateIntentList(int count) { - LinkedList<IntentData> intents = new LinkedList<>(); - IntStream.rangeClosed(1, count) - .forEach(i -> - intents.add( - new IntentData( - builder1 - .priority(i) - .build(), - IntentState.INSTALLED, - new IntentTestsMocks.MockTimestamp(12)))); - return intents; - } - - /** - * Tests the intent count APIs. - */ - @Test - public void testGetIntentCount() { - assertThat(intentStore.getIntentCount(), is(0L)); - - generateIntentList(5).forEach(intentStore::write); - - assertThat(intentStore.getIntentCount(), is(5L)); - } - - /** - * Tests the batch add API. - */ - @Test - public void testBatchAdd() { - assertThat(intentStore.getIntentCount(), is(0L)); - - List<IntentData> intents = generateIntentList(5); - - intentStore.batchWrite(intents); - assertThat(intentStore.getIntentCount(), is(5L)); - } - - - /** - * Tests adding and withdrawing an Intent. - */ - @Test - public void testAddAndWithdrawIntent() { - // build and install one intent - Intent intent = builder1.build(); - IntentData installed = new IntentData( - intent, - IntentState.INSTALLED, - new IntentTestsMocks.MockTimestamp(12)); - intentStore.write(installed); - - // check that the intent count includes the new one - assertThat(intentStore.getIntentCount(), is(1L)); - - // check that the getIntents() API returns the new intent - intentStore.getIntents() - .forEach(item -> assertThat(item, is(intent))); - - // check that the getInstallableIntents() API returns the new intent - intentStore.getInstallableIntents(intent.key()) - .forEach(item -> assertThat(item, is(intent))); - - // check that the getIntent() API can find the new intent - Intent queried = intentStore.getIntent(intent.key()); - assertThat(queried, is(intent)); - - // check that the state of the new intent is correct - IntentState state = intentStore.getIntentState(intent.key()); - assertThat(state, is(IntentState.INSTALLED)); - - // check that the getIntentData() API returns the proper value for the - // new intent - IntentData dataByQuery = intentStore.getIntentData(intent.key()); - assertThat(dataByQuery, is(installed)); - - // check that the getIntentData() API returns the new intent when given - // a time stamp to look for - Iterable<IntentData> dataIteratorByTime = intentStore.getIntentData(true, 10L); - assertThat(dataIteratorByTime.iterator().hasNext(), is(true)); - dataIteratorByTime.forEach( - data -> assertThat(data, is(installed)) - ); - - // check that the getIntentData() API returns the new intent when asked to - // find all intents - Iterable<IntentData> dataIteratorAll = intentStore.getIntentData(false, 0L); - assertThat(dataIteratorAll.iterator().hasNext(), is(true)); - dataIteratorAll.forEach( - data -> assertThat(data, is(installed)) - ); - - // now purge the intent that was created - IntentData purge = new IntentData( - intent, - IntentState.PURGE_REQ, - new IntentTestsMocks.MockTimestamp(12)); - intentStore.write(purge); - - // check that no intents are left - assertThat(intentStore.getIntentCount(), is(0L)); - - // check that a getIntent() operation on the key of the purged intent - // returns null - Intent queriedAfterWithdrawal = intentStore.getIntent(intent.key()); - assertThat(queriedAfterWithdrawal, nullValue()); - } - - /** - * Tests the operation of the APIs for the pending map. - */ - @Test - public void testPending() { - // crete a new intent and add it as pending - Intent intent = builder1.build(); - IntentData installed = new IntentData( - intent, - IntentState.INSTALLED, - new IntentTestsMocks.MockTimestamp(11)); - intentStore.addPending(installed); - - // check that the getPending() API returns the new pending intent - Iterable<Intent> pendingIntentIteratorAll = intentStore.getPending(); - assertThat(pendingIntentIteratorAll.iterator().hasNext(), is(true)); - pendingIntentIteratorAll.forEach( - data -> assertThat(data, is(intent)) - ); - - // check that the getPendingData() API returns the IntentData for the - // new pending intent - Iterable<IntentData> pendingDataIteratorAll = intentStore.getPendingData(); - assertThat(pendingDataIteratorAll.iterator().hasNext(), is(true)); - pendingDataIteratorAll.forEach( - data -> assertThat(data, is(installed)) - ); - - // check that the new pending intent is returned by the getPendingData() - // API when a time stamp is provided - Iterable<IntentData> pendingDataIteratorSelected = - intentStore.getPendingData(true, 10L); - assertThat(pendingDataIteratorSelected.iterator().hasNext(), is(true)); - pendingDataIteratorSelected.forEach( - data -> assertThat(data, is(installed)) - ); - - // check that the new pending intent is returned by the getPendingData() - // API when a time stamp is provided - Iterable<IntentData> pendingDataIteratorAllFromTimestamp = - intentStore.getPendingData(false, 0L); - assertThat(pendingDataIteratorAllFromTimestamp.iterator().hasNext(), is(true)); - pendingDataIteratorSelected.forEach( - data -> assertThat(data, is(installed)) - ); - } -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/PartitionManagerTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/PartitionManagerTest.java deleted file mode 100644 index 61d1937e..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/PartitionManagerTest.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.intent.impl; - -import org.junit.Before; -import org.junit.Test; -import org.onlab.junit.NullScheduledExecutor; -import org.onlab.packet.IpAddress; -import org.onosproject.cluster.ClusterServiceAdapter; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.DefaultControllerNode; -import org.onosproject.cluster.Leadership; -import org.onosproject.cluster.LeadershipEvent; -import org.onosproject.cluster.LeadershipEventListener; -import org.onosproject.cluster.LeadershipService; -import org.onosproject.cluster.LeadershipServiceAdapter; -import org.onosproject.cluster.NodeId; -import org.onosproject.common.event.impl.TestEventDispatcher; -import org.onosproject.net.intent.Key; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.CompletableFuture; - -import static junit.framework.TestCase.assertFalse; -import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.anyString; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.expectLastCall; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.reset; -import static org.easymock.EasyMock.verify; -import static org.junit.Assert.assertTrue; - -/** - * Unit tests for the PartitionManager class. - */ -public class PartitionManagerTest { - - private final LeadershipEvent event - = new LeadershipEvent(LeadershipEvent.Type.LEADER_ELECTED, - new Leadership(ELECTION_PREFIX + "0", - MY_NODE_ID, 0, 0)); - - private static final NodeId MY_NODE_ID = new NodeId("local"); - private static final NodeId OTHER_NODE_ID = new NodeId("other"); - private static final NodeId INACTIVE_NODE_ID = new NodeId("inactive"); - - private static final String ELECTION_PREFIX = "intent-partition-"; - - private LeadershipService leadershipService; - private LeadershipEventListener leaderListener; - - private PartitionManager partitionManager; - - @Before - public void setUp() { - leadershipService = createMock(LeadershipService.class); - - leadershipService.addListener(anyObject(LeadershipEventListener.class)); - expectLastCall().andDelegateTo(new TestLeadershipService()); - for (int i = 0; i < PartitionManager.NUM_PARTITIONS; i++) { - expect(leadershipService.runForLeadership(ELECTION_PREFIX + i)) - .andReturn(CompletableFuture.completedFuture(null)) - .times(1); - } - - partitionManager = new PartitionManager() - .withScheduledExecutor(new NullScheduledExecutor()); - - partitionManager.clusterService = new TestClusterService(); - partitionManager.leadershipService = leadershipService; - partitionManager.eventDispatcher = new TestEventDispatcher(); - } - - /** - * Configures a mock leadership service to have the specified number of - * partitions owned by the local node and all other partitions owned by a - * (fake) remote node. - * - * @param numMine number of partitions that should be owned by the local node - */ - private void setUpLeadershipService(int numMine) { - - Map<String, Leadership> leaderBoard = new HashMap<>(); - - for (int i = 0; i < numMine; i++) { - expect(leadershipService.getLeader(ELECTION_PREFIX + i)) - .andReturn(MY_NODE_ID).anyTimes(); - leaderBoard.put(ELECTION_PREFIX + i, - new Leadership(ELECTION_PREFIX + i, MY_NODE_ID, 0, 0)); - } - - for (int i = numMine; i < PartitionManager.NUM_PARTITIONS; i++) { - expect(leadershipService.getLeader(ELECTION_PREFIX + i)) - .andReturn(OTHER_NODE_ID).anyTimes(); - - leaderBoard.put(ELECTION_PREFIX + i, - new Leadership(ELECTION_PREFIX + i, OTHER_NODE_ID, 0, 0)); - } - - expect(leadershipService.getLeaderBoard()).andReturn(leaderBoard).anyTimes(); - } - - /** - * Tests that the PartitionManager's activate method correctly runs for - * all the leader elections that it should. - */ - @Test - public void testActivate() { - reset(leadershipService); - - leadershipService.addListener(anyObject(LeadershipEventListener.class)); - - for (int i = 0; i < PartitionManager.NUM_PARTITIONS; i++) { - expect(leadershipService.runForLeadership(ELECTION_PREFIX + i)) - .andReturn(CompletableFuture.completedFuture(null)) - .times(1); - } - - replay(leadershipService); - - partitionManager.activate(); - - verify(leadershipService); - } - - /** - * Tests that the isMine method returns the correct result based on the - * underlying leadership service data. - */ - @Test - public void testIsMine() { - // We'll own only the first partition - setUpLeadershipService(1); - replay(leadershipService); - - Key myKey = new ControllableHashKey(0); - Key notMyKey = new ControllableHashKey(1); - - assertTrue(partitionManager.isMine(myKey)); - assertFalse(partitionManager.isMine(notMyKey)); - - // Make us the owner of 4 partitions now - reset(leadershipService); - setUpLeadershipService(4); - replay(leadershipService); - - assertTrue(partitionManager.isMine(myKey)); - // notMyKey is now my key because because we're in control of that - // partition now - assertTrue(partitionManager.isMine(notMyKey)); - - assertFalse(partitionManager.isMine(new ControllableHashKey(4))); - } - - /** - * Tests sending in LeadershipServiceEvents in the case when we have - * too many partitions. The event will trigger the partition manager to - * schedule a rebalancing activity. - */ - @Test - public void testRebalanceScheduling() { - // We have all the partitions so we'll need to relinquish some - setUpLeadershipService(PartitionManager.NUM_PARTITIONS); - - replay(leadershipService); - - partitionManager.activate(); - // Send in the event - leaderListener.event(event); - - assertTrue(partitionManager.rebalanceScheduled.get()); - - verify(leadershipService); - } - - /** - * Tests rebalance will trigger the right now of leadership withdraw calls. - */ - @Test - public void testRebalance() { - // We have all the partitions so we'll need to relinquish some - setUpLeadershipService(PartitionManager.NUM_PARTITIONS); - - expect(leadershipService.withdraw(anyString())) - .andReturn(CompletableFuture.completedFuture(null)) - .times(7); - - replay(leadershipService); - - partitionManager.activate(); - - // trigger rebalance - partitionManager.doRebalance(); - - verify(leadershipService); - } - - /** - * Tests that attempts to rebalance when the paritions are already - * evenly distributed does not result in any relinquish attempts. - */ - @Test - public void testNoRebalance() { - // Partitions are already perfectly balanced among the two active instances - setUpLeadershipService(PartitionManager.NUM_PARTITIONS / 2); - replay(leadershipService); - - partitionManager.activate(); - - // trigger rebalance - partitionManager.doRebalance(); - - verify(leadershipService); - - reset(leadershipService); - // We have a smaller share than we should - setUpLeadershipService(PartitionManager.NUM_PARTITIONS / 2 - 1); - replay(leadershipService); - - // trigger rebalance - partitionManager.doRebalance(); - - verify(leadershipService); - } - - /** - * LeadershipService that allows us to grab a reference to - * PartitionManager's LeadershipEventListener. - */ - public class TestLeadershipService extends LeadershipServiceAdapter { - @Override - public void addListener(LeadershipEventListener listener) { - leaderListener = listener; - } - } - - /** - * ClusterService set up with a very simple cluster - 3 nodes, one is the - * current node, one is a different active node, and one is an inactive node. - */ - private class TestClusterService extends ClusterServiceAdapter { - - private final ControllerNode self = - new DefaultControllerNode(MY_NODE_ID, IpAddress.valueOf(1)); - private final ControllerNode otherNode = - new DefaultControllerNode(OTHER_NODE_ID, IpAddress.valueOf(2)); - private final ControllerNode inactiveNode = - new DefaultControllerNode(INACTIVE_NODE_ID, IpAddress.valueOf(3)); - - Set<ControllerNode> nodes; - - public TestClusterService() { - nodes = new HashSet<>(); - nodes.add(self); - nodes.add(otherNode); - nodes.add(inactiveNode); - } - - @Override - public ControllerNode getLocalNode() { - return self; - } - - @Override - public Set<ControllerNode> getNodes() { - return nodes; - } - - @Override - public ControllerNode getNode(NodeId nodeId) { - return nodes.stream() - .filter(c -> c.id().equals(nodeId)) - .findFirst() - .get(); - } - - @Override - public ControllerNode.State getState(NodeId nodeId) { - return nodeId.equals(INACTIVE_NODE_ID) ? ControllerNode.State.INACTIVE : - ControllerNode.State.ACTIVE; - } - } - - /** - * A key that always hashes to a value provided to the constructor. This - * allows us to control the hash of the key for unit tests. - */ - private class ControllableHashKey extends Key { - - protected ControllableHashKey(long hash) { - super(hash); - } - - @Override - public int hashCode() { - return Objects.hash(hash()); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof ControllableHashKey)) { - return false; - } - - ControllableHashKey that = (ControllableHashKey) obj; - - return Objects.equals(this.hash(), that.hash()); - } - - @Override - public int compareTo(Key o) { - Long thisHash = hash(); - return thisHash.compareTo(o.hash()); - } - } -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/link/impl/GossipLinkStoreTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/link/impl/GossipLinkStoreTest.java deleted file mode 100644 index f8b5b860..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/link/impl/GossipLinkStoreTest.java +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.link.impl; - -import com.google.common.collect.Iterables; - -import org.easymock.Capture; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; -import org.onlab.packet.IpAddress; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.DefaultControllerNode; -import org.onosproject.cluster.NodeId; -import org.onosproject.mastership.MastershipServiceAdapter; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.DeviceId; -import org.onosproject.net.Link; -import org.onosproject.net.Link.Type; -import org.onosproject.net.LinkKey; -import org.onosproject.net.PortNumber; -import org.onosproject.net.SparseAnnotations; -import org.onosproject.net.device.DeviceClockService; -import org.onosproject.net.device.DeviceClockServiceAdapter; -import org.onosproject.net.link.DefaultLinkDescription; -import org.onosproject.net.link.LinkDescription; -import org.onosproject.net.link.LinkEvent; -import org.onosproject.net.link.LinkStore; -import org.onosproject.net.link.LinkStoreDelegate; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.Timestamp; -import org.onosproject.store.cluster.StaticClusterService; -import org.onosproject.store.cluster.messaging.ClusterCommunicationService; -import org.onosproject.store.cluster.messaging.ClusterMessageHandler; -import org.onosproject.store.cluster.messaging.MessageSubject; -import org.onosproject.store.impl.MastershipBasedTimestamp; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import java.util.function.Function; - -import static org.easymock.EasyMock.*; -import static org.junit.Assert.*; -import static org.onosproject.cluster.ControllerNode.State.ACTIVE; -import static org.onosproject.net.DeviceId.deviceId; -import static org.onosproject.net.Link.Type.DIRECT; -import static org.onosproject.net.Link.Type.EDGE; -import static org.onosproject.net.Link.Type.INDIRECT; -import static org.onosproject.net.NetTestTools.assertAnnotationsEquals; -import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED; -import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED; -import static org.onosproject.net.link.LinkEvent.Type.LINK_UPDATED; - -/** - * Test of the GossipLinkStoreTest implementation. - */ -public class GossipLinkStoreTest { - - private static final ProviderId PID = new ProviderId("of", "foo"); - private static final ProviderId PIDA = new ProviderId("of", "bar", true); - private static final DeviceId DID1 = deviceId("of:foo"); - private static final DeviceId DID2 = deviceId("of:bar"); - - private static final PortNumber P1 = PortNumber.portNumber(1); - private static final PortNumber P2 = PortNumber.portNumber(2); - private static final PortNumber P3 = PortNumber.portNumber(3); - - private static final SparseAnnotations A1 = DefaultAnnotations.builder() - .set("A1", "a1") - .set("B1", "b1") - .build(); - private static final SparseAnnotations A1_2 = DefaultAnnotations.builder() - .remove("A1") - .set("B3", "b3") - .build(); - private static final SparseAnnotations A2 = DefaultAnnotations.builder() - .set("A2", "a2") - .set("B2", "b2") - .build(); - private static final SparseAnnotations A2_2 = DefaultAnnotations.builder() - .remove("A2") - .set("B4", "b4") - .build(); - - // local node - private static final NodeId NID1 = new NodeId("local"); - private static final ControllerNode ONOS1 = - new DefaultControllerNode(NID1, IpAddress.valueOf("127.0.0.1")); - - // remote node - private static final NodeId NID2 = new NodeId("remote"); - private static final ControllerNode ONOS2 = - new DefaultControllerNode(NID2, IpAddress.valueOf("127.0.0.2")); - - private GossipLinkStore linkStoreImpl; - private LinkStore linkStore; - - private final AtomicLong ticker = new AtomicLong(); - private DeviceClockService deviceClockService; - private ClusterCommunicationService clusterCommunicator; - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - } - - @Before - public void setUp() throws Exception { - // TODO mock clusterCommunicator - clusterCommunicator = createNiceMock(ClusterCommunicationService.class); - clusterCommunicator.addSubscriber(anyObject(MessageSubject.class), - anyObject(ClusterMessageHandler.class), - anyObject(ExecutorService.class)); - expectLastCall().anyTimes(); - replay(clusterCommunicator); - - linkStoreImpl = new GossipLinkStore(); - linkStoreImpl.deviceClockService = deviceClockService; - linkStoreImpl.clusterCommunicator = clusterCommunicator; - linkStoreImpl.clusterService = new TestClusterService(); - linkStoreImpl.deviceClockService = new TestDeviceClockService(); - linkStoreImpl.mastershipService = new TestMastershipService(); - linkStoreImpl.activate(); - linkStore = linkStoreImpl; - - verify(clusterCommunicator); - reset(clusterCommunicator); - - } - - @After - public void tearDown() throws Exception { - linkStoreImpl.deactivate(); - } - - private void putLink(DeviceId srcId, PortNumber srcNum, - DeviceId dstId, PortNumber dstNum, Type type, - SparseAnnotations... annotations) { - ConnectPoint src = new ConnectPoint(srcId, srcNum); - ConnectPoint dst = new ConnectPoint(dstId, dstNum); - reset(clusterCommunicator); - clusterCommunicator.<InternalLinkEvent>broadcast( - anyObject(InternalLinkEvent.class), anyObject(MessageSubject.class), anyObject(Function.class)); - expectLastCall().anyTimes(); - replay(clusterCommunicator); - linkStore.createOrUpdateLink(PID, new DefaultLinkDescription(src, dst, type, annotations)); - verify(clusterCommunicator); - } - - private <T> void resetCommunicatorExpectingSingleBroadcast( - Capture<T> message, - Capture<MessageSubject> subject, - Capture<Function<T, byte[]>> encoder) { - message.reset(); - subject.reset(); - encoder.reset(); - reset(clusterCommunicator); - clusterCommunicator.broadcast(capture(message), capture(subject), capture(encoder)); - expectLastCall().once(); - replay(clusterCommunicator); - } - - private void putLink(LinkKey key, Type type, SparseAnnotations... annotations) { - putLink(key.src().deviceId(), key.src().port(), - key.dst().deviceId(), key.dst().port(), - type, annotations); - } - - private static void assertLink(DeviceId srcId, PortNumber srcNum, - DeviceId dstId, PortNumber dstNum, Type type, - Link link) { - assertEquals(srcId, link.src().deviceId()); - assertEquals(srcNum, link.src().port()); - assertEquals(dstId, link.dst().deviceId()); - assertEquals(dstNum, link.dst().port()); - assertEquals(type, link.type()); - } - - private static void assertLink(LinkKey key, Type type, Link link) { - assertLink(key.src().deviceId(), key.src().port(), - key.dst().deviceId(), key.dst().port(), - type, link); - } - - @Test - public final void testGetLinkCount() { - assertEquals("initialy empty", 0, linkStore.getLinkCount()); - - putLink(DID1, P1, DID2, P2, DIRECT); - putLink(DID2, P2, DID1, P1, DIRECT); - putLink(DID1, P1, DID2, P2, DIRECT); - - assertEquals("expecting 2 unique link", 2, linkStore.getLinkCount()); - } - - @Test - public final void testGetLinks() { - assertEquals("initialy empty", 0, - Iterables.size(linkStore.getLinks())); - - LinkKey linkId1 = LinkKey.linkKey(new ConnectPoint(DID1, P1), new ConnectPoint(DID2, P2)); - LinkKey linkId2 = LinkKey.linkKey(new ConnectPoint(DID2, P2), new ConnectPoint(DID1, P1)); - - putLink(linkId1, DIRECT); - putLink(linkId2, DIRECT); - putLink(linkId1, DIRECT); - - assertEquals("expecting 2 unique link", 2, - Iterables.size(linkStore.getLinks())); - - Map<LinkKey, Link> links = new HashMap<>(); - for (Link link : linkStore.getLinks()) { - links.put(LinkKey.linkKey(link), link); - } - - assertLink(linkId1, DIRECT, links.get(linkId1)); - assertLink(linkId2, DIRECT, links.get(linkId2)); - } - - @Test - public final void testGetDeviceEgressLinks() { - LinkKey linkId1 = LinkKey.linkKey(new ConnectPoint(DID1, P1), new ConnectPoint(DID2, P2)); - LinkKey linkId2 = LinkKey.linkKey(new ConnectPoint(DID2, P2), new ConnectPoint(DID1, P1)); - LinkKey linkId3 = LinkKey.linkKey(new ConnectPoint(DID1, P2), new ConnectPoint(DID2, P3)); - - putLink(linkId1, DIRECT); - putLink(linkId2, DIRECT); - putLink(linkId3, DIRECT); - - // DID1,P1 => DID2,P2 - // DID2,P2 => DID1,P1 - // DID1,P2 => DID2,P3 - - Set<Link> links1 = linkStore.getDeviceEgressLinks(DID1); - assertEquals(2, links1.size()); - // check - - Set<Link> links2 = linkStore.getDeviceEgressLinks(DID2); - assertEquals(1, links2.size()); - assertLink(linkId2, DIRECT, links2.iterator().next()); - } - - @Test - public final void testGetDeviceIngressLinks() { - LinkKey linkId1 = LinkKey.linkKey(new ConnectPoint(DID1, P1), new ConnectPoint(DID2, P2)); - LinkKey linkId2 = LinkKey.linkKey(new ConnectPoint(DID2, P2), new ConnectPoint(DID1, P1)); - LinkKey linkId3 = LinkKey.linkKey(new ConnectPoint(DID1, P2), new ConnectPoint(DID2, P3)); - - putLink(linkId1, DIRECT); - putLink(linkId2, DIRECT); - putLink(linkId3, DIRECT); - - // DID1,P1 => DID2,P2 - // DID2,P2 => DID1,P1 - // DID1,P2 => DID2,P3 - - Set<Link> links1 = linkStore.getDeviceIngressLinks(DID2); - assertEquals(2, links1.size()); - // check - - Set<Link> links2 = linkStore.getDeviceIngressLinks(DID1); - assertEquals(1, links2.size()); - assertLink(linkId2, DIRECT, links2.iterator().next()); - } - - @Test - public final void testGetLink() { - ConnectPoint src = new ConnectPoint(DID1, P1); - ConnectPoint dst = new ConnectPoint(DID2, P2); - LinkKey linkId1 = LinkKey.linkKey(src, dst); - - putLink(linkId1, DIRECT); - - Link link = linkStore.getLink(src, dst); - assertLink(linkId1, DIRECT, link); - - assertNull("There shouldn't be reverese link", - linkStore.getLink(dst, src)); - } - - @Test - public final void testGetEgressLinks() { - final ConnectPoint d1P1 = new ConnectPoint(DID1, P1); - final ConnectPoint d2P2 = new ConnectPoint(DID2, P2); - LinkKey linkId1 = LinkKey.linkKey(d1P1, d2P2); - LinkKey linkId2 = LinkKey.linkKey(d2P2, d1P1); - LinkKey linkId3 = LinkKey.linkKey(new ConnectPoint(DID1, P2), new ConnectPoint(DID2, P3)); - - putLink(linkId1, DIRECT); - putLink(linkId2, DIRECT); - putLink(linkId3, DIRECT); - - // DID1,P1 => DID2,P2 - // DID2,P2 => DID1,P1 - // DID1,P2 => DID2,P3 - - Set<Link> links1 = linkStore.getEgressLinks(d1P1); - assertEquals(1, links1.size()); - assertLink(linkId1, DIRECT, links1.iterator().next()); - - Set<Link> links2 = linkStore.getEgressLinks(d2P2); - assertEquals(1, links2.size()); - assertLink(linkId2, DIRECT, links2.iterator().next()); - } - - @Test - public final void testGetIngressLinks() { - final ConnectPoint d1P1 = new ConnectPoint(DID1, P1); - final ConnectPoint d2P2 = new ConnectPoint(DID2, P2); - LinkKey linkId1 = LinkKey.linkKey(d1P1, d2P2); - LinkKey linkId2 = LinkKey.linkKey(d2P2, d1P1); - LinkKey linkId3 = LinkKey.linkKey(new ConnectPoint(DID1, P2), new ConnectPoint(DID2, P3)); - - putLink(linkId1, DIRECT); - putLink(linkId2, DIRECT); - putLink(linkId3, DIRECT); - - // DID1,P1 => DID2,P2 - // DID2,P2 => DID1,P1 - // DID1,P2 => DID2,P3 - - Set<Link> links1 = linkStore.getIngressLinks(d2P2); - assertEquals(1, links1.size()); - assertLink(linkId1, DIRECT, links1.iterator().next()); - - Set<Link> links2 = linkStore.getIngressLinks(d1P1); - assertEquals(1, links2.size()); - assertLink(linkId2, DIRECT, links2.iterator().next()); - } - - @Test - public final void testCreateOrUpdateLink() { - ConnectPoint src = new ConnectPoint(DID1, P1); - ConnectPoint dst = new ConnectPoint(DID2, P2); - - Capture<InternalLinkEvent> message = new Capture<>(); - Capture<MessageSubject> subject = new Capture<>(); - Capture<Function<InternalLinkEvent, byte[]>> encoder = new Capture<>(); - - // add link - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - final DefaultLinkDescription linkDescription = new DefaultLinkDescription(src, dst, INDIRECT); - LinkEvent event = linkStore.createOrUpdateLink(PID, - linkDescription); - verifyLinkBroadcastMessage(PID, NID1, src, dst, INDIRECT, message, subject, encoder); - - assertLink(DID1, P1, DID2, P2, INDIRECT, event.subject()); - assertEquals(LINK_ADDED, event.type()); - - // update link type - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - LinkEvent event2 = linkStore.createOrUpdateLink(PID, - new DefaultLinkDescription(src, dst, DIRECT)); - verifyLinkBroadcastMessage(PID, NID1, src, dst, DIRECT, message, subject, encoder); - - assertLink(DID1, P1, DID2, P2, DIRECT, event2.subject()); - assertEquals(LINK_UPDATED, event2.type()); - - // no change - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - LinkEvent event3 = linkStore.createOrUpdateLink(PID, - new DefaultLinkDescription(src, dst, DIRECT)); - verifyNoBroadcastMessage(message); - - assertNull("No change event expected", event3); - } - - private <T> void verifyNoBroadcastMessage(Capture<T> message) { - assertFalse("No broadcast expected", message.hasCaptured()); - } - - private void verifyLinkBroadcastMessage(ProviderId providerId, - NodeId sender, - ConnectPoint src, - ConnectPoint dst, - Type type, - Capture<InternalLinkEvent> actualLinkEvent, - Capture<MessageSubject> actualSubject, - Capture<Function<InternalLinkEvent, byte[]>> actualEncoder) { - verify(clusterCommunicator); - assertTrue(actualLinkEvent.hasCaptured()); - assertEquals(GossipLinkStoreMessageSubjects.LINK_UPDATE, actualSubject.getValue()); - assertEquals(providerId, actualLinkEvent.getValue().providerId()); - assertLinkDescriptionEquals(src, dst, type, actualLinkEvent.getValue().linkDescription().value()); - } - - private static void assertLinkDescriptionEquals(ConnectPoint src, - ConnectPoint dst, - Type type, - LinkDescription actual) { - assertEquals(src, actual.src()); - assertEquals(dst, actual.dst()); - assertEquals(type, actual.type()); - // TODO check annotations - } - - @Test - public final void testCreateOrUpdateLinkAncillary() { - ConnectPoint src = new ConnectPoint(DID1, P1); - ConnectPoint dst = new ConnectPoint(DID2, P2); - - Capture<InternalLinkEvent> message = new Capture<>(); - Capture<MessageSubject> subject = new Capture<>(); - Capture<Function<InternalLinkEvent, byte[]>> encoder = new Capture<>(); - - // add Ancillary link - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - LinkEvent event = linkStore.createOrUpdateLink(PIDA, - new DefaultLinkDescription(src, dst, INDIRECT, A1)); - verifyLinkBroadcastMessage(PIDA, NID1, src, dst, INDIRECT, message, subject, encoder); - - assertNotNull("Ancillary only link is ignored", event); - - // add Primary link - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - LinkEvent event2 = linkStore.createOrUpdateLink(PID, - new DefaultLinkDescription(src, dst, INDIRECT, A2)); - verifyLinkBroadcastMessage(PID, NID1, src, dst, INDIRECT, message, subject, encoder); - - assertLink(DID1, P1, DID2, P2, INDIRECT, event2.subject()); - assertAnnotationsEquals(event2.subject().annotations(), A2, A1); - assertEquals(LINK_UPDATED, event2.type()); - - // update link type - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - LinkEvent event3 = linkStore.createOrUpdateLink(PID, - new DefaultLinkDescription(src, dst, DIRECT, A2)); - verifyLinkBroadcastMessage(PID, NID1, src, dst, DIRECT, message, subject, encoder); - - assertLink(DID1, P1, DID2, P2, DIRECT, event3.subject()); - assertAnnotationsEquals(event3.subject().annotations(), A2, A1); - assertEquals(LINK_UPDATED, event3.type()); - - - // no change - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - LinkEvent event4 = linkStore.createOrUpdateLink(PID, - new DefaultLinkDescription(src, dst, DIRECT)); - verifyNoBroadcastMessage(message); - - assertNull("No change event expected", event4); - - // update link annotation (Primary) - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - LinkEvent event5 = linkStore.createOrUpdateLink(PID, - new DefaultLinkDescription(src, dst, DIRECT, A2_2)); - verifyLinkBroadcastMessage(PID, NID1, src, dst, DIRECT, message, subject, encoder); - - assertLink(DID1, P1, DID2, P2, DIRECT, event5.subject()); - assertAnnotationsEquals(event5.subject().annotations(), A2, A2_2, A1); - assertEquals(LINK_UPDATED, event5.type()); - - // update link annotation (Ancillary) - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - LinkEvent event6 = linkStore.createOrUpdateLink(PIDA, - new DefaultLinkDescription(src, dst, DIRECT, A1_2)); - verifyLinkBroadcastMessage(PIDA, NID1, src, dst, DIRECT, message, subject, encoder); - - assertLink(DID1, P1, DID2, P2, DIRECT, event6.subject()); - assertAnnotationsEquals(event6.subject().annotations(), A2, A2_2, A1, A1_2); - assertEquals(LINK_UPDATED, event6.type()); - - // update link type (Ancillary) : ignored - resetCommunicatorExpectingSingleBroadcast(message, subject, encoder); - LinkEvent event7 = linkStore.createOrUpdateLink(PIDA, - new DefaultLinkDescription(src, dst, EDGE)); - verifyNoBroadcastMessage(message); - assertNull("Ancillary change other than annotation is ignored", event7); - } - - - @Test - public final void testRemoveLink() { - final ConnectPoint d1P1 = new ConnectPoint(DID1, P1); - final ConnectPoint d2P2 = new ConnectPoint(DID2, P2); - LinkKey linkId1 = LinkKey.linkKey(d1P1, d2P2); - LinkKey linkId2 = LinkKey.linkKey(d2P2, d1P1); - - putLink(linkId1, DIRECT, A1); - putLink(linkId2, DIRECT, A2); - - // DID1,P1 => DID2,P2 - // DID2,P2 => DID1,P1 - // DID1,P2 => DID2,P3 - - LinkEvent event = linkStore.removeLink(d1P1, d2P2); - assertEquals(LINK_REMOVED, event.type()); - assertAnnotationsEquals(event.subject().annotations(), A1); - LinkEvent event2 = linkStore.removeLink(d1P1, d2P2); - assertNull(event2); - - assertLink(linkId2, DIRECT, linkStore.getLink(d2P2, d1P1)); - assertAnnotationsEquals(linkStore.getLink(d2P2, d1P1).annotations(), A2); - - // annotations, etc. should not survive remove - putLink(linkId1, DIRECT); - assertLink(linkId1, DIRECT, linkStore.getLink(d1P1, d2P2)); - assertAnnotationsEquals(linkStore.getLink(d1P1, d2P2).annotations()); - } - - @Test - public final void testAncillaryVisible() { - ConnectPoint src = new ConnectPoint(DID1, P1); - ConnectPoint dst = new ConnectPoint(DID2, P2); - - // add Ancillary link - linkStore.createOrUpdateLink(PIDA, - new DefaultLinkDescription(src, dst, INDIRECT, A1)); - - // Ancillary only link should not be visible - assertEquals(1, linkStore.getLinkCount()); - assertNotNull(linkStore.getLink(src, dst)); - } - - // If Delegates should be called only on remote events, - // then Simple* should never call them, thus not test required. - @Ignore("Ignore until Delegate spec. is clear.") - @Test - public final void testEvents() throws InterruptedException { - - final ConnectPoint d1P1 = new ConnectPoint(DID1, P1); - final ConnectPoint d2P2 = new ConnectPoint(DID2, P2); - final LinkKey linkId1 = LinkKey.linkKey(d1P1, d2P2); - - final CountDownLatch addLatch = new CountDownLatch(1); - LinkStoreDelegate checkAdd = event -> { - assertEquals(LINK_ADDED, event.type()); - assertLink(linkId1, INDIRECT, event.subject()); - addLatch.countDown(); - }; - final CountDownLatch updateLatch = new CountDownLatch(1); - LinkStoreDelegate checkUpdate = event -> { - assertEquals(LINK_UPDATED, event.type()); - assertLink(linkId1, DIRECT, event.subject()); - updateLatch.countDown(); - }; - final CountDownLatch removeLatch = new CountDownLatch(1); - LinkStoreDelegate checkRemove = event -> { - assertEquals(LINK_REMOVED, event.type()); - assertLink(linkId1, DIRECT, event.subject()); - removeLatch.countDown(); - }; - - linkStore.setDelegate(checkAdd); - putLink(linkId1, INDIRECT); - assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS)); - - linkStore.unsetDelegate(checkAdd); - linkStore.setDelegate(checkUpdate); - putLink(linkId1, DIRECT); - assertTrue("Update event fired", updateLatch.await(1, TimeUnit.SECONDS)); - - linkStore.unsetDelegate(checkUpdate); - linkStore.setDelegate(checkRemove); - linkStore.removeLink(d1P1, d2P2); - assertTrue("Remove event fired", removeLatch.await(1, TimeUnit.SECONDS)); - } - - private static final class TestClusterService extends StaticClusterService { - - public TestClusterService() { - localNode = ONOS1; - nodes.put(NID1, ONOS1); - nodeStates.put(NID1, ACTIVE); - - nodes.put(NID2, ONOS2); - nodeStates.put(NID2, ACTIVE); - } - } - - private final class TestDeviceClockService extends DeviceClockServiceAdapter { - - private final AtomicLong ticker = new AtomicLong(); - - @Override - public Timestamp getTimestamp(DeviceId deviceId) { - if (DID1.equals(deviceId)) { - return new MastershipBasedTimestamp(1, ticker.getAndIncrement()); - } else if (DID2.equals(deviceId)) { - return new MastershipBasedTimestamp(2, ticker.getAndIncrement()); - } else { - throw new IllegalStateException(); - } - } - - @Override - public boolean isTimestampAvailable(DeviceId deviceId) { - return DID1.equals(deviceId) || DID2.equals(deviceId); - } - } - - private final class TestMastershipService extends MastershipServiceAdapter { - @Override - public NodeId getMasterFor(DeviceId deviceId) { - return NID1; - } - } -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/link/impl/LinkFragmentIdTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/link/impl/LinkFragmentIdTest.java deleted file mode 100644 index a14b6e60..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/link/impl/LinkFragmentIdTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.link.impl; - -import static org.onosproject.net.DeviceId.deviceId; - -import org.junit.Test; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.DeviceId; -import org.onosproject.net.LinkKey; -import org.onosproject.net.PortNumber; -import org.onosproject.net.provider.ProviderId; -import com.google.common.testing.EqualsTester; - -public class LinkFragmentIdTest { - - private static final ProviderId PID = new ProviderId("of", "foo"); - private static final ProviderId PIDA = new ProviderId("of", "bar", true); - - private static final DeviceId DID1 = deviceId("of:foo"); - private static final DeviceId DID2 = deviceId("of:bar"); - - private static final PortNumber P1 = PortNumber.portNumber(1); - private static final PortNumber P2 = PortNumber.portNumber(2); - private static final PortNumber P3 = PortNumber.portNumber(3); - - private static final ConnectPoint CP1 = new ConnectPoint(DID1, P1); - private static final ConnectPoint CP2 = new ConnectPoint(DID2, P2); - - private static final ConnectPoint CP3 = new ConnectPoint(DID1, P2); - private static final ConnectPoint CP4 = new ConnectPoint(DID2, P3); - - private static final LinkKey L1 = LinkKey.linkKey(CP1, CP2); - private static final LinkKey L2 = LinkKey.linkKey(CP3, CP4); - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup(new LinkFragmentId(L1, PID), - new LinkFragmentId(L1, PID)) - .addEqualityGroup(new LinkFragmentId(L2, PID), - new LinkFragmentId(L2, PID)) - .addEqualityGroup(new LinkFragmentId(L1, PIDA), - new LinkFragmentId(L1, PIDA)) - .addEqualityGroup(new LinkFragmentId(L2, PIDA), - new LinkFragmentId(L2, PIDA)) - .testEquals(); - } - -} diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/mastership/impl/RoleValueTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/mastership/impl/RoleValueTest.java deleted file mode 100644 index d3b5c764..00000000 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/mastership/impl/RoleValueTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.mastership.impl; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.onosproject.net.MastershipRole.*; - -import org.junit.Test; -import org.onosproject.cluster.NodeId; - -import com.google.common.collect.Sets; - -public class RoleValueTest { - - private static final RoleValue RV = new RoleValue(); - - private static final NodeId NID1 = new NodeId("node1"); - private static final NodeId NID2 = new NodeId("node2"); - private static final NodeId NID3 = new NodeId("node3"); - - @Test - public void add() { - assertEquals("faulty initialization: ", 3, RV.value.size()); - RV.add(MASTER, NID1); - RV.add(STANDBY, NID2); - RV.add(STANDBY, NID3); - - assertEquals("wrong nodeID: ", NID1, RV.get(MASTER)); - assertTrue("wrong nodeIDs: ", - Sets.newHashSet(NID3, NID2).containsAll(RV.nodesOfRole(STANDBY))); - } -} diff --git a/framework/src/onos/core/store/persistence/pom.xml b/framework/src/onos/core/store/persistence/pom.xml deleted file mode 100644 index bb3cd8e1..00000000 --- a/framework/src/onos/core/store/persistence/pom.xml +++ /dev/null @@ -1,66 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright 2015 Open Networking Laboratory - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> - <repositories> - <repository> - <id>repository.springsource.com.release</id> - <name>SpringSource OBR - Release</name> - <url>http://repository.springsource.com/maven/bundles/release</url> - </repository> - <repository> - <id>repository.springsource.com.external</id> - <name>SpringSource OBR - External</name> - <url>http://repository.springsource.com/maven/bundles/external</url> - </repository> - </repositories> - - <parent> - <groupId>org.onosproject</groupId> - <artifactId>onos-core-store</artifactId> - <version>1.4.0-rc1</version> - <relativePath>../pom.xml</relativePath> - </parent> - - <artifactId>onos-core-persistence</artifactId> - <packaging>bundle</packaging> - - <description>ONOS Core persistent local store subsystem</description> - - - - <dependencies> - <!--<dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-api</artifactId> - </dependency>--> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-api</artifactId> - <classifier>tests</classifier> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.mapdb</groupId> - <artifactId>mapdb</artifactId> - <version>1.0.8</version> - </dependency> - </dependencies> - -</project> diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentMapBuilder.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentMapBuilder.java deleted file mode 100644 index 88c7d148..00000000 --- a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentMapBuilder.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.persistence.impl; - -import org.mapdb.DB; -import org.onosproject.persistence.PersistentMapBuilder; -import org.onosproject.store.service.Serializer; - -import java.util.Map; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Default builder for persistent maps stored in the mapDB local database via the persistence service. - */ -public class DefaultPersistentMapBuilder<K, V> implements PersistentMapBuilder<K, V> { - - private final DB localDB; - - private String name = null; - - private Serializer serializer = null; - - - public DefaultPersistentMapBuilder(DB localDB) { - checkNotNull(localDB, "The local database cannot be null."); - this.localDB = localDB; - } - - public PersistentMapBuilder<K, V> withName(String name) { - this.name = PersistenceManager.MAP_PREFIX + checkNotNull(name); - return this; - } - - public PersistentMapBuilder<K, V> withSerializer(Serializer serializer) { - checkArgument(this.serializer == null); - checkNotNull(serializer); - this.serializer = serializer; - return this; - } - - public Map<K, V> build() { - checkNotNull(name, "The name must be assigned."); - checkNotNull(serializer, "The key serializer must be assigned."); - - return new PersistentMap<K, V>(serializer, localDB, name); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentSetBuilder.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentSetBuilder.java deleted file mode 100644 index e1544fb4..00000000 --- a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentSetBuilder.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.persistence.impl; - -import org.mapdb.DB; -import org.onosproject.persistence.PersistentSetBuilder; -import org.onosproject.store.service.Serializer; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Default builder for persistent sets stored in the mapDB local database via the persistence service.. - */ -public class DefaultPersistentSetBuilder<E> implements PersistentSetBuilder<E> { - - private final DB localDB; - - private String name = null; - - private Serializer serializer = null; - - public DefaultPersistentSetBuilder(DB localDB) { - this.localDB = checkNotNull(localDB, "The local database cannot be null."); - } - - public PersistentSetBuilder<E> withName(String name) { - this.name = PersistenceManager.SET_PREFIX + checkNotNull(name); - return this; - } - - public PersistentSetBuilder<E> withSerializer(Serializer serializer) { - checkArgument(this.serializer == null); - checkNotNull(serializer); - this.serializer = serializer; - return this; - } - - public PersistentSet<E> build() { - checkNotNull(name, "The name must be assigned."); - checkNotNull(serializer, "The serializer must be assigned."); - - return new PersistentSet<E>(serializer, localDB, name); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceException.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceException.java deleted file mode 100644 index f2ba20c2..00000000 --- a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.persistence.impl; - -/** - * An exception defined for failures of the local persistent store system. - */ - -/** - * Throws an exception with the specified message. - */ -public class PersistenceException extends RuntimeException { - public PersistenceException(String s) { - super(s); - } -} diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java deleted file mode 100644 index 05c577c0..00000000 --- a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.persistence.impl; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Service; -import org.mapdb.DB; -import org.mapdb.DBMaker; -import org.onosproject.persistence.PersistenceService; -import org.onosproject.persistence.PersistentMapBuilder; -import org.onosproject.persistence.PersistentSetBuilder; -import org.slf4j.Logger; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Map; -import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; - -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Service that maintains local disk backed maps and sets. This implementation automatically deletes empty structures - * on shutdown. - */ -@Component(immediate = true) -@Service -public class PersistenceManager implements PersistenceService { - - private static final String DATABASE_PATH = "../data/localDB"; - private static final String ENCLOSING_FOLDER = "../data"; - - static final String MAP_PREFIX = "map:"; - - static final String SET_PREFIX = "set:"; - - private final Logger log = getLogger(getClass()); - - private DB localDB = null; - - private static final int FLUSH_FREQUENCY_MILLIS = 3000; - - private Timer timer; - - private final CommitTask commitTask = new CommitTask(); - - @Activate - public void activate() { - timer = new Timer(); - Path dbPath = Paths.get(DATABASE_PATH); - Path dbFolderPath = Paths.get(ENCLOSING_FOLDER); - //Make sure the directory exists, if it does not, make it. - if (!dbFolderPath.toFile().isDirectory()) { - log.info("The specified folder location for the database did not exist and will be created."); - try { - Files.createDirectories(dbFolderPath); - } catch (IOException e) { - log.error("Could not create the required folder for the database."); - throw new PersistenceException("Database folder could not be created."); - } - } - //Notify if the database file does not exist. - boolean dbFound = Files.exists(dbPath); - if (!dbFound) { - log.info("The database file could not be located, a new database will be constructed."); - - } else { - log.info("A previous database file has been found."); - } - localDB = DBMaker.newFileDB(dbPath.toFile()) - .asyncWriteEnable() - .closeOnJvmShutdown() - .make(); - timer.schedule(commitTask, FLUSH_FREQUENCY_MILLIS, FLUSH_FREQUENCY_MILLIS); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - timer.cancel(); - for (Map.Entry<String, Object> entry : localDB.getAll().entrySet()) { - String key = entry.getKey(); - Object value = entry.getValue(); - //This is a map implementation to be handled as such - if (value instanceof Map) { - Map asMap = (Map) value; - if (asMap.isEmpty()) { - //the map is empty and may be deleted - localDB.delete(key); - } - //This is a set implementation and can be handled as such - } else if (value instanceof Set) { - Set asSet = (Set) value; - if (asSet.isEmpty()) { - //the set is empty and may be deleted - localDB.delete(key); - } - } - } - localDB.commit(); - localDB.close(); - log.info("Stopped"); - } - - public <K, V> PersistentMapBuilder<K, V> persistentMapBuilder() { - return new DefaultPersistentMapBuilder<>(localDB); - } - - public <E> PersistentSetBuilder<E> persistentSetBuilder() { - return new DefaultPersistentSetBuilder<>(localDB); - } - - private class CommitTask extends TimerTask { - - @Override - public void run() { - localDB.commit(); - } - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java deleted file mode 100644 index 4506bbda..00000000 --- a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.persistence.impl; - -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import org.mapdb.DB; -import org.mapdb.Hasher; -import org.onosproject.store.service.Serializer; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -import static com.google.common.base.Preconditions.checkNotNull; - - -/** - * A map implementation that stores and receives all data from a serialized internal map. - */ -public class PersistentMap<K, V> implements Map<K, V> { - - private final Serializer serializer; - - private final org.mapdb.DB database; - - private final Map<byte[], byte[]> items; - - private final String name; - - public PersistentMap(Serializer serializer, DB database, String name) { - this.serializer = checkNotNull(serializer); - this.database = checkNotNull(database); - this.name = checkNotNull(name); - - items = database - .createHashMap(name) - .keySerializer(org.mapdb.Serializer.BYTE_ARRAY) - .valueSerializer(org.mapdb.Serializer.BYTE_ARRAY) - .hasher(Hasher.BYTE_ARRAY) - .makeOrGet(); - } - - /** - * Reads this set in deserialized form into the provided map. - * - * @param items the map to be populated - */ - public void readInto(Map<K, V> items) { - this.items.forEach((keyBytes, valueBytes) -> - items.put(serializer.decode(keyBytes), - serializer.decode(valueBytes))); - } - - @Override - public V remove(Object key) { - checkNotNull(key, "Key can not be null."); - V removed = get(key); - items.remove(serializer.encode(key)); - return removed; - } - - @Override - public int size() { - return items.size(); - } - - @Override - public boolean isEmpty() { - return items.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - checkNotNull(key, "Key cannot be null."); - return items.containsKey(serializer.encode(key)); - } - - @Override - public boolean containsValue(Object value) { - checkNotNull(value, "Value cannot be null."); - byte[] serialized = serializer.encode(value); - for (byte[] compareValue : items.values()) { - boolean same = true; - if (compareValue == null) { - same = false; - } else if (compareValue.length != serialized.length) { - same = false; - } else { - for (int i = 0; i < serialized.length; i++) { - if (serialized[i] != compareValue[i]) { - same = false; - break; - } - } - } - if (same) { - return true; - } - } - return false; - } - - @Override - public V get(Object key) { - checkNotNull(key, "Key cannot be null."); - return serializer.decode(items.get(serializer.encode(key))); - } - - @Override - public V put(K key, V value) { - checkNotNull(key, "Key cannot be null."); - checkNotNull(value, "Value cannot be null."); - byte[] prevVal = items.put(serializer.encode(key), serializer.encode(value)); - if (prevVal == null) { - return null; - } - return serializer.decode(prevVal); - } - - @Override - public void putAll(Map<? extends K, ? extends V> m) { - checkNotNull(m, "The passed in map cannot be null."); - m.forEach((k, v) -> items.put(serializer.encode(k), serializer.encode(v))); - } - - @Override - public void clear() { - items.clear(); - } - - @Override - public Set<K> keySet() { - Set<K> keys = Sets.newHashSet(); - items.keySet().forEach(k -> keys.add(serializer.decode(k))); - return keys; - } - - @Override - public Collection<V> values() { - Collection<V> values = Sets.newHashSet(); - items.values().forEach(v -> values.add(serializer.decode(v))); - return values; - } - - @Override - public Set<Entry<K, V>> entrySet() { - Set<Entry<K, V>> entries = Sets.newHashSet(); - items.entrySet(). - forEach(e -> entries.add(Maps.immutableEntry(serializer.decode(e.getKey()), - serializer.decode(e.getValue())))); - return entries; - } - - @Override - public boolean equals(Object map) { - //This is not threadsafe and on larger maps incurs a significant processing cost - if (!(map instanceof Map)) { - return false; - } - Map asMap = (Map) map; - if (this.size() != asMap.size()) { - return false; - } - for (Entry entry : this.entrySet()) { - Object key = entry.getKey(); - if (!asMap.containsKey(key) || !asMap.get(key).equals(entry.getValue())) { - return false; - } - } - return true; - } - - @Override - public int hashCode() { - return super.hashCode(); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentSet.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentSet.java deleted file mode 100644 index 26118cf6..00000000 --- a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentSet.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.persistence.impl; - -import com.google.common.collect.Iterators; -import org.mapdb.DB; -import org.mapdb.Hasher; -import org.mapdb.Serializer; - -import java.util.Collection; -import java.util.Iterator; -import java.util.Set; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * A set implementation that gets and receives all data from a serialized internal set. - */ -//TODO add locking for reads and writes -public class PersistentSet<E> implements Set<E> { - - private final org.onosproject.store.service.Serializer serializer; - - private final org.mapdb.DB database; - - private final Set<byte[]> items; - - private final String name; - - public PersistentSet(org.onosproject.store.service.Serializer serializer, DB database, String name) { - this.serializer = checkNotNull(serializer); - this.database = checkNotNull(database); - this.name = checkNotNull(name); - - items = database - .createHashSet(name) - .serializer(Serializer.BYTE_ARRAY) - .hasher(Hasher.BYTE_ARRAY) - .makeOrGet(); - } - - public void readInto(Set<E> items) { - this.items.forEach(item -> items.add(serializer.decode(item))); - } - - @Override - public int size() { - return items.size(); - } - - @Override - public boolean isEmpty() { - return items.isEmpty(); - } - - @Override - public boolean contains(Object o) { - checkNotNull(o, "The argument cannot be null"); - return items.contains(serializer.encode(o)); - } - - @Override - public Iterator<E> iterator() { - return Iterators.transform(items.iterator(), serializer::decode); - } - - @Override - public Object[] toArray() { - Object[] retArray = new Object[items.size()]; - int index = 0; - Iterator<byte[]> iterator = items.iterator(); - while (iterator.hasNext()) { - retArray[index] = serializer.decode(iterator.next()); - index++; - } - return retArray; - } - - @Override - public <T> T[] toArray(T[] a) { - checkNotNull(a, "The passed in array cannot be null."); - int index = 0; - Iterator<byte[]> iterator = items.iterator(); - T[] retArray; - if (a.length >= items.size()) { - retArray = a; - } else { - retArray = (T[]) new Object[items.size()]; - } - while (iterator.hasNext()) { - retArray[index++] = serializer.decode(iterator.next()); - } - if (retArray.length > items.size()) { - retArray[index] = null; - } - return retArray; - } - - @Override - public boolean add(E item) { - checkNotNull("Item to be added cannot be null."); - return items.add(serializer.encode(item)); - } - - @Override - public boolean remove(Object o) { - checkNotNull(o, "Item to be removed cannot be null."); - return items.remove(serializer.encode(o)); - } - - @Override - public boolean containsAll(Collection<?> c) { - checkNotNull(c, "Collection cannot be internal."); - for (Object item : c) { - if (!items.contains(serializer.encode(item))) { - return false; - } - } - return true; - } - - @Override - public boolean addAll(Collection<? extends E> c) { - checkNotNull(c, "The collection to be added cannot be null."); - boolean changed = false; - for (Object item : c) { - changed = items.add(serializer.encode(item)) || changed; - } - return changed; - } - - @Override - public boolean retainAll(Collection<?> c) { - boolean changed = false; - for (byte[] item : items) { - E deserialized = serializer.decode(item); - if (!c.contains(deserialized)) { - changed = items.remove(item) || changed; - } - } - return changed; - } - - @Override - public boolean removeAll(Collection<?> c) { - boolean changed = false; - for (Object item : c) { - changed = items.remove(serializer.encode(item)) || changed; - } - return changed; - } - - @Override - public void clear() { - items.clear(); - } - - @Override - public boolean equals(Object set) { - //This is not threadsafe and on larger sets incurs a significant processing cost - if (!(set instanceof Set)) { - return false; - } - Set asSet = (Set) set; - if (asSet.size() != this.size()) { - return false; - } - for (Object item : this) { - if (!asSet.contains(item)) { - return false; - } - } - return true; - } - - @Override - public int hashCode() { - return super.hashCode(); - } -}
\ No newline at end of file diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/package-info.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/package-info.java deleted file mode 100644 index 968a5046..00000000 --- a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Implementations of core persistence classes. - */ -package org.onosproject.persistence.impl; diff --git a/framework/src/onos/core/store/persistence/src/main/test/test/PersistentMapTest.java b/framework/src/onos/core/store/persistence/src/main/test/test/PersistentMapTest.java deleted file mode 100644 index b059f18e..00000000 --- a/framework/src/onos/core/store/persistence/src/main/test/test/PersistentMapTest.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package test; - -import com.google.common.collect.Maps; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mapdb.DB; -import org.mapdb.DBMaker; -import org.onosproject.persistence.impl.PersistentMap; -import org.onosproject.store.service.Serializer; - -import java.nio.file.Paths; -import java.util.Map; -import java.util.Set; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -/** - * Test suite for Persistent Map. - */ -public class PersistentMapTest { - - private Map<Integer, Integer> map = null; - private DB fakeDB = null; - - - /** - * Set up the database, create a map and a direct executor to handle it. - * - * @throws Exception if instantiation fails - */ - @Before - public void setUp() throws Exception { - //Creates a db, a map within it and a basic integer serializer (async writing is off) - fakeDB = DBMaker - .newFileDB(Paths.get("../testDb").toFile()) - .asyncWriteEnable() - .closeOnJvmShutdown() - .make(); - map = new PersistentMap<Integer, Integer>(new Serializer() { - @Override - public <T> byte[] encode(T object) { - if (object == null) { - return null; - } - int num = (Integer) object; - byte[] result = new byte[4]; - - result[0] = (byte) (num >> 24); - result[1] = (byte) (num >> 16); - result[2] = (byte) (num >> 8); - result[3] = (byte) num; - return result; - } - - @Override - public <T> T decode(byte[] bytes) { - if (bytes == null) { - return null; - } - int num = 0x00000000; - - num = num | bytes[0] << 24; - num = num | bytes[1] << 16; - num = num | bytes[2] << 8; - num = num | bytes[3]; - - return (T) new java.lang.Integer(num); - } - }, fakeDB, "map"); - } - - /** - * Clears and deletes the map, closes the datbase and deletes the file. - * - * @throws Exception if shutdown fails - */ - @After - public void tearDown() throws Exception { - map.clear(); - fakeDB.delete("map:map"); - fakeDB.commit(); - fakeDB.close(); - //This is key to prevent artifacts persisting between tests. - Paths.get("../testDB").toFile().delete(); - - - } - - @Test - public void testRemove() throws Exception { - //Checks removal and return values - fillMap(10); - assertEquals(10, map.size()); - for (int i = 0; i < 10; i++) { - assertEquals("The previous value was wrong.", new Integer(i), map.remove(i)); - assertNull("The previous value was wrong.", map.remove(i)); - //(i+1) compensates for base zero. - assertEquals("The size was wrong.", 10 - (i + 1), map.size()); - } - } - - @Test - public void testSize() throws Exception { - //Checks size values throughout addition and removal - for (int i = 0; i < 10; i++) { - map.put(i, i); - assertEquals("The map size is wrong.", i + 1, map.size()); - } - for (int i = 0; i < 10; i++) { - map.remove(i); - assertEquals("The map size is wrong.", 9 - i, map.size()); - } - } - - @Test - public void testIsEmpty() throws Exception { - //Checks empty condition - //asserts that the map starts out empty - assertTrue("Map should be empty", map.isEmpty()); - map.put(1, 1); - assertFalse("Map shouldn't be empty.", map.isEmpty()); - map.remove(1); - assertTrue("Map should be empty", map.isEmpty()); - } - - @Test - public void testContains() throws Exception { - //Checks both containsKey and containsValue be aware the implementations vary widely (value does not use mapDB - //due to object '=='being an insufficient check) - for (int i = 0; i < 10; i++) { - assertFalse("Map should not contain the key", map.containsKey(i)); - assertFalse("Map should not contain the value", map.containsValue(i)); - map.put(i, i); - assertTrue("Map should contain the key", map.containsKey(i)); - assertTrue("Map should contain the value", map.containsValue(i)); - } - } - - @Test - public void testGet() throws Exception { - //Tests value retrieval and nonexistent key return values - for (int i = 0; i < 10; i++) { - map.put(i, i); - for (int j = 0; j <= i; j++) { - assertEquals("The value was wrong.", new Integer(j), map.get(j)); - } - } - assertNull("Null return value for nonexistent keys.", map.get(10)); - } - - @Test - public void testPutAll() throws Exception { - //Tests adding of an outside map - Map<Integer, Integer> testMap = Maps.newHashMap(); - fillMap(10); - map.putAll(testMap); - for (int i = 0; i < 10; i++) { - assertTrue("The map should contain the current 'i' value.", map.containsKey(i)); - assertTrue("The map should contain the current 'i' value.", map.containsValue(i)); - } - } - - @Test - public void testClear() throws Exception { - //Tests clearing the map - assertTrue("Map was initialized incorrectly, should be empty.", map.isEmpty()); - fillMap(10); - assertFalse("Map should contain entries now.", map.isEmpty()); - map.clear(); - assertTrue("Map should have been cleared of entries.", map.isEmpty()); - - } - - @Test - public void testKeySet() throws Exception { - //Tests key set generation - fillMap(10); - Set<Integer> keys = map.keySet(); - for (int i = 0; i < 10; i++) { - assertTrue("The key set doesn't contain all keys 0-9", keys.contains(i)); - } - assertEquals("The key set has an incorrect number of entries", 10, keys.size()); - } - - @Test - public void testValues() throws Exception { - //Tests value set generation - fillMap(10); - Set<Integer> values = (Set<Integer>) map.values(); - for (int i = 0; i < 10; i++) { - assertTrue("The key set doesn't contain all keys 0-9", values.contains(i)); - } - assertEquals("The key set has an incorrect number of entries", 10, values.size()); - } - - @Test - public void testEntrySet() throws Exception { - //Test entry set generation (violates abstraction by knowing the type of the returned entries) - fillMap(10); - Set<Map.Entry<Integer, Integer>> entries = map.entrySet(); - for (int i = 0; i < 10; i++) { - assertTrue("The key set doesn't contain all keys 0-9", entries.contains(Maps.immutableEntry(i, i))); - } - assertEquals("The key set has an incorrect number of entries", 10, entries.size()); - } - - @Test public void testPut() throws Exception { - //Tests insertion behavior (particularly the returning of previous value) - fillMap(10); - for (int i = 0; i < 10; i++) { - assertEquals("Put should return the previous value", new Integer(i), map.put(i, i + 1)); - } - assertNull(map.put(11, 11)); - } - - /** - * Populated the map with pairs of integers from (0, 0) up to (numEntries - 1, numEntries -1). - * @param numEntries number of entries to add - */ - private void fillMap(int numEntries) { - for (int i = 0; i < numEntries; i++) { - map.put(i, i); - } - } -} diff --git a/framework/src/onos/core/store/persistence/src/main/test/test/PersistentSetTest.java b/framework/src/onos/core/store/persistence/src/main/test/test/PersistentSetTest.java deleted file mode 100644 index 3107ab30..00000000 --- a/framework/src/onos/core/store/persistence/src/main/test/test/PersistentSetTest.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package test; - -import com.google.common.collect.Sets; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mapdb.DB; -import org.mapdb.DBMaker; -import org.onosproject.persistence.impl.PersistentSet; -import org.onosproject.store.service.Serializer; - -import java.nio.file.Paths; -import java.util.HashSet; -import java.util.Set; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -/** - * Test suite for Persistent Set. - */ -public class PersistentSetTest { - - private Set<Integer> set = null; - private DB fakeDB = null; - - @Before - public void setUp() throws Exception { - //Creates a db, a set within it and a basic integer serializer (async writing is off) - fakeDB = DBMaker - .newFileDB(Paths.get("../testDb").toFile()) - .asyncWriteEnable() - .closeOnJvmShutdown() - .make(); - set = new PersistentSet<Integer>(new Serializer() { - @Override - public <T> byte[] encode(T object) { - if (object == null) { - return null; - } - int num = (Integer) object; - byte[] result = new byte[4]; - - result[0] = (byte) (num >> 24); - result[1] = (byte) (num >> 16); - result[2] = (byte) (num >> 8); - result[3] = (byte) num; - return result; - } - - @Override - public <T> T decode(byte[] bytes) { - if (bytes == null) { - return null; - } - int num = 0x00000000; - - num = num | bytes[0] << 24; - num = num | bytes[1] << 16; - num = num | bytes[2] << 8; - num = num | bytes[3]; - - return (T) new java.lang.Integer(num); - } - }, fakeDB, "set"); - - } - - @After - public void tearDown() throws Exception { - set.clear(); - fakeDB.delete("map:map"); - fakeDB.commit(); - fakeDB.close(); - //This is key to prevent artifacts persisting between tests. - Paths.get("../testDB").toFile().delete(); - } - - @Test - public void testSize() throws Exception { - //Check correct sizing throughout population - for (int i = 0; i < 10; i++) { - set.add(i); - assertEquals("The set should have i + 1 entries.", i + 1, set.size()); - } - } - - @Test - public void testIsEmpty() throws Exception { - //test empty condition - assertTrue("The set should be initialized empty.", set.isEmpty()); - fillSet(5, this.set); - assertFalse("The set should no longer be empty.", set.isEmpty()); - set.clear(); - assertTrue("The set should have been cleared.", set.isEmpty()); - } - - @Test - public void testContains() throws Exception { - //Test contains - assertFalse("The set should not contain anything", set.contains(1)); - fillSet(10, this.set); - for (int i = 0; i < 10; i++) { - assertTrue("The set should contain all values 0-9.", set.contains(i)); - } - } - - @Test - public void testIterator() throws Exception { - //Test iterator behavior (no order guarantees are made) - Set<Integer> validationSet = Sets.newHashSet(); - fillSet(10, this.set); - fillSet(10, validationSet); - set.iterator().forEachRemaining(item -> assertTrue("Items were mismatched.", validationSet.remove(item))); - //All values should have been seen and removed - assertTrue("All entries in the validation set should have been removed.", validationSet.isEmpty()); - } - - @Test - public void testToArray() throws Exception { - //Test creation of a new array of the values - fillSet(10, set); - Object[] arr = set.toArray(); - assertEquals("The array should be of length 10.", 10, arr.length); - for (int i = 0; i < 10; i++) { - assertTrue("All elements of the array should be in the set.", set.contains((Integer) arr[i])); - } - } - - @Test - public void testToArray1() throws Exception { - //Test creation of a new array with the possibility of populating passed array if space allows - Integer[] originalArray = new Integer[9]; - fillSet(9, set); - //Test the case where the array and set match in size - Object[] retArray = set.toArray(originalArray); - assertEquals("If the set can fit the array should be the one passed in.", originalArray, retArray); - //Test the case where the passe array is too small to fit the set - set.add(9); - assertNotEquals("A new set should be generated if the contents will not fit in the passed set", - set.toArray(originalArray), originalArray); - //Now test the case where there should be a null terminator - set.clear(); - fillSet(5, set); - assertNull("The character one after last should be null if the array is larger than the set.", - set.toArray(originalArray)[5]); - } - - @Test - public void testAdd() throws Exception { - //Test of add - for (int i = 0; i < 10; i++) { - assertEquals("The size of the set is wrong.", i, set.size()); - assertTrue("The first add of an element should be true.", set.add(i)); - assertFalse("The second add of an element should be false.", set.add(i)); - } - } - - @Test - public void testRemove() throws Exception { - //Test removal - fillSet(10, set); - for (int i = 0; i < 10; i++) { - assertEquals("The size of the set is wrong.", 10 - i, set.size()); - assertTrue("The first removal should be true.", set.remove(i)); - assertFalse("The second removal should be false (item no longer contained).", set.remove(i)); - } - assertTrue("All elements should have been removed.", set.isEmpty()); - } - - @Test - public void testContainsAll() throws Exception { - //Test contains with short circuiting - Set<Integer> integersToCheck = Sets.newHashSet(); - fillSet(10, integersToCheck); - fillSet(10, set); - assertTrue("The sets should be identical so mutual subsets.", set.containsAll(integersToCheck)); - set.remove(9); - assertFalse("The set should contain one fewer value.", set.containsAll(integersToCheck)); - } - - @Test - public void testAddAll() throws Exception { - //Test multi-adds with change checking - Set<Integer> integersToCheck = Sets.newHashSet(); - fillSet(10, integersToCheck); - assertFalse("Set should be empty and so integers to check should not be a subset.", - set.containsAll(integersToCheck)); - assertTrue("The set should have changed as a result of add all.", set.addAll(integersToCheck)); - assertFalse("The set should not have changed as a result of add all a second time.", - set.addAll(integersToCheck)); - assertTrue("The sets should now be equivalent.", set.containsAll(integersToCheck)); - assertTrue("The sets should now be equivalent.", integersToCheck.containsAll(set)); - } - - @Test - public void testRetainAll() throws Exception { - //Test ability to generate the intersection set - Set<Integer> retainSet = Sets.newHashSet(); - fillSet(10, set); - assertTrue("The set should have changed.", set.retainAll(retainSet)); - assertTrue("The set should have been emptied.", set.isEmpty()); - fillSet(10, set); - fillSet(10, retainSet); - Set<Integer> duplicateSet = new HashSet<>(set); - assertFalse("The set should not have changed.", set.retainAll(retainSet)); - assertEquals("The set should be the same as the duplicate.", duplicateSet, set); - retainSet.remove(9); - assertTrue("The set should have changed.", set.retainAll(retainSet)); - duplicateSet.remove(9); - assertEquals("The set should have had the nine element removed.", duplicateSet, set); - } - - @Test - public void testRemoveAll() throws Exception { - //Test for mass removal and change checking - Set<Integer> removeSet = Sets.newHashSet(); - fillSet(10, set); - Set<Integer> duplicateSet = Sets.newHashSet(set); - assertFalse("No elements should change.", set.removeAll(removeSet)); - assertEquals("Set should not have diverged from the duplicate.", duplicateSet, set); - fillSet(5, removeSet); - assertTrue("Elements should have been removed.", set.removeAll(removeSet)); - assertNotEquals("Duplicate set should no longer be equivalent.", duplicateSet, set); - assertEquals("Five elements should have been removed from set.", 5, set.size()); - for (Integer item : removeSet) { - assertFalse("No element of remove set should remain.", set.contains(item)); - } - } - - @Test - public void testClear() throws Exception { - //Test set emptying - assertTrue("The set should be initialized empty.", set.isEmpty()); - set.clear(); - assertTrue("Clear should have no effect on an empty set.", set.isEmpty()); - fillSet(10, set); - assertFalse("The set should no longer be empty.", set.isEmpty()); - set.clear(); - assertTrue("The set should be empty after clear.", set.isEmpty()); - } - - /** - * Populated the map with integers from (0) up to (numEntries - 1). - * - * @param numEntries number of entries to add - */ - private void fillSet(int numEntries, Set<Integer> set) { - checkNotNull(set); - for (int i = 0; i < numEntries; i++) { - set.add(i); - } - } -} diff --git a/framework/src/onos/core/store/pom.xml b/framework/src/onos/core/store/pom.xml deleted file mode 100644 index 24326575..00000000 --- a/framework/src/onos/core/store/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright 2014 Open Networking Laboratory - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> - - <parent> - <groupId>org.onosproject</groupId> - <artifactId>onos-core</artifactId> - <version>1.4.0-rc1</version> - <relativePath>../pom.xml</relativePath> - </parent> - - <artifactId>onos-core-store</artifactId> - <packaging>pom</packaging> - - <description>ONOS Core Store subsystem</description> - - <modules> - <module>dist</module> - <module>persistence</module> - <module>serializers</module> - </modules> - - <dependencies> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-api</artifactId> - </dependency> - - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-core-common</artifactId> - <version>${project.version}</version> - <classifier>tests</classifier> - <scope>test</scope> - </dependency> - </dependencies> - -</project> diff --git a/framework/src/onos/core/store/serializers/pom.xml b/framework/src/onos/core/store/serializers/pom.xml deleted file mode 100644 index 6fe4c160..00000000 --- a/framework/src/onos/core/store/serializers/pom.xml +++ /dev/null @@ -1,50 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright 2014 Open Networking Laboratory - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> - - <parent> - <groupId>org.onosproject</groupId> - <artifactId>onos-core-store</artifactId> - <version>1.4.0-rc1</version> - <relativePath>../pom.xml</relativePath> - </parent> - - <artifactId>onos-core-serializers</artifactId> - <packaging>bundle</packaging> - - <description>Serializers for ONOS classes</description> - - <dependencies> - <dependency> - <groupId>com.esotericsoftware</groupId> - <artifactId>kryo</artifactId> - </dependency> - <dependency> - <groupId>com.google.guava</groupId> - <artifactId>guava-testlib</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-incubator-api</artifactId> - </dependency> - </dependencies> - -</project> diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/AnnotationsSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/AnnotationsSerializer.java deleted file mode 100644 index ed02c3e3..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/AnnotationsSerializer.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onosproject.net.DefaultAnnotations; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -import java.util.HashMap; - -public class AnnotationsSerializer extends Serializer<DefaultAnnotations> { - - public AnnotationsSerializer() { - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, DefaultAnnotations object) { - kryo.writeObject(output, object.asMap()); - } - - @Override - public DefaultAnnotations read(Kryo kryo, Input input, Class<DefaultAnnotations> type) { - DefaultAnnotations.Builder b = DefaultAnnotations.builder(); - HashMap<String, String> map = kryo.readObject(input, HashMap.class); - map.forEach((k, v) -> b.set(k, v)); - - return b.build(); - } - -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ArraysAsListSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ArraysAsListSerializer.java deleted file mode 100644 index 99c35310..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ArraysAsListSerializer.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.serializers; - -import java.util.ArrayList; -import java.util.List; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link java.util.Arrays#asList(Object...)}. - */ -public final class ArraysAsListSerializer extends Serializer<List<?>> { - - @Override - public void write(Kryo kryo, Output output, List<?> object) { - output.writeInt(object.size(), true); - for (Object elm : object) { - kryo.writeClassAndObject(output, elm); - } - } - - @Override - public List<?> read(Kryo kryo, Input input, Class<List<?>> type) { - final int size = input.readInt(true); - List<Object> list = new ArrayList<>(size); - for (int i = 0; i < size; ++i) { - list.add(kryo.readClassAndObject(input)); - } - return list; - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ConnectPointSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ConnectPointSerializer.java deleted file mode 100644 index f1027d5e..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ConnectPointSerializer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.ElementId; -import org.onosproject.net.PortNumber; -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link ConnectPointSerializer}. - */ -public class ConnectPointSerializer extends Serializer<ConnectPoint> { - - /** - * Creates {@link ConnectPointSerializer} serializer instance. - */ - public ConnectPointSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, ConnectPoint object) { - kryo.writeClassAndObject(output, object.elementId()); - kryo.writeClassAndObject(output, object.port()); - } - - @Override - public ConnectPoint read(Kryo kryo, Input input, Class<ConnectPoint> type) { - ElementId elementId = (ElementId) kryo.readClassAndObject(input); - PortNumber portNumber = (PortNumber) kryo.readClassAndObject(input); - return new ConnectPoint(elementId, portNumber); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultApplicationIdSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultApplicationIdSerializer.java deleted file mode 100644 index 0b1ad957..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultApplicationIdSerializer.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import org.onosproject.core.DefaultApplicationId; - -/** - * Kryo Serializer for {@link org.onosproject.core.DefaultApplicationId}. - */ -public final class DefaultApplicationIdSerializer extends Serializer<DefaultApplicationId> { - - /** - * Creates {@link org.onosproject.core.DefaultApplicationId} serializer instance. - */ - public DefaultApplicationIdSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, DefaultApplicationId object) { - kryo.writeObject(output, object.id()); - kryo.writeObject(output, object.name()); - } - - @Override - public DefaultApplicationId read(Kryo kryo, Input input, Class<DefaultApplicationId> type) { - short id = kryo.readObject(input, Short.class); - String name = kryo.readObject(input, String.class); - return new DefaultApplicationId(id, name); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultLinkSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultLinkSerializer.java deleted file mode 100644 index 6cc90667..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultLinkSerializer.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.DefaultLink; -import org.onosproject.net.Link.State; -import org.onosproject.net.Link.Type; -import org.onosproject.net.provider.ProviderId; - -/** - * Kryo Serializer for {@link DefaultLink}. - */ -public class DefaultLinkSerializer extends Serializer<DefaultLink> { - - /** - * Creates {@link DefaultLink} serializer instance. - */ - public DefaultLinkSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, DefaultLink object) { - kryo.writeClassAndObject(output, object.providerId()); - kryo.writeClassAndObject(output, object.src()); - kryo.writeClassAndObject(output, object.dst()); - kryo.writeClassAndObject(output, object.type()); - kryo.writeClassAndObject(output, object.state()); - output.writeBoolean(object.isDurable()); - } - - @Override - public DefaultLink read(Kryo kryo, Input input, Class<DefaultLink> type) { - ProviderId providerId = (ProviderId) kryo.readClassAndObject(input); - ConnectPoint src = (ConnectPoint) kryo.readClassAndObject(input); - ConnectPoint dst = (ConnectPoint) kryo.readClassAndObject(input); - Type linkType = (Type) kryo.readClassAndObject(input); - State state = (State) kryo.readClassAndObject(input); - boolean isDurable = input.readBoolean(); - return new DefaultLink(providerId, src, dst, linkType, state, isDurable); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultOutboundPacketSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultOutboundPacketSerializer.java deleted file mode 100644 index 9d12e458..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultOutboundPacketSerializer.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import java.nio.ByteBuffer; - -import org.onosproject.net.DeviceId; -import org.onosproject.net.flow.TrafficTreatment; -import org.onosproject.net.packet.DefaultOutboundPacket; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Serializer for a default outbound packet. - */ -public class DefaultOutboundPacketSerializer extends Serializer<DefaultOutboundPacket> { - - /** - * Creates {@link DefaultOutboundPacket} serializer instance. - */ - public DefaultOutboundPacketSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public DefaultOutboundPacket read(Kryo kryo, Input input, - Class<DefaultOutboundPacket> type) { - DeviceId sendThrough = (DeviceId) kryo.readClassAndObject(input); - TrafficTreatment treatment = (TrafficTreatment) kryo.readClassAndObject(input); - byte[] data = (byte[]) kryo.readClassAndObject(input); - return new DefaultOutboundPacket(sendThrough, treatment, ByteBuffer.wrap(data)); - } - - @Override - public void write(Kryo kryo, Output output, DefaultOutboundPacket object) { - kryo.writeClassAndObject(output, object.sendThrough()); - kryo.writeClassAndObject(output, object.treatment()); - kryo.writeClassAndObject(output, object.data().array()); - } - -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultPortSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultPortSerializer.java deleted file mode 100644 index 60d09fbe..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultPortSerializer.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onosproject.net.Annotations; -import org.onosproject.net.DefaultPort; -import org.onosproject.net.Element; -import org.onosproject.net.Port; -import org.onosproject.net.PortNumber; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link DefaultPort}. - */ -public final class DefaultPortSerializer extends - Serializer<DefaultPort> { - - /** - * Creates {@link DefaultPort} serializer instance. - */ - public DefaultPortSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, DefaultPort object) { - kryo.writeClassAndObject(output, object.element()); - kryo.writeObject(output, object.number()); - output.writeBoolean(object.isEnabled()); - kryo.writeObject(output, object.type()); - output.writeLong(object.portSpeed()); - kryo.writeClassAndObject(output, object.annotations()); - } - - @Override - public DefaultPort read(Kryo kryo, Input input, Class<DefaultPort> aClass) { - Element element = (Element) kryo.readClassAndObject(input); - PortNumber number = kryo.readObject(input, PortNumber.class); - boolean isEnabled = input.readBoolean(); - Port.Type type = kryo.readObject(input, Port.Type.class); - long portSpeed = input.readLong(); - Annotations annotations = (Annotations) kryo.readClassAndObject(input); - - return new DefaultPort(element, number, isEnabled, type, portSpeed, annotations); - } - -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DeviceIdSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DeviceIdSerializer.java deleted file mode 100644 index a74a7695..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/DeviceIdSerializer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onosproject.net.DeviceId; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** -* Kryo Serializer for {@link DeviceId}. -*/ -public final class DeviceIdSerializer extends Serializer<DeviceId> { - - /** - * Creates {@link DeviceId} serializer instance. - */ - public DeviceIdSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, DeviceId object) { - output.writeString(object.toString()); - } - - @Override - public DeviceId read(Kryo kryo, Input input, Class<DeviceId> type) { - final String str = input.readString(); - return DeviceId.deviceId(str); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ExtensionInstructionSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ExtensionInstructionSerializer.java deleted file mode 100644 index e688a80c..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ExtensionInstructionSerializer.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onosproject.store.serializers; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import org.onlab.osgi.DefaultServiceDirectory; -import org.onosproject.net.DeviceId; -import org.onosproject.net.behaviour.ExtensionTreatmentResolver; -import org.onosproject.net.driver.DefaultDriverData; -import org.onosproject.net.driver.DefaultDriverHandler; -import org.onosproject.net.driver.DriverHandler; -import org.onosproject.net.driver.DriverService; -import org.onosproject.net.flow.instructions.ExtensionTreatment; -import org.onosproject.net.flow.instructions.ExtensionTreatmentType; -import org.onosproject.net.flow.instructions.Instructions; - -/** - * Created by jono on 10/29/15. - */ -public class ExtensionInstructionSerializer extends - Serializer<Instructions.ExtensionInstructionWrapper> { - - public ExtensionInstructionSerializer() { - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, Instructions.ExtensionInstructionWrapper object) { - kryo.writeClassAndObject(output, object.extensionInstruction().type()); - kryo.writeClassAndObject(output, object.deviceId()); - - kryo.writeClassAndObject(output, object.extensionInstruction().serialize()); - - } - - @Override - public Instructions.ExtensionInstructionWrapper read(Kryo kryo, Input input, - Class<Instructions.ExtensionInstructionWrapper> type) { - ExtensionTreatmentType exType = (ExtensionTreatmentType) kryo.readClassAndObject(input); - DeviceId deviceId = (DeviceId) kryo.readClassAndObject(input); - - DriverService driverService = DefaultServiceDirectory.getService(DriverService.class); - DriverHandler handler = new DefaultDriverHandler( - new DefaultDriverData(driverService.getDriver(deviceId), deviceId)); - - ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class); - - ExtensionTreatment instruction = resolver.getExtensionInstruction(exType); - - byte[] bytes = (byte[]) kryo.readClassAndObject(input); - - instruction.deserialize(bytes); - - return Instructions.extension(instruction, deviceId); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/HostLocationSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/HostLocationSerializer.java deleted file mode 100644 index 270eb218..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/HostLocationSerializer.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onosproject.net.DeviceId; -import org.onosproject.net.HostLocation; -import org.onosproject.net.PortNumber; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** -* Kryo Serializer for {@link HostLocation}. -*/ -public class HostLocationSerializer extends Serializer<HostLocation> { - - /** - * Creates {@link HostLocation} serializer instance. - */ - public HostLocationSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, HostLocation object) { - kryo.writeClassAndObject(output, object.deviceId()); - kryo.writeClassAndObject(output, object.port()); - output.writeLong(object.time()); - } - - @Override - public HostLocation read(Kryo kryo, Input input, Class<HostLocation> type) { - DeviceId deviceId = (DeviceId) kryo.readClassAndObject(input); - PortNumber portNumber = (PortNumber) kryo.readClassAndObject(input); - long time = input.readLong(); - return new HostLocation(deviceId, portNumber, time); - } - -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ImmutableListSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ImmutableListSerializer.java deleted file mode 100644 index 95166c3b..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ImmutableListSerializer.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableList.Builder; - -/** - * Creates {@link ImmutableList} serializer instance. - */ -public class ImmutableListSerializer extends Serializer<ImmutableList<?>> { - - /** - * Creates {@link ImmutableList} serializer instance. - */ - public ImmutableListSerializer() { - // non-null, immutable - super(false, true); - } - @Override - public void write(Kryo kryo, Output output, ImmutableList<?> object) { - output.writeInt(object.size()); - for (Object e : object) { - kryo.writeClassAndObject(output, e); - } - } - - @Override - public ImmutableList<?> read(Kryo kryo, Input input, - Class<ImmutableList<?>> type) { - final int size = input.readInt(); - Builder<Object> builder = ImmutableList.builder(); - for (int i = 0; i < size; ++i) { - builder.add(kryo.readClassAndObject(input)); - } - return builder.build(); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ImmutableMapSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ImmutableMapSerializer.java deleted file mode 100644 index 4d6af788..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ImmutableMapSerializer.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import com.esotericsoftware.kryo.serializers.MapSerializer; -import com.google.common.collect.ImmutableMap; - -/** -* Kryo Serializer for {@link ImmutableMap}. -*/ -public class ImmutableMapSerializer extends Serializer<ImmutableMap<?, ?>> { - - private final MapSerializer mapSerializer = new MapSerializer(); - - /** - * Creates {@link ImmutableMap} serializer instance. - */ - public ImmutableMapSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, ImmutableMap<?, ?> object) { - // wrapping with unmodifiableMap proxy - // to avoid Kryo from writing only the reference marker of this instance, - // which will be embedded right before this method call. - kryo.writeObject(output, Collections.unmodifiableMap(object), mapSerializer); - } - - @Override - public ImmutableMap<?, ?> read(Kryo kryo, Input input, - Class<ImmutableMap<?, ?>> type) { - Map<?, ?> map = kryo.readObject(input, HashMap.class, mapSerializer); - return ImmutableMap.copyOf(map); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ImmutableSetSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ImmutableSetSerializer.java deleted file mode 100644 index cb9b0543..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ImmutableSetSerializer.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import java.util.ArrayList; -import java.util.List; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import com.esotericsoftware.kryo.serializers.CollectionSerializer; -import com.google.common.collect.ImmutableSet; - -/** -* Kryo Serializer for {@link ImmutableSet}. -*/ -public class ImmutableSetSerializer extends Serializer<ImmutableSet<?>> { - - private final CollectionSerializer serializer = new CollectionSerializer(); - - /** - * Creates {@link ImmutableSet} serializer instance. - */ - public ImmutableSetSerializer() { - // non-null, immutable - super(false, true); - serializer.setElementsCanBeNull(false); - } - - @Override - public void write(Kryo kryo, Output output, ImmutableSet<?> object) { - kryo.writeObject(output, object.asList(), serializer); - } - - @Override - public ImmutableSet<?> read(Kryo kryo, Input input, - Class<ImmutableSet<?>> type) { - List<?> elms = kryo.readObject(input, ArrayList.class, serializer); - return ImmutableSet.copyOf(elms); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/Ip4AddressSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/Ip4AddressSerializer.java deleted file mode 100644 index 2370ad92..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/Ip4AddressSerializer.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onlab.packet.Ip4Address; -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link Ip4Address}. - */ -public class Ip4AddressSerializer extends Serializer<Ip4Address> { - - /** - * Creates {@link Ip4Address} serializer instance. - */ - public Ip4AddressSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, Ip4Address object) { - byte[] octs = object.toOctets(); - // It is always Ip4Address.BYTE_LENGTH - output.writeInt(octs.length); - output.writeBytes(octs); - } - - @Override - public Ip4Address read(Kryo kryo, Input input, Class<Ip4Address> type) { - final int octLen = input.readInt(); - byte[] octs = new byte[octLen]; - input.readBytes(octs); - return Ip4Address.valueOf(octs); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/Ip4PrefixSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/Ip4PrefixSerializer.java deleted file mode 100644 index 029ffb1a..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/Ip4PrefixSerializer.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onlab.packet.Ip4Prefix; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link Ip4Prefix}. - */ -public final class Ip4PrefixSerializer extends Serializer<Ip4Prefix> { - - /** - * Creates {@link Ip4Prefix} serializer instance. - */ - public Ip4PrefixSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, - Ip4Prefix object) { - byte[] octs = object.address().toOctets(); - // It is always Ip4Address.BYTE_LENGTH - output.writeInt(octs.length); - output.writeBytes(octs); - output.writeInt(object.prefixLength()); - } - - @Override - public Ip4Prefix read(Kryo kryo, Input input, - Class<Ip4Prefix> type) { - int octLen = input.readInt(); - byte[] octs = new byte[octLen]; - input.readBytes(octs); - int prefLen = input.readInt(); - return Ip4Prefix.valueOf(octs, prefLen); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/Ip6AddressSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/Ip6AddressSerializer.java deleted file mode 100644 index f8101f98..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/Ip6AddressSerializer.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onlab.packet.Ip6Address; -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link Ip6Address}. - */ -public class Ip6AddressSerializer extends Serializer<Ip6Address> { - - /** - * Creates {@link Ip6Address} serializer instance. - */ - public Ip6AddressSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, Ip6Address object) { - byte[] octs = object.toOctets(); - // It is always Ip6Address.BYTE_LENGTH - output.writeInt(octs.length); - output.writeBytes(octs); - } - - @Override - public Ip6Address read(Kryo kryo, Input input, Class<Ip6Address> type) { - final int octLen = input.readInt(); - byte[] octs = new byte[octLen]; - input.readBytes(octs); - return Ip6Address.valueOf(octs); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/Ip6PrefixSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/Ip6PrefixSerializer.java deleted file mode 100644 index 91ba5a29..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/Ip6PrefixSerializer.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onlab.packet.Ip6Prefix; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link Ip6Prefix}. - */ -public final class Ip6PrefixSerializer extends Serializer<Ip6Prefix> { - - /** - * Creates {@link Ip6Prefix} serializer instance. - */ - public Ip6PrefixSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, - Ip6Prefix object) { - byte[] octs = object.address().toOctets(); - // It is always Ip6Address.BYTE_LENGTH - output.writeInt(octs.length); - output.writeBytes(octs); - output.writeInt(object.prefixLength()); - } - - @Override - public Ip6Prefix read(Kryo kryo, Input input, - Class<Ip6Prefix> type) { - int octLen = input.readInt(); - byte[] octs = new byte[octLen]; - input.readBytes(octs); - int prefLen = input.readInt(); - return Ip6Prefix.valueOf(octs, prefLen); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/IpAddressSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/IpAddressSerializer.java deleted file mode 100644 index cb85fec8..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/IpAddressSerializer.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onlab.packet.IpAddress; -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link IpAddress}. - */ -public class IpAddressSerializer extends Serializer<IpAddress> { - - /** - * Creates {@link IpAddress} serializer instance. - */ - public IpAddressSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, IpAddress object) { - byte[] octs = object.toOctets(); - output.writeInt(octs.length); - output.writeBytes(octs); - } - - @Override - public IpAddress read(Kryo kryo, Input input, Class<IpAddress> type) { - final int octLen = input.readInt(); - byte[] octs = new byte[octLen]; - input.readBytes(octs); - // Use the address size to decide whether it is IPv4 or IPv6 address - if (octLen == IpAddress.INET_BYTE_LENGTH) { - return IpAddress.valueOf(IpAddress.Version.INET, octs); - } - if (octLen == IpAddress.INET6_BYTE_LENGTH) { - return IpAddress.valueOf(IpAddress.Version.INET6, octs); - } - return null; // Shouldn't be reached - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/IpPrefixSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/IpPrefixSerializer.java deleted file mode 100644 index cf0a20b9..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/IpPrefixSerializer.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onlab.packet.IpAddress; -import org.onlab.packet.IpPrefix; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link IpPrefix}. - */ -public final class IpPrefixSerializer extends Serializer<IpPrefix> { - - /** - * Creates {@link IpPrefix} serializer instance. - */ - public IpPrefixSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, - IpPrefix object) { - byte[] octs = object.address().toOctets(); - output.writeInt(octs.length); - output.writeBytes(octs); - output.writeInt(object.prefixLength()); - } - - @Override - public IpPrefix read(Kryo kryo, Input input, - Class<IpPrefix> type) { - int octLen = input.readInt(); - byte[] octs = new byte[octLen]; - input.readBytes(octs); - int prefLen = input.readInt(); - // Use the address size to decide whether it is IPv4 or IPv6 address - if (octLen == IpAddress.INET_BYTE_LENGTH) { - return IpPrefix.valueOf(IpAddress.Version.INET, octs, prefLen); - } - if (octLen == IpAddress.INET6_BYTE_LENGTH) { - return IpPrefix.valueOf(IpAddress.Version.INET6, octs, prefLen); - } - return null; // Shouldn't be reached - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java deleted file mode 100644 index 1b883a30..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Maps; -import org.onlab.packet.ChassisId; -import org.onlab.packet.EthType; -import org.onlab.packet.Ip4Address; -import org.onlab.packet.Ip4Prefix; -import org.onlab.packet.Ip6Address; -import org.onlab.packet.Ip6Prefix; -import org.onlab.packet.IpAddress; -import org.onlab.packet.IpPrefix; -import org.onlab.packet.MacAddress; -import org.onlab.packet.TpPort; -import org.onlab.packet.VlanId; -import org.onlab.util.Bandwidth; -import org.onlab.util.Frequency; -import org.onlab.util.KryoNamespace; -import org.onosproject.app.ApplicationState; -import org.onosproject.cluster.ControllerNode; -import org.onosproject.cluster.DefaultControllerNode; -import org.onosproject.cluster.Leadership; -import org.onosproject.cluster.LeadershipEvent; -import org.onosproject.cluster.NodeId; -import org.onosproject.cluster.RoleInfo; -import org.onosproject.core.ApplicationRole; -import org.onosproject.core.DefaultApplication; -import org.onosproject.core.DefaultApplicationId; -import org.onosproject.core.DefaultGroupId; -import org.onosproject.core.Version; -import org.onosproject.incubator.net.domain.IntentDomainId; -import org.onosproject.mastership.MastershipTerm; -import org.onosproject.net.Annotations; -import org.onosproject.net.ChannelSpacing; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.DefaultDevice; -import org.onosproject.net.DefaultEdgeLink; -import org.onosproject.net.DefaultHost; -import org.onosproject.net.DefaultLink; -import org.onosproject.net.DefaultPath; -import org.onosproject.net.DefaultPort; -import org.onosproject.net.Device; -import org.onosproject.net.DeviceId; -import org.onosproject.net.Element; -import org.onosproject.net.GridType; -import org.onosproject.net.HostId; -import org.onosproject.net.HostLocation; -import org.onosproject.net.IndexedLambda; -import org.onosproject.net.Link; -import org.onosproject.net.LinkKey; -import org.onosproject.net.OchPort; -import org.onosproject.net.OchSignal; -import org.onosproject.net.OchSignalType; -import org.onosproject.net.OduCltPort; -import org.onosproject.net.OduSignalId; -import org.onosproject.net.OduSignalType; -import org.onosproject.net.OmsPort; -import org.onosproject.net.Port; -import org.onosproject.net.PortNumber; -import org.onosproject.net.TributarySlot; -import org.onosproject.net.device.DefaultDeviceDescription; -import org.onosproject.net.device.DefaultPortDescription; -import org.onosproject.net.device.DefaultPortStatistics; -import org.onosproject.net.device.OchPortDescription; -import org.onosproject.net.device.OduCltPortDescription; -import org.onosproject.net.device.OmsPortDescription; -import org.onosproject.net.device.PortStatistics; -import org.onosproject.net.flow.CompletedBatchOperation; -import org.onosproject.net.flow.DefaultFlowEntry; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTableStatisticsEntry; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowEntry; -import org.onosproject.net.flow.FlowId; -import org.onosproject.net.flow.FlowRuleBatchEntry; -import org.onosproject.net.flow.FlowRuleBatchEvent; -import org.onosproject.net.flow.FlowRuleBatchOperation; -import org.onosproject.net.flow.FlowRuleBatchRequest; -import org.onosproject.net.flow.FlowRuleEvent; -import org.onosproject.net.flow.FlowRuleExtPayLoad; -import org.onosproject.net.flow.StoredFlowEntry; -import org.onosproject.net.flow.TableStatisticsEntry; -import org.onosproject.net.flow.criteria.Criterion; -import org.onosproject.net.flow.criteria.EthCriterion; -import org.onosproject.net.flow.criteria.EthTypeCriterion; -import org.onosproject.net.flow.criteria.IPCriterion; -import org.onosproject.net.flow.criteria.IPDscpCriterion; -import org.onosproject.net.flow.criteria.IPEcnCriterion; -import org.onosproject.net.flow.criteria.IPProtocolCriterion; -import org.onosproject.net.flow.criteria.IPv6ExthdrFlagsCriterion; -import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion; -import org.onosproject.net.flow.criteria.IPv6NDLinkLayerAddressCriterion; -import org.onosproject.net.flow.criteria.IPv6NDTargetAddressCriterion; -import org.onosproject.net.flow.criteria.IcmpCodeCriterion; -import org.onosproject.net.flow.criteria.IcmpTypeCriterion; -import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion; -import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion; -import org.onosproject.net.flow.criteria.IndexedLambdaCriterion; -import org.onosproject.net.flow.criteria.LambdaCriterion; -import org.onosproject.net.flow.criteria.MetadataCriterion; -import org.onosproject.net.flow.criteria.MplsCriterion; -import org.onosproject.net.flow.criteria.OchSignalCriterion; -import org.onosproject.net.flow.criteria.OchSignalTypeCriterion; -import org.onosproject.net.flow.criteria.OduSignalIdCriterion; -import org.onosproject.net.flow.criteria.OduSignalTypeCriterion; -import org.onosproject.net.flow.criteria.PortCriterion; -import org.onosproject.net.flow.criteria.SctpPortCriterion; -import org.onosproject.net.flow.criteria.TcpPortCriterion; -import org.onosproject.net.flow.criteria.TunnelIdCriterion; -import org.onosproject.net.flow.criteria.UdpPortCriterion; -import org.onosproject.net.flow.criteria.VlanIdCriterion; -import org.onosproject.net.flow.criteria.VlanPcpCriterion; -import org.onosproject.net.flow.instructions.ExtensionTreatmentType; -import org.onosproject.net.flow.instructions.Instructions; -import org.onosproject.net.flow.instructions.L0ModificationInstruction; -import org.onosproject.net.flow.instructions.L1ModificationInstruction; -import org.onosproject.net.flow.instructions.L2ModificationInstruction; -import org.onosproject.net.flow.instructions.L3ModificationInstruction; -import org.onosproject.net.flow.instructions.L4ModificationInstruction; -import org.onosproject.net.host.DefaultHostDescription; -import org.onosproject.net.host.HostDescription; -import org.onosproject.net.intent.ConnectivityIntent; -import org.onosproject.net.intent.FlowRuleIntent; -import org.onosproject.net.intent.HostToHostIntent; -import org.onosproject.net.intent.Intent; -import org.onosproject.net.intent.IntentId; -import org.onosproject.net.intent.IntentOperation; -import org.onosproject.net.intent.IntentState; -import org.onosproject.net.intent.Key; -import org.onosproject.net.intent.LinkCollectionIntent; -import org.onosproject.net.intent.MplsIntent; -import org.onosproject.net.intent.MplsPathIntent; -import org.onosproject.net.intent.MultiPointToSinglePointIntent; -import org.onosproject.net.intent.OpticalCircuitIntent; -import org.onosproject.net.intent.OpticalConnectivityIntent; -import org.onosproject.net.intent.OpticalPathIntent; -import org.onosproject.net.intent.PathIntent; -import org.onosproject.net.intent.PointToPointIntent; -import org.onosproject.net.intent.SinglePointToMultiPointIntent; -import org.onosproject.net.intent.constraint.AnnotationConstraint; -import org.onosproject.net.intent.constraint.BandwidthConstraint; -import org.onosproject.net.intent.constraint.BooleanConstraint; -import org.onosproject.net.intent.constraint.LambdaConstraint; -import org.onosproject.net.intent.constraint.LatencyConstraint; -import org.onosproject.net.intent.constraint.LinkTypeConstraint; -import org.onosproject.net.intent.constraint.ObstacleConstraint; -import org.onosproject.net.intent.constraint.PartialFailureConstraint; -import org.onosproject.net.intent.constraint.WaypointConstraint; -import org.onosproject.net.link.DefaultLinkDescription; -import org.onosproject.net.meter.MeterId; -import org.onosproject.net.newresource.ResourceAllocation; -import org.onosproject.net.newresource.ResourcePath; -import org.onosproject.net.packet.DefaultOutboundPacket; -import org.onosproject.net.packet.DefaultPacketRequest; -import org.onosproject.net.packet.PacketPriority; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.net.resource.link.BandwidthResource; -import org.onosproject.net.resource.link.BandwidthResourceAllocation; -import org.onosproject.net.resource.link.BandwidthResourceRequest; -import org.onosproject.net.resource.link.DefaultLinkResourceAllocations; -import org.onosproject.net.resource.link.DefaultLinkResourceRequest; -import org.onosproject.net.resource.link.LambdaResource; -import org.onosproject.net.resource.link.LambdaResourceAllocation; -import org.onosproject.net.resource.link.LambdaResourceRequest; -import org.onosproject.net.resource.link.LinkResourceRequest; -import org.onosproject.net.resource.link.MplsLabel; -import org.onosproject.net.resource.link.MplsLabelResourceAllocation; -import org.onosproject.net.resource.link.MplsLabelResourceRequest; -import org.onosproject.store.Timestamp; -import org.onosproject.store.service.MapEvent; -import org.onosproject.store.service.SetEvent; -import org.onosproject.store.service.Versioned; - -import java.net.URI; -import java.time.Duration; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -public final class KryoNamespaces { - - public static final KryoNamespace BASIC = KryoNamespace.newBuilder() - .nextId(KryoNamespace.FLOATING_ID) - .register(byte[].class) - .register(AtomicBoolean.class) - .register(AtomicInteger.class) - .register(AtomicLong.class) - .register(new ImmutableListSerializer(), - ImmutableList.class, - ImmutableList.of(1).getClass(), - ImmutableList.of(1, 2).getClass()) - .register(new ImmutableSetSerializer(), - ImmutableSet.class, - ImmutableSet.of().getClass(), - ImmutableSet.of(1).getClass(), - ImmutableSet.of(1, 2).getClass()) - .register(new ImmutableMapSerializer(), - ImmutableMap.class, - ImmutableMap.of().getClass(), - ImmutableMap.of("a", 1).getClass(), - ImmutableMap.of("R", 2, "D", 2).getClass()) - .register(HashMap.class) - .register(ConcurrentHashMap.class) - .register(CopyOnWriteArraySet.class) - .register(ArrayList.class, - LinkedList.class, - HashSet.class - ) - .register(Maps.immutableEntry("a", "b").getClass()) - .register(new ArraysAsListSerializer(), Arrays.asList().getClass()) - .register(Collections.singletonList(1).getClass()) - .register(Duration.class) - .register(Collections.emptySet().getClass()) - .register(Optional.class) - .register(Collections.emptyList().getClass()) - .register(Collections.unmodifiableSet(Collections.emptySet()).getClass()) - .register(Collections.singleton(Object.class).getClass()) - .build(); - - /** - * KryoNamespace which can serialize ON.lab misc classes. - */ - public static final KryoNamespace MISC = KryoNamespace.newBuilder() - .nextId(KryoNamespace.FLOATING_ID) - .register(new IpPrefixSerializer(), IpPrefix.class) - .register(new Ip4PrefixSerializer(), Ip4Prefix.class) - .register(new Ip6PrefixSerializer(), Ip6Prefix.class) - .register(new IpAddressSerializer(), IpAddress.class) - .register(new Ip4AddressSerializer(), Ip4Address.class) - .register(new Ip6AddressSerializer(), Ip6Address.class) - .register(new MacAddressSerializer(), MacAddress.class) - .register(VlanId.class) - .register(Frequency.class) - .register(Bandwidth.class) - .build(); - - /** - * Kryo registration Id for user custom registration. - */ - public static final int BEGIN_USER_CUSTOM_ID = 300; - - // TODO: Populate other classes - /** - * KryoNamespace which can serialize API bundle classes. - */ - public static final KryoNamespace API = KryoNamespace.newBuilder() - .nextId(KryoNamespace.INITIAL_ID) - .register(BASIC) - .nextId(KryoNamespace.INITIAL_ID + 30) - .register(MISC) - .nextId(KryoNamespace.INITIAL_ID + 30 + 10) - .register( - Instructions.MeterInstruction.class, - MeterId.class, - Version.class, - ControllerNode.State.class, - ApplicationState.class, - ApplicationRole.class, - DefaultApplication.class, - Device.Type.class, - Port.Type.class, - ChassisId.class, - DefaultControllerNode.class, - DefaultDevice.class, - DefaultDeviceDescription.class, - DefaultHost.class, - DefaultLinkDescription.class, - Port.class, - DefaultPortDescription.class, - Element.class, - Link.Type.class, - Link.State.class, - Timestamp.class, - Leadership.class, - LeadershipEvent.class, - LeadershipEvent.Type.class, - HostId.class, - HostDescription.class, - DefaultHostDescription.class, - DefaultFlowEntry.class, - StoredFlowEntry.class, - DefaultFlowRule.class, - DefaultFlowEntry.class, - DefaultPacketRequest.class, - PacketPriority.class, - FlowEntry.FlowEntryState.class, - FlowId.class, - DefaultTrafficSelector.class, - PortCriterion.class, - MetadataCriterion.class, - EthCriterion.class, - EthType.class, - EthTypeCriterion.class, - VlanIdCriterion.class, - VlanPcpCriterion.class, - IPDscpCriterion.class, - IPEcnCriterion.class, - IPProtocolCriterion.class, - IPCriterion.class, - TpPort.class, - TcpPortCriterion.class, - UdpPortCriterion.class, - SctpPortCriterion.class, - IcmpTypeCriterion.class, - IcmpCodeCriterion.class, - IPv6FlowLabelCriterion.class, - Icmpv6TypeCriterion.class, - Icmpv6CodeCriterion.class, - IPv6NDTargetAddressCriterion.class, - IPv6NDLinkLayerAddressCriterion.class, - MplsCriterion.class, - TunnelIdCriterion.class, - IPv6ExthdrFlagsCriterion.class, - LambdaCriterion.class, - IndexedLambdaCriterion.class, - OchSignalCriterion.class, - OchSignalTypeCriterion.class, - OduSignalIdCriterion.class, - OduSignalTypeCriterion.class, - Criterion.class, - Criterion.Type.class, - DefaultTrafficTreatment.class, - Instructions.DropInstruction.class, - Instructions.NoActionInstruction.class, - Instructions.OutputInstruction.class, - Instructions.GroupInstruction.class, - Instructions.TableTypeTransition.class, - L0ModificationInstruction.class, - L0ModificationInstruction.L0SubType.class, - L0ModificationInstruction.ModLambdaInstruction.class, - L0ModificationInstruction.ModOchSignalInstruction.class, - L1ModificationInstruction.class, - L1ModificationInstruction.L1SubType.class, - L1ModificationInstruction.ModOduSignalIdInstruction.class, - L2ModificationInstruction.class, - L2ModificationInstruction.L2SubType.class, - L2ModificationInstruction.ModEtherInstruction.class, - L2ModificationInstruction.PushHeaderInstructions.class, - L2ModificationInstruction.ModVlanIdInstruction.class, - L2ModificationInstruction.ModVlanPcpInstruction.class, - L2ModificationInstruction.PopVlanInstruction.class, - L2ModificationInstruction.ModMplsLabelInstruction.class, - L2ModificationInstruction.ModMplsBosInstruction.class, - L2ModificationInstruction.ModMplsTtlInstruction.class, - L2ModificationInstruction.ModTunnelIdInstruction.class, - L3ModificationInstruction.class, - L3ModificationInstruction.L3SubType.class, - L3ModificationInstruction.ModIPInstruction.class, - L3ModificationInstruction.ModIPv6FlowLabelInstruction.class, - L3ModificationInstruction.ModTtlInstruction.class, - L4ModificationInstruction.class, - L4ModificationInstruction.L4SubType.class, - L4ModificationInstruction.ModTransportPortInstruction.class, - RoleInfo.class, - FlowRuleBatchEvent.class, - FlowRuleBatchEvent.Type.class, - FlowRuleBatchRequest.class, - FlowRuleBatchOperation.class, - FlowRuleEvent.class, - FlowRuleEvent.Type.class, - CompletedBatchOperation.class, - FlowRuleBatchEntry.class, - FlowRuleBatchEntry.FlowRuleOperation.class, - IntentId.class, - IntentState.class, - //Key.class, is abstract - Key.of(1L, new DefaultApplicationId(0, "bar")).getClass(), //LongKey.class - Key.of("foo", new DefaultApplicationId(0, "bar")).getClass(), //StringKey.class - Intent.class, - ConnectivityIntent.class, - PathIntent.class, - DefaultPath.class, - DefaultEdgeLink.class, - HostToHostIntent.class, - PointToPointIntent.class, - MultiPointToSinglePointIntent.class, - SinglePointToMultiPointIntent.class, - FlowRuleIntent.class, - LinkCollectionIntent.class, - OpticalConnectivityIntent.class, - OpticalPathIntent.class, - OpticalCircuitIntent.class, - LinkResourceRequest.class, - DefaultLinkResourceRequest.class, - BandwidthResourceRequest.class, - LambdaResourceRequest.class, - LambdaResource.class, - BandwidthResource.class, - DefaultLinkResourceAllocations.class, - BandwidthResourceAllocation.class, - LambdaResourceAllocation.class, - ResourcePath.class, - ResourcePath.Discrete.class, - ResourcePath.Continuous.class, - ResourceAllocation.class, - // Constraints - LambdaConstraint.class, - BandwidthConstraint.class, - LinkTypeConstraint.class, - LatencyConstraint.class, - WaypointConstraint.class, - ObstacleConstraint.class, - AnnotationConstraint.class, - BooleanConstraint.class, - PartialFailureConstraint.class, - IntentOperation.class, - FlowRuleExtPayLoad.class, - Frequency.class, - DefaultAnnotations.class, - PortStatistics.class, - DefaultPortStatistics.class, - IntentDomainId.class, - TableStatisticsEntry.class, - DefaultTableStatisticsEntry.class - ) - .register(new DefaultApplicationIdSerializer(), DefaultApplicationId.class) - .register(new UriSerializer(), URI.class) - .register(new NodeIdSerializer(), NodeId.class) - .register(new ProviderIdSerializer(), ProviderId.class) - .register(new DeviceIdSerializer(), DeviceId.class) - .register(new PortNumberSerializer(), PortNumber.class) - .register(new DefaultPortSerializer(), DefaultPort.class) - .register(new LinkKeySerializer(), LinkKey.class) - .register(new ConnectPointSerializer(), ConnectPoint.class) - .register(new DefaultLinkSerializer(), DefaultLink.class) - .register(new MastershipTermSerializer(), MastershipTerm.class) - .register(new HostLocationSerializer(), HostLocation.class) - .register(new DefaultOutboundPacketSerializer(), DefaultOutboundPacket.class) - .register(new AnnotationsSerializer(), DefaultAnnotations.class) - .register(new ExtensionInstructionSerializer(), Instructions.ExtensionInstructionWrapper.class) - .register(ExtensionTreatmentType.class) - .register(Versioned.class) - .register(MapEvent.class) - .register(MapEvent.Type.class) - .register(SetEvent.class) - .register(SetEvent.Type.class) - .register(DefaultGroupId.class) - .register(Annotations.class) - .register(OmsPort.class) - .register(OchPort.class) - .register(OduSignalType.class) - .register(OchSignalType.class) - .register(GridType.class) - .register(ChannelSpacing.class) - .register(OduCltPort.class) - .register(OduCltPort.SignalType.class) - .register(IndexedLambda.class) - .register(OchSignal.class) - .register(OduSignalId.class) - .register(OduCltPortDescription.class) - .register(OchPortDescription.class) - .register(OmsPortDescription.class) - .register(TributarySlot.class) - .register( - MplsIntent.class, - MplsPathIntent.class, - MplsLabelResourceAllocation.class, - MplsLabelResourceRequest.class, - MplsLabel.class, - org.onlab.packet.MplsLabel.class, - org.onlab.packet.MPLS.class - ) - - .build(); - - - // not to be instantiated - private KryoNamespaces() {} -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoSerializer.java deleted file mode 100644 index dbad6d0d..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoSerializer.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; - -import org.onlab.util.KryoNamespace; - -import com.google.common.base.MoreObjects; - -/** - * StoreSerializer implementation using Kryo. - */ -public class KryoSerializer implements StoreSerializer { - - protected KryoNamespace serializerPool; - - public KryoSerializer() { - setupKryoPool(); - } - - /** - * Sets up the common serializers pool. - */ - protected void setupKryoPool() { - serializerPool = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID) - .build(); - } - - @Override - public byte[] encode(final Object obj) { - return serializerPool.serialize(obj); - } - - @Override - public <T> T decode(final byte[] bytes) { - if (bytes == null) { - return null; - } - return serializerPool.deserialize(bytes); - } - - @Override - public void encode(Object obj, ByteBuffer buffer) { - serializerPool.serialize(obj, buffer); - } - - @Override - public <T> T decode(ByteBuffer buffer) { - return serializerPool.deserialize(buffer); - } - - @Override - public void encode(Object obj, OutputStream stream) { - serializerPool.serialize(obj, stream); - } - - @Override - public <T> T decode(InputStream stream) { - return serializerPool.deserialize(stream); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("serializerPool", serializerPool) - .toString(); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/LinkKeySerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/LinkKeySerializer.java deleted file mode 100644 index 4bef3369..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/LinkKeySerializer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.LinkKey; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link LinkKey}. - */ -public class LinkKeySerializer extends Serializer<LinkKey> { - - /** - * Creates {@link LinkKey} serializer instance. - */ - public LinkKeySerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, LinkKey object) { - kryo.writeClassAndObject(output, object.src()); - kryo.writeClassAndObject(output, object.dst()); - } - - @Override - public LinkKey read(Kryo kryo, Input input, Class<LinkKey> type) { - ConnectPoint src = (ConnectPoint) kryo.readClassAndObject(input); - ConnectPoint dst = (ConnectPoint) kryo.readClassAndObject(input); - return LinkKey.linkKey(src, dst); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/MacAddressSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/MacAddressSerializer.java deleted file mode 100644 index 881e0ec0..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/MacAddressSerializer.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onlab.packet.MacAddress; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link MacAddress}. - */ -public class MacAddressSerializer extends Serializer<MacAddress> { - - /** - * Creates {@link MacAddress} serializer instance. - */ - public MacAddressSerializer() { - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, MacAddress object) { - output.writeBytes(object.toBytes()); - } - - @Override - public MacAddress read(Kryo kryo, Input input, Class<MacAddress> type) { - return MacAddress.valueOf(input.readBytes(MacAddress.MAC_ADDRESS_LENGTH)); - } - -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/MastershipTermSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/MastershipTermSerializer.java deleted file mode 100644 index 43bce71c..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/MastershipTermSerializer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onosproject.cluster.NodeId; -import org.onosproject.mastership.MastershipTerm; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Kryo Serializer for {@link org.onosproject.mastership.MastershipTerm}. - */ -public class MastershipTermSerializer extends Serializer<MastershipTerm> { - - /** - * Creates {@link MastershipTerm} serializer instance. - */ - public MastershipTermSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public MastershipTerm read(Kryo kryo, Input input, Class<MastershipTerm> type) { - final NodeId node = (NodeId) kryo.readClassAndObject(input); - final long term = input.readLong(); - return MastershipTerm.of(node, term); - } - - @Override - public void write(Kryo kryo, Output output, MastershipTerm object) { - kryo.writeClassAndObject(output, object.master()); - output.writeLong(object.termNumber()); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/NodeIdSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/NodeIdSerializer.java deleted file mode 100644 index da8939b0..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/NodeIdSerializer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -import org.onosproject.cluster.NodeId; - -/** - * Kryo Serializer for {@link org.onosproject.cluster.NodeId}. - */ -public final class NodeIdSerializer extends Serializer<NodeId> { - - /** - * Creates {@link NodeId} serializer instance. - */ - public NodeIdSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, NodeId object) { - output.writeString(object.toString()); - } - - @Override - public NodeId read(Kryo kryo, Input input, Class<NodeId> type) { - final String id = input.readString(); - return new NodeId(id); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/PortNumberSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/PortNumberSerializer.java deleted file mode 100644 index 74db644d..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/PortNumberSerializer.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onosproject.net.PortNumber; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Serializer for {@link PortNumber}. - */ -public final class PortNumberSerializer extends - Serializer<PortNumber> { - - /** - * Creates {@link PortNumber} serializer instance. - */ - public PortNumberSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, PortNumber object) { - output.writeBoolean(object.hasName()); - output.writeLong(object.toLong()); - if (object.hasName()) { - output.writeString(object.name()); - } - } - - @Override - public PortNumber read(Kryo kryo, Input input, Class<PortNumber> type) { - if (input.readBoolean()) { - return PortNumber.portNumber(input.readLong(), input.readString()); - } else { - return PortNumber.portNumber(input.readLong()); - } - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ProviderIdSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ProviderIdSerializer.java deleted file mode 100644 index 7f9b6ffc..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ProviderIdSerializer.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import org.onosproject.net.provider.ProviderId; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** - * Serializer for {@link ProviderId}. - */ -public class ProviderIdSerializer extends Serializer<ProviderId> { - - /** - * Creates {@link ProviderId} serializer instance. - */ - public ProviderIdSerializer() { - // non-null, immutable - super(false, true); - } - - @Override - public void write(Kryo kryo, Output output, ProviderId object) { - output.writeString(object.scheme()); - output.writeString(object.id()); - output.writeBoolean(object.isAncillary()); - } - - @Override - public ProviderId read(Kryo kryo, Input input, Class<ProviderId> type) { - String scheme = input.readString(); - String id = input.readString(); - boolean isAncillary = input.readBoolean(); - return new ProviderId(scheme, id, isAncillary); - } - -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/StoreSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/StoreSerializer.java deleted file mode 100644 index f0149fc5..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/StoreSerializer.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; - -// TODO: To be replaced with SerializationService from IOLoop activity -/** - * Service to serialize Objects into byte array. - */ -public interface StoreSerializer { - - /** - * Serializes the specified object into bytes. - * - * @param obj object to be serialized - * @return serialized bytes - */ - byte[] encode(final Object obj); - - /** - * Serializes the specified object into bytes. - * - * @param obj object to be serialized - * @param buffer to write serialized bytes - */ - void encode(final Object obj, ByteBuffer buffer); - - /** - * Serializes the specified object into bytes. - * - * @param obj object to be serialized - * @param stream to write serialized bytes - */ - void encode(final Object obj, final OutputStream stream); - - /** - * Deserializes the specified bytes into an object. - * - * @param bytes bytes to be deserialized - * @return deserialized object - * @param <T> decoded type - */ - <T> T decode(final byte[] bytes); - - /** - * Deserializes the specified bytes into an object. - * - * @param buffer bytes to be deserialized - * @return deserialized object - * @param <T> decoded type - */ - <T> T decode(final ByteBuffer buffer); - - /** - * Deserializes the specified bytes into an object. - * - * @param stream stream containing the bytes to be deserialized - * @return deserialized object - * @param <T> decoded type - */ - <T> T decode(final InputStream stream); -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/UriSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/UriSerializer.java deleted file mode 100644 index 1d146a55..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/UriSerializer.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -import java.net.URI; - -/** - * Serializer for {@link URI}. - */ -public class UriSerializer extends Serializer<URI> { - - /** - * Creates {@link URI} serializer instance. - */ - public UriSerializer() { - super(false); - } - - @Override - public void write(Kryo kryo, Output output, URI object) { - output.writeString(object.toString()); - } - - @Override - public URI read(Kryo kryo, Input input, Class<URI> type) { - return URI.create(input.readString()); - } -} diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/package-info.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/package-info.java deleted file mode 100644 index 9471b43e..00000000 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Various Kryo serializers for use in distributed stores. - */ -package org.onosproject.store.serializers; diff --git a/framework/src/onos/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java b/framework/src/onos/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java deleted file mode 100644 index 7df518e2..00000000 --- a/framework/src/onos/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.store.serializers; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.testing.EqualsTester; - -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.onlab.packet.VlanId; -import org.onlab.util.Bandwidth; -import org.onlab.util.Frequency; -import org.onosproject.cluster.NodeId; -import org.onosproject.cluster.RoleInfo; -import org.onosproject.core.DefaultApplicationId; -import org.onosproject.core.DefaultGroupId; -import org.onosproject.mastership.MastershipTerm; -import org.onosproject.net.Annotations; -import org.onosproject.net.ChannelSpacing; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.DefaultDevice; -import org.onosproject.net.DefaultLink; -import org.onosproject.net.DefaultPort; -import org.onosproject.net.Device; -import org.onosproject.net.DeviceId; -import org.onosproject.net.GridType; -import org.onosproject.net.HostLocation; -import org.onosproject.net.IndexedLambda; -import org.onosproject.net.Link; -import org.onosproject.net.Link.Type; -import org.onosproject.net.LinkKey; -import org.onosproject.net.OchPort; -import org.onosproject.net.OchSignal; -import org.onosproject.net.OduCltPort; -import org.onosproject.net.OmsPort; -import org.onosproject.net.PortNumber; -import org.onosproject.net.OduSignalType; -import org.onosproject.net.SparseAnnotations; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowId; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleBatchEntry; -import org.onosproject.net.intent.IntentId; -import org.onosproject.net.newresource.ResourcePath; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.net.resource.link.BandwidthResource; -import org.onosproject.net.resource.link.BandwidthResourceAllocation; -import org.onosproject.net.resource.link.DefaultLinkResourceAllocations; -import org.onosproject.net.resource.link.DefaultLinkResourceRequest; -import org.onosproject.net.resource.link.LambdaResource; -import org.onosproject.net.resource.link.LambdaResourceAllocation; -import org.onosproject.net.resource.link.LinkResourceRequest; -import org.onosproject.net.resource.ResourceAllocation; -import org.onosproject.net.intent.constraint.AnnotationConstraint; -import org.onosproject.net.intent.constraint.BandwidthConstraint; -import org.onosproject.net.intent.constraint.LambdaConstraint; -import org.onosproject.net.intent.constraint.LatencyConstraint; -import org.onosproject.net.intent.constraint.LinkTypeConstraint; -import org.onosproject.net.intent.constraint.ObstacleConstraint; -import org.onosproject.net.intent.constraint.WaypointConstraint; -import org.onlab.packet.ChassisId; -import org.onlab.packet.IpAddress; -import org.onlab.packet.Ip4Address; -import org.onlab.packet.Ip6Address; -import org.onlab.packet.IpPrefix; -import org.onlab.packet.Ip4Prefix; -import org.onlab.packet.Ip6Prefix; -import org.onlab.packet.MacAddress; -import org.onlab.util.KryoNamespace; - -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.time.Duration; - -import static java.util.Arrays.asList; -import static org.junit.Assert.*; -import static org.onosproject.net.DeviceId.deviceId; -import static org.onosproject.net.PortNumber.portNumber; - -public class KryoSerializerTest { - - private static final ProviderId PID = new ProviderId("of", "foo"); - private static final ProviderId PIDA = new ProviderId("of", "foo", true); - private static final DeviceId DID1 = deviceId("of:foo"); - private static final DeviceId DID2 = deviceId("of:bar"); - private static final PortNumber P1 = portNumber(1); - private static final PortNumber P2 = portNumber(2); - private static final ConnectPoint CP1 = new ConnectPoint(DID1, P1); - private static final ConnectPoint CP2 = new ConnectPoint(DID2, P2); - private static final String MFR = "whitebox"; - private static final String HW = "1.1.x"; - private static final String SW1 = "3.8.1"; - private static final String SW2 = "3.9.5"; - private static final String SN = "43311-12345"; - private static final ChassisId CID = new ChassisId(); - private static final Device DEV1 = new DefaultDevice(PID, DID1, Device.Type.SWITCH, MFR, HW, - SW1, SN, CID); - private static final SparseAnnotations A1 = DefaultAnnotations.builder() - .set("A1", "a1") - .set("B1", "b1") - .build(); - private static final SparseAnnotations A1_2 = DefaultAnnotations.builder() - .remove("A1") - .set("B3", "b3") - .build(); - private static final OchSignal OCH_SIGNAL1 = (OchSignal) org.onosproject.net.Lambda.ochSignal( - GridType.DWDM, ChannelSpacing.CHL_100GHZ, -8, 4); - private static final VlanId VLAN1 = VlanId.vlanId((short) 100); - - private KryoSerializer serializer; - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - } - - @Before - public void setUp() throws Exception { - serializer = new KryoSerializer() { - - @Override - protected void setupKryoPool() { - serializerPool = KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID) - .build(); - } - }; - } - - @After - public void tearDown() throws Exception { - } - - private <T> void testSerializedEquals(T original) { - ByteBuffer buffer = ByteBuffer.allocate(1 * 1024 * 1024); - serializer.encode(original, buffer); - buffer.flip(); - T copy = serializer.decode(buffer); - - T copy2 = serializer.decode(serializer.encode(original)); - - new EqualsTester() - .addEqualityGroup(original, copy, copy2) - .testEquals(); - } - - private <T> void testSerializable(T original) { - byte[] bs = serializer.encode(original); - T copy = serializer.decode(bs); - assertNotNull(copy); - } - - - @Test - public void testConnectPoint() { - testSerializedEquals(new ConnectPoint(DID1, P1)); - } - - @Test - public void testDefaultLink() { - testSerializedEquals(new DefaultLink(PID, CP1, CP2, Link.Type.DIRECT)); - testSerializedEquals(new DefaultLink(PID, CP1, CP2, Link.Type.DIRECT, A1)); - } - - @Test - public void testDefaultPort() { - testSerializedEquals(new DefaultPort(DEV1, P1, true)); - testSerializedEquals(new DefaultPort(DEV1, P1, true, A1_2)); - } - - @Test - public void testOmsPort() { - testSerializedEquals(new OmsPort(DEV1, P1, true, Frequency.ofGHz(190_100), Frequency.ofGHz(197_300), - Frequency.ofGHz(100))); - testSerializedEquals(new OmsPort(DEV1, P1, true, Frequency.ofGHz(190_100), Frequency.ofGHz(197_300), - Frequency.ofGHz(100), A1_2)); - } - - @Test - public void testOchPort() { - testSerializedEquals(new OchPort(DEV1, P1, true, OduSignalType.ODU0, false, OCH_SIGNAL1)); - testSerializedEquals(new OchPort(DEV1, P1, true, OduSignalType.ODU0, false, OCH_SIGNAL1, A1_2)); - } - - @Test - public void testOduCltPort() { - testSerializedEquals(new OduCltPort(DEV1, P1, true, OduCltPort.SignalType.CLT_10GBE)); - testSerializedEquals(new OduCltPort(DEV1, P1, true, OduCltPort.SignalType.CLT_10GBE, A1_2)); - } - - @Test - public void testDeviceId() { - testSerializedEquals(DID1); - } - - @Test - public void testImmutableMap() { - testSerializedEquals(ImmutableMap.of(DID1, DEV1, DID2, DEV1)); - testSerializedEquals(ImmutableMap.of(DID1, DEV1)); - testSerializedEquals(ImmutableMap.of()); - } - - @Test - public void testImmutableSet() { - testSerializedEquals(ImmutableSet.of(DID1, DID2)); - testSerializedEquals(ImmutableSet.of(DID1)); - testSerializedEquals(ImmutableSet.of()); - } - - @Test - public void testImmutableList() { - testSerializedEquals(ImmutableList.of(DID1, DID2)); - testSerializedEquals(ImmutableList.of(DID1)); - testSerializedEquals(ImmutableList.of()); - } - - @Test - public void testFlowRuleBatchEntry() { - final FlowRule rule1 = - DefaultFlowRule.builder() - .forDevice(DID1) - .withSelector(DefaultTrafficSelector.emptySelector()) - .withTreatment(DefaultTrafficTreatment.emptyTreatment()) - .withPriority(0) - .fromApp(new DefaultApplicationId(1, "1")) - .makeTemporary(1) - .build(); - - final FlowRuleBatchEntry entry1 = - new FlowRuleBatchEntry(FlowRuleBatchEntry.FlowRuleOperation.ADD, rule1); - final FlowRuleBatchEntry entry2 = - new FlowRuleBatchEntry(FlowRuleBatchEntry.FlowRuleOperation.ADD, rule1, 100L); - - testSerializedEquals(entry1); - testSerializedEquals(entry2); - } - - @Test - public void testIpPrefix() { - testSerializedEquals(IpPrefix.valueOf("192.168.0.1/24")); - } - - @Test - public void testIp4Prefix() { - testSerializedEquals(Ip4Prefix.valueOf("192.168.0.1/24")); - } - - @Test - public void testIp6Prefix() { - testSerializedEquals(Ip6Prefix.valueOf("1111:2222::/120")); - } - - @Test - public void testIpAddress() { - testSerializedEquals(IpAddress.valueOf("192.168.0.1")); - } - - @Test - public void testIp4Address() { - testSerializedEquals(Ip4Address.valueOf("192.168.0.1")); - } - - @Test - public void testIp6Address() { - testSerializedEquals(Ip6Address.valueOf("1111:2222::")); - } - - @Test - public void testMacAddress() { - testSerializedEquals(MacAddress.valueOf("12:34:56:78:90:ab")); - } - - @Test - public void testLinkKey() { - testSerializedEquals(LinkKey.linkKey(CP1, CP2)); - } - - @Test - public void testNodeId() { - testSerializedEquals(new NodeId("SomeNodeIdentifier")); - } - - @Test - public void testPortNumber() { - testSerializedEquals(P1); - } - - @Test - public void testProviderId() { - testSerializedEquals(PID); - testSerializedEquals(PIDA); - } - - @Test - public void testMastershipTerm() { - testSerializedEquals(MastershipTerm.of(new NodeId("foo"), 2)); - testSerializedEquals(MastershipTerm.of(null, 0)); - } - - @Test - public void testHostLocation() { - testSerializedEquals(new HostLocation(CP1, 1234L)); - } - - @Test - public void testFlowId() { - testSerializedEquals(FlowId.valueOf(0x12345678L)); - } - - @Test - public void testRoleInfo() { - testSerializedEquals(new RoleInfo(new NodeId("master"), - asList(new NodeId("stby1"), new NodeId("stby2")))); - } - - @Test - public void testIndexedLambda() { - testSerializedEquals(org.onosproject.net.Lambda.indexedLambda(10L)); - } - - @Test - public void testOchSignal() { - testSerializedEquals(org.onosproject.net.Lambda.ochSignal( - GridType.DWDM, ChannelSpacing.CHL_100GHZ, 1, 1 - )); - } - - @Test - public void testDefaultLinkResourceRequest() { - testSerializable(DefaultLinkResourceRequest.builder(IntentId.valueOf(2501), ImmutableList.of()) - .addLambdaRequest() - .addBandwidthRequest(32.195) - .build() - ); - } - - @Test - public void testDefaultLinkResourceAllocations() { - LinkResourceRequest request = DefaultLinkResourceRequest - .builder(IntentId.valueOf(2501), ImmutableList.of()) - .addLambdaRequest() - .addBandwidthRequest(32.195) - .build(); - Map<Link, Set<ResourceAllocation>> allocations = new HashMap<>(); - allocations.put(new DefaultLink(PID, CP1, CP2, Type.DIRECT), - ImmutableSet.of(new BandwidthResourceAllocation(new BandwidthResource(Bandwidth.bps(10.0))), - new LambdaResourceAllocation(LambdaResource.valueOf(1)))); - testSerializable(new DefaultLinkResourceAllocations(request, allocations)); - } - - @Test - public void testResourcePath() { - testSerializedEquals(ResourcePath.discrete(DID1, P1, VLAN1)); - } - - @Test - public void testResourceAllocation() { - testSerializedEquals(new org.onosproject.net.newresource.ResourceAllocation( - ResourcePath.discrete(DID1, P1, VLAN1), - IntentId.valueOf(30))); - } - - @Test - public void testFrequency() { - testSerializedEquals(Frequency.ofGHz(100)); - } - - @Test - public void testBandwidth() { - testSerializedEquals(Bandwidth.mbps(1000.0)); - } - - @Test - public void testLambdaConstraint() { - testSerializable(new LambdaConstraint(new IndexedLambda(1))); - } - - @Test - public void testBandwidthConstraint() { - testSerializable(new BandwidthConstraint(Bandwidth.bps(1000.0))); - } - - @Test - public void testLinkTypeConstraint() { - testSerializable(new LinkTypeConstraint(true, Link.Type.DIRECT)); - } - - @Test - public void testLatencyConstraint() { - testSerializable(new LatencyConstraint(Duration.ofSeconds(10))); - } - - @Test - public void testWaypointConstraint() { - testSerializable(new WaypointConstraint(deviceId("of:1"), deviceId("of:2"))); - } - - @Test - public void testObstacleConstraint() { - testSerializable(new ObstacleConstraint(deviceId("of:1"), deviceId("of:2"))); - } - - @Test - public void testArraysAsList() { - testSerializedEquals(Arrays.asList(1, 2, 3)); - } - - @Test - public void testAnnotationConstraint() { - testSerializable(new AnnotationConstraint("distance", 100.0)); - } - - @Test - public void testDefaultGroupId() { - testSerializedEquals(new DefaultGroupId(99)); - } - - @Test - public void testEmptySet() { - testSerializedEquals(Collections.emptySet()); - } - - @Test - public void testAnnotations() { - // Annotations does not have equals defined, manually test equality - final byte[] a1Bytes = serializer.encode(A1); - SparseAnnotations copiedA1 = serializer.decode(a1Bytes); - assertAnnotationsEquals(copiedA1, A1); - - final byte[] a12Bytes = serializer.encode(A1_2); - SparseAnnotations copiedA12 = serializer.decode(a12Bytes); - assertAnnotationsEquals(copiedA12, A1_2); - } - - // code clone - protected static void assertAnnotationsEquals(Annotations actual, SparseAnnotations... annotations) { - SparseAnnotations expected = DefaultAnnotations.builder().build(); - for (SparseAnnotations a : annotations) { - expected = DefaultAnnotations.union(expected, a); - } - assertEquals(expected.keys(), actual.keys()); - for (String key : expected.keys()) { - assertEquals(expected.value(key), actual.value(key)); - } - } - -} |