- return debugTransactions;
- }
-
- final DataTreeSnapshot takeSnapshot() {
- return dataTree.takeSnapshot();
- }
-
- @Override
- public <L extends AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>> ListenerRegistration<L> registerChangeListener(
- final YangInstanceIdentifier path, final L listener, final DataChangeScope scope) {
-
- /*
- * Make sure commit is not occurring right now. Listener has to be
- * registered and its state capture enqueued at a consistent point.
- *
- * FIXME: improve this to read-write lock, such that multiple listener
- * registrations can occur simultaneously
- */
- final DataChangeListenerRegistration<L> reg;
- synchronized (this) {
- LOG.debug("{}: Registering data change listener {} for {}", name, listener, path);
-
- reg = listenerTree.registerDataChangeListener(path, listener, scope);
-
- Optional<NormalizedNode<?, ?>> currentState = dataTree.takeSnapshot().readNode(path);
- if (currentState.isPresent()) {
- final NormalizedNode<?, ?> data = currentState.get();
-
- final DOMImmutableDataChangeEvent event = DOMImmutableDataChangeEvent.builder(DataChangeScope.BASE) //
- .setAfter(data) //
- .addCreated(path, data) //
- .build();
-
- dataChangeListenerNotificationManager.submitNotification(reg, event);
- }
- }
-
- return new AbstractListenerRegistration<L>(listener) {
- @Override
- protected void removeRegistration() {
- synchronized (InMemoryDOMDataStore.this) {
- reg.close();
- }
- }
- };
- }
-
- @Override
- protected void transactionAborted(final SnapshotBackedWriteTransaction tx) {
- LOG.debug("Tx: {} is closed.", tx.getIdentifier());
- }
-
- @Override
- protected DOMStoreThreePhaseCommitCohort transactionReady(final SnapshotBackedWriteTransaction tx, final DataTreeModification tree) {
- LOG.debug("Tx: {} is submitted. Modifications: {}", tx.getIdentifier(), tree);
- return new ThreePhaseCommitImpl(tx, tree);
- }
-
- Object nextIdentifier() {
- return name + "-" + txCounter.getAndIncrement();
- }
-
- private final class ThreePhaseCommitImpl implements DOMStoreThreePhaseCommitCohort {
- private final SnapshotBackedWriteTransaction transaction;
- private final DataTreeModification modification;
-
- private ResolveDataChangeEventsTask listenerResolver;
- private DataTreeCandidate candidate;
-
- public ThreePhaseCommitImpl(final SnapshotBackedWriteTransaction writeTransaction, final DataTreeModification modification) {
- this.transaction = writeTransaction;
- this.modification = modification;
- }
-
- @Override
- public ListenableFuture<Boolean> canCommit() {
- return commitExecutor.submit(new Callable<Boolean>() {
- @Override
- public Boolean call() throws TransactionCommitFailedException {
- try {
- dataTree.validate(modification);
- LOG.debug("Store Transaction: {} can be committed", transaction.getIdentifier());
- return true;
- } catch (ConflictingModificationAppliedException e) {
- LOG.warn("Store Tx: {} Conflicting modification for {}.", transaction.getIdentifier(),
- e.getPath());
- transaction.warnDebugContext(LOG);
- throw new OptimisticLockFailedException("Optimistic lock failed.",e);
- } catch (DataValidationFailedException e) {
- LOG.warn("Store Tx: {} Data Precondition failed for {}.", transaction.getIdentifier(),
- e.getPath(), e);
- transaction.warnDebugContext(LOG);
- throw new TransactionCommitFailedException("Data did not pass validation.",e);
- }
- }
- });
- }
-
- @Override
- public ListenableFuture<Void> preCommit() {
- return commitExecutor.submit(new Callable<Void>() {
- @Override
- public Void call() {
- candidate = dataTree.prepare(modification);
- listenerResolver = ResolveDataChangeEventsTask.create(candidate, listenerTree);
- return null;
- }
- });
- }
-
- @Override
- public ListenableFuture<Void> abort() {
- candidate = null;
- return SUCCESSFUL_FUTURE;
- }
-
- @Override
- public ListenableFuture<Void> commit() {
- checkState(candidate != null, "Proposed subtree must be computed");
-
- /*
- * The commit has to occur atomically with regard to listener
- * registrations.
- */
- synchronized (InMemoryDOMDataStore.this) {
- dataTree.commit(candidate);
- listenerResolver.resolve(dataChangeListenerNotificationManager);
- }
-
- return SUCCESSFUL_FUTURE;
- }