ONOS-239 Retrigger compilation when new resources are available

When an intent is withdrawn and frees up resources, trigger
recompilation of any failed intents to allow the ones waiting
for resources to be installed.

Change-Id: Ic15678378ce41516a7eab890b4b4898aeb901f78
diff --git a/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceEvent.java b/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceEvent.java
new file mode 100644
index 0000000..0428864
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceEvent.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2014 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.onlab.onos.net.resource;
+
+import java.util.Collection;
+
+import org.onlab.onos.event.AbstractEvent;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Describes an event related to a Link Resource.
+ */
+public final class LinkResourceEvent
+       extends AbstractEvent<LinkResourceEvent.Type, Collection<LinkResourceAllocations>> {
+
+    /**
+     * Type of resource this event is for.
+     */
+    public enum Type {
+        /** Additional resources are now available. */
+        ADDITIONAL_RESOURCES_AVAILABLE
+    }
+
+    /**
+     * Constructs a link resource event.
+     *
+     * @param type type of resource event to create
+     * @param linkResourceAllocations allocations that are now available
+     */
+    public LinkResourceEvent(Type type,
+                             Collection<LinkResourceAllocations> linkResourceAllocations) {
+        super(type, ImmutableList.copyOf(linkResourceAllocations));
+    }
+}
diff --git a/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceListener.java b/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceListener.java
new file mode 100644
index 0000000..11aacc1
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 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.onlab.onos.net.resource;
+
+import org.onlab.onos.event.EventListener;
+
+/**
+ * Entity for receiving link resource events.
+ */
+public interface LinkResourceListener extends EventListener<LinkResourceEvent> {
+}
diff --git a/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceService.java b/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceService.java
index 69cc5c0..b4dfa62 100644
--- a/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceService.java
+++ b/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceService.java
@@ -89,4 +89,18 @@
     Iterable<ResourceRequest> getAvailableResources(Link link,
                                           LinkResourceAllocations allocations);
 
+    /**
+     * Adds a listener for resource related events.
+     *
+     * @param listener listener to add
+     */
+    void addListener(LinkResourceListener listener);
+
+    /**
+     * Removes a listener for resource related events.
+     *
+     * @param listener listener to remove.
+     */
+    void removeListener(LinkResourceListener listener);
+
 }
diff --git a/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceStore.java b/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceStore.java
index 59d1e19..85ee89c 100644
--- a/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceStore.java
+++ b/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceStore.java
@@ -44,7 +44,7 @@
      *
      * @param allocations resources to be released
      */
-    void releaseResources(LinkResourceAllocations allocations);
+    LinkResourceEvent releaseResources(LinkResourceAllocations allocations);
 
     /**
      * Returns resources allocated for an Intent.
diff --git a/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceStoreDelegate.java b/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceStoreDelegate.java
new file mode 100644
index 0000000..be12e04
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 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.onlab.onos.net.resource;
+
+import org.onlab.onos.store.StoreDelegate;
+
+/**
+ * Link resource store delegate abstraction.
+ */
+public interface LinkResourceStoreDelegate extends StoreDelegate<LinkResourceEvent> {
+}
diff --git a/core/api/src/test/java/org/onlab/onos/net/intent/IntentTestsMocks.java b/core/api/src/test/java/org/onlab/onos/net/intent/IntentTestsMocks.java
index c5483c9..0e22a79 100644
--- a/core/api/src/test/java/org/onlab/onos/net/intent/IntentTestsMocks.java
+++ b/core/api/src/test/java/org/onlab/onos/net/intent/IntentTestsMocks.java
@@ -43,6 +43,7 @@
 import org.onlab.onos.net.resource.BandwidthResourceRequest;
 import org.onlab.onos.net.resource.LambdaResourceRequest;
 import org.onlab.onos.net.resource.LinkResourceAllocations;
+import org.onlab.onos.net.resource.LinkResourceListener;
 import org.onlab.onos.net.resource.LinkResourceRequest;
 import org.onlab.onos.net.resource.LinkResourceService;
 import org.onlab.onos.net.resource.ResourceAllocation;
@@ -273,6 +274,16 @@
         public Iterable<ResourceRequest> getAvailableResources(Link link, LinkResourceAllocations allocations) {
             return null;
         }
+
+        @Override
+        public void addListener(LinkResourceListener listener) {
+
+        }
+
+        @Override
+        public void removeListener(LinkResourceListener listener) {
+
+        }
     }
 
     private static final IntentTestsMocks.MockSelector SELECTOR =
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java
index 7773ecf..fb6aa40 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java
@@ -15,10 +15,18 @@
  */
 package org.onlab.onos.net.intent.impl;
 
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -50,22 +58,20 @@
 import org.onlab.onos.net.intent.IntentStoreDelegate;
 import org.slf4j.Logger;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
-import static org.onlab.onos.net.intent.IntentState.*;
+import static org.onlab.onos.net.intent.IntentState.COMPILING;
+import static org.onlab.onos.net.intent.IntentState.FAILED;
+import static org.onlab.onos.net.intent.IntentState.INSTALLED;
+import static org.onlab.onos.net.intent.IntentState.INSTALLING;
+import static org.onlab.onos.net.intent.IntentState.WITHDRAWING;
+import static org.onlab.onos.net.intent.IntentState.WITHDRAWN;
 import static org.onlab.util.Tools.namedThreads;
 import static org.slf4j.LoggerFactory.getLogger;
 
@@ -159,8 +165,8 @@
         checkNotNull(oldIntentId, INTENT_ID_NULL);
         checkNotNull(newIntent, INTENT_NULL);
         execute(IntentOperations.builder()
-                        .addReplaceOperation(oldIntentId, newIntent)
-                        .build());
+                .addReplaceOperation(oldIntentId, newIntent)
+                .build());
     }
 
     @Override
@@ -681,7 +687,7 @@
             // TODO: clean this up, or set to debug
             IntentState oldState = stateMap.get(intent);
             log.debug("intent id: {}, old state: {}, new state: {}",
-                     intent.id(), oldState, newState);
+                    intent.id(), oldState, newState);
 
             stateMap.put(intent, newState);
             IntentEvent event = store.setState(intent, newState);
@@ -845,4 +851,5 @@
             log.warn("NOT IMPLEMENTED -- Cancel operations: {}", operations);
         }
     }
+
 }
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/ObjectiveTracker.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/ObjectiveTracker.java
index c984632..7eeec65 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/ObjectiveTracker.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/ObjectiveTracker.java
@@ -15,8 +15,11 @@
  */
 package org.onlab.onos.net.intent.impl;
 
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.SetMultimap;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -29,15 +32,16 @@
 import org.onlab.onos.net.NetworkResource;
 import org.onlab.onos.net.intent.IntentId;
 import org.onlab.onos.net.link.LinkEvent;
+import org.onlab.onos.net.resource.LinkResourceEvent;
+import org.onlab.onos.net.resource.LinkResourceListener;
+import org.onlab.onos.net.resource.LinkResourceService;
 import org.onlab.onos.net.topology.TopologyEvent;
 import org.onlab.onos.net.topology.TopologyListener;
 import org.onlab.onos.net.topology.TopologyService;
 import org.slf4j.Logger;
 
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.SetMultimap;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -53,7 +57,7 @@
  * Entity responsible for tracking installed flows and for monitoring topology
  * events to determine what flows are affected by topology changes.
  */
-@Component
+@Component(immediate = true)
 @Service
 public class ObjectiveTracker implements ObjectiveTrackerService {
 
@@ -65,21 +69,28 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected TopologyService topologyService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkResourceService resourceManager;
+
     private ExecutorService executorService =
             newSingleThreadExecutor(namedThreads("onos-flowtracker"));
 
     private TopologyListener listener = new InternalTopologyListener();
+    private LinkResourceListener linkResourceListener =
+            new InternalLinkResourceListener();
     private TopologyChangeDelegate delegate;
 
     @Activate
     public void activate() {
         topologyService.addListener(listener);
+        resourceManager.addListener(linkResourceListener);
         log.info("Started");
     }
 
     @Deactivate
     public void deactivate() {
         topologyService.removeListener(listener);
+        resourceManager.removeListener(linkResourceListener);
         log.info("Stopped");
     }
 
@@ -173,4 +184,37 @@
         }
     }
 
+    /**
+     * Internal re-actor to resource available events.
+     */
+    private class InternalLinkResourceListener implements LinkResourceListener {
+        @Override
+        public void event(LinkResourceEvent event) {
+            executorService.execute(new ResourceAvailableHandler(event));
+        }
+    }
+
+    /*
+     * Re-dispatcher of resource available events.
+     */
+    private class ResourceAvailableHandler implements Runnable {
+
+        private final LinkResourceEvent event;
+
+        ResourceAvailableHandler(LinkResourceEvent event) {
+            this.event = event;
+        }
+
+        @Override
+        public void run() {
+            // If there is no delegate, why bother? Just bail.
+            if (delegate == null) {
+                return;
+            }
+
+            delegate.triggerCompile(new HashSet<>(), true);
+        }
+    }
+
+
 }
diff --git a/core/net/src/main/java/org/onlab/onos/net/resource/impl/LinkResourceManager.java b/core/net/src/main/java/org/onlab/onos/net/resource/impl/LinkResourceManager.java
index e7f22be..9f5d763 100644
--- a/core/net/src/main/java/org/onlab/onos/net/resource/impl/LinkResourceManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/resource/impl/LinkResourceManager.java
@@ -32,6 +32,8 @@
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
+import org.onlab.onos.event.AbstractListenerRegistry;
+import org.onlab.onos.event.EventDeliveryService;
 import org.onlab.onos.net.Link;
 import org.onlab.onos.net.intent.IntentId;
 import org.onlab.onos.net.resource.BandwidthResourceAllocation;
@@ -41,9 +43,12 @@
 import org.onlab.onos.net.resource.LambdaResourceAllocation;
 import org.onlab.onos.net.resource.LambdaResourceRequest;
 import org.onlab.onos.net.resource.LinkResourceAllocations;
+import org.onlab.onos.net.resource.LinkResourceEvent;
+import org.onlab.onos.net.resource.LinkResourceListener;
 import org.onlab.onos.net.resource.LinkResourceRequest;
 import org.onlab.onos.net.resource.LinkResourceService;
 import org.onlab.onos.net.resource.LinkResourceStore;
+import org.onlab.onos.net.resource.LinkResourceStoreDelegate;
 import org.onlab.onos.net.resource.ResourceAllocation;
 import org.onlab.onos.net.resource.ResourceRequest;
 import org.onlab.onos.net.resource.ResourceType;
@@ -58,11 +63,18 @@
 
     private final Logger log = getLogger(getClass());
 
+    protected final AbstractListenerRegistry<LinkResourceEvent, LinkResourceListener>
+            listenerRegistry = new AbstractListenerRegistry<>();
+
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     private LinkResourceStore store;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected EventDeliveryService eventDispatcher;
+
     @Activate
     public void activate() {
+        eventDispatcher.addSink(LinkResourceEvent.class, listenerRegistry);
         log.info("Started");
     }
 
@@ -150,7 +162,10 @@
 
     @Override
     public void releaseResources(LinkResourceAllocations allocations) {
-        store.releaseResources(allocations);
+        final LinkResourceEvent event = store.releaseResources(allocations);
+        if (event != null) {
+            post(event);
+        }
     }
 
     @Override
@@ -205,4 +220,32 @@
         return result;
     }
 
+    @Override
+    public void addListener(LinkResourceListener listener) {
+        listenerRegistry.addListener(listener);
+    }
+
+    @Override
+    public void removeListener(LinkResourceListener listener) {
+        listenerRegistry.removeListener(listener);
+    }
+
+    /**
+     * Posts the specified event to the local event dispatcher.
+     */
+    private void post(LinkResourceEvent event) {
+        if (event != null) {
+            eventDispatcher.post(event);
+        }
+    }
+
+    /**
+     * Store delegate to re-post events emitted from the store.
+     */
+    private class InternalStoreDelegate implements LinkResourceStoreDelegate {
+        @Override
+        public void notify(LinkResourceEvent event) {
+            post(event);
+        }
+    }
 }
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/resource/impl/DistributedLinkResourceStore.java b/core/store/dist/src/main/java/org/onlab/onos/store/resource/impl/DistributedLinkResourceStore.java
index 1078728..c45b3d3 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/resource/impl/DistributedLinkResourceStore.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/resource/impl/DistributedLinkResourceStore.java
@@ -15,6 +15,14 @@
  */
 package org.onlab.onos.store.resource.impl;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -30,6 +38,7 @@
 import org.onlab.onos.net.resource.Lambda;
 import org.onlab.onos.net.resource.LambdaResourceAllocation;
 import org.onlab.onos.net.resource.LinkResourceAllocations;
+import org.onlab.onos.net.resource.LinkResourceEvent;
 import org.onlab.onos.net.resource.LinkResourceStore;
 import org.onlab.onos.net.resource.ResourceAllocation;
 import org.onlab.onos.net.resource.ResourceType;
@@ -48,17 +57,10 @@
 
 import com.google.common.base.Function;
 import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
@@ -98,7 +100,7 @@
 
     // Link annotation key name to use as bandwidth
     private String bandwidthAnnotation = "bandwidth";
-    // Link annotation key name to use as max lamda
+    // Link annotation key name to use as max lambda
     private String wavesAnnotation = "optical.waves";
 
     private StoreSerializer serializer;
@@ -423,7 +425,7 @@
     }
 
     @Override
-    public void releaseResources(LinkResourceAllocations allocations) {
+    public LinkResourceEvent releaseResources(LinkResourceAllocations allocations) {
         checkNotNull(allocations);
 
         final IntentId intendId = allocations.intendId();
@@ -458,6 +460,14 @@
             BatchWriteResult batchWrite = databaseService.batchWrite(tx.build());
             success = batchWrite.isSuccessful();
         } while (!success);
+
+        // Issue events to force recompilation of intents.
+
+        final List<LinkResourceAllocations> releasedResources =
+                ImmutableList.of(allocations);
+        return new LinkResourceEvent(
+                LinkResourceEvent.Type.ADDITIONAL_RESOURCES_AVAILABLE,
+                releasedResources);
     }
 
     @Override
@@ -565,5 +575,4 @@
             })
             .filter(notNull());
     }
-
 }
diff --git a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleLinkResourceStore.java b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleLinkResourceStore.java
index a093fa5..76e0ff6 100644
--- a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleLinkResourceStore.java
+++ b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleLinkResourceStore.java
@@ -15,13 +15,10 @@
  */
 package org.onlab.onos.store.trivial.impl;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static org.slf4j.LoggerFactory.getLogger;
-
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -38,11 +35,18 @@
 import org.onlab.onos.net.resource.Lambda;
 import org.onlab.onos.net.resource.LambdaResourceAllocation;
 import org.onlab.onos.net.resource.LinkResourceAllocations;
+import org.onlab.onos.net.resource.LinkResourceEvent;
 import org.onlab.onos.net.resource.LinkResourceStore;
 import org.onlab.onos.net.resource.ResourceAllocation;
 import org.onlab.onos.net.resource.ResourceType;
 import org.slf4j.Logger;
 
+import com.google.common.collect.ImmutableList;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static org.slf4j.LoggerFactory.getLogger;
+
 /**
  * Manages link resources using trivial in-memory structures implementation.
  */
@@ -51,6 +55,7 @@
 public class SimpleLinkResourceStore implements LinkResourceStore {
     private static final int DEFAULT_BANDWIDTH = 1_000;
     private final Logger log = getLogger(getClass());
+
     private Map<IntentId, LinkResourceAllocations> linkResourceAllocationsMap;
     private Map<Link, Set<LinkResourceAllocations>> allocatedResources;
     private Map<Link, Set<ResourceAllocation>> freeResources;
@@ -213,7 +218,7 @@
     }
 
     @Override
-    public synchronized void releaseResources(LinkResourceAllocations allocations) {
+    public synchronized LinkResourceEvent releaseResources(LinkResourceAllocations allocations) {
         checkNotNull(allocations);
         linkResourceAllocationsMap.remove(allocations.intendId());
         for (Link link : allocations.links()) {
@@ -226,6 +231,13 @@
             }
             allocatedResources.put(link, linkAllocs);
         }
+
+        final List<LinkResourceAllocations> releasedResources =
+                ImmutableList.of(allocations);
+
+        return new LinkResourceEvent(
+                LinkResourceEvent.Type.ADDITIONAL_RESOURCES_AVAILABLE,
+                releasedResources);
     }
 
     @Override
@@ -249,4 +261,5 @@
         return Collections.unmodifiableCollection(linkResourceAllocationsMap.values());
     }
 
+
 }
diff --git a/core/store/trivial/src/test/java/org/onlab/onos/store/trivial/impl/SimpleLinkResourceStoreTest.java b/core/store/trivial/src/test/java/org/onlab/onos/store/trivial/impl/SimpleLinkResourceStoreTest.java
index f28bb63..add26ad 100644
--- a/core/store/trivial/src/test/java/org/onlab/onos/store/trivial/impl/SimpleLinkResourceStoreTest.java
+++ b/core/store/trivial/src/test/java/org/onlab/onos/store/trivial/impl/SimpleLinkResourceStoreTest.java
@@ -15,13 +15,6 @@
  */
 package org.onlab.onos.store.trivial.impl;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.onlab.onos.net.DeviceId.deviceId;
-import static org.onlab.onos.net.Link.Type.DIRECT;
-import static org.onlab.onos.net.PortNumber.portNumber;
-
 import java.util.HashSet;
 import java.util.Set;
 
@@ -43,6 +36,13 @@
 import org.onlab.onos.net.resource.ResourceAllocation;
 import org.onlab.onos.net.resource.ResourceType;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.onlab.onos.net.DeviceId.deviceId;
+import static org.onlab.onos.net.Link.Type.DIRECT;
+import static org.onlab.onos.net.PortNumber.portNumber;
+
 /**
  * Test of the simple LinkResourceStore implementation.
  */