You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by am...@apache.org on 2019/09/04 12:45:15 UTC
[ignite] branch master updated: IGNITE-12112: H2TreeIndex should
throw CorruptTreeException with cacheId,
cacheName and indexName. This closes #6817.
This is an automated email from the ASF dual-hosted git repository.
amashenkov 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 27f6d82 IGNITE-12112: H2TreeIndex should throw CorruptTreeException with cacheId, cacheName and indexName. This closes #6817.
27f6d82 is described below
commit 27f6d824f4b1a055d6e1960e7b65786156f00243
Author: denis-chudov <mo...@gmail.com>
AuthorDate: Wed Sep 4 15:39:52 2019 +0300
IGNITE-12112: H2TreeIndex should throw CorruptTreeException with cacheId, cacheName and indexName. This closes #6817.
---
.../benchmarks/jmh/tree/BPlusTreeBenchmark.java | 1 +
.../processors/cache/mvcc/txlog/TxLogTree.java | 1 +
.../cache/persistence/DataStructure.java | 12 +-
.../cache/persistence/IndexStorageImpl.java | 7 +-
.../cache/persistence/freelist/PagesList.java | 2 +-
.../persistence/metastorage/MetastorageTree.java | 1 +
.../cache/persistence/tree/BPlusTree.java | 41 ++++--
.../persistence/tree/CorruptedTreeException.java | 67 +++++++--
.../processors/cache/tree/CacheDataTree.java | 1 +
.../processors/cache/tree/PendingEntriesTree.java | 1 +
.../processors/database/BPlusTreeSelfTest.java | 1 +
.../processors/query/h2/IgniteH2Indexing.java | 1 +
.../processors/query/h2/database/H2Tree.java | 25 +++-
.../processors/query/h2/database/H2TreeIndex.java | 1 +
.../index/H2TreeCorruptedTreeExceptionTest.java | 162 +++++++++++++++++++++
.../IgniteCacheWithIndexingTestSuite.java | 5 +-
16 files changed, 295 insertions(+), 34 deletions(-)
diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
index c7ea741..7a35430 100644
--- a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
+++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
@@ -178,6 +178,7 @@ public class BPlusTreeBenchmark extends JmhAbstractBenchmark {
super(
"test",
cacheId,
+ null,
pageMem,
null,
new AtomicLong(),
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLogTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLogTree.java
index 200bc66..c850928 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLogTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/txlog/TxLogTree.java
@@ -53,6 +53,7 @@ public class TxLogTree extends BPlusTree<TxKey, TxRow> {
super(
TxLog.TX_LOG_CACHE_NAME,
TxLog.TX_LOG_CACHE_ID,
+ TxLog.TX_LOG_CACHE_NAME,
pageMem,
wal,
new AtomicLong(),
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java
index 252e48f..9004a6d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java
@@ -52,6 +52,9 @@ public abstract class DataStructure {
protected final int grpId;
/** */
+ protected final String grpName;
+
+ /** */
protected final PageMemory pageMem;
/** */
@@ -64,19 +67,22 @@ public abstract class DataStructure {
protected ReuseList reuseList;
/**
- * @param cacheId Cache group ID.
+ * @param cacheGrpId Cache group ID.
+ * @param grpName Cache group name.
* @param pageMem Page memory.
* @param wal Write ahead log manager.
*/
public DataStructure(
- int cacheId,
+ int cacheGrpId,
+ String grpName,
PageMemory pageMem,
IgniteWriteAheadLogManager wal,
PageLockListener lockLsnr
) {
assert pageMem != null;
- this.grpId = cacheId;
+ this.grpId = cacheGrpId;
+ this.grpName = grpName;
this.pageMem = pageMem;
this.wal = wal;
this.lockLsnr = lockLsnr == null ? NOOP_LSNR : lockLsnr;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java
index 2be0c7a..1be0b97 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IndexStorageImpl.java
@@ -192,18 +192,18 @@ public class IndexStorageImpl implements IndexStorage {
/** {@inheritDoc} */
@Override public Collection<String> getIndexNames() throws IgniteCheckedException {
assert metaTree != null;
-
+
GridCursor<IndexItem> cursor = metaTree.find(null, null);
ArrayList<String> names = new ArrayList<>((int)metaTree.size());
while (cursor.next()) {
IndexItem item = cursor.get();
-
+
if (item != null)
names.add(new String(item.idxName));
}
-
+
return names;
}
@@ -259,6 +259,7 @@ public class IndexStorageImpl implements IndexStorage {
super(
treeName("meta", "Meta"),
cacheId,
+ null,
pageMem,
wal,
globalRmvId,
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java
index 7734ba4..a4767b3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java
@@ -144,7 +144,7 @@ public abstract class PagesList extends DataStructure {
long metaPageId,
PageLockListener lockLsnr
) {
- super(cacheId, pageMem, wal, lockLsnr);
+ super(cacheId, null, pageMem, wal, lockLsnr);
this.name = name;
this.buckets = buckets;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetastorageTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetastorageTree.java
index 556a79a..970be5b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetastorageTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetastorageTree.java
@@ -75,6 +75,7 @@ public class MetastorageTree extends BPlusTree<MetastorageSearchRow, Metastorage
super(
name,
cacheId,
+ null,
pageMem,
wal,
globalRmvId,
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
index a24896d..fc14a5b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java
@@ -737,7 +737,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
/**
* @param name Tree name.
- * @param cacheId Cache ID.
+ * @param cacheGrpId Cache group ID.
+ * @param cacheGrpName Cache group name.
* @param pageMem Page memory.
* @param wal Write ahead log manager.
* @param globalRmvId Remove ID.
@@ -750,7 +751,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
*/
protected BPlusTree(
String name,
- int cacheId,
+ int cacheGrpId,
+ String cacheGrpName,
PageMemory pageMem,
IgniteWriteAheadLogManager wal,
AtomicLong globalRmvId,
@@ -763,7 +765,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
) throws IgniteCheckedException {
this(
name,
- cacheId,
+ cacheGrpId,
+ cacheGrpName,
pageMem,
wal,
globalRmvId,
@@ -778,7 +781,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
/**
* @param name Tree name.
- * @param cacheId Cache ID.
+ * @param cacheGrpId Cache ID.
+ * @param grpName Cache group name.
* @param pageMem Page memory.
* @param wal Write ahead log manager.
* @param globalRmvId Remove ID.
@@ -789,7 +793,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
*/
protected BPlusTree(
String name,
- int cacheId,
+ int cacheGrpId,
+ String grpName,
PageMemory pageMem,
IgniteWriteAheadLogManager wal,
AtomicLong globalRmvId,
@@ -798,7 +803,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
@Nullable FailureProcessor failureProcessor,
@Nullable PageLockListener lsnr
) throws IgniteCheckedException {
- super(cacheId, pageMem, wal, lsnr);
+ super(cacheGrpId, grpName, pageMem, wal, lsnr);
assert !F.isEmpty(name);
@@ -1570,8 +1575,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
private void fail(Object msg) {
AssertionError err = new AssertionError(msg);
- if (failureProcessor != null)
- failureProcessor.process(new FailureContext(FailureType.CRITICAL_ERROR, err));
+ processFailure(FailureType.CRITICAL_ERROR, err);
throw err;
}
@@ -2902,8 +2906,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
"(the tree may be corrupted). Increase " + IGNITE_BPLUS_TREE_LOCK_RETRIES + " system property " +
"if you regularly see this message (current value is " + getLockRetries() + ").");
- if (failureProcessor != null)
- failureProcessor.process(new FailureContext(FailureType.CRITICAL_ERROR, e));
+ processFailure(FailureType.CRITICAL_ERROR, e);
throw e;
}
@@ -5920,12 +5923,22 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements
* @param pageIds Pages ids.
* @return New CorruptedTreeException instance.
*/
- private CorruptedTreeException corruptedTreeException(String msg, Throwable cause, int grpId, long... pageIds) {
- CorruptedTreeException e = new CorruptedTreeException(msg, cause, grpId, pageIds);
+ protected CorruptedTreeException corruptedTreeException(String msg, Throwable cause, int grpId, long... pageIds) {
+ CorruptedTreeException e = new CorruptedTreeException(msg, cause, grpId, grpName, pageIds);
- if (failureProcessor != null)
- failureProcessor.process(new FailureContext(FailureType.CRITICAL_ERROR, e));
+ processFailure(FailureType.CRITICAL_ERROR, e);
return e;
}
+
+ /**
+ * Processes failure with failure processor.
+ *
+ * @param failureType Failure type.
+ * @param e Exception.
+ */
+ protected void processFailure(FailureType failureType, Throwable e) {
+ if (failureProcessor != null)
+ failureProcessor.process(new FailureContext(failureType, e));
+ }
}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java
index 56dc7db..215584a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java
@@ -25,9 +25,10 @@ import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.internal.pagemem.PageIdAllocator;
import org.apache.ignite.internal.pagemem.PageIdUtils;
import org.apache.ignite.internal.processors.cache.persistence.CorruptedPersistenceException;
+import org.apache.ignite.internal.util.GridStringBuilder;
import org.apache.ignite.internal.util.typedef.T2;
import org.apache.ignite.internal.util.typedef.X;
-import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.CU;
import org.jetbrains.annotations.Nullable;
import static java.util.Arrays.asList;
@@ -46,19 +47,51 @@ public class CorruptedTreeException extends IgniteCheckedException implements Co
* @param msg Message.
* @param cause Cause.
* @param grpId Group id of potentially corrupted pages.
+ * @param grpName Group name of potentially corrupted pages.
* @param pageIds Potentially corrupted pages.
*/
- public CorruptedTreeException(String msg, @Nullable Throwable cause, int grpId, long... pageIds) {
- this(msg, cause, toPagesArray(grpId, pageIds));
+ public CorruptedTreeException(String msg, @Nullable Throwable cause, int grpId, String grpName, long... pageIds) {
+ this(msg, null, null, grpName, cause, toPagesArray(grpId, pageIds));
}
/**
* @param msg Message.
* @param cause Cause.
+ * @param grpId Group id of potentially corrupted pages.
+ * @param grpName Group name of potentially corrupted pages.
+ * @param cacheName Cache name.
+ * @param indexName Index name.
+ * @param pageIds Potentially corrupted pages.
+ */
+ public CorruptedTreeException(
+ String msg,
+ @Nullable Throwable cause,
+ int grpId,
+ String grpName,
+ String cacheName,
+ String indexName,
+ long... pageIds
+ ) {
+ this(msg, cacheName, indexName, grpName, cause, toPagesArray(grpId, pageIds));
+ }
+
+ /**
+ * @param msg Message.
+ * @param cacheName Cache name.
+ * @param indexName Index name.
+ * @param grpName Cache group name.
+ * @param cause Cause.
* @param pages (groupId, pageId) pairs for pages that might be corrupted.
*/
- public CorruptedTreeException(String msg, @Nullable Throwable cause, T2<Integer, Long>... pages) {
- super(getMsg(msg, pages), cause);
+ public CorruptedTreeException(
+ String msg,
+ String cacheName,
+ String indexName,
+ String grpName,
+ @Nullable Throwable cause,
+ T2<Integer, Long>... pages
+ ) {
+ super(getMsg(msg, cacheName, indexName, grpName, pages), cause);
this.pages = expandPagesArray(pages, cause);
}
@@ -99,11 +132,25 @@ public class CorruptedTreeException extends IgniteCheckedException implements Co
}
/** */
- private static String getMsg(String msg, T2<Integer, Long>... pages) {
- return S.toString("B+Tree is corrupted",
- "pages(groupId, pageId)", Arrays.toString(pages), false,
- "msg", msg, false
- );
+ private static String getMsg(String msg, String cacheName, String indexName, String grpName, T2<Integer, Long>... pages) {
+ GridStringBuilder stringBuilder = new GridStringBuilder("B+Tree is corrupted [")
+ .a("pages(groupId, pageId)=").a(Arrays.toString(pages));
+
+ if (cacheName != null) {
+ stringBuilder
+ .a(", cacheId=").a(CU.cacheId(cacheName))
+ .a(", cacheName=").a(cacheName);
+ }
+
+ if (indexName != null)
+ stringBuilder.a(", indexName=").a(indexName);
+
+ if (grpName != null)
+ stringBuilder.a(", groupName=").a(grpName);
+
+ stringBuilder.a(", msg=").a(msg).a("]");
+
+ return stringBuilder.toString();
}
/**
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/CacheDataTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/CacheDataTree.java
index 4bc71fa..a8f9c51 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/CacheDataTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/CacheDataTree.java
@@ -98,6 +98,7 @@ public class CacheDataTree extends BPlusTree<CacheSearchRow, CacheDataRow> {
super(
name,
grp.groupId(),
+ grp.name(),
grp.dataRegion().pageMemory(),
grp.dataRegion().config().isPersistenceEnabled() ? grp.shared().wal() : null,
grp.offheap().globalRemoveId(),
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/PendingEntriesTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/PendingEntriesTree.java
index 88de417..763ea93 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/PendingEntriesTree.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/tree/PendingEntriesTree.java
@@ -57,6 +57,7 @@ public class PendingEntriesTree extends BPlusTree<PendingRow, PendingRow> {
super(
name,
grp.groupId(),
+ grp.name(),
pageMem,
grp.dataRegion().config().isPersistenceEnabled() ? grp.shared().wal() : null,
grp.offheap().globalRemoveId(),
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java
index 9490c29..f946382 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java
@@ -2743,6 +2743,7 @@ public class BPlusTreeSelfTest extends GridCommonAbstractTest {
super(
"test",
cacheId,
+ null,
pageMem,
null,
new AtomicLong(),
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 5ac88d4..f1b9959 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -2364,6 +2364,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
BPlusTree<H2Row, H2Row> tree = new BPlusTree<H2Row, H2Row>(
indexName,
grpId,
+ grpName,
pageMemory,
ctx.cache().context().wal(),
removeId,
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java
index 2297b3d..7ab1d74 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java
@@ -26,6 +26,8 @@ import java.util.stream.Collectors;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.IgniteSystemProperties;
+import org.apache.ignite.failure.FailureType;
+import org.apache.ignite.internal.metric.IoStatisticsHolder;
import org.apache.ignite.internal.pagemem.PageIdUtils;
import org.apache.ignite.internal.pagemem.PageMemory;
import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
@@ -33,6 +35,7 @@ import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.mvcc.MvccUtils;
import org.apache.ignite.internal.processors.cache.persistence.CacheDataRowAdapter;
import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree;
+import org.apache.ignite.internal.processors.cache.persistence.tree.CorruptedTreeException;
import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusIO;
import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusMetaIO;
import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList;
@@ -43,9 +46,8 @@ import org.apache.ignite.internal.processors.query.h2.database.io.H2ExtrasInnerI
import org.apache.ignite.internal.processors.query.h2.database.io.H2ExtrasLeafIO;
import org.apache.ignite.internal.processors.query.h2.database.io.H2RowLinkIO;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
-import org.apache.ignite.internal.processors.query.h2.opt.H2Row;
import org.apache.ignite.internal.processors.query.h2.opt.H2CacheRow;
-import org.apache.ignite.internal.metric.IoStatisticsHolder;
+import org.apache.ignite.internal.processors.query.h2.opt.H2Row;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.h2.result.SearchRow;
@@ -159,6 +161,7 @@ public class H2Tree extends BPlusTree<H2Row, H2Row> {
String tblName,
ReuseList reuseList,
int grpId,
+ String grpName,
PageMemory pageMem,
IgniteWriteAheadLogManager wal,
AtomicLong globalRmvId,
@@ -178,6 +181,7 @@ public class H2Tree extends BPlusTree<H2Row, H2Row> {
super(
name,
grpId,
+ grpName,
pageMem,
wal,
globalRmvId,
@@ -655,4 +659,21 @@ public class H2Tree extends BPlusTree<H2Row, H2Row> {
@Override public String toString() {
return S.toString(H2Tree.class, this, "super", super.toString());
}
+
+ /**
+ * Construct the exception and invoke failure processor.
+ *
+ * @param msg Message.
+ * @param cause Cause.
+ * @param grpId Group id.
+ * @param pageIds Pages ids.
+ * @return New CorruptedTreeException instance.
+ */
+ @Override protected CorruptedTreeException corruptedTreeException(String msg, Throwable cause, int grpId, long... pageIds) {
+ CorruptedTreeException e = new CorruptedTreeException(msg, cause, grpId, grpName, cacheName, idxName, pageIds);
+
+ processFailure(FailureType.CRITICAL_ERROR, e);
+
+ return e;
+ }
}
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java
index 7711b42..8f61270 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java
@@ -234,6 +234,7 @@ public class H2TreeIndex extends H2TreeIndexBase {
table.cacheName(),
cctx.offheap().reuseListForIndex(treeName),
cctx.groupId(),
+ cctx.group().name(),
cctx.dataRegion().pageMemory(),
cctx.shared().wal(),
cctx.offheap().globalRemoveId(),
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2TreeCorruptedTreeExceptionTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2TreeCorruptedTreeExceptionTest.java
new file mode 100644
index 0000000..1b8fdd6
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2TreeCorruptedTreeExceptionTest.java
@@ -0,0 +1,162 @@
+/*
+ * 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.ignite.internal.processors.cache.index;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.metric.IoStatisticsHolder;
+import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree;
+import org.apache.ignite.internal.processors.cache.persistence.tree.CorruptedTreeException;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler;
+import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandlerWrapper;
+import org.apache.ignite.internal.processors.query.h2.database.H2Tree;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.testframework.ListeningTestLogger;
+import org.apache.ignite.testframework.LogListener;
+import org.apache.ignite.testframework.MessageOrderLogListener;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+import static java.lang.String.format;
+
+/** */
+public class H2TreeCorruptedTreeExceptionTest extends GridCommonAbstractTest {
+ /** */
+ private static final String IDX_NAME = "A_IDX";
+
+ /** */
+ private static final String GRP_NAME = "cacheGrp";
+
+ /** */
+ private final AtomicBoolean failWithCorruptTree = new AtomicBoolean(false);
+
+ /** */
+ private PageHandlerWrapper<BPlusTree.Result> regularWrapper;
+
+ /** */
+ private final LogListener logListener = new MessageOrderLogListener(
+ format(".*?Tree is corrupted.*?cacheId=65, cacheName=A, indexName=%s, groupName=%s.*", IDX_NAME, GRP_NAME)
+ );
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ cfg.setConsistentId(gridName);
+
+ cfg.setCacheConfiguration(new CacheConfiguration<>()
+ .setName(DEFAULT_CACHE_NAME)
+ .setAffinity(new RendezvousAffinityFunction().setPartitions(1))
+ .setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL)
+ );
+
+ ListeningTestLogger listeningTestLog = new ListeningTestLogger(false, log);
+
+ listeningTestLog.registerListener(logListener);
+
+ cfg.setGridLogger(listeningTestLog);
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ super.beforeTest();
+
+ stopAllGrids();
+
+ cleanPersistenceDir();
+
+ regularWrapper = BPlusTree.pageHndWrapper;
+
+ BPlusTree.pageHndWrapper = (tree, hnd) -> {
+ if (hnd instanceof BPlusTree.Insert) {
+ PageHandler<Object, BPlusTree.Result> delegate = (PageHandler<Object, BPlusTree.Result>)hnd;
+
+ return new PageHandler<Object, BPlusTree.Result>() {
+ @Override public BPlusTree.Result run(
+ int cacheId,
+ long pageId,
+ long page,
+ long pageAddr,
+ PageIO io,
+ Boolean walPlc,
+ Object arg,
+ int intArg,
+ IoStatisticsHolder statHolder
+ ) throws IgniteCheckedException {
+ BPlusTree.Result res =
+ delegate.run(cacheId, pageId, page, pageAddr, io, walPlc, arg, intArg, statHolder);
+
+ if (failWithCorruptTree.get() && tree instanceof H2Tree && tree.getName().contains(IDX_NAME))
+ throw new RuntimeException("test exception");
+
+ return res;
+ }
+ };
+ }
+ else
+ return hnd;
+ };
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ //restoring wrapper
+ BPlusTree.pageHndWrapper = regularWrapper;
+
+ stopAllGrids();
+
+ cleanPersistenceDir();
+
+ super.afterTest();
+ }
+
+ /** */
+ @Test
+ public void testCorruptedTree() throws Exception {
+ IgniteEx srv = startGrid(0);
+
+ srv.cluster().active(true);
+
+ IgniteCache<Integer, Integer> cache = srv.getOrCreateCache(DEFAULT_CACHE_NAME);
+
+ cache.query(new SqlFieldsQuery("create table a (id integer primary key, a integer) with \"CACHE_GROUP=" + GRP_NAME + "\""));
+ cache.query(new SqlFieldsQuery("create index " + IDX_NAME + " on a(a)"));
+
+ failWithCorruptTree.set(true);
+
+ try {
+ cache.query(new SqlFieldsQuery("insert into a(id, a) values (11, 1)"));
+
+ fail("Cache operations are expected to fail");
+ }
+ catch (Throwable e) {
+ assertTrue(X.hasCause(e, CorruptedTreeException.class));
+ }
+
+ assertTrue(logListener.check());
+ }
+}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
index dfcce97..0c68da9 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
@@ -37,6 +37,7 @@ import org.apache.ignite.internal.processors.cache.IgniteCacheConfigurationPrimi
import org.apache.ignite.internal.processors.cache.IgniteCacheGroupsSqlTest;
import org.apache.ignite.internal.processors.cache.IgniteCacheStarvationOnRebalanceTest;
import org.apache.ignite.internal.processors.cache.IgniteClientReconnectQueriesTest;
+import org.apache.ignite.internal.processors.cache.index.H2TreeCorruptedTreeExceptionTest;
import org.apache.ignite.internal.processors.cache.persistence.RebuildIndexLogMessageTest;
import org.apache.ignite.internal.processors.cache.ttl.CacheTtlAtomicLocalSelfTest;
import org.apache.ignite.internal.processors.cache.ttl.CacheTtlAtomicPartitionedSelfTest;
@@ -94,7 +95,9 @@ import org.junit.runners.Suite;
CacheGroupMetricsWithIndexTest.class,
- RebuildIndexLogMessageTest.class
+ RebuildIndexLogMessageTest.class,
+
+ H2TreeCorruptedTreeExceptionTest.class
})
public class IgniteCacheWithIndexingTestSuite {
}