X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-dom-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fmd%2Fsal%2Fdom%2Fstore%2Fimpl%2FInMemoryDOMDataStore.java;h=9bbba1e24d8600f196f23df145105d1b787e9c6e;hp=2091913f24949106aae128e07083a4354b992b70;hb=84248dac9ed8aa37e996e39429c8aa8ece473eaf;hpb=029fc5247757e94a9430f22c0ed51702ea7b51a1 diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java index 2091913f24..9bbba1e24d 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java @@ -18,8 +18,7 @@ import java.util.concurrent.atomic.AtomicReference; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener; -import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode; -import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode.DataChangeListenerRegistration; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree; import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType; import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification; import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode; @@ -27,7 +26,9 @@ import org.opendaylight.controller.sal.core.spi.data.DOMStore; import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction; import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction; import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort; +import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransaction; import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction; +import org.opendaylight.yangtools.concepts.AbstractListenerRegistration; import org.opendaylight.yangtools.concepts.Identifiable; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; @@ -39,6 +40,8 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.primitives.UnsignedLong; @@ -55,7 +58,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch private final ListeningExecutorService executor; private final String name; private final AtomicLong txCounter = new AtomicLong(0); - private final ListenerRegistrationNode listenerTree; + private final ListenerTree listenerTree; private final AtomicReference snapshot; private ModificationApplyOperation operationTree; @@ -65,7 +68,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch public InMemoryDOMDataStore(final String name, final ListeningExecutorService executor) { this.name = Preconditions.checkNotNull(name); this.executor = Preconditions.checkNotNull(executor); - this.listenerTree = ListenerRegistrationNode.createRoot(); + this.listenerTree = ListenerTree.create(); this.snapshot = new AtomicReference(DataAndMetadataSnapshot.createEmpty()); this.operationTree = new AlwaysFailOperation(); } @@ -99,11 +102,6 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch @Override public >> ListenerRegistration registerChangeListener( final InstanceIdentifier path, final L listener, final DataChangeScope scope) { - LOG.debug("{}: Registering data change listener {} for {}",name,listener,path); - ListenerRegistrationNode listenerNode = listenerTree; - for(PathArgument arg : path.getPath()) { - listenerNode = listenerNode.ensureChild(arg); - } /* * Make sure commit is not occurring right now. Listener has to be registered and its @@ -114,13 +112,15 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch */ final DataChangeListenerRegistration reg; synchronized (this) { - reg = listenerNode.registerDataChangeListener(path, listener, scope); + LOG.debug("{}: Registering data change listener {} for {}",name,listener,path); + + reg = listenerTree.registerDataChangeListener(path, listener, scope); Optional currentState = snapshot.get().read(path); if (currentState.isPresent()) { final NormalizedNode data = currentState.get().getData(); - final DOMImmutableDataChangeEvent event = DOMImmutableDataChangeEvent.builder() // + final DOMImmutableDataChangeEvent event = DOMImmutableDataChangeEvent.builder(DataChangeScope.BASE) // .setAfter(data) // .addCreated(path, data) // .build(); @@ -128,7 +128,14 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch } } - return reg; + return new AbstractListenerRegistration(listener) { + @Override + protected void removeRegistration() { + synchronized (InMemoryDOMDataStore.this) { + reg.close(); + } + } + }; } private synchronized DOMStoreThreePhaseCommitCohort submit( @@ -142,7 +149,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch } private void commit(final DataAndMetadataSnapshot currentSnapshot, - final StoreMetadataNode newDataTree, final Iterable listenerTasks) { + final StoreMetadataNode newDataTree, final ResolveDataChangeEventsTask listenerResolver) { LOG.debug("Updating Store snaphot version: {} with version:{}",currentSnapshot.getMetadataTree().getSubtreeVersion(),newDataTree.getSubtreeVersion()); if(LOG.isTraceEnabled()) { @@ -161,31 +168,53 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch final boolean success = snapshot.compareAndSet(currentSnapshot, newSnapshot); checkState(success, "Store snapshot and transaction snapshot differ. This should never happen."); - for (ChangeListenerNotifyTask task : listenerTasks) { + for (ChangeListenerNotifyTask task : listenerResolver.call()) { + LOG.trace("Scheduling invocation of listeners: {}",task); executor.submit(task); } } } - private static class SnapshotBackedReadTransaction implements DOMStoreReadTransaction { - - private DataAndMetadataSnapshot stableSnapshot; + private static abstract class AbstractDOMStoreTransaction implements DOMStoreTransaction { private final Object identifier; - public SnapshotBackedReadTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot) { + protected AbstractDOMStoreTransaction(final Object identifier) { this.identifier = identifier; - this.stableSnapshot = snapshot; - LOG.debug("ReadOnly Tx: {} allocated with snapshot {}",identifier,snapshot.getMetadataTree().getSubtreeVersion()); - } @Override - public Object getIdentifier() { + public final Object getIdentifier() { return identifier; } + @Override + public final String toString() { + return addToStringAttributes(Objects.toStringHelper(this)).toString(); + } + + /** + * Add class-specific toString attributes. + * + * @param toStringHelper ToStringHelper instance + * @return ToStringHelper instance which was passed in + */ + protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) { + return toStringHelper.add("id", identifier); + } + } + + private static class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements DOMStoreReadTransaction { + private DataAndMetadataSnapshot stableSnapshot; + + public SnapshotBackedReadTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot) { + super(identifier); + this.stableSnapshot = Preconditions.checkNotNull(snapshot); + LOG.debug("ReadOnly Tx: {} allocated with snapshot {}", identifier, snapshot.getMetadataTree().getSubtreeVersion()); + } + @Override public void close() { + LOG.debug("Store transaction: {} : Closed", getIdentifier()); stableSnapshot = null; } @@ -195,37 +224,24 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch checkState(stableSnapshot != null, "Transaction is closed"); return Futures.immediateFuture(NormalizedNodeUtils.findNode(stableSnapshot.getDataTree(), path)); } - - @Override - public String toString() { - return "SnapshotBackedReadTransaction [id =" + identifier + "]"; - } - } - private static class SnaphostBackedWriteTransaction implements DOMStoreWriteTransaction { - + private static class SnaphostBackedWriteTransaction extends AbstractDOMStoreTransaction implements DOMStoreWriteTransaction { private MutableDataTree mutableTree; - private final Object identifier; private InMemoryDOMDataStore store; - private boolean ready = false; public SnaphostBackedWriteTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot, final InMemoryDOMDataStore store, final ModificationApplyOperation applyOper) { - this.identifier = identifier; + super(identifier); mutableTree = MutableDataTree.from(snapshot, applyOper); this.store = store; LOG.debug("Write Tx: {} allocated with snapshot {}",identifier,snapshot.getMetadataTree().getSubtreeVersion()); } - @Override - public Object getIdentifier() { - return identifier; - } - @Override public void close() { + LOG.debug("Store transaction: {} : Closed", getIdentifier()); this.mutableTree = null; this.store = null; } @@ -233,26 +249,52 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch @Override public void write(final InstanceIdentifier path, final NormalizedNode data) { checkNotReady(); - mutableTree.write(path, data); + try { + LOG.trace("Tx: {} Write: {}:{}",getIdentifier(),path,data); + mutableTree.write(path, data); + // FIXME: Add checked exception + } catch (Exception e) { + LOG.error("Tx: {}, failed to write {}:{} in {}",getIdentifier(),path,data,mutableTree,e); + } + } + + @Override + public void merge(final InstanceIdentifier path, final NormalizedNode data) { + checkNotReady(); + try { + LOG.trace("Tx: {} Merge: {}:{}",getIdentifier(),path,data); + mutableTree.merge(path, data); + // FIXME: Add checked exception + } catch (Exception e) { + LOG.error("Tx: {}, failed to write {}:{} in {}",getIdentifier(),path,data,mutableTree,e); + } } @Override public void delete(final InstanceIdentifier path) { checkNotReady(); - mutableTree.delete(path); + try { + LOG.trace("Tx: {} Delete: {}",getIdentifier(),path); + mutableTree.delete(path); + // FIXME: Add checked exception + } catch (Exception e) { + LOG.error("Tx: {}, failed to delete {} in {}",getIdentifier(),path,mutableTree,e); + } } - protected boolean isReady() { + protected final boolean isReady() { return ready; } - protected void checkNotReady() { - checkState(!ready, "Transaction is ready. No further modifications allowed."); + protected final void checkNotReady() { + checkState(!ready, "Transaction %s is ready. No further modifications allowed.", getIdentifier()); } @Override public synchronized DOMStoreThreePhaseCommitCohort ready() { + checkState(!ready, "Transaction %s is already ready.", getIdentifier()); ready = true; + LOG.debug("Store transaction: {} : Ready", getIdentifier()); mutableTree.seal(); return store.submit(this); @@ -263,10 +305,9 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch } @Override - public String toString() { - return "SnaphostBackedWriteTransaction [id=" + getIdentifier() + ", ready=" + isReady() + "]"; + protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) { + return toStringHelper.add("ready", isReady()); } - } private static class SnapshotBackedReadWriteTransaction extends SnaphostBackedWriteTransaction implements @@ -279,14 +320,14 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch @Override public ListenableFuture>> read(final InstanceIdentifier path) { - return Futures.immediateFuture(getMutatedView().read(path)); - } - - @Override - public String toString() { - return "SnapshotBackedReadWriteTransaction [id=" + getIdentifier() + ", ready=" + isReady() + "]"; + LOG.trace("Tx: {} Read: {}",getIdentifier(),path); + try { + return Futures.immediateFuture(getMutatedView().read(path)); + } catch (Exception e) { + LOG.error("Tx: {} Failed Read of {}",getIdentifier(),path,e); + throw e; + } } - } private class ThreePhaseCommitImpl implements DOMStoreThreePhaseCommitCohort { @@ -296,7 +337,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch private DataAndMetadataSnapshot storeSnapshot; private Optional proposedSubtree; - private Iterable listenerTasks; + private ResolveDataChangeEventsTask listenerResolver; public ThreePhaseCommitImpl(final SnaphostBackedWriteTransaction writeTransaction) { this.transaction = writeTransaction; @@ -337,13 +378,12 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch proposedSubtree = operationTree.apply(modification, Optional.of(metadataTree), increase(metadataTree.getSubtreeVersion())); - listenerTasks = DataChangeEventResolver.create() // + listenerResolver = ResolveDataChangeEventsTask.create() // .setRootPath(PUBLIC_ROOT_PATH) // .setBeforeRoot(Optional.of(metadataTree)) // .setAfterRoot(proposedSubtree) // .setModificationRoot(modification) // - .setListenerRoot(listenerTree) // - .resolve(); + .setListenerRoot(listenerTree); return null; } @@ -366,7 +406,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch checkState(proposedSubtree != null,"Proposed subtree must be computed"); checkState(storeSnapshot != null,"Proposed subtree must be computed"); // return ImmediateFuture<>; - InMemoryDOMDataStore.this.commit(storeSnapshot, proposedSubtree.get(),listenerTasks); + InMemoryDOMDataStore.this.commit(storeSnapshot, proposedSubtree.get(),listenerResolver); return Futures. immediateFuture(null); }