sanpwc commented on a change in pull request #642:
URL: https://github.com/apache/ignite-3/pull/642#discussion_r829055639



##########
File path: 
modules/metastorage-client/src/main/java/org/apache/ignite/internal/metastorage/client/MetaStorageService.java
##########
@@ -31,6 +31,20 @@
  * Defines interface for access to a meta storage service.
  */
 public interface MetaStorageService {
+    /**
+     * Retrieves a current revision.
+     *
+     * @return Revision.
+     */
+    CompletableFuture<Long> revision();

Review comment:
       Both introduced methods should be removed, ya?

##########
File path: 
modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
##########
@@ -98,6 +103,12 @@
      */
     private static final Path PARTITIONS_STORE_PATH = Paths.get("db");
 
+    /**
+     * Difference between the local node applied revision and distributed data 
storage revision on start.
+     * TODO: IGNITE-16488 Move the property to configuration.
+     */
+    public static final int METADATA_DIFFERENCE = 100;

Review comment:
       private

##########
File path: 
modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java
##########
@@ -192,219 +194,127 @@ public TableManager(
 
         engine = new RocksDbStorageEngine();
 
-        tablesVv = new VersionedValue<>(registry);
-        tablesByIdVv = new VersionedValue<>(registry);
+        tablesVv = new VersionedValue<>(registry, HashMap::new);
+        tablesByIdVv = new VersionedValue<>(registry, HashMap::new);
     }
 
     /** {@inheritDoc} */
     @Override
     public void start() {
-        tablesCfg.tables()
-                .listenElements(new ConfigurationNamedListListener<>() {
-                    @Override
-                    public CompletableFuture<?> 
onCreate(ConfigurationNotificationEvent<TableView> ctx) {
-                        if (!busyLock.enterBusy()) {
-                            String tblName = ctx.newValue().name();
-                            UUID tblId = ((ExtendedTableView) 
ctx.newValue()).id();
-
-                            fireEvent(TableEvent.CREATE,
-                                    new 
TableEventParameters(ctx.storageRevision(), tblId, tblName),
-                                    new NodeStoppingException()
-                            );
-
-                            return CompletableFuture.failedFuture(new 
NodeStoppingException());
-                        }
+        ((ExtendedTableConfiguration) 
tablesCfg.tables().any()).schemas().listenElements(new 
ConfigurationNamedListListener<>() {

Review comment:
       In order to improve the readability I'd rather extract all 
listener-reaction-logic to explicit methods
   ```
           ((ExtendedTableConfiguration) 
tablesCfg.tables().any()).schemas().listenElements(new 
ConfigurationNamedListListener<>() {
               @Override
               public CompletableFuture<?> 
onCreate(ConfigurationNotificationEvent<SchemaView> schemasCtx) {
                 return **onSchemaCreate();**
               }
      }
   
           ((ExtendedTableConfiguration) 
tablesCfg.tables().any()).assignments().listen(() -> **onAssignmentsChange()**);
   
   ...
   
   ```

##########
File path: 
modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
##########
@@ -164,7 +167,121 @@ public void nodeWithDataTest(TestInfo testInfo) {
                 + "  }\n"
                 + "}", workDir);
 
-        TableDefinition scmTbl1 = SchemaBuilders.tableBuilder("PUBLIC", 
TABLE_NAME).columns(
+        createTableWithData(ignite, TABLE_NAME, i -> "name " + i);
+
+        IgnitionManager.stop(nodeName);
+
+        ignite = IgnitionManager.start(nodeName, null, workDir);
+
+        checkTableWithData(ignite, TABLE_NAME,  i -> "name " + i);
+
+        IgnitionManager.stop(nodeName);
+    }
+
+    /**
+     * Starts two nodes and checks that the data are storing through restarts.
+     * Nodes restart in the same order when they started at first.
+     *
+     * @param testInfo Test information object.
+     */
+    @Test
+    public void testTwoNodesRestartDirect(TestInfo testInfo) {
+        twoNodesRestart(testInfo, true);
+    }
+
+    /**
+     * Starts two nodes and checks that the data are storing through restarts.
+     * Nodes restart in reverse order when they started at first.
+     *
+     * @param testInfo Test information object.
+     */
+    @Test
+    @Disabled("IGNITE-16034 Unblock a node start that happenes before 
Metastorage is ready")
+    public void testTwoNodesRestartReverse(TestInfo testInfo) {
+        twoNodesRestart(testInfo, false);
+    }
+
+    /**
+     * Starts two nodes and checks that the data are storing through restarts.
+     *
+     * @param testInfo Test information object.
+     * @param directOrder When the parameter is true, nodes restart in direct 
order, otherwise they restart in reverse order.
+     */
+    private void twoNodesRestart(TestInfo testInfo, boolean directOrder) {

Review comment:
       We definitely need to check scenarios where 
   1. Node that was stopped received and applied all meta when it was alive.
   2. Skipped some meta that will be recovered during node recovery process.
   
   Seems that given two-node-tests aren't enough specific, we either don't 
assert that all nodes apply all meta nor check second option.
   
   Besides that we should add recovery tests that check whether data itself 
(not meta data) is available on restored node. In other words we should add 
tests for replica factor 3 + leader change or direct storage checks. 

##########
File path: 
modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
##########
@@ -363,6 +382,98 @@ public void start(@Nullable String cfg) {
         }
     }
 
+    /**
+     * Whether the node had started in standalone mode (for example, 
maintenance mode).
+     *
+     * @return Whether the node had started in standalone mode.
+     */
+    private boolean standaloneMode() {
+        return false;
+    }
+
+    /**
+     * Awaits for a permission to join the cluster, i.e. node join response 
from Cluster Management group.
+     * After the completion of this method, the node is considered as 
validated.
+     */
+    private void waitForJoinPermission() {
+        // TODO https://issues.apache.org/jira/browse/IGNITE-15114
+    }
+
+    /**
+     * Listens Metastorage revision updates.
+     *
+     * @return Future, which completes when the local metadata enough closer 
to distributed.
+     */
+    private CompletableFuture<Void> listenMetastorageRevision() {
+        //TODO: IGNITE-15114 This is a temporary solution until full process 
of the node join is implemented.
+        if (!metaStorageMgr.isMetaStorageInitializedOnStart()) {
+            return CompletableFuture.completedFuture(null);
+        }
+
+        CompletableFuture<Void> upToDateMetastorageRevisionFut = new 
CompletableFuture<>();
+
+        ConfigurationStorageRevisionListener listener = cfgUpdateRevision -> {
+            long metastorageRevision = metaStorageMgr.revision().join();

Review comment:
       Despite the fact that it'll rather be storageRevision directValue than 
metaStorageMgr.**revision** let's only recheck it on match rather than on every 
listener notification.

##########
File path: 
modules/metastorage-server/src/main/java/org/apache/ignite/internal/metastorage/server/KeyValueStorage.java
##########
@@ -41,6 +41,13 @@
      */
     long revision();
 
+    /**
+     * Returns the earliest storage revision that is available.
+     *
+     * @return Storage revision.
+     */
+    long earliestRevision();

Review comment:
       Because currently there won't be any usages of such method, let's remove 
it from given PR for now, what do you think?

##########
File path: 
modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
##########
@@ -325,6 +336,10 @@ public void start(@Nullable String cfg) {
                 nodeCfgMgr.configurationRegistry().initializeDefaults();
             }
 
+            if (!standaloneMode()) {

Review comment:
       Seems that currently we're far-far away from any understanding of what 
standalone mode is. It might be somehow related to maintenance mode, or not, 
it's not clear yet. I'd remove this method until clarification.

##########
File path: 
modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
##########
@@ -164,7 +167,121 @@ public void nodeWithDataTest(TestInfo testInfo) {
                 + "  }\n"
                 + "}", workDir);
 
-        TableDefinition scmTbl1 = SchemaBuilders.tableBuilder("PUBLIC", 
TABLE_NAME).columns(
+        createTableWithData(ignite, TABLE_NAME, i -> "name " + i);
+
+        IgnitionManager.stop(nodeName);
+
+        ignite = IgnitionManager.start(nodeName, null, workDir);
+
+        checkTableWithData(ignite, TABLE_NAME,  i -> "name " + i);
+
+        IgnitionManager.stop(nodeName);

Review comment:
       Minor: I'd rather move all after test cleanup logic, e.g. 
IgnitionManager.stop() to @afterEach.

##########
File path: 
modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
##########
@@ -363,6 +382,98 @@ public void start(@Nullable String cfg) {
         }
     }
 
+    /**
+     * Whether the node had started in standalone mode (for example, 
maintenance mode).
+     *
+     * @return Whether the node had started in standalone mode.
+     */
+    private boolean standaloneMode() {
+        return false;
+    }
+
+    /**
+     * Awaits for a permission to join the cluster, i.e. node join response 
from Cluster Management group.
+     * After the completion of this method, the node is considered as 
validated.
+     */
+    private void waitForJoinPermission() {
+        // TODO https://issues.apache.org/jira/browse/IGNITE-15114
+    }
+
+    /**
+     * Listens Metastorage revision updates.
+     *
+     * @return Future, which completes when the local metadata enough closer 
to distributed.
+     */
+    private CompletableFuture<Void> listenMetastorageRevision() {
+        //TODO: IGNITE-15114 This is a temporary solution until full process 
of the node join is implemented.
+        if (!metaStorageMgr.isMetaStorageInitializedOnStart()) {
+            return CompletableFuture.completedFuture(null);
+        }
+
+        CompletableFuture<Void> upToDateMetastorageRevisionFut = new 
CompletableFuture<>();
+
+        ConfigurationStorageRevisionListener listener = cfgUpdateRevision -> {
+            long metastorageRevision = metaStorageMgr.revision().join();
+
+            assert metastorageRevision >= cfgUpdateRevision : 
IgniteStringFormatter.format(
+                    "Metastorage revision must be greater than local node 
applied revision [msRev={}, appliedRev={}",
+                    metastorageRevision, cfgUpdateRevision);
+
+            if (isMetadataUpToDate(metastorageRevision, cfgUpdateRevision)) {
+                upToDateMetastorageRevisionFut.complete(null);
+            }
+
+            return CompletableFuture.completedFuture(null);
+        };
+
+        
clusterCfgMgr.configurationRegistry().listenUpdateStorageRevision(listener);

Review comment:
       As was discussed let's consider configuration data as an only recovery 
source and remove corresponding meta storage methods and events that were 
introduced: revision, latestRevision, MetastorageEvent.REVISION_APPLIED, etc.

##########
File path: 
modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
##########
@@ -164,7 +167,121 @@ public void nodeWithDataTest(TestInfo testInfo) {
                 + "  }\n"
                 + "}", workDir);
 
-        TableDefinition scmTbl1 = SchemaBuilders.tableBuilder("PUBLIC", 
TABLE_NAME).columns(
+        createTableWithData(ignite, TABLE_NAME, i -> "name " + i);
+
+        IgnitionManager.stop(nodeName);
+
+        ignite = IgnitionManager.start(nodeName, null, workDir);
+
+        checkTableWithData(ignite, TABLE_NAME,  i -> "name " + i);
+
+        IgnitionManager.stop(nodeName);
+    }
+
+    /**
+     * Starts two nodes and checks that the data are storing through restarts.
+     * Nodes restart in the same order when they started at first.
+     *
+     * @param testInfo Test information object.
+     */
+    @Test
+    public void testTwoNodesRestartDirect(TestInfo testInfo) {
+        twoNodesRestart(testInfo, true);
+    }
+
+    /**
+     * Starts two nodes and checks that the data are storing through restarts.
+     * Nodes restart in reverse order when they started at first.
+     *
+     * @param testInfo Test information object.
+     */
+    @Test
+    @Disabled("IGNITE-16034 Unblock a node start that happenes before 
Metastorage is ready")
+    public void testTwoNodesRestartReverse(TestInfo testInfo) {
+        twoNodesRestart(testInfo, false);
+    }
+
+    /**
+     * Starts two nodes and checks that the data are storing through restarts.
+     *
+     * @param testInfo Test information object.
+     * @param directOrder When the parameter is true, nodes restart in direct 
order, otherwise they restart in reverse order.
+     */
+    private void twoNodesRestart(TestInfo testInfo, boolean directOrder) {
+        String metastorageNode = testNodeName(testInfo, 3344);
+
+        Ignite ignite = IgnitionManager.start(metastorageNode, "{\n"
+                + "  \"node\": {\n"
+                + "    \"metastorageNodes\":[ " + metastorageNode + " ]\n"
+                + "  },\n"
+                + "  \"network\": {\n"
+                + "    \"port\":3344,\n"
+                + "    \"nodeFinder\": {\n"
+                + "      \"netClusterNodes\":[ \"localhost:3344\" ] \n"
+                + "    }\n"
+                + "  }\n"
+                + "}", workDir.resolve(metastorageNode));
+
+        String nodeName = testNodeName(testInfo, 3345);
+
+        IgnitionManager.start(nodeName, "{\n"
+                + "  \"node\": {\n"
+                + "    \"metastorageNodes\":[ " + metastorageNode + " ]\n"
+                + "  },\n"
+                + "  \"network\": {\n"
+                + "    \"port\":3345,\n"
+                + "    \"nodeFinder\": {\n"
+                + "      \"netClusterNodes\":[ \"localhost:3344\" ] \n"
+                + "    }\n"
+                + "  }\n"
+                + "}", workDir.resolve(nodeName));
+
+        createTableWithData(ignite, TABLE_NAME, i -> "name " + i);
+        createTableWithData(ignite, TABLE_NAME_2, i -> "val " + i);
+
+        IgnitionManager.stop(metastorageNode);
+        IgnitionManager.stop(nodeName);
+
+        if (directOrder) {
+            IgnitionManager.start(metastorageNode, null, 
workDir.resolve(metastorageNode));
+            ignite = IgnitionManager.start(nodeName, null, 
workDir.resolve(nodeName));
+        } else {
+            ignite = IgnitionManager.start(nodeName, null, 
workDir.resolve(nodeName));
+            IgnitionManager.start(metastorageNode, null, 
workDir.resolve(metastorageNode));
+        }
+
+        checkTableWithData(ignite, TABLE_NAME,  i -> "name " + i);
+        checkTableWithData(ignite, TABLE_NAME_2,  i -> "val " + i);
+
+        IgnitionManager.stop(metastorageNode);
+        IgnitionManager.stop(nodeName);
+    }
+
+    /**
+     * Checks the table exists and validates all data in it.
+     *
+     * @param ignite Ignite.
+     * @param valueProducer Producer to predict a value.

Review comment:
       Minor: let's either add all parameters or none? same for 
createTableWithData()

##########
File path: 
modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
##########
@@ -164,7 +167,121 @@ public void nodeWithDataTest(TestInfo testInfo) {
                 + "  }\n"
                 + "}", workDir);
 
-        TableDefinition scmTbl1 = SchemaBuilders.tableBuilder("PUBLIC", 
TABLE_NAME).columns(
+        createTableWithData(ignite, TABLE_NAME, i -> "name " + i);
+
+        IgnitionManager.stop(nodeName);
+
+        ignite = IgnitionManager.start(nodeName, null, workDir);
+
+        checkTableWithData(ignite, TABLE_NAME,  i -> "name " + i);
+
+        IgnitionManager.stop(nodeName);
+    }
+
+    /**
+     * Starts two nodes and checks that the data are storing through restarts.
+     * Nodes restart in the same order when they started at first.
+     *
+     * @param testInfo Test information object.
+     */
+    @Test
+    public void testTwoNodesRestartDirect(TestInfo testInfo) {
+        twoNodesRestart(testInfo, true);
+    }
+
+    /**
+     * Starts two nodes and checks that the data are storing through restarts.
+     * Nodes restart in reverse order when they started at first.
+     *
+     * @param testInfo Test information object.
+     */
+    @Test
+    @Disabled("IGNITE-16034 Unblock a node start that happenes before 
Metastorage is ready")
+    public void testTwoNodesRestartReverse(TestInfo testInfo) {
+        twoNodesRestart(testInfo, false);
+    }
+
+    /**
+     * Starts two nodes and checks that the data are storing through restarts.
+     *
+     * @param testInfo Test information object.
+     * @param directOrder When the parameter is true, nodes restart in direct 
order, otherwise they restart in reverse order.
+     */
+    private void twoNodesRestart(TestInfo testInfo, boolean directOrder) {
+        String metastorageNode = testNodeName(testInfo, 3344);
+
+        Ignite ignite = IgnitionManager.start(metastorageNode, "{\n"
+                + "  \"node\": {\n"
+                + "    \"metastorageNodes\":[ " + metastorageNode + " ]\n"
+                + "  },\n"
+                + "  \"network\": {\n"
+                + "    \"port\":3344,\n"
+                + "    \"nodeFinder\": {\n"
+                + "      \"netClusterNodes\":[ \"localhost:3344\" ] \n"
+                + "    }\n"
+                + "  }\n"
+                + "}", workDir.resolve(metastorageNode));
+
+        String nodeName = testNodeName(testInfo, 3345);
+
+        IgnitionManager.start(nodeName, "{\n"
+                + "  \"node\": {\n"
+                + "    \"metastorageNodes\":[ " + metastorageNode + " ]\n"
+                + "  },\n"
+                + "  \"network\": {\n"
+                + "    \"port\":3345,\n"
+                + "    \"nodeFinder\": {\n"
+                + "      \"netClusterNodes\":[ \"localhost:3344\" ] \n"
+                + "    }\n"
+                + "  }\n"
+                + "}", workDir.resolve(nodeName));
+
+        createTableWithData(ignite, TABLE_NAME, i -> "name " + i);
+        createTableWithData(ignite, TABLE_NAME_2, i -> "val " + i);
+
+        IgnitionManager.stop(metastorageNode);
+        IgnitionManager.stop(nodeName);
+
+        if (directOrder) {
+            IgnitionManager.start(metastorageNode, null, 
workDir.resolve(metastorageNode));
+            ignite = IgnitionManager.start(nodeName, null, 
workDir.resolve(nodeName));
+        } else {
+            ignite = IgnitionManager.start(nodeName, null, 
workDir.resolve(nodeName));
+            IgnitionManager.start(metastorageNode, null, 
workDir.resolve(metastorageNode));
+        }
+
+        checkTableWithData(ignite, TABLE_NAME,  i -> "name " + i);
+        checkTableWithData(ignite, TABLE_NAME_2,  i -> "val " + i);
+
+        IgnitionManager.stop(metastorageNode);
+        IgnitionManager.stop(nodeName);
+    }
+
+    /**
+     * Checks the table exists and validates all data in it.
+     *
+     * @param ignite Ignite.
+     * @param valueProducer Producer to predict a value.
+     */
+    private void checkTableWithData(Ignite ignite, String name, 
IntFunction<String> valueProducer) {

Review comment:
       Why do we need valueProducer? Seems that actual value is partially 
generated inside createTableWithData, so what's the point in generating value 
prefix externally?

##########
File path: 
modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/schema/SqlSchemaManagerImpl.java
##########
@@ -133,10 +131,10 @@ public IgniteTable tableById(UUID id, int ver) {
      * @param causalityToken Causality token.
      */
     public synchronized void onSchemaCreated(String schemaName, long 
causalityToken) {
-        schemasVv.update(
+        Map<String, IgniteSchema> schemasMap = schemasVv.update(
                 causalityToken,
                 schemas -> {
-                    Map<String, IgniteSchema> res = new HashMap<>(schemas);
+                    Map<String, IgniteSchema> res =  new HashMap<>(schemas);

Review comment:
       2 white spaces?




-- 
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