This is an automated email from the ASF dual-hosted git repository.
jackietien pushed a commit to branch dev/1.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/dev/1.3 by this push:
new bbb74b1ae9b [to dev/1.3] Transfer schema tree in batches & add memory
control for schema tree
bbb74b1ae9b is described below
commit bbb74b1ae9be9d498b6192a2c4557cf8c50895ad
Author: shuwenwei <[email protected]>
AuthorDate: Fri Aug 8 17:28:32 2025 +0800
[to dev/1.3] Transfer schema tree in batches & add memory control for
schema tree
---
.../iotdb/db/it/orderBy/IoTDBOrderBy2IT.java | 4 +
.../db/it/orderBy/IoTDBOrderByForDebugIT.java | 4 +
.../apache/iotdb/db/it/orderBy/IoTDBOrderByIT.java | 4 +
.../db/queryengine/common/MPPQueryContext.java | 33 ++++
.../common/schematree/ClusterSchemaTree.java | 192 ++++++++++++++++-----
.../queryengine/common/schematree/ISchemaTree.java | 3 +-
.../common/schematree/node/SchemaEntityNode.java | 23 +++
.../common/schematree/node/SchemaInternalNode.java | 17 ++
.../schematree/node/SchemaMeasurementNode.java | 24 +++
.../common/schematree/node/SchemaNode.java | 6 +-
.../operator/schema/SchemaFetchScanOperator.java | 104 ++++++++---
.../queryengine/plan/analyze/AnalyzeVisitor.java | 2 +-
.../db/queryengine/plan/analyze/Analyzer.java | 14 +-
.../analyze/schema/ClusterSchemaFetchExecutor.java | 29 +++-
.../iotdb/db/schemaengine/template/Template.java | 15 +-
.../schema/SchemaFetchScanOperatorTest.java | 52 ++++--
pom.xml | 2 +-
17 files changed, 438 insertions(+), 90 deletions(-)
diff --git
a/integration-test/src/test/java/org/apache/iotdb/db/it/orderBy/IoTDBOrderBy2IT.java
b/integration-test/src/test/java/org/apache/iotdb/db/it/orderBy/IoTDBOrderBy2IT.java
index 131ea8bf3b5..51bfdf3dd2a 100644
---
a/integration-test/src/test/java/org/apache/iotdb/db/it/orderBy/IoTDBOrderBy2IT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/orderBy/IoTDBOrderBy2IT.java
@@ -37,6 +37,10 @@ public class IoTDBOrderBy2IT extends IoTDBOrderByIT {
public static void setUp() throws Exception {
EnvFactory.getEnv().getConfig().getDataNodeCommonConfig().setSortBufferSize(2048);
EnvFactory.getEnv().getConfig().getDataNodeCommonConfig().setMaxTsBlockSizeInByte(200);
+ EnvFactory.getEnv()
+ .getConfig()
+ .getDataNodeCommonConfig()
+ .setQueryMemoryProportion("1:100:200:50:400:200:200:50");
EnvFactory.getEnv().initClusterEnvironment();
insertData();
}
diff --git
a/integration-test/src/test/java/org/apache/iotdb/db/it/orderBy/IoTDBOrderByForDebugIT.java
b/integration-test/src/test/java/org/apache/iotdb/db/it/orderBy/IoTDBOrderByForDebugIT.java
index c6f502bd4b5..2f5807388d1 100644
---
a/integration-test/src/test/java/org/apache/iotdb/db/it/orderBy/IoTDBOrderByForDebugIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/orderBy/IoTDBOrderByForDebugIT.java
@@ -104,6 +104,10 @@ public class IoTDBOrderByForDebugIT {
@BeforeClass
public static void setUp() throws Exception {
EnvFactory.getEnv().getConfig().getDataNodeCommonConfig().setSortBufferSize(1024
* 1024L);
+ EnvFactory.getEnv()
+ .getConfig()
+ .getDataNodeCommonConfig()
+ .setQueryMemoryProportion("1:100:200:50:400:200:200:50");
EnvFactory.getEnv().initClusterEnvironment();
insertData();
}
diff --git
a/integration-test/src/test/java/org/apache/iotdb/db/it/orderBy/IoTDBOrderByIT.java
b/integration-test/src/test/java/org/apache/iotdb/db/it/orderBy/IoTDBOrderByIT.java
index 097fa98281f..d1f9d5a2c25 100644
---
a/integration-test/src/test/java/org/apache/iotdb/db/it/orderBy/IoTDBOrderByIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/orderBy/IoTDBOrderByIT.java
@@ -107,6 +107,10 @@ public class IoTDBOrderByIT {
@BeforeClass
public static void setUp() throws Exception {
EnvFactory.getEnv().getConfig().getDataNodeCommonConfig().setSortBufferSize(1024
* 1024L);
+ EnvFactory.getEnv()
+ .getConfig()
+ .getDataNodeCommonConfig()
+ .setQueryMemoryProportion("1:100:200:50:400:200:200:50");
EnvFactory.getEnv().initClusterEnvironment();
insertData();
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/MPPQueryContext.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/MPPQueryContext.java
index 63970762de7..0035f726c4d 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/MPPQueryContext.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/MPPQueryContext.java
@@ -37,6 +37,7 @@ import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
+import java.util.function.LongConsumer;
/**
* This class is used to record the context of a query including QueryId,
query statement, session
@@ -88,6 +89,10 @@ public class MPPQueryContext {
// the updateScanNum process in distributed planning can be skipped.
private boolean needUpdateScanNumForLastQuery = false;
+ private long reservedMemoryCostForSchemaTree = 0;
+ private boolean releaseSchemaTreeAfterAnalyzing = true;
+ private LongConsumer reserveMemoryForSchemaTreeFunc = null;
+
private boolean userQuery = false;
public MPPQueryContext(QueryId queryId) {
@@ -128,6 +133,34 @@ public class MPPQueryContext {
this.initResultNodeContext();
}
+ public void setReserveMemoryForSchemaTreeFunc(LongConsumer
reserveMemoryForSchemaTreeFunc) {
+ this.reserveMemoryForSchemaTreeFunc = reserveMemoryForSchemaTreeFunc;
+ }
+
+ public void reserveMemoryForSchemaTree(long memoryCost) {
+ if (reserveMemoryForSchemaTreeFunc == null) {
+ return;
+ }
+ reserveMemoryForSchemaTreeFunc.accept(memoryCost);
+ this.reservedMemoryCostForSchemaTree += memoryCost;
+ }
+
+ public void setReleaseSchemaTreeAfterAnalyzing(boolean
releaseSchemaTreeAfterAnalyzing) {
+ this.releaseSchemaTreeAfterAnalyzing = releaseSchemaTreeAfterAnalyzing;
+ }
+
+ public boolean releaseSchemaTreeAfterAnalyzing() {
+ return releaseSchemaTreeAfterAnalyzing;
+ }
+
+ public void releaseMemoryForSchemaTree() {
+ if (reservedMemoryCostForSchemaTree <= 0) {
+ return;
+ }
+
this.memoryReservationManager.releaseMemoryCumulatively(reservedMemoryCostForSchemaTree);
+ reservedMemoryCostForSchemaTree = 0;
+ }
+
public void prepareForRetry() {
this.initResultNodeContext();
this.releaseAllMemoryReservedForFrontEnd();
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/ClusterSchemaTree.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/ClusterSchemaTree.java
index dc9776ab54a..40a49c368d9 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/ClusterSchemaTree.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/ClusterSchemaTree.java
@@ -39,6 +39,7 @@ import
org.apache.iotdb.db.schemaengine.template.ClusterTemplateManager;
import org.apache.iotdb.db.schemaengine.template.Template;
import org.apache.tsfile.utils.Pair;
+import org.apache.tsfile.utils.RamUsageEstimator;
import org.apache.tsfile.utils.ReadWriteIOUtils;
import org.apache.tsfile.write.schema.IMeasurementSchema;
@@ -49,8 +50,10 @@ import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.Set;
import static org.apache.iotdb.commons.conf.IoTDBConstant.PATH_ROOT;
@@ -60,6 +63,8 @@ import static
org.apache.iotdb.db.queryengine.common.schematree.node.SchemaNode.
import static
org.apache.iotdb.db.queryengine.common.schematree.node.SchemaNode.SCHEMA_MEASUREMENT_NODE;
public class ClusterSchemaTree implements ISchemaTree {
+ private static final long SHALLOW_SIZE =
+ RamUsageEstimator.shallowSizeOfInstance(ClusterSchemaTree.class);
private static final ClusterTemplateManager templateManager =
ClusterTemplateManager.getInstance();
@@ -75,6 +80,8 @@ public class ClusterSchemaTree implements ISchemaTree {
private Map<Integer, Template> templateMap = new HashMap<>();
+ private long ramBytesUsed;
+
public ClusterSchemaTree() {
root = new SchemaInternalNode(PATH_ROOT);
}
@@ -484,59 +491,158 @@ public class ClusterSchemaTree implements ISchemaTree {
root.serialize(outputStream);
}
- public static ClusterSchemaTree deserialize(InputStream inputStream) throws
IOException {
+ public Iterator<SchemaNode> getIteratorForSerialize() {
+ return new SchemaNodePostOrderIterator(root);
+ }
- byte nodeType;
- int childNum;
- Deque<SchemaNode> stack = new ArrayDeque<>();
- SchemaNode child;
- boolean hasLogicalView = false;
- boolean hasNormalTimeSeries = false;
- Map<Integer, Template> templateMap = new HashMap<>();
-
- while (inputStream.available() > 0) {
- nodeType = ReadWriteIOUtils.readByte(inputStream);
- if (nodeType == SCHEMA_MEASUREMENT_NODE) {
- SchemaMeasurementNode measurementNode =
SchemaMeasurementNode.deserialize(inputStream);
- stack.push(measurementNode);
- if (measurementNode.isLogicalView()) {
- hasLogicalView = true;
+ @Override
+ public long ramBytesUsed() {
+ if (ramBytesUsed > 0) {
+ return ramBytesUsed;
+ }
+ ramBytesUsed =
+ root.ramBytesUsed()
+ + SHALLOW_SIZE
+ + RamUsageEstimator.sizeOfMapWithKnownShallowSize(
+ templateMap,
+ RamUsageEstimator.SHALLOW_SIZE_OF_HASHMAP,
+ RamUsageEstimator.SHALLOW_SIZE_OF_HASHMAP_ENTRY);
+ return ramBytesUsed;
+ }
+
+ public void setRamBytesUsed(long ramBytesUsed) {
+ this.ramBytesUsed = ramBytesUsed;
+ }
+
+ private static class SchemaNodePostOrderIterator implements
Iterator<SchemaNode> {
+ // This class is likely to be faster than Stack when used as a stack
+ private final Deque<Pair<SchemaNode, Iterator<SchemaNode>>> stack = new
ArrayDeque<>();
+ private SchemaNode nextNode;
+
+ public SchemaNodePostOrderIterator(SchemaNode root) {
+ stack.push(new Pair<>(root, root.getChildrenIterator()));
+ prepareNext();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return nextNode != null;
+ }
+
+ @Override
+ public SchemaNode next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ SchemaNode result = nextNode;
+ prepareNext();
+ return result;
+ }
+
+ private void prepareNext() {
+ nextNode = null;
+ while (!stack.isEmpty()) {
+ Pair<SchemaNode, Iterator<SchemaNode>> pair = stack.peek();
+ SchemaNode currentNode = pair.getLeft();
+ Iterator<SchemaNode> childrenIterator = pair.getRight();
+ if (childrenIterator.hasNext()) {
+ SchemaNode child = childrenIterator.next();
+ stack.push(new Pair<>(child, child.getChildrenIterator()));
+ } else {
+ stack.pop();
+ nextNode = currentNode;
+ return;
}
- hasNormalTimeSeries = true;
- } else {
- SchemaInternalNode internalNode;
- if (nodeType == SCHEMA_ENTITY_NODE) {
- internalNode = SchemaEntityNode.deserialize(inputStream);
- int templateId = internalNode.getAsEntityNode().getTemplateId();
- if (templateId != NON_TEMPLATE) {
- templateMap.putIfAbsent(templateId,
templateManager.getTemplate(templateId));
+ }
+ }
+ }
+
+ public static class SchemaNodeBatchDeserializer {
+ private byte nodeType;
+ private int childNum;
+ // This class is likely to be faster than Stack when used as a stack
+ private final Deque<SchemaNode> stack = new ArrayDeque<>();
+ private SchemaNode child;
+ private boolean hasLogicalView = false;
+ private boolean hasNormalTimeSeries = false;
+ private Map<Integer, Template> templateMap = new HashMap<>();
+ private boolean isFirstBatch = true;
+
+ public boolean isFirstBatch() {
+ return isFirstBatch;
+ }
+
+ public void deserializeFromBatch(InputStream inputStream) throws
IOException {
+ isFirstBatch = false;
+ while (inputStream.available() > 0) {
+ nodeType = ReadWriteIOUtils.readByte(inputStream);
+ if (nodeType == SCHEMA_MEASUREMENT_NODE) {
+ SchemaMeasurementNode measurementNode =
SchemaMeasurementNode.deserialize(inputStream);
+ stack.push(measurementNode);
+ if (measurementNode.isLogicalView()) {
+ hasLogicalView = true;
}
+ hasNormalTimeSeries = true;
} else {
- internalNode = SchemaInternalNode.deserialize(inputStream);
- }
+ SchemaInternalNode internalNode;
+ if (nodeType == SCHEMA_ENTITY_NODE) {
+ internalNode = SchemaEntityNode.deserialize(inputStream);
+ int templateId = internalNode.getAsEntityNode().getTemplateId();
+ if (templateId != NON_TEMPLATE) {
+ templateMap.putIfAbsent(templateId,
templateManager.getTemplate(templateId));
+ }
+ } else {
+ internalNode = SchemaInternalNode.deserialize(inputStream);
+ }
- childNum = ReadWriteIOUtils.readInt(inputStream);
- while (childNum > 0) {
- child = stack.pop();
- internalNode.addChild(child.getName(), child);
- if (child.isMeasurement()) {
- SchemaMeasurementNode measurementNode =
child.getAsMeasurementNode();
- if (measurementNode.getAlias() != null) {
- internalNode
- .getAsEntityNode()
- .addAliasChild(measurementNode.getAlias(), measurementNode);
+ childNum = ReadWriteIOUtils.readInt(inputStream);
+ while (childNum > 0) {
+ child = stack.pop();
+ internalNode.addChild(child.getName(), child);
+ if (child.isMeasurement()) {
+ SchemaMeasurementNode measurementNode =
child.getAsMeasurementNode();
+ if (measurementNode.getAlias() != null) {
+ internalNode
+ .getAsEntityNode()
+ .addAliasChild(measurementNode.getAlias(),
measurementNode);
+ }
}
+ childNum--;
}
- childNum--;
+ stack.push(internalNode);
}
- stack.push(internalNode);
}
}
- ClusterSchemaTree result = new ClusterSchemaTree(stack.poll());
- result.templateMap = templateMap;
- result.hasLogicalMeasurementPath = hasLogicalView;
- result.hasNormalTimeSeries = hasNormalTimeSeries;
- return result;
+
+ public ClusterSchemaTree finish() {
+ try {
+ ClusterSchemaTree result = new ClusterSchemaTree(stack.poll());
+ result.templateMap = templateMap;
+ result.hasLogicalMeasurementPath = hasLogicalView;
+ result.hasNormalTimeSeries = hasNormalTimeSeries;
+ return result;
+ } finally {
+ reset();
+ }
+ }
+
+ private void reset() {
+ nodeType = 0;
+ childNum = 0;
+ stack.clear();
+ child = null;
+ hasLogicalView = false;
+ hasNormalTimeSeries = false;
+ // templateMap is set to the returned schema tree, so we should create a
new one
+ templateMap = new HashMap<>();
+ isFirstBatch = true;
+ }
+ }
+
+ public static ClusterSchemaTree deserialize(InputStream inputStream) throws
IOException {
+ SchemaNodeBatchDeserializer schemaNodeBatchDeserializer = new
SchemaNodeBatchDeserializer();
+ schemaNodeBatchDeserializer.deserializeFromBatch(inputStream);
+ return schemaNodeBatchDeserializer.finish();
}
/**
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/ISchemaTree.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/ISchemaTree.java
index 0288033b695..34cb2a09786 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/ISchemaTree.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/ISchemaTree.java
@@ -24,12 +24,13 @@ import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.commons.utils.TestOnly;
import org.apache.iotdb.db.schemaengine.template.Template;
+import org.apache.tsfile.utils.Accountable;
import org.apache.tsfile.utils.Pair;
import java.util.List;
import java.util.Set;
-public interface ISchemaTree {
+public interface ISchemaTree extends Accountable {
/**
* Return all measurement paths for given path pattern and filter the result
by slimit and offset.
*
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaEntityNode.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaEntityNode.java
index b877dc9d7a2..cf111e61b29 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaEntityNode.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaEntityNode.java
@@ -19,6 +19,7 @@
package org.apache.iotdb.db.queryengine.common.schematree.node;
+import org.apache.tsfile.utils.RamUsageEstimator;
import org.apache.tsfile.utils.ReadWriteIOUtils;
import java.io.IOException;
@@ -31,6 +32,9 @@ import static
org.apache.iotdb.commons.schema.SchemaConstant.NON_TEMPLATE;
public class SchemaEntityNode extends SchemaInternalNode {
+ private static final long SHALLOW_SIZE =
+ RamUsageEstimator.shallowSizeOfInstance(SchemaEntityNode.class);
+
private boolean isAligned;
private Map<String, SchemaMeasurementNode> aliasChildren;
@@ -117,6 +121,11 @@ public class SchemaEntityNode extends SchemaInternalNode {
@Override
public void serialize(OutputStream outputStream) throws IOException {
serializeChildren(outputStream);
+ this.serializeNodeOwnContent(outputStream);
+ }
+
+ @Override
+ public void serializeNodeOwnContent(OutputStream outputStream) throws
IOException {
ReadWriteIOUtils.write(getType(), outputStream);
ReadWriteIOUtils.write(name, outputStream);
ReadWriteIOUtils.write(isAligned, outputStream);
@@ -133,4 +142,18 @@ public class SchemaEntityNode extends SchemaInternalNode {
entityNode.setTemplateId(templateId);
return entityNode;
}
+
+ @Override
+ public long ramBytesUsed() {
+ return SHALLOW_SIZE
+ + RamUsageEstimator.sizeOf(name)
+ + RamUsageEstimator.sizeOfMapWithKnownShallowSize(
+ children,
+ RamUsageEstimator.SHALLOW_SIZE_OF_HASHMAP,
+ RamUsageEstimator.SHALLOW_SIZE_OF_HASHMAP_ENTRY)
+ + RamUsageEstimator.sizeOfMapWithKnownShallowSize(
+ aliasChildren,
+ RamUsageEstimator.SHALLOW_SIZE_OF_HASHMAP,
+ RamUsageEstimator.SHALLOW_SIZE_OF_HASHMAP_ENTRY);
+ }
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaInternalNode.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaInternalNode.java
index 5c6de241baf..84ccf5b35fa 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaInternalNode.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaInternalNode.java
@@ -19,6 +19,7 @@
package org.apache.iotdb.db.queryengine.common.schematree.node;
+import org.apache.tsfile.utils.RamUsageEstimator;
import org.apache.tsfile.utils.ReadWriteIOUtils;
import java.io.IOException;
@@ -30,6 +31,9 @@ import java.util.Map;
public class SchemaInternalNode extends SchemaNode {
+ private static final long SHALLOW_SIZE =
+ RamUsageEstimator.shallowSizeOfInstance(SchemaInternalNode.class);
+
protected Map<String, SchemaNode> children = new HashMap<>();
public SchemaInternalNode(String name) {
@@ -85,7 +89,10 @@ public class SchemaInternalNode extends SchemaNode {
public void serialize(OutputStream outputStream) throws IOException {
serializeChildren(outputStream);
+ serializeNodeOwnContent(outputStream);
+ }
+ public void serializeNodeOwnContent(OutputStream outputStream) throws
IOException {
ReadWriteIOUtils.write(getType(), outputStream);
ReadWriteIOUtils.write(name, outputStream);
ReadWriteIOUtils.write(children.size(), outputStream);
@@ -102,4 +109,14 @@ public class SchemaInternalNode extends SchemaNode {
return new SchemaInternalNode(name);
}
+
+ @Override
+ public long ramBytesUsed() {
+ return SHALLOW_SIZE
+ + RamUsageEstimator.sizeOf(name)
+ + RamUsageEstimator.sizeOfMapWithKnownShallowSize(
+ children,
+ RamUsageEstimator.SHALLOW_SIZE_OF_HASHMAP,
+ RamUsageEstimator.SHALLOW_SIZE_OF_HASHMAP_ENTRY);
+ }
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaMeasurementNode.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaMeasurementNode.java
index b1eaa7ff5c1..6f5bd07f08f 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaMeasurementNode.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaMeasurementNode.java
@@ -22,6 +22,7 @@ package
org.apache.iotdb.db.queryengine.common.schematree.node;
import org.apache.iotdb.commons.schema.view.LogicalViewSchema;
import
org.apache.iotdb.db.queryengine.common.schematree.IMeasurementSchemaInfo;
+import org.apache.tsfile.utils.RamUsageEstimator;
import org.apache.tsfile.utils.ReadWriteIOUtils;
import org.apache.tsfile.write.schema.IMeasurementSchema;
import org.apache.tsfile.write.schema.MeasurementSchema;
@@ -34,6 +35,9 @@ import java.util.Map;
public class SchemaMeasurementNode extends SchemaNode implements
IMeasurementSchemaInfo {
+ private static final long SHALLOW_SIZE =
+ RamUsageEstimator.shallowSizeOfInstance(SchemaMeasurementNode.class);
+
private String alias;
private IMeasurementSchema schema;
private Map<String, String> tagMap;
@@ -44,6 +48,22 @@ public class SchemaMeasurementNode extends SchemaNode
implements IMeasurementSch
this.schema = schema;
}
+ @Override
+ public long ramBytesUsed() {
+ return SHALLOW_SIZE
+ + RamUsageEstimator.sizeOf(name)
+ + RamUsageEstimator.sizeOf(alias)
+ + schema.ramBytesUsed()
+ + RamUsageEstimator.sizeOfMapWithKnownShallowSize(
+ tagMap,
+ RamUsageEstimator.SHALLOW_SIZE_OF_HASHMAP,
+ RamUsageEstimator.SHALLOW_SIZE_OF_HASHMAP_ENTRY)
+ + RamUsageEstimator.sizeOfMapWithKnownShallowSize(
+ attributeMap,
+ RamUsageEstimator.SHALLOW_SIZE_OF_HASHMAP,
+ RamUsageEstimator.SHALLOW_SIZE_OF_HASHMAP_ENTRY);
+ }
+
public String getAlias() {
return alias;
}
@@ -143,6 +163,10 @@ public class SchemaMeasurementNode extends SchemaNode
implements IMeasurementSch
@Override
public void serialize(OutputStream outputStream) throws IOException {
+ serializeNodeOwnContent(outputStream);
+ }
+
+ public void serializeNodeOwnContent(OutputStream outputStream) throws
IOException {
ReadWriteIOUtils.write(getType(), outputStream);
ReadWriteIOUtils.write(name, outputStream);
ReadWriteIOUtils.write(alias, outputStream);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaNode.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaNode.java
index e2625cd97ac..dd4e5e57a2e 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaNode.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/node/SchemaNode.java
@@ -21,13 +21,15 @@ package
org.apache.iotdb.db.queryengine.common.schematree.node;
import org.apache.iotdb.commons.schema.tree.ITreeNode;
+import org.apache.tsfile.utils.Accountable;
+
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
-public abstract class SchemaNode implements ITreeNode {
+public abstract class SchemaNode implements ITreeNode, Accountable {
public static final byte SCHEMA_INTERNAL_NODE = 0;
public static final byte SCHEMA_ENTITY_NODE = 1;
@@ -80,4 +82,6 @@ public abstract class SchemaNode implements ITreeNode {
public abstract byte getType();
public abstract void serialize(OutputStream outputStream) throws IOException;
+
+ public abstract void serializeNodeOwnContent(OutputStream outputStream)
throws IOException;
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaFetchScanOperator.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaFetchScanOperator.java
index f4b40c69b79..6cc8e06878c 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaFetchScanOperator.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaFetchScanOperator.java
@@ -23,7 +23,9 @@ import org.apache.iotdb.commons.exception.MetadataException;
import org.apache.iotdb.commons.exception.runtime.SchemaExecutionException;
import org.apache.iotdb.commons.path.PathPatternTree;
import org.apache.iotdb.commons.schema.SchemaConstant;
+import org.apache.iotdb.commons.utils.TestOnly;
import org.apache.iotdb.db.queryengine.common.schematree.ClusterSchemaTree;
+import org.apache.iotdb.db.queryengine.common.schematree.node.SchemaNode;
import org.apache.iotdb.db.queryengine.execution.MemoryEstimationHelper;
import org.apache.iotdb.db.queryengine.execution.operator.OperatorContext;
import
org.apache.iotdb.db.queryengine.execution.operator.source.SourceOperator;
@@ -36,12 +38,12 @@ import org.apache.tsfile.read.common.block.TsBlock;
import org.apache.tsfile.read.common.block.column.BinaryColumn;
import org.apache.tsfile.read.common.block.column.TimeColumn;
import org.apache.tsfile.utils.Binary;
+import org.apache.tsfile.utils.PublicBAOS;
import org.apache.tsfile.utils.RamUsageEstimator;
import org.apache.tsfile.utils.ReadWriteIOUtils;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
import java.util.Collections;
+import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
@@ -62,7 +64,12 @@ public class SchemaFetchScanOperator implements
SourceOperator {
private boolean isFinished = false;
private final PathPatternTree authorityScope;
- private static final int DEFAULT_MAX_TSBLOCK_SIZE_IN_BYTES =
+ private Iterator<SchemaNode> schemaNodeIteratorForSerialize = null;
+ private long schemaTreeMemCost;
+ private PublicBAOS baos = null;
+ // Reserve some bytes to avoid capacity grow
+ private static final int EXTRA_SIZE_TO_AVOID_GROW = 1024;
+ private static int DEFAULT_MAX_TSBLOCK_SIZE_IN_BYTES =
TSFileDescriptor.getInstance().getConfig().getMaxTsBlockSizeInBytes();
private static final long INSTANCE_SIZE =
@@ -152,12 +159,33 @@ public class SchemaFetchScanOperator implements
SourceOperator {
if (!hasNext()) {
throw new NoSuchElementException();
}
- isFinished = true;
- try {
- return fetchSchema();
- } catch (MetadataException e) {
- throw new SchemaExecutionException(e);
+
+ boolean isFirstBatch = schemaNodeIteratorForSerialize == null;
+ prepareSchemaNodeIteratorForSerialize();
+ // to indicate this binary data is a part of schema tree, and the
remaining parts will be sent
+ // later
+ ReadWriteIOUtils.write((byte) 2, baos);
+ // the estimated mem cost to deserialize the total schema tree
+ if (isFirstBatch) {
+ ReadWriteIOUtils.write(schemaTreeMemCost, baos);
+ }
+ while (schemaNodeIteratorForSerialize.hasNext()
+ && baos.size() < DEFAULT_MAX_TSBLOCK_SIZE_IN_BYTES) {
+ SchemaNode node = schemaNodeIteratorForSerialize.next();
+ node.serializeNodeOwnContent(baos);
}
+ byte[] currentBatch = baos.toByteArray();
+ baos.reset();
+ isFinished = !schemaNodeIteratorForSerialize.hasNext();
+ if (isFinished) {
+ // indicate all continuous binary data is finished
+ currentBatch[0] = 3;
+ releaseSchemaTree();
+ baos = null;
+ }
+ return new TsBlock(
+ new TimeColumn(1, new long[] {0}),
+ new BinaryColumn(1, Optional.empty(), new Binary[] {new
Binary(currentBatch)}));
}
@Override
@@ -172,7 +200,8 @@ public class SchemaFetchScanOperator implements
SourceOperator {
@Override
public void close() throws Exception {
- // do nothing
+ releaseSchemaTree();
+ baos = null;
}
@Override
@@ -180,26 +209,28 @@ public class SchemaFetchScanOperator implements
SourceOperator {
return sourceId;
}
- private TsBlock fetchSchema() throws MetadataException {
- ClusterSchemaTree schemaTree =
- fetchDevice
- ? schemaRegion.fetchDeviceSchema(patternTree, authorityScope)
- : schemaRegion.fetchSeriesSchema(
- patternTree, templateMap, withTags, withAttributes,
withTemplate, withAliasForce);
-
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ private void prepareSchemaNodeIteratorForSerialize() {
+ if (schemaNodeIteratorForSerialize != null) {
+ return;
+ }
try {
- // to indicate this binary data is database info
- ReadWriteIOUtils.write((byte) 1, outputStream);
-
- schemaTree.serialize(outputStream);
- } catch (IOException e) {
- // Totally memory operation. This case won't happen.
+ ClusterSchemaTree schemaTree =
+ fetchDevice
+ ? schemaRegion.fetchDeviceSchema(patternTree, authorityScope)
+ : schemaRegion.fetchSeriesSchema(
+ patternTree, templateMap, withTags, withAttributes,
withTemplate, withAliasForce);
+ schemaNodeIteratorForSerialize = schemaTree.getIteratorForSerialize();
+ baos = new PublicBAOS(DEFAULT_MAX_TSBLOCK_SIZE_IN_BYTES +
EXTRA_SIZE_TO_AVOID_GROW);
+ if (operatorContext != null) {
+ schemaTreeMemCost = schemaTree.ramBytesUsed();
+ operatorContext
+ .getInstanceContext()
+ .getMemoryReservationContext()
+ .reserveMemoryCumulatively(schemaTreeMemCost);
+ }
+ } catch (MetadataException e) {
+ throw new SchemaExecutionException(e);
}
- return new TsBlock(
- new TimeColumn(1, new long[] {0}),
- new BinaryColumn(
- 1, Optional.empty(), new Binary[] {new
Binary(outputStream.toByteArray())}));
}
@Override
@@ -221,6 +252,25 @@ public class SchemaFetchScanOperator implements
SourceOperator {
public long ramBytesUsed() {
return INSTANCE_SIZE
+
MemoryEstimationHelper.getEstimatedSizeOfAccountableObject(operatorContext)
+ + DEFAULT_MAX_TSBLOCK_SIZE_IN_BYTES
+ + EXTRA_SIZE_TO_AVOID_GROW
+ MemoryEstimationHelper.getEstimatedSizeOfAccountableObject(sourceId);
}
+
+ private void releaseSchemaTree() {
+ if (schemaTreeMemCost <= 0 || operatorContext == null) {
+ return;
+ }
+ operatorContext
+ .getInstanceContext()
+ .getMemoryReservationContext()
+ .releaseMemoryCumulatively(schemaTreeMemCost);
+ schemaTreeMemCost = 0;
+ schemaNodeIteratorForSerialize = null;
+ }
+
+ @TestOnly
+ public static void setDefaultMaxTsBlockSizeInBytes(int newSize) {
+ DEFAULT_MAX_TSBLOCK_SIZE_IN_BYTES = newSize;
+ }
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
index 9ec064245f4..dab31639205 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
@@ -535,7 +535,6 @@ public class AnalyzeVisitor extends
StatementVisitor<Analysis, MPPQueryContext>
context.setFetchSchemaCost(schemaFetchCost);
QueryPlanCostMetricSet.getInstance().recordPlanCost(SCHEMA_FETCHER,
schemaFetchCost);
}
-
analysis.setSchemaTree(schemaTree);
return schemaTree;
}
@@ -3610,6 +3609,7 @@ public class AnalyzeVisitor extends
StatementVisitor<Analysis, MPPQueryContext>
}
}
analysis.setSchemaTree(schemaTree);
+ context.setReleaseSchemaTreeAfterAnalyzing(false);
Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = new
HashMap<>();
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/Analyzer.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/Analyzer.java
index f7ca04f7d05..34b17003f1b 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/Analyzer.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/Analyzer.java
@@ -43,8 +43,18 @@ public class Analyzer {
public Analysis analyze(Statement statement) {
long startTime = System.nanoTime();
- Analysis analysis =
- new AnalyzeVisitor(partitionFetcher, schemaFetcher).process(statement,
context);
+ AnalyzeVisitor visitor = new AnalyzeVisitor(partitionFetcher,
schemaFetcher);
+ Analysis analysis = null;
+
context.setReserveMemoryForSchemaTreeFunc(context::reserveMemoryForFrontEnd);
+ try {
+ analysis = visitor.process(statement, context);
+ } finally {
+ if (analysis != null && context.releaseSchemaTreeAfterAnalyzing()) {
+ analysis.setSchemaTree(null);
+ context.releaseMemoryForSchemaTree();
+ }
+ context.setReserveMemoryForSchemaTreeFunc(null);
+ }
if (statement.isQuery()) {
QueryPlanCostMetricSet.getInstance().recordPlanCost(ANALYZER,
System.nanoTime() - startTime);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/schema/ClusterSchemaFetchExecutor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/schema/ClusterSchemaFetchExecutor.java
index d62b5640d9d..e71b3299612 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/schema/ClusterSchemaFetchExecutor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/schema/ClusterSchemaFetchExecutor.java
@@ -252,6 +252,8 @@ class ClusterSchemaFetchExecutor {
}
try (SetThreadName threadName = new
SetThreadName(executionResult.queryId.getId())) {
ClusterSchemaTree result = new ClusterSchemaTree();
+ ClusterSchemaTree.SchemaNodeBatchDeserializer deserializer =
+ new ClusterSchemaTree.SchemaNodeBatchDeserializer();
Set<String> databaseSet = new HashSet<>();
while (coordinator.getQueryExecution(queryId).hasNextResult()) {
// The query will be transited to FINISHED when invoking
getBatchResult() at the last time
@@ -268,7 +270,7 @@ class ClusterSchemaFetchExecutor {
}
Column column = tsBlock.get().getColumn(0);
for (int i = 0; i < column.getPositionCount(); i++) {
- parseFetchedData(column.getBinary(i), result, databaseSet);
+ parseFetchedData(column.getBinary(i), result, deserializer,
databaseSet, context);
}
}
result.setDatabases(databaseSet);
@@ -283,7 +285,11 @@ class ClusterSchemaFetchExecutor {
}
private void parseFetchedData(
- Binary data, ClusterSchemaTree resultSchemaTree, Set<String>
databaseSet) {
+ Binary data,
+ ClusterSchemaTree resultSchemaTree,
+ ClusterSchemaTree.SchemaNodeBatchDeserializer deserializer,
+ Set<String> databaseSet,
+ MPPQueryContext context) {
InputStream inputStream = new ByteArrayInputStream(data.getValues());
try {
byte type = ReadWriteIOUtils.readByte(inputStream);
@@ -293,7 +299,24 @@ class ClusterSchemaFetchExecutor {
databaseSet.add(ReadWriteIOUtils.readString(inputStream));
}
} else if (type == 1) {
-
resultSchemaTree.mergeSchemaTree(ClusterSchemaTree.deserialize(inputStream));
+ // for data from old version
+ ClusterSchemaTree deserializedSchemaTree =
ClusterSchemaTree.deserialize(inputStream);
+ if (context != null) {
+
context.reserveMemoryForSchemaTree(deserializedSchemaTree.ramBytesUsed());
+ }
+ resultSchemaTree.mergeSchemaTree(deserializedSchemaTree);
+ } else if (type == 2 || type == 3) {
+ if (deserializer.isFirstBatch()) {
+ long memCost = ReadWriteIOUtils.readLong(inputStream);
+ if (context != null) {
+ context.reserveMemoryForSchemaTree(memCost);
+ }
+ }
+ deserializer.deserializeFromBatch(inputStream);
+ if (type == 3) {
+ // 'type == 3' indicates this batch is finished
+ resultSchemaTree.mergeSchemaTree(deserializer.finish());
+ }
} else {
throw new RuntimeException(
new MetadataException("Failed to fetch schema because of
unrecognized data"));
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/template/Template.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/template/Template.java
index 8fe86a9abfe..6639427b59b 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/template/Template.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/template/Template.java
@@ -25,6 +25,8 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.file.metadata.enums.CompressionType;
import org.apache.tsfile.file.metadata.enums.TSEncoding;
+import org.apache.tsfile.utils.Accountable;
+import org.apache.tsfile.utils.RamUsageEstimator;
import org.apache.tsfile.utils.ReadWriteIOUtils;
import org.apache.tsfile.write.schema.IMeasurementSchema;
import org.apache.tsfile.write.schema.MeasurementSchema;
@@ -39,8 +41,9 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-public class Template implements Serializable {
+public class Template implements Serializable, Accountable {
+ private static final long SHALLOW_SIZE =
RamUsageEstimator.shallowSizeOfInstance(Template.class);
private int id;
private String name;
private boolean isDirectAligned;
@@ -226,4 +229,14 @@ public class Template implements Serializable {
public int hashCode() {
return new HashCodeBuilder(17,
37).append(name).append(schemaMap).toHashCode();
}
+
+ @Override
+ public long ramBytesUsed() {
+ return SHALLOW_SIZE
+ + RamUsageEstimator.sizeOf(name)
+ + RamUsageEstimator.sizeOfMapWithKnownShallowSize(
+ schemaMap,
+ RamUsageEstimator.SHALLOW_SIZE_OF_CONCURRENT_HASHMAP,
+ RamUsageEstimator.SHALLOW_SIZE_OF_CONCURRENT_HASHMAP_ENTRY);
+ }
}
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaFetchScanOperatorTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaFetchScanOperatorTest.java
index 50249bc55d5..2ac62e4e633 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaFetchScanOperatorTest.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaFetchScanOperatorTest.java
@@ -24,9 +24,9 @@ import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.commons.path.PathPatternTree;
import org.apache.iotdb.db.queryengine.common.schematree.ClusterSchemaTree;
import org.apache.iotdb.db.queryengine.common.schematree.DeviceSchemaInfo;
-import org.apache.iotdb.db.queryengine.common.schematree.ISchemaTree;
import org.apache.iotdb.db.schemaengine.schemaregion.ISchemaRegion;
+import org.apache.tsfile.common.conf.TSFileDescriptor;
import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.file.metadata.enums.CompressionType;
import org.apache.tsfile.file.metadata.enums.TSEncoding;
@@ -36,19 +36,42 @@ import org.apache.tsfile.utils.Pair;
import org.apache.tsfile.utils.ReadWriteIOUtils;
import org.apache.tsfile.write.schema.IMeasurementSchema;
import org.apache.tsfile.write.schema.MeasurementSchema;
+import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import org.mockito.Mockito;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
+@RunWith(Parameterized.class)
public class SchemaFetchScanOperatorTest {
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection<Object[]> data() {
+ return Arrays.asList(
+ new Object[][] {
+ {1024}, {128 * 1024}, {16},
+ });
+ }
+
+ public SchemaFetchScanOperatorTest(int maxTsBlockSizeInBytes) {
+
SchemaFetchScanOperator.setDefaultMaxTsBlockSizeInBytes(maxTsBlockSizeInBytes);
+ }
+
+ @After
+ public void tearDown() {
+ SchemaFetchScanOperator.setDefaultMaxTsBlockSizeInBytes(
+ TSFileDescriptor.getInstance().getConfig().getMaxTsBlockSizeInBytes());
+ }
+
@Test
public void testSchemaFetchResult() throws Exception {
ISchemaRegion schemaRegion = mockSchemaRegion();
@@ -70,16 +93,25 @@ public class SchemaFetchScanOperatorTest {
true,
false);
- Assert.assertTrue(schemaFetchScanOperator.hasNext());
-
- TsBlock tsBlock = schemaFetchScanOperator.next();
-
+ ClusterSchemaTree.SchemaNodeBatchDeserializer deserializer =
+ new ClusterSchemaTree.SchemaNodeBatchDeserializer();
+ byte type = 0;
+ while (schemaFetchScanOperator.hasNext()) {
+ TsBlock tsBlock = schemaFetchScanOperator.next();
+ Binary binary = tsBlock.getColumn(0).getBinary(0);
+ InputStream inputStream = new ByteArrayInputStream(binary.getValues());
+ if (!deserializer.isFirstBatch()) {
+ Assert.assertEquals(2, type);
+ }
+ type = ReadWriteIOUtils.readByte(inputStream);
+ if (deserializer.isFirstBatch()) {
+ ReadWriteIOUtils.readLong(inputStream);
+ }
+ deserializer.deserializeFromBatch(inputStream);
+ }
+ Assert.assertEquals(3, type);
Assert.assertFalse(schemaFetchScanOperator.hasNext());
-
- Binary binary = tsBlock.getColumn(0).getBinary(0);
- InputStream inputStream = new ByteArrayInputStream(binary.getValues());
- Assert.assertEquals(1, ReadWriteIOUtils.readByte(inputStream));
- ISchemaTree schemaTree = ClusterSchemaTree.deserialize(inputStream);
+ ClusterSchemaTree schemaTree = deserializer.finish();
DeviceSchemaInfo deviceSchemaInfo =
schemaTree.searchDeviceSchemaInfo(
diff --git a/pom.xml b/pom.xml
index 2ae4f3a04e4..58bd5e89bca 100644
--- a/pom.xml
+++ b/pom.xml
@@ -175,7 +175,7 @@
<thrift.version>0.14.1</thrift.version>
<xz.version>1.9</xz.version>
<zstd-jni.version>1.5.6-3</zstd-jni.version>
- <tsfile.version>1.1.2-250725-SNAPSHOT</tsfile.version>
+ <tsfile.version>1.1.2-250801-SNAPSHOT</tsfile.version>
</properties>
<!--
if we claim dependencies in dependencyManagement, then we do not claim