Add intents -p commmand to have some visibility into the pending map

Change-Id: Ic29460d8bf78f185bbfa426bc0aeef309b22cf7f
diff --git a/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java b/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java
index e20b015..ae6f189 100644
--- a/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java
@@ -56,6 +56,11 @@
             required = false, multiValued = false)
     private boolean intentsSummary = false;
 
+    @Option(name = "-p", aliases = "--pending",
+            description = "Show inforamtion about pending intents",
+            required = false, multiValued = false)
+    private boolean pending = false;
+
     @Override
     protected void execute() {
         IntentService service = get(IntentService.class);
@@ -70,6 +75,14 @@
                 intentSummaries.printSummary();
             }
             return;
+        } else if (pending) {
+            service.getPending().forEach(intent ->
+            print("id=%s, key=%s, type=%s, appId=%s",
+                  intent.id(), intent.key(),
+                  intent.getClass().getSimpleName(),
+                  intent.appId().name())
+            );
+            return;
         }
 
         if (outputJson()) {
diff --git a/core/api/src/main/java/org/onosproject/net/intent/IntentService.java b/core/api/src/main/java/org/onosproject/net/intent/IntentService.java
index ff7083d..354db6f 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/IntentService.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/IntentService.java
@@ -16,6 +16,7 @@
 package org.onosproject.net.intent;
 
 
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -82,11 +83,21 @@
      */
     List<Intent> getInstallableIntents(Key intentKey);
 
+    // TODO remove defaults
     default boolean isLocal(Key intentKey) {
         return true;
     }
 
     /**
+     * Returns the list of intent requests pending processing.
+     *
+     * @return intents pending processing
+     */
+    default Iterable<Intent> getPending() {
+        return Collections.emptyList();
+    }
+
+    /**
      * Adds the specified listener for intent events.
      *
      * @param listener listener to be added
diff --git a/core/api/src/main/java/org/onosproject/net/intent/IntentStore.java b/core/api/src/main/java/org/onosproject/net/intent/IntentStore.java
index a7c7515..d8e63df 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/IntentStore.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/IntentStore.java
@@ -17,6 +17,7 @@
 
 import org.onosproject.store.Store;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -113,4 +114,14 @@
     default boolean isMaster(Key intentKey) { //FIXME remove default when impl.
         return true;
     }
+
+    /**
+     * Returns the intent requests pending processing.
+     *
+     * @return pending intents
+     */
+    // FIXME remove default
+    default Iterable<Intent> getPending() {
+        return Collections.emptyList();
+    }
 }
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 dd25015..280ff32 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
@@ -222,6 +222,11 @@
         return installerRegistry.getInstallers();
     }
 
+    @Override
+    public Iterable<Intent> getPending() {
+        return store.getPending();
+    }
+
     // Store delegate to re-post events emitted from the store.
     private class InternalStoreDelegate implements IntentStoreDelegate {
         @Override
diff --git a/core/store/dist/src/main/java/org/onosproject/store/ecmap/AntiEntropyAdvertisement.java b/core/store/dist/src/main/java/org/onosproject/store/ecmap/AntiEntropyAdvertisement.java
index 446f96b..23b2dfc 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/ecmap/AntiEntropyAdvertisement.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/ecmap/AntiEntropyAdvertisement.java
@@ -15,6 +15,7 @@
  */
 package org.onosproject.store.ecmap;
 
+import com.google.common.base.MoreObjects;
 import org.onosproject.cluster.NodeId;
 import org.onosproject.store.Timestamp;
 
@@ -80,4 +81,12 @@
         this.timestamps = null;
         this.tombstones = null;
     }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("timestampsSize", timestamps.size())
+                .add("tombstonesSize", tombstones.size())
+                .toString();
+    }
 }
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 9b38f44..cdb5bf3 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
@@ -32,12 +32,12 @@
 import org.onosproject.net.intent.Key;
 import org.onosproject.store.AbstractStore;
 import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
-import org.onosproject.store.impl.MultiValuedTimestamp;
-import org.onosproject.store.impl.SystemClockTimestamp;
 import org.onosproject.store.ecmap.EventuallyConsistentMap;
 import org.onosproject.store.ecmap.EventuallyConsistentMapEvent;
 import org.onosproject.store.ecmap.EventuallyConsistentMapImpl;
 import org.onosproject.store.ecmap.EventuallyConsistentMapListener;
+import org.onosproject.store.impl.MultiValuedTimestamp;
+import org.onosproject.store.impl.SystemClockTimestamp;
 import org.onosproject.store.serializers.KryoNamespaces;
 import org.slf4j.Logger;
 
@@ -237,7 +237,7 @@
             // if current.put succeeded
             pending.remove(newData.key(), newData);
         } else {
-            log.debug("not writing update: {}", newData);
+            log.debug("not writing update: current {}, new {}", currentData, newData);
         }
         /*try {
             notifyDelegate(IntentEvent.getEvent(newData));
@@ -280,6 +280,13 @@
         return partitionService.isMine(intentKey);
     }
 
+    @Override
+    public Iterable<Intent> getPending() {
+        return pending.values().stream()
+                .map(IntentData::intent)
+                .collect(Collectors.toList());
+    }
+
     private void notifyDelegateIfNotNull(IntentEvent event) {
         if (event != null) {
             notifyDelegate(event);
@@ -310,6 +317,7 @@
                 // some work.
                 if (isMaster(event.value().intent().key())) {
                     if (delegate != null) {
+                        log.debug("processing {}", event.key());
                         delegate.process(copyData(event.value()));
                     }
                 }