Bug 1112: Update toaster to use async best practices
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / test / java / org / opendaylight / controller / sal / binding / test / util / BindingTestContext.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.sal.binding.test.util;
9
10 import static com.google.common.base.Preconditions.checkState;
11
12 import java.io.InputStream;
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.Set;
16 import java.util.concurrent.Future;
17
18 import javassist.ClassPool;
19
20 import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
23 import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl;
24 import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker;
25 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
26 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
27 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
28 import org.opendaylight.controller.sal.binding.api.mount.MountProviderService;
29 import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
30 import org.opendaylight.controller.sal.binding.impl.NotificationBrokerImpl;
31 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
32 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingDomConnectorDeployer;
33 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
34 import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedBindingBrokerImpl;
35 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
36 import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
37 import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
38 import org.opendaylight.controller.sal.core.api.BrokerService;
39 import org.opendaylight.controller.sal.core.api.RpcImplementation;
40 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
41 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
42 import org.opendaylight.controller.sal.core.api.data.DataStore;
43 import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
44 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
45 import org.opendaylight.controller.sal.dom.broker.BrokerImpl;
46 import org.opendaylight.controller.sal.dom.broker.MountPointManagerImpl;
47 import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper;
48 import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
49 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
50 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
51 import org.opendaylight.yangtools.concepts.ListenerRegistration;
52 import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
53 import org.opendaylight.yangtools.yang.common.QName;
54 import org.opendaylight.yangtools.yang.common.RpcResult;
55 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
56 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
57 import org.opendaylight.yangtools.yang.model.api.Module;
58 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
59 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
60 import org.reflections.Reflections;
61 import org.reflections.scanners.ResourcesScanner;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 import com.google.common.base.Predicate;
66 import com.google.common.collect.ClassToInstanceMap;
67 import com.google.common.collect.ImmutableClassToInstanceMap;
68 import com.google.common.collect.ImmutableMap;
69 import com.google.common.collect.MutableClassToInstanceMap;
70 import com.google.common.util.concurrent.ListeningExecutorService;
71
72 public class BindingTestContext implements AutoCloseable {
73
74     public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier TREE_ROOT = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
75             .builder().toInstance();
76
77     private static final Logger LOG = LoggerFactory.getLogger(BindingTestContext.class);
78
79     private RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
80
81     private DomForwardedBindingBrokerImpl baBrokerImpl;
82     private DataBrokerImpl baDataImpl;
83     private NotificationBrokerImpl baNotifyImpl;
84     private BindingIndependentConnector baConnectImpl;
85
86     private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
87     private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataLegacyBroker;
88     private BrokerImpl biBrokerImpl;
89     private HashMapDataStore rawDataStore;
90     private SchemaAwareDataStoreAdapter schemaAwareDataStore;
91     private DataStoreStatsWrapper dataStoreStats;
92     private DataStore dataStore;
93
94     private final boolean dataStoreStatisticsEnabled = false;
95
96     private final ListeningExecutorService executor;
97     private final ClassPool classPool;
98
99     private final boolean startWithSchema;
100
101     private MountPointManagerImpl biMountImpl;
102
103
104
105     private ImmutableMap<LogicalDatastoreType, DOMStore> newDatastores;
106
107     private BackwardsCompatibleDataBroker biCompatibleBroker;
108
109     private DataProviderService baData;
110
111     private DOMDataBroker newDOMDataBroker;
112
113     private final MockSchemaService mockSchemaService = new MockSchemaService();
114
115
116
117     public DOMDataBroker getDomAsyncDataBroker() {
118         return newDOMDataBroker;
119     }
120
121     protected BindingTestContext(final ListeningExecutorService executor, final ClassPool classPool, final boolean startWithSchema) {
122         this.executor = executor;
123         this.classPool = classPool;
124         this.startWithSchema = startWithSchema;
125     }
126
127     @Deprecated
128     public void startDomDataStore() {
129         checkState(dataStore == null, "DataStore already started.");
130         checkState(biDataImpl != null, "Dom Data Broker not present");
131         rawDataStore = new HashMapDataStore();
132         schemaAwareDataStore = new SchemaAwareDataStoreAdapter();
133         schemaAwareDataStore.changeDelegate(rawDataStore);
134         if (dataStoreStatisticsEnabled) {
135             dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore);
136             dataStore = dataStoreStats;
137         } else {
138             dataStore = schemaAwareDataStore;
139         }
140         mockSchemaService.registerSchemaServiceListener(schemaAwareDataStore);
141         biDataImpl.registerConfigurationReader(TREE_ROOT, dataStore);
142         biDataImpl.registerOperationalReader(TREE_ROOT, dataStore);
143         biDataImpl.registerCommitHandler(TREE_ROOT, dataStore);
144     }
145
146     public void startDomDataBroker() {
147         checkState(executor != null, "Executor needs to be set");
148         biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
149         biDataImpl.setExecutor(executor);
150         biDataLegacyBroker = biDataImpl;
151     }
152
153     public void startNewDomDataBroker() {
154         checkState(executor != null, "Executor needs to be set");
155         InMemoryDOMDataStore operStore = new InMemoryDOMDataStore("OPER", executor);
156         InMemoryDOMDataStore configStore = new InMemoryDOMDataStore("CFG", executor);
157         newDatastores = ImmutableMap.<LogicalDatastoreType, DOMStore>builder()
158                 .put(LogicalDatastoreType.OPERATIONAL, operStore)
159                 .put(LogicalDatastoreType.CONFIGURATION, configStore)
160                 .build();
161
162         newDOMDataBroker = new DOMDataBrokerImpl(newDatastores, executor);
163
164         biCompatibleBroker = new BackwardsCompatibleDataBroker(newDOMDataBroker,mockSchemaService);
165
166         mockSchemaService.registerSchemaServiceListener(configStore);
167         mockSchemaService.registerSchemaServiceListener(operStore);
168         biDataLegacyBroker = biCompatibleBroker;
169     }
170
171     public void startBindingDataBroker() {
172         checkState(executor != null, "Executor needs to be set");
173         baDataImpl = new DataBrokerImpl();
174         baDataImpl.setExecutor(executor);
175         baData = baDataImpl;
176     }
177
178     public void startBindingBroker() {
179         checkState(executor != null, "Executor needs to be set");
180         checkState(baData != null, "Binding Data Broker must be started");
181         checkState(baNotifyImpl != null, "Notification Service must be started");
182         baBrokerImpl = new DomForwardedBindingBrokerImpl("test");
183
184         baBrokerImpl.getMountManager().setDataCommitExecutor(executor);
185         baBrokerImpl.getMountManager().setNotificationExecutor(executor);
186         baBrokerImpl.setRpcBroker(new RpcProviderRegistryImpl("test"));
187         baBrokerImpl.setLegacyDataBroker(baData);
188         baBrokerImpl.setNotificationBroker(baNotifyImpl);
189         baBrokerImpl.start();
190     }
191
192     public void startForwarding() {
193         checkState(baData != null, "Binding Data Broker needs to be started");
194         checkState(biDataLegacyBroker != null, "DOM Data Broker needs to be started.");
195         checkState(mappingServiceImpl != null, "DOM Mapping Service needs to be started.");
196
197         baConnectImpl = BindingDomConnectorDeployer.createConnector(getBindingToDomMappingService());
198         baConnectImpl.setDomRpcRegistry(getDomRpcRegistry());
199         baBrokerImpl.setConnector(baConnectImpl);
200         baBrokerImpl.setDomProviderContext(createMockContext());
201         baBrokerImpl.startForwarding();
202     }
203
204     private ProviderSession createMockContext() {
205
206         final ClassToInstanceMap<BrokerService> domBrokerServices = ImmutableClassToInstanceMap
207                 .<BrokerService> builder()
208                 //
209                 .put(org.opendaylight.controller.sal.core.api.data.DataProviderService.class, biDataLegacyBroker) //
210                 .put(RpcProvisionRegistry.class, biBrokerImpl.getRouter()) //
211                 .put(MountProvisionService.class, biMountImpl) //
212                 .build();
213
214         return new ProviderSession() {
215
216             @Override
217             public Future<RpcResult<CompositeNode>> rpc(final QName rpc, final CompositeNode input) {
218                 throw new UnsupportedOperationException();
219             }
220
221             @Override
222             public <T extends BrokerService> T getService(final Class<T> service) {
223                 return domBrokerServices.getInstance(service);
224             }
225
226             @Override
227             public boolean isClosed() {
228                 return false;
229             }
230
231             @Override
232             public Set<QName> getSupportedRpcs() {
233                 return null;
234             }
235
236             @Override
237             public void close() {
238             }
239
240             @Override
241             public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(
242                     final RpcRegistrationListener listener) {
243                 return null;
244             }
245
246             @Override
247             public RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation)
248                     throws IllegalArgumentException {
249                 return null;
250             }
251
252             @Override
253             public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
254                 return null;
255             }
256
257             @Override
258             public RoutedRpcRegistration addMountedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
259                 return null;
260             }
261         };
262     }
263
264     public void startBindingToDomMappingService() {
265         checkState(classPool != null, "ClassPool needs to be present");
266         mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(classPool);
267         mockSchemaService.registerSchemaServiceListener(mappingServiceImpl);
268     }
269
270     public void updateYangSchema(final String[] files) {
271         mockSchemaService.changeSchema(getContext(files));
272     }
273
274     public static String[] getAllYangFilesOnClasspath() {
275         Predicate<String> predicate = new Predicate<String>() {
276             @Override
277             public boolean apply(final String input) {
278                 return input.endsWith(".yang");
279             }
280         };
281         Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner());
282         Set<String> result = reflection.getResources(predicate);
283         return result.toArray(new String[result.size()]);
284     }
285
286     private static SchemaContext getContext(final String[] yangFiles) {
287         ClassLoader loader = BindingTestContext.class.getClassLoader();
288         List<InputStream> streams = new ArrayList<>();
289         for (String string : yangFiles) {
290             InputStream stream = loader.getResourceAsStream(string);
291             streams.add(stream);
292         }
293         YangParserImpl parser = new YangParserImpl();
294         Set<Module> modules = parser.parseYangModelsFromStreams(streams);
295         return parser.resolveSchemaContext(modules);
296     }
297
298     public void startLegacy() {
299         startBindingDataBroker();
300         startBindingNotificationBroker();
301         startBindingBroker();
302         startDomDataBroker();
303         startDomDataStore();
304         startDomBroker();
305         startDomMountPoint();
306         startBindingToDomMappingService();
307         startForwarding();
308         if (startWithSchema) {
309             loadYangSchemaFromClasspath();
310         }
311     }
312
313     public void start() {
314         startNewDomDataBroker();
315         startDomBroker();
316         startDomMountPoint();
317         startBindingToDomMappingService();
318         startNewBindingDataBroker();
319
320         startBindingNotificationBroker();
321         startBindingBroker();
322
323         startForwarding();
324         if (startWithSchema) {
325             loadYangSchemaFromClasspath();
326         }
327     }
328
329     public void startNewBindingDataBroker() {
330         ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, mappingServiceImpl,mockSchemaService, executor);
331         baData = forwarded;
332     }
333
334     private void startDomMountPoint() {
335         biMountImpl = new MountPointManagerImpl();
336         biMountImpl.setDataBroker(getDomDataBroker());
337     }
338
339     private void startDomBroker() {
340         checkState(executor != null);
341
342         SchemaAwareRpcBroker router = new SchemaAwareRpcBroker("/", mockSchemaService);
343         ClassToInstanceMap<BrokerService> services = MutableClassToInstanceMap.create();
344         biBrokerImpl = new BrokerImpl(router,services);
345
346     }
347
348     public void startBindingNotificationBroker() {
349         checkState(executor != null);
350         baNotifyImpl = new NotificationBrokerImpl(executor);
351
352     }
353
354     public void loadYangSchemaFromClasspath() {
355         String[] files = getAllYangFilesOnClasspath();
356         updateYangSchema(files);
357     }
358
359     public DataProviderService getBindingDataBroker() {
360         return baData;
361     }
362
363     public org.opendaylight.controller.sal.core.api.data.DataProviderService getDomDataBroker() {
364         return biDataLegacyBroker;
365     }
366
367     public DataStore getDomDataStore() {
368         return dataStore;
369     }
370
371     public BindingIndependentMappingService getBindingToDomMappingService() {
372         return mappingServiceImpl;
373     }
374
375     public void logDataStoreStatistics() {
376         if (dataStoreStats == null) {
377             return;
378         }
379
380         LOG.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
381                 dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(),
382                 dataStoreStats.getConfigurationReadAverageTime());
383
384         LOG.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
385                 dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(),
386                 dataStoreStats.getOperationalReadAverageTime());
387
388         LOG.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
389                 dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(),
390                 dataStoreStats.getRequestCommitAverageTime());
391     }
392
393     public RpcProviderRegistry getBindingRpcRegistry() {
394         return baBrokerImpl.getRoot();
395     }
396
397     public RpcProvisionRegistry getDomRpcRegistry() {
398         if (biBrokerImpl == null) {
399             return null;
400         }
401         return biBrokerImpl.getRouter();
402     }
403
404     public RpcImplementation getDomRpcInvoker() {
405         return biBrokerImpl.getRouter();
406     }
407
408     @Override
409     public void close() throws Exception {
410
411     }
412
413     public MountProviderService getBindingMountProviderService() {
414         return baBrokerImpl.getMountManager();
415     }
416
417     public MountProvisionService getDomMountProviderService() {
418         return biMountImpl;
419     }
420
421
422 }