This is an automated email from the ASF dual-hosted git repository.
nizhikov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new df22bb8d9c7 IGNITE-18834 Index rebuild ducktest (#10561)
df22bb8d9c7 is described below
commit df22bb8d9c77feb68b013d07a6c2636a1d467a68
Author: Nikolay <[email protected]>
AuthorDate: Mon Feb 27 20:11:53 2023 +0300
IGNITE-18834 Index rebuild ducktest (#10561)
---
.../managers/indexing/IndexesRebuildTask.java | 4 +-
.../ducktest/tests/DataGenerationApplication.java | 54 ++++++-
.../tests/ignitetest/services/utils/path.py | 24 +++
.../tests/ignitetest/tests/index_rebuild_test.py | 165 +++++++++++++++++++++
modules/ducktests/tests/ignitetest/tests/util.py | 4 +-
.../WalDisabledDuringIndexRecreateTest.java | 6 +-
6 files changed, 246 insertions(+), 11 deletions(-)
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/managers/indexing/IndexesRebuildTask.java
b/modules/core/src/main/java/org/apache/ignite/internal/managers/indexing/IndexesRebuildTask.java
index 85046fbe4b8..f317d0bbfec 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/managers/indexing/IndexesRebuildTask.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/managers/indexing/IndexesRebuildTask.java
@@ -97,7 +97,7 @@ public class IndexesRebuildTask {
if (log.isInfoEnabled()) {
log.info("WAL disabled for index partition " +
- "[name=" + cctx.group().name() + ", id=" + cctx.groupId()
+ ']');
+ "[name=" + cctx.group().cacheOrGroupName() + ", id=" +
cctx.groupId() + ']');
}
}
@@ -151,7 +151,7 @@ public class IndexesRebuildTask {
if (log.isInfoEnabled()) {
log.info("WAL enabled for index partition " +
- "[name=" + cctx.group().name() + ", id=" +
cctx.group().groupId() + ']');
+ "[name=" + cctx.group().cacheOrGroupName() + ",
id=" + cctx.group().groupId() + ']');
}
}
}
diff --git
a/modules/ducktests/src/main/java/org/apache/ignite/internal/ducktest/tests/DataGenerationApplication.java
b/modules/ducktests/src/main/java/org/apache/ignite/internal/ducktest/tests/DataGenerationApplication.java
index bfd7fe111ce..216fbf72d62 100644
---
a/modules/ducktests/src/main/java/org/apache/ignite/internal/ducktest/tests/DataGenerationApplication.java
+++
b/modules/ducktests/src/main/java/org/apache/ignite/internal/ducktest/tests/DataGenerationApplication.java
@@ -17,12 +17,17 @@
package org.apache.ignite.internal.ducktest.tests;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import com.fasterxml.jackson.databind.JsonNode;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteDataStreamer;
import org.apache.ignite.binary.BinaryObject;
import org.apache.ignite.binary.BinaryObjectBuilder;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.internal.ducktest.utils.IgniteAwareApplication;
@@ -33,6 +38,9 @@ public class DataGenerationApplication extends
IgniteAwareApplication {
/** Max streamer data size. */
private static final int MAX_STREAMER_DATA_SIZE = 100_000_000;
+ /** */
+ public static final String VAL_TYPE =
"org.apache.ignite.ducktest.DataBinary";
+
/** {@inheritDoc} */
@Override protected void run(JsonNode jsonNode) throws Exception {
int backups = jsonNode.get("backups").asInt();
@@ -41,14 +49,40 @@ public class DataGenerationApplication extends
IgniteAwareApplication {
int from = jsonNode.get("from").asInt();
int to = jsonNode.get("to").asInt();
+ int idxCnt = 0;
+
+ if (jsonNode.has("indexCount"))
+ idxCnt = jsonNode.get("indexCount").asInt();
+
markInitialized();
for (int i = 1; i <= cacheCnt; i++) {
- IgniteCache<Integer, BinaryObject> cache = ignite.getOrCreateCache(
- new CacheConfiguration<Integer, BinaryObject>("test-cache-" +
i)
- .setBackups(backups));
+ CacheConfiguration<Integer, BinaryObject> ccfg = new
CacheConfiguration<Integer, BinaryObject>("test-cache-" + i)
+ .setBackups(backups);
+
+ if (idxCnt > 0) {
+ QueryEntity qe = new QueryEntity();
+ List<QueryIndex> qi = new ArrayList<>(idxCnt);
+
+ qe.setKeyType(Integer.class.getName());
+ qe.setValueType(VAL_TYPE);
+
+ for (int j = 0; j < idxCnt; j++) {
+ String field = "bytes" + j;
+
+ qe.addQueryField(field, byte[].class.getName(), null);
+ qi.add(new QueryIndex(field));
+ }
+
+ qe.setIndexes(qi);
- generateCacheData(cache.getName(), entrySize, from, to);
+ ccfg.setQueryEntities(Collections.singleton(qe));
+
+ }
+
+ IgniteCache<Integer, BinaryObject> cache =
ignite.getOrCreateCache(ccfg);
+
+ generateCacheData(cache.getName(), entrySize, from, to, idxCnt);
}
markFinished();
@@ -60,11 +94,11 @@ public class DataGenerationApplication extends
IgniteAwareApplication {
* @param from From key.
* @param to To key.
*/
- private void generateCacheData(String cacheName, int entrySize, int from,
int to) {
+ private void generateCacheData(String cacheName, int entrySize, int from,
int to, int idxCnt) {
int flushEach = MAX_STREAMER_DATA_SIZE / entrySize +
(MAX_STREAMER_DATA_SIZE % entrySize == 0 ? 0 : 1);
int logEach = (to - from) / 10;
- BinaryObjectBuilder builder =
ignite.binary().builder("org.apache.ignite.ducktest.DataBinary");
+ BinaryObjectBuilder builder = ignite.binary().builder(VAL_TYPE);
byte[] data = new byte[entrySize];
@@ -75,6 +109,14 @@ public class DataGenerationApplication extends
IgniteAwareApplication {
builder.setField("key", i);
builder.setField("data", data);
+ for (int j = 0; j < idxCnt; j++) {
+ byte[] indexedBytes = new byte[100];
+
+ ThreadLocalRandom.current().nextBytes(indexedBytes);
+
+ builder.setField("bytes" + j, indexedBytes);
+ }
+
stmr.addData(i, builder.build());
if ((i - from + 1) % logEach == 0 && log.isDebugEnabled())
diff --git a/modules/ducktests/tests/ignitetest/services/utils/path.py
b/modules/ducktests/tests/ignitetest/services/utils/path.py
index e86fd23964b..3e8f1f99ee1 100644
--- a/modules/ducktests/tests/ignitetest/services/utils/path.py
+++ b/modules/ducktests/tests/ignitetest/services/utils/path.py
@@ -215,6 +215,13 @@ class IgnitePathAware(PathAware, metaclass=ABCMeta):
"""
return os.path.join(self.work_dir, "db")
+ @property
+ def wal_dir(self):
+ """
+ :return: path to wal directory
+ """
+ return os.path.join(self.database_dir, "wal")
+
@property
def snapshots_dir(self):
"""
@@ -235,3 +242,20 @@ class IgnitePathAware(PathAware, metaclass=ABCMeta):
:return: absolute path to the specified script
"""
return os.path.join(self.home_dir, "bin", script_name)
+
+ def cache_dir(self, consistent_dir, cache_name):
+ """
+ :param consistent_dir: consistent ID directory.
+ :param cache_name: cache name.
+ :return: absolute path to the cache directory.
+ """
+ consistent_dir = consistent_dir.replace('.', '_')
+ return os.path.join(self.database_dir, consistent_dir,
f'cache-{cache_name}')
+
+ def index_file(self, consistent_dir, cache_name):
+ """
+ :param consistent_dir: consistent ID directory.
+ :param cache_name: cache name.
+ :return: absolute path to the index file of cache.
+ """
+ return os.path.join(self.cache_dir(consistent_dir, cache_name),
'index.bin')
diff --git a/modules/ducktests/tests/ignitetest/tests/index_rebuild_test.py
b/modules/ducktests/tests/ignitetest/tests/index_rebuild_test.py
new file mode 100644
index 00000000000..ca53edd25f8
--- /dev/null
+++ b/modules/ducktests/tests/ignitetest/tests/index_rebuild_test.py
@@ -0,0 +1,165 @@
+# 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.
+
+"""
+Module contains index.bin rebuild tests.
+"""
+import time
+
+from ducktape.mark import defaults
+
+from ignitetest.services.ignite import IgniteService
+from ignitetest.services.utils.control_utility import ControlUtility
+from ignitetest.services.utils.ignite_aware import IgniteAwareService
+from ignitetest.services.utils.ignite_configuration import
DataStorageConfiguration, IgniteConfiguration
+from ignitetest.services.utils.ignite_configuration.data_storage import
DataRegionConfiguration
+from ignitetest.services.utils.ignite_configuration.discovery import
from_ignite_cluster
+from ignitetest.tests.rebalance.util import NUM_NODES
+from ignitetest.tests.util import DataGenerationParams, preload_data
+from ignitetest.utils import cluster, ignite_versions
+from ignitetest.utils.ignite_test import IgniteTest
+from ignitetest.utils.version import DEV_BRANCH, LATEST, IgniteVersion
+
+
+def get_file_sizes(nodes: list, file: str) -> dict:
+ """
+ Return file size in bytes.
+
+ :param nodes: List of nodes.
+ :param file: File to get size for.
+ :return Dictionary with key as hostname value is files sizes on the node.
+ """
+ res = {}
+ for node in nodes:
+ out = IgniteAwareService.exec_command(node, f'du -sb {file}')
+
+ data = out.split("\t")
+
+ res[node.account.hostname] = int(data[0])
+
+ return res
+
+
+CACHE_NAME = "test-cache-1"
+
+
+class IndexRebuildTest(IgniteTest):
+ """
+ Tests index.bin rebuild.
+ """
+
+ @cluster(num_nodes=NUM_NODES)
+ @ignite_versions(str(DEV_BRANCH), str(LATEST))
+ @defaults(backups=[1], cache_count=[1], entry_count=[50000],
entry_size=[50], preloaders=[1], index_count=[3])
+ def test_index_bin_rebuild(self, ignite_version, backups, cache_count,
entry_count, entry_size, preloaders,
+ index_count):
+ """
+ Tests index.bin rebuild on node start.
+ """
+
+ data_gen_params = DataGenerationParams(backups=backups,
cache_count=cache_count, entry_count=entry_count,
+ entry_size=entry_size,
preloaders=preloaders, index_count=index_count)
+
+ ignites = self.start_ignite(ignite_version, data_gen_params)
+
+ control_utility = ControlUtility(ignites)
+
+ control_utility.activate()
+
+ control_utility.disable_baseline_auto_adjust()
+
+ _, version, _ = control_utility.cluster_state()
+ control_utility.set_baseline(version)
+
+ preload_time = preload_data(
+ self.test_context,
+ ignites.config._replace(client_mode=True,
discovery_spi=from_ignite_cluster(ignites)),
+ data_gen_params=data_gen_params)
+
+ control_utility.deactivate()
+
+ ignites.stop()
+
+ wal_before_rebuild = get_file_sizes(ignites.nodes, ignites.wal_dir)
+ idx_before_rebuild = get_file_sizes(ignites.nodes,
ignites.index_file('*', CACHE_NAME))
+
+ for node in ignites.nodes:
+ IgniteAwareService.exec_command(node, f'rm
{ignites.index_file(node.account.hostname, CACHE_NAME)}')
+
+ start_time = round(time.time() * 1000)
+
+ ignites.start(clean=False)
+
+ control_utility.activate()
+
+ timeout_sec = round(data_gen_params.entry_count / (len(ignites.nodes)
* 250))
+
+ ignites.await_event(f"Started indexes rebuilding for cache
\\[name={CACHE_NAME}, grpName=null\\]",
+ from_the_beginning=True, timeout_sec=timeout_sec)
+ ignites.await_event("Indexes rebuilding completed for all caches.",
from_the_beginning=True,
+ timeout_sec=timeout_sec)
+
+ control_utility.deactivate()
+
+ ignites.stop()
+
+ rebuild_time = round(time.time() * 1000) - start_time
+
+ wal_after_rebuild = get_file_sizes(ignites.nodes, ignites.wal_dir)
+ idx_after_rebuild = get_file_sizes(ignites.nodes,
ignites.index_file('*', CACHE_NAME))
+
+ wal_enlargement = {}
+ for node in wal_before_rebuild:
+ wal_enlargement[node] = wal_after_rebuild[node] -
wal_before_rebuild[node]
+
+ return {
+ "preload_time": preload_time,
+ "wal_before_rebuild": wal_before_rebuild,
+ "wal_after_rebuild": wal_after_rebuild,
+ "idx_before_rebuild": idx_before_rebuild,
+ "idx_after_rebuild": idx_after_rebuild,
+ "wal_enlargement_bytes": wal_enlargement,
+ "rebuild_time_ms": rebuild_time
+ }
+
+ def start_ignite(self, ignite_version: str, data_gen_params:
DataGenerationParams) -> IgniteService:
+ """
+ Start IgniteService:
+
+ :param ignite_version: Ignite version.
+ :param data_gen_params: Data generation parameters.
+ :return: IgniteService.
+ """
+ node_count = self.available_cluster_size - data_gen_params.preloaders
+
+ node_config = IgniteConfiguration(
+ cluster_state='INACTIVE',
+ auto_activation_enabled=False,
+ version=IgniteVersion(ignite_version),
+ data_storage=DataStorageConfiguration(
+ max_wal_archive_size=1000 *
data_gen_params.data_region_max_size,
+ wal_segment_size=50 * 1024 * 1024,
+ default=DataRegionConfiguration(
+ persistence_enabled=True,
+ max_size=data_gen_params.data_region_max_size
+ )
+ ),
+
metric_exporters={"org.apache.ignite.spi.metric.jmx.JmxMetricExporterSpi"}
+ )
+
+ ignites = IgniteService(self.test_context, config=node_config,
num_nodes=node_count)
+ ignites.start()
+
+ return ignites
diff --git a/modules/ducktests/tests/ignitetest/tests/util.py
b/modules/ducktests/tests/ignitetest/tests/util.py
index 9ac87c0232e..b8192a3443b 100644
--- a/modules/ducktests/tests/ignitetest/tests/util.py
+++ b/modules/ducktests/tests/ignitetest/tests/util.py
@@ -34,6 +34,7 @@ class DataGenerationParams(NamedTuple):
entry_count: int = 15_000
entry_size: int = 50_000
preloaders: int = 1
+ index_count: int = 0
@property
def data_region_max_size(self):
@@ -77,7 +78,8 @@ def preload_data(context, config, data_gen_params:
DataGenerationParams, timeout
"cacheCount": data_gen_params.cache_count,
"entrySize": data_gen_params.entry_size,
"from": _from,
- "to": _to
+ "to": _to,
+ "indexCount": data_gen_params.index_count
},
shutdown_timeout_sec=timeout)
app.start_async()
diff --git
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/WalDisabledDuringIndexRecreateTest.java
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/WalDisabledDuringIndexRecreateTest.java
index 21d6e42d527..0874d65bf72 100644
---
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/WalDisabledDuringIndexRecreateTest.java
+++
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/WalDisabledDuringIndexRecreateTest.java
@@ -228,12 +228,14 @@ public class WalDisabledDuringIndexRecreateTest extends
GridCommonAbstractTest {
private void awaitRebuild() throws Exception {
LogListener walDisabledLsnr = LogListener.matches(
"WAL disabled for index partition " +
- "[name=" + cacheGroupName() + ", id=" +
cacheGroupId(cacheName(), cacheGroupName()) + ']'
+ "[name=" + (cacheGroupName() == null ? cacheName() :
cacheGroupName()) +
+ ", id=" + cacheGroupId(cacheName(), cacheGroupName()) + ']'
).build();
LogListener walEnabledLsnr = LogListener.matches(
"WAL enabled for index partition " +
- "[name=" + cacheGroupName() + ", id=" +
cacheGroupId(cacheName(), cacheGroupName()) + ']'
+ "[name=" + (cacheGroupName() == null ? cacheName() :
cacheGroupName()) +
+ ", id=" + cacheGroupId(cacheName(), cacheGroupName()) + ']'
).build();
testLog.registerListener(walDisabledLsnr);