[ONOS-5919] (vCore) separate Intent store
Change-Id: I3b5b67d7286dafdf11bf3d8d4acafb59a3034e22
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkIntentStore.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkIntentStore.java
new file mode 100644
index 0000000..1c0d3cc
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkIntentStore.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2017-present 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.incubator.net.virtual;
+
+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.IntentStoreDelegate;
+import org.onosproject.net.intent.Key;
+
+import java.util.List;
+
+public interface VirtualNetworkIntentStore
+ extends VirtualStore<IntentEvent, IntentStoreDelegate> {
+
+ /**
+ * Returns the number of intents in the store.
+ *
+ * @param networkId the virtual network identifier
+ * @return the number of intents in the store
+ */
+ long getIntentCount(NetworkId networkId);
+
+ /**
+ * Returns an iterable of all intents in the store.
+ *
+ * @param networkId the virtual network identifier
+ * @return iterable of all intents
+ */
+ Iterable<Intent> getIntents(NetworkId networkId);
+
+ /**
+ * Returns an iterable of all intent data objects in the store.
+ *
+ * @param networkId the virtual network identifier
+ * @param localOnly should only intents for which this instance is master
+ * be returned
+ * @param olderThan specified duration in milliseconds (0 for "now")
+ * @return iterable of all intent data objects
+ */
+ Iterable<IntentData> getIntentData(NetworkId networkId, boolean localOnly,
+ long olderThan);
+
+ /**
+ * Returns the state of the specified intent.
+ *
+ * @param networkId the virtual network identifier
+ * @param intentKey intent identification
+ * @return current intent state
+ */
+ IntentState getIntentState(NetworkId networkId, Key intentKey);
+
+ /**
+ * Returns the list of the installable events associated with the specified
+ * original intent.
+ *
+ * @param networkId the virtual network identifier
+ * @param intentKey original intent identifier
+ * @return compiled installable intents, or null if no installables exist
+ */
+ List<Intent> getInstallableIntents(NetworkId networkId, Key intentKey);
+
+ /**
+ * Writes an IntentData object to the store.
+ *
+ * @param networkId the virtual network identifier
+ * @param newData new intent data to write
+ */
+ void write(NetworkId networkId, IntentData newData);
+
+ /**
+ * Writes a batch of IntentData objects to the store. A batch has no
+ * semantics, this is simply a convenience API.
+ *
+ * @param networkId the virtual network identifier
+ * @param updates collection of intent data objects to write
+ */
+ void batchWrite(NetworkId networkId, Iterable<IntentData> updates);
+
+ /**
+ * Returns the intent with the specified identifier.
+ *
+ * @param networkId the virtual network identifier
+ * @param key key
+ * @return intent or null if not found
+ */
+ Intent getIntent(NetworkId networkId, Key key);
+
+ /**
+ * Returns the intent data object associated with the specified key.
+ *
+ * @param networkId the virtual network identifier
+ * @param key key to look up
+ * @return intent data object
+ */
+ IntentData getIntentData(NetworkId networkId, Key key);
+
+ /**
+ * Adds a new operation, which should be persisted and delegated.
+ *
+ * @param networkId the virtual network identifier
+ * @param intent operation
+ */
+ void addPending(NetworkId networkId, IntentData intent);
+
+ /**
+ * Checks to see whether the calling instance is the master for processing
+ * this intent, or more specifically, the key contained in this intent.
+ *
+ * @param networkId the virtual network identifier
+ * @param intentKey intentKey to check
+ * @return true if master; false, otherwise
+ */
+ //TODO better name
+ boolean isMaster(NetworkId networkId, Key intentKey);
+
+ /**
+ * Returns the intent requests pending processing.
+ *
+ * @param networkId the virtual network identifier
+ * @return pending intents
+ */
+ Iterable<Intent> getPending(NetworkId networkId);
+
+ /**
+ * Returns the intent data objects that are pending processing.
+ *
+ * @param networkId the virtual network identifier
+ * @return pending intent data objects
+ */
+ Iterable<IntentData> getPendingData(NetworkId networkId);
+
+ /**
+ * Returns the intent data object that are pending processing for a specfied
+ * key.
+ *
+ * @param networkId the virtual network identifier
+ * @param intentKey key to look up
+ * @return pending intent data object
+ */
+ IntentData getPendingData(NetworkId networkId, Key intentKey);
+
+ /**
+ * Returns the intent data objects that are pending processing for longer
+ * than the specified duration.
+ *
+ * @param networkId the virtual network identifier
+ * @param localOnly should only intents for which this instance is master
+ * be returned
+ * @param olderThan specified duration in milliseconds (0 for "now")
+ * @return pending intent data objects
+ */
+ Iterable<IntentData> getPendingData(NetworkId networkId, boolean localOnly, long olderThan);
+
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStore.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStore.java
index 516d901..0e6b2a9 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStore.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkStore.java
@@ -26,9 +26,6 @@
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.net.intent.Intent;
-import org.onosproject.net.intent.IntentData;
-import org.onosproject.net.intent.IntentState;
-import org.onosproject.net.intent.Key;
import org.onosproject.store.Store;
import java.util.Set;
@@ -238,22 +235,6 @@
Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId);
/**
- * Add or update the intent to the store.
- *
- * @param intent virtual intent
- * @param state intent state
- */
- void addOrUpdateIntent(Intent intent, IntentState state);
-
- /**
- * Remove the virtual intent from the store.
- *
- * @param intentKey intent key
- * @return intent data
- */
- IntentData removeIntent(Key intentKey);
-
- /**
* Adds the intent to tunnel identifier mapping to the store.
*
* @param intent intent
@@ -276,34 +257,4 @@
* @param tunnelId tunnel identifier
*/
void removeTunnelId(Intent intent, TunnelId tunnelId);
-
- /**
- * Return all intents.
- *
- * @return set of intents
- */
- Set<Intent> getIntents();
-
- /**
- * Return the intent for the specified intent key.
- *
- * @param key intent key
- * @return intent
- */
- Intent getIntent(Key key);
-
- /**
- * Return the set of intent data.
- *
- * @return set of intent data
- */
- Set<IntentData> getIntentData();
-
- /**
- * Return the intent data matching the intent key.
- *
- * @param key intent key
- * @return intent data
- */
- IntentData getIntentData(Key key);
}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkIntentManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkIntentManager.java
index 41cd952..48ad983 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkIntentManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkIntentManager.java
@@ -19,6 +19,7 @@
import com.google.common.collect.Iterators;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.incubator.net.virtual.VirtualNetworkIntent;
+import org.onosproject.incubator.net.virtual.VirtualNetworkIntentStore;
import org.onosproject.incubator.net.virtual.VirtualNetworkService;
import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
import org.onosproject.incubator.net.virtual.VirtualPort;
@@ -64,6 +65,7 @@
protected IntentService intentService;
protected VirtualNetworkStore store;
+ protected VirtualNetworkIntentStore intentStore;
protected WorkPartitionService partitionService;
/**
@@ -78,6 +80,7 @@
super(virtualNetworkManager, networkId, IntentEvent.class);
this.store = serviceDirectory.get(VirtualNetworkStore.class);
+ this.intentStore = serviceDirectory.get(VirtualNetworkIntentStore.class);
this.intentService = serviceDirectory.get(IntentService.class);
this.partitionService = serviceDirectory.get(WorkPartitionService.class);
}
@@ -117,7 +120,7 @@
private boolean validateConnectPoint(ConnectPoint connectPoint) {
checkNotNull(connectPoint, CP_NULL);
Port port = getPort(connectPoint.deviceId(), connectPoint.port());
- return port == null ? false : true;
+ return port != null;
}
/**
@@ -179,12 +182,12 @@
@Override
public Intent getIntent(Key key) {
checkNotNull(key, KEY_NULL);
- return store.getIntent(key);
+ return intentStore.getIntent(networkId, key);
}
@Override
public Iterable<Intent> getIntents() {
- return store.getIntents();
+ return intentStore.getIntents(networkId);
}
@Override
@@ -194,7 +197,7 @@
@Override
public Iterable<IntentData> getIntentData() {
- return store.getIntentData();
+ return intentStore.getIntentData(networkId, false, 0);
}
@Override
@@ -205,7 +208,7 @@
@Override
public IntentState getIntentState(Key intentKey) {
checkNotNull(intentKey, KEY_NULL);
- return Optional.ofNullable(store.getIntentData(intentKey))
+ return Optional.ofNullable(intentStore.getIntentData(networkId, intentKey))
.map(IntentData::state)
.orElse(null);
}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java
index 96979f5..d57801b 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java
@@ -40,7 +40,6 @@
import org.onosproject.incubator.net.virtual.VirtualNetwork;
import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
-import org.onosproject.incubator.net.virtual.VirtualNetworkIntent;
import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
import org.onosproject.incubator.net.virtual.VirtualNetworkService;
import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
@@ -63,10 +62,7 @@
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.group.GroupService;
import org.onosproject.net.host.HostService;
-import org.onosproject.net.intent.IntentEvent;
-import org.onosproject.net.intent.IntentListener;
import org.onosproject.net.intent.IntentService;
-import org.onosproject.net.intent.IntentState;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.packet.PacketService;
import org.onosproject.net.provider.AbstractListenerProviderRegistry;
@@ -112,9 +108,6 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
- private final InternalVirtualIntentListener intentListener =
- new InternalVirtualIntentListener();
-
private VirtualNetworkStoreDelegate delegate = this::post;
private ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
@@ -147,7 +140,6 @@
eventDispatcher.addSink(VirtualEvent.class,
VirtualListenerRegistryManager.getInstance());
store.setDelegate(delegate);
- intentService.addListener(intentListener);
appId = coreService.registerApplication(VIRTUAL_NETWORK_APP_ID_STRING);
log.info("Started");
}
@@ -157,7 +149,6 @@
store.unsetDelegate(delegate);
eventDispatcher.removeSink(VirtualNetworkEvent.class);
eventDispatcher.removeSink(VirtualEvent.class);
- intentService.removeListener(intentListener);
log.info("Stopped");
}
@@ -517,64 +508,12 @@
}
}
- /**
- * Internal intent event listener.
- */
- private class InternalVirtualIntentListener implements IntentListener {
-
- @Override
- public void event(IntentEvent event) {
-
- // Ignore intent events that are not relevant.
- if (!isRelevant(event)) {
- return;
- }
-
- VirtualNetworkIntent intent = (VirtualNetworkIntent) event.subject();
-
- switch (event.type()) {
- case INSTALL_REQ:
- store.addOrUpdateIntent(intent, IntentState.INSTALL_REQ);
- break;
- case INSTALLED:
- store.addOrUpdateIntent(intent, IntentState.INSTALLED);
- break;
- case WITHDRAW_REQ:
- store.addOrUpdateIntent(intent, IntentState.WITHDRAW_REQ);
- break;
- case WITHDRAWN:
- store.addOrUpdateIntent(intent, IntentState.WITHDRAWN);
- break;
- case FAILED:
- store.addOrUpdateIntent(intent, IntentState.FAILED);
- break;
- case CORRUPT:
- store.addOrUpdateIntent(intent, IntentState.CORRUPT);
- break;
- case PURGED:
- store.removeIntent(intent.key());
- default:
- break;
- }
- }
-
- @Override
- public boolean isRelevant(IntentEvent event) {
- if (event.subject() instanceof VirtualNetworkIntent) {
- return true;
- }
- return false;
- }
- }
-
-
@Override
protected VirtualNetworkProviderService
createProviderService(VirtualNetworkProvider provider) {
return new InternalVirtualNetworkProviderService(provider);
}
-
/**
* Service issued to registered virtual network providers so that they
* can interact with the core.
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkIntentManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkIntentManagerTest.java
index 4b7cf84..3b59e9a 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkIntentManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkIntentManagerTest.java
@@ -37,8 +37,10 @@
import org.onosproject.incubator.net.virtual.VirtualLink;
import org.onosproject.incubator.net.virtual.VirtualNetwork;
import org.onosproject.incubator.net.virtual.VirtualNetworkIntent;
+import org.onosproject.incubator.net.virtual.VirtualNetworkIntentStore;
import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore;
+import org.onosproject.incubator.store.virtual.impl.SimpleVirtualIntentStore;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.EncapsulationType;
@@ -100,6 +102,7 @@
private VirtualNetworkManager manager;
private static DistributedVirtualNetworkStore virtualNetworkManagerStore;
+ private VirtualNetworkIntentStore intentStore;
private CoreService coreService;
private TestableIntentService intentService = new FakeIntentManager();
private VirtualNetworkIntentManager vnetIntentService;
@@ -117,6 +120,7 @@
@Before
public void setUp() throws Exception {
virtualNetworkManagerStore = new DistributedVirtualNetworkStore();
+ intentStore = new SimpleVirtualIntentStore();
coreService = new VirtualNetworkIntentManagerTest.TestCoreService();
@@ -215,7 +219,7 @@
vnetIntentService = new VirtualNetworkIntentManager(manager, virtualNetwork.id());
vnetIntentService.intentService = intentService;
- vnetIntentService.store = virtualNetworkManagerStore;
+ vnetIntentService.intentStore = intentStore;
vnetIntentService.partitionService = workPartitionService;
return virtualNetwork;
}
@@ -347,12 +351,12 @@
switch (event.type()) {
case INSTALLED:
// Release one permit on the created semaphore since the Intent event was received.
- virtualNetworkManagerStore.addOrUpdateIntent(event.subject(), IntentState.INSTALLED);
+// virtualNetworkManagerStore.addOrUpdateIntent(event.subject(), IntentState.INSTALLED);
created.release();
break;
case WITHDRAWN:
// Release one permit on the removed semaphore since the Intent event was received.
- virtualNetworkManagerStore.addOrUpdateIntent(event.subject(), IntentState.WITHDRAWN);
+// virtualNetworkManagerStore.addOrUpdateIntent(event.subject(), IntentState.WITHDRAWN);
withdrawn.release();
break;
case PURGED:
@@ -396,4 +400,15 @@
super(APP_ID, Collections.singletonList(new IntentTestsMocks.MockFlowRule(100)), Collections.emptyList());
}
}
+
+// private void addOrUpdateIntent(Intent intent, IntentState state) {
+// checkNotNull(intent, "Intent cannot be null");
+// IntentData intentData = intentStore.(intent.key());
+// if (intentData == null) {
+// intentData = new IntentData(intent, state, new WallClockTimestamp(System.currentTimeMillis()));
+// } else {
+// intentData = new IntentData(intent, state, intentData.version());
+// }
+// intentKeyIntentDataMap.put(intent.key(), intentData);
+// }
}
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManagerTest.java
index 765b4cb..9d4086e 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManagerTest.java
@@ -71,7 +71,6 @@
import org.onosproject.net.host.HostService;
import org.onosproject.net.intent.FakeIntentManager;
import org.onosproject.net.intent.IntentService;
-import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.MockIdGenerator;
import org.onosproject.net.intent.TestableIntentService;
@@ -684,57 +683,6 @@
assertTrue("The virtual network set should be empty.", virtualNetworks.isEmpty());
}
-
- /**
- * Tests the addOrUpdateIntent() method in the store with a null intent.
- */
- @Test(expected = NullPointerException.class)
- public void testAddOrUpdateNullIntent() {
- manager.store.addOrUpdateIntent(null, null);
- }
-
- /**
- * Tests the removeIntent() method in the store with a null intent key.
- */
- @Test(expected = NullPointerException.class)
- public void testRemoveNullIntentKey() {
- manager.store.removeIntent(null);
- }
-
- /**
- * Tests the addOrUpdateIntent(), getIntents(), getIntent(), removeIntent() methods with the store.
- */
- @Test
- public void testAddOrUpdateIntent() {
- manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
- VirtualNetwork virtualNetwork =
- manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
- ConnectPoint cp1 = new ConnectPoint(DID1, P1);
- ConnectPoint cp2 = new ConnectPoint(DID2, P1);
-
- VirtualNetworkIntent virtualIntent = VirtualNetworkIntent.builder()
- .networkId(virtualNetwork.id())
- .key(Key.of("Test", APP_ID))
- .appId(APP_ID)
- .ingressPoint(cp1)
- .egressPoint(cp2)
- .build();
-
- // Add the intent to the store.
- manager.store.addOrUpdateIntent(virtualIntent, IntentState.INSTALL_REQ);
- assertEquals("The intent size should match.", 1,
- manager.store.getIntents().size());
- assertNotNull("The intent should not be null.",
- manager.store.getIntent(virtualIntent.key()));
-
- // remove the intent from the store.
- manager.store.removeIntent(virtualIntent.key());
- assertTrue("The intents should be empty.",
- manager.store.getIntents().isEmpty());
- assertNull("The intent should be null.",
- manager.store.getIntent(virtualIntent.key()));
- }
-
/**
* Tests the addTunnelId() method in the store with a null intent.
*/
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
index 6447916..c938814 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
@@ -55,8 +55,6 @@
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.net.intent.Intent;
-import org.onosproject.net.intent.IntentData;
-import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Key;
import org.onosproject.store.AbstractStore;
import org.onosproject.store.serializers.KryoNamespaces;
@@ -167,10 +165,6 @@
private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap;
private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap;
- // Track intent key to intent data
- private ConsistentMap<Key, IntentData> intentKeyIntentDataConsistentMap;
- private Map<Key, IntentData> intentKeyIntentDataMap;
-
// Track intent ID to TunnelIds
private ConsistentMap<Key, Set<TunnelId>> intentKeyTunnelIdSetConsistentMap;
private Map<Key, Set<TunnelId>> intentKeyTunnelIdSetMap;
@@ -192,7 +186,6 @@
.register(DefaultVirtualPort.class)
.register(Device.class)
.register(TunnelId.class)
- .register(IntentData.class)
.register(VirtualNetworkIntent.class)
.register(WallClockTimestamp.class)
.nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
@@ -278,13 +271,6 @@
.build();
intentKeyTunnelIdSetMap = intentKeyTunnelIdSetConsistentMap.asJavaMap();
- intentKeyIntentDataConsistentMap = storageService.<Key, IntentData>consistentMapBuilder()
- .withSerializer(SERIALIZER)
- .withName("onos-intentKey-intentData")
- .withRelaxedReadConsistency()
- .build();
- intentKeyIntentDataMap = intentKeyIntentDataConsistentMap.asJavaMap();
-
log.info("Started");
}
@@ -798,24 +784,6 @@
}
@Override
- public synchronized void addOrUpdateIntent(Intent intent, IntentState state) {
- checkNotNull(intent, "Intent cannot be null");
- IntentData intentData = removeIntent(intent.key());
- if (intentData == null) {
- intentData = new IntentData(intent, state, new WallClockTimestamp(System.currentTimeMillis()));
- } else {
- intentData = new IntentData(intent, state, intentData.version());
- }
- intentKeyIntentDataMap.put(intent.key(), intentData);
- }
-
- @Override
- public IntentData removeIntent(Key intentKey) {
- checkNotNull(intentKey, "Intent key cannot be null");
- return intentKeyIntentDataMap.remove(intentKey);
- }
-
- @Override
public void addTunnelId(Intent intent, TunnelId tunnelId) {
// Add the tunnelId to the intent key set map
Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.remove(intent.key());
@@ -852,30 +820,6 @@
}
}
- @Override
- public Set<Intent> getIntents() {
- Set<Intent> intents = new HashSet<>();
- intentKeyIntentDataMap.values().forEach(intentData -> intents.add(intentData.intent()));
- return ImmutableSet.copyOf(intents);
- }
-
- @Override
- public Intent getIntent(Key key) {
- IntentData intentData = intentKeyIntentDataMap.get(key);
- return intentData == null ? null : intentData.intent();
- }
-
- @Override
- public Set<IntentData> getIntentData() {
- return ImmutableSet.copyOf(intentKeyIntentDataMap.values());
- }
-
- @Override
- public IntentData getIntentData(Key key) {
- IntentData intentData = intentKeyIntentDataMap.get(key);
- return intentData == null ? null : new IntentData(intentData);
- }
-
/**
* Listener class to map listener set events to the virtual network events.
*/
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/SimpleVirtualIntentStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/SimpleVirtualIntentStore.java
new file mode 100644
index 0000000..7f739b1
--- /dev/null
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/SimpleVirtualIntentStore.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2017-present 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.incubator.store.virtual.impl;
+
+import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.Lists;
+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.Service;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkIntentStore;
+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.IntentStoreDelegate;
+import org.onosproject.net.intent.Key;
+import org.onosproject.store.Timestamp;
+import org.slf4j.Logger;
+
+import java.util.List;
+import java.util.Map;
+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.intent.IntentState.PURGE_REQ;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Simple single-instance implementation of the intent store for virtual networks.
+ */
+
+@Component(immediate = true)
+@Service
+public class SimpleVirtualIntentStore
+ extends AbstractVirtualStore<IntentEvent, IntentStoreDelegate>
+ implements VirtualNetworkIntentStore {
+
+ private final Logger log = getLogger(getClass());
+
+ private final Map<NetworkId, Map<Key, IntentData>> currentByNetwork =
+ Maps.newConcurrentMap();
+ private final Map<NetworkId, Map<Key, IntentData>> pendingByNetwork =
+ Maps.newConcurrentMap();
+
+ @Activate
+ public void activate() {
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ log.info("Stopped");
+ }
+
+
+ @Override
+ public long getIntentCount(NetworkId networkId) {
+ return getCurrentMap(networkId).size();
+ }
+
+ @Override
+ public Iterable<Intent> getIntents(NetworkId networkId) {
+ return getCurrentMap(networkId).values().stream()
+ .map(IntentData::intent)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Iterable<IntentData> getIntentData(NetworkId networkId,
+ boolean localOnly, long olderThan) {
+ if (localOnly || olderThan > 0) {
+ long older = System.nanoTime() - olderThan * 1_000_000; //convert ms to ns
+ final SystemClockTimestamp time = new SystemClockTimestamp(older);
+ return getCurrentMap(networkId).values().stream()
+ .filter(data -> data.version().isOlderThan(time) &&
+ (!localOnly || isMaster(networkId, data.key())))
+ .collect(Collectors.toList());
+ }
+ return Lists.newArrayList(getCurrentMap(networkId).values());
+ }
+
+ @Override
+ public IntentState getIntentState(NetworkId networkId, Key intentKey) {
+ IntentData data = getCurrentMap(networkId).get(intentKey);
+ return (data != null) ? data.state() : null;
+ }
+
+ @Override
+ public List<Intent> getInstallableIntents(NetworkId networkId, Key intentKey) {
+ IntentData data = getCurrentMap(networkId).get(intentKey);
+ if (data != null) {
+ return data.installables();
+ }
+ return null;
+ }
+
+ @Override
+ public void write(NetworkId networkId, IntentData newData) {
+ checkNotNull(newData);
+
+ synchronized (this) {
+ // TODO this could be refactored/cleaned up
+ IntentData currentData = getCurrentMap(networkId).get(newData.key());
+ IntentData pendingData = getPendingMap(networkId).get(newData.key());
+
+ if (IntentData.isUpdateAcceptable(currentData, newData)) {
+ if (pendingData != null) {
+ if (pendingData.state() == PURGE_REQ) {
+ getCurrentMap(networkId).remove(newData.key(), newData);
+ } else {
+ getCurrentMap(networkId).put(newData.key(), new IntentData(newData));
+ }
+
+ if (pendingData.version().compareTo(newData.version()) <= 0) {
+ // pendingData version is less than or equal to newData's
+ // Note: a new update for this key could be pending (it's version will be greater)
+ getPendingMap(networkId).remove(newData.key());
+ }
+ }
+ IntentEvent.getEvent(newData).ifPresent(e -> notifyDelegate(networkId, e));
+ }
+ }
+ }
+
+ @Override
+ public void batchWrite(NetworkId networkId, Iterable<IntentData> updates) {
+ for (IntentData data : updates) {
+ write(networkId, data);
+ }
+ }
+
+ @Override
+ public Intent getIntent(NetworkId networkId, Key key) {
+ IntentData data = getCurrentMap(networkId).get(key);
+ return (data != null) ? data.intent() : null;
+ }
+
+ @Override
+ public IntentData getIntentData(NetworkId networkId, Key key) {
+ IntentData currentData = getCurrentMap(networkId).get(key);
+ if (currentData == null) {
+ return null;
+ }
+ return new IntentData(currentData);
+ }
+
+ @Override
+ public void addPending(NetworkId networkId, IntentData data) {
+ if (data.version() == null) { // recompiled intents will already have a version
+ data = new IntentData(data.intent(), data.state(), new SystemClockTimestamp());
+ }
+ synchronized (this) {
+ IntentData existingData = getPendingMap(networkId).get(data.key());
+ if (existingData == null ||
+ // existing version is strictly less than data's version
+ // Note: if they are equal, we already have the update
+ // TODO maybe we should still make this <= to be safe?
+ existingData.version().compareTo(data.version()) < 0) {
+ getPendingMap(networkId).put(data.key(), data);
+
+ checkNotNull(delegateMap.get(networkId), "Store delegate is not set")
+ .process(new IntentData(data));
+ IntentEvent.getEvent(data).ifPresent(e -> notifyDelegate(networkId, e));
+ } else {
+ log.debug("IntentData {} is older than existing: {}",
+ data, existingData);
+ }
+ //TODO consider also checking the current map at this point
+ }
+ }
+
+ @Override
+ public boolean isMaster(NetworkId networkId, Key intentKey) {
+ return true;
+ }
+
+ @Override
+ public Iterable<Intent> getPending(NetworkId networkId) {
+ return getPendingMap(networkId).values().stream()
+ .map(IntentData::intent)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Iterable<IntentData> getPendingData(NetworkId networkId) {
+ return Lists.newArrayList(getPendingMap(networkId).values());
+ }
+
+ @Override
+ public IntentData getPendingData(NetworkId networkId, Key intentKey) {
+ return getPendingMap(networkId).get(intentKey);
+ }
+
+ @Override
+ public Iterable<IntentData> getPendingData(NetworkId networkId,
+ boolean localOnly, long olderThan) {
+ long older = System.nanoTime() - olderThan * 1_000_000; //convert ms to ns
+ final SystemClockTimestamp time = new SystemClockTimestamp(older);
+ return getPendingMap(networkId).values().stream()
+ .filter(data -> data.version().isOlderThan(time) &&
+ (!localOnly || isMaster(networkId, data.key())))
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Returns the current intent map for a specific virtual network.
+ *
+ * @param networkId a virtual network identifier
+ * @return the current map for the requested virtual network
+ */
+ private Map<Key, IntentData> getCurrentMap(NetworkId networkId) {
+ currentByNetwork.computeIfAbsent(networkId,
+ n -> Maps.newConcurrentMap());
+ return currentByNetwork.get(networkId);
+ }
+
+ /**
+ * Returns the pending intent map for a specific virtual network.
+ *
+ * @param networkId a virtual network identifier
+ * @return the pending intent map for the requested virtual network
+ */
+ private Map<Key, IntentData> getPendingMap(NetworkId networkId) {
+ pendingByNetwork.computeIfAbsent(networkId,
+ n -> Maps.newConcurrentMap());
+ return pendingByNetwork.get(networkId);
+ }
+
+ public class SystemClockTimestamp implements Timestamp {
+
+ private final long nanoTimestamp;
+
+ public SystemClockTimestamp() {
+ nanoTimestamp = System.nanoTime();
+ }
+
+ public SystemClockTimestamp(long timestamp) {
+ nanoTimestamp = timestamp;
+ }
+
+ @Override
+ public int compareTo(Timestamp o) {
+ checkArgument(o instanceof SystemClockTimestamp,
+ "Must be SystemClockTimestamp", o);
+ SystemClockTimestamp that = (SystemClockTimestamp) o;
+
+ return ComparisonChain.start()
+ .compare(this.nanoTimestamp, that.nanoTimestamp)
+ .result();
+ }
+ }
+}