Change-Id: Iaab4941ab777eaef1068523fc055391d31ca3072
Signed-off-by: Robert Varga <rovarga@cisco.com>
private static final Logger LOG = LoggerFactory.getLogger(PingPongTransactionChain.class);
private final DOMTransactionChain delegate;
private static final Logger LOG = LoggerFactory.getLogger(PingPongTransactionChain.class);
private final DOMTransactionChain delegate;
- @GuardedBy("this")
- private PingPongTransaction inflightTransaction;
@GuardedBy("this")
private boolean failed;
@GuardedBy("this")
private boolean failed;
AtomicReferenceFieldUpdater.newUpdater(PingPongTransactionChain.class, PingPongTransaction.class, "lockedTx");
private volatile PingPongTransaction lockedTx;
AtomicReferenceFieldUpdater.newUpdater(PingPongTransactionChain.class, PingPongTransaction.class, "lockedTx");
private volatile PingPongTransaction lockedTx;
+ /**
+ * This updater is used to manipulate the "inflight" transaction. There can be at most
+ * one of these at any given time. We perform only compare-and-swap on these.
+ */
+ private static final AtomicReferenceFieldUpdater<PingPongTransactionChain, PingPongTransaction> INFLIGHT_UPDATER =
+ AtomicReferenceFieldUpdater.newUpdater(PingPongTransactionChain.class, PingPongTransaction.class, "inflightTx");
+ private volatile PingPongTransaction inflightTx;
+
PingPongTransactionChain(final DOMDataBroker broker, final TransactionChainListener listener) {
this.delegate = broker.createTransactionChain(new TransactionChainListener() {
@Override
PingPongTransactionChain(final DOMDataBroker broker, final TransactionChainListener listener) {
this.delegate = broker.createTransactionChain(new TransactionChainListener() {
@Override
LOG.debug("Delegate chain {} reported failure in {}", chain, transaction, cause);
final DOMDataReadWriteTransaction frontend;
LOG.debug("Delegate chain {} reported failure in {}", chain, transaction, cause);
final DOMDataReadWriteTransaction frontend;
- if (inflightTransaction == null) {
+ final PingPongTransaction tx = inflightTx;
+ if (tx == null) {
LOG.warn("Transaction chain {} failed with no pending transactions", chain);
frontend = null;
} else {
LOG.warn("Transaction chain {} failed with no pending transactions", chain);
frontend = null;
} else {
- frontend = inflightTransaction.getFrontendTransaction();
+ frontend = tx.getFrontendTransaction();
- listener.onTransactionChainFailed(PingPongTransactionChain.this, frontend , cause);
+ listener.onTransactionChainFailed(PingPongTransactionChain.this, frontend, cause);
}
LOG.debug("Submitting transaction {}", tx);
}
LOG.debug("Submitting transaction {}", tx);
- final CheckedFuture<Void, ?> f = tx.getTransaction().submit();
- inflightTransaction = tx;
+ if (!INFLIGHT_UPDATER.compareAndSet(this, null, tx)) {
+ LOG.warn("Submitting transaction {} while {} is still running", tx, inflightTx);
+ }
- Futures.addCallback(f, new FutureCallback<Void>() {
+ Futures.addCallback(tx.getTransaction().submit(), new FutureCallback<Void>() {
@Override
public void onSuccess(final Void result) {
transactionSuccessful(tx, result);
@Override
public void onSuccess(final Void result) {
transactionSuccessful(tx, result);
private void transactionSuccessful(final PingPongTransaction tx, final Void result) {
LOG.debug("Transaction {} completed successfully", tx);
private void transactionSuccessful(final PingPongTransaction tx, final Void result) {
LOG.debug("Transaction {} completed successfully", tx);
- synchronized (this) {
- Preconditions.checkState(inflightTransaction == tx, "Successful transaction %s while %s was submitted", tx, inflightTransaction);
+ final boolean success = INFLIGHT_UPDATER.compareAndSet(this, tx, null);
+ Preconditions.checkState(success, "Successful transaction %s while %s was submitted", tx, inflightTx);
- inflightTransaction = null;
private void transactionFailed(final PingPongTransaction tx, final Throwable t) {
LOG.debug("Transaction {} failed", tx, t);
private void transactionFailed(final PingPongTransaction tx, final Throwable t) {
LOG.debug("Transaction {} failed", tx, t);
- synchronized (this) {
- Preconditions.checkState(inflightTransaction == tx, "Failed transaction %s while %s was submitted", tx, inflightTransaction);
- inflightTransaction = null;
- }
+ final boolean success = INFLIGHT_UPDATER.compareAndSet(this, tx, null);
+ Preconditions.checkState(success, "Failed transaction %s while %s was submitted", tx, inflightTx);
LOG.debug("Transaction {} unlocked", tx);
LOG.debug("Transaction {} unlocked", tx);
- synchronized (this) {
- if (inflightTransaction == null) {
+ if (inflightTx == null) {
+ synchronized (this) {
processTransaction(tx);
}
}
processTransaction(tx);
}
}