blob: bfdc5368681337aeaa9719c43d2ea36f4bcdde9e [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
38import java.util.HashSet;
39import java.util.Set;
40
41import static com.google.common.base.Preconditions.checkArgument;
42import static org.slf4j.LoggerFactory.getLogger;
43import static com.google.common.base.Preconditions.checkNotNull;
44
45/**
46 * Store that manages device resources using Copycat-backed TransactionalMaps.
47 */
48@Component(immediate = true, enabled = true)
49@Service
50public class ConsistentDeviceResourceStore implements DeviceResourceStore {
51 private final Logger log = getLogger(getClass());
52
53 private static final String PORT_ALLOCATIONS = "PortAllocations";
54 private static final String INTENT_ALLOCATIONS = "IntentAllocations";
55
56 private static final Serializer SERIALIZER = Serializer.using(
57 new KryoNamespace.Builder().register(KryoNamespaces.API).build());
58
59 private ConsistentMap<Port, IntentId> portAllocMap;
60 private ConsistentMap<IntentId, Set<Port>> intentAllocMap;
61
62 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 protected StorageService storageService;
64
65 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 protected DeviceService deviceService;
67
68 @Activate
69 public void activate() {
70 portAllocMap = storageService.<Port, IntentId>consistentMapBuilder()
71 .withName(PORT_ALLOCATIONS)
72 .withSerializer(SERIALIZER)
73 .build();
74 intentAllocMap = storageService.<IntentId, Set<Port>>consistentMapBuilder()
75 .withName(INTENT_ALLOCATIONS)
76 .withSerializer(SERIALIZER)
77 .build();
78 log.info("Started");
79 }
80
81 @Deactivate
82 public void deactivate() {
83 log.info("Stopped");
84 }
85
86 private TransactionalMap<Port, IntentId> getPortAllocs(TransactionContext tx) {
87 return tx.getTransactionalMap(PORT_ALLOCATIONS, SERIALIZER);
88 }
89
90 private TransactionalMap<IntentId, Set<Port>> getIntentAllocs(TransactionContext tx) {
91 return tx.getTransactionalMap(INTENT_ALLOCATIONS, SERIALIZER);
92 }
93
94 private TransactionContext getTxContext() {
95 return storageService.transactionContextBuilder().build();
96 }
97
98 @Override
99 public Set<Port> getFreePorts(DeviceId deviceId) {
100 checkNotNull(deviceId);
101
102 Set<Port> freePorts = new HashSet<>();
103 for (Port port : deviceService.getPorts(deviceId)) {
104 if (!portAllocMap.containsKey(port)) {
105 freePorts.add(port);
106 }
107 }
108
109 return freePorts;
110 }
111
112 @Override
113 public void allocatePorts(Set<Port> ports, IntentId intentId) {
114 checkNotNull(ports);
115 checkArgument(ports.size() > 0);
116 checkNotNull(intentId);
117
118 TransactionContext tx = getTxContext();
119 tx.begin();
120 try {
121 TransactionalMap<Port, IntentId> portAllocs = getPortAllocs(tx);
122 for (Port port : ports) {
123 portAllocs.put(port, intentId);
124 }
125 TransactionalMap<IntentId, Set<Port>> intentAllocs = getIntentAllocs(tx);
126 intentAllocs.put(intentId, ports);
127 tx.commit();
128 } catch (Exception e) {
129 log.error("Exception thrown, rolling back", e);
130 tx.abort();
131 throw e;
132 }
133 }
134
135 @Override
136 public void releasePorts(IntentId intentId) {
137 checkNotNull(intentId);
138
139 TransactionContext tx = getTxContext();
140 tx.begin();
141 try {
142 TransactionalMap<IntentId, Set<Port>> intentAllocs = getIntentAllocs(tx);
143 Set<Port> ports = intentAllocs.get(intentId);
144 intentAllocs.remove(intentId);
145
146 TransactionalMap<Port, IntentId> portAllocs = getPortAllocs(tx);
147 for (Port port : ports) {
148 portAllocs.remove(port);
149 }
150 } catch (Exception e) {
151 log.error("Exception thrown, rolling back", e);
152 tx.abort();
153 throw e;
154 }
155 }
156}