*/
package org.opendaylight.controller.cluster.datastore;
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import java.util.AbstractMap.SimpleEntry;
import java.util.HashMap;
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.api.DOMDataTreeChangeListener;
-import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent;
+import org.opendaylight.controller.md.sal.dom.store.impl.DataChangeListenerRegistration;
import org.opendaylight.controller.md.sal.dom.store.impl.ResolveDataChangeEventsTask;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateTip;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
import org.opendaylight.yangtools.yang.data.api.schema.tree.TipProducingDataTree;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.slf4j.Logger;
* This class is not part of the API contract and is subject to change at any time.
*/
@NotThreadSafe
-@VisibleForTesting
-public final class ShardDataTree extends ShardDataTreeTransactionParent {
+public class ShardDataTree extends ShardDataTreeTransactionParent {
private static final Logger LOG = LoggerFactory.getLogger(ShardDataTree.class);
+ private static final YangInstanceIdentifier ROOT_PATH = YangInstanceIdentifier.builder().build();
private static final ShardDataTreeNotificationManager MANAGER = new ShardDataTreeNotificationManager();
private final Map<String, ShardDataTreeTransactionChain> transactionChains = new HashMap<>();
private final ShardDataTreeChangePublisher treeChangePublisher = new ShardDataTreeChangePublisher();
private final ListenerTree listenerTree = ListenerTree.create();
private final TipProducingDataTree dataTree;
+ private SchemaContext schemaContext;
- ShardDataTree(final SchemaContext schemaContext) {
- dataTree = InMemoryDataTreeFactory.getInstance().create();
- if (schemaContext != null) {
- dataTree.setSchemaContext(schemaContext);
- }
+ public ShardDataTree(final SchemaContext schemaContext, final TreeType treeType) {
+ dataTree = InMemoryDataTreeFactory.getInstance().create(treeType);
+ updateSchemaContext(schemaContext);
}
- TipProducingDataTree getDataTree() {
+ public TipProducingDataTree getDataTree() {
return dataTree;
}
+ SchemaContext getSchemaContext() {
+ return schemaContext;
+ }
+
void updateSchemaContext(final SchemaContext schemaContext) {
+ Preconditions.checkNotNull(schemaContext);
+ this.schemaContext = schemaContext;
dataTree.setSchemaContext(schemaContext);
}
ReadWriteShardDataTreeTransaction newReadWriteTransaction(final String txId, final String chainId) {
if (Strings.isNullOrEmpty(chainId)) {
- return new ReadWriteShardDataTreeTransaction(this, txId, dataTree.takeSnapshot().newModification());
+ return new ReadWriteShardDataTreeTransaction(ShardDataTree.this, txId, dataTree.takeSnapshot()
+ .newModification());
}
return ensureTransactionChain(chainId).newReadWriteTransaction(txId);
}
- void notifyListeners(final DataTreeCandidate candidate) {
+ public void notifyListeners(final DataTreeCandidate candidate) {
LOG.debug("Notifying listeners on candidate {}", candidate);
// DataTreeChanges first, as they are more light-weight
ResolveDataChangeEventsTask.create(candidate, listenerTree).resolve(MANAGER);
}
+ void notifyOfInitialData(DataChangeListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier,
+ NormalizedNode<?, ?>>> listenerReg, Optional<DataTreeCandidate> currentState) {
+
+ if(currentState.isPresent()) {
+ ListenerTree localListenerTree = ListenerTree.create();
+ localListenerTree.registerDataChangeListener(listenerReg.getPath(), listenerReg.getInstance(),
+ listenerReg.getScope());
+
+ ResolveDataChangeEventsTask.create(currentState.get(), localListenerTree).resolve(MANAGER);
+ }
+ }
+
+ void notifyOfInitialData(final YangInstanceIdentifier path, final DOMDataTreeChangeListener listener,
+ final Optional<DataTreeCandidate> currentState) {
+ if(currentState.isPresent()) {
+ ShardDataTreeChangePublisher localTreeChangePublisher = new ShardDataTreeChangePublisher();
+ localTreeChangePublisher.registerTreeChangeListener(path, listener);
+ localTreeChangePublisher.publishChanges(currentState.get());
+ }
+ }
+
void closeAllTransactionChains() {
for (ShardDataTreeTransactionChain chain : transactionChains.values()) {
chain.close();
}
}
- Entry<ListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>>, DOMImmutableDataChangeEvent> registerChangeListener(
- final YangInstanceIdentifier path,
- final AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener, final DataChangeScope scope) {
- final ListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>> reg =
+ Entry<DataChangeListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>>,
+ Optional<DataTreeCandidate>> registerChangeListener(final YangInstanceIdentifier path,
+ final AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener,
+ final DataChangeScope scope) {
+ final DataChangeListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>> reg =
listenerTree.registerDataChangeListener(path, listener, scope);
- final Optional<NormalizedNode<?, ?>> currentState = dataTree.takeSnapshot().readNode(path);
- final DOMImmutableDataChangeEvent event;
- if (currentState.isPresent()) {
- final NormalizedNode<?, ?> data = currentState.get();
- event = DOMImmutableDataChangeEvent.builder(DataChangeScope.BASE).setAfter(data).addCreated(path, data).build();
- } else {
- event = null;
- }
+ return new SimpleEntry<>(reg, readCurrentData());
+ }
- return new SimpleEntry<>(reg, event);
+ private Optional<DataTreeCandidate> readCurrentData() {
+ final Optional<NormalizedNode<?, ?>> currentState = dataTree.takeSnapshot().readNode(ROOT_PATH);
+ return currentState.isPresent() ? Optional.of(DataTreeCandidates.fromNormalizedNode(
+ ROOT_PATH, currentState.get())) : Optional.<DataTreeCandidate>absent();
}
- Entry<ListenerRegistration<DOMDataTreeChangeListener>, DataTreeCandidate> registerTreeChangeListener(final YangInstanceIdentifier path,
- final DOMDataTreeChangeListener listener) {
- final ListenerRegistration<DOMDataTreeChangeListener> reg = treeChangePublisher.registerTreeChangeListener(path, listener);
+ public Entry<ListenerRegistration<DOMDataTreeChangeListener>, Optional<DataTreeCandidate>> registerTreeChangeListener(
+ final YangInstanceIdentifier path, final DOMDataTreeChangeListener listener) {
+ final ListenerRegistration<DOMDataTreeChangeListener> reg = treeChangePublisher.registerTreeChangeListener(
+ path, listener);
- final Optional<NormalizedNode<?, ?>> currentState = dataTree.takeSnapshot().readNode(path);
- final DataTreeCandidate event;
- if (currentState.isPresent()) {
- event = DataTreeCandidates.fromNormalizedNode(path, currentState.get());
- } else {
- event = null;
- }
- return new SimpleEntry<>(reg, event);
+ return new SimpleEntry<>(reg, readCurrentData());
}
void applyForeignCandidate(final String identifier, final DataTreeCandidate foreign) throws DataValidationFailedException {
ShardDataTreeCohort finishTransaction(final ReadWriteShardDataTreeTransaction transaction) {
final DataTreeModification snapshot = transaction.getSnapshot();
snapshot.ready();
- return new SimpleShardDataTreeCohort(this, snapshot);
+ return new SimpleShardDataTreeCohort(this, snapshot, transaction.getId());
+ }
+
+ public Optional<NormalizedNode<?, ?>> readNode(YangInstanceIdentifier path) {
+ return dataTree.takeSnapshot().readNode(path);
}
+ public DataTreeSnapshot takeSnapshot() {
+ return dataTree.takeSnapshot();
+ }
+
+ public DataTreeModification newModification() {
+ return dataTree.takeSnapshot().newModification();
+ }
+
+ public DataTreeCandidate commit(DataTreeModification modification) throws DataValidationFailedException {
+ modification.ready();
+ dataTree.validate(modification);
+ DataTreeCandidateTip candidate = dataTree.prepare(modification);
+ dataTree.commit(candidate);
+ return candidate;
+ }
}