blob: 78cbb28c329bfe0ea3a2f8b22cb60c39729b7584 [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;
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -070036import org.onosproject.store.service.Versioned;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070037import org.slf4j.Logger;
38
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070039import java.util.Collections;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070040import java.util.HashSet;
41import java.util.Set;
42
43import static com.google.common.base.Preconditions.checkArgument;
44import static org.slf4j.LoggerFactory.getLogger;
45import static com.google.common.base.Preconditions.checkNotNull;
46
47/**
48 * Store that manages device resources using Copycat-backed TransactionalMaps.
49 */
50@Component(immediate = true, enabled = true)
51@Service
52public class ConsistentDeviceResourceStore implements DeviceResourceStore {
53 private final Logger log = getLogger(getClass());
54
55 private static final String PORT_ALLOCATIONS = "PortAllocations";
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070056 private static final String INTENT_MAPPING = "IntentMapping";
Ayaka Koshibebcb02372015-06-01 10:56:42 -070057 private static final String INTENT_ALLOCATIONS = "PortIntentAllocations";
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070058
59 private static final Serializer SERIALIZER = Serializer.using(
60 new KryoNamespace.Builder().register(KryoNamespaces.API).build());
61
62 private ConsistentMap<Port, IntentId> portAllocMap;
63 private ConsistentMap<IntentId, Set<Port>> intentAllocMap;
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070064 private ConsistentMap<IntentId, Set<IntentId>> intentMapping;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070065
66 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 protected StorageService storageService;
68
69 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
70 protected DeviceService deviceService;
71
72 @Activate
73 public void activate() {
74 portAllocMap = storageService.<Port, IntentId>consistentMapBuilder()
75 .withName(PORT_ALLOCATIONS)
76 .withSerializer(SERIALIZER)
77 .build();
78 intentAllocMap = storageService.<IntentId, Set<Port>>consistentMapBuilder()
79 .withName(INTENT_ALLOCATIONS)
80 .withSerializer(SERIALIZER)
81 .build();
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070082 intentMapping = storageService.<IntentId, Set<IntentId>>consistentMapBuilder()
83 .withName(INTENT_MAPPING)
84 .withSerializer(SERIALIZER)
85 .build();
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070086 log.info("Started");
87 }
88
89 @Deactivate
90 public void deactivate() {
91 log.info("Stopped");
92 }
93
94 private TransactionalMap<Port, IntentId> getPortAllocs(TransactionContext tx) {
95 return tx.getTransactionalMap(PORT_ALLOCATIONS, SERIALIZER);
96 }
97
98 private TransactionalMap<IntentId, Set<Port>> getIntentAllocs(TransactionContext tx) {
99 return tx.getTransactionalMap(INTENT_ALLOCATIONS, SERIALIZER);
100 }
101
102 private TransactionContext getTxContext() {
103 return storageService.transactionContextBuilder().build();
104 }
105
106 @Override
107 public Set<Port> getFreePorts(DeviceId deviceId) {
108 checkNotNull(deviceId);
109
110 Set<Port> freePorts = new HashSet<>();
111 for (Port port : deviceService.getPorts(deviceId)) {
112 if (!portAllocMap.containsKey(port)) {
113 freePorts.add(port);
114 }
115 }
116
117 return freePorts;
118 }
119
120 @Override
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700121 public boolean allocatePorts(Set<Port> ports, IntentId intentId) {
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700122 checkNotNull(ports);
123 checkArgument(ports.size() > 0);
124 checkNotNull(intentId);
125
126 TransactionContext tx = getTxContext();
127 tx.begin();
128 try {
129 TransactionalMap<Port, IntentId> portAllocs = getPortAllocs(tx);
130 for (Port port : ports) {
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700131 if (portAllocs.putIfAbsent(port, intentId) != null) {
132 throw new Exception("Port already allocated " + port.toString());
133 }
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700134 }
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700135
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700136 TransactionalMap<IntentId, Set<Port>> intentAllocs = getIntentAllocs(tx);
137 intentAllocs.put(intentId, ports);
138 tx.commit();
139 } catch (Exception e) {
140 log.error("Exception thrown, rolling back", e);
141 tx.abort();
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700142 return false;
143 }
144
145 return true;
146 }
147
148 @Override
149 public Set<Port> getAllocations(IntentId intentId) {
150 if (!intentAllocMap.containsKey(intentId)) {
151 Collections.emptySet();
152 }
153
154 return intentAllocMap.get(intentId).value();
155 }
156
157 @Override
158 public IntentId getAllocations(Port port) {
159 if (!portAllocMap.containsKey(port)) {
160 return null;
161 }
162
163 return portAllocMap.get(port).value();
164 }
165
166 @Override
167 public Set<IntentId> getMapping(IntentId intentId) {
Marc De Leenheer723f5532015-06-03 20:16:17 -0700168 Versioned<Set<IntentId>> result = intentMapping.get(intentId);
169
Marc De Leenheerc9733082015-06-04 12:22:38 -0700170 if (result != null) {
Marc De Leenheer723f5532015-06-03 20:16:17 -0700171 return result.value();
172 }
173
174 return null;
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700175 }
176
177 @Override
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700178 public boolean allocateMapping(IntentId keyIntentId, IntentId valIntentId) {
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700179 Versioned<Set<IntentId>> versionedIntents = intentMapping.get(keyIntentId);
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700180
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700181 if (versionedIntents == null) {
Marc De Leenheer723f5532015-06-03 20:16:17 -0700182 Set<IntentId> newSet = new HashSet<>();
183 newSet.add(valIntentId);
184 intentMapping.put(keyIntentId, newSet);
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700185 } else {
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700186 versionedIntents.value().add(valIntentId);
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700187 }
188
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700189 return true;
190 }
191
192 @Override
Marc De Leenheer9f7d1892015-05-30 13:22:24 -0700193 public void releaseMapping(IntentId intentId) {
194 for (IntentId intent : intentMapping.keySet()) {
195 // TODO: optimize by checking for identical src & dst
196 Set<IntentId> mapping = intentMapping.get(intent).value();
197 if (mapping.remove(intentId)) {
198 return;
199 }
200 }
201 }
202
203 @Override
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700204 public boolean releasePorts(IntentId intentId) {
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700205 checkNotNull(intentId);
206
207 TransactionContext tx = getTxContext();
208 tx.begin();
209 try {
210 TransactionalMap<IntentId, Set<Port>> intentAllocs = getIntentAllocs(tx);
211 Set<Port> ports = intentAllocs.get(intentId);
212 intentAllocs.remove(intentId);
213
214 TransactionalMap<Port, IntentId> portAllocs = getPortAllocs(tx);
215 for (Port port : ports) {
216 portAllocs.remove(port);
217 }
Marc De Leenheerc9733082015-06-04 12:22:38 -0700218 tx.commit();
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700219 } catch (Exception e) {
220 log.error("Exception thrown, rolling back", e);
221 tx.abort();
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700222 return false;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700223 }
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700224
225 return true;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700226 }
227}