blob: db484eea8dd73c972cefe4ab822b16aa8572fb9f [file] [log] [blame]
Thomas Vachuska96d55b12015-05-11 08:52:03 -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 */
Thomas Vachuska4998caa2015-08-26 13:28:38 -070016package org.onosproject.net.config.impl;
Thomas Vachuska96d55b12015-05-11 08:52:03 -070017
Thomas Vachuska0a400ea2015-09-04 11:25:03 -070018import com.fasterxml.jackson.databind.JsonNode;
Thomas Vachuska96d55b12015-05-11 08:52:03 -070019import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.Maps;
21import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.apache.felix.scr.annotations.Service;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070027import org.onosproject.event.AbstractListenerManager;
Ray Milkeya4122362015-08-18 15:19:08 -070028import org.onosproject.net.config.Config;
29import org.onosproject.net.config.ConfigFactory;
30import org.onosproject.net.config.NetworkConfigEvent;
31import org.onosproject.net.config.NetworkConfigListener;
32import org.onosproject.net.config.NetworkConfigRegistry;
33import org.onosproject.net.config.NetworkConfigService;
34import org.onosproject.net.config.NetworkConfigStore;
35import org.onosproject.net.config.NetworkConfigStoreDelegate;
36import org.onosproject.net.config.SubjectFactory;
Thomas Vachuska96d55b12015-05-11 08:52:03 -070037import org.slf4j.Logger;
38import org.slf4j.LoggerFactory;
39
40import java.util.Map;
41import java.util.Objects;
42import java.util.Set;
43
44import static com.google.common.base.Preconditions.checkNotNull;
45
46/**
47 * Implementation of the network configuration subsystem.
48 */
49@Component(immediate = true)
50@Service
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070051public class NetworkConfigManager
52 extends AbstractListenerManager<NetworkConfigEvent, NetworkConfigListener>
53 implements NetworkConfigRegistry, NetworkConfigService {
Thomas Vachuska96d55b12015-05-11 08:52:03 -070054
55 private final Logger log = LoggerFactory.getLogger(getClass());
56
57 private static final String NULL_FACTORY_MSG = "Factory cannot be null";
58 private static final String NULL_SCLASS_MSG = "Subject class cannot be null";
59 private static final String NULL_CCLASS_MSG = "Config class cannot be null";
60 private static final String NULL_SUBJECT_MSG = "Subject cannot be null";
61
62 // Inventory of configuration factories
63 private final Map<ConfigKey, ConfigFactory> factories = Maps.newConcurrentMap();
64
Ray Milkey0a4f6c32015-08-03 11:22:01 -070065 // Secondary indices to retrieve subject and config classes by keys
Thomas Vachuska96d55b12015-05-11 08:52:03 -070066 private final Map<String, SubjectFactory> subjectClasses = Maps.newConcurrentMap();
67 private final Map<Class, SubjectFactory> subjectClassKeys = Maps.newConcurrentMap();
Jonathan Hart111b42b2015-07-14 13:28:05 -070068 private final Map<ConfigIdentifier, Class<? extends Config>> configClasses = Maps.newConcurrentMap();
Thomas Vachuska96d55b12015-05-11 08:52:03 -070069
Thomas Vachuska96d55b12015-05-11 08:52:03 -070070 private final NetworkConfigStoreDelegate storeDelegate = new InternalStoreDelegate();
71
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected NetworkConfigStore store;
74
Thomas Vachuska96d55b12015-05-11 08:52:03 -070075
76 @Activate
77 public void activate() {
78 eventDispatcher.addSink(NetworkConfigEvent.class, listenerRegistry);
79 store.setDelegate(storeDelegate);
80 log.info("Started");
81 }
82
83 @Deactivate
84 public void deactivate() {
85 eventDispatcher.removeSink(NetworkConfigEvent.class);
86 store.unsetDelegate(storeDelegate);
87 log.info("Stopped");
88 }
89
90
91 @Override
92 @SuppressWarnings("unchecked")
93 public void registerConfigFactory(ConfigFactory configFactory) {
94 checkNotNull(configFactory, NULL_FACTORY_MSG);
95 factories.put(key(configFactory), configFactory);
Jonathan Hart111b42b2015-07-14 13:28:05 -070096 configClasses.put(identifier(configFactory), configFactory.configClass());
Thomas Vachuska96d55b12015-05-11 08:52:03 -070097
98 SubjectFactory subjectFactory = configFactory.subjectFactory();
Thomas Vachuskaea5adc62015-10-07 11:52:30 -070099 subjectClasses.putIfAbsent(subjectFactory.subjectClassKey(), subjectFactory);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700100 subjectClassKeys.putIfAbsent(subjectFactory.subjectClass(), subjectFactory);
101
102 store.addConfigFactory(configFactory);
103 }
104
105 @Override
106 public void unregisterConfigFactory(ConfigFactory configFactory) {
107 checkNotNull(configFactory, NULL_FACTORY_MSG);
108 factories.remove(key(configFactory));
Ray Milkey0a4f6c32015-08-03 11:22:01 -0700109 configClasses.remove(identifier(configFactory));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700110
111 // Note that we are deliberately not removing subject factory key bindings.
112 store.removeConfigFactory(configFactory);
113 }
114
115 @Override
116 public Set<ConfigFactory> getConfigFactories() {
117 return ImmutableSet.copyOf(factories.values());
118 }
119
120
121 @Override
122 @SuppressWarnings("unchecked")
123 public <S, C extends Config<S>> Set<ConfigFactory<S, C>> getConfigFactories(Class<S> subjectClass) {
124 ImmutableSet.Builder<ConfigFactory<S, C>> builder = ImmutableSet.builder();
125 factories.forEach((key, factory) -> {
126 if (factory.subjectFactory().subjectClass().equals(subjectClass)) {
127 builder.add(factory);
128 }
129 });
130 return builder.build();
131 }
132
133 @Override
134 public <S, C extends Config<S>> ConfigFactory<S, C> getConfigFactory(Class<C> configClass) {
135 checkNotNull(configClass, NULL_CCLASS_MSG);
136 return store.getConfigFactory(configClass);
137 }
138
139
140 @Override
141 public Set<Class> getSubjectClasses() {
142 ImmutableSet.Builder<Class> builder = ImmutableSet.builder();
143 factories.forEach((k, v) -> builder.add(k.subjectClass));
144 return builder.build();
145 }
146
147 @Override
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700148 public SubjectFactory getSubjectFactory(String subjectClassKey) {
149 return subjectClasses.get(subjectClassKey);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700150 }
151
152 @Override
153 public SubjectFactory getSubjectFactory(Class subjectClass) {
154 return subjectClassKeys.get(subjectClass);
155 }
156
157 @Override
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700158 public Class<? extends Config> getConfigClass(String subjectClassKey, String configKey) {
159 return configClasses.get(new ConfigIdentifier(subjectClassKey, configKey));
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700160 }
161
162 @Override
163 public <S> Set<S> getSubjects(Class<S> subjectClass) {
164 checkNotNull(subjectClass, NULL_SCLASS_MSG);
165 return store.getSubjects(subjectClass);
166 }
167
168 @Override
169 public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass, Class<C> configClass) {
170 checkNotNull(subjectClass, NULL_SCLASS_MSG);
171 checkNotNull(configClass, NULL_CCLASS_MSG);
172 return store.getSubjects(subjectClass, configClass);
173 }
174
175 @Override
176 public <S> Set<Config<S>> getConfigs(S subject) {
177 checkNotNull(subject, NULL_SUBJECT_MSG);
178 Set<Class<? extends Config<S>>> configClasses = store.getConfigClasses(subject);
179 ImmutableSet.Builder<Config<S>> cfg = ImmutableSet.builder();
180 configClasses.forEach(cc -> cfg.add(store.getConfig(subject, cc)));
181 return cfg.build();
182 }
183
184 @Override
185 public <S, T extends Config<S>> T getConfig(S subject, Class<T> configClass) {
186 checkNotNull(subject, NULL_SUBJECT_MSG);
187 checkNotNull(configClass, NULL_CCLASS_MSG);
188 return store.getConfig(subject, configClass);
189 }
190
191
192 @Override
193 public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) {
194 checkNotNull(subject, NULL_SUBJECT_MSG);
195 checkNotNull(configClass, NULL_CCLASS_MSG);
196 return store.createConfig(subject, configClass);
197 }
198
199 @Override
Thomas Vachuska0a400ea2015-09-04 11:25:03 -0700200 public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) {
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700201 checkNotNull(subject, NULL_SUBJECT_MSG);
202 checkNotNull(configClass, NULL_CCLASS_MSG);
203 return store.applyConfig(subject, configClass, json);
204 }
205
206 @Override
207 public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) {
208 checkNotNull(subject, NULL_SUBJECT_MSG);
209 checkNotNull(configClass, NULL_CCLASS_MSG);
210 store.clearConfig(subject, configClass);
211 }
212
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700213 // Auxiliary store delegate to receive notification about changes in
214 // the network configuration store state - by the store itself.
215 private class InternalStoreDelegate implements NetworkConfigStoreDelegate {
216 @Override
217 public void notify(NetworkConfigEvent event) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700218 post(event);
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700219 }
220 }
221
222
223 // Produces a key for uniquely tracking a config factory.
224 private static ConfigKey key(ConfigFactory factory) {
225 return new ConfigKey(factory.subjectFactory().subjectClass(), factory.configClass());
226 }
227
228 // Auxiliary key to track config factories.
Ray Milkeyae9faf12015-08-03 15:52:26 -0700229 protected static final class ConfigKey {
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700230 final Class subjectClass;
231 final Class configClass;
232
Ray Milkeyae9faf12015-08-03 15:52:26 -0700233 protected ConfigKey(Class subjectClass, Class configClass) {
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700234 this.subjectClass = subjectClass;
235 this.configClass = configClass;
236 }
237
238 @Override
239 public int hashCode() {
240 return Objects.hash(subjectClass, configClass);
241 }
242
243 @Override
244 public boolean equals(Object obj) {
245 if (this == obj) {
246 return true;
247 }
248 if (obj instanceof ConfigKey) {
249 final ConfigKey other = (ConfigKey) obj;
250 return Objects.equals(this.subjectClass, other.subjectClass)
251 && Objects.equals(this.configClass, other.configClass);
252 }
253 return false;
254 }
255 }
256
Jonathan Hart111b42b2015-07-14 13:28:05 -0700257 private static ConfigIdentifier identifier(ConfigFactory factory) {
Thomas Vachuskaea5adc62015-10-07 11:52:30 -0700258 return new ConfigIdentifier(factory.subjectFactory().subjectClassKey(), factory.configKey());
Jonathan Hart111b42b2015-07-14 13:28:05 -0700259 }
260
Thomas Vachuska4998caa2015-08-26 13:28:38 -0700261 static final class ConfigIdentifier {
Jonathan Hart111b42b2015-07-14 13:28:05 -0700262 final String subjectKey;
263 final String configKey;
264
Ray Milkeyae9faf12015-08-03 15:52:26 -0700265 protected ConfigIdentifier(String subjectKey, String configKey) {
Jonathan Hart111b42b2015-07-14 13:28:05 -0700266 this.subjectKey = subjectKey;
267 this.configKey = configKey;
268 }
269
270 @Override
271 public int hashCode() {
272 return Objects.hash(subjectKey, configKey);
273 }
274
275 @Override
276 public boolean equals(Object obj) {
277 if (this == obj) {
278 return true;
279 }
280 if (obj instanceof ConfigIdentifier) {
281 final ConfigIdentifier other = (ConfigIdentifier) obj;
282 return Objects.equals(this.subjectKey, other.subjectKey)
283 && Objects.equals(this.configKey, other.configKey);
284 }
285 return false;
286 }
287 }
Thomas Vachuska96d55b12015-05-11 08:52:03 -0700288}