/*
* Copyright 2015 Terracotta, Inc., a Software AG company.
*
* Licensed 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.terracotta.offheapstore;
import org.terracotta.offheapstore.concurrent.ConcurrentOffHeapClockCache;
import org.terracotta.offheapstore.exceptions.OversizeMappingException;
import org.terracotta.offheapstore.paging.PageSource;
import org.terracotta.offheapstore.storage.StorageEngine;
import org.terracotta.offheapstore.storage.portability.ByteArrayPortability;
import org.terracotta.offheapstore.storage.portability.SerializablePortability;
import org.terracotta.offheapstore.storage.portability.StringPortability;
import org.terracotta.offheapstore.util.Factory;
import org.terracotta.offheapstore.util.OffHeapAndDiskStorageEngineDependentTest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.junit.Test;
import static org.terracotta.offheapstore.util.MemoryUnit.KILOBYTES;
import static org.terracotta.offheapstore.util.MemoryUnit.MEGABYTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.fail;
import org.terracotta.offheapstore.buffersource.OffHeapBufferSource;
import org.terracotta.offheapstore.paging.UnlimitedPageSource;
public class CacheGrowthRaceIT extends OffHeapAndDiskStorageEngineDependentTest {
public CacheGrowthRaceIT(TestMode mode) {
super(mode);
}
@Test
public void testCrossSegmentGrowthCompetition() throws Exception {
final int TASK_COUNT = 8;
PageSource source = createPageSource(1, MEGABYTES);
Factory<? extends StorageEngine<Integer, byte[]>> factory = createFactory(source, new SerializablePortability(), ByteArrayPortability.INSTANCE);
final Map<Integer, byte[]> cache = new ConcurrentOffHeapClockCache<Integer, byte[]>(new UnlimitedPageSource(new OffHeapBufferSource()), factory);
final byte[] large = new byte[KILOBYTES.toBytes(768)];
ExecutorService executor = Executors.newCachedThreadPool();
Collection<Callable<Void>> tasks = new ArrayList<Callable<Void>>();
for (int i = 0; i < TASK_COUNT; i++) {
final int index = i;
tasks.add(new Callable<Void>() {
@Override
public Void call() throws Exception {
cache.put(index, large);
return null;
}});
}
for (Future<?> result : executor.invokeAll(tasks, 100000, SECONDS)) {
result.get();
}
}
@Test
public void testExpectedFailureCrossSegmentGrowthCompetition() throws Exception {
final int TASK_COUNT = 8;
PageSource source = createPageSource(1, MEGABYTES);
Factory<? extends StorageEngine<String, byte[]>> factory = createFactory(source, StringPortability.INSTANCE, ByteArrayPortability.INSTANCE);
final Map<String, byte[]> cache = new ConcurrentOffHeapClockCache<String, byte[]>(source, factory);
final byte[] large = new byte[MEGABYTES.toBytes(2)];
ExecutorService executor = Executors.newCachedThreadPool();
Collection<Callable<Void>> tasks = new ArrayList<Callable<Void>>();
for (int i = 0; i < TASK_COUNT; i++) {
final int index = i;
tasks.add(new Callable<Void>() {
@Override
public Void call() throws Exception {
try {
cache.put(Integer.toString(index), large);
fail();
} catch (OversizeMappingException e) {
//expected
}
return null;
}});
}
for (Future<?> result : executor.invokeAll(tasks, 100000, SECONDS)) {
result.get();
}
}
}