/* * 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.database; import java.util.HashSet; import java.util.Set; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.pagemem.PageMemory; import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager; import org.apache.ignite.internal.processors.cache.database.tree.io.PageIO; import org.apache.ignite.internal.processors.cache.database.tree.reuse.ReuseList; import org.apache.ignite.internal.processors.cache.database.tree.reuse.ReuseListImpl; import static org.apache.ignite.internal.pagemem.PageIdUtils.effectivePageId; /** * Test with reuse list. */ public class BPlusTreeReuseSelfTest extends BPlusTreeSelfTest { /** {@inheritDoc} */ @Override protected ReuseList createReuseList(int cacheId, PageMemory pageMem, long rootId, boolean initNew) throws IgniteCheckedException { return new TestReuseList(cacheId, "test", pageMem, null, rootId, initNew); } /** {@inheritDoc} */ @Override protected void assertNoLocks() { super.assertNoLocks(); assertTrue(TestReuseList.checkNoLocks()); } /** * */ private static class TestReuseList extends ReuseListImpl { /** */ private static ThreadLocal<Set<Long>> readLocks = new ThreadLocal<Set<Long>>() { @Override protected Set<Long> initialValue() { return new HashSet<>(); } }; /** */ private static ThreadLocal<Set<Long>> writeLocks = new ThreadLocal<Set<Long>>() { @Override protected Set<Long> initialValue() { return new HashSet<>(); } }; /** * @param cacheId Cache ID. * @param name Name (for debug purpose). * @param pageMem Page memory. * @param wal Write ahead log manager. * @param metaPageId Metadata page ID. * @param initNew {@code True} if new metadata should be initialized. * @throws IgniteCheckedException If failed. */ public TestReuseList( int cacheId, String name, PageMemory pageMem, IgniteWriteAheadLogManager wal, long metaPageId, boolean initNew ) throws IgniteCheckedException { super(cacheId, name, pageMem, wal, metaPageId, initNew); } /** {@inheritDoc} */ @Override public void onBeforeReadLock(int cacheId, long pageId, long page) { // No-op. } /** {@inheritDoc} */ @Override public void onReadLock(int cacheId, long pageId, long page, long pageAddr) { checkPageId(pageId, pageAddr); assertTrue(readLocks.get().add(pageId)); } /** {@inheritDoc} */ @Override public void onReadUnlock(int cacheId, long pageId, long page, long pageAddr) { checkPageId(pageId, pageAddr); assertTrue(readLocks.get().remove(pageId)); } /** {@inheritDoc} */ @Override public void onBeforeWriteLock(int cacheId, long pageId, long page) { // No-op. } /** {@inheritDoc} */ @Override public void onWriteLock(int cacheId, long pageId, long page, long pageAddr) { if (pageAddr == 0L) return; // Failed to lock. checkPageId(pageId, pageAddr); assertTrue(writeLocks.get().add(pageId)); } /** {@inheritDoc} */ @Override public void onWriteUnlock(int cacheId, long pageId, long page, long pageAddr) { assertEquals(effectivePageId(pageId), effectivePageId(PageIO.getPageId(pageAddr))); assertTrue(writeLocks.get().remove(pageId)); } static boolean checkNoLocks() { return readLocks.get().isEmpty() && writeLocks.get().isEmpty(); } } }