ConsistentLinkResourceStore to replace HazelcastLinkResourceStore. Also
includes:

 - typo fix (intendId -> intentId)
 - refactored ResourceAllocations command so it doesn't use error handling as
   part of control flow
 - add ability to compare LinkResourceAllocations

Reference: ONOS-1076

Conflicts:
	cli/src/main/java/org/onosproject/cli/net/ResourceAllocationsCommand.java

Change-Id: I6a68012d8d7d359ce7c5dcd31e80a3b9f63d5670
diff --git a/cli/src/main/java/org/onosproject/cli/net/ResourceAllocationsCommand.java b/cli/src/main/java/org/onosproject/cli/net/ResourceAllocationsCommand.java
index d45be27f..c3b0c83 100644
--- a/cli/src/main/java/org/onosproject/cli/net/ResourceAllocationsCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/ResourceAllocationsCommand.java
@@ -21,14 +21,13 @@
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.Link;
 import org.onosproject.net.link.LinkService;
-import org.onosproject.net.resource.LinkResourceAllocations;
 import org.onosproject.net.resource.LinkResourceService;
 
 /**
- * Lists allocations by link.
+ * Lists allocations by link. Lists all allocations if link is unspecified.
  */
 @Command(scope = "onos", name = "resource-allocations",
-         description = "Lists allocations by link")
+        description = "Lists allocations by link. Lists all allocations if link is unspecified.")
 public class ResourceAllocationsCommand extends AbstractShellCommand {
 
     private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s%s";
@@ -46,27 +45,20 @@
         LinkResourceService resourceService = get(LinkResourceService.class);
         LinkService linkService = get(LinkService.class);
 
-        Iterable<LinkResourceAllocations> itr = null;
-        try {
-            ConnectPoint src = ConnectPoint.deviceConnectPoint(srcString);
+        if (srcString == null || dstString == null) {
+            print("----- Displaying all resource allocations -----");
+            resourceService.getAllocations().forEach(alloc -> print("%s", alloc));
+            return;
+        }
 
-            ConnectPoint dst = ConnectPoint.deviceConnectPoint(dstString);
+        ConnectPoint src = ConnectPoint.deviceConnectPoint(srcString);
+        ConnectPoint dst = ConnectPoint.deviceConnectPoint(dstString);
 
-            Link link = linkService.getLink(src, dst);
-
-            itr = resourceService.getAllocations(link);
-
-            for (LinkResourceAllocations allocation : itr) {
-                print("%s", allocation.getResourceAllocation(link));
-            }
-
-        } catch (Exception e) {
-            print("----- Displaying all resource allocations -----", e.getMessage());
-            itr = resourceService.getAllocations();
-            for (LinkResourceAllocations allocation : itr) {
-                print("%s", allocation);
-            }
-
+        Link link = linkService.getLink(src, dst);
+        if (link != null) {
+            resourceService.getAllocations(link).forEach(alloc -> print("%s", alloc));
+        } else {
+            print("No path found for endpoints: %s, %s", src, dst);
         }
     }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/resource/BandwidthResourceRequest.java b/core/api/src/main/java/org/onosproject/net/resource/BandwidthResourceRequest.java
index 6c7d249..4e012fc 100644
--- a/core/api/src/main/java/org/onosproject/net/resource/BandwidthResourceRequest.java
+++ b/core/api/src/main/java/org/onosproject/net/resource/BandwidthResourceRequest.java
@@ -15,6 +15,8 @@
  */
 package org.onosproject.net.resource;
 
+import java.util.Objects;
+
 import com.google.common.base.MoreObjects;
 
 /**
@@ -48,6 +50,23 @@
     }
 
     @Override
+    public int hashCode() {
+        return Objects.hash(bandwidth);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        final BandwidthResourceAllocation other = (BandwidthResourceAllocation) obj;
+        return Objects.equals(this.bandwidth, other.bandwidth());
+    }
+
+    @Override
     public String toString() {
         return MoreObjects.toStringHelper(this)
                 .add("bandwidth", bandwidth)
diff --git a/core/api/src/main/java/org/onosproject/net/resource/DefaultLinkResourceAllocations.java b/core/api/src/main/java/org/onosproject/net/resource/DefaultLinkResourceAllocations.java
index b2c8fa1..3a2f66d 100644
--- a/core/api/src/main/java/org/onosproject/net/resource/DefaultLinkResourceAllocations.java
+++ b/core/api/src/main/java/org/onosproject/net/resource/DefaultLinkResourceAllocations.java
@@ -27,6 +27,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Map.Entry;
 import java.util.Set;
 
@@ -56,8 +57,8 @@
     }
 
     @Override
-    public IntentId intendId() {
-        return request.intendId();
+    public IntentId intentId() {
+        return request.intentId();
     }
 
     @Override
@@ -85,6 +86,24 @@
     }
 
     @Override
+    public int hashCode() {
+        return Objects.hash(request, allocations);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        final DefaultLinkResourceAllocations other = (DefaultLinkResourceAllocations) obj;
+        return Objects.equals(this.request, other.request)
+                && Objects.equals(this.allocations, other.allocations);
+    }
+
+    @Override
     public String toString() {
         return MoreObjects.toStringHelper(this)
                 .add("allocations", allocations)
diff --git a/core/api/src/main/java/org/onosproject/net/resource/DefaultLinkResourceRequest.java b/core/api/src/main/java/org/onosproject/net/resource/DefaultLinkResourceRequest.java
index 10c991c..0c6f4bf 100644
--- a/core/api/src/main/java/org/onosproject/net/resource/DefaultLinkResourceRequest.java
+++ b/core/api/src/main/java/org/onosproject/net/resource/DefaultLinkResourceRequest.java
@@ -18,12 +18,14 @@
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.Objects;
 
 import org.onosproject.net.Link;
 import org.onosproject.net.intent.Constraint;
 import org.onosproject.net.intent.IntentId;
 
 import com.google.common.collect.ImmutableSet;
+
 import org.onosproject.net.intent.constraint.BandwidthConstraint;
 import org.onosproject.net.intent.constraint.LambdaConstraint;
 
@@ -59,7 +61,7 @@
     }
 
     @Override
-    public IntentId intendId() {
+    public IntentId intentId() {
         return intentId;
     }
 
@@ -150,7 +152,6 @@
             return this;
         }
 
-
         /**
          * Returns link resource request.
          *
@@ -162,4 +163,21 @@
         }
     }
 
+    @Override
+    public int hashCode() {
+        return Objects.hash(intentId, links);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        final DefaultLinkResourceRequest other = (DefaultLinkResourceRequest) obj;
+        return Objects.equals(this.intentId, other.intentId)
+                && Objects.equals(this.links, other.links);
+    }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/resource/LinkResourceRequest.java b/core/api/src/main/java/org/onosproject/net/resource/LinkResourceRequest.java
index 8ac3fe1..06671eb 100644
--- a/core/api/src/main/java/org/onosproject/net/resource/LinkResourceRequest.java
+++ b/core/api/src/main/java/org/onosproject/net/resource/LinkResourceRequest.java
@@ -32,7 +32,7 @@
      *
      * @return the {@link IntentId} associated with the request
      */
-    IntentId intendId();
+    IntentId intentId();
 
     /**
      * Returns the set of target links.
diff --git a/core/api/src/main/java/org/onosproject/store/service/TransactionalMap.java b/core/api/src/main/java/org/onosproject/store/service/TransactionalMap.java
index ebc6611..657d933 100644
--- a/core/api/src/main/java/org/onosproject/store/service/TransactionalMap.java
+++ b/core/api/src/main/java/org/onosproject/store/service/TransactionalMap.java
@@ -16,7 +16,6 @@
 
 package org.onosproject.store.service;
 
-
 /**
  * Transactional Map data structure.
  * <p>
diff --git a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
index ace4ff5..8e89632 100644
--- a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
+++ b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
@@ -184,7 +184,7 @@
         }
 
         @Override
-        public IntentId intendId() {
+        public IntentId intentId() {
             return null;
         }
 
diff --git a/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java b/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java
index 9d13833..10b7cfd 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java
@@ -34,7 +34,6 @@
  * Default TransactionContext implementation.
  */
 public class DefaultTransactionContext implements TransactionContext {
-
     private static final String TX_NOT_OPEN_ERROR = "Transaction Context is not open";
 
     @SuppressWarnings("rawtypes")
diff --git a/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/PartitionedDatabase.java b/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/PartitionedDatabase.java
index 903e61e..bc36419 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/PartitionedDatabase.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/PartitionedDatabase.java
@@ -356,7 +356,6 @@
         }
         Map<Database, Transaction> subTransactions = Maps.newHashMap();
         perPartitionUpdates.forEach((k, v) -> subTransactions.put(k, new DefaultTransaction(transaction.id(), v)));
-
         return subTransactions;
     }
 }
diff --git a/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/TransactionManager.java b/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/TransactionManager.java
index 8a3603a..45b590a 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/TransactionManager.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/TransactionManager.java
@@ -16,6 +16,7 @@
 package org.onosproject.store.consistent.impl;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+
 import java.util.Collection;
 import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
diff --git a/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentLinkResourceStore.java b/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentLinkResourceStore.java
new file mode 100644
index 0000000..e00bcb2
--- /dev/null
+++ b/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentLinkResourceStore.java
@@ -0,0 +1,497 @@
+package org.onosproject.store.resource.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.slf4j.Logger;
+import org.onlab.util.KryoNamespace;
+import org.onlab.util.PositionalParameterStringFormatter;
+import org.onosproject.net.Link;
+import org.onosproject.net.LinkKey;
+import org.onosproject.net.intent.IntentId;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.net.resource.Bandwidth;
+import org.onosproject.net.resource.BandwidthResourceAllocation;
+import org.onosproject.net.resource.Lambda;
+import org.onosproject.net.resource.LambdaResourceAllocation;
+import org.onosproject.net.resource.LinkResourceAllocations;
+import org.onosproject.net.resource.LinkResourceEvent;
+import org.onosproject.net.resource.LinkResourceStore;
+import org.onosproject.net.resource.LinkResourceStoreDelegate;
+import org.onosproject.net.resource.MplsLabel;
+import org.onosproject.net.resource.MplsLabelResourceAllocation;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceAllocationException;
+import org.onosproject.net.resource.ResourceType;
+import org.onosproject.store.AbstractStore;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.ConsistentMap;
+import org.onosproject.store.service.Serializer;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.TransactionContext;
+import org.onosproject.store.service.TransactionException;
+import org.onosproject.store.service.TransactionalMap;
+import org.onosproject.store.service.Versioned;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static org.slf4j.LoggerFactory.getLogger;
+import static org.onosproject.net.AnnotationKeys.BANDWIDTH;
+import static org.onosproject.net.AnnotationKeys.OPTICAL_WAVES;
+
+/**
+ * Store that manages link resources using Copycat-backed TransactionalMaps.
+ */
+@Component(immediate = true, enabled = false)
+@Service
+public class ConsistentLinkResourceStore extends
+        AbstractStore<LinkResourceEvent, LinkResourceStoreDelegate> implements
+        LinkResourceStore {
+
+    private final Logger log = getLogger(getClass());
+
+    private static final Bandwidth DEFAULT_BANDWIDTH = Bandwidth.mbps(1_000);
+    private static final Bandwidth EMPTY_BW = Bandwidth.bps(0);
+
+    // Smallest non-reserved MPLS label
+    private static final int MIN_UNRESERVED_LABEL = 0x10;
+    // Max non-reserved MPLS label = 239
+    private static final int MAX_UNRESERVED_LABEL = 0xEF;
+
+    // table to store current allocations
+    /** LinkKey -> List<LinkResourceAllocations>. */
+    private static final String LINK_RESOURCE_ALLOCATIONS = "LinkResourceAllocations";
+
+    /** IntentId -> LinkResourceAllocations. */
+    private static final String INTENT_ALLOCATIONS = "IntentAllocations";
+
+    private static final Serializer SERIALIZER = Serializer.using(
+            new KryoNamespace.Builder().register(KryoNamespaces.API).build());
+
+    // for reading committed values.
+    private ConsistentMap<IntentId, LinkResourceAllocations> intentAllocMap;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected StorageService storageService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkService linkService;
+
+    @Activate
+    public void activate() {
+        intentAllocMap = storageService.<IntentId, LinkResourceAllocations>consistentMapBuilder()
+                .withName(INTENT_ALLOCATIONS)
+                .withSerializer(SERIALIZER)
+                .build();
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        log.info("Stopped");
+    }
+
+    private TransactionalMap<IntentId, LinkResourceAllocations> getIntentAllocs(TransactionContext tx) {
+        return tx.getTransactionalMap(INTENT_ALLOCATIONS, SERIALIZER);
+    }
+
+    private TransactionalMap<LinkKey, List<LinkResourceAllocations>> getLinkAllocs(TransactionContext tx) {
+        return tx.getTransactionalMap(LINK_RESOURCE_ALLOCATIONS, SERIALIZER);
+    }
+
+    private TransactionContext getTxContext() {
+        return storageService.transactionContextBuilder().build();
+    }
+
+    private Set<? extends ResourceAllocation> getResourceCapacity(ResourceType type, Link link) {
+        if (type == ResourceType.BANDWIDTH) {
+            return ImmutableSet.of(getBandwidthResourceCapacity(link));
+        }
+        if (type == ResourceType.LAMBDA) {
+            return getLambdaResourceCapacity(link);
+        }
+        if (type == ResourceType.MPLS_LABEL) {
+            return getMplsResourceCapacity();
+        }
+        return ImmutableSet.of();
+    }
+
+    private Set<LambdaResourceAllocation> getLambdaResourceCapacity(Link link) {
+        Set<LambdaResourceAllocation> allocations = new HashSet<>();
+        try {
+            final int waves = Integer.parseInt(link.annotations().value(OPTICAL_WAVES));
+            for (int i = 1; i <= waves; i++) {
+                allocations.add(new LambdaResourceAllocation(Lambda.valueOf(i)));
+            }
+        } catch (NumberFormatException e) {
+            log.debug("No {} annotation on link {}", OPTICAL_WAVES, link);
+        }
+        return allocations;
+    }
+
+    private BandwidthResourceAllocation getBandwidthResourceCapacity(Link link) {
+
+        // if Link annotation exist, use them
+        // if all fails, use DEFAULT_BANDWIDTH
+        Bandwidth bandwidth = null;
+        String strBw = link.annotations().value(BANDWIDTH);
+        if (strBw != null) {
+            try {
+                bandwidth = Bandwidth.mbps(Double.parseDouble(strBw));
+            } catch (NumberFormatException e) {
+                // do nothings
+                bandwidth = null;
+            }
+        }
+
+        if (bandwidth == null) {
+            // fall back, use fixed default
+            bandwidth = DEFAULT_BANDWIDTH;
+        }
+        return new BandwidthResourceAllocation(bandwidth);
+    }
+
+    private Set<MplsLabelResourceAllocation> getMplsResourceCapacity() {
+        Set<MplsLabelResourceAllocation> allocations = new HashSet<>();
+        //Ignoring reserved labels of 0 through 15
+        for (int i = MIN_UNRESERVED_LABEL; i <= MAX_UNRESERVED_LABEL; i++) {
+            allocations.add(new MplsLabelResourceAllocation(MplsLabel
+                    .valueOf(i)));
+
+        }
+        return allocations;
+    }
+
+    private Map<ResourceType, Set<? extends ResourceAllocation>> getResourceCapacity(Link link) {
+        Map<ResourceType, Set<? extends ResourceAllocation>> caps = new HashMap<>();
+        for (ResourceType type : ResourceType.values()) {
+            Set<? extends ResourceAllocation> cap = getResourceCapacity(type, link);
+            if (cap != null) {
+                caps.put(type, cap);
+            }
+        }
+        return caps;
+    }
+
+    @Override
+    public Set<ResourceAllocation> getFreeResources(Link link) {
+        TransactionContext tx = getTxContext();
+
+        tx.begin();
+        try {
+            Map<ResourceType, Set<? extends ResourceAllocation>> freeResources = getFreeResourcesEx(tx, link);
+            Set<ResourceAllocation> allFree = new HashSet<>();
+            freeResources.values().forEach(allFree::addAll);
+            return allFree;
+        } finally {
+            tx.abort();
+        }
+    }
+
+    private Map<ResourceType, Set<? extends ResourceAllocation>> getFreeResourcesEx(TransactionContext tx, Link link) {
+        checkNotNull(tx);
+        checkNotNull(link);
+
+        Map<ResourceType, Set<? extends ResourceAllocation>> free = new HashMap<>();
+        final Map<ResourceType, Set<? extends ResourceAllocation>> caps = getResourceCapacity(link);
+        final Iterable<LinkResourceAllocations> allocations = getAllocations(tx, link);
+
+        for (ResourceType type : ResourceType.values()) {
+            // there should be class/category of resources
+
+            switch (type) {
+                case BANDWIDTH:
+                    Set<? extends ResourceAllocation> bw = caps.get(type);
+                    if (bw == null || bw.isEmpty()) {
+                        bw = Sets.newHashSet(new BandwidthResourceAllocation(EMPTY_BW));
+                    }
+
+                    BandwidthResourceAllocation cap = (BandwidthResourceAllocation) bw.iterator().next();
+                    double freeBw = cap.bandwidth().toDouble();
+
+                    // enumerate current allocations, subtracting resources
+                    for (LinkResourceAllocations alloc : allocations) {
+                        Set<ResourceAllocation> types = alloc.getResourceAllocation(link);
+                        for (ResourceAllocation a : types) {
+                            if (a instanceof BandwidthResourceAllocation) {
+                                BandwidthResourceAllocation bwA = (BandwidthResourceAllocation) a;
+                                freeBw -= bwA.bandwidth().toDouble();
+                            }
+                        }
+                    }
+
+                    free.put(type, Sets.newHashSet(new BandwidthResourceAllocation(Bandwidth.bps(freeBw))));
+                    break;
+                case LAMBDA:
+                    Set<? extends ResourceAllocation> lmd = caps.get(type);
+                    if (lmd == null || lmd.isEmpty()) {
+                        // nothing left
+                        break;
+                    }
+                    Set<LambdaResourceAllocation> freeL = new HashSet<>();
+                    for (ResourceAllocation r : lmd) {
+                        if (r instanceof LambdaResourceAllocation) {
+                            freeL.add((LambdaResourceAllocation) r);
+                        }
+                    }
+
+                    // enumerate current allocations, removing resources
+                    for (LinkResourceAllocations alloc : allocations) {
+                        Set<ResourceAllocation> types = alloc.getResourceAllocation(link);
+                        for (ResourceAllocation a : types) {
+                            if (a instanceof LambdaResourceAllocation) {
+                                freeL.remove(a);
+                            }
+                        }
+                    }
+
+                    free.put(type, freeL);
+                    break;
+                case MPLS_LABEL:
+                    Set<? extends ResourceAllocation> mpls = caps.get(type);
+                    if (mpls == null || mpls.isEmpty()) {
+                        // nothing left
+                        break;
+                    }
+                    Set<MplsLabelResourceAllocation> freeLabel = new HashSet<>();
+                    for (ResourceAllocation r : mpls) {
+                        if (r instanceof MplsLabelResourceAllocation) {
+                            freeLabel.add((MplsLabelResourceAllocation) r);
+                        }
+                    }
+
+                    // enumerate current allocations, removing resources
+                    for (LinkResourceAllocations alloc : allocations) {
+                        Set<ResourceAllocation> types = alloc.getResourceAllocation(link);
+                        for (ResourceAllocation a : types) {
+                            if (a instanceof MplsLabelResourceAllocation) {
+                                freeLabel.remove(a);
+                            }
+                        }
+                    }
+
+                    free.put(type, freeLabel);
+                    break;
+                default:
+                    log.debug("unsupported ResourceType {}", type);
+                    break;
+            }
+        }
+        return free;
+    }
+
+    @Override
+    public void allocateResources(LinkResourceAllocations allocations) {
+        checkNotNull(allocations);
+        TransactionContext tx = getTxContext();
+
+        tx.begin();
+        try {
+            TransactionalMap<IntentId, LinkResourceAllocations> intentAllocs = getIntentAllocs(tx);
+            intentAllocs.put(allocations.intentId(), allocations);
+            allocations.links().forEach(link -> allocateLinkResource(tx, link, allocations));
+            tx.commit();
+        } catch (Exception e) {
+            log.error("Exception thrown, rolling back", e);
+            tx.abort();
+            throw e;
+        }
+    }
+
+    private void allocateLinkResource(TransactionContext tx, Link link,
+            LinkResourceAllocations allocations) {
+        // requested resources
+        Set<ResourceAllocation> reqs = allocations.getResourceAllocation(link);
+        Map<ResourceType, Set<? extends ResourceAllocation>> available = getFreeResourcesEx(tx, link);
+        for (ResourceAllocation req : reqs) {
+            Set<? extends ResourceAllocation> avail = available.get(req.type());
+            if (req instanceof BandwidthResourceAllocation) {
+                // check if allocation should be accepted
+                if (avail.isEmpty()) {
+                    checkState(!avail.isEmpty(),
+                               "There's no Bandwidth resource on %s?",
+                               link);
+                }
+                BandwidthResourceAllocation bw = (BandwidthResourceAllocation) avail.iterator().next();
+                double bwLeft = bw.bandwidth().toDouble();
+                BandwidthResourceAllocation bwReq = ((BandwidthResourceAllocation) req);
+                bwLeft -= bwReq.bandwidth().toDouble();
+                if (bwLeft < 0) {
+                    throw new ResourceAllocationException(
+                            PositionalParameterStringFormatter.format(
+                                    "Unable to allocate bandwidth for link {} "
+                                        + " requested amount is {} current allocation is {}",
+                                    link,
+                                    bwReq.bandwidth().toDouble(),
+                                    bw));
+                }
+            } else if (req instanceof LambdaResourceAllocation) {
+                LambdaResourceAllocation lambdaAllocation = (LambdaResourceAllocation) req;
+                // check if allocation should be accepted
+                if (!avail.contains(req)) {
+                    // requested lambda was not available
+                    throw new ResourceAllocationException(
+                            PositionalParameterStringFormatter.format(
+                                "Unable to allocate lambda for link {} lambda is {}",
+                                    link,
+                                    lambdaAllocation.lambda().toInt()));
+                }
+            } else if (req instanceof MplsLabelResourceAllocation) {
+                MplsLabelResourceAllocation mplsAllocation = (MplsLabelResourceAllocation) req;
+                if (!avail.contains(req)) {
+                    throw new ResourceAllocationException(
+                                                          PositionalParameterStringFormatter
+                                                                  .format("Unable to allocate MPLS label for link "
+                                                                          + "{} MPLS label is {}",
+                                                                          link,
+                                                                          mplsAllocation
+                                                                                  .mplsLabel()
+                                                                                  .toString()));
+                }
+            }
+        }
+        // all requests allocatable => add allocation
+        final LinkKey linkKey = LinkKey.linkKey(link);
+        TransactionalMap<LinkKey, List<LinkResourceAllocations>> linkAllocs = getLinkAllocs(tx);
+        List<LinkResourceAllocations> before = linkAllocs.get(linkKey);
+        if (before == null) {
+            List<LinkResourceAllocations> after = new ArrayList<>();
+            after.add(allocations);
+            before = linkAllocs.putIfAbsent(linkKey, after);
+            if (before != null) {
+                // concurrent allocation detected, retry transaction : is this needed?
+                log.warn("Concurrent Allocation, retrying");
+                throw new TransactionException();
+            }
+        } else {
+            List<LinkResourceAllocations> after = new ArrayList<>(before.size() + 1);
+            after.addAll(before);
+            after.add(allocations);
+            linkAllocs.replace(linkKey, before, after);
+        }
+    }
+
+    @Override
+    public LinkResourceEvent releaseResources(LinkResourceAllocations allocations) {
+        checkNotNull(allocations);
+
+        final IntentId intentId = allocations.intentId();
+        final Collection<Link> links = allocations.links();
+        boolean success = false;
+        do {
+            TransactionContext tx = getTxContext();
+            tx.begin();
+            try {
+                TransactionalMap<IntentId, LinkResourceAllocations> intentAllocs = getIntentAllocs(tx);
+                intentAllocs.remove(intentId);
+
+                TransactionalMap<LinkKey, List<LinkResourceAllocations>> linkAllocs = getLinkAllocs(tx);
+                links.forEach(link -> {
+                    final LinkKey linkId = LinkKey.linkKey(link);
+
+                    List<LinkResourceAllocations> before = linkAllocs.get(linkId);
+                    if (before == null || before.isEmpty()) {
+                        // something is wrong, but it is already freed
+                        log.warn("There was no resource left to release on {}", linkId);
+                        return;
+                    }
+                    List<LinkResourceAllocations> after = new ArrayList<>(before);
+                    after.remove(allocations);
+                    linkAllocs.replace(linkId, before, after);
+                });
+                tx.commit();
+                success = true;
+            } catch (TransactionException e) {
+                log.debug("Transaction failed, retrying", e);
+                tx.abort();
+            } catch (Exception e) {
+                log.error("Exception thrown during releaseResource {}", allocations, e);
+                tx.abort();
+                throw e;
+            }
+        } 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
+    public LinkResourceAllocations getAllocations(IntentId intentId) {
+        checkNotNull(intentId);
+        Versioned<LinkResourceAllocations> alloc = null;
+        try {
+            alloc = intentAllocMap.get(intentId);
+        } catch (Exception e) {
+            log.warn("Could not read resource allocation information", e);
+        }
+        return alloc == null ? null : alloc.value();
+    }
+
+    @Override
+    public Iterable<LinkResourceAllocations> getAllocations(Link link) {
+        checkNotNull(link);
+        TransactionContext tx = getTxContext();
+        Iterable<LinkResourceAllocations> res = null;
+        tx.begin();
+        try {
+            res = getAllocations(tx, link);
+        } finally {
+            tx.abort();
+        }
+        return res == null ? Collections.emptyList() : res;
+    }
+
+    @Override
+    public Iterable<LinkResourceAllocations> getAllocations() {
+        try {
+            Set<LinkResourceAllocations> allocs =
+                    intentAllocMap.values().stream().map(Versioned::value).collect(Collectors.toSet());
+            return ImmutableSet.copyOf(allocs);
+        } catch (Exception e) {
+            log.warn("Could not read resource allocation information", e);
+        }
+        return ImmutableSet.of();
+    }
+
+    private Iterable<LinkResourceAllocations> getAllocations(TransactionContext tx, Link link) {
+        checkNotNull(tx);
+        checkNotNull(link);
+        final LinkKey key = LinkKey.linkKey(link);
+        TransactionalMap<LinkKey, List<LinkResourceAllocations>> linkAllocs = getLinkAllocs(tx);
+        List<LinkResourceAllocations> res = null;
+
+        res = linkAllocs.get(key);
+        if (res == null) {
+            res = linkAllocs.putIfAbsent(key, new ArrayList<>());
+
+            if (res == null) {
+                return Collections.emptyList();
+            } else {
+                return res;
+            }
+        }
+        return res;
+    }
+
+}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/resource/impl/HazelcastLinkResourceStore.java b/core/store/dist/src/main/java/org/onosproject/store/resource/impl/HazelcastLinkResourceStore.java
index 52494dd..913042e 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/resource/impl/HazelcastLinkResourceStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/resource/impl/HazelcastLinkResourceStore.java
@@ -339,7 +339,7 @@
 
                 STxMap<IntentId, LinkResourceAllocations> intentAllocs = getIntentAllocs(tx);
                 // should this be conditional write?
-                intentAllocs.put(allocations.intendId(), allocations);
+                intentAllocs.put(allocations.intentId(), allocations);
 
                 for (Link link : allocations.links()) {
                     allocateLinkResource(tx, link, allocations);
@@ -349,7 +349,7 @@
                 return;
             } catch (TransactionException e) {
                 log.debug("Failed to commit allocations for {}. [retry={}]",
-                          allocations.intendId(), i);
+                          allocations.intentId(), i);
                 log.trace(" details {} ", allocations, e);
                 continue;
             } catch (Exception e) {
@@ -438,7 +438,7 @@
     public LinkResourceEvent releaseResources(LinkResourceAllocations allocations) {
         checkNotNull(allocations);
 
-        final IntentId intendId = allocations.intendId();
+        final IntentId intendId = allocations.intentId();
         final Collection<Link> links = allocations.links();
 
         boolean success = false;
diff --git a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleLinkResourceStore.java b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleLinkResourceStore.java
index b31face..0d9d09c 100644
--- a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleLinkResourceStore.java
+++ b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleLinkResourceStore.java
@@ -224,7 +224,7 @@
     @Override
     public synchronized void allocateResources(LinkResourceAllocations allocations) {
         checkNotNull(allocations);
-        linkResourceAllocationsMap.put(allocations.intendId(), allocations);
+        linkResourceAllocationsMap.put(allocations.intentId(), allocations);
         for (Link link : allocations.links()) {
             subtractFreeResources(link, allocations);
             Set<LinkResourceAllocations> linkAllocs = allocatedResources.get(link);
@@ -239,7 +239,7 @@
     @Override
     public synchronized LinkResourceEvent releaseResources(LinkResourceAllocations allocations) {
         checkNotNull(allocations);
-        linkResourceAllocationsMap.remove(allocations.intendId());
+        linkResourceAllocationsMap.remove(allocations.intentId());
         for (Link link : allocations.links()) {
             addFreeResources(link, allocations);
             Set<LinkResourceAllocations> linkAllocs = allocatedResources.get(link);
diff --git a/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleLinkResourceStoreTest.java b/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleLinkResourceStoreTest.java
index 4f1bcab..3b281c7 100644
--- a/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleLinkResourceStoreTest.java
+++ b/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleLinkResourceStoreTest.java
@@ -191,7 +191,7 @@
         }
 
         @Override
-        public IntentId intendId() {
+        public IntentId intentId() {
             return null;
         }
 
@@ -227,7 +227,7 @@
         }
 
         @Override
-        public IntentId intendId() {
+        public IntentId intentId() {
             return null;
         }