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 java.util.Map;
import java.util.Map.Entry;
import javax.annotation.concurrent.NotThreadSafe;
+import org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier;
+import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
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.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.Identifier;
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;
@NotThreadSafe
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 Map<LocalHistoryIdentifier, ShardDataTreeTransactionChain> transactionChains = new HashMap<>();
+ private final ShardDataTreeChangeListenerPublisher treeChangeListenerPublisher;
+ private final ShardDataChangeListenerPublisher dataChangeListenerPublisher;
private final TipProducingDataTree dataTree;
+ private final String logContext;
private SchemaContext schemaContext;
- public ShardDataTree(final SchemaContext schemaContext) {
- dataTree = InMemoryDataTreeFactory.getInstance().create();
+ public ShardDataTree(final SchemaContext schemaContext, final TreeType treeType,
+ final ShardDataTreeChangeListenerPublisher treeChangeListenerPublisher,
+ final ShardDataChangeListenerPublisher dataChangeListenerPublisher, final String logContext) {
+ dataTree = InMemoryDataTreeFactory.getInstance().create(treeType);
updateSchemaContext(schemaContext);
+ this.treeChangeListenerPublisher = treeChangeListenerPublisher;
+ this.dataChangeListenerPublisher = dataChangeListenerPublisher;
+ this.logContext = logContext;
+ }
+ public ShardDataTree(final SchemaContext schemaContext, final TreeType treeType) {
+ this(schemaContext, treeType, new DefaultShardDataTreeChangeListenerPublisher(),
+ new DefaultShardDataChangeListenerPublisher(), "");
}
public TipProducingDataTree getDataTree() {
dataTree.setSchemaContext(schemaContext);
}
- private ShardDataTreeTransactionChain ensureTransactionChain(final String chainId) {
- ShardDataTreeTransactionChain chain = transactionChains.get(chainId);
+ private ShardDataTreeTransactionChain ensureTransactionChain(final LocalHistoryIdentifier localHistoryIdentifier) {
+ ShardDataTreeTransactionChain chain = transactionChains.get(localHistoryIdentifier);
if (chain == null) {
- chain = new ShardDataTreeTransactionChain(chainId, this);
- transactionChains.put(chainId, chain);
+ chain = new ShardDataTreeTransactionChain(localHistoryIdentifier, this);
+ transactionChains.put(localHistoryIdentifier, chain);
}
return chain;
}
- ReadOnlyShardDataTreeTransaction newReadOnlyTransaction(final String txId, final String chainId) {
- if (Strings.isNullOrEmpty(chainId)) {
+ ReadOnlyShardDataTreeTransaction newReadOnlyTransaction(final TransactionIdentifier txId) {
+ if (txId.getHistoryId().getHistoryId() == 0) {
return new ReadOnlyShardDataTreeTransaction(txId, dataTree.takeSnapshot());
}
- return ensureTransactionChain(chainId).newReadOnlyTransaction(txId);
+ return ensureTransactionChain(txId.getHistoryId()).newReadOnlyTransaction(txId);
}
- ReadWriteShardDataTreeTransaction newReadWriteTransaction(final String txId, final String chainId) {
- if (Strings.isNullOrEmpty(chainId)) {
+ ReadWriteShardDataTreeTransaction newReadWriteTransaction(final TransactionIdentifier txId) {
+ if (txId.getHistoryId().getHistoryId() == 0) {
return new ReadWriteShardDataTreeTransaction(ShardDataTree.this, txId, dataTree.takeSnapshot()
.newModification());
}
- return ensureTransactionChain(chainId).newReadWriteTransaction(txId);
+ return ensureTransactionChain(txId.getHistoryId()).newReadWriteTransaction(txId);
}
public void notifyListeners(final DataTreeCandidate candidate) {
- LOG.debug("Notifying listeners on candidate {}", candidate);
-
- // DataTreeChanges first, as they are more light-weight
- treeChangePublisher.publishChanges(candidate);
-
- // DataChanges second, as they are heavier
- ResolveDataChangeEventsTask.create(candidate, listenerTree).resolve(MANAGER);
+ treeChangeListenerPublisher.publishChanges(candidate, logContext);
+ dataChangeListenerPublisher.publishChanges(candidate, logContext);
}
void notifyOfInitialData(DataChangeListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier,
NormalizedNode<?, ?>>> listenerReg, Optional<DataTreeCandidate> currentState) {
if(currentState.isPresent()) {
- ListenerTree localListenerTree = ListenerTree.create();
- localListenerTree.registerDataChangeListener(listenerReg.getPath(), listenerReg.getInstance(),
+ ShardDataChangeListenerPublisher localPublisher = dataChangeListenerPublisher.newInstance();
+ localPublisher.registerDataChangeListener(listenerReg.getPath(), listenerReg.getInstance(),
listenerReg.getScope());
-
- ResolveDataChangeEventsTask.create(currentState.get(), localListenerTree).resolve(MANAGER);
+ localPublisher.publishChanges(currentState.get(), logContext);
}
}
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());
+ ShardDataTreeChangeListenerPublisher localPublisher = treeChangeListenerPublisher.newInstance();
+ localPublisher.registerTreeChangeListener(path, listener);
+ localPublisher.publishChanges(currentState.get(), logContext);
}
}
transactionChains.clear();
}
- void closeTransactionChain(final String transactionChainId) {
+ void closeTransactionChain(final LocalHistoryIdentifier transactionChainId) {
final ShardDataTreeTransactionChain chain = transactionChains.remove(transactionChainId);
if (chain != null) {
chain.close();
} else {
- LOG.debug("Closing non-existent transaction chain {}", transactionChainId);
+ LOG.debug("{}: Closing non-existent transaction chain {}", logContext, transactionChainId);
}
}
final AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener,
final DataChangeScope scope) {
final DataChangeListenerRegistration<AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>> reg =
- listenerTree.registerDataChangeListener(path, listener, scope);
+ dataChangeListenerPublisher.registerDataChangeListener(path, listener, scope);
return new SimpleEntry<>(reg, readCurrentData());
}
private Optional<DataTreeCandidate> readCurrentData() {
- final Optional<NormalizedNode<?, ?>> currentState = dataTree.takeSnapshot().readNode(ROOT_PATH);
+ final Optional<NormalizedNode<?, ?>> currentState = dataTree.takeSnapshot().readNode(YangInstanceIdentifier.EMPTY);
return currentState.isPresent() ? Optional.of(DataTreeCandidates.fromNormalizedNode(
- ROOT_PATH, currentState.get())) : Optional.<DataTreeCandidate>absent();
+ YangInstanceIdentifier.EMPTY, currentState.get())) : Optional.<DataTreeCandidate>absent();
}
public Entry<ListenerRegistration<DOMDataTreeChangeListener>, Optional<DataTreeCandidate>> registerTreeChangeListener(
final YangInstanceIdentifier path, final DOMDataTreeChangeListener listener) {
- final ListenerRegistration<DOMDataTreeChangeListener> reg = treeChangePublisher.registerTreeChangeListener(
+ final ListenerRegistration<DOMDataTreeChangeListener> reg = treeChangeListenerPublisher.registerTreeChangeListener(
path, listener);
return new SimpleEntry<>(reg, readCurrentData());
}
- void applyForeignCandidate(final String identifier, final DataTreeCandidate foreign) throws DataValidationFailedException {
- LOG.debug("Applying foreign transaction {}", identifier);
+ void applyForeignCandidate(final Identifier identifier, final DataTreeCandidate foreign) throws DataValidationFailedException {
+ LOG.debug("{}: Applying foreign transaction {}", logContext, identifier);
final DataTreeModification mod = dataTree.takeSnapshot().newModification();
DataTreeCandidates.applyToModification(mod, foreign);
mod.ready();
- LOG.trace("Applying foreign modification {}", mod);
+ LOG.trace("{}: Applying foreign modification {}", logContext, mod);
dataTree.validate(mod);
final DataTreeCandidate candidate = dataTree.prepare(mod);
dataTree.commit(candidate);
snapshot.ready();
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();
+ }
+
+ // FIXME: This should be removed, it violates encapsulation
+ public DataTreeCandidate commit(DataTreeModification modification) throws DataValidationFailedException {
+ modification.ready();
+ dataTree.validate(modification);
+ DataTreeCandidateTip candidate = dataTree.prepare(modification);
+ dataTree.commit(candidate);
+ return candidate;
+ }
}