Ayaka Koshibe
Committed by Gerrit Code Review

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
...@@ -21,14 +21,13 @@ import org.onosproject.cli.AbstractShellCommand; ...@@ -21,14 +21,13 @@ import org.onosproject.cli.AbstractShellCommand;
21 import org.onosproject.net.ConnectPoint; 21 import org.onosproject.net.ConnectPoint;
22 import org.onosproject.net.Link; 22 import org.onosproject.net.Link;
23 import org.onosproject.net.link.LinkService; 23 import org.onosproject.net.link.LinkService;
24 -import org.onosproject.net.resource.LinkResourceAllocations;
25 import org.onosproject.net.resource.LinkResourceService; 24 import org.onosproject.net.resource.LinkResourceService;
26 25
27 /** 26 /**
28 - * Lists allocations by link. 27 + * Lists allocations by link. Lists all allocations if link is unspecified.
29 */ 28 */
30 @Command(scope = "onos", name = "resource-allocations", 29 @Command(scope = "onos", name = "resource-allocations",
31 - description = "Lists allocations by link") 30 + description = "Lists allocations by link. Lists all allocations if link is unspecified.")
32 public class ResourceAllocationsCommand extends AbstractShellCommand { 31 public class ResourceAllocationsCommand extends AbstractShellCommand {
33 32
34 private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s%s"; 33 private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s%s";
...@@ -46,27 +45,20 @@ public class ResourceAllocationsCommand extends AbstractShellCommand { ...@@ -46,27 +45,20 @@ public class ResourceAllocationsCommand extends AbstractShellCommand {
46 LinkResourceService resourceService = get(LinkResourceService.class); 45 LinkResourceService resourceService = get(LinkResourceService.class);
47 LinkService linkService = get(LinkService.class); 46 LinkService linkService = get(LinkService.class);
48 47
49 - Iterable<LinkResourceAllocations> itr = null; 48 + if (srcString == null || dstString == null) {
50 - try { 49 + print("----- Displaying all resource allocations -----");
51 - ConnectPoint src = ConnectPoint.deviceConnectPoint(srcString); 50 + resourceService.getAllocations().forEach(alloc -> print("%s", alloc));
52 - 51 + return;
53 - ConnectPoint dst = ConnectPoint.deviceConnectPoint(dstString); 52 + }
54 -
55 - Link link = linkService.getLink(src, dst);
56 -
57 - itr = resourceService.getAllocations(link);
58 -
59 - for (LinkResourceAllocations allocation : itr) {
60 - print("%s", allocation.getResourceAllocation(link));
61 - }
62 53
63 - } catch (Exception e) { 54 + ConnectPoint src = ConnectPoint.deviceConnectPoint(srcString);
64 - print("----- Displaying all resource allocations -----", e.getMessage()); 55 + ConnectPoint dst = ConnectPoint.deviceConnectPoint(dstString);
65 - itr = resourceService.getAllocations();
66 - for (LinkResourceAllocations allocation : itr) {
67 - print("%s", allocation);
68 - }
69 56
57 + Link link = linkService.getLink(src, dst);
58 + if (link != null) {
59 + resourceService.getAllocations(link).forEach(alloc -> print("%s", alloc));
60 + } else {
61 + print("No path found for endpoints: %s, %s", src, dst);
70 } 62 }
71 } 63 }
72 } 64 }
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
15 */ 15 */
16 package org.onosproject.net.resource; 16 package org.onosproject.net.resource;
17 17
18 +import java.util.Objects;
19 +
18 import com.google.common.base.MoreObjects; 20 import com.google.common.base.MoreObjects;
19 21
20 /** 22 /**
...@@ -48,6 +50,23 @@ public class BandwidthResourceRequest implements ResourceRequest { ...@@ -48,6 +50,23 @@ public class BandwidthResourceRequest implements ResourceRequest {
48 } 50 }
49 51
50 @Override 52 @Override
53 + public int hashCode() {
54 + return Objects.hash(bandwidth);
55 + }
56 +
57 + @Override
58 + public boolean equals(Object obj) {
59 + if (this == obj) {
60 + return true;
61 + }
62 + if (obj == null || getClass() != obj.getClass()) {
63 + return false;
64 + }
65 + final BandwidthResourceAllocation other = (BandwidthResourceAllocation) obj;
66 + return Objects.equals(this.bandwidth, other.bandwidth());
67 + }
68 +
69 + @Override
51 public String toString() { 70 public String toString() {
52 return MoreObjects.toStringHelper(this) 71 return MoreObjects.toStringHelper(this)
53 .add("bandwidth", bandwidth) 72 .add("bandwidth", bandwidth)
......
...@@ -27,6 +27,7 @@ import org.onosproject.net.intent.IntentId; ...@@ -27,6 +27,7 @@ import org.onosproject.net.intent.IntentId;
27 import java.util.Collection; 27 import java.util.Collection;
28 import java.util.Collections; 28 import java.util.Collections;
29 import java.util.Map; 29 import java.util.Map;
30 +import java.util.Objects;
30 import java.util.Map.Entry; 31 import java.util.Map.Entry;
31 import java.util.Set; 32 import java.util.Set;
32 33
...@@ -56,8 +57,8 @@ public class DefaultLinkResourceAllocations implements LinkResourceAllocations { ...@@ -56,8 +57,8 @@ public class DefaultLinkResourceAllocations implements LinkResourceAllocations {
56 } 57 }
57 58
58 @Override 59 @Override
59 - public IntentId intendId() { 60 + public IntentId intentId() {
60 - return request.intendId(); 61 + return request.intentId();
61 } 62 }
62 63
63 @Override 64 @Override
...@@ -85,6 +86,24 @@ public class DefaultLinkResourceAllocations implements LinkResourceAllocations { ...@@ -85,6 +86,24 @@ public class DefaultLinkResourceAllocations implements LinkResourceAllocations {
85 } 86 }
86 87
87 @Override 88 @Override
89 + public int hashCode() {
90 + return Objects.hash(request, allocations);
91 + }
92 +
93 + @Override
94 + public boolean equals(Object obj) {
95 + if (this == obj) {
96 + return true;
97 + }
98 + if (obj == null || getClass() != obj.getClass()) {
99 + return false;
100 + }
101 + final DefaultLinkResourceAllocations other = (DefaultLinkResourceAllocations) obj;
102 + return Objects.equals(this.request, other.request)
103 + && Objects.equals(this.allocations, other.allocations);
104 + }
105 +
106 + @Override
88 public String toString() { 107 public String toString() {
89 return MoreObjects.toStringHelper(this) 108 return MoreObjects.toStringHelper(this)
90 .add("allocations", allocations) 109 .add("allocations", allocations)
......
...@@ -18,12 +18,14 @@ package org.onosproject.net.resource; ...@@ -18,12 +18,14 @@ package org.onosproject.net.resource;
18 import java.util.Collection; 18 import java.util.Collection;
19 import java.util.HashSet; 19 import java.util.HashSet;
20 import java.util.Set; 20 import java.util.Set;
21 +import java.util.Objects;
21 22
22 import org.onosproject.net.Link; 23 import org.onosproject.net.Link;
23 import org.onosproject.net.intent.Constraint; 24 import org.onosproject.net.intent.Constraint;
24 import org.onosproject.net.intent.IntentId; 25 import org.onosproject.net.intent.IntentId;
25 26
26 import com.google.common.collect.ImmutableSet; 27 import com.google.common.collect.ImmutableSet;
28 +
27 import org.onosproject.net.intent.constraint.BandwidthConstraint; 29 import org.onosproject.net.intent.constraint.BandwidthConstraint;
28 import org.onosproject.net.intent.constraint.LambdaConstraint; 30 import org.onosproject.net.intent.constraint.LambdaConstraint;
29 31
...@@ -59,7 +61,7 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest { ...@@ -59,7 +61,7 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
59 } 61 }
60 62
61 @Override 63 @Override
62 - public IntentId intendId() { 64 + public IntentId intentId() {
63 return intentId; 65 return intentId;
64 } 66 }
65 67
...@@ -150,7 +152,6 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest { ...@@ -150,7 +152,6 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
150 return this; 152 return this;
151 } 153 }
152 154
153 -
154 /** 155 /**
155 * Returns link resource request. 156 * Returns link resource request.
156 * 157 *
...@@ -162,4 +163,21 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest { ...@@ -162,4 +163,21 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
162 } 163 }
163 } 164 }
164 165
166 + @Override
167 + public int hashCode() {
168 + return Objects.hash(intentId, links);
169 + }
170 +
171 + @Override
172 + public boolean equals(Object obj) {
173 + if (this == obj) {
174 + return true;
175 + }
176 + if (obj == null || getClass() != obj.getClass()) {
177 + return false;
178 + }
179 + final DefaultLinkResourceRequest other = (DefaultLinkResourceRequest) obj;
180 + return Objects.equals(this.intentId, other.intentId)
181 + && Objects.equals(this.links, other.links);
182 + }
165 } 183 }
......
...@@ -32,7 +32,7 @@ public interface LinkResourceRequest extends ResourceRequest { ...@@ -32,7 +32,7 @@ public interface LinkResourceRequest extends ResourceRequest {
32 * 32 *
33 * @return the {@link IntentId} associated with the request 33 * @return the {@link IntentId} associated with the request
34 */ 34 */
35 - IntentId intendId(); 35 + IntentId intentId();
36 36
37 /** 37 /**
38 * Returns the set of target links. 38 * Returns the set of target links.
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
16 16
17 package org.onosproject.store.service; 17 package org.onosproject.store.service;
18 18
19 -
20 /** 19 /**
21 * Transactional Map data structure. 20 * Transactional Map data structure.
22 * <p> 21 * <p>
......
...@@ -184,7 +184,7 @@ public class IntentTestsMocks { ...@@ -184,7 +184,7 @@ public class IntentTestsMocks {
184 } 184 }
185 185
186 @Override 186 @Override
187 - public IntentId intendId() { 187 + public IntentId intentId() {
188 return null; 188 return null;
189 } 189 }
190 190
......
...@@ -34,7 +34,6 @@ import com.google.common.collect.Maps; ...@@ -34,7 +34,6 @@ import com.google.common.collect.Maps;
34 * Default TransactionContext implementation. 34 * Default TransactionContext implementation.
35 */ 35 */
36 public class DefaultTransactionContext implements TransactionContext { 36 public class DefaultTransactionContext implements TransactionContext {
37 -
38 private static final String TX_NOT_OPEN_ERROR = "Transaction Context is not open"; 37 private static final String TX_NOT_OPEN_ERROR = "Transaction Context is not open";
39 38
40 @SuppressWarnings("rawtypes") 39 @SuppressWarnings("rawtypes")
......
...@@ -356,7 +356,6 @@ public class PartitionedDatabase implements Database { ...@@ -356,7 +356,6 @@ public class PartitionedDatabase implements Database {
356 } 356 }
357 Map<Database, Transaction> subTransactions = Maps.newHashMap(); 357 Map<Database, Transaction> subTransactions = Maps.newHashMap();
358 perPartitionUpdates.forEach((k, v) -> subTransactions.put(k, new DefaultTransaction(transaction.id(), v))); 358 perPartitionUpdates.forEach((k, v) -> subTransactions.put(k, new DefaultTransaction(transaction.id(), v)));
359 -
360 return subTransactions; 359 return subTransactions;
361 } 360 }
362 } 361 }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 package org.onosproject.store.consistent.impl; 16 package org.onosproject.store.consistent.impl;
17 17
18 import static com.google.common.base.Preconditions.checkNotNull; 18 import static com.google.common.base.Preconditions.checkNotNull;
19 +
19 import java.util.Collection; 20 import java.util.Collection;
20 import java.util.concurrent.CompletableFuture; 21 import java.util.concurrent.CompletableFuture;
21 import java.util.stream.Collectors; 22 import java.util.stream.Collectors;
......
1 +package org.onosproject.store.resource.impl;
2 +
3 +import java.util.ArrayList;
4 +import java.util.Collection;
5 +import java.util.Collections;
6 +import java.util.HashMap;
7 +import java.util.HashSet;
8 +import java.util.List;
9 +import java.util.Map;
10 +import java.util.Set;
11 +import java.util.stream.Collectors;
12 +
13 +import org.apache.felix.scr.annotations.Component;
14 +import org.apache.felix.scr.annotations.Reference;
15 +import org.apache.felix.scr.annotations.ReferenceCardinality;
16 +import org.apache.felix.scr.annotations.Service;
17 +import org.apache.felix.scr.annotations.Activate;
18 +import org.apache.felix.scr.annotations.Deactivate;
19 +import org.slf4j.Logger;
20 +import org.onlab.util.KryoNamespace;
21 +import org.onlab.util.PositionalParameterStringFormatter;
22 +import org.onosproject.net.Link;
23 +import org.onosproject.net.LinkKey;
24 +import org.onosproject.net.intent.IntentId;
25 +import org.onosproject.net.link.LinkService;
26 +import org.onosproject.net.resource.Bandwidth;
27 +import org.onosproject.net.resource.BandwidthResourceAllocation;
28 +import org.onosproject.net.resource.Lambda;
29 +import org.onosproject.net.resource.LambdaResourceAllocation;
30 +import org.onosproject.net.resource.LinkResourceAllocations;
31 +import org.onosproject.net.resource.LinkResourceEvent;
32 +import org.onosproject.net.resource.LinkResourceStore;
33 +import org.onosproject.net.resource.LinkResourceStoreDelegate;
34 +import org.onosproject.net.resource.MplsLabel;
35 +import org.onosproject.net.resource.MplsLabelResourceAllocation;
36 +import org.onosproject.net.resource.ResourceAllocation;
37 +import org.onosproject.net.resource.ResourceAllocationException;
38 +import org.onosproject.net.resource.ResourceType;
39 +import org.onosproject.store.AbstractStore;
40 +import org.onosproject.store.serializers.KryoNamespaces;
41 +import org.onosproject.store.service.ConsistentMap;
42 +import org.onosproject.store.service.Serializer;
43 +import org.onosproject.store.service.StorageService;
44 +import org.onosproject.store.service.TransactionContext;
45 +import org.onosproject.store.service.TransactionException;
46 +import org.onosproject.store.service.TransactionalMap;
47 +import org.onosproject.store.service.Versioned;
48 +
49 +import com.google.common.collect.ImmutableList;
50 +import com.google.common.collect.ImmutableSet;
51 +import com.google.common.collect.Sets;
52 +
53 +import static com.google.common.base.Preconditions.checkNotNull;
54 +import static com.google.common.base.Preconditions.checkState;
55 +import static org.slf4j.LoggerFactory.getLogger;
56 +import static org.onosproject.net.AnnotationKeys.BANDWIDTH;
57 +import static org.onosproject.net.AnnotationKeys.OPTICAL_WAVES;
58 +
59 +/**
60 + * Store that manages link resources using Copycat-backed TransactionalMaps.
61 + */
62 +@Component(immediate = true, enabled = false)
63 +@Service
64 +public class ConsistentLinkResourceStore extends
65 + AbstractStore<LinkResourceEvent, LinkResourceStoreDelegate> implements
66 + LinkResourceStore {
67 +
68 + private final Logger log = getLogger(getClass());
69 +
70 + private static final Bandwidth DEFAULT_BANDWIDTH = Bandwidth.mbps(1_000);
71 + private static final Bandwidth EMPTY_BW = Bandwidth.bps(0);
72 +
73 + // Smallest non-reserved MPLS label
74 + private static final int MIN_UNRESERVED_LABEL = 0x10;
75 + // Max non-reserved MPLS label = 239
76 + private static final int MAX_UNRESERVED_LABEL = 0xEF;
77 +
78 + // table to store current allocations
79 + /** LinkKey -> List<LinkResourceAllocations>. */
80 + private static final String LINK_RESOURCE_ALLOCATIONS = "LinkResourceAllocations";
81 +
82 + /** IntentId -> LinkResourceAllocations. */
83 + private static final String INTENT_ALLOCATIONS = "IntentAllocations";
84 +
85 + private static final Serializer SERIALIZER = Serializer.using(
86 + new KryoNamespace.Builder().register(KryoNamespaces.API).build());
87 +
88 + // for reading committed values.
89 + private ConsistentMap<IntentId, LinkResourceAllocations> intentAllocMap;
90 +
91 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 + protected StorageService storageService;
93 +
94 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 + protected LinkService linkService;
96 +
97 + @Activate
98 + public void activate() {
99 + intentAllocMap = storageService.<IntentId, LinkResourceAllocations>consistentMapBuilder()
100 + .withName(INTENT_ALLOCATIONS)
101 + .withSerializer(SERIALIZER)
102 + .build();
103 + log.info("Started");
104 + }
105 +
106 + @Deactivate
107 + public void deactivate() {
108 + log.info("Stopped");
109 + }
110 +
111 + private TransactionalMap<IntentId, LinkResourceAllocations> getIntentAllocs(TransactionContext tx) {
112 + return tx.getTransactionalMap(INTENT_ALLOCATIONS, SERIALIZER);
113 + }
114 +
115 + private TransactionalMap<LinkKey, List<LinkResourceAllocations>> getLinkAllocs(TransactionContext tx) {
116 + return tx.getTransactionalMap(LINK_RESOURCE_ALLOCATIONS, SERIALIZER);
117 + }
118 +
119 + private TransactionContext getTxContext() {
120 + return storageService.transactionContextBuilder().build();
121 + }
122 +
123 + private Set<? extends ResourceAllocation> getResourceCapacity(ResourceType type, Link link) {
124 + if (type == ResourceType.BANDWIDTH) {
125 + return ImmutableSet.of(getBandwidthResourceCapacity(link));
126 + }
127 + if (type == ResourceType.LAMBDA) {
128 + return getLambdaResourceCapacity(link);
129 + }
130 + if (type == ResourceType.MPLS_LABEL) {
131 + return getMplsResourceCapacity();
132 + }
133 + return ImmutableSet.of();
134 + }
135 +
136 + private Set<LambdaResourceAllocation> getLambdaResourceCapacity(Link link) {
137 + Set<LambdaResourceAllocation> allocations = new HashSet<>();
138 + try {
139 + final int waves = Integer.parseInt(link.annotations().value(OPTICAL_WAVES));
140 + for (int i = 1; i <= waves; i++) {
141 + allocations.add(new LambdaResourceAllocation(Lambda.valueOf(i)));
142 + }
143 + } catch (NumberFormatException e) {
144 + log.debug("No {} annotation on link {}", OPTICAL_WAVES, link);
145 + }
146 + return allocations;
147 + }
148 +
149 + private BandwidthResourceAllocation getBandwidthResourceCapacity(Link link) {
150 +
151 + // if Link annotation exist, use them
152 + // if all fails, use DEFAULT_BANDWIDTH
153 + Bandwidth bandwidth = null;
154 + String strBw = link.annotations().value(BANDWIDTH);
155 + if (strBw != null) {
156 + try {
157 + bandwidth = Bandwidth.mbps(Double.parseDouble(strBw));
158 + } catch (NumberFormatException e) {
159 + // do nothings
160 + bandwidth = null;
161 + }
162 + }
163 +
164 + if (bandwidth == null) {
165 + // fall back, use fixed default
166 + bandwidth = DEFAULT_BANDWIDTH;
167 + }
168 + return new BandwidthResourceAllocation(bandwidth);
169 + }
170 +
171 + private Set<MplsLabelResourceAllocation> getMplsResourceCapacity() {
172 + Set<MplsLabelResourceAllocation> allocations = new HashSet<>();
173 + //Ignoring reserved labels of 0 through 15
174 + for (int i = MIN_UNRESERVED_LABEL; i <= MAX_UNRESERVED_LABEL; i++) {
175 + allocations.add(new MplsLabelResourceAllocation(MplsLabel
176 + .valueOf(i)));
177 +
178 + }
179 + return allocations;
180 + }
181 +
182 + private Map<ResourceType, Set<? extends ResourceAllocation>> getResourceCapacity(Link link) {
183 + Map<ResourceType, Set<? extends ResourceAllocation>> caps = new HashMap<>();
184 + for (ResourceType type : ResourceType.values()) {
185 + Set<? extends ResourceAllocation> cap = getResourceCapacity(type, link);
186 + if (cap != null) {
187 + caps.put(type, cap);
188 + }
189 + }
190 + return caps;
191 + }
192 +
193 + @Override
194 + public Set<ResourceAllocation> getFreeResources(Link link) {
195 + TransactionContext tx = getTxContext();
196 +
197 + tx.begin();
198 + try {
199 + Map<ResourceType, Set<? extends ResourceAllocation>> freeResources = getFreeResourcesEx(tx, link);
200 + Set<ResourceAllocation> allFree = new HashSet<>();
201 + freeResources.values().forEach(allFree::addAll);
202 + return allFree;
203 + } finally {
204 + tx.abort();
205 + }
206 + }
207 +
208 + private Map<ResourceType, Set<? extends ResourceAllocation>> getFreeResourcesEx(TransactionContext tx, Link link) {
209 + checkNotNull(tx);
210 + checkNotNull(link);
211 +
212 + Map<ResourceType, Set<? extends ResourceAllocation>> free = new HashMap<>();
213 + final Map<ResourceType, Set<? extends ResourceAllocation>> caps = getResourceCapacity(link);
214 + final Iterable<LinkResourceAllocations> allocations = getAllocations(tx, link);
215 +
216 + for (ResourceType type : ResourceType.values()) {
217 + // there should be class/category of resources
218 +
219 + switch (type) {
220 + case BANDWIDTH:
221 + Set<? extends ResourceAllocation> bw = caps.get(type);
222 + if (bw == null || bw.isEmpty()) {
223 + bw = Sets.newHashSet(new BandwidthResourceAllocation(EMPTY_BW));
224 + }
225 +
226 + BandwidthResourceAllocation cap = (BandwidthResourceAllocation) bw.iterator().next();
227 + double freeBw = cap.bandwidth().toDouble();
228 +
229 + // enumerate current allocations, subtracting resources
230 + for (LinkResourceAllocations alloc : allocations) {
231 + Set<ResourceAllocation> types = alloc.getResourceAllocation(link);
232 + for (ResourceAllocation a : types) {
233 + if (a instanceof BandwidthResourceAllocation) {
234 + BandwidthResourceAllocation bwA = (BandwidthResourceAllocation) a;
235 + freeBw -= bwA.bandwidth().toDouble();
236 + }
237 + }
238 + }
239 +
240 + free.put(type, Sets.newHashSet(new BandwidthResourceAllocation(Bandwidth.bps(freeBw))));
241 + break;
242 + case LAMBDA:
243 + Set<? extends ResourceAllocation> lmd = caps.get(type);
244 + if (lmd == null || lmd.isEmpty()) {
245 + // nothing left
246 + break;
247 + }
248 + Set<LambdaResourceAllocation> freeL = new HashSet<>();
249 + for (ResourceAllocation r : lmd) {
250 + if (r instanceof LambdaResourceAllocation) {
251 + freeL.add((LambdaResourceAllocation) r);
252 + }
253 + }
254 +
255 + // enumerate current allocations, removing resources
256 + for (LinkResourceAllocations alloc : allocations) {
257 + Set<ResourceAllocation> types = alloc.getResourceAllocation(link);
258 + for (ResourceAllocation a : types) {
259 + if (a instanceof LambdaResourceAllocation) {
260 + freeL.remove(a);
261 + }
262 + }
263 + }
264 +
265 + free.put(type, freeL);
266 + break;
267 + case MPLS_LABEL:
268 + Set<? extends ResourceAllocation> mpls = caps.get(type);
269 + if (mpls == null || mpls.isEmpty()) {
270 + // nothing left
271 + break;
272 + }
273 + Set<MplsLabelResourceAllocation> freeLabel = new HashSet<>();
274 + for (ResourceAllocation r : mpls) {
275 + if (r instanceof MplsLabelResourceAllocation) {
276 + freeLabel.add((MplsLabelResourceAllocation) r);
277 + }
278 + }
279 +
280 + // enumerate current allocations, removing resources
281 + for (LinkResourceAllocations alloc : allocations) {
282 + Set<ResourceAllocation> types = alloc.getResourceAllocation(link);
283 + for (ResourceAllocation a : types) {
284 + if (a instanceof MplsLabelResourceAllocation) {
285 + freeLabel.remove(a);
286 + }
287 + }
288 + }
289 +
290 + free.put(type, freeLabel);
291 + break;
292 + default:
293 + log.debug("unsupported ResourceType {}", type);
294 + break;
295 + }
296 + }
297 + return free;
298 + }
299 +
300 + @Override
301 + public void allocateResources(LinkResourceAllocations allocations) {
302 + checkNotNull(allocations);
303 + TransactionContext tx = getTxContext();
304 +
305 + tx.begin();
306 + try {
307 + TransactionalMap<IntentId, LinkResourceAllocations> intentAllocs = getIntentAllocs(tx);
308 + intentAllocs.put(allocations.intentId(), allocations);
309 + allocations.links().forEach(link -> allocateLinkResource(tx, link, allocations));
310 + tx.commit();
311 + } catch (Exception e) {
312 + log.error("Exception thrown, rolling back", e);
313 + tx.abort();
314 + throw e;
315 + }
316 + }
317 +
318 + private void allocateLinkResource(TransactionContext tx, Link link,
319 + LinkResourceAllocations allocations) {
320 + // requested resources
321 + Set<ResourceAllocation> reqs = allocations.getResourceAllocation(link);
322 + Map<ResourceType, Set<? extends ResourceAllocation>> available = getFreeResourcesEx(tx, link);
323 + for (ResourceAllocation req : reqs) {
324 + Set<? extends ResourceAllocation> avail = available.get(req.type());
325 + if (req instanceof BandwidthResourceAllocation) {
326 + // check if allocation should be accepted
327 + if (avail.isEmpty()) {
328 + checkState(!avail.isEmpty(),
329 + "There's no Bandwidth resource on %s?",
330 + link);
331 + }
332 + BandwidthResourceAllocation bw = (BandwidthResourceAllocation) avail.iterator().next();
333 + double bwLeft = bw.bandwidth().toDouble();
334 + BandwidthResourceAllocation bwReq = ((BandwidthResourceAllocation) req);
335 + bwLeft -= bwReq.bandwidth().toDouble();
336 + if (bwLeft < 0) {
337 + throw new ResourceAllocationException(
338 + PositionalParameterStringFormatter.format(
339 + "Unable to allocate bandwidth for link {} "
340 + + " requested amount is {} current allocation is {}",
341 + link,
342 + bwReq.bandwidth().toDouble(),
343 + bw));
344 + }
345 + } else if (req instanceof LambdaResourceAllocation) {
346 + LambdaResourceAllocation lambdaAllocation = (LambdaResourceAllocation) req;
347 + // check if allocation should be accepted
348 + if (!avail.contains(req)) {
349 + // requested lambda was not available
350 + throw new ResourceAllocationException(
351 + PositionalParameterStringFormatter.format(
352 + "Unable to allocate lambda for link {} lambda is {}",
353 + link,
354 + lambdaAllocation.lambda().toInt()));
355 + }
356 + } else if (req instanceof MplsLabelResourceAllocation) {
357 + MplsLabelResourceAllocation mplsAllocation = (MplsLabelResourceAllocation) req;
358 + if (!avail.contains(req)) {
359 + throw new ResourceAllocationException(
360 + PositionalParameterStringFormatter
361 + .format("Unable to allocate MPLS label for link "
362 + + "{} MPLS label is {}",
363 + link,
364 + mplsAllocation
365 + .mplsLabel()
366 + .toString()));
367 + }
368 + }
369 + }
370 + // all requests allocatable => add allocation
371 + final LinkKey linkKey = LinkKey.linkKey(link);
372 + TransactionalMap<LinkKey, List<LinkResourceAllocations>> linkAllocs = getLinkAllocs(tx);
373 + List<LinkResourceAllocations> before = linkAllocs.get(linkKey);
374 + if (before == null) {
375 + List<LinkResourceAllocations> after = new ArrayList<>();
376 + after.add(allocations);
377 + before = linkAllocs.putIfAbsent(linkKey, after);
378 + if (before != null) {
379 + // concurrent allocation detected, retry transaction : is this needed?
380 + log.warn("Concurrent Allocation, retrying");
381 + throw new TransactionException();
382 + }
383 + } else {
384 + List<LinkResourceAllocations> after = new ArrayList<>(before.size() + 1);
385 + after.addAll(before);
386 + after.add(allocations);
387 + linkAllocs.replace(linkKey, before, after);
388 + }
389 + }
390 +
391 + @Override
392 + public LinkResourceEvent releaseResources(LinkResourceAllocations allocations) {
393 + checkNotNull(allocations);
394 +
395 + final IntentId intentId = allocations.intentId();
396 + final Collection<Link> links = allocations.links();
397 + boolean success = false;
398 + do {
399 + TransactionContext tx = getTxContext();
400 + tx.begin();
401 + try {
402 + TransactionalMap<IntentId, LinkResourceAllocations> intentAllocs = getIntentAllocs(tx);
403 + intentAllocs.remove(intentId);
404 +
405 + TransactionalMap<LinkKey, List<LinkResourceAllocations>> linkAllocs = getLinkAllocs(tx);
406 + links.forEach(link -> {
407 + final LinkKey linkId = LinkKey.linkKey(link);
408 +
409 + List<LinkResourceAllocations> before = linkAllocs.get(linkId);
410 + if (before == null || before.isEmpty()) {
411 + // something is wrong, but it is already freed
412 + log.warn("There was no resource left to release on {}", linkId);
413 + return;
414 + }
415 + List<LinkResourceAllocations> after = new ArrayList<>(before);
416 + after.remove(allocations);
417 + linkAllocs.replace(linkId, before, after);
418 + });
419 + tx.commit();
420 + success = true;
421 + } catch (TransactionException e) {
422 + log.debug("Transaction failed, retrying", e);
423 + tx.abort();
424 + } catch (Exception e) {
425 + log.error("Exception thrown during releaseResource {}", allocations, e);
426 + tx.abort();
427 + throw e;
428 + }
429 + } while (!success);
430 +
431 + // Issue events to force recompilation of intents.
432 + final List<LinkResourceAllocations> releasedResources = ImmutableList.of(allocations);
433 + return new LinkResourceEvent(
434 + LinkResourceEvent.Type.ADDITIONAL_RESOURCES_AVAILABLE,
435 + releasedResources);
436 +
437 + }
438 +
439 + @Override
440 + public LinkResourceAllocations getAllocations(IntentId intentId) {
441 + checkNotNull(intentId);
442 + Versioned<LinkResourceAllocations> alloc = null;
443 + try {
444 + alloc = intentAllocMap.get(intentId);
445 + } catch (Exception e) {
446 + log.warn("Could not read resource allocation information", e);
447 + }
448 + return alloc == null ? null : alloc.value();
449 + }
450 +
451 + @Override
452 + public Iterable<LinkResourceAllocations> getAllocations(Link link) {
453 + checkNotNull(link);
454 + TransactionContext tx = getTxContext();
455 + Iterable<LinkResourceAllocations> res = null;
456 + tx.begin();
457 + try {
458 + res = getAllocations(tx, link);
459 + } finally {
460 + tx.abort();
461 + }
462 + return res == null ? Collections.emptyList() : res;
463 + }
464 +
465 + @Override
466 + public Iterable<LinkResourceAllocations> getAllocations() {
467 + try {
468 + Set<LinkResourceAllocations> allocs =
469 + intentAllocMap.values().stream().map(Versioned::value).collect(Collectors.toSet());
470 + return ImmutableSet.copyOf(allocs);
471 + } catch (Exception e) {
472 + log.warn("Could not read resource allocation information", e);
473 + }
474 + return ImmutableSet.of();
475 + }
476 +
477 + private Iterable<LinkResourceAllocations> getAllocations(TransactionContext tx, Link link) {
478 + checkNotNull(tx);
479 + checkNotNull(link);
480 + final LinkKey key = LinkKey.linkKey(link);
481 + TransactionalMap<LinkKey, List<LinkResourceAllocations>> linkAllocs = getLinkAllocs(tx);
482 + List<LinkResourceAllocations> res = null;
483 +
484 + res = linkAllocs.get(key);
485 + if (res == null) {
486 + res = linkAllocs.putIfAbsent(key, new ArrayList<>());
487 +
488 + if (res == null) {
489 + return Collections.emptyList();
490 + } else {
491 + return res;
492 + }
493 + }
494 + return res;
495 + }
496 +
497 +}
...@@ -339,7 +339,7 @@ public class HazelcastLinkResourceStore ...@@ -339,7 +339,7 @@ public class HazelcastLinkResourceStore
339 339
340 STxMap<IntentId, LinkResourceAllocations> intentAllocs = getIntentAllocs(tx); 340 STxMap<IntentId, LinkResourceAllocations> intentAllocs = getIntentAllocs(tx);
341 // should this be conditional write? 341 // should this be conditional write?
342 - intentAllocs.put(allocations.intendId(), allocations); 342 + intentAllocs.put(allocations.intentId(), allocations);
343 343
344 for (Link link : allocations.links()) { 344 for (Link link : allocations.links()) {
345 allocateLinkResource(tx, link, allocations); 345 allocateLinkResource(tx, link, allocations);
...@@ -349,7 +349,7 @@ public class HazelcastLinkResourceStore ...@@ -349,7 +349,7 @@ public class HazelcastLinkResourceStore
349 return; 349 return;
350 } catch (TransactionException e) { 350 } catch (TransactionException e) {
351 log.debug("Failed to commit allocations for {}. [retry={}]", 351 log.debug("Failed to commit allocations for {}. [retry={}]",
352 - allocations.intendId(), i); 352 + allocations.intentId(), i);
353 log.trace(" details {} ", allocations, e); 353 log.trace(" details {} ", allocations, e);
354 continue; 354 continue;
355 } catch (Exception e) { 355 } catch (Exception e) {
...@@ -438,7 +438,7 @@ public class HazelcastLinkResourceStore ...@@ -438,7 +438,7 @@ public class HazelcastLinkResourceStore
438 public LinkResourceEvent releaseResources(LinkResourceAllocations allocations) { 438 public LinkResourceEvent releaseResources(LinkResourceAllocations allocations) {
439 checkNotNull(allocations); 439 checkNotNull(allocations);
440 440
441 - final IntentId intendId = allocations.intendId(); 441 + final IntentId intendId = allocations.intentId();
442 final Collection<Link> links = allocations.links(); 442 final Collection<Link> links = allocations.links();
443 443
444 boolean success = false; 444 boolean success = false;
......
...@@ -224,7 +224,7 @@ public class SimpleLinkResourceStore implements LinkResourceStore { ...@@ -224,7 +224,7 @@ public class SimpleLinkResourceStore implements LinkResourceStore {
224 @Override 224 @Override
225 public synchronized void allocateResources(LinkResourceAllocations allocations) { 225 public synchronized void allocateResources(LinkResourceAllocations allocations) {
226 checkNotNull(allocations); 226 checkNotNull(allocations);
227 - linkResourceAllocationsMap.put(allocations.intendId(), allocations); 227 + linkResourceAllocationsMap.put(allocations.intentId(), allocations);
228 for (Link link : allocations.links()) { 228 for (Link link : allocations.links()) {
229 subtractFreeResources(link, allocations); 229 subtractFreeResources(link, allocations);
230 Set<LinkResourceAllocations> linkAllocs = allocatedResources.get(link); 230 Set<LinkResourceAllocations> linkAllocs = allocatedResources.get(link);
...@@ -239,7 +239,7 @@ public class SimpleLinkResourceStore implements LinkResourceStore { ...@@ -239,7 +239,7 @@ public class SimpleLinkResourceStore implements LinkResourceStore {
239 @Override 239 @Override
240 public synchronized LinkResourceEvent releaseResources(LinkResourceAllocations allocations) { 240 public synchronized LinkResourceEvent releaseResources(LinkResourceAllocations allocations) {
241 checkNotNull(allocations); 241 checkNotNull(allocations);
242 - linkResourceAllocationsMap.remove(allocations.intendId()); 242 + linkResourceAllocationsMap.remove(allocations.intentId());
243 for (Link link : allocations.links()) { 243 for (Link link : allocations.links()) {
244 addFreeResources(link, allocations); 244 addFreeResources(link, allocations);
245 Set<LinkResourceAllocations> linkAllocs = allocatedResources.get(link); 245 Set<LinkResourceAllocations> linkAllocs = allocatedResources.get(link);
......
...@@ -191,7 +191,7 @@ public class SimpleLinkResourceStoreTest { ...@@ -191,7 +191,7 @@ public class SimpleLinkResourceStoreTest {
191 } 191 }
192 192
193 @Override 193 @Override
194 - public IntentId intendId() { 194 + public IntentId intentId() {
195 return null; 195 return null;
196 } 196 }
197 197
...@@ -227,7 +227,7 @@ public class SimpleLinkResourceStoreTest { ...@@ -227,7 +227,7 @@ public class SimpleLinkResourceStoreTest {
227 } 227 }
228 228
229 @Override 229 @Override
230 - public IntentId intendId() { 230 + public IntentId intentId() {
231 return null; 231 return null;
232 } 232 }
233 233
......