1 package org.opendaylight.controller.sal.binding.impl.connect.dom;
3 import java.util.Collection;
4 import java.util.Collections;
6 import java.util.Map.Entry;
7 import java.util.concurrent.ConcurrentHashMap;
8 import java.util.concurrent.ConcurrentMap;
9 import java.util.concurrent.ExecutionException;
10 import java.util.concurrent.Future;
12 import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
13 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
14 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
15 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
16 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
17 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
18 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
19 import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
20 import org.opendaylight.controller.sal.common.util.Rpcs;
21 import org.opendaylight.controller.sal.core.api.Provider;
22 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
23 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
24 import org.opendaylight.yangtools.concepts.Registration;
25 import org.opendaylight.yangtools.yang.binding.DataObject;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.opendaylight.yangtools.yang.common.RpcError;
28 import org.opendaylight.yangtools.yang.common.RpcResult;
29 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 public class BindingIndependentDataServiceConnector implements //
34 RuntimeDataProvider, //
35 Provider, AutoCloseable {
37 private final Logger LOG = LoggerFactory.getLogger(BindingIndependentDataServiceConnector.class);
39 private static final InstanceIdentifier<? extends DataObject> ROOT = InstanceIdentifier.builder().toInstance();
41 private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ROOT_BI = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
42 .builder().toInstance();
44 private BindingIndependentMappingService mappingService;
46 private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
48 private DataProviderService baDataService;
50 private ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions = new ConcurrentHashMap<>();
51 private ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions = new ConcurrentHashMap<>();
53 private BindingToDomCommitHandler bindingToDomCommitHandler = new BindingToDomCommitHandler();
54 private DomToBindingCommitHandler domToBindingCommitHandler = new DomToBindingCommitHandler();
56 private Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> baCommitHandlerRegistration;
58 private Registration<DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode>> biCommitHandlerRegistration;
61 public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
63 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
64 CompositeNode result = biDataService.readOperationalData(biPath);
65 return mappingService.dataObjectFromDataDom(path, result);
66 } catch (DeserializationException e) {
67 throw new IllegalStateException(e);
72 public DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
74 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
75 CompositeNode result = biDataService.readConfigurationData(biPath);
76 return mappingService.dataObjectFromDataDom(path, result);
77 } catch (DeserializationException e) {
78 throw new IllegalStateException(e);
82 private DataModificationTransaction createBindingToDomTransaction(
83 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
84 DataModificationTransaction target = biDataService.beginTransaction();
85 for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
87 Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
89 target.putConfigurationData(biEntry.getKey(), biEntry.getValue());
91 for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedOperationalData()
93 Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
95 target.putOperationalData(biEntry.getKey(), biEntry.getValue());
97 for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
98 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
99 target.removeConfigurationData(biEntry);
101 for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
102 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
103 target.removeOperationalData(biEntry);
108 private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction(
109 DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
110 org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService
112 for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
113 .getUpdatedConfigurationData().entrySet()) {
115 InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
116 DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
117 target.putConfigurationData(baKey, baData);
118 } catch (DeserializationException e) {
119 LOG.error("Ommiting from BA transaction: {}. Reason{}.", entry.getKey(), e);
122 for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
123 .getUpdatedOperationalData().entrySet()) {
126 InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
127 DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
128 target.putOperationalData(baKey, baData);
129 } catch (DeserializationException e) {
130 LOG.error("Ommiting from BA transaction: {}. Reason{}.", entry.getKey(), e);
133 for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
136 InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
137 target.removeConfigurationData(baEntry);
138 } catch (DeserializationException e) {
139 LOG.error("Ommiting from BA transaction: {}. Reason{}.", entry, e);
142 for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
145 InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
146 target.removeOperationalData(baEntry);
147 } catch (DeserializationException e) {
148 LOG.error("Ommiting from BA transaction: {}. Reason{}.", entry, e);
154 public org.opendaylight.controller.sal.core.api.data.DataProviderService getBiDataService() {
155 return biDataService;
158 public void setBiDataService(org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
159 this.biDataService = biDataService;
162 public DataProviderService getBaDataService() {
163 return baDataService;
166 public void setBaDataService(DataProviderService baDataService) {
167 this.baDataService = baDataService;
170 public void start() {
171 baDataService.registerDataReader(ROOT, this);
172 baCommitHandlerRegistration = baDataService.registerCommitHandler(ROOT, bindingToDomCommitHandler);
173 biCommitHandlerRegistration = biDataService.registerCommitHandler(ROOT_BI, domToBindingCommitHandler);
174 baDataService.registerCommitHandlerListener(domToBindingCommitHandler);
177 public void setMappingService(BindingIndependentMappingService mappingService) {
178 this.mappingService = mappingService;
182 public Collection<ProviderFunctionality> getProviderFunctionality() {
183 return Collections.emptyList();
187 public void onSessionInitiated(ProviderSession session) {
188 setBiDataService(session.getService(org.opendaylight.controller.sal.core.api.data.DataProviderService.class));
193 public void close() throws Exception {
195 if (baCommitHandlerRegistration != null) {
196 baCommitHandlerRegistration.close();
198 if (biCommitHandlerRegistration != null) {
199 biCommitHandlerRegistration.close();
204 private class DomToBindingTransaction implements
205 DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
207 private final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing;
208 private final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification;
210 public DomToBindingTransaction(
211 org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
212 DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification) {
214 this.backing = backing;
215 this.modification = modification;
216 bindingOpenedTransactions.put(backing.getIdentifier(), this);
220 public DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getModification() {
225 public RpcResult<Void> rollback() throws IllegalStateException {
227 return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
231 public RpcResult<Void> finish() throws IllegalStateException {
232 Future<RpcResult<TransactionStatus>> result = backing.commit();
234 RpcResult<TransactionStatus> baResult = result.get();
235 return Rpcs.<Void> getRpcResult(baResult.isSuccessful(), null, baResult.getErrors());
236 } catch (InterruptedException e) {
237 throw new IllegalStateException("", e);
238 } catch (ExecutionException e) {
239 throw new IllegalStateException("", e);
244 private class BindingToDomTransaction implements
245 DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
247 private DataModificationTransaction backing;
248 private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
250 public BindingToDomTransaction(DataModificationTransaction backing,
251 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
252 this.backing = backing;
253 this.modification = modification;
254 domOpenedTransactions.put(backing.getIdentifier(), this);
258 public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
263 public RpcResult<Void> finish() throws IllegalStateException {
264 Future<RpcResult<TransactionStatus>> result = backing.commit();
266 RpcResult<TransactionStatus> biResult = result.get();
267 return Rpcs.<Void> getRpcResult(biResult.isSuccessful(), null, biResult.getErrors());
268 } catch (InterruptedException e) {
269 throw new IllegalStateException("", e);
270 } catch (ExecutionException e) {
271 throw new IllegalStateException("", e);
273 domOpenedTransactions.remove(backing.getIdentifier());
278 public RpcResult<Void> rollback() throws IllegalStateException {
279 domOpenedTransactions.remove(backing.getIdentifier());
280 return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
284 private class BindingToDomCommitHandler implements
285 DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
288 public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
289 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
292 * Transaction was created as DOM transaction, in that case we do
293 * not need to forward it back.
295 if (bindingOpenedTransactions.containsKey(bindingTransaction.getIdentifier())) {
297 return CommitHandlersTransactions.allwaysSuccessfulTransaction(bindingTransaction);
299 DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction);
300 BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction);
301 LOG.info("Forwarding Binding Transaction: {} as DOM Transaction: {} .", bindingTransaction.getIdentifier(),
302 domTransaction.getIdentifier());
307 private class DomToBindingCommitHandler implements //
308 RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject>>, //
309 DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
312 public void onRegister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
314 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration
316 // FIXME: do registration based on only active commit handlers.
321 public void onUnregister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
323 // FIXME: do registration based on only active commit handlers.
326 public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> requestCommit(
327 DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
328 Object identifier = domTransaction.getIdentifier();
331 * We checks if the transcation was originated in this mapper. If it
332 * was originated in this mapper we are returing allways success
333 * commit hanlder to prevent creating loop in two-phase commit and
336 if (domOpenedTransactions.containsKey(identifier)) {
337 return CommitHandlersTransactions.allwaysSuccessfulTransaction(domTransaction);
340 org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction baTransaction = createDomToBindingTransaction(domTransaction);
341 DomToBindingTransaction forwardedTransaction = new DomToBindingTransaction(baTransaction, domTransaction);
342 LOG.info("Forwarding DOM Transaction: {} as Binding Transaction: {}.", domTransaction.getIdentifier(),
343 baTransaction.getIdentifier());
344 return forwardedTransaction;