[ASTERIXDB-2494][RT] Ensure Dataset Ref Counters Are Thread-safe
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
- Dataset/Index reference counters are modified concurrently by
multiple threads and should be thread-safe. Thread-safety issues
in these counters could result in leaving a dataset allocated
in memory even though it can be evicted.
Change-Id: I9328df660f463bd45bfc003b1e44c9df2702cc90
Reviewed-on: https://asterix-gerrit.ics.uci.edu/3089
Sonar-Qube: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <tillw@apache.org>
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/DatasetInfo.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/DatasetInfo.java
index 6e2e320..4ccb0cc 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/DatasetInfo.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/DatasetInfo.java
@@ -18,6 +18,7 @@
*/
package org.apache.asterix.common.context;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -159,8 +160,8 @@
this.isExternal = isExternal;
}
- public Map<Long, IndexInfo> getIndexes() {
- return indexes;
+ public synchronized Map<Long, IndexInfo> getIndexes() {
+ return Collections.unmodifiableMap(indexes);
}
public synchronized void addIndex(long resourceID, IndexInfo indexInfo) {
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/DatasetLifecycleManager.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/DatasetLifecycleManager.java
index 1dff69d..d767219 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/DatasetLifecycleManager.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/DatasetLifecycleManager.java
@@ -163,9 +163,11 @@
dsInfo.waitForIO();
closeIndex(iInfo);
dsInfo.removeIndex(resourceID);
- if (dsInfo.getReferenceCount() == 0 && dsInfo.isOpen() && dsInfo.getIndexes().isEmpty()
- && !dsInfo.isExternal()) {
- removeDatasetFromCache(dsInfo.getDatasetID());
+ synchronized (dsInfo) {
+ if (dsInfo.getReferenceCount() == 0 && dsInfo.isOpen() && dsInfo.getIndexes().isEmpty()
+ && !dsInfo.isExternal()) {
+ removeDatasetFromCache(dsInfo.getDatasetID());
+ }
}
}
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/Info.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/Info.java
index 8afae0d..fa0f14c 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/Info.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/context/Info.java
@@ -18,25 +18,26 @@
*/
package org.apache.asterix.common.context;
+import java.util.concurrent.atomic.AtomicInteger;
+
public abstract class Info {
- private int referenceCount;
- private boolean isOpen;
+ private final AtomicInteger referenceCount = new AtomicInteger();
+ private volatile boolean isOpen;
public Info() {
- referenceCount = 0;
isOpen = false;
}
public void touch() {
- ++referenceCount;
+ referenceCount.incrementAndGet();
}
public void untouch() {
- --referenceCount;
+ referenceCount.decrementAndGet();
}
public int getReferenceCount() {
- return referenceCount;
+ return referenceCount.get();
}
public boolean isOpen() {