All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.maxifier.mxcache.impl.StorageBasedCacheManager Maven / Gradle / Ivy

Go to download

Constains all classes necessary for launching a MxCache-instrumentated application

There is a newer version: 2.6.9
Show newest version
/*
 * Copyright (c) 2008-2014 Maxifier Ltd. All Rights Reserved.
 */
package com.maxifier.mxcache.impl;

import com.maxifier.mxcache.StatisticsModeEnum;
import com.maxifier.mxcache.caches.*;
import com.maxifier.mxcache.context.CacheContext;
import com.maxifier.mxcache.impl.caches.def.*;
import com.maxifier.mxcache.impl.resource.DependencyNode;
import com.maxifier.mxcache.impl.resource.DependencyNodeVisitor;
import com.maxifier.mxcache.interfaces.Statistics;
import com.maxifier.mxcache.interfaces.StatisticsHolder;
import com.maxifier.mxcache.provider.CacheDescriptor;
import com.maxifier.mxcache.provider.Signature;
import com.maxifier.mxcache.caches.Cache;
import com.maxifier.mxcache.impl.wrapping.WrapperFactory;
import com.maxifier.mxcache.impl.wrapping.Wrapping;
import com.maxifier.mxcache.provider.StorageFactory;
import com.maxifier.mxcache.storage.CalculableInterceptor;
import com.maxifier.mxcache.storage.Storage;
import com.maxifier.mxcache.storage.elementlocked.ElementLockedStorage;
import com.maxifier.mxcache.util.TIdentityHashSet;

import javax.annotation.Nonnull;

import java.lang.ref.Reference;

/**
 * This is a default implementation of CacheManager that handles Storage-based caches.
 *
 * @author Alexander Kochurov ([email protected])
 */
public class StorageBasedCacheManager extends AbstractCacheManager {
    public static final DependencyNode MARKER_NODE = new MarkerDependencyNode();

    private final StorageFactory storageFactory;

    private final Signature cacheSignature;

    private WrapperFactory wrapperFactoryCache;
    private boolean elementLockedCache;
    private Signature storageSignatureCache;
    private boolean inlineCache;

    public StorageBasedCacheManager(CacheContext context, CacheDescriptor descriptor, StorageFactory storageFactory) {
        super(context, descriptor);
        this.storageFactory = storageFactory;
        cacheSignature = descriptor.getSignature();
        inlineCache = canInlineCache(descriptor, storageFactory);
    }

    private boolean canInlineCache(CacheDescriptor descriptor, StorageFactory storageFactory) {
        // check class, not instanceof as child classes can override the behavior
        return storageFactory.getClass() == DefaultStorageFactory.class &&
                descriptor.getSignature().getContainer() == null &&
                !descriptor.isResourceView();
    }

    @Nonnull
    @Override
    protected Cache createCache(T owner, DependencyNode dependencyNode, MutableStatistics statistics) throws Exception {
        if (inlineCache) {
            if (dependencyNode == MARKER_NODE) {
                return createInlineCacheWithDependencyNode(owner, statistics);
            }
            Cache cache = createInlineCache(owner, statistics);
            cache.setDependencyNode(dependencyNode);
            return cache;
        }
        Storage storage = storageFactory.createStorage(owner);
        StatisticsModeEnum statisticsMode = getStatisticsMode();
        switch (statisticsMode) {
            case STORAGE:
                statistics = (MutableStatistics)((StatisticsHolder)storage).getStatistics();
                break;
            case STATIC_OR_STORAGE:
                if (storage instanceof StatisticsHolder) {
                    Statistics storageStatistics = ((StatisticsHolder) storage).getStatistics();
                    if (storageStatistics instanceof MutableStatistics) {
                        statistics = (MutableStatistics) storageStatistics;
                    }
                }
                break;
        }
        Calculable calculable = getDescriptor().getCalculable();
        if (storage instanceof CalculableInterceptor) {
            calculable = ((CalculableInterceptor)storage).createInterceptedCalculable(calculable);
        }
        Cache cache = getWrapperFactory(storage instanceof ElementLockedStorage, Signature.ofStorage(storage.getClass()))
                .wrap(owner, calculable, storage, statistics);
        cache.setDependencyNode(dependencyNode);
        return cache;
    }

    @Override
    protected DependencyNode createInstanceNode() {
        if (inlineCache) {
            return MARKER_NODE;
        }
        return super.createInstanceNode();
    }

    private Cache createInlineCache(T owner, MutableStatistics statistics) {
        assert inlineCache;
        CacheDescriptor descriptor = getDescriptor();
        Class valueType = descriptor.getSignature().getValue();
        Calculable calculable = descriptor.getCalculable();
        if (valueType == boolean.class) {
            return new BooleanInlineCacheImpl(owner, (BooleanCalculatable) calculable, statistics);
        }
        if (valueType == byte.class) {
            return new ByteInlineCacheImpl(owner, (ByteCalculatable) calculable, statistics);
        }
        if (valueType == short.class) {
            return new ShortInlineCacheImpl(owner, (ShortCalculatable) calculable, statistics);
        }
        if (valueType == char.class) {
            return new CharacterInlineCacheImpl(owner, (CharacterCalculatable) calculable, statistics);
        }
        if (valueType == int.class) {
            return new IntInlineCacheImpl(owner, (IntCalculatable) calculable, statistics);
        }
        if (valueType == long.class) {
            return new LongInlineCacheImpl(owner, (LongCalculatable) calculable, statistics);
        }
        if (valueType == float.class) {
            return new FloatInlineCacheImpl(owner, (FloatCalculatable) calculable, statistics);
        }
        if (valueType == double.class) {
            return new DoubleInlineCacheImpl(owner, (DoubleCalculatable) calculable, statistics);
        }
        //noinspection unchecked
        return new ObjectInlineCacheImpl(owner, (ObjectCalculatable) calculable, statistics);
    }

    private Cache createInlineCacheWithDependencyNode(T owner, MutableStatistics statistics) {
        assert inlineCache;
        CacheDescriptor descriptor = getDescriptor();
        Class valueType = descriptor.getSignature().getValue();
        Calculable calculable = descriptor.getCalculable();
        if (valueType == boolean.class) {
            return new BooleanInlineDependencyCache(owner, (BooleanCalculatable) calculable, statistics);
        }
        if (valueType == byte.class) {
            return new ByteInlineDependencyCache(owner, (ByteCalculatable) calculable, statistics);
        }
        if (valueType == short.class) {
            return new ShortInlineDependencyCache(owner, (ShortCalculatable) calculable, statistics);
        }
        if (valueType == char.class) {
            return new CharacterInlineDependencyCache(owner, (CharacterCalculatable) calculable, statistics);
        }
        if (valueType == int.class) {
            return new IntInlineDependencyCache(owner, (IntCalculatable) calculable, statistics);
        }
        if (valueType == long.class) {
            return new LongInlineDependencyCache(owner, (LongCalculatable) calculable, statistics);
        }
        if (valueType == float.class) {
            return new FloatInlineDependencyCache(owner, (FloatCalculatable) calculable, statistics);
        }
        if (valueType == double.class) {
            return new DoubleInlineDependencyCache(owner, (DoubleCalculatable) calculable, statistics);
        }
        //noinspection unchecked
        return new ObjectInlineDependencyCache(owner, (ObjectCalculatable) calculable, statistics);
    }


    private synchronized WrapperFactory getWrapperFactory(boolean elementLocked, Signature storageSignature) {
        if (wrapperFactoryCache == null || !storageSignature.equals(storageSignatureCache) || elementLocked != elementLockedCache) {
            wrapperFactoryCache = Wrapping.getFactory(storageSignature, cacheSignature, getDescriptor().getKeyTransform(), getDescriptor().getValueTransform(), elementLocked);
            storageSignatureCache = storageSignature;
            elementLockedCache = elementLocked;
        }
        return wrapperFactoryCache;
    }

    @Override
    public String getImplementationDetails() {
        return storageFactory.getImplementationDetails();
    }

    private static class MarkerDependencyNode implements DependencyNode {
        @Override
        public Reference getSelfReference() {
            throw new UnsupportedOperationException();
        }

        @Override
        public void visitDependantNodes(DependencyNodeVisitor visitor) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void appendNodes(TIdentityHashSet elements) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void trackDependency(DependencyNode node) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void addNode(@Nonnull CleaningNode cache) {
            // do nothing: cache itself is DependencyNode
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy