use of org.apache.ignite.internal.processors.cache.persistence.tree.CorruptedTreeException in project ignite by apache.
the class InlineIndexTree method corruptedTreeException.
/**
* 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, grpName, def.idxName().cacheName(), def.idxName().idxName(), grpId, pageIds);
processFailure(FailureType.CRITICAL_ERROR, e);
return e;
}
use of org.apache.ignite.internal.processors.cache.persistence.tree.CorruptedTreeException in project ignite by apache.
the class CorruptedTreeFailureHandlingTest method testCorruptedPage.
/**
* Check that if a corrupted page exists, an {@link CorruptedTreeException}
* will be thrown and a diagnostic file will be generated.
*
* @throws Exception If failed.
*/
@Test
public void testCorruptedPage() throws Exception {
IgniteEx srv = startGrid(0);
File diagnosticDir = new File(srv.context().config().getWorkDirectory(), "diagnostic");
FileUtils.deleteDirectory(diagnosticDir);
srv.cluster().state(ClusterState.ACTIVE);
IgniteCache<Integer, Integer> cache = srv.getOrCreateCache(DEFAULT_CACHE_NAME);
for (int i = 0; i < 10; i++) cache.put(i, i);
int pageSize = srv.configuration().getDataStorageConfiguration().getPageSize();
int grpId = srv.context().cache().cacheGroups().stream().filter(context -> context.cacheOrGroupName().equals(DEFAULT_CACHE_NAME)).findAny().orElseThrow(() -> new RuntimeException("Cache group not found")).groupId();
stopGrid(0, false);
// Node is stopped, we're ready to corrupt partition data.
long link = linkRef.get();
long pageId = PageIdUtils.pageId(link);
int itemId = PageIdUtils.itemId(link);
ByteBuffer pageBuf = ByteBuffer.allocateDirect(pageSize);
OpenOption[] options = { StandardOpenOption.READ, StandardOpenOption.WRITE };
try (RandomAccessFileIO fileIO = new RandomAccessFileIO(fileRef.get(), options)) {
DataPageIO dataPageIO = DataPageIO.VERSIONS.latest();
long pageOff = pageSize + PageIdUtils.pageIndex(pageId) * pageSize;
// Read index page.
fileIO.position(pageOff);
fileIO.readFully(pageBuf);
long pageAddr = GridUnsafe.bufferAddress(pageBuf);
// Remove existing item from index page.
dataPageIO.removeRow(pageAddr, itemId, pageSize);
// Recalculate CRC.
PageIO.setCrc(pageAddr, 0);
pageBuf.rewind();
PageIO.setCrc(pageAddr, FastCrc.calcCrc(pageBuf, pageSize));
// Write it back.
pageBuf.rewind();
fileIO.position(pageOff);
fileIO.writeFully(pageBuf);
}
LogListener logLsnr = LogListener.matches("CorruptedTreeException has occurred. " + "To diagnose it, make a backup of the following directories: ").build();
srv = startGrid(0, cfg -> {
cfg.setGridLogger(new ListeningTestLogger(cfg.getGridLogger(), logLsnr));
});
// Add modified page to WAL so it won't be restored to previous (valid) state.
pageBuf.rewind();
ByteBuffer cpBuf = ByteBuffer.allocate(pageBuf.capacity());
cpBuf.put(pageBuf);
PageSnapshot pageSnapshot = new PageSnapshot(new FullPageId(pageId, grpId), cpBuf.array(), pageSize);
srv.context().cache().context().wal().log(pageSnapshot);
// Access cache.
cache = srv.cache(DEFAULT_CACHE_NAME);
try {
for (int i = 0; i < CACHE_ENTRIES; i++) cache.get(i);
fail("Cache operations are expected to fail");
} catch (Throwable e) {
assertTrue(X.hasCause(e, CorruptedTreeException.class));
}
assertTrue(GridTestUtils.waitForCondition(() -> G.allGrids().isEmpty(), 10_000L));
assertTrue(diagnosticDir.exists());
assertTrue(diagnosticDir.isDirectory());
Pattern corruptedPagesFileNamePtrn = corruptedPagesFileNamePattern();
File[] txtFiles = diagnosticDir.listFiles((dir, name) -> corruptedPagesFileNamePtrn.matcher(name).matches());
assertFalse(F.isEmpty(txtFiles));
assertEquals(1, txtFiles.length);
assertTrue(logLsnr.check());
}
use of org.apache.ignite.internal.processors.cache.persistence.tree.CorruptedTreeException in project ignite by apache.
the class DiagnosticProcessorTest method testOutputDiagnosticCorruptedPagesInfo.
/**
* Check that when an CorruptedTreeException is thrown, a "corruptedPages_TIMESTAMP.txt"
* will be created and a warning will be in the log.
*
* @throws Exception If failed.
*/
@Test
public void testOutputDiagnosticCorruptedPagesInfo() throws Exception {
ListeningTestLogger listeningTestLog = new ListeningTestLogger(GridAbstractTest.log);
IgniteEx n = startGrid(0, cfg -> {
cfg.setGridLogger(listeningTestLog);
});
n.cluster().state(ClusterState.ACTIVE);
awaitPartitionMapExchange();
for (int i = 0; i < 10_000; i++) n.cache(DEFAULT_CACHE_NAME).put(i, "val_" + i);
assertNotNull(n.context().diagnostic());
T2<Integer, Long> anyPageId = findAnyPageId(n);
assertNotNull(anyPageId);
LogListener logLsnr = LogListener.matches("CorruptedTreeException has occurred. " + "To diagnose it, make a backup of the following directories: ").build();
listeningTestLog.registerListener(logLsnr);
n.context().failure().process(new FailureContext(FailureType.CRITICAL_ERROR, new CorruptedTreeException("Test ex", null, DEFAULT_CACHE_NAME, anyPageId.get1(), anyPageId.get2())));
assertTrue(logLsnr.check());
Path diagnosticPath = getFieldValue(n.context().diagnostic(), "diagnosticPath");
List<File> corruptedPagesFiles = Arrays.stream(diagnosticPath.toFile().listFiles()).filter(f -> corruptedPagesFileNamePattern().matcher(f.getName()).matches()).collect(toList());
assertEquals(1, corruptedPagesFiles.size());
assertTrue(corruptedPagesFiles.get(0).length() > 0);
}
Aggregations