This is an automated email from the ASF dual-hosted git repository.
jiangtian 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 1e495354fe5 Avoid the NPE problem occur that tsTable is null (#15618)
1e495354fe5 is described below
commit 1e495354fe5cb2708712360b1e032350d54a1e84
Author: libo <[email protected]>
AuthorDate: Tue Jun 3 10:24:11 2025 +0800
Avoid the NPE problem occur that tsTable is null (#15618)
* Avoid the NPE problem occur that tsTable is null, and ensure if table is
not exist and catch this exception to tell leader datanode for retry or do
nothing.
* Avoid the NPE problem occur that tsTable is null via retry to get the
tsTable.
* Add license description
---
.../java/org/apache/iotdb/rpc/TSStatusCode.java | 1 +
.../dataregion/DataExecutionVisitor.java | 5 +++
.../dataregion/DataRegionStateMachine.java | 4 ++
.../runtime/TableLostRuntimeException.java | 36 +++++++++++++++++
.../runtime/TableNotExistsRuntimeException.java | 36 +++++++++++++++++
.../db/storageengine/dataregion/DataRegion.java | 47 ++++++++++++++++++++--
6 files changed, 126 insertions(+), 3 deletions(-)
diff --git
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
index d054a31e74d..3f7eb8f6507 100644
---
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
+++
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
@@ -91,6 +91,7 @@ public enum TSStatusCode {
TABLE_NOT_EXISTS(550),
TABLE_ALREADY_EXISTS(551),
COLUMN_ALREADY_EXISTS(552),
+ TABLE_IS_LOST(553),
ONLY_LOGICAL_VIEW(560),
// Storage Engine
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataExecutionVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataExecutionVisitor.java
index 43d58119b00..7431aa9a79d 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataExecutionVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataExecutionVisitor.java
@@ -27,6 +27,8 @@ import org.apache.iotdb.db.exception.BatchProcessException;
import org.apache.iotdb.db.exception.WriteProcessException;
import org.apache.iotdb.db.exception.WriteProcessRejectException;
import org.apache.iotdb.db.exception.query.OutOfTTLException;
+import org.apache.iotdb.db.exception.runtime.TableLostRuntimeException;
+import org.apache.iotdb.db.exception.runtime.TableNotExistsRuntimeException;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.pipe.PipeEnrichedDeleteDataNode;
@@ -160,6 +162,9 @@ public class DataExecutionVisitor extends
PlanVisitor<TSStatus, DataRegion> {
}
}
return firstStatus;
+ } catch (TableNotExistsRuntimeException | TableLostRuntimeException e) {
+ LOGGER.error("Error in executing plan node: {}, caused by {}", node,
e.getMessage());
+ return RpcUtils.getStatus(e.getErrorCode(), e.getMessage());
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachine.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachine.java
index c430be4b174..cfee2b54a6e 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachine.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachine.java
@@ -230,6 +230,10 @@ public class DataRegionStateMachine extends
BaseStateMachine {
Thread.currentThread().interrupt();
}
} else {
+ if (TSStatusCode.TABLE_NOT_EXISTS.getStatusCode() == result.getCode()
+ || TSStatusCode.TABLE_IS_LOST.getStatusCode() == result.getCode())
{
+ logger.info("table is not exists or lost, result code is {}",
result.getCode());
+ }
break;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/runtime/TableLostRuntimeException.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/runtime/TableLostRuntimeException.java
new file mode 100644
index 00000000000..572be2f0974
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/runtime/TableLostRuntimeException.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.exception.runtime;
+
+import org.apache.iotdb.commons.exception.IoTDBRuntimeException;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+public class TableLostRuntimeException extends IoTDBRuntimeException {
+
+ public TableLostRuntimeException(final String databaseName, final String
tableName) {
+ super(
+ String.format("Table %s in the database %s is lost unexpected.",
tableName, databaseName),
+ TSStatusCode.TABLE_IS_LOST.getStatusCode());
+ }
+
+ public TableLostRuntimeException(final Throwable cause) {
+ super(cause, TSStatusCode.TABLE_IS_LOST.getStatusCode());
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/runtime/TableNotExistsRuntimeException.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/runtime/TableNotExistsRuntimeException.java
new file mode 100644
index 00000000000..8590b4c70cf
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/runtime/TableNotExistsRuntimeException.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.exception.runtime;
+
+import org.apache.iotdb.commons.exception.IoTDBRuntimeException;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+public class TableNotExistsRuntimeException extends IoTDBRuntimeException {
+
+ public TableNotExistsRuntimeException(final String databaseName, final
String tableName) {
+ super(
+ String.format("Table %s in the database %s is not exists.", tableName,
databaseName),
+ TSStatusCode.TABLE_NOT_EXISTS.getStatusCode());
+ }
+
+ public TableNotExistsRuntimeException(final Throwable cause) {
+ super(cause, TSStatusCode.TABLE_NOT_EXISTS.getStatusCode());
+ }
+}
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 b698469b51d..0f81908a435 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
@@ -20,6 +20,7 @@
package org.apache.iotdb.db.storageengine.dataregion;
import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.commons.client.exception.ClientManagerException;
import org.apache.iotdb.commons.cluster.NodeStatus;
import org.apache.iotdb.commons.concurrent.IoTDBThreadPoolFactory;
import org.apache.iotdb.commons.conf.CommonDescriptor;
@@ -29,6 +30,8 @@ import org.apache.iotdb.commons.file.SystemFileFactory;
import org.apache.iotdb.commons.path.IFullPath;
import org.apache.iotdb.commons.path.MeasurementPath;
import org.apache.iotdb.commons.schema.SchemaConstant;
+import org.apache.iotdb.commons.schema.table.TsTable;
+import org.apache.iotdb.commons.schema.table.TsTableInternalRPCUtil;
import org.apache.iotdb.commons.service.metric.MetricService;
import org.apache.iotdb.commons.service.metric.PerformanceOverviewMetrics;
import org.apache.iotdb.commons.service.metric.enums.Metric;
@@ -37,6 +40,7 @@ import org.apache.iotdb.commons.utils.CommonDateTimeUtils;
import org.apache.iotdb.commons.utils.RetryUtils;
import org.apache.iotdb.commons.utils.TestOnly;
import org.apache.iotdb.commons.utils.TimePartitionUtils;
+import org.apache.iotdb.confignode.rpc.thrift.TDescTableResp;
import org.apache.iotdb.consensus.ConsensusFactory;
import org.apache.iotdb.db.conf.IoTDBConfig;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
@@ -50,11 +54,15 @@ import org.apache.iotdb.db.exception.load.LoadFileException;
import org.apache.iotdb.db.exception.query.OutOfTTLException;
import org.apache.iotdb.db.exception.query.QueryProcessException;
import org.apache.iotdb.db.exception.quota.ExceedQuotaException;
+import org.apache.iotdb.db.exception.runtime.TableLostRuntimeException;
+import org.apache.iotdb.db.exception.runtime.TableNotExistsRuntimeException;
import org.apache.iotdb.db.pipe.consensus.deletion.DeletionResource;
import org.apache.iotdb.db.pipe.consensus.deletion.DeletionResource.Status;
import org.apache.iotdb.db.pipe.consensus.deletion.DeletionResourceManager;
import
org.apache.iotdb.db.pipe.consensus.deletion.persist.PageCacheDeletionBuffer;
import
org.apache.iotdb.db.pipe.extractor.dataregion.realtime.listener.PipeInsertionDataNodeListener;
+import org.apache.iotdb.db.protocol.client.ConfigNodeClientManager;
+import org.apache.iotdb.db.protocol.client.ConfigNodeInfo;
import org.apache.iotdb.db.queryengine.common.DeviceContext;
import org.apache.iotdb.db.queryengine.execution.fragment.QueryContext;
import org.apache.iotdb.db.queryengine.metric.QueryResourceMetricSet;
@@ -147,6 +155,7 @@ import org.apache.iotdb.rpc.RpcUtils;
import org.apache.iotdb.rpc.TSStatusCode;
import org.apache.commons.io.FileUtils;
+import org.apache.thrift.TException;
import org.apache.tsfile.file.metadata.ChunkMetadata;
import org.apache.tsfile.file.metadata.IDeviceID;
import org.apache.tsfile.fileSystem.FSFactoryProducer;
@@ -1399,9 +1408,41 @@ public class DataRegion implements IDataRegionForQuery {
if (tableName != null) {
tsFileProcessor.registerToTsFile(
tableName,
- t ->
-
TableSchema.of(DataNodeTableCache.getInstance().getTable(getDatabaseName(), t))
- .toTsFileTableSchemaNoAttribute());
+ t -> {
+ TsTable tsTable =
DataNodeTableCache.getInstance().getTable(getDatabaseName(), t);
+ if (tsTable == null) {
+ // There is a high probability that the leader node has been
executed and is currently
+ // located in the follower node.
+ if (node.isGeneratedByRemoteConsensusLeader()) {
+ // If current node is follower, after request config node and
get the answer that
+ // table is exist or not, then tell leader node when table is
not exist.
+ try {
+ TDescTableResp resp =
+ ConfigNodeClientManager.getInstance()
+ .borrowClient(ConfigNodeInfo.CONFIG_REGION_ID)
+ .describeTable(getDatabaseName(), tableName, false);
+ tsTable =
+ (resp != null) && (resp.tableInfo != null)
+ ?
TsTableInternalRPCUtil.deserializeSingleTsTable(resp.getTableInfo())
+ : null;
+ } catch (TException | ClientManagerException e) {
+ logger.error(
+ "Remote request config node failed that judgment if
table is exist, occur exception. {}",
+ e.getMessage());
+ }
+ if (tsTable == null) {
+ throw new TableNotExistsRuntimeException(getDatabaseName(),
tableName);
+ }
+ } else {
+ // Here may be invoked by leader node, the table is very
unexpected not exist in the
+ // DataNodeTableCache
+ logger.error(
+ "Due tsTable is null, table schema can't be got, leader
node occur special situation need to resolve.");
+ throw new TableLostRuntimeException(getDatabaseName(),
tableName);
+ }
+ }
+ return TableSchema.of(tsTable).toTsFileTableSchemaNoAttribute();
+ });
}
}