Fixes for GossipIntentStore
* State checking to prevent state updates outrunning.
* Copy IntentData on the way in and out of the store.
Change-Id: Id18164d15c896c5a62376aac17b7c8c2cac420c2
diff --git a/core/store/dist/src/main/java/org/onosproject/store/impl/EventuallyConsistentMapImpl.java b/core/store/dist/src/main/java/org/onosproject/store/impl/EventuallyConsistentMapImpl.java
index 0e6a590..66e85bd 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/impl/EventuallyConsistentMapImpl.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/impl/EventuallyConsistentMapImpl.java
@@ -242,11 +242,13 @@
synchronized (this) {
Timestamp removed = removedItems.get(key);
if (removed != null && removed.compareTo(timestamp) > 0) {
+ log.debug("ecmap - removed was newer {}", value);
return false;
}
Timestamped<V> existing = items.get(key);
if (existing != null && existing.isNewer(timestamp)) {
+ log.debug("ecmap - existing was newer {}", value);
return false;
} else {
items.put(key, new Timestamped<>(value, timestamp));
diff --git a/core/store/dist/src/main/java/org/onosproject/store/intent/impl/GossipIntentStore.java b/core/store/dist/src/main/java/org/onosproject/store/intent/impl/GossipIntentStore.java
index 17439ef..d81435f 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/intent/impl/GossipIntentStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/intent/impl/GossipIntentStore.java
@@ -45,13 +45,18 @@
import java.util.List;
import java.util.stream.Collectors;
+import static org.onosproject.net.intent.IntentState.FAILED;
+import static org.onosproject.net.intent.IntentState.INSTALLED;
+import static org.onosproject.net.intent.IntentState.INSTALLING;
+import static org.onosproject.net.intent.IntentState.WITHDRAWING;
+import static org.onosproject.net.intent.IntentState.WITHDRAWN;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Manages inventory of Intents in a distributed data store that uses optimistic
* replication and gossip based techniques.
*/
-@Component(immediate = false, enabled = false)
+@Component(immediate = false, enabled = true)
@Service
public class GossipIntentStore
extends AbstractStore<IntentEvent, IntentStoreDelegate>
@@ -144,17 +149,104 @@
return null;
}
+ private IntentData copyData(IntentData original) {
+ if (original == null) {
+ return null;
+ }
+ IntentData result =
+ new IntentData(original.intent(), original.state(), original.version());
+
+ if (original.installables() != null) {
+ result.setInstallables(original.installables());
+ }
+ return result;
+ }
+
+ /**
+ * TODO.
+ * @param currentData
+ * @param newData
+ * @return
+ */
+ private boolean isUpdateAcceptable(IntentData currentData, IntentData newData) {
+
+ if (currentData == null) {
+ return true;
+ } else if (currentData.version().compareTo(newData.version()) < 0) {
+ return true;
+ } else if (currentData.version().compareTo(newData.version()) > 0) {
+ return false;
+ }
+
+ // current and new data versions are the same
+ IntentState currentState = currentData.state();
+ IntentState newState = newData.state();
+
+ switch (newState) {
+ case INSTALLING:
+ if (currentState == INSTALLING) {
+ return false;
+ }
+ // FALLTHROUGH
+ case INSTALLED:
+ if (currentState == INSTALLED) {
+ return false;
+ } else if (currentState == WITHDRAWING || currentState == WITHDRAWN) {
+ log.warn("Invalid state transition from {} to {} for intent {}",
+ currentState, newState, newData.key());
+ return false;
+ }
+ return true;
+
+ case WITHDRAWING:
+ if (currentState == WITHDRAWING) {
+ return false;
+ }
+ // FALLTHROUGH
+ case WITHDRAWN:
+ if (currentState == WITHDRAWN) {
+ return false;
+ } else if (currentState == INSTALLING || currentState == INSTALLED) {
+ log.warn("Invalid state transition from {} to {} for intent {}",
+ currentState, newState, newData.key());
+ return false;
+ }
+ return true;
+
+
+ case FAILED:
+ if (currentState == FAILED) {
+ return false;
+ }
+ return true;
+
+
+ case COMPILING:
+ case RECOMPILING:
+ case INSTALL_REQ:
+ case WITHDRAW_REQ:
+ default:
+ log.warn("Invalid state {} for intent {}", newState, newData.key());
+ return false;
+ }
+ }
+
@Override
public void write(IntentData newData) {
- log.debug("writing intent {}", newData);
+ //log.debug("writing intent {}", newData);
- // Only the master is modifying the current state. Therefore assume
- // this always succeeds
- currentState.put(newData.key(), newData);
+ IntentData currentData = currentState.get(newData.key());
- // if current.put succeeded
- pending.remove(newData.key(), newData);
+ if (isUpdateAcceptable(currentData, newData)) {
+ // Only the master is modifying the current state. Therefore assume
+ // this always succeeds
+ currentState.put(newData.key(), copyData(newData));
+ // if current.put succeeded
+ pending.remove(newData.key(), newData);
+ } else {
+ log.debug("not writing update: {}", newData);
+ }
/*try {
notifyDelegate(IntentEvent.getEvent(newData));
} catch (IllegalArgumentException e) {
@@ -179,7 +271,7 @@
@Override
public IntentData getIntentData(Key key) {
- return currentState.get(key);
+ return copyData(currentState.get(key));
}
@Override
@@ -189,7 +281,7 @@
log.debug("updating timestamp");
data.setVersion(new SystemClockTimestamp());
}
- pending.put(data.key(), data);
+ pending.put(data.key(), copyData(data));
}
@Override
@@ -234,7 +326,7 @@
// some work.
if (isMaster(event.value().intent())) {
if (delegate != null) {
- delegate.process(event.value());
+ delegate.process(copyData(event.value()));
}
}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/intent/impl/SimpleIntentStore.java b/core/store/dist/src/main/java/org/onosproject/store/intent/impl/SimpleIntentStore.java
index 59b1d74..89952ce 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/intent/impl/SimpleIntentStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/intent/impl/SimpleIntentStore.java
@@ -43,7 +43,7 @@
//TODO Note: this store will be removed once the GossipIntentStore is stable
-@Component(immediate = true)
+@Component(immediate = true, enabled = false)
@Service
//FIXME remove this
public class SimpleIntentStore