2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.sal.binding.test.util;
10 import static com.google.common.base.Preconditions.checkState;
12 import java.io.InputStream;
13 import java.util.ArrayList;
14 import java.util.List;
16 import java.util.concurrent.Future;
18 import javassist.ClassPool;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
22 import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
25 import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl;
26 import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker;
27 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
28 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
29 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
30 import org.opendaylight.controller.sal.binding.api.mount.MountProviderService;
31 import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
32 import org.opendaylight.controller.sal.binding.impl.NotificationBrokerImpl;
33 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
34 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingDomConnectorDeployer;
35 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
36 import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedBindingBrokerImpl;
37 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
38 import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
39 import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
40 import org.opendaylight.controller.sal.core.api.BrokerService;
41 import org.opendaylight.controller.sal.core.api.RpcImplementation;
42 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
43 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
44 import org.opendaylight.controller.sal.core.api.data.DataStore;
45 import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
46 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
47 import org.opendaylight.controller.sal.dom.broker.BrokerImpl;
48 import org.opendaylight.controller.sal.dom.broker.MountPointManagerImpl;
49 import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper;
50 import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
51 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
52 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
53 import org.opendaylight.yangtools.concepts.ListenerRegistration;
54 import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
55 import org.opendaylight.yangtools.yang.common.QName;
56 import org.opendaylight.yangtools.yang.common.RpcResult;
57 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
58 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
59 import org.opendaylight.yangtools.yang.model.api.Module;
60 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
61 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
62 import org.reflections.Reflections;
63 import org.reflections.scanners.ResourcesScanner;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
67 import com.google.common.base.Predicate;
68 import com.google.common.collect.ClassToInstanceMap;
69 import com.google.common.collect.ImmutableClassToInstanceMap;
70 import com.google.common.collect.ImmutableMap;
71 import com.google.common.collect.MutableClassToInstanceMap;
72 import com.google.common.util.concurrent.ListeningExecutorService;
74 public class BindingTestContext implements AutoCloseable {
76 public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier TREE_ROOT = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
77 .builder().toInstance();
79 private static final Logger LOG = LoggerFactory.getLogger(BindingTestContext.class);
81 private RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
83 private DomForwardedBindingBrokerImpl baBrokerImpl;
84 private DataBrokerImpl baDataImpl;
85 private NotificationBrokerImpl baNotifyImpl;
86 private BindingIndependentConnector baConnectImpl;
88 private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
89 private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataLegacyBroker;
90 private BrokerImpl biBrokerImpl;
91 private HashMapDataStore rawDataStore;
92 private SchemaAwareDataStoreAdapter schemaAwareDataStore;
93 private DataStoreStatsWrapper dataStoreStats;
94 private DataStore dataStore;
96 private final boolean dataStoreStatisticsEnabled = false;
98 private final ListeningExecutorService executor;
99 private final ClassPool classPool;
101 private final boolean startWithSchema;
103 private MountPointManagerImpl biMountImpl;
107 private ImmutableMap<LogicalDatastoreType, DOMStore> newDatastores;
109 private BackwardsCompatibleDataBroker biCompatibleBroker;
111 private DataProviderService baData;
113 private DOMDataBroker newDOMDataBroker;
115 private final MockSchemaService mockSchemaService = new MockSchemaService();
117 private DataBroker dataBroker;
121 public DOMDataBroker getDomAsyncDataBroker() {
122 return newDOMDataBroker;
125 protected BindingTestContext(final ListeningExecutorService executor, final ClassPool classPool, final boolean startWithSchema) {
126 this.executor = executor;
127 this.classPool = classPool;
128 this.startWithSchema = startWithSchema;
132 public void startDomDataStore() {
133 checkState(dataStore == null, "DataStore already started.");
134 checkState(biDataImpl != null, "Dom Data Broker not present");
135 rawDataStore = new HashMapDataStore();
136 schemaAwareDataStore = new SchemaAwareDataStoreAdapter();
137 schemaAwareDataStore.changeDelegate(rawDataStore);
138 if (dataStoreStatisticsEnabled) {
139 dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore);
140 dataStore = dataStoreStats;
142 dataStore = schemaAwareDataStore;
144 mockSchemaService.registerSchemaServiceListener(schemaAwareDataStore);
145 biDataImpl.registerConfigurationReader(TREE_ROOT, dataStore);
146 biDataImpl.registerOperationalReader(TREE_ROOT, dataStore);
147 biDataImpl.registerCommitHandler(TREE_ROOT, dataStore);
150 public void startDomDataBroker() {
151 checkState(executor != null, "Executor needs to be set");
152 biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
153 biDataImpl.setExecutor(executor);
154 biDataLegacyBroker = biDataImpl;
157 public void startNewDataBroker() {
158 checkState(executor != null, "Executor needs to be set");
159 checkState(newDOMDataBroker != null, "DOM Data Broker must be set");
160 dataBroker = new ForwardedBindingDataBroker(newDOMDataBroker, mappingServiceImpl, mockSchemaService);
163 public void startNewDomDataBroker() {
164 checkState(executor != null, "Executor needs to be set");
165 InMemoryDOMDataStore operStore = new InMemoryDOMDataStore("OPER", executor);
166 InMemoryDOMDataStore configStore = new InMemoryDOMDataStore("CFG", executor);
167 newDatastores = ImmutableMap.<LogicalDatastoreType, DOMStore>builder()
168 .put(LogicalDatastoreType.OPERATIONAL, operStore)
169 .put(LogicalDatastoreType.CONFIGURATION, configStore)
172 newDOMDataBroker = new DOMDataBrokerImpl(newDatastores, executor);
174 biCompatibleBroker = new BackwardsCompatibleDataBroker(newDOMDataBroker,mockSchemaService);
176 mockSchemaService.registerSchemaServiceListener(configStore);
177 mockSchemaService.registerSchemaServiceListener(operStore);
178 biDataLegacyBroker = biCompatibleBroker;
181 public void startBindingDataBroker() {
182 checkState(executor != null, "Executor needs to be set");
183 baDataImpl = new DataBrokerImpl();
184 baDataImpl.setExecutor(executor);
188 public void startBindingBroker() {
189 checkState(executor != null, "Executor needs to be set");
190 checkState(baData != null, "Binding Data Broker must be started");
191 checkState(baNotifyImpl != null, "Notification Service must be started");
192 baBrokerImpl = new DomForwardedBindingBrokerImpl("test");
194 baBrokerImpl.getMountManager().setDataCommitExecutor(executor);
195 baBrokerImpl.getMountManager().setNotificationExecutor(executor);
196 baBrokerImpl.setRpcBroker(new RpcProviderRegistryImpl("test"));
197 baBrokerImpl.setLegacyDataBroker(baData);
198 baBrokerImpl.setNotificationBroker(baNotifyImpl);
199 baBrokerImpl.start();
202 public void startForwarding() {
203 checkState(baData != null, "Binding Data Broker needs to be started");
204 checkState(biDataLegacyBroker != null, "DOM Data Broker needs to be started.");
205 checkState(mappingServiceImpl != null, "DOM Mapping Service needs to be started.");
207 baConnectImpl = BindingDomConnectorDeployer.createConnector(getBindingToDomMappingService());
208 baConnectImpl.setDomRpcRegistry(getDomRpcRegistry());
209 baBrokerImpl.setConnector(baConnectImpl);
210 baBrokerImpl.setDomProviderContext(createMockContext());
211 baBrokerImpl.startForwarding();
214 private ProviderSession createMockContext() {
216 final ClassToInstanceMap<BrokerService> domBrokerServices = ImmutableClassToInstanceMap
217 .<BrokerService> builder()
219 .put(org.opendaylight.controller.sal.core.api.data.DataProviderService.class, biDataLegacyBroker) //
220 .put(RpcProvisionRegistry.class, biBrokerImpl.getRouter()) //
221 .put(MountProvisionService.class, biMountImpl) //
224 return new ProviderSession() {
227 public Future<RpcResult<CompositeNode>> rpc(final QName rpc, final CompositeNode input) {
228 throw new UnsupportedOperationException();
232 public <T extends BrokerService> T getService(final Class<T> service) {
233 return domBrokerServices.getInstance(service);
237 public boolean isClosed() {
242 public Set<QName> getSupportedRpcs() {
247 public void close() {
251 public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(
252 final RpcRegistrationListener listener) {
257 public RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation)
258 throws IllegalArgumentException {
263 public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
268 public RoutedRpcRegistration addMountedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
274 public void startBindingToDomMappingService() {
275 checkState(classPool != null, "ClassPool needs to be present");
276 mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(classPool);
277 mockSchemaService.registerSchemaServiceListener(mappingServiceImpl);
280 public void updateYangSchema(final String[] files) {
281 mockSchemaService.changeSchema(getContext(files));
284 public static String[] getAllYangFilesOnClasspath() {
285 Predicate<String> predicate = new Predicate<String>() {
287 public boolean apply(final String input) {
288 return input.endsWith(".yang");
291 Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner());
292 Set<String> result = reflection.getResources(predicate);
293 return result.toArray(new String[result.size()]);
296 private static SchemaContext getContext(final String[] yangFiles) {
297 ClassLoader loader = BindingTestContext.class.getClassLoader();
298 List<InputStream> streams = new ArrayList<>();
299 for (String string : yangFiles) {
300 InputStream stream = loader.getResourceAsStream(string);
303 YangParserImpl parser = new YangParserImpl();
304 Set<Module> modules = parser.parseYangModelsFromStreams(streams);
305 return parser.resolveSchemaContext(modules);
308 public void startLegacy() {
309 startBindingDataBroker();
310 startBindingNotificationBroker();
311 startBindingBroker();
312 startDomDataBroker();
315 startDomMountPoint();
316 startBindingToDomMappingService();
318 if (startWithSchema) {
319 loadYangSchemaFromClasspath();
323 public void start() {
324 startNewDomDataBroker();
327 startDomMountPoint();
328 startBindingToDomMappingService();
329 startNewDataBroker();
330 startNewBindingDataBroker();
331 startBindingNotificationBroker();
332 startBindingBroker();
335 if (startWithSchema) {
336 loadYangSchemaFromClasspath();
340 public void startNewBindingDataBroker() {
341 ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, mappingServiceImpl,mockSchemaService, executor);
345 private void startDomMountPoint() {
346 biMountImpl = new MountPointManagerImpl();
347 biMountImpl.setDataBroker(getDomDataBroker());
350 private void startDomBroker() {
351 checkState(executor != null);
353 SchemaAwareRpcBroker router = new SchemaAwareRpcBroker("/", mockSchemaService);
354 ClassToInstanceMap<BrokerService> services = MutableClassToInstanceMap.create();
355 biBrokerImpl = new BrokerImpl(router,services);
359 public void startBindingNotificationBroker() {
360 checkState(executor != null);
361 baNotifyImpl = new NotificationBrokerImpl(executor);
365 public void loadYangSchemaFromClasspath() {
366 String[] files = getAllYangFilesOnClasspath();
367 updateYangSchema(files);
370 public DataProviderService getBindingDataBroker() {
374 public org.opendaylight.controller.sal.core.api.data.DataProviderService getDomDataBroker() {
375 return biDataLegacyBroker;
378 public DataStore getDomDataStore() {
382 public BindingIndependentMappingService getBindingToDomMappingService() {
383 return mappingServiceImpl;
386 public void logDataStoreStatistics() {
387 if (dataStoreStats == null) {
391 LOG.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
392 dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(),
393 dataStoreStats.getConfigurationReadAverageTime());
395 LOG.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
396 dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(),
397 dataStoreStats.getOperationalReadAverageTime());
399 LOG.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
400 dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(),
401 dataStoreStats.getRequestCommitAverageTime());
404 public RpcProviderRegistry getBindingRpcRegistry() {
405 return baBrokerImpl.getRoot();
408 public RpcProvisionRegistry getDomRpcRegistry() {
409 if (biBrokerImpl == null) {
412 return biBrokerImpl.getRouter();
415 public RpcImplementation getDomRpcInvoker() {
416 return biBrokerImpl.getRouter();
420 public void close() throws Exception {
424 public MountProviderService getBindingMountProviderService() {
425 return baBrokerImpl.getMountManager();
428 public MountProvisionService getDomMountProviderService() {
432 public DataBroker getDataBroker() {