/*
* 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.map.impl.mapstore;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.MapLoaderLifecycleSupport;
import com.hazelcast.core.MapStore;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
class EventBasedMapStore<K, V> implements MapLoaderLifecycleSupport, MapStore<K, V> {
enum STORE_EVENTS {
STORE, STORE_ALL, DELETE, DELETE_ALL, LOAD, LOAD_ALL, LOAD_ALL_KEYS
}
protected final Map<K, V> store = new ConcurrentHashMap<K, V>();
protected final BlockingQueue<STORE_EVENTS> events = new LinkedBlockingQueue<STORE_EVENTS>();
protected final AtomicInteger storeCount = new AtomicInteger();
protected final AtomicInteger storeAllCount = new AtomicInteger();
protected final AtomicInteger loadCount = new AtomicInteger();
protected final AtomicInteger callCount = new AtomicInteger();
protected final AtomicInteger initCount = new AtomicInteger();
protected HazelcastInstance hazelcastInstance;
protected Properties properties;
protected String mapName;
protected boolean loadAllKeys = true;
protected CountDownLatch storeLatch;
protected CountDownLatch deleteLatch;
protected CountDownLatch loadAllLatch;
public void init(HazelcastInstance hazelcastInstance, Properties properties, String mapName) {
this.hazelcastInstance = hazelcastInstance;
this.properties = properties;
this.mapName = mapName;
initCount.incrementAndGet();
}
public BlockingQueue getEvents() {
return events;
}
public void destroy() {
}
public int getEventCount() {
return events.size();
}
public int getInitCount() {
return initCount.get();
}
public boolean isLoadAllKeys() {
return loadAllKeys;
}
public void setLoadAllKeys(boolean loadAllKeys) {
this.loadAllKeys = loadAllKeys;
}
public HazelcastInstance getHazelcastInstance() {
return hazelcastInstance;
}
public String getMapName() {
return mapName;
}
public Properties getProperties() {
return properties;
}
Map<K, V> getStore() {
return store;
}
public EventBasedMapStore<K, V> insert(K key, V value) {
store.put(key, value);
return this;
}
public void store(K key, V value) {
store.put(key, value);
callCount.incrementAndGet();
storeCount.incrementAndGet();
if (storeLatch != null) {
storeLatch.countDown();
}
events.offer(STORE_EVENTS.STORE);
}
public V load(K key) {
callCount.incrementAndGet();
loadCount.incrementAndGet();
events.offer(STORE_EVENTS.LOAD);
return store.get(key);
}
public void storeAll(Map<K, V> map) {
store.putAll(map);
callCount.incrementAndGet();
storeAllCount.incrementAndGet();
final int size = map.size();
if (storeLatch != null) {
for (int i = 0; i < size; i++) {
storeLatch.countDown();
}
}
events.offer(STORE_EVENTS.STORE_ALL);
}
public void delete(K key) {
store.remove(key);
callCount.incrementAndGet();
if (deleteLatch != null) {
deleteLatch.countDown();
}
events.offer(STORE_EVENTS.DELETE);
}
public Set<K> loadAllKeys() {
if (loadAllLatch != null) {
loadAllLatch.countDown();
}
callCount.incrementAndGet();
events.offer(STORE_EVENTS.LOAD_ALL_KEYS);
if (!loadAllKeys) {
return null;
}
return store.keySet();
}
public Map<K, V> loadAll(Collection<K> keys) {
Map<K, V> map = new HashMap<K, V>(keys.size());
for (K key : keys) {
V value = store.get(key);
if (value != null) {
map.put(key, value);
}
}
callCount.incrementAndGet();
events.offer(STORE_EVENTS.LOAD_ALL);
return map;
}
public void deleteAll(Collection<K> keys) {
for (K key : keys) {
store.remove(key);
}
callCount.incrementAndGet();
if (deleteLatch != null) {
for (int i = 0; i < keys.size(); i++) {
deleteLatch.countDown();
}
}
events.offer(STORE_EVENTS.DELETE_ALL);
}
}