use of org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener in project ignite by apache.
the class JmhPageLockTrackerBenchmark method lockUnlock.
/**
* Mesure cost for (beforelock -> lock -> unlock) operation.
*/
@Benchmark
@BenchmarkMode(Mode.Throughput)
@Fork(1)
@Warmup(iterations = 10)
@Measurement(iterations = 10)
public // @OutputTimeUnit(TimeUnit.MICROSECONDS)
void lockUnlock(ThreadLocalState localState) {
PageLockListener pl = localState.pl;
for (int i = 0; i < localState.stackSize; i++) {
int pageId = i + 1;
pl.onBeforeReadLock(localState.StructureId, pageId, pageId);
pl.onReadLock(localState.StructureId, pageId, pageId, pageId);
}
for (int i = localState.stackSize; i > 0; i--) {
int pageId = i;
pl.onReadUnlock(localState.StructureId, pageId, pageId, pageId);
}
}
use of org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener in project ignite by apache.
the class SharedPageLockTrackerTest method testCloseListener.
/**
* Tests that a structure gets unregistered when a listener gets closed.
*/
@Test
public void testCloseListener() {
SharedPageLockTracker tracker = new SharedPageLockTracker();
PageLockListener foo = tracker.registerStructure("foo");
PageLockListener bar = tracker.registerStructure("bar");
assertThat(tracker.dump().structureIdToStructureName.values(), containsInAnyOrder("foo", "bar"));
IgniteUtils.closeQuiet(foo);
assertThat(tracker.dump().structureIdToStructureName.values(), containsInAnyOrder("bar"));
IgniteUtils.closeQuiet(bar);
assertThat(tracker.dump().structureIdToStructureName.values(), is(empty()));
}
use of org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener in project ignite by apache.
the class SharedPageLockTrackerTest method doTestTakeDumpByCount.
/**
*/
private void doTestTakeDumpByCount(int pagesCnt, int structuresCnt, int dumpCnt, int threads) throws IgniteCheckedException, InterruptedException {
SharedPageLockTracker sharedPageLockTracker = new SharedPageLockTracker();
List<PageMeta> pageMetas = new CopyOnWriteArrayList<>();
int id = 1;
for (int i = 0; i < pagesCnt; i++) pageMetas.add(new PageMeta((id++) % structuresCnt, id++, id++, id++));
List<PageLockListener> pageLsnrs = new ArrayList<>();
for (int i = 0; i < structuresCnt; i++) pageLsnrs.add(sharedPageLockTracker.registerStructure("my-structure-" + i));
AtomicBoolean stop = new AtomicBoolean();
CountDownLatch awaitThreadStartLatch = new CountDownLatch(threads);
IgniteInternalFuture f = GridTestUtils.runMultiThreadedAsync(() -> {
List<PageLockListener> locks = new ArrayList<>(pageLsnrs);
List<PageMeta> pages = new ArrayList<>();
pages.addAll(pageMetas);
boolean latchDown = false;
while (!stop.get()) {
Collections.shuffle(locks);
Collections.shuffle(pages);
for (PageLockListener lsnr : locks) {
for (PageMeta pageMeta : pages) {
awaitRandom(50);
lsnr.onBeforeReadLock(pageMeta.structureId, pageMeta.pageId, pageMeta.page);
awaitRandom(50);
lsnr.onReadLock(pageMeta.structureId, pageMeta.pageId, pageMeta.page, pageMeta.pageAddr);
}
}
awaitRandom(10);
Collections.reverse(locks);
Collections.reverse(pages);
for (PageLockListener lsnr : locks) {
for (PageMeta pageMeta : pages) {
awaitRandom(50);
lsnr.onReadUnlock(pageMeta.structureId, pageMeta.pageId, pageMeta.page, pageMeta.pageAddr);
}
}
if (!latchDown) {
awaitThreadStartLatch.countDown();
latchDown = true;
}
}
}, threads, "PageLocker");
awaitThreadStartLatch.await();
for (int i = 0; i < dumpCnt; i++) {
awaitRandom(1000);
SharedPageLockTrackerDump dump = sharedPageLockTracker.dump();
assertEquals(threads, dump.threadPageLockStates.size());
assertEquals(0, dump.threadPageLockStates.stream().filter(e -> e.invalidContext != null).count());
}
stop.set(true);
f.get();
}
use of org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener in project ignite by apache.
the class SharedPageLockTrackerTest method testMemoryLeakOnThreadTerminates.
/**
* Test for checking that internal maps is not leaked after threads stopped.
*/
@Test
public void testMemoryLeakOnThreadTerminates() throws Exception {
int threadLimits = 1000;
int timeOutWorkerInterval = 10_000;
Consumer<Set<PageLockThreadState>> handler = (threads) -> {
};
SharedPageLockTracker sharedPageLockTracker = new SharedPageLockTracker(threadLimits, timeOutWorkerInterval, handler, new MemoryCalculator());
int threads = 10_000;
int cacheId = 1;
long pageId = 2;
long page = 3;
long pageAdder = 4;
PageLockListener lt = sharedPageLockTracker.registerStructure("test");
List<Thread> threadsList = new ArrayList<>(threads);
String threadNamePreffix = "my-thread-";
for (int i = 0; i < threads; i++) {
Thread th = new Thread(() -> {
lt.onBeforeReadLock(cacheId, pageId, page);
lt.onReadLock(cacheId, pageId, page, pageAdder);
lt.onReadUnlock(cacheId, pageId, page, pageAdder);
});
th.setName(threadNamePreffix + i);
threadsList.add(th);
th.start();
System.out.println(">>> start thread:" + th.getName());
}
threadsList.forEach(th -> {
try {
System.out.println(">>> await thread:" + th.getName());
th.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
sharedPageLockTracker.start();
SharedPageLockTrackerDump dump = sharedPageLockTracker.dump();
assertTrue(dump.time > 0);
assertTrue(!dump.threadPageLockStates.isEmpty());
for (ThreadPageLockState threadPageLockState : dump.threadPageLockStates) {
assertNull(threadPageLockState.invalidContext);
assertTrue(threadPageLockState.threadName.startsWith(threadNamePreffix));
assertSame(Thread.State.TERMINATED, threadPageLockState.state);
}
assertEquals(1, dump.structureIdToStructureName.size());
synchronized (sharedPageLockTracker) {
Map<Long, Thread> threadMap0 = U.field(sharedPageLockTracker, "threadIdToThreadRef");
Map<Long, ?> threadStacksMap0 = U.field(sharedPageLockTracker, "threadStacks");
// Stopped threads should remove from map after map limit reached.
assertTrue(threadMap0.size() <= threadLimits);
assertTrue(threadStacksMap0.size() <= threadLimits);
}
// Await cleanup worker interval.
U.sleep(timeOutWorkerInterval + 1000);
synchronized (sharedPageLockTracker) {
Map<Long, Thread> threadMap1 = U.field(sharedPageLockTracker, "threadIdToThreadRef");
Map<Long, ?> threadStacksMap1 = U.field(sharedPageLockTracker, "threadStacks");
// Cleanup worker should remove all stopped threads.
assertTrue(threadMap1.isEmpty());
assertTrue(threadStacksMap1.isEmpty());
}
SharedPageLockTrackerDump dump1 = sharedPageLockTracker.dump();
assertTrue(dump1.time > 0);
assertTrue(dump1.threadPageLockStates.isEmpty());
}
use of org.apache.ignite.internal.processors.cache.persistence.tree.util.PageLockListener in project ignite by apache.
the class SharedPageLockTrackerTest method testAutoDetectHangThreads.
/**
*/
@Test
public void testAutoDetectHangThreads() throws Exception {
String thInWaitName = "threadInWait";
String thInRunnableName = "threadInRunnable";
String thInAwaitWithoutLocksName = "threadInAwaitWithoutLocks";
AtomicReference<Exception> error = new AtomicReference<>();
CountDownLatch awaitLatch = new CountDownLatch(1);
SharedPageLockTracker sharedPageLockTracker = new SharedPageLockTracker(1000, 10_000, hangsThreads -> {
if (hangsThreads.isEmpty()) {
error.set(new Exception("No one thread is hangs."));
return;
}
// Checking threads.
for (PageLockThreadState state : hangsThreads) {
String name = state.thread.getName();
if (name.equals(thInAwaitWithoutLocksName)) {
error.set(new Exception("Thread without locks should not be here." + state));
continue;
}
if (name.equals(thInWaitName)) {
if (state.heldLockCnt == 0)
error.set(new Exception("Thread should hold lock." + state));
if (state.thread.getState() != Thread.State.WAITING)
error.set(new Exception("Thread should in WAITING state." + state));
continue;
}
if (name.equals(thInRunnableName)) {
if (state.heldLockCnt == 0)
error.set(new Exception("Thread should hold lock." + state));
if (state.thread.getState() != Thread.State.RUNNABLE)
error.set(new Exception("Thread should in RUNNABLE state." + state));
continue;
}
}
awaitLatch.countDown();
}, new MemoryCalculator());
int cacheId = 1;
long pageId = 2;
long page = 3;
long pageAdder = 4;
PageLockListener lt = sharedPageLockTracker.registerStructure("test");
Thread thInWait = new Thread(() -> {
lt.onBeforeReadLock(cacheId, pageId, page);
lt.onReadLock(cacheId, pageId, page, pageAdder);
try {
awaitLatch.await();
} catch (InterruptedException ignored) {
// No-op.
}
});
thInWait.setName(thInWaitName);
Thread thInRunnable = new Thread(() -> {
lt.onBeforeReadLock(cacheId, pageId, page);
lt.onReadLock(cacheId, pageId, page, pageAdder);
while (awaitLatch.getCount() > 0) {
// Busy wait. Can not park this thread, we should check running hangs too.
}
});
thInRunnable.setName(thInRunnableName);
Thread thInAwaitWithoutLocks = new Thread(() -> {
lt.onBeforeReadLock(cacheId, pageId, page);
lt.onReadLock(cacheId, pageId, page, pageAdder);
lt.onReadUnlock(cacheId, pageId, page, pageAdder);
try {
awaitLatch.await();
} catch (InterruptedException ignored) {
// No-op.
}
});
thInAwaitWithoutLocks.setName(thInAwaitWithoutLocksName);
sharedPageLockTracker.start();
thInWait.start();
thInRunnable.start();
thInAwaitWithoutLocks.start();
thInWait.join();
thInRunnable.join();
thInAwaitWithoutLocks.join();
if (error.get() != null)
throw error.get();
}
Aggregations