/*
* Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved.
*
* 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 com.hazelcast.cache;
import com.hazelcast.cache.impl.HazelcastServerCachingProvider;
import com.hazelcast.config.CacheConfig;
import com.hazelcast.test.HazelcastParallelClassRunner;
import com.hazelcast.test.HazelcastTestSupport;
import com.hazelcast.test.TestHazelcastInstanceFactory;
import com.hazelcast.test.annotation.ParallelTest;
import com.hazelcast.test.annotation.QuickTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import javax.cache.Cache;
import javax.cache.CacheManager;
import javax.cache.configuration.CompleteConfiguration;
import javax.cache.configuration.Factory;
import javax.cache.configuration.FactoryBuilder;
import javax.cache.configuration.MutableCacheEntryListenerConfiguration;
import javax.cache.event.CacheEntryCreatedListener;
import javax.cache.event.CacheEntryListenerException;
import javax.cache.integration.CacheLoader;
import javax.cache.integration.CacheLoaderException;
import javax.cache.integration.CacheWriter;
import javax.cache.integration.CacheWriterException;
import javax.cache.spi.CachingProvider;
import java.io.Closeable;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.locks.LockSupport;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@RunWith(HazelcastParallelClassRunner.class)
@Category({QuickTest.class, ParallelTest.class})
public class CacheResourceTest
extends HazelcastTestSupport {
private TestHazelcastInstanceFactory factory;
@Before
public void init() {
factory = new TestHazelcastInstanceFactory(2);
}
@After
public void tear() {
factory.shutdownAll();
}
@Test
public void testCloseableCacheLoader() throws InterruptedException {
CachingProvider provider =
HazelcastServerCachingProvider.createCachingProvider(factory.newHazelcastInstance());
CacheManager cacheManager = provider.getCacheManager();
CloseableCacheLoader loader = new CloseableCacheLoader();
Factory<CloseableCacheLoader> loaderFactory = FactoryBuilder.factoryOf(loader);
CompleteConfiguration<Object, Object> configuration =
new CacheConfig()
.setCacheLoaderFactory(loaderFactory)
.setReadThrough(true);
Cache<Object, Object> cache = cacheManager.createCache("test", configuration);
// trigger partition assignment
cache.get("key");
factory.newHazelcastInstance();
for (int i = 0; i < 1000; i++) {
cache.get(i);
LockSupport.parkNanos(1000);
}
assertFalse("CacheLoader should not be closed!", loader.closed);
}
private static class CloseableCacheLoader implements CacheLoader, Closeable, Serializable {
private volatile boolean closed = false;
@Override
public Object load(Object key) throws CacheLoaderException {
if (closed) {
throw new IllegalStateException();
}
return null;
}
@Override
public Map loadAll(Iterable keys) throws CacheLoaderException {
if (closed) {
throw new IllegalStateException();
}
return null;
}
@Override
public void close() throws IOException {
closed = true;
}
}
@Test
public void testCloseableCacheWriter() throws InterruptedException {
CachingProvider provider =
HazelcastServerCachingProvider.createCachingProvider(factory.newHazelcastInstance());
CacheManager cacheManager = provider.getCacheManager();
CloseableCacheWriter writer = new CloseableCacheWriter();
Factory<CloseableCacheWriter> writerFactory = FactoryBuilder.factoryOf(writer);
CompleteConfiguration<Object, Object> configuration =
new CacheConfig()
.setCacheWriterFactory(writerFactory)
.setWriteThrough(true);
Cache<Object, Object> cache = cacheManager.createCache("test", configuration);
// trigger partition assignment
cache.get("key");
factory.newHazelcastInstance();
for (int i = 0; i < 1000; i++) {
cache.put(i, i);
LockSupport.parkNanos(1000);
}
assertFalse("CacheWriter should not be closed!", writer.closed);
}
private static class CloseableCacheWriter implements CacheWriter, Closeable, Serializable {
private volatile boolean closed = false;
@Override
public void write(Cache.Entry entry) throws CacheWriterException {
if (closed) {
throw new IllegalStateException();
}
}
@Override
public void delete(Object key) throws CacheWriterException {
if (closed) {
throw new IllegalStateException();
}
}
@Override
public void deleteAll(Collection keys) throws CacheWriterException {
if (closed) {
throw new IllegalStateException();
}
}
@Override
public void writeAll(Collection collection) throws CacheWriterException {
if (closed) {
throw new IllegalStateException();
}
}
@Override
public void close() throws IOException {
closed = true;
}
}
@Test
public void testCloseableCacheListener() {
CachingProvider provider =
HazelcastServerCachingProvider
.createCachingProvider(factory.newHazelcastInstance());
CacheManager cacheManager = provider.getCacheManager();
CloseableListener listener = new CloseableListener();
Factory<CloseableListener> listenerFactory = FactoryBuilder.factoryOf(listener);
CompleteConfiguration<Object, Object> configuration =
new CacheConfig()
.addCacheEntryListenerConfiguration(
new MutableCacheEntryListenerConfiguration(listenerFactory, null, true, false));
Cache<Object, Object> cache = cacheManager.createCache("test", configuration);
cache.close();
assertTrue("CloseableListener.close() should be called when cache is closed!", listener.closed);
}
private static class CloseableListener implements CacheEntryCreatedListener, Closeable, Serializable {
private volatile boolean closed = false;
@Override
public void onCreated(Iterable iterable) throws CacheEntryListenerException {
if (closed) {
throw new IllegalStateException();
}
}
@Override
public void close() throws IOException {
closed = true;
}
}
}