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.Augmentable;
26 import org.opendaylight.yangtools.yang.binding.Augmentation;
27 import org.opendaylight.yangtools.yang.binding.DataObject;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29 import org.opendaylight.yangtools.yang.common.RpcError;
30 import org.opendaylight.yangtools.yang.common.RpcResult;
31 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
35 public class BindingIndependentDataServiceConnector implements //
36 RuntimeDataProvider, //
37 Provider, AutoCloseable {
39 private final Logger LOG = LoggerFactory.getLogger(BindingIndependentDataServiceConnector.class);
41 private static final InstanceIdentifier<? extends DataObject> ROOT = InstanceIdentifier.builder().toInstance();
43 private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ROOT_BI = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
44 .builder().toInstance();
46 private BindingIndependentMappingService mappingService;
48 private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
50 private DataProviderService baDataService;
52 private ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions = new ConcurrentHashMap<>();
53 private ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions = new ConcurrentHashMap<>();
55 private BindingToDomCommitHandler bindingToDomCommitHandler = new BindingToDomCommitHandler();
56 private DomToBindingCommitHandler domToBindingCommitHandler = new DomToBindingCommitHandler();
58 private Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> baCommitHandlerRegistration;
60 private Registration<DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode>> biCommitHandlerRegistration;
63 public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
65 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
68 CompositeNode result = biDataService.readOperationalData(biPath);
69 Class<? extends DataObject> targetType = path.getTargetType();
71 if(Augmentation.class.isAssignableFrom(targetType)) {
72 path = mappingService.fromDataDom(biPath);
73 Class<? extends Augmentation<?>> augmentType = (Class<? extends Augmentation<?>>) targetType;
74 DataObject parentTo = mappingService.dataObjectFromDataDom(path, result);
75 if(parentTo instanceof Augmentable<?>) {
76 return (DataObject) ((Augmentable) parentTo).getAugmentation(augmentType);
80 return mappingService.dataObjectFromDataDom(path, result);
82 } catch (DeserializationException e) {
83 throw new IllegalStateException(e);
88 public DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
90 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
91 CompositeNode result = biDataService.readConfigurationData(biPath);
92 return mappingService.dataObjectFromDataDom(path, result);
93 } catch (DeserializationException e) {
94 throw new IllegalStateException(e);
98 private DataModificationTransaction createBindingToDomTransaction(
99 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
100 DataModificationTransaction target = biDataService.beginTransaction();
101 for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
103 Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
105 target.putConfigurationData(biEntry.getKey(), biEntry.getValue());
107 for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedOperationalData()
109 Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
111 target.putOperationalData(biEntry.getKey(), biEntry.getValue());
113 for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
114 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
115 target.removeConfigurationData(biEntry);
117 for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
118 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
119 target.removeOperationalData(biEntry);
124 private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction(
125 DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
126 org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService
128 for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
129 .getUpdatedConfigurationData().entrySet()) {
131 InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
132 DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
133 target.putConfigurationData(baKey, baData);
134 } catch (DeserializationException e) {
135 LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
138 for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
139 .getUpdatedOperationalData().entrySet()) {
142 InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
143 DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
144 target.putOperationalData(baKey, baData);
145 } catch (DeserializationException e) {
146 LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
149 for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
152 InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
153 target.removeConfigurationData(baEntry);
154 } catch (DeserializationException e) {
155 LOG.error("Ommiting from BA transaction: {}.", entry, e);
158 for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
161 InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
162 target.removeOperationalData(baEntry);
163 } catch (DeserializationException e) {
164 LOG.error("Ommiting from BA transaction: {}.", entry, e);
170 public org.opendaylight.controller.sal.core.api.data.DataProviderService getBiDataService() {
171 return biDataService;
174 public void setBiDataService(org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
175 this.biDataService = biDataService;
178 public DataProviderService getBaDataService() {
179 return baDataService;
182 public void setBaDataService(DataProviderService baDataService) {
183 this.baDataService = baDataService;
186 public void start() {
187 baDataService.registerDataReader(ROOT, this);
188 baCommitHandlerRegistration = baDataService.registerCommitHandler(ROOT, bindingToDomCommitHandler);
189 biCommitHandlerRegistration = biDataService.registerCommitHandler(ROOT_BI, domToBindingCommitHandler);
190 baDataService.registerCommitHandlerListener(domToBindingCommitHandler);
193 public void setMappingService(BindingIndependentMappingService mappingService) {
194 this.mappingService = mappingService;
198 public Collection<ProviderFunctionality> getProviderFunctionality() {
199 return Collections.emptyList();
203 public void onSessionInitiated(ProviderSession session) {
204 setBiDataService(session.getService(org.opendaylight.controller.sal.core.api.data.DataProviderService.class));
209 public void close() throws Exception {
210 if (baCommitHandlerRegistration != null) {
211 baCommitHandlerRegistration.close();
213 if (biCommitHandlerRegistration != null) {
214 biCommitHandlerRegistration.close();
219 private class DomToBindingTransaction implements
220 DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
222 private final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing;
223 private final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification;
225 public DomToBindingTransaction(
226 org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
227 DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification) {
229 this.backing = backing;
230 this.modification = modification;
231 bindingOpenedTransactions.put(backing.getIdentifier(), this);
235 public DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getModification() {
240 public RpcResult<Void> rollback() throws IllegalStateException {
242 return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
246 public RpcResult<Void> finish() throws IllegalStateException {
247 Future<RpcResult<TransactionStatus>> result = backing.commit();
249 RpcResult<TransactionStatus> baResult = result.get();
250 return Rpcs.<Void> getRpcResult(baResult.isSuccessful(), null, baResult.getErrors());
251 } catch (InterruptedException e) {
252 throw new IllegalStateException("", e);
253 } catch (ExecutionException e) {
254 throw new IllegalStateException("", e);
259 private class BindingToDomTransaction implements
260 DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
262 private DataModificationTransaction backing;
263 private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
265 public BindingToDomTransaction(DataModificationTransaction backing,
266 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
267 this.backing = backing;
268 this.modification = modification;
269 domOpenedTransactions.put(backing.getIdentifier(), this);
273 public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
278 public RpcResult<Void> finish() throws IllegalStateException {
279 Future<RpcResult<TransactionStatus>> result = backing.commit();
281 RpcResult<TransactionStatus> biResult = result.get();
282 return Rpcs.<Void> getRpcResult(biResult.isSuccessful(), null, biResult.getErrors());
283 } catch (InterruptedException e) {
284 throw new IllegalStateException("", e);
285 } catch (ExecutionException e) {
286 throw new IllegalStateException("", e);
288 domOpenedTransactions.remove(backing.getIdentifier());
293 public RpcResult<Void> rollback() throws IllegalStateException {
294 domOpenedTransactions.remove(backing.getIdentifier());
295 return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
299 private class BindingToDomCommitHandler implements
300 DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
303 public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
304 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
307 * Transaction was created as DOM transaction, in that case we do
308 * not need to forward it back.
310 if (bindingOpenedTransactions.containsKey(bindingTransaction.getIdentifier())) {
312 return CommitHandlersTransactions.allwaysSuccessfulTransaction(bindingTransaction);
314 DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction);
315 BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction);
316 LOG.info("Forwarding Binding Transaction: {} as DOM Transaction: {} .", bindingTransaction.getIdentifier(),
317 domTransaction.getIdentifier());
322 private class DomToBindingCommitHandler implements //
323 RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject>>, //
324 DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
327 public void onRegister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
329 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration
335 public void onUnregister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
337 // FIXME: do registration based on only active commit handlers.
340 public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> requestCommit(
341 DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
342 Object identifier = domTransaction.getIdentifier();
345 * We checks if the transcation was originated in this mapper. If it
346 * was originated in this mapper we are returing allways success
347 * commit hanlder to prevent creating loop in two-phase commit and
350 if (domOpenedTransactions.containsKey(identifier)) {
351 return CommitHandlersTransactions.allwaysSuccessfulTransaction(domTransaction);
354 org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction baTransaction = createDomToBindingTransaction(domTransaction);
355 DomToBindingTransaction forwardedTransaction = new DomToBindingTransaction(baTransaction, domTransaction);
356 LOG.info("Forwarding DOM Transaction: {} as Binding Transaction: {}.", domTransaction.getIdentifier(),
357 baTransaction.getIdentifier());
358 return forwardedTransaction;