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 {
194 if (baCommitHandlerRegistration != null) {
195 baCommitHandlerRegistration.close();
197 if (biCommitHandlerRegistration != null) {
198 biCommitHandlerRegistration.close();
203 private class DomToBindingTransaction implements
204 DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
206 private final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing;
207 private final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification;
209 public DomToBindingTransaction(
210 org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
211 DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification) {
213 this.backing = backing;
214 this.modification = modification;
215 bindingOpenedTransactions.put(backing.getIdentifier(), this);
219 public DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getModification() {
224 public RpcResult<Void> rollback() throws IllegalStateException {
226 return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
230 public RpcResult<Void> finish() throws IllegalStateException {
231 Future<RpcResult<TransactionStatus>> result = backing.commit();
233 RpcResult<TransactionStatus> baResult = result.get();
234 return Rpcs.<Void> getRpcResult(baResult.isSuccessful(), null, baResult.getErrors());
235 } catch (InterruptedException e) {
236 throw new IllegalStateException("", e);
237 } catch (ExecutionException e) {
238 throw new IllegalStateException("", e);
243 private class BindingToDomTransaction implements
244 DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
246 private DataModificationTransaction backing;
247 private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
249 public BindingToDomTransaction(DataModificationTransaction backing,
250 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
251 this.backing = backing;
252 this.modification = modification;
253 domOpenedTransactions.put(backing.getIdentifier(), this);
257 public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
262 public RpcResult<Void> finish() throws IllegalStateException {
263 Future<RpcResult<TransactionStatus>> result = backing.commit();
265 RpcResult<TransactionStatus> biResult = result.get();
266 return Rpcs.<Void> getRpcResult(biResult.isSuccessful(), null, biResult.getErrors());
267 } catch (InterruptedException e) {
268 throw new IllegalStateException("", e);
269 } catch (ExecutionException e) {
270 throw new IllegalStateException("", e);
272 domOpenedTransactions.remove(backing.getIdentifier());
277 public RpcResult<Void> rollback() throws IllegalStateException {
278 domOpenedTransactions.remove(backing.getIdentifier());
279 return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
283 private class BindingToDomCommitHandler implements
284 DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
287 public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
288 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
291 * Transaction was created as DOM transaction, in that case we do
292 * not need to forward it back.
294 if (bindingOpenedTransactions.containsKey(bindingTransaction.getIdentifier())) {
296 return CommitHandlersTransactions.allwaysSuccessfulTransaction(bindingTransaction);
298 DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction);
299 BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction);
300 LOG.info("Forwarding Binding Transaction: {} as DOM Transaction: {} .", bindingTransaction.getIdentifier(),
301 domTransaction.getIdentifier());
306 private class DomToBindingCommitHandler implements //
307 RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject>>, //
308 DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
311 public void onRegister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
313 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration
315 // FIXME: do registration based on only active commit handlers.
320 public void onUnregister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
322 // FIXME: do registration based on only active commit handlers.
325 public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> requestCommit(
326 DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
327 Object identifier = domTransaction.getIdentifier();
330 * We checks if the transcation was originated in this mapper. If it
331 * was originated in this mapper we are returing allways success
332 * commit hanlder to prevent creating loop in two-phase commit and
335 if (domOpenedTransactions.containsKey(identifier)) {
336 return CommitHandlersTransactions.allwaysSuccessfulTransaction(domTransaction);
339 org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction baTransaction = createDomToBindingTransaction(domTransaction);
340 DomToBindingTransaction forwardedTransaction = new DomToBindingTransaction(baTransaction, domTransaction);
341 LOG.info("Forwarding DOM Transaction: {} as Binding Transaction: {}.", domTransaction.getIdentifier(),
342 baTransaction.getIdentifier());
343 return forwardedTransaction;