Repository: asterixdb
Updated Branches:
  refs/heads/master fdf862eac -> 05365fd06


[NO ISSUE][TXN] Prevent deadlock in Metadata transactions

- user model changes: no
- storage format changes: no
- interface changes: no

Details:
- Flushes in metadata datasets are triggerred by entity update
  logs, unlike regular transactions where flushes are triggerred
  by entity commit logs.
- Because entity update logs can be writting to disk before the
  operation completes, there is a chance that an operation that
  caused the component to be full exits after the log is flushed
  and so, a flush operation is not scheduled.
- This change proposes a simple fix. The fix is that metadata
  operation will also check if a flush is needed and will schedule
  one if needed.

Change-Id: I07a18840dc54fe052b7bd294595f816f6d8a4d2f
Reviewed-on: https://asterix-gerrit.ics.uci.edu/2413
Sonar-Qube: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Reviewed-by: Murtadha Hubail <mhub...@apache.org>
Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Contrib: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu>


Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/05365fd0
Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/05365fd0
Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/05365fd0

Branch: refs/heads/master
Commit: 05365fd0639c14eed80bfbe67ae3f24fef72228a
Parents: fdf862e
Author: Abdullah Alamoudi <bamou...@gmail.com>
Authored: Wed Feb 21 08:20:39 2018 -0800
Committer: abdullah alamoudi <bamou...@gmail.com>
Committed: Wed Feb 21 09:53:09 2018 -0800

----------------------------------------------------------------------
 .../common/context/PrimaryIndexOperationTracker.java | 15 ++++++++++-----
 .../org/apache/asterix/metadata/MetadataNode.java    |  4 +++-
 2 files changed, 13 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/05365fd0/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/PrimaryIndexOperationTracker.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/PrimaryIndexOperationTracker.java
 
b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/PrimaryIndexOperationTracker.java
index 1a76b66..f7f2806 100644
--- 
a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/PrimaryIndexOperationTracker.java
+++ 
b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/PrimaryIndexOperationTracker.java
@@ -86,17 +86,19 @@ public class PrimaryIndexOperationTracker extends 
BaseOperationTracker {
             throws HyracksDataException {
         if (opType == LSMOperationType.MODIFICATION || opType == 
LSMOperationType.FORCE_MODIFICATION) {
             decrementNumActiveOperations(modificationCallback);
-            if (numActiveOperations.get() == 0) {
-                flushIfRequested();
-            } else if (numActiveOperations.get() < 0) {
-                throw new HyracksDataException("The number of active 
operations cannot be negative!");
-            }
+            flushIfNeeded();
         } else if (opType == LSMOperationType.FLUSH || opType == 
LSMOperationType.MERGE
                 || opType == LSMOperationType.REPLICATE) {
             dsInfo.undeclareActiveIOOperation();
         }
     }
 
+    public synchronized void flushIfNeeded() throws HyracksDataException {
+        if (numActiveOperations.get() == 0) {
+            flushIfRequested();
+        }
+    }
+
     public void flushIfRequested() throws HyracksDataException {
         // If we need a flush, and this is the last completing operation, then 
schedule the flush,
         // or if there is a flush scheduled by the checkpoint (flushOnExit), 
then schedule it
@@ -177,6 +179,9 @@ public class PrimaryIndexOperationTracker extends 
BaseOperationTracker {
         //modificationCallback can be NoOpOperationCallback when redo/undo 
operations are executed.
         if (modificationCallback != NoOpOperationCallback.INSTANCE) {
             numActiveOperations.decrementAndGet();
+            if (numActiveOperations.get() < 0) {
+                throw new IllegalStateException("The number of active 
operations cannot be negative!");
+            }
             ((AbstractOperationCallback) 
modificationCallback).afterOperation();
         }
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/05365fd0/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
 
b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
index 64d0389..f81d7da 100644
--- 
a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
+++ 
b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/MetadataNode.java
@@ -30,6 +30,7 @@ import org.apache.asterix.common.api.IDatasetLifecycleManager;
 import org.apache.asterix.common.api.INcApplicationContext;
 import org.apache.asterix.common.config.DatasetConfig.DatasetType;
 import org.apache.asterix.common.config.DatasetConfig.IndexType;
+import org.apache.asterix.common.context.PrimaryIndexOperationTracker;
 import org.apache.asterix.common.dataflow.LSMIndexUtil;
 import org.apache.asterix.common.exceptions.ACIDException;
 import org.apache.asterix.common.functions.FunctionSignature;
@@ -347,7 +348,6 @@ public class MetadataNode implements IMetadataNode {
             DatasetTupleTranslator tupleReaderWriter = 
tupleTranslatorProvider.getDatasetTupleTranslator(true);
             ITupleReference datasetTuple = 
tupleReaderWriter.getTupleFromMetadataEntity(dataset);
             insertTupleIntoIndex(txnId, 
MetadataPrimaryIndexes.DATASET_DATASET, datasetTuple);
-
             if (dataset.getDatasetType() == DatasetType.INTERNAL) {
                 // Add the primary index for the dataset.
                 InternalDatasetDetails id = (InternalDatasetDetails) 
dataset.getDatasetDetails();
@@ -501,6 +501,8 @@ public class MetadataNode implements IMetadataNode {
                 default:
                     throw new IllegalStateException("Unknown operation type: " 
+ op);
             }
+            PrimaryIndexOperationTracker opTracker = 
(PrimaryIndexOperationTracker) lsmIndex.getOperationTracker();
+            opTracker.flushIfNeeded(); // there is a window where the flush is 
not triggerred after an operation
         } finally {
             datasetLifecycleManager.close(resourceName);
         }

Reply via email to