Package info.archinnov.achilles.internal.statement.cache

Source Code of info.archinnov.achilles.internal.statement.cache.CacheManager

/*
* Copyright (C) 2012-2014 DuyHai DOAN
*
*  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 info.archinnov.achilles.internal.statement.cache;

import static com.google.common.collect.Collections2.transform;
import static info.archinnov.achilles.type.OptionsBuilder.noOptions;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.Session;
import com.google.common.base.Function;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheStats;
import com.google.common.collect.Sets;
import info.archinnov.achilles.internal.context.facade.PersistentStateHolder;
import info.archinnov.achilles.internal.metadata.holder.EntityMeta;
import info.archinnov.achilles.internal.metadata.holder.PropertyMeta;
import info.archinnov.achilles.internal.persistence.operations.CollectionAndMapChangeType;
import info.archinnov.achilles.internal.proxy.dirtycheck.DirtyCheckChangeSet;
import info.archinnov.achilles.internal.statement.prepared.PreparedStatementGenerator;
import info.archinnov.achilles.query.slice.SliceQueryProperties;

public class CacheManager {
    private static final Logger log = LoggerFactory.getLogger(CacheManager.class);

    private final int maxLRUCacheSize;

    public CacheManager(int maxLRUCacheSize) {
        this.maxLRUCacheSize = maxLRUCacheSize;
    }

    private PreparedStatementGenerator generator = PreparedStatementGenerator.Singleton.INSTANCE.get();

    private Function<PropertyMeta, String> propertyExtractor = new Function<PropertyMeta, String>() {
        @Override
        public String apply(PropertyMeta pm) {
            return pm.getPropertyName();
        }
    };

    public PreparedStatement getCacheForFieldSelect(Session session,Cache<StatementCacheKey, PreparedStatement> dynamicPSCache,
            PersistentStateHolder context, PropertyMeta pm) {

        log.trace("Get cache for SELECT property {} from entity class {}", pm.getPropertyName(), pm.getEntityClassName());

        Class<?> entityClass = context.getEntityClass();
        EntityMeta entityMeta = context.getEntityMeta();
        Set<String> clusteredFields = pm.forCache().extractClusteredFieldsIfNecessary();
        StatementCacheKey cacheKey = new StatementCacheKey(CacheType.SELECT_FIELD, clusteredFields, entityClass, noOptions());
        PreparedStatement ps = dynamicPSCache.getIfPresent(cacheKey);
        if (ps == null) {
            ps = generator.prepareSelectField(session, entityMeta, pm);
            dynamicPSCache.put(cacheKey, ps);
            displayCacheStatistics(dynamicPSCache);
        }
        return ps;
    }

    public PreparedStatement getCacheForEntityInsert(Session session, Cache<StatementCacheKey, PreparedStatement> dynamicPSCache,
            PersistentStateHolder context, List<PropertyMeta> pms) {

        log.trace("Get cache for INSERT properties {} from entity class {}", pms, context.getEntityClass());

        Class<?> entityClass = context.getEntityClass();
        EntityMeta entityMeta = context.getEntityMeta();
        Set<String> fields = new HashSet<>(transform(pms, propertyExtractor));
        StatementCacheKey cacheKey = new StatementCacheKey(CacheType.INSERT, fields, entityClass, context.getOptions());
        PreparedStatement ps = dynamicPSCache.getIfPresent(cacheKey);
        if (ps == null) {
            ps = generator.prepareInsert(session, entityMeta, pms, context.getOptions());
            dynamicPSCache.put(cacheKey, ps);
            displayCacheStatistics(dynamicPSCache);
        }
        return ps;
    }

    public PreparedStatement getCacheForFieldsUpdate(Session session, Cache<StatementCacheKey, PreparedStatement> dynamicPSCache,
            PersistentStateHolder context, List<PropertyMeta> pms) {

        log.trace("Get cache for UPDATE properties {} from entity class {}", pms, context.getEntityClass());

        Class<?> entityClass = context.getEntityClass();
        EntityMeta entityMeta = context.getEntityMeta();
        Set<String> fields = new HashSet<>(transform(pms, propertyExtractor));
        StatementCacheKey cacheKey = new StatementCacheKey(CacheType.UPDATE_FIELDS, fields, entityClass, context.getOptions());
        PreparedStatement ps = dynamicPSCache.getIfPresent(cacheKey);
        if (ps == null) {
            ps = generator.prepareUpdateFields(session, entityMeta, pms, context.getOptions());
            dynamicPSCache.put(cacheKey, ps);
            displayCacheStatistics(dynamicPSCache);
        }
        return ps;
    }

    public PreparedStatement getCacheForCollectionAndMapOperation(Session session, Cache<StatementCacheKey,
            PreparedStatement> dynamicPSCache, PersistentStateHolder context, PropertyMeta pm, DirtyCheckChangeSet changeSet) {
        final Class<Object> entityClass = context.getEntityClass();
        CollectionAndMapChangeType changeType = changeSet.getChangeType();
        log.trace("Get cache for operation {} on entity class {} and property {}", changeType.name(),
                entityClass, pm.getPropertyName());

        StatementCacheKey cacheKey = new StatementCacheKey(changeType.cacheType(), Sets.newHashSet(pm.getPropertyName()), entityClass, context.getOptions());

        PreparedStatement ps = dynamicPSCache.getIfPresent(cacheKey);
        if (ps == null) {
            ps = generator.prepareCollectionAndMapUpdate(session, context.getEntityMeta(), changeSet, context.getOptions());
            dynamicPSCache.put(cacheKey, ps);
            displayCacheStatistics(dynamicPSCache);
        }
        return ps;
    }

    public PreparedStatement getCacheForSliceSelectAndIterator(Session session, Cache<StatementCacheKey,PreparedStatement> dynamicPSCache,
            SliceQueryProperties sliceQueryProperties) {

        StatementCacheKey cacheKey = new StatementCacheKey(CacheType.SLICE_QUERY_SELECT, sliceQueryProperties);
        PreparedStatement ps = dynamicPSCache.getIfPresent(cacheKey);
        if (ps == null) {
            ps = generator.prepareSelectSliceQuery(session, sliceQueryProperties);
            dynamicPSCache.put(cacheKey, ps);
            displayCacheStatistics(dynamicPSCache);
        }
        return ps;
    }

    public PreparedStatement getCacheForSliceDelete(Session session, Cache<StatementCacheKey,PreparedStatement> dynamicPSCache,
            SliceQueryProperties sliceQueryProperties) {
        StatementCacheKey cacheKey = new StatementCacheKey(CacheType.SLICE_QUERY_DELETE, sliceQueryProperties);
        PreparedStatement ps = dynamicPSCache.getIfPresent(cacheKey);
        if (ps == null) {
            ps = generator.prepareDeleteSliceQuery(session, sliceQueryProperties);
            dynamicPSCache.put(cacheKey, ps);
            displayCacheStatistics(dynamicPSCache);
        }
        return ps;
    }

    private void displayCacheStatistics(Cache<StatementCacheKey, PreparedStatement> dynamicPSCache) {

        long cacheSize = dynamicPSCache.size();
        CacheStats cacheStats = dynamicPSCache.stats();

        log.info("Total LRU cache size {}", cacheSize);
        if (cacheSize > (maxLRUCacheSize * 0.8)) {
            log.warn("Warning, the LRU prepared statements cache is over 80% full");
        }

        if (log.isDebugEnabled()) {
            log.debug("Cache statistics :");
            log.debug("\t\t- hits count : {}", cacheStats.hitCount());
            log.debug("\t\t- hits rate : {}", cacheStats.hitRate());
            log.debug("\t\t- miss count : {}", cacheStats.missCount());
            log.debug("\t\t- miss rate : {}", cacheStats.missRate());
            log.debug("\t\t- eviction count : {}", cacheStats.evictionCount());
            log.debug("\t\t- load count : {}", cacheStats.loadCount());
            log.debug("\t\t- load success count : {}", cacheStats.loadSuccessCount());
            log.debug("\t\t- load exception count : {}", cacheStats.loadExceptionCount());
            log.debug("\t\t- total load time : {}", cacheStats.totalLoadTime());
            log.debug("\t\t- average load penalty : {}", cacheStats.averageLoadPenalty());
            log.debug("");
            log.debug("");
        }
    }
}
TOP

Related Classes of info.archinnov.achilles.internal.statement.cache.CacheManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.