ONOS-6468 Fix for race condition between compilation and installation complete state.

- Fix for a bug where intent compilation complete state,
  can overwrites intent installation complete state,
  if intent installation completes before compilation complete state is written to the store.
  - Introduced internalState version on IntentData,
    which is effectively mutation count, in order to avoid
    batch write of compilation result overwriting installation result

Change-Id: I5d77dfbe496e690ebdf2b4f9643d2b64c4233182
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
index 7b09a1a..0cae8da 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
@@ -239,7 +239,7 @@
     public void submit(Intent intent) {
         checkPermission(INTENT_WRITE);
         checkNotNull(intent, INTENT_NULL);
-        IntentData data = new IntentData(intent, IntentState.INSTALL_REQ, null);
+        IntentData data = IntentData.submit(intent);
         store.addPending(data);
     }
 
@@ -247,7 +247,7 @@
     public void withdraw(Intent intent) {
         checkPermission(INTENT_WRITE);
         checkNotNull(intent, INTENT_NULL);
-        IntentData data = new IntentData(intent, IntentState.WITHDRAW_REQ, null);
+        IntentData data = IntentData.withdraw(intent);
         store.addPending(data);
     }
 
@@ -255,7 +255,7 @@
     public void purge(Intent intent) {
         checkPermission(INTENT_WRITE);
         checkNotNull(intent, INTENT_NULL);
-        IntentData data = new IntentData(intent, IntentState.PURGE_REQ, null);
+        IntentData data = IntentData.purge(intent);
         store.addPending(data);
 
         // remove associated group if there is one
@@ -495,6 +495,8 @@
         @Override
         public void triggerCompile(Iterable<Key> intentKeys,
                                    boolean compileAllFailed) {
+            // TODO figure out who is making excessive calls?
+            log.trace("submitting {} + all?:{}", intentKeys, compileAllFailed);
             buildAndSubmitBatches(intentKeys, compileAllFailed);
         }
     }
@@ -509,6 +511,10 @@
             CompletableFuture.runAsync(() -> {
                 // process intent until the phase reaches one of the final phases
                 List<CompletableFuture<IntentData>> futures = operations.stream()
+                        .map(data -> {
+                            log.debug("Start processing of {} {}@{}", data.request(), data.key(), data.version());
+                            return data;
+                        })
                         .map(x -> CompletableFuture.completedFuture(x)
                                 .thenApply(IntentManager.this::createInitialPhase)
                                 .thenApplyAsync(IntentProcessPhase::process, workerExecutor)
@@ -525,9 +531,9 @@
                                         case INSTALLING:
                                         case WITHDRAW_REQ:
                                         case WITHDRAWING:
-                                            x.setState(FAILED);
+                                            // TODO should we swtich based on current
                                             IntentData current = store.getIntentData(x.key());
-                                            return new IntentData(x, current.installables());
+                                            return IntentData.nextState(current, FAILED);
                                         default:
                                             return null;
                                     }