Release permits as transactions are replayed 65/70965/2
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 12 Apr 2018 11:11:38 +0000 (13:11 +0200)
committerRobert Varga <nite@hq.sk>
Wed, 18 Apr 2018 07:20:01 +0000 (07:20 +0000)
Since we have correct accounting at the cost of needing to finish
the transition to new context in user thread, we need to make sure
we release permits as we push them towards the TransactionContext
if it is not handling it itself -- hence the user threads will not
be charged for operations which have logically been completed.

CONTROLLER-1825
Change-Id: I4bae984b08b99a042766d0a41475110781ef8377
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionContextWrapper.java

index 0e1260962d37d807f53233729f3f999e996faed9..d11ee3e0bd318d6f6cf9476f5694e2626c4b4ba1 100644 (file)
@@ -166,9 +166,6 @@ class TransactionContextWrapper {
                     if (!pendingEnqueue) {
                         // We're done invoking the TransactionOperations so we can now publish the TransactionContext.
                         localTransactionContext.operationHandOffComplete();
-                        if (!localTransactionContext.usesOperationLimiting()) {
-                            limiter.releaseAll();
-                        }
 
                         // This is null-to-non-null transition after which we are releasing the lock and not doing
                         // any further processing.
@@ -183,11 +180,16 @@ class TransactionContextWrapper {
                 queuedTxOperations.clear();
             }
 
-            // Invoke TransactionOperations outside the sync block to avoid unnecessary blocking.
-            // A slight down-side is that we need to re-acquire the lock below but this should
-            // be negligible.
+            // Invoke TransactionOperations outside the sync block to avoid unnecessary blocking. A slight down-side is
+            // that we need to re-acquire the lock below but this should be negligible.
             for (Entry<TransactionOperation, Boolean> oper : operationsBatch) {
-                oper.getKey().invoke(localTransactionContext, oper.getValue());
+                final Boolean permit = oper.getValue();
+                if (permit.booleanValue() && !localTransactionContext.usesOperationLimiting()) {
+                    // If the context is not using limiting we need to release operations as we are queueing them, so
+                    // user threads are not charged for them.
+                    limiter.release();
+                }
+                oper.getKey().invoke(localTransactionContext, permit);
             }
         }
     }