
com.hazelcast.query.impl.getters.EvictableGetterCache Maven / Gradle / Ivy
/*
* Copyright (c) 2008-2016, 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.query.impl.getters;
import com.hazelcast.util.ConstructorFunction;
import com.hazelcast.util.SampleableConcurrentHashMap;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import static com.hazelcast.util.ConcurrencyUtil.getOrPutIfAbsent;
class EvictableGetterCache {
private final SampleableConcurrentHashMap> getterCache;
private final ConstructorFunction> getterCacheConstructor;
private final int maxClassCount;
private final int afterEvictionClassCount;
private final int maxGetterPerClassCount;
private final int afterEvictionGetterPerClassCount;
EvictableGetterCache(int maxClassCount, final int maxGetterPerClassCount, float evictPercentage) {
getterCache = new SampleableConcurrentHashMap>(maxClassCount);
getterCacheConstructor = new ConstructorFunction>() {
@Override
public SampleableConcurrentHashMap createNew(Class arg) {
return new SampleableConcurrentHashMap(maxGetterPerClassCount);
}
};
this.maxClassCount = maxClassCount;
this.afterEvictionClassCount = (int) (maxClassCount * (1 - evictPercentage));
this.maxGetterPerClassCount = maxGetterPerClassCount;
this.afterEvictionGetterPerClassCount = (int) (maxGetterPerClassCount * (1 - evictPercentage));
}
@Nullable
Getter getGetter(Class clazz, String attributeName) {
ConcurrentMap cache = getterCache.get(clazz);
if (cache == null) {
return null;
}
return cache.get(attributeName);
}
Getter putGetter(Class clazz, String attributeName, Getter getter) {
SampleableConcurrentHashMap cache = getOrPutIfAbsent(getterCache, clazz, getterCacheConstructor);
Getter foundGetter = cache.putIfAbsent(attributeName, getter);
evictOnPut(cache);
return foundGetter == null ? getter : foundGetter;
}
private void evictOnPut(SampleableConcurrentHashMap getterPerClassCache) {
evictMap(getterPerClassCache, maxGetterPerClassCount, afterEvictionGetterPerClassCount);
evictMap(getterCache, maxClassCount, afterEvictionClassCount);
}
/**
* It works on best effort basis. If multi-threaded calls involved it may evict all elements, but it's unlikely.
*/
private void evictMap(SampleableConcurrentHashMap, ?> map, int triggeringEvictionSize, int afterEvictionSize) {
int mapSize = map.size();
if (mapSize - triggeringEvictionSize >= 0) {
for (Map.Entry entry : map.getRandomSamples(mapSize - afterEvictionSize)) {
map.remove(entry.getKey());
}
}
}
int getClassCacheSize() {
return getterCache.size();
}
int getGetterPerClassCacheSize(Class clazz) {
SampleableConcurrentHashMap cacheForClass = getterCache.get(clazz);
return cacheForClass != null ? cacheForClass.size() : -1;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy