aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleIntentStore.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleIntentStore.java')
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleIntentStore.java212
1 files changed, 212 insertions, 0 deletions
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleIntentStore.java b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleIntentStore.java
new file mode 100644
index 00000000..9f959663
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleIntentStore.java
@@ -0,0 +1,212 @@
+/*
+ * 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.trivial;
+
+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.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.store.AbstractStore;
+import org.slf4j.Logger;
+
+import java.util.List;
+import java.util.Map;
+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;
+
+/**
+ * Simple single-instance implementation of the intent store.
+ */
+@Component(immediate = true)
+@Service
+public class SimpleIntentStore
+ extends AbstractStore<IntentEvent, IntentStoreDelegate>
+ implements IntentStore {
+
+ private final Logger log = getLogger(getClass());
+
+ private final Map<Key, IntentData> current = Maps.newConcurrentMap();
+ private final Map<Key, IntentData> pending = Maps.newConcurrentMap();
+
+ @Activate
+ public void activate() {
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ log.info("Stopped");
+ }
+
+ @Override
+ public long getIntentCount() {
+ return current.size();
+ }
+
+ @Override
+ public Iterable<Intent> getIntents() {
+ return current.values().stream()
+ .map(IntentData::intent)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Iterable<IntentData> getIntentData(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 current.values().stream()
+ .filter(data -> data.version().isOlderThan(time) &&
+ (!localOnly || isMaster(data.key())))
+ .collect(Collectors.toList());
+ }
+ return Lists.newArrayList(current.values());
+ }
+
+ @Override
+ public IntentState getIntentState(Key intentKey) {
+ IntentData data = current.get(intentKey);
+ return (data != null) ? data.state() : null;
+ }
+
+ @Override
+ public List<Intent> getInstallableIntents(Key intentKey) {
+ IntentData data = current.get(intentKey);
+ if (data != null) {
+ return data.installables();
+ }
+ return null;
+ }
+
+ @Override
+ public void write(IntentData newData) {
+ checkNotNull(newData);
+
+ synchronized (this) {
+ // TODO this could be refactored/cleaned up
+ IntentData currentData = current.get(newData.key());
+ IntentData pendingData = pending.get(newData.key());
+
+ if (IntentData.isUpdateAcceptable(currentData, newData)) {
+ if (pendingData != null) {
+ if (pendingData.state() == PURGE_REQ) {
+ current.remove(newData.key(), newData);
+ } else {
+ current.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)
+ pending.remove(newData.key());
+ }
+ }
+ notifyDelegateIfNotNull(IntentEvent.getEvent(newData));
+ }
+ }
+ }
+
+ private void notifyDelegateIfNotNull(IntentEvent event) {
+ if (event != null) {
+ notifyDelegate(event);
+ }
+ }
+
+ @Override
+ public void batchWrite(Iterable<IntentData> updates) {
+ for (IntentData data : updates) {
+ write(data);
+ }
+ }
+
+ @Override
+ public Intent getIntent(Key key) {
+ IntentData data = current.get(key);
+ return (data != null) ? data.intent() : null;
+ }
+
+ @Override
+ public IntentData getIntentData(Key key) {
+ IntentData currentData = current.get(key);
+ if (currentData == null) {
+ return null;
+ }
+ return new IntentData(currentData);
+ }
+
+ @Override
+ public void addPending(IntentData data) {
+ if (data.version() == null) { // recompiled intents will already have a version
+ data.setVersion(new SystemClockTimestamp());
+ }
+ synchronized (this) {
+ IntentData existingData = pending.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) {
+ pending.put(data.key(), data);
+ checkNotNull(delegate, "Store delegate is not set")
+ .process(new IntentData(data));
+ notifyDelegateIfNotNull(IntentEvent.getEvent(data));
+ } else {
+ log.debug("IntentData {} is older than existing: {}",
+ data, existingData);
+ }
+ //TODO consider also checking the current map at this point
+ }
+ }
+
+ @Override
+ public boolean isMaster(Key intentKey) {
+ return true;
+ }
+
+ @Override
+ public Iterable<Intent> getPending() {
+ return pending.values().stream()
+ .map(IntentData::intent)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Iterable<IntentData> getPendingData() {
+ return Lists.newArrayList(pending.values());
+ }
+
+ @Override
+ public Iterable<IntentData> getPendingData(boolean localOnly, long olderThan) {
+ long older = System.nanoTime() - olderThan * 1_000_000; //convert ms to ns
+ final SystemClockTimestamp time = new SystemClockTimestamp(older);
+ return pending.values().stream()
+ .filter(data -> data.version().isOlderThan(time) &&
+ (!localOnly || isMaster(data.key())))
+ .collect(Collectors.toList());
+ }
+}