JackieTien97 commented on code in PR #18127:
URL: https://github.com/apache/iotdb/pull/18127#discussion_r3534093133


##########
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/RemoveDataNodeHandler.java:
##########
@@ -455,6 +456,9 @@ public void 
removeDataNodePersistence(List<TDataNodeLocation> removedDataNodes)
       PartitionMetrics.unbindDataNodePartitionMetricsWhenUpdate(
           MetricService.getInstance(),
           
NodeUrlUtils.convertTEndPointUrl(dataNodeLocation.getClientRpcEndPoint()));
+      // Drop the removed DataNode's metadata-lease contact/capability state 
so it is not retained,
+      // and a future DataNode reusing the id cannot inherit stale fencing 
history.

Review Comment:
   id will always increase, no new DN will reuse removed DN's id



##########
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java:
##########
@@ -2416,12 +2416,17 @@ public TDeleteTableDeviceResp deleteDevices(
     }
   }
 
+  // only care about the AbstractAlterOrDropTableProcedure(except the drop 
table/view)
+  // and the DeleteDatabaseProcedure

Review Comment:
   explain why we need to exclude the drop table/view procedure



##########
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/AbstractAlterOrDropTableProcedure.java:
##########
@@ -91,17 +93,22 @@ protected void preRelease(final ConfigNodeProcedureEnv env) 
{
   }
 
   protected void preRelease(final ConfigNodeProcedureEnv env, final @Nullable 
String oldName) {
-    final Map<Integer, TSStatus> failedResults =
-        SchemaUtils.preReleaseTable(database, table, env.getConfigManager(), 
oldName);
-
-    if (!failedResults.isEmpty()) {
-      // All dataNodes must clear the related schema cache
+    // Proceed once every unreachable DataNode is provably self-fenced instead 
of hard-failing the
+    // DDL: a fenced DataNode fails closed on its now-stale table cache and 
resyncs on lease
+    // recovery, so it cannot serve dirty schema. Only fail if an unacked 
DataNode is not provably
+    // fenced (it may still be serving clients).
+    final TUpdateTableReq req = SchemaUtils.BuildPreUpdateTableReq(database, 
table, oldName);

Review Comment:
   ```suggestion
       final TUpdateTableReq req = SchemaUtils.buildPreUpdateTableReq(database, 
table, oldName);
   ```



##########
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/AbstractAlterOrDropTableProcedure.java:
##########
@@ -140,18 +147,21 @@ protected void rollbackPreRelease(final 
ConfigNodeProcedureEnv env) {
 
   protected void rollbackPreRelease(
       final ConfigNodeProcedureEnv env, final @Nullable String tableName) {
-    final Map<Integer, TSStatus> failedResults =
-        SchemaUtils.rollbackPreRelease(
-            database, table.getTableName(), env.getConfigManager(), tableName);
-
-    if (!failedResults.isEmpty()) {
-      // All dataNodes must clear the related schema cache
+    // A down DataNode must not block rollback either: proceed past 
provably-fenced DataNodes (which
+    // resync on recovery) and only fail on an unacked DataNode that is not 
provably fenced.
+    final TUpdateTableReq req =
+        SchemaUtils.rollbackUpdateTableReq(database, table.getTableName(), 
tableName);
+    final boolean proceeded =
+        new ClusterCachePropagator(env.getConfigManager())
+            .propagate(targets -> SchemaUtils.broadcastTableUpdate(req, 
targets));
+
+    if (!proceeded) {
       LOGGER.warn(
           
ProcedureMessages.FAILED_TO_ROLLBACK_PRE_RELEASE_FOR_TABLE_INFO_TO_DATANODE,
           getActionMessage(),
           database,
           table.getTableName(),
-          failedResults);
+          "an unreachable DataNode is not provably fenced");

Review Comment:
   follow the i18n standarn, define a constant in both zh and en.



##########
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/CreateTableProcedure.java:
##########
@@ -151,16 +153,22 @@ protected void preCreateTable(final 
ConfigNodeProcedureEnv env) {
   }
 
   private void preReleaseTable(final ConfigNodeProcedureEnv env) {
-    final Map<Integer, TSStatus> failedResults =
-        SchemaUtils.preReleaseTable(database, table, env.getConfigManager(), 
null);
-
-    if (!failedResults.isEmpty()) {
-      // All dataNodes must clear the related schema cache
+    // Broadcast the pre-update to all DataNodes. Instead of failing whenever 
any DataNode is
+    // unreachable, proceed once every unacked DataNode is provably 
self-fenced: such a DataNode
+    // fails closed on its (now-stale) table cache and resyncs on lease 
recovery, so it cannot serve
+    // dirty schema. Only fail if an unacked DataNode is not provably fenced 
(it may still be
+    // serving clients).
+    final TUpdateTableReq req = SchemaUtils.BuildPreUpdateTableReq(database, 
table, null);
+    final boolean proceeded =
+        new ClusterCachePropagator(env.getConfigManager())
+            .propagate(targets -> SchemaUtils.broadcastTableUpdate(req, 
targets));
+
+    if (!proceeded) {
       LOGGER.warn(
           
ProcedureMessages.FAILED_TO_SYNC_TABLE_PRE_CREATE_INFO_TO_DATANODE_FAILURE,
           database,
           table.getTableName(),
-          failedResults);
+          "an unreachable DataNode is not provably fenced");

Review Comment:
   i18n



##########
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/AlterTimeSeriesDataTypeProcedure.java:
##########
@@ -249,26 +246,17 @@ public static void invalidateCache(
       final String requestMessage,
       final Consumer<ProcedureException> setFailure,
       final boolean needLock) {
-    final Map<Integer, TDataNodeLocation> dataNodeLocationMap =
-        
env.getConfigManager().getNodeManager().getRegisteredDataNodeLocations();
-    final DataNodeAsyncRequestContext<TInvalidateMatchedSchemaCacheReq, 
TSStatus> clientHandler =
-        new DataNodeAsyncRequestContext<>(
-            CnToDnAsyncRequestType.INVALIDATE_MATCHED_SCHEMA_CACHE,
-            new 
TInvalidateMatchedSchemaCacheReq(measurementPathBytes).setNeedLock(needLock),
-            dataNodeLocationMap);
-    
CnToDnInternalServiceAsyncRequestManager.getInstance().sendAsyncRequestWithRetry(clientHandler);
-    final Map<Integer, TSStatus> statusMap = clientHandler.getResponseMap();
-    for (final TSStatus status : statusMap.values()) {
+    // Proceed past provably-fenced DataNodes instead of hard-failing on the 
first unreachable one
+    // (see SchemaUtils.invalidateMatchedSchemaCache). Runs before the 
physical datatype change, so
+    // the "alter only after PROCEED" ordering holds.
+    if (!SchemaUtils.invalidateMatchedSchemaCache(
+        env.getConfigManager(), measurementPathBytes, needLock)) {
       // All dataNodes must clear the related schemaEngine cache
-      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
-        LOGGER.error(
-            
ProcedureMessages.FAILED_TO_INVALIDATE_SCHEMAENGINE_CACHE_OF_TIMESERIES,
-            requestMessage);
-        setFailure.accept(
-            new ProcedureException(
-                new 
MetadataException(ProcedureMessages.INVALIDATE_SCHEMAENGINE_CACHE_FAILED)));
-        return;
-      }
+      LOGGER.error(

Review Comment:
   warn



##########
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteLogicalViewProcedure.java:
##########
@@ -167,26 +164,15 @@ protected List<TConsensusGroupId> 
processResponseOfOneDataNode(
   }
 
   private void invalidateCache(final ConfigNodeProcedureEnv env) {
-    final Map<Integer, TDataNodeLocation> dataNodeLocationMap =
-        
env.getConfigManager().getNodeManager().getRegisteredDataNodeLocations();
-    final DataNodeAsyncRequestContext<TInvalidateMatchedSchemaCacheReq, 
TSStatus> clientHandler =
-        new DataNodeAsyncRequestContext<>(
-            CnToDnAsyncRequestType.INVALIDATE_MATCHED_SCHEMA_CACHE,
-            new TInvalidateMatchedSchemaCacheReq(patternTreeBytes),
-            dataNodeLocationMap);
-    
CnToDnInternalServiceAsyncRequestManager.getInstance().sendAsyncRequestWithRetry(clientHandler);
-    final Map<Integer, TSStatus> statusMap = clientHandler.getResponseMap();
-    for (final TSStatus status : statusMap.values()) {
+    if (!SchemaUtils.invalidateMatchedSchemaCache(
+        env.getConfigManager(), patternTreeBytes, false)) {
       // all dataNodes must clear the related schemaengine cache
-      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
-        LOGGER.error(
-            ProcedureMessages.FAILED_TO_INVALIDATE_SCHEMAENGINE_CACHE_OF_VIEW, 
requestMessage);
-        setFailure(
-            new ProcedureException(
-                new MetadataException(
-                    
ProcedureMessages.INVALIDATE_VIEW_SCHEMAENGINE_CACHE_FAILED)));
-        return;
-      }
+      LOGGER.error(

Review Comment:
   warn



##########
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/DropTableColumnProcedure.java:
##########
@@ -150,43 +151,48 @@ private void checkAndPreDeleteColumn(final 
ConfigNodeProcedureEnv env) {
   }
 
   private void invalidateCache(final ConfigNodeProcedureEnv env) {
-    final Map<Integer, TDataNodeLocation> dataNodeLocationMap =
-        
env.getConfigManager().getNodeManager().getRegisteredDataNodeLocations();
-    final DataNodeAsyncRequestContext<TInvalidateColumnCacheReq, TSStatus> 
clientHandler =
-        new DataNodeAsyncRequestContext<>(
-            CnToDnAsyncRequestType.INVALIDATE_COLUMN_CACHE,
-            new TInvalidateColumnCacheReq(database, tableName, columnName, 
isAttributeColumn),
-            dataNodeLocationMap);
-    
CnToDnInternalServiceAsyncRequestManager.getInstance().sendAsyncRequestWithRetry(clientHandler);
-    final Map<Integer, TSStatus> statusMap = clientHandler.getResponseMap();
-    for (final TSStatus status : statusMap.values()) {
-      // All dataNodes must clear the related schemaEngine cache
-      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
-        LOGGER.error(
-            ProcedureMessages.FAILED_TO_INVALIDATE_COLUMN_S_CACHE_OF_TABLE,
-            isAttributeColumn ? "attribute" : "measurement",
-            columnName,
-            database,
-            tableName);
-        setFailure(
-            new ProcedureException(
-                new MetadataException(
-                    String.format(
-                        
ProcedureMessages.INVALIDATE_COLUMN_CACHE_FAILED_FOR_TABLE,
-                        columnName,
-                        database,
-                        tableName))));
-        return;
-      }
-    }
+    TInvalidateColumnCacheReq req =
+        new TInvalidateColumnCacheReq(database, tableName, columnName, 
isAttributeColumn);
+    final boolean proceeded =
+        new ClusterCachePropagator(env.getConfigManager())
+            .propagate(targets -> broadCastInvalidateCache(req, targets));
 
+    if (!proceeded) {
+      LOGGER.error(

Review Comment:
   no need to be error, just warn is enough, error only for unexpected fatal 
cases.



##########
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/PreDeleteTsTable.java:
##########
@@ -0,0 +1,39 @@
+/*
+ * 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.commons.schema.table;
+
+import org.apache.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class PreDeleteTsTable extends TsTable {
+  public static final int PRE_DELETE_MARKER = -2;

Review Comment:
   ```suggestion
     public static final int PRE_DELETE_MARKER = -3;
   ```
   
   put it as an enum, add comments that -2 is reserved and don't use.



##########
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/AlterLogicalViewProcedure.java:
##########
@@ -123,27 +120,15 @@ protected Flow executeFromState(
   }
 
   private void invalidateCache(final ConfigNodeProcedureEnv env) {
-    final Map<Integer, TDataNodeLocation> dataNodeLocationMap =
-        
env.getConfigManager().getNodeManager().getRegisteredDataNodeLocations();
-    final DataNodeAsyncRequestContext<TInvalidateMatchedSchemaCacheReq, 
TSStatus> clientHandler =
-        new DataNodeAsyncRequestContext<>(
-            CnToDnAsyncRequestType.INVALIDATE_MATCHED_SCHEMA_CACHE,
-            new TInvalidateMatchedSchemaCacheReq(patternTreeBytes),
-            dataNodeLocationMap);
-    
CnToDnInternalServiceAsyncRequestManager.getInstance().sendAsyncRequestWithRetry(clientHandler);
-    final Map<Integer, TSStatus> statusMap = clientHandler.getResponseMap();
-    for (final TSStatus status : statusMap.values()) {
+    if (!SchemaUtils.invalidateMatchedSchemaCache(
+        env.getConfigManager(), patternTreeBytes, false)) {
       // all dataNodes must clear the related schemaengine cache
-      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
-        LOGGER.error(
-            ProcedureMessages.FAILED_TO_INVALIDATE_SCHEMAENGINE_CACHE_OF_VIEW,
-            viewPathToSourceMap.keySet());
-        setFailure(
-            new ProcedureException(
-                new MetadataException(
-                    
ProcedureMessages.INVALIDATE_VIEW_SCHEMAENGINE_CACHE_FAILED)));
-        return;
-      }
+      LOGGER.error(

Review Comment:
   warn?



##########
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteTimeSeriesProcedure.java:
##########
@@ -197,26 +194,18 @@ public static void invalidateCache(
       final String requestMessage,
       final Consumer<ProcedureException> setFailure,
       final boolean needLock) {
-    final Map<Integer, TDataNodeLocation> dataNodeLocationMap =
-        
env.getConfigManager().getNodeManager().getRegisteredDataNodeLocations();
-    final DataNodeAsyncRequestContext<TInvalidateMatchedSchemaCacheReq, 
TSStatus> clientHandler =
-        new DataNodeAsyncRequestContext<>(
-            CnToDnAsyncRequestType.INVALIDATE_MATCHED_SCHEMA_CACHE,
-            new 
TInvalidateMatchedSchemaCacheReq(patternTreeBytes).setNeedLock(needLock),
-            dataNodeLocationMap);
-    
CnToDnInternalServiceAsyncRequestManager.getInstance().sendAsyncRequestWithRetry(clientHandler);
-    final Map<Integer, TSStatus> statusMap = clientHandler.getResponseMap();
-    for (final TSStatus status : statusMap.values()) {
+    // Proceed once every unreachable DataNode is provably self-fenced (it 
fails closed on its
+    // schema cache and resyncs on recovery, so it cannot serve the 
to-be-deleted/altered series),
+    // instead of hard-failing on the first unreachable DataNode. This runs 
before the physical
+    // delete in the state machine, so the "delete only after PROCEED" 
ordering holds.
+    if (!SchemaUtils.invalidateMatchedSchemaCache(
+        env.getConfigManager(), patternTreeBytes, needLock)) {
       // All dataNodes must clear the related schemaEngine cache
-      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
-        LOGGER.error(
-            
ProcedureMessages.FAILED_TO_INVALIDATE_SCHEMAENGINE_CACHE_OF_TIMESERIES,
-            requestMessage);
-        setFailure.accept(
-            new ProcedureException(
-                new 
MetadataException(ProcedureMessages.INVALIDATE_SCHEMAENGINE_CACHE_FAILED)));
-        return;
-      }
+      LOGGER.error(

Review Comment:
   warn



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to