use of org.apache.ignite.lang.IgniteInternalCheckedException in project ignite-3 by apache.
the class RootQuery method tryClose.
/**
* Can be called multiple times after receive each error at {@link #onResponse(RemoteFragmentKey, Throwable)}.
*/
@Override
protected void tryClose() {
QueryState state0 = null;
synchronized (mux) {
if (state == QueryState.CLOSED) {
return;
}
if (state == QueryState.INITED || state == QueryState.PLANNING || state == QueryState.MAPPING) {
state = QueryState.CLOSED;
return;
}
if (state == QueryState.EXECUTING) {
state0 = state = QueryState.CLOSING;
root.closeInternal();
}
if (state == QueryState.CLOSING && waiting.isEmpty()) {
state0 = state = QueryState.CLOSED;
}
}
if (state0 == QueryState.CLOSED) {
try {
IgniteInternalException wrpEx = null;
for (String nodeId : remotes) {
try {
if (!nodeId.equals(root.context().localNodeId())) {
exchangeService.closeQuery(nodeId, id());
}
} catch (IgniteInternalCheckedException e) {
if (wrpEx == null) {
wrpEx = new IgniteInternalException("Failed to send cancel message. [nodeId=" + nodeId + ']', e);
} else {
wrpEx.addSuppressed(e);
}
}
}
if (wrpEx != null) {
log.warn("An exception occures during the query cancel", wrpEx);
}
} finally {
super.tryClose();
}
}
}
use of org.apache.ignite.lang.IgniteInternalCheckedException in project ignite-3 by apache.
the class ItBplusTreeSelfTest method testPutSizeLivelock.
/**
* The test forces {@link BplusTree#size} method to run into a livelock: during single run the method is picking up new pages which are
* concurrently added to the tree until the new pages are not added anymore. Test verifies that despite livelock condition a size from a
* valid range is returned.
*
* <p>NB: This test has to be changed with the integration of IGNITE-3478.
*
* @throws Exception if test failed
*/
@Test
public void testPutSizeLivelock() throws Exception {
MAX_PER_PAGE = 5;
CNT = 800;
final int slidingWindowSize = 16;
final boolean debugPrint = false;
final TestTree tree = createTestTree(false);
final AtomicLong curRmvKey = new AtomicLong(0);
final AtomicLong curPutKey = new AtomicLong(slidingWindowSize);
for (long i = curRmvKey.get(); i < curPutKey.get(); ++i) {
assertNull(tree.put(i));
}
final int hwThreads = CPUS;
final int putRmvThreadCnt = Math.max(1, hwThreads / 2);
final int sizeThreadCnt = hwThreads - putRmvThreadCnt;
final CyclicBarrier putRmvOpBarrier = new CyclicBarrier(putRmvThreadCnt, () -> {
if (debugPrint) {
try {
println("===BARRIER=== size=" + tree.size() + " [" + tree.findFirst() + ".." + tree.findLast() + "]");
} catch (IgniteInternalCheckedException e) {
// ignore
}
}
});
final int loopCnt = CNT / hwThreads;
CompletableFuture<?> putRmvFut = runMultiThreadedAsync(() -> {
for (int i = 0; i < loopCnt && !stop.get(); ++i) {
int order;
try {
order = putRmvOpBarrier.await();
} catch (BrokenBarrierException e) {
// barrier reset() has been called: terminate
break;
}
Long putVal = curPutKey.getAndIncrement();
if ((i & 0xff) == 0) {
println(order + ": --> put(" + putVal + ")");
}
assertNull(tree.put(putVal));
Long rmvVal = curRmvKey.getAndIncrement();
if ((i & 0xff) == 0) {
println(order + ": --> rmv(" + rmvVal + ")");
}
assertEquals(rmvVal, tree.remove(rmvVal));
assertNull(tree.findOne(rmvVal));
}
return null;
}, putRmvThreadCnt, "put-remove");
CompletableFuture<?> sizeFut = runMultiThreadedAsync(() -> {
final List<Long> treeContents = new ArrayList<>(slidingWindowSize * 2);
final TreeRowClosure<Long, Long> rowDumper = (tree1, io, pageAddr, idx) -> {
treeContents.add(io.getLookupRow(tree1, pageAddr, idx));
final long endMs = System.currentTimeMillis() + 10;
final long endPutKey = curPutKey.get() + MAX_PER_PAGE;
while (System.currentTimeMillis() < endMs && curPutKey.get() < endPutKey) {
Thread.yield();
}
return true;
};
while (!stop.get()) {
treeContents.clear();
long treeSize = tree.size(rowDumper);
long curPutVal = curPutKey.get();
println(" ======> size=" + treeSize + "; last-put-value=" + curPutVal);
if (treeSize < slidingWindowSize || treeSize > curPutVal) {
fail("Tree size is not in bounds [" + slidingWindowSize + ".." + curPutVal + "]:" + treeSize + "; contents=" + treeContents);
}
}
return null;
}, sizeThreadCnt, "size");
asyncRunFut = CompletableFuture.allOf(putRmvFut, sizeFut);
try {
putRmvFut.get(getTestTimeout(), MILLISECONDS);
} finally {
stop.set(true);
putRmvOpBarrier.reset();
asyncRunFut.get(getTestTimeout(), MILLISECONDS);
}
tree.validateTree();
assertNoLocks();
}
use of org.apache.ignite.lang.IgniteInternalCheckedException in project ignite-3 by apache.
the class ItBplusTreeSelfTest method doTestSizeForRandomPutRmvMultithreadedAsync.
/**
* Verifies that concurrent running of {@link BplusTree#put} + {@link BplusTree#remove} sequence and {@link BplusTree#size} methods
* results in correct calculation of tree size.
*
* <p>Since in the presence of concurrent modifications the size may differ from the actual one, the test maintains sliding window of
* records in the tree, uses a barrier between concurrent runs to limit runaway delta in the calculated size, and checks that the
* measured size lies within certain bounds.
*
* <p>NB: This test has to be changed with the integration of IGNITE-3478.
*/
public void doTestSizeForRandomPutRmvMultithreadedAsync(final int rmvPutSlidingWindowSize) throws Exception {
MAX_PER_PAGE = 5;
final boolean debugPrint = false;
final TestTree tree = createTestTree(false);
final AtomicLong curRmvKey = new AtomicLong(0);
final AtomicLong curPutKey = new AtomicLong(rmvPutSlidingWindowSize);
for (long i = curRmvKey.get(); i < curPutKey.get(); ++i) {
assertNull(tree.put(i));
}
final int putRmvThreadCnt = Math.min(CPUS, rmvPutSlidingWindowSize);
final int sizeThreadCnt = putRmvThreadCnt;
final CyclicBarrier putRmvOpBarrier = new CyclicBarrier(putRmvThreadCnt + sizeThreadCnt, () -> {
if (debugPrint) {
try {
println("===BARRIER=== size=" + tree.size() + "; contents=[" + tree.findFirst() + ".." + tree.findLast() + "]" + "; rmvVal=" + curRmvKey.get() + "; putVal=" + curPutKey.get());
println(tree.printTree());
} catch (IgniteInternalCheckedException e) {
// ignore
}
}
});
final int loopCnt = 250;
CompletableFuture<?> putRmvFut = runMultiThreadedAsync(() -> {
for (int i = 0; i < loopCnt && !stop.get(); ++i) {
int order;
try {
order = putRmvOpBarrier.await();
} catch (BrokenBarrierException e) {
break;
}
Long putVal = curPutKey.getAndIncrement();
if (debugPrint || (i & 0x3ff) == 0) {
println(order + ": --> put(" + putVal + ")");
}
assertNull(tree.put(putVal));
Long rmvVal = curRmvKey.getAndIncrement();
if (debugPrint || (i & 0x3ff) == 0) {
println(order + ": --> rmv(" + rmvVal + ")");
}
assertEquals(rmvVal, tree.remove(rmvVal));
assertNull(tree.findOne(rmvVal));
}
return null;
}, putRmvThreadCnt, "put-remove");
CompletableFuture<?> sizeFut = runMultiThreadedAsync(() -> {
final List<Long> treeContents = new ArrayList<>(rmvPutSlidingWindowSize * 2);
final TreeRowClosure<Long, Long> rowDumper = (tree1, io, pageAddr, idx) -> {
treeContents.add(io.getLookupRow(tree1, pageAddr, idx));
return true;
};
for (long iter = 0; !stop.get(); ++iter) {
int order = 0;
try {
order = putRmvOpBarrier.await();
} catch (BrokenBarrierException e) {
break;
}
long correctSize = curPutKey.get() - curRmvKey.get();
treeContents.clear();
long treeSize = tree.size(rowDumper);
long minBound = correctSize - putRmvThreadCnt;
long maxBound = correctSize + putRmvThreadCnt;
if (debugPrint || (iter & 0x3ff) == 0) {
println(order + ": size=" + treeSize + "; bounds=[" + minBound + ".." + maxBound + "]; contents=" + treeContents);
}
if (treeSize < minBound || treeSize > maxBound) {
fail("Tree size is not in bounds [" + minBound + ".." + maxBound + "]: " + treeSize + "; Tree contents: " + treeContents);
}
}
return null;
}, sizeThreadCnt, "size");
CompletableFuture<?> lockPrintingFut = runMultiThreadedAsync(() -> {
while (!stop.get()) {
Thread.sleep(1_000);
println(TestTree.printLocks());
}
return null;
}, 1, "printLocks");
asyncRunFut = CompletableFuture.allOf(putRmvFut, sizeFut, lockPrintingFut);
try {
putRmvFut.get(getTestTimeout(), MILLISECONDS);
} finally {
stop.set(true);
// To ensure that an BrokenBarrierException is thrown on method CyclicBarrier#await in other threads.
while (!asyncRunFut.isDone()) {
putRmvOpBarrier.reset();
Thread.sleep(10);
}
asyncRunFut.get(getTestTimeout(), MILLISECONDS);
}
tree.validateTree();
assertNoLocks();
}
use of org.apache.ignite.lang.IgniteInternalCheckedException in project ignite-3 by apache.
the class BplusTree method findLast.
/**
* Returns a value mapped to the greatest key, or {@code null} if tree is empty or no entry matches the passed filter.
*
* @param c Filter closure.
* @return Value.
* @throws IgniteInternalCheckedException If failed.
*/
public T findLast(final TreeRowClosure<L, T> c) throws IgniteInternalCheckedException {
checkDestroyed();
Get g = null;
try {
if (c == null) {
g = new GetOne(null, null, null, true);
doFind(g);
return (T) g.row;
} else {
GetLast getLast = new GetLast(c);
g = getLast;
return getLast.find();
}
} catch (CorruptedDataStructureException e) {
throw e;
} catch (IgniteInternalCheckedException e) {
throw new IgniteInternalCheckedException("Runtime failure on last row lookup", e);
} catch (RuntimeException | AssertionError e) {
Get g0 = g;
long[] pageIds = pages(g == null, () -> new long[] { g0.pageId });
throw corruptedTreeException("Runtime failure on last row lookup", e, grpId, pageIds);
} finally {
checkDestroyed();
}
}
use of org.apache.ignite.lang.IgniteInternalCheckedException in project ignite-3 by apache.
the class BplusTree method iterate.
/**
* Iterates over the tree.
*
* @param lower Lower bound inclusive.
* @param upper Upper bound inclusive.
* @param c Closure applied for all found items, iteration is stopped if closure returns {@code false}.
* @throws IgniteInternalCheckedException If failed.
*/
public void iterate(L lower, L upper, TreeRowClosure<L, T> c) throws IgniteInternalCheckedException {
checkDestroyed();
ClosureCursor cursor = new ClosureCursor(lower, upper, c);
try {
cursor.iterate();
} catch (CorruptedDataStructureException e) {
throw e;
} catch (IgniteInternalCheckedException e) {
throw new IgniteInternalCheckedException("Runtime failure on bounds: [lower=" + lower + ", upper=" + upper + "]", e);
} catch (RuntimeException | AssertionError e) {
throw corruptedTreeException("Runtime failure on bounds: [lower=" + lower + ", upper=" + upper + "]", e, grpId, pages(cursor.getCursor != null, () -> new long[] { cursor.getCursor.pageId }));
} finally {
checkDestroyed();
}
}
Aggregations