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, //
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) {
62 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
63 CompositeNode result = biDataService.readOperationalData(biPath);
64 return mappingService.dataObjectFromDataDom(path, result);
68 public DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
69 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
70 CompositeNode result = biDataService.readConfigurationData(biPath);
71 return mappingService.dataObjectFromDataDom(path, result);
74 private DataModificationTransaction createBindingToDomTransaction(
75 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
76 DataModificationTransaction target = biDataService.beginTransaction();
77 for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
79 Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
81 target.putConfigurationData(biEntry.getKey(), biEntry.getValue());
83 for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedOperationalData()
85 Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
87 target.putOperationalData(biEntry.getKey(), biEntry.getValue());
89 for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
90 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
91 target.removeConfigurationData(biEntry);
93 for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
94 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
95 target.removeOperationalData(biEntry);
100 private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction(
101 DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
102 org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService
104 for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
105 .getUpdatedConfigurationData().entrySet()) {
106 InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
107 DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
108 target.putConfigurationData(baKey, baData);
110 for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
111 .getUpdatedOperationalData().entrySet()) {
112 InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
113 DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
114 target.putOperationalData(baKey, baData);
116 for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
117 InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
118 target.removeConfigurationData(baEntry);
120 for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
121 InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
122 target.removeOperationalData(baEntry);
127 public org.opendaylight.controller.sal.core.api.data.DataProviderService getBiDataService() {
128 return biDataService;
131 public void setBiDataService(org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
132 this.biDataService = biDataService;
135 public DataProviderService getBaDataService() {
136 return baDataService;
139 public void setBaDataService(DataProviderService baDataService) {
140 this.baDataService = baDataService;
143 public void start() {
144 baDataService.registerDataReader(ROOT, this);
145 baCommitHandlerRegistration = baDataService.registerCommitHandler(ROOT, bindingToDomCommitHandler);
146 biCommitHandlerRegistration = biDataService.registerCommitHandler(ROOT_BI, domToBindingCommitHandler);
147 baDataService.registerCommitHandlerListener(domToBindingCommitHandler);
150 public void setMappingService(BindingIndependentMappingService mappingService) {
151 this.mappingService = mappingService;
155 public Collection<ProviderFunctionality> getProviderFunctionality() {
156 return Collections.emptyList();
160 public void onSessionInitiated(ProviderSession session) {
161 setBiDataService(session.getService(org.opendaylight.controller.sal.core.api.data.DataProviderService.class));
165 private class DomToBindingTransaction implements
166 DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
168 private final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing;
169 private final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification;
171 public DomToBindingTransaction(
172 org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
173 DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification) {
175 this.backing = backing;
176 this.modification = modification;
177 bindingOpenedTransactions.put(backing.getIdentifier(), this);
181 public DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getModification() {
186 public RpcResult<Void> rollback() throws IllegalStateException {
188 return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
192 public RpcResult<Void> finish() throws IllegalStateException {
193 Future<RpcResult<TransactionStatus>> result = backing.commit();
195 RpcResult<TransactionStatus> baResult = result.get();
196 return Rpcs.<Void> getRpcResult(baResult.isSuccessful(), null, baResult.getErrors());
197 } catch (InterruptedException e) {
198 throw new IllegalStateException("", e);
199 } catch (ExecutionException e) {
200 throw new IllegalStateException("", e);
205 private class BindingToDomTransaction implements
206 DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
208 private DataModificationTransaction backing;
209 private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
211 public BindingToDomTransaction(DataModificationTransaction backing,
212 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
213 this.backing = backing;
214 this.modification = modification;
215 domOpenedTransactions.put(backing.getIdentifier(), this);
219 public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
224 public RpcResult<Void> finish() throws IllegalStateException {
225 Future<RpcResult<TransactionStatus>> result = backing.commit();
227 RpcResult<TransactionStatus> biResult = result.get();
228 return Rpcs.<Void> getRpcResult(biResult.isSuccessful(), null, biResult.getErrors());
229 } catch (InterruptedException e) {
230 throw new IllegalStateException("", e);
231 } catch (ExecutionException e) {
232 throw new IllegalStateException("", e);
234 domOpenedTransactions.remove(backing.getIdentifier());
239 public RpcResult<Void> rollback() throws IllegalStateException {
240 domOpenedTransactions.remove(backing.getIdentifier());
241 return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
245 private class BindingToDomCommitHandler implements
246 DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
249 public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
250 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
253 * Transaction was created as DOM transaction, in that case we do
254 * not need to forward it back.
256 if (bindingOpenedTransactions.containsKey(bindingTransaction.getIdentifier())) {
258 return CommitHandlersTransactions.allwaysSuccessfulTransaction(bindingTransaction);
260 DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction);
261 BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction);
262 LOG.info("Forwarding Binding Transaction: {} as DOM Transaction: {} .", bindingTransaction.getIdentifier(),
263 domTransaction.getIdentifier());
268 private class DomToBindingCommitHandler implements //
269 RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject>>, //
270 DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
273 public void onRegister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
275 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration.getPath());
276 // FIXME: do registration based on only active commit handlers.
281 public void onUnregister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
283 // FIXME: do registration based on only active commit handlers.
286 public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> requestCommit(
287 DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
288 Object identifier = domTransaction.getIdentifier();
291 * We checks if the transcation was originated in this mapper. If it
292 * was originated in this mapper we are returing allways success
293 * commit hanlder to prevent creating loop in two-phase commit and
296 if (domOpenedTransactions.containsKey(identifier)) {
297 return CommitHandlersTransactions.allwaysSuccessfulTransaction(domTransaction);
300 org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction baTransaction = createDomToBindingTransaction(domTransaction);
301 DomToBindingTransaction forwardedTransaction = new DomToBindingTransaction(baTransaction, domTransaction);
302 LOG.info("Forwarding DOM Transaction: {} as Binding Transaction: {}.", domTransaction.getIdentifier(),
303 baTransaction.getIdentifier());
304 return forwardedTransaction;