Initial implementation of LinkResourceStore for single instance env.
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
new file mode 100644
index 0000000..30ea79c
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/net/resource/LinkResourceStore.java
@@ -0,0 +1,39 @@
+/*
+ * 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.Set;
+
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.intent.IntentId;
+
+
+/**
+ * Manages link resources.
+ */
+public interface LinkResourceStore {
+ Set<ResourceAllocation> getFreeResources(Link link);
+
+ void allocateResources(LinkResourceAllocations allocations);
+
+ void releaseResources(LinkResourceAllocations allocations);
+
+ LinkResourceAllocations getAllocations(IntentId intentId);
+
+ Iterable<LinkResourceAllocations> getAllocations(Link link);
+
+ Iterable<LinkResourceAllocations> getAllocations();
+}
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 4f84b82..7f01d37 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
@@ -15,10 +15,13 @@
*/
package org.onlab.onos.net.resource.impl;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
-import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@@ -26,6 +29,8 @@
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
+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.net.Link;
import org.onlab.onos.net.intent.IntentId;
@@ -33,15 +38,16 @@
import org.onlab.onos.net.resource.BandwidthResourceRequest;
import org.onlab.onos.net.resource.Lambda;
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.LinkResourceRequest;
import org.onlab.onos.net.resource.LinkResourceService;
+import org.onlab.onos.net.resource.LinkResourceStore;
import org.onlab.onos.net.resource.ResourceAllocation;
import org.onlab.onos.net.resource.ResourceRequest;
+import org.onlab.onos.net.resource.ResourceType;
import org.slf4j.Logger;
-import com.google.common.collect.Sets;
-
/**
* Provides basic implementation of link resources allocation.
*/
@@ -51,7 +57,8 @@
private final Logger log = getLogger(getClass());
- LinkResourceAllocations savedAllocations;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private LinkResourceStore store;
@Activate
public void activate() {
@@ -63,30 +70,65 @@
log.info("Stopped");
}
- private Iterable<Lambda> getAvailableLambdas(Iterable<Link> links) {
- return Sets.newHashSet(Lambda.valueOf(7));
+ /**
+ * Returns available lambdas on specified link.
+ *
+ * @param link the link
+ * @return available lambdas on specified link
+ */
+ private Set<Lambda> getAvailableLambdas(Link link) {
+ checkNotNull(link);
+ Set<ResourceAllocation> resAllocs = store.getFreeResources(link);
+ if (resAllocs == null) {
+ return Collections.emptySet();
+ }
+ Set<Lambda> lambdas = new HashSet<>();
+ for (ResourceAllocation res : resAllocs) {
+ if (res.type() == ResourceType.LAMBDA) {
+ lambdas.add(((LambdaResourceAllocation) res).lambda());
+ }
+ }
+ return lambdas;
}
- double usedBandwidth = 0.0;
+ /**
+ * Returns available lambdas on specified links.
+ *
+ * @param links the links
+ * @return available lambdas on specified links
+ */
+ private Iterable<Lambda> getAvailableLambdas(Iterable<Link> links) {
+ checkNotNull(links);
+ Iterator<Link> i = links.iterator();
+ checkArgument(i.hasNext());
+ Set<Lambda> lambdas = new HashSet<>(getAvailableLambdas(i.next()));
+ while (i.hasNext()) {
+ lambdas.retainAll(getAvailableLambdas(i.next()));
+ }
+ return lambdas;
+ }
@Override
public LinkResourceAllocations requestResources(LinkResourceRequest req) {
- // TODO implement it using a resource data store.
+ // TODO Concatenate multiple bandwidth requests.
+ // TODO Support multiple lambda resource requests.
+ // TODO Throw appropriate exception.
- ResourceAllocation alloc = null;
+ Set<ResourceAllocation> allocs = new HashSet<>();
for (ResourceRequest r : req.resources()) {
switch (r.type()) {
case BANDWIDTH:
- log.info("requestResources() always returns requested bandwidth");
BandwidthResourceRequest br = (BandwidthResourceRequest) r;
- alloc = new BandwidthResourceAllocation(br.bandwidth());
- usedBandwidth += br.bandwidth().toDouble();
+ allocs.add(new BandwidthResourceAllocation(br.bandwidth()));
break;
case LAMBDA:
- log.info("requestResources() always returns lambda 7");
- Iterator<Lambda> lambdaIterator = getAvailableLambdas(req.links()).iterator();
+ Iterator<Lambda> lambdaIterator =
+ getAvailableLambdas(req.links()).iterator();
if (lambdaIterator.hasNext()) {
- alloc = new LambdaResourceAllocation(lambdaIterator.next());
+ allocs.add(new LambdaResourceAllocation(lambdaIterator.next()));
+ } else {
+ log.info("Failed to allocate lambda resource.");
+ return null;
}
break;
default:
@@ -96,56 +138,66 @@
Map<Link, Set<ResourceAllocation>> allocations = new HashMap<>();
for (Link link : req.links()) {
- allocations.put(link, Sets.newHashSet(alloc));
+ allocations.put(link, allocs);
}
- savedAllocations = new DefaultLinkResourceAllocations(req, allocations);
- return savedAllocations;
+ LinkResourceAllocations result =
+ new DefaultLinkResourceAllocations(req, allocations);
+ store.allocateResources(result);
+ return result;
+
}
@Override
public void releaseResources(LinkResourceAllocations allocations) {
- // TODO Auto-generated method stub
-
+ store.releaseResources(allocations);
}
@Override
public LinkResourceAllocations updateResources(LinkResourceRequest req,
- LinkResourceAllocations oldAllocations) {
+ LinkResourceAllocations oldAllocations) {
+ // TODO
return null;
}
@Override
public Iterable<LinkResourceAllocations> getAllocations() {
- // TODO Auto-generated method stub
- return null;
+ return store.getAllocations();
}
@Override
public Iterable<LinkResourceAllocations> getAllocations(Link link) {
- ArrayList<LinkResourceAllocations> retval = new ArrayList<>(0);
- if (savedAllocations != null) {
- retval.add(savedAllocations);
- }
- return retval;
+ return store.getAllocations(link);
}
@Override
public LinkResourceAllocations getAllocations(IntentId intentId) {
- // TODO Auto-generated method stub
- return null;
+ return store.getAllocations(intentId);
}
@Override
public Iterable<ResourceRequest> getAvailableResources(Link link) {
- BandwidthResourceRequest bw = new BandwidthResourceRequest(usedBandwidth);
- ArrayList<ResourceRequest> result = new ArrayList<>();
- result.add(bw);
+ Set<ResourceAllocation> freeRes = store.getFreeResources(link);
+ Set<ResourceRequest> result = new HashSet<>();
+ for (ResourceAllocation alloc : freeRes) {
+ switch (alloc.type()) {
+ case BANDWIDTH:
+ result.add(new BandwidthResourceRequest(
+ ((BandwidthResourceAllocation) alloc).bandwidth()));
+ break;
+ case LAMBDA:
+ result.add(new LambdaResourceRequest());
+ break;
+ default:
+ break;
+ }
+ }
return result;
}
@Override
public ResourceRequest getAvailableResources(Link link,
- LinkResourceAllocations allocations) {
+ LinkResourceAllocations allocations) {
+ // TODO
return null;
}
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
new file mode 100644
index 0000000..8af6fa3
--- /dev/null
+++ b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleLinkResourceStore.java
@@ -0,0 +1,207 @@
+/*
+ * 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.store.trivial.impl;
+
+import static com.google.common.base.Preconditions.*;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+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;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.intent.IntentId;
+import org.onlab.onos.net.resource.Bandwidth;
+import org.onlab.onos.net.resource.BandwidthResourceAllocation;
+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.LinkResourceStore;
+import org.onlab.onos.net.resource.ResourceAllocation;
+import org.onlab.onos.net.resource.ResourceType;
+import org.slf4j.Logger;
+
+/**
+ * Manages link resources using trivial in-memory structures implementation.
+ */
+@Component(immediate = true)
+@Service
+public class SimpleLinkResourceStore implements LinkResourceStore {
+ private final Logger log = getLogger(getClass());
+ private Map<IntentId, LinkResourceAllocations> linkResourceAllocationsMap;
+ private Map<Link, Set<LinkResourceAllocations>> allocatedResources;
+ private Map<Link, Set<ResourceAllocation>> freeResources;
+
+ @Activate
+ public void activate() {
+ linkResourceAllocationsMap = new HashMap<>();
+ allocatedResources = new HashMap<>();
+ freeResources = new HashMap<>();
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ log.info("Stopped");
+ }
+
+ private Set<ResourceAllocation> readOriginalFreeResources(Link link) {
+ // TODO read capacity and lambda resources from topology
+ Set<ResourceAllocation> allocations = new HashSet<>();
+ for (int i = 1; i <= 100; i++) {
+ allocations.add(new LambdaResourceAllocation(Lambda.valueOf(i)));
+ }
+ allocations.add(new BandwidthResourceAllocation(Bandwidth.valueOf(1000000)));
+ return allocations;
+ }
+
+ private BandwidthResourceAllocation getBandwidth(Set<ResourceAllocation> freeRes) {
+ for (ResourceAllocation res : freeRes) {
+ if (res.type() == ResourceType.BANDWIDTH) {
+ return (BandwidthResourceAllocation) res;
+ }
+ }
+ return new BandwidthResourceAllocation(Bandwidth.valueOf(0));
+ }
+
+ private void subtractFreeResources(Link link, LinkResourceAllocations allocations) {
+ // TODO Use lock or version for updating freeResources.
+ checkNotNull(link);
+ Set<ResourceAllocation> freeRes = freeResources.get(link);
+ checkNotNull(freeRes);
+ freeRes = new HashSet<>(freeRes);
+ Set<ResourceAllocation> subRes = allocations.getResourceAllocation(link);
+ for (ResourceAllocation res : subRes) {
+ switch (res.type()) {
+ case BANDWIDTH:
+ BandwidthResourceAllocation ba = getBandwidth(freeRes);
+ double requestedBandwidth =
+ ((BandwidthResourceAllocation) res).bandwidth().toDouble();
+ double newBandwidth = ba.bandwidth().toDouble() - requestedBandwidth;
+ checkState(newBandwidth >= 0.0);
+ freeRes.remove(ba);
+ freeRes.add(new BandwidthResourceAllocation(
+ Bandwidth.valueOf(newBandwidth)));
+ break;
+ case LAMBDA:
+ checkState(freeRes.remove(res));
+ break;
+ default:
+ break;
+ }
+ }
+ freeResources.put(link, freeRes);
+
+ }
+
+ private void addFreeResources(Link link, LinkResourceAllocations allocations) {
+ // TODO Use lock or version for updating freeResources.
+ Set<ResourceAllocation> freeRes = freeResources.get(link);
+ checkNotNull(freeRes);
+ freeRes = new HashSet<>(freeRes);
+ Set<ResourceAllocation> addRes = allocations.getResourceAllocation(link);
+ for (ResourceAllocation res : addRes) {
+ switch (res.type()) {
+ case BANDWIDTH:
+ BandwidthResourceAllocation ba = getBandwidth(freeRes);
+ double requestedBandwidth =
+ ((BandwidthResourceAllocation) res).bandwidth().toDouble();
+ double newBandwidth = ba.bandwidth().toDouble() + requestedBandwidth;
+ freeRes.remove(ba);
+ freeRes.add(new BandwidthResourceAllocation(
+ Bandwidth.valueOf(newBandwidth)));
+ break;
+ case LAMBDA:
+ checkState(freeRes.add(res));
+ break;
+ default:
+ break;
+ }
+ }
+ freeResources.put(link, freeRes);
+ }
+
+ @Override
+ public Set<ResourceAllocation> getFreeResources(Link link) {
+ checkNotNull(link);
+ Set<ResourceAllocation> freeRes = freeResources.get(link);
+ if (freeRes == null) {
+ freeRes = readOriginalFreeResources(link);
+ }
+
+ return freeRes;
+ }
+
+ @Override
+ public void allocateResources(LinkResourceAllocations allocations) {
+ checkNotNull(allocations);
+ linkResourceAllocationsMap.put(allocations.intendId(), allocations);
+ for (Link link : allocations.links()) {
+ subtractFreeResources(link, allocations);
+ Set<LinkResourceAllocations> linkAllocs = allocatedResources.get(link);
+ if (linkAllocs == null) {
+ linkAllocs = new HashSet<>();
+ }
+ linkAllocs.add(allocations);
+ allocatedResources.put(link, linkAllocs);
+ }
+ }
+
+ @Override
+ public void releaseResources(LinkResourceAllocations allocations) {
+ checkNotNull(allocations);
+ linkResourceAllocationsMap.remove(allocations);
+ for (Link link : allocations.links()) {
+ addFreeResources(link, allocations);
+ Set<LinkResourceAllocations> linkAllocs = allocatedResources.get(link);
+ if (linkAllocs == null) {
+ log.error("Missing resource allocation.");
+ } else {
+ linkAllocs.remove(allocations);
+ }
+ allocatedResources.put(link, linkAllocs);
+ }
+ }
+
+ @Override
+ public LinkResourceAllocations getAllocations(IntentId intentId) {
+ checkNotNull(intentId);
+ return linkResourceAllocationsMap.get(intentId);
+ }
+
+ @Override
+ public Iterable<LinkResourceAllocations> getAllocations(Link link) {
+ checkNotNull(link);
+ Set<LinkResourceAllocations> result = allocatedResources.get(link);
+ if (result == null) {
+ result = Collections.emptySet();
+ }
+ return Collections.unmodifiableSet(result);
+ }
+
+ @Override
+ public Iterable<LinkResourceAllocations> getAllocations() {
+ return Collections.unmodifiableCollection(linkResourceAllocationsMap.values());
+ }
+
+}