This is an automated email from the ASF dual-hosted git repository.
jackietien pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new e1066549218 fix delete dead lock.
e1066549218 is described below
commit e106654921879d88c264500021bc9ac165a2726f
Author: Colin Li <[email protected]>
AuthorDate: Tue Apr 9 18:25:26 2024 +0800
fix delete dead lock.
---
.../analyze/cache/schema/DataNodeSchemaCache.java | 25 +++++
.../analyze/cache/schema/SchemaCacheEntry.java | 8 ++
.../cache/schema/TimeSeriesSchemaCache.java | 32 ++++++
.../cache/schema/dualkeycache/IDualKeyCache.java | 9 ++
.../schema/dualkeycache/impl/DualKeyCacheImpl.java | 59 +++++++++++
.../schema/lastcache/DataNodeLastCacheManager.java | 7 ++
.../schema/lastcache/ILastCacheContainer.java | 5 +-
.../cache/schema/lastcache/LastCacheContainer.java | 7 ++
.../db/storageengine/dataregion/DataRegion.java | 44 +-------
.../cache/dualkeycache/DualKeyCacheTest.java | 114 +++++++++++++++++++++
10 files changed, 269 insertions(+), 41 deletions(-)
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/DataNodeSchemaCache.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/DataNodeSchemaCache.java
index 5559f7b5483..cc5dd91fea2 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/DataNodeSchemaCache.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/DataNodeSchemaCache.java
@@ -19,6 +19,7 @@
package org.apache.iotdb.db.queryengine.plan.analyze.cache.schema;
+import org.apache.iotdb.commons.conf.CommonDescriptor;
import org.apache.iotdb.commons.path.MeasurementPath;
import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.commons.service.metric.MetricService;
@@ -218,6 +219,30 @@ public class DataNodeSchemaCache {
return timeSeriesSchemaCache.getLastCache(seriesPath);
}
+ public void invalidateLastCache(PartialPath path) {
+ if (!CommonDescriptor.getInstance().getConfig().isLastCacheEnable()) {
+ return;
+ }
+ takeReadLock();
+ try {
+ timeSeriesSchemaCache.invalidateLastCache(path);
+ } finally {
+ releaseReadLock();
+ }
+ }
+
+ public void invalidateLastCacheInDataRegion(String database) {
+ if (!CommonDescriptor.getInstance().getConfig().isLastCacheEnable()) {
+ return;
+ }
+ takeReadLock();
+ try {
+ timeSeriesSchemaCache.invalidateDataRegionLastCache(database);
+ } finally {
+ releaseReadLock();
+ }
+ }
+
/** get SchemaCacheEntry and update last cache */
@TestOnly
public void updateLastCache(
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/SchemaCacheEntry.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/SchemaCacheEntry.java
index 55a8bb21a27..181f0eeccba 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/SchemaCacheEntry.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/SchemaCacheEntry.java
@@ -163,4 +163,12 @@ public class SchemaCacheEntry implements
IMeasurementSchemaInfo {
public boolean isLogicalView() {
return this.iMeasurementSchema.isLogicalView();
}
+
+ public int invalidateLastCache() {
+ if (this.lastCacheContainer == null ||
this.lastCacheContainer.getCachedLast() == null) {
+ return 0;
+ }
+
+ return this.lastCacheContainer.invalidateLastCache();
+ }
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/TimeSeriesSchemaCache.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/TimeSeriesSchemaCache.java
index 5613a7c8cdc..0f3df8aa745 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/TimeSeriesSchemaCache.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/TimeSeriesSchemaCache.java
@@ -393,6 +393,38 @@ public class TimeSeriesSchemaCache {
dualKeyCache.invalidate(database);
}
+ public void invalidateLastCache(PartialPath path) {
+ if (!path.hasWildcard()) {
+ SchemaCacheEntry entry = dualKeyCache.get(path.getDevicePath(),
path.getMeasurement());
+ if (null == entry) {
+ return;
+ }
+ dualKeyCache.update(
+ new IDualKeyCacheUpdating<PartialPath, String, SchemaCacheEntry>() {
+ @Override
+ public PartialPath getFirstKey() {
+ return path.getDevicePath();
+ }
+
+ @Override
+ public String[] getSecondKeyList() {
+ return new String[] {path.getMeasurement()};
+ }
+
+ @Override
+ public int updateValue(int index, SchemaCacheEntry value) {
+ return DataNodeLastCacheManager.invalidateLastCache(value);
+ }
+ });
+ } else {
+ dualKeyCache.invalidateLastCache(path);
+ }
+ }
+
+ public void invalidateDataRegionLastCache(String database) {
+ dualKeyCache.invalidateDataRegionLastCache(database);
+ }
+
public void invalidate(List<PartialPath> partialPathList) {
dualKeyCache.invalidate(partialPathList);
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/dualkeycache/IDualKeyCache.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/dualkeycache/IDualKeyCache.java
index 0fcf11b37fa..95f0b0e8f00 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/dualkeycache/IDualKeyCache.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/dualkeycache/IDualKeyCache.java
@@ -54,6 +54,15 @@ public interface IDualKeyCache<FK, SK, V> {
/** put the cache value into cache */
void put(FK firstKey, SK secondKey, V value);
+ /**
+ * Invalidate last cache in datanode schema cache. Do not invalidate time
series cache.
+ *
+ * @param partialPathList
+ */
+ void invalidateLastCache(PartialPath partialPath);
+
+ void invalidateDataRegionLastCache(String database);
+
/**
* Invalidate all cache values in the cache and clear related cache keys.
The cache status and
* statistics won't be clear and they can still be accessed via
cache.stats().
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/dualkeycache/impl/DualKeyCacheImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/dualkeycache/impl/DualKeyCacheImpl.java
index 96bc7fd7408..d3a385467f8 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/dualkeycache/impl/DualKeyCacheImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/dualkeycache/impl/DualKeyCacheImpl.java
@@ -22,10 +22,12 @@ package
org.apache.iotdb.db.queryengine.plan.analyze.cache.schema.dualkeycache.i
import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.commons.path.PathPatternUtil;
import org.apache.iotdb.commons.utils.TestOnly;
+import
org.apache.iotdb.db.queryengine.plan.analyze.cache.schema.SchemaCacheEntry;
import
org.apache.iotdb.db.queryengine.plan.analyze.cache.schema.dualkeycache.IDualKeyCache;
import
org.apache.iotdb.db.queryengine.plan.analyze.cache.schema.dualkeycache.IDualKeyCacheComputation;
import
org.apache.iotdb.db.queryengine.plan.analyze.cache.schema.dualkeycache.IDualKeyCacheStats;
import
org.apache.iotdb.db.queryengine.plan.analyze.cache.schema.dualkeycache.IDualKeyCacheUpdating;
+import
org.apache.iotdb.db.queryengine.plan.analyze.cache.schema.lastcache.DataNodeLastCacheManager;
import java.util.ArrayList;
import java.util.Arrays;
@@ -240,6 +242,63 @@ class DualKeyCacheImpl<FK, SK, V, T extends
ICacheEntry<SK, V>>
}
}
+ @Override
+ public void invalidateLastCache(PartialPath path) {
+ String measurement = path.getMeasurement();
+ PartialPath devicePath = path.getDevicePath();
+ Function<FK, Boolean> deviceFilter = null;
+ Function<SK, Boolean> measurementFilter = null;
+
+ if (PathPatternUtil.hasWildcard(devicePath.getFullPath())) {
+ deviceFilter = d -> devicePath.matchFullPath((PartialPath) d);
+ }
+ if (PathPatternUtil.isMultiLevelMatchWildcard(measurement)) {
+ measurementFilter = m -> true;
+ }
+ if (deviceFilter == null) {
+ deviceFilter = d -> ((PartialPath) d).equals(devicePath);
+ }
+
+ if (measurementFilter == null) {
+ measurementFilter = m -> PathPatternUtil.isNodeMatch(measurement,
m.toString());
+ }
+
+ for (FK device : firstKeyMap.getAllKeys()) {
+ if (Boolean.TRUE.equals(deviceFilter.apply(device))) {
+ ICacheEntryGroup<FK, SK, V, T> entryGroup = firstKeyMap.get(device);
+ for (Iterator<Map.Entry<SK, T>> it = entryGroup.getAllCacheEntries();
it.hasNext(); ) {
+ Map.Entry<SK, T> entry = it.next();
+ if (Boolean.TRUE.equals(measurementFilter.apply(entry.getKey()))) {
+ T cacheEntry = entry.getValue();
+ synchronized (cacheEntry) {
+ SchemaCacheEntry schemaCacheEntry = (SchemaCacheEntry)
cacheEntry.getValue();
+ cacheStats.decreaseMemoryUsage(
+
DataNodeLastCacheManager.invalidateLastCache(schemaCacheEntry));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void invalidateDataRegionLastCache(String database) {
+ for (FK device : firstKeyMap.getAllKeys()) {
+ if (device.toString().startsWith(database)) {
+ ICacheEntryGroup<FK, SK, V, T> entryGroup = firstKeyMap.get(device);
+ for (Iterator<Map.Entry<SK, T>> it = entryGroup.getAllCacheEntries();
it.hasNext(); ) {
+ Map.Entry<SK, T> entry = it.next();
+ T cacheEntry = entry.getValue();
+ synchronized (cacheEntry) {
+ SchemaCacheEntry schemaCacheEntry = (SchemaCacheEntry)
cacheEntry.getValue();
+ cacheStats.decreaseMemoryUsage(
+
DataNodeLastCacheManager.invalidateLastCache(schemaCacheEntry));
+ }
+ }
+ }
+ }
+ }
+
@Override
public void invalidateAll() {
executeInvalidateAll();
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/lastcache/DataNodeLastCacheManager.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/lastcache/DataNodeLastCacheManager.java
index 6790f2cb645..88fee643e9c 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/lastcache/DataNodeLastCacheManager.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/lastcache/DataNodeLastCacheManager.java
@@ -65,4 +65,11 @@ public class DataNodeLastCacheManager {
}
return entry.updateLastCache(timeValuePair, highPriorityUpdate,
latestFlushedTime);
}
+
+ public static int invalidateLastCache(SchemaCacheEntry entry) {
+ if (!CACHE_ENABLED || null == entry) {
+ return 0;
+ }
+ return entry.invalidateLastCache();
+ }
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/lastcache/ILastCacheContainer.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/lastcache/ILastCacheContainer.java
index 3ada99d8ebf..de5ffdc2fd1 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/lastcache/ILastCacheContainer.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/lastcache/ILastCacheContainer.java
@@ -28,7 +28,7 @@ public interface ILastCacheContainer {
TimeValuePair getCachedLast();
/**
- * update last point cache
+ * update last point cache and enable last cache.
*
* @param timeValuePair last point
* @param highPriorityUpdate whether it's a high priority update
@@ -38,5 +38,8 @@ public interface ILastCacheContainer {
int updateCachedLast(
TimeValuePair timeValuePair, boolean highPriorityUpdate, Long
latestFlushedTime);
+ /** Invalidate Last cache. */
+ int invalidateLastCache();
+
int estimateSize();
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/lastcache/LastCacheContainer.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/lastcache/LastCacheContainer.java
index 0f9d34cc06b..e02809652cd 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/lastcache/LastCacheContainer.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/cache/schema/lastcache/LastCacheContainer.java
@@ -70,6 +70,13 @@ public class LastCacheContainer implements
ILastCacheContainer {
return 0;
}
+ @Override
+ public int invalidateLastCache() {
+ int size = lastCacheValue.estimateSize();
+ lastCacheValue = null;
+ return size;
+ }
+
private int getDiffSize(TsPrimitiveType oldValue, TsPrimitiveType newValue) {
if (oldValue == null) {
return newValue == null ? 0 : newValue.getSize();
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/DataRegion.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/DataRegion.java
index 8500b735ebc..9555eb0b7f2 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/DataRegion.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/DataRegion.java
@@ -23,7 +23,6 @@ import org.apache.iotdb.common.rpc.thrift.TSStatus;
import org.apache.iotdb.commons.cluster.NodeStatus;
import org.apache.iotdb.commons.conf.CommonDescriptor;
import org.apache.iotdb.commons.consensus.DataRegionId;
-import org.apache.iotdb.commons.exception.IllegalPathException;
import org.apache.iotdb.commons.exception.MetadataException;
import org.apache.iotdb.commons.file.SystemFileFactory;
import org.apache.iotdb.commons.path.PartialPath;
@@ -1945,17 +1944,8 @@ public class DataRegion implements IDataRegionForQuery {
boolean hasReleasedLock = false;
try {
-
+ DataNodeSchemaCache.getInstance().invalidateLastCache(pattern);
Set<PartialPath> devicePaths = new
HashSet<>(pattern.getDevicePathPattern());
-
- // delete Last cache record if necessary
- DataNodeSchemaCache.getInstance().takeWriteLock();
- try {
-
DataNodeSchemaCache.getInstance().invalidate(Collections.singletonList(pattern));
- } finally {
- DataNodeSchemaCache.getInstance().releaseWriteLock();
- }
-
// write log to impacted working TsFileProcessors
List<WALFlushListener> walListeners =
logDeletionInWAL(startTime, endTime, searchIndex, pattern);
@@ -1980,7 +1970,6 @@ public class DataRegion implements IDataRegionForQuery {
hasReleasedLock = true;
deleteDataInFiles(sealedTsFileResource, deletion, devicePaths,
deviceMatchInfo);
-
} catch (Exception e) {
throw new IOException(e);
} finally {
@@ -2000,15 +1989,9 @@ public class DataRegion implements IDataRegionForQuery {
writeLock("deleteDataDirect");
boolean releasedLock = false;
- try {
- // delete last cache record if necessary
- DataNodeSchemaCache.getInstance().takeWriteLock();
- try {
- DataNodeSchemaCache.getInstance().invalidate(databaseName);
- } finally {
- DataNodeSchemaCache.getInstance().releaseWriteLock();
- }
+ try {
+
DataNodeSchemaCache.getInstance().invalidateLastCacheInDataRegion(getDatabaseName());
// write log to impacted working TsFileProcessors
List<WALFlushListener> walListeners =
logDeletionInWAL(startTime, endTime, searchIndex, pathToDelete);
@@ -2539,18 +2522,6 @@ public class DataRegion implements IDataRegionForQuery {
}
}
- private void resetLastCacheWhenLoadingTsFile() throws IllegalPathException {
- if (!CommonDescriptor.getInstance().getConfig().isLastCacheEnable()) {
- return;
- }
- DataNodeSchemaCache.getInstance().takeWriteLock();
- try {
- DataNodeSchemaCache.getInstance().invalidateAll();
- } finally {
- DataNodeSchemaCache.getInstance().releaseWriteLock();
- }
- }
-
/**
* Load a new tsfile to unsequence dir.
*
@@ -2603,10 +2574,6 @@ public class DataRegion implements IDataRegionForQuery {
false,
newTsFileResource.getTsFile().getName());
- // Update last cache
- resetLastCacheWhenLoadingTsFile();
-
- // Update last flush time & help last flush time map degrade
if (config.isEnableSeparateData()) {
final DataRegionId dataRegionId = new
DataRegionId(Integer.parseInt(this.dataRegionId));
final long timePartitionId = newTsFileResource.getTimePartition();
@@ -2637,12 +2604,9 @@ public class DataRegion implements IDataRegionForQuery {
tsfileToBeInserted.getAbsolutePath(),
tsfileToBeInserted.getParentFile().getName());
throw new LoadFileException(e);
- } catch (IllegalPathException e) {
- logger.error(
- "Failed to reset last cache when loading file {}",
newTsFileResource.getTsFilePath());
- throw new LoadFileException(e);
} finally {
writeUnlock();
+
DataNodeSchemaCache.getInstance().invalidateLastCacheInDataRegion(databaseName);
}
}
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/cache/dualkeycache/DualKeyCacheTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/cache/dualkeycache/DualKeyCacheTest.java
index 65a88591d7b..4f2a8840278 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/cache/dualkeycache/DualKeyCacheTest.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/cache/dualkeycache/DualKeyCacheTest.java
@@ -374,4 +374,118 @@ public class DualKeyCacheTest {
Assert.assertEquals(expectSize, dualKeyCache.stats().memoryUsage());
return dualKeyCache;
}
+
+ private IDualKeyCache<PartialPath, String, SchemaCacheEntry>
generateLastCache()
+ throws IllegalPathException {
+ DualKeyCacheBuilder<PartialPath, String, SchemaCacheEntry>
dualKeyCacheBuilder =
+ new DualKeyCacheBuilder<>();
+ IDualKeyCache<PartialPath, String, SchemaCacheEntry> dualKeyCache =
+ dualKeyCacheBuilder
+ .cacheEvictionPolicy(DualKeyCachePolicy.valueOf(policy))
+ .memoryCapacity(2000) // actual threshold is 1600
+ .firstKeySizeComputer(PartialPath::estimateSize)
+ .secondKeySizeComputer(this::computeStringSize)
+ .valueSizeComputer(SchemaCacheEntry::estimateSize)
+ .build();
+ SchemaCacheEntry cacheEntry1 =
+ new SchemaCacheEntry(
+ "root.db1",
+ new MeasurementSchema("s1", TSDataType.INT32),
+ Collections.emptyMap(),
+ false);
+ cacheEntry1.updateLastCache(new TimeValuePair(1L, new
TsPrimitiveType.TsInt(1)), true, 0L);
+ dualKeyCache.put(new PartialPath("root.db1.d1"), "s1", cacheEntry1);
+
+ SchemaCacheEntry cacheEntry2 =
+ new SchemaCacheEntry(
+ "root.db1",
+ new MeasurementSchema("s2", TSDataType.INT32),
+ Collections.emptyMap(),
+ false);
+ cacheEntry2.updateLastCache(new TimeValuePair(1L, new
TsPrimitiveType.TsInt(1)), true, 0L);
+ dualKeyCache.put(new PartialPath("root.db1.d1"), "s2", cacheEntry2);
+
+ SchemaCacheEntry cacheEntry3 =
+ new SchemaCacheEntry(
+ "root.db2",
+ new MeasurementSchema("s2", TSDataType.INT32),
+ Collections.emptyMap(),
+ false);
+ cacheEntry3.updateLastCache(new TimeValuePair(1L, new
TsPrimitiveType.TsInt(1)), true, 0L);
+ dualKeyCache.put(new PartialPath("root.db2.d1"), "s2", cacheEntry3);
+
+ SchemaCacheEntry cacheEntry4 =
+ new SchemaCacheEntry(
+ "root.db2",
+ new MeasurementSchema("s2", TSDataType.INT32),
+ Collections.emptyMap(),
+ false);
+ cacheEntry4.updateLastCache(new TimeValuePair(1L, new
TsPrimitiveType.TsInt(1)), true, 0L);
+ dualKeyCache.put(new PartialPath("root.db2.d1"), "s1", cacheEntry4);
+
+ SchemaCacheEntry cacheEntry5 =
+ new SchemaCacheEntry(
+ "root.db1",
+ new MeasurementSchema("s2", TSDataType.INT32),
+ Collections.emptyMap(),
+ false);
+ cacheEntry5.updateLastCache(new TimeValuePair(1L, new
TsPrimitiveType.TsInt(1)), true, 0L);
+ dualKeyCache.put(new PartialPath("root.db1"), "s2", cacheEntry5);
+
+ Assert.assertNotNull(dualKeyCache.get(new PartialPath("root.db1.d1"),
"s1"));
+ Assert.assertNotNull(dualKeyCache.get(new PartialPath("root.db1.d1"),
"s2"));
+ Assert.assertNotNull(dualKeyCache.get(new PartialPath("root.db1"), "s2"));
+ Assert.assertNotNull(dualKeyCache.get(new PartialPath("root.db2.d1"),
"s1"));
+ Assert.assertNotNull(dualKeyCache.get(new PartialPath("root.db2.d1"),
"s2"));
+
+ int expectSize =
+ PartialPath.estimateSize(new PartialPath("root.db1.d1")) * 2
+ + PartialPath.estimateSize(new PartialPath("root.db1"))
+ + computeStringSize("s1") * 5
+ + SchemaCacheEntry.estimateSize(cacheEntry1) * 5;
+ Assert.assertEquals(expectSize, dualKeyCache.stats().memoryUsage());
+ return dualKeyCache;
+ }
+
+ @Test
+ public void testInvalidateSimpleTimeseriesAndDataRegion() throws
IllegalPathException {
+ IDualKeyCache<PartialPath, String, SchemaCacheEntry> dualKeyCache =
generateLastCache();
+ long memUse = dualKeyCache.stats().memoryUsage();
+
+ dualKeyCache.invalidateLastCache(new PartialPath("root.db1.d1.s1"));
+ SchemaCacheEntry cacheEntry = dualKeyCache.get(new
PartialPath("root.db1.d1"), "s1");
+ Assert.assertNull(cacheEntry.getLastCacheContainer().getCachedLast());
+
+ dualKeyCache.invalidateLastCache(new PartialPath("root.db1.d1.*"));
+ cacheEntry = dualKeyCache.get(new PartialPath("root.db1.d1"), "s2");
+ Assert.assertNull(cacheEntry.getLastCacheContainer().getCachedLast());
+
+ dualKeyCache.invalidateLastCache(new PartialPath("root.db2.d1.**"));
+ cacheEntry = dualKeyCache.get(new PartialPath("root.db2.d1"), "s2");
+ Assert.assertNull(cacheEntry.getLastCacheContainer().getCachedLast());
+
+ dualKeyCache.invalidateDataRegionLastCache("root.db2");
+ cacheEntry = dualKeyCache.get(new PartialPath("root.db2.d1"), "s1");
+ Assert.assertNull(cacheEntry.getLastCacheContainer().getCachedLast());
+
+ cacheEntry = dualKeyCache.get(new PartialPath("root.db1"), "s2");
+ // last cache container' estimateSize(): header 8b + Ilastcachevalueref 8b
+ lastcache's size
+ // invalidate operation: make Ilastcachevalueref = null.
+ // So the amount of change in size is estimateSize() - 8b - 8b
+ int size = cacheEntry.getLastCacheContainer().estimateSize() - 16;
+ Assert.assertEquals(memUse - size * 4, dualKeyCache.stats().memoryUsage());
+ }
+
+ @Test
+ public void testComplexInvalidate() throws IllegalPathException {
+ IDualKeyCache<PartialPath, String, SchemaCacheEntry> dualKeyCache =
generateLastCache();
+
+ dualKeyCache.invalidateLastCache(new PartialPath("root.db1.*.s1"));
+ SchemaCacheEntry cacheEntry = dualKeyCache.get(new
PartialPath("root.db1.d1"), "s1");
+ Assert.assertNull(cacheEntry.getLastCacheContainer().getCachedLast());
+
+ dualKeyCache.invalidateLastCache(new PartialPath("root.db1.**.s2"));
+ cacheEntry = dualKeyCache.get(new PartialPath("root.db1.d1"), "s2");
+ Assert.assertNull(cacheEntry.getLastCacheContainer().getCachedLast());
+ }
}