X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-binding-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Fbinding%2Fimpl%2Fconnect%2Fdom%2FBindingIndependentDataServiceConnector.java;h=ccd6079cc997b00b9de8a2a6f5ee935155f01340;hp=ff897aa41de0a6e474bb1db876c1cdfbca3a920c;hb=3979e330c9f95a898c54a9234f3a07e3b2ae4349;hpb=13efd0b8e167e8aadd531b5ec0e72572a72bc249 diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java index ff897aa41d..ccd6079cc9 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java @@ -1,44 +1,64 @@ package org.opendaylight.controller.sal.binding.impl.connect.dom; +import java.util.Collection; import java.util.Collections; +import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; -import org.opendaylight.controller.config.api.jmx.CommitStatus; +import org.opendaylight.controller.md.sal.common.api.RegistrationListener; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler; -import org.opendaylight.controller.md.sal.common.api.data.DataModification; -import org.opendaylight.controller.md.sal.common.api.data.DataReader; import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction; +import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration; +import org.opendaylight.controller.md.sal.common.api.data.DataModification; import org.opendaylight.controller.sal.binding.api.data.DataProviderService; import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider; import org.opendaylight.controller.sal.common.util.Rpcs; -import org.opendaylight.controller.sal.core.api.data.DataBrokerService; +import org.opendaylight.controller.sal.core.api.Provider; +import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction; +import org.opendaylight.yangtools.concepts.Registration; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; - -import com.google.common.base.Preconditions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class BindingIndependentDataServiceConnector implements // RuntimeDataProvider, // - DataCommitHandler, DataObject> { + Provider { + + private final Logger LOG = LoggerFactory.getLogger(BindingIndependentDataServiceConnector.class); private static final InstanceIdentifier ROOT = InstanceIdentifier.builder().toInstance(); + private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ROOT_BI = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier + .builder().toInstance(); + private BindingIndependentMappingService mappingService; - private DataBrokerService biDataService; + private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService; private DataProviderService baDataService; + private ConcurrentMap domOpenedTransactions = new ConcurrentHashMap<>(); + private ConcurrentMap bindingOpenedTransactions = new ConcurrentHashMap<>(); + + private BindingToDomCommitHandler bindingToDomCommitHandler = new BindingToDomCommitHandler(); + private DomToBindingCommitHandler domToBindingCommitHandler = new DomToBindingCommitHandler(); + + private Registration, DataObject>> baCommitHandlerRegistration; + + private Registration> biCommitHandlerRegistration; + @Override public DataObject readOperationalData(InstanceIdentifier path) { - // TODO Auto-generated method stub org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path); CompositeNode result = biDataService.readOperationalData(biPath); return mappingService.dataObjectFromDataDom(path, result); @@ -51,15 +71,7 @@ public class BindingIndependentDataServiceConnector implements // return mappingService.dataObjectFromDataDom(path, result); } - @Override - public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction, DataObject> requestCommit( - DataModification, DataObject> modification) { - - DataModificationTransaction translated = translateTransaction(modification); - return new WrappedTransaction(translated, modification); - } - - private DataModificationTransaction translateTransaction( + private DataModificationTransaction createBindingToDomTransaction( DataModification, DataObject> source) { DataModificationTransaction target = biDataService.beginTransaction(); for (Entry, DataObject> entry : source.getUpdatedConfigurationData() @@ -74,27 +86,133 @@ public class BindingIndependentDataServiceConnector implements // .toDataDom(entry); target.putOperationalData(biEntry.getKey(), biEntry.getValue()); } - for(InstanceIdentifier entry : source.getRemovedConfigurationData()) { + for (InstanceIdentifier entry : source.getRemovedConfigurationData()) { org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry); target.removeConfigurationData(biEntry); } - for(InstanceIdentifier entry : source.getRemovedOperationalData()) { + for (InstanceIdentifier entry : source.getRemovedOperationalData()) { org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry); target.removeOperationalData(biEntry); } return target; } - private class WrappedTransaction implements + private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction( + DataModification source) { + org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService + .beginTransaction(); + for (Entry entry : source + .getUpdatedConfigurationData().entrySet()) { + InstanceIdentifier baKey = mappingService.fromDataDom(entry.getKey()); + DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue()); + target.putConfigurationData(baKey, baData); + } + for (Entry entry : source + .getUpdatedOperationalData().entrySet()) { + InstanceIdentifier baKey = mappingService.fromDataDom(entry.getKey()); + DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue()); + target.putOperationalData(baKey, baData); + } + for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) { + InstanceIdentifier baEntry = mappingService.fromDataDom(entry); + target.removeConfigurationData(baEntry); + } + for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) { + InstanceIdentifier baEntry = mappingService.fromDataDom(entry); + target.removeOperationalData(baEntry); + } + return target; + } + + public org.opendaylight.controller.sal.core.api.data.DataProviderService getBiDataService() { + return biDataService; + } + + public void setBiDataService(org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) { + this.biDataService = biDataService; + } + + public DataProviderService getBaDataService() { + return baDataService; + } + + public void setBaDataService(DataProviderService baDataService) { + this.baDataService = baDataService; + } + + public void start() { + baDataService.registerDataReader(ROOT, this); + baCommitHandlerRegistration = baDataService.registerCommitHandler(ROOT, bindingToDomCommitHandler); + biCommitHandlerRegistration = biDataService.registerCommitHandler(ROOT_BI, domToBindingCommitHandler); + baDataService.registerCommitHandlerListener(domToBindingCommitHandler); + } + + public void setMappingService(BindingIndependentMappingService mappingService) { + this.mappingService = mappingService; + } + + @Override + public Collection getProviderFunctionality() { + return Collections.emptyList(); + } + + @Override + public void onSessionInitiated(ProviderSession session) { + setBiDataService(session.getService(org.opendaylight.controller.sal.core.api.data.DataProviderService.class)); + start(); + } + + private class DomToBindingTransaction implements + DataCommitTransaction { + + private final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing; + private final DataModification modification; + + public DomToBindingTransaction( + org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing, + DataModification modification) { + super(); + this.backing = backing; + this.modification = modification; + bindingOpenedTransactions.put(backing.getIdentifier(), this); + } + + @Override + public DataModification getModification() { + return modification; + } + + @Override + public RpcResult rollback() throws IllegalStateException { + // backing.cancel(); + return Rpcs. getRpcResult(true, null, Collections. emptySet()); + } + + @Override + public RpcResult finish() throws IllegalStateException { + Future> result = backing.commit(); + try { + RpcResult baResult = result.get(); + return Rpcs. getRpcResult(baResult.isSuccessful(), null, baResult.getErrors()); + } catch (InterruptedException e) { + throw new IllegalStateException("", e); + } catch (ExecutionException e) { + throw new IllegalStateException("", e); + } + } + } + + private class BindingToDomTransaction implements DataCommitTransaction, DataObject> { private DataModificationTransaction backing; private DataModification, DataObject> modification; - public WrappedTransaction(DataModificationTransaction backing, + public BindingToDomTransaction(DataModificationTransaction backing, DataModification, DataObject> modification) { this.backing = backing; this.modification = modification; + domOpenedTransactions.put(backing.getIdentifier(), this); } @Override @@ -106,46 +224,84 @@ public class BindingIndependentDataServiceConnector implements // public RpcResult finish() throws IllegalStateException { Future> result = backing.commit(); try { - RpcResult biresult = result.get(); + RpcResult biResult = result.get(); + return Rpcs. getRpcResult(biResult.isSuccessful(), null, biResult.getErrors()); } catch (InterruptedException e) { throw new IllegalStateException("", e); } catch (ExecutionException e) { throw new IllegalStateException("", e); + } finally { + domOpenedTransactions.remove(backing.getIdentifier()); } - return Rpcs. getRpcResult(true, null, Collections. emptySet()); } @Override public RpcResult rollback() throws IllegalStateException { - // backing.cancel(); + domOpenedTransactions.remove(backing.getIdentifier()); return Rpcs. getRpcResult(true, null, Collections. emptySet()); } - } - public DataBrokerService getBiDataService() { - return biDataService; - } + private class BindingToDomCommitHandler implements + DataCommitHandler, DataObject> { - public void setBiDataService(DataBrokerService biDataService) { - this.biDataService = biDataService; - } + @Override + public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction, DataObject> requestCommit( + DataModification, DataObject> bindingTransaction) { - public DataProviderService getBaDataService() { - return baDataService; - } + /** + * Transaction was created as DOM transaction, in that case we do + * not need to forward it back. + */ + if (bindingOpenedTransactions.containsKey(bindingTransaction.getIdentifier())) { - public void setBaDataService(DataProviderService baDataService) { - this.baDataService = baDataService; + return CommitHandlersTransactions.allwaysSuccessfulTransaction(bindingTransaction); + } + DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction); + BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction); + LOG.info("Forwarding Binding Transaction: {} as DOM Transaction: {} .", bindingTransaction.getIdentifier(), + domTransaction.getIdentifier()); + return wrapped; + } } - public void start() { - baDataService.registerDataReader(ROOT, this); - baDataService.registerCommitHandler(ROOT, this); - } + private class DomToBindingCommitHandler implements // + RegistrationListener, DataObject>>, // + DataCommitHandler { - public void setMappingService(BindingIndependentMappingService mappingService) { - this.mappingService = mappingService; - } + @Override + public void onRegister(DataCommitHandlerRegistration, DataObject> registration) { + + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration.getPath()); + // FIXME: do registration based on only active commit handlers. + + } + @Override + public void onUnregister(DataCommitHandlerRegistration, DataObject> registration) { + // NOOP for now + // FIXME: do registration based on only active commit handlers. + } + + public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction requestCommit( + DataModification domTransaction) { + Object identifier = domTransaction.getIdentifier(); + + /** + * We checks if the transcation was originated in this mapper. If it + * was originated in this mapper we are returing allways success + * commit hanlder to prevent creating loop in two-phase commit and + * duplicating data. + */ + if (domOpenedTransactions.containsKey(identifier)) { + return CommitHandlersTransactions.allwaysSuccessfulTransaction(domTransaction); + } + + org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction baTransaction = createDomToBindingTransaction(domTransaction); + DomToBindingTransaction forwardedTransaction = new DomToBindingTransaction(baTransaction, domTransaction); + LOG.info("Forwarding DOM Transaction: {} as Binding Transaction: {}.", domTransaction.getIdentifier(), + baTransaction.getIdentifier()); + return forwardedTransaction; + } + } }