blob: b519652ce1919791baea78b597c0beffadb84898 [file] [log] [blame]
Marc De Leenheer1afa2a02015-05-13 09:18:07 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.store.resource.impl;
17
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.apache.felix.scr.annotations.Service;
24import org.onlab.util.KryoNamespace;
25import org.onosproject.net.DeviceId;
26import org.onosproject.net.Port;
27import org.onosproject.net.device.DeviceService;
28import org.onosproject.net.intent.IntentId;
Brian O'Connor6de2e202015-05-21 14:30:41 -070029import org.onosproject.net.resource.device.DeviceResourceStore;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070030import org.onosproject.store.serializers.KryoNamespaces;
31import org.onosproject.store.service.ConsistentMap;
32import org.onosproject.store.service.Serializer;
33import org.onosproject.store.service.StorageService;
34import org.onosproject.store.service.TransactionContext;
35import org.onosproject.store.service.TransactionalMap;
36import org.slf4j.Logger;
37
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070038import java.util.Collections;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070039import java.util.HashSet;
40import java.util.Set;
41
42import static com.google.common.base.Preconditions.checkArgument;
43import static org.slf4j.LoggerFactory.getLogger;
44import static com.google.common.base.Preconditions.checkNotNull;
45
46/**
47 * Store that manages device resources using Copycat-backed TransactionalMaps.
48 */
49@Component(immediate = true, enabled = true)
50@Service
51public class ConsistentDeviceResourceStore implements DeviceResourceStore {
52 private final Logger log = getLogger(getClass());
53
54 private static final String PORT_ALLOCATIONS = "PortAllocations";
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070055 private static final String INTENT_MAPPING = "IntentMapping";
Ayaka Koshibebcb02372015-06-01 10:56:42 -070056 private static final String INTENT_ALLOCATIONS = "PortIntentAllocations";
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070057
58 private static final Serializer SERIALIZER = Serializer.using(
59 new KryoNamespace.Builder().register(KryoNamespaces.API).build());
60
61 private ConsistentMap<Port, IntentId> portAllocMap;
62 private ConsistentMap<IntentId, Set<Port>> intentAllocMap;
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070063 private ConsistentMap<IntentId, Set<IntentId>> intentMapping;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070064
65 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 protected StorageService storageService;
67
68 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
69 protected DeviceService deviceService;
70
71 @Activate
72 public void activate() {
73 portAllocMap = storageService.<Port, IntentId>consistentMapBuilder()
74 .withName(PORT_ALLOCATIONS)
75 .withSerializer(SERIALIZER)
76 .build();
77 intentAllocMap = storageService.<IntentId, Set<Port>>consistentMapBuilder()
78 .withName(INTENT_ALLOCATIONS)
79 .withSerializer(SERIALIZER)
80 .build();
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070081 intentMapping = storageService.<IntentId, Set<IntentId>>consistentMapBuilder()
82 .withName(INTENT_MAPPING)
83 .withSerializer(SERIALIZER)
84 .build();
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070085 log.info("Started");
86 }
87
88 @Deactivate
89 public void deactivate() {
90 log.info("Stopped");
91 }
92
93 private TransactionalMap<Port, IntentId> getPortAllocs(TransactionContext tx) {
94 return tx.getTransactionalMap(PORT_ALLOCATIONS, SERIALIZER);
95 }
96
97 private TransactionalMap<IntentId, Set<Port>> getIntentAllocs(TransactionContext tx) {
98 return tx.getTransactionalMap(INTENT_ALLOCATIONS, SERIALIZER);
99 }
100
101 private TransactionContext getTxContext() {
102 return storageService.transactionContextBuilder().build();
103 }
104
105 @Override
106 public Set<Port> getFreePorts(DeviceId deviceId) {
107 checkNotNull(deviceId);
108
109 Set<Port> freePorts = new HashSet<>();
110 for (Port port : deviceService.getPorts(deviceId)) {
111 if (!portAllocMap.containsKey(port)) {
112 freePorts.add(port);
113 }
114 }
115
116 return freePorts;
117 }
118
119 @Override
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700120 public boolean allocatePorts(Set<Port> ports, IntentId intentId) {
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700121 checkNotNull(ports);
122 checkArgument(ports.size() > 0);
123 checkNotNull(intentId);
124
125 TransactionContext tx = getTxContext();
126 tx.begin();
127 try {
128 TransactionalMap<Port, IntentId> portAllocs = getPortAllocs(tx);
129 for (Port port : ports) {
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700130 if (portAllocs.putIfAbsent(port, intentId) != null) {
131 throw new Exception("Port already allocated " + port.toString());
132 }
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700133 }
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700134
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700135 TransactionalMap<IntentId, Set<Port>> intentAllocs = getIntentAllocs(tx);
136 intentAllocs.put(intentId, ports);
137 tx.commit();
138 } catch (Exception e) {
139 log.error("Exception thrown, rolling back", e);
140 tx.abort();
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700141 return false;
142 }
143
144 return true;
145 }
146
147 @Override
148 public Set<Port> getAllocations(IntentId intentId) {
149 if (!intentAllocMap.containsKey(intentId)) {
150 Collections.emptySet();
151 }
152
153 return intentAllocMap.get(intentId).value();
154 }
155
156 @Override
157 public IntentId getAllocations(Port port) {
158 if (!portAllocMap.containsKey(port)) {
159 return null;
160 }
161
162 return portAllocMap.get(port).value();
163 }
164
165 @Override
166 public Set<IntentId> getMapping(IntentId intentId) {
167 return intentMapping.get(intentId).value();
168 }
169
170 @Override
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700171 public boolean allocateMapping(IntentId keyIntentId, IntentId valIntentId) {
172 Set<IntentId> intents = intentMapping.get(keyIntentId).value();
173
174 if (intents == null) {
175 intents = Collections.singleton(valIntentId);
176 } else {
177 intents.add(valIntentId);
178 }
179
180 intentMapping.put(keyIntentId, intents);
181
182 return true;
183 }
184
185 @Override
Marc De Leenheer9f7d1892015-05-30 13:22:24 -0700186 public void releaseMapping(IntentId intentId) {
187 for (IntentId intent : intentMapping.keySet()) {
188 // TODO: optimize by checking for identical src & dst
189 Set<IntentId> mapping = intentMapping.get(intent).value();
190 if (mapping.remove(intentId)) {
191 return;
192 }
193 }
194 }
195
196 @Override
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700197 public boolean releasePorts(IntentId intentId) {
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700198 checkNotNull(intentId);
199
200 TransactionContext tx = getTxContext();
201 tx.begin();
202 try {
203 TransactionalMap<IntentId, Set<Port>> intentAllocs = getIntentAllocs(tx);
204 Set<Port> ports = intentAllocs.get(intentId);
205 intentAllocs.remove(intentId);
206
207 TransactionalMap<Port, IntentId> portAllocs = getPortAllocs(tx);
208 for (Port port : ports) {
209 portAllocs.remove(port);
210 }
211 } catch (Exception e) {
212 log.error("Exception thrown, rolling back", e);
213 tx.abort();
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700214 return false;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700215 }
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700216
217 return true;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700218 }
219}