blob: 4a50e4030f7c80741e15db3ce120614dce530f80 [file] [log] [blame]
/*
* 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.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.ignite.configuration.DataRegionConfiguration;
import org.apache.ignite.internal.mem.DirectMemoryProvider;
import org.apache.ignite.internal.mem.file.MappedFileMemoryProvider;
import org.apache.ignite.internal.pagemem.FullPageId;
import org.apache.ignite.internal.pagemem.PageIdAllocator;
import org.apache.ignite.internal.pagemem.PageMemory;
import org.apache.ignite.internal.pagemem.impl.PageMemoryNoStoreImpl;
import org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl;
import org.apache.ignite.internal.processors.cache.persistence.IndexStorageImpl;
import org.apache.ignite.internal.processors.cache.persistence.RootPage;
import org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerManager;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.testframework.junits.GridTestKernalContext;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.junit.Test;
import static org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerManager.NOOP_LSNR;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
*
*/
public class IndexStorageSelfTest extends GridCommonAbstractTest {
/** Make sure page is small enough to trigger multiple pages in a linked list. */
private static final int PAGE_SIZE = 1024;
/** */
private static File allocationPath;
/** */
private static final char[] ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
allocationPath = U.resolveWorkDirectory(U.defaultWorkDirectory(), "pagemem", false);
}
/**
* @throws Exception if failed.
*/
@Test
public void testMetaIndexAllocation() throws Exception {
metaAllocation();
}
/**
* @throws Exception If failed.
*/
private void metaAllocation() throws Exception {
PageMemory mem = memory(true);
int[] cacheIds = new int[]{1, "partitioned".hashCode(), "replicated".hashCode()};
Map<Integer, Map<String, RootPage>> allocatedIdxs = new HashMap<>();
mem.start();
try {
final Map<Integer, IndexStorageImpl> storeMap = new HashMap<>();
for (int i = 0; i < 1_000; i++) {
int cacheId = cacheIds[i % cacheIds.length];
Map<String, RootPage> idxMap = allocatedIdxs.get(cacheId);
if (idxMap == null) {
idxMap = new HashMap<>();
allocatedIdxs.put(cacheId, idxMap);
}
String idxName;
do {
idxName = randomName();
} while (idxMap.containsKey(idxName));
IndexStorageImpl metaStore = storeMap.get(cacheId);
if (metaStore == null) {
PageLockTrackerManager pageLockTrackerManager = mock(PageLockTrackerManager.class);
when(pageLockTrackerManager.createPageLockTracker(anyString())).thenReturn(NOOP_LSNR);
metaStore = new IndexStorageImpl(
"indexStorageTree",
mem,
null,
new AtomicLong(),
cacheId,
false,
PageIdAllocator.INDEX_PARTITION,
PageMemory.FLAG_IDX,
null,
mem.allocatePage(cacheId, PageIdAllocator.INDEX_PARTITION, PageMemory.FLAG_IDX),
true,
null,
pageLockTrackerManager
);
storeMap.put(cacheId, metaStore);
}
final RootPage rootPage = metaStore.allocateIndex(idxName);
assertTrue(rootPage.isAllocated());
idxMap.put(idxName, rootPage);
}
for (int cacheId : cacheIds) {
Map<String, RootPage> idxMap = allocatedIdxs.get(cacheId);
for (Map.Entry<String, RootPage> entry : idxMap.entrySet()) {
String idxName = entry.getKey();
FullPageId rootPageId = entry.getValue().pageId();
final RootPage rootPage = storeMap.get(cacheId).allocateIndex(idxName);
assertEquals("Invalid root page ID restored [cacheId=" + cacheId + ", idxName=" + idxName + ']',
rootPageId, rootPage.pageId());
assertFalse("Root page already allocated [cacheId=" + cacheId + ", idxName=" + idxName + ']',
rootPage.isAllocated());
}
}
}
finally {
mem.stop(true);
}
}
/**
* @return Random name.
*/
private static String randomName() {
StringBuilder sb = new StringBuilder();
Random rnd = ThreadLocalRandom.current();
int size = rnd.nextInt(25) + 1;
for (int i = 0; i < size; i++)
sb.append(ALPHABET[rnd.nextInt(ALPHABET.length)]);
return sb.toString();
}
/**
* @param clean Clean flag. If {@code true}, will clean previous memory state and allocate
* new empty page memory.
* @return Page memory instance.
*/
protected PageMemory memory(boolean clean) throws Exception {
DirectMemoryProvider provider = new MappedFileMemoryProvider(log(), allocationPath);
DataRegionConfiguration plcCfg = new DataRegionConfiguration()
.setMaxSize(30L * 1024 * 1024).setInitialSize(30L * 1024 * 1024);
return new PageMemoryNoStoreImpl(
log,
provider,
null,
PAGE_SIZE,
plcCfg,
new DataRegionMetricsImpl(plcCfg, new GridTestKernalContext(log())),
true);
}
}