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

com.turbospaces.ebean.AbstractEbeanCache Maven / Gradle / Ivy

There is a newer version: 2.0.33
Show newest version
package com.turbospaces.ebean;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Objects;

import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;

import com.turbospaces.cache.BlockhoundCacheWrapper;
import com.turbospaces.cfg.ApplicationProperties;
import com.turbospaces.common.PlatformUtil;

import io.ebean.cache.ServerCacheConfig;
import io.ebean.cache.ServerCacheStatistics;
import io.ebean.cache.ServerCacheType;
import io.ebean.cache.TenantAwareKey;
import io.ebean.config.CurrentTenantProvider;
import io.ebeaninternal.server.cache.CachedBeanData;
import io.ebeaninternal.server.cache.CachedManyIds;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class AbstractEbeanCache implements LocalCache {
    private final ApplicationProperties props;
    private final String cacheKey;
    private final BlockhoundCacheWrapper cache;
    private final TenantAwareKey tenantAwareKey;
    private final ServerCacheConfig config;

    protected AbstractEbeanCache(
            ApplicationProperties props,
            String cacheKey,
            BlockhoundCacheWrapper cache,
            CurrentTenantProvider tenantProvider,
            ServerCacheConfig config) {
        this.props = Objects.requireNonNull(props);
        this.cacheKey = Objects.requireNonNull(cacheKey);
        this.cache = Objects.requireNonNull(cache);
        this.tenantAwareKey = new TenantAwareKey(tenantProvider);
        this.config = Objects.requireNonNull(config);
    }
    @Override
    public Object get(Object id) {
        String key = key(id);
        return cache.getIfPresent(key);
    }
    @Override
    public void put(Object id, Object obj) {
        String key = key(id);
        cache.put(key, obj);
    }
    @Override
    public void remove(Object id) {
        String key = key(id);
        cache.invalidate(key);
    }
    @Override
    public void clear() {
        cache.invalidateAll();
    }
    @Override
    public int size() {
        return (int) cache.size();
    }
    @Override
    public void cleanUp() {
        cache.cleanUp();
    }
    @Override
    public int hitRatio() {
        return (int) (cache.stats().hitRate() * 100);
    }
    @Override
    public ServerCacheStatistics statistics(boolean reset) {
        return LocalCache.stats(cacheKey, cache);
    }
    @Override
    public ServerCacheType type() {
        return config.getType();
    }
    @Override
    public String cacheKey() {
        return cacheKey;
    }
    @Override
    public String toString() {
        return cacheKey();
    }
    @Override
    public int hashCode() {
        return Objects.hash(cacheKey());
    }
    @Override
    public boolean equals(Object obj) {
        return Objects.equals(cacheKey, ((AbstractEbeanCache) obj).cacheKey());
    }
    @Override
    public void onRemove(byte[] data) {
        String key = SerializationUtils.deserialize(data);
        log.trace("onRemove {} by key: {}", cacheKey, key);
        cache.invalidate(key);
    }
    @Override
    public int onClear() {
        String idx = props.CLOUD_APP_INSTANCE_INDEX.get();
        int size = size();
        log.debug("onClear {} items: {} on ({})", cacheKey, size, idx);
        cache.invalidateAll();
        return size;
    }
    protected void onPut(byte[] keyData, byte[] valueData) throws IOException {
        //
        // ~ fast and reusable input stream
        //
        UnsynchronizedByteArrayInputStream kstream = UnsynchronizedByteArrayInputStream.builder().setByteArray(keyData).get();
        UnsynchronizedByteArrayInputStream vstream = UnsynchronizedByteArrayInputStream.builder().setByteArray(valueData).get();

        String key = PlatformUtil.deserialize(kstream);

        switch (type()) {
            case NATURAL_KEY: {
                Object read = PlatformUtil.deserialize(vstream);
                cache.put(key, read);
                break;
            }
            case BEAN: {
                try (ObjectInputStream ois = new ObjectInputStream(vstream)) {
                    CachedBeanData read = new CachedBeanData();
                    read.readExternal(ois);

                    //
                    // ~ hack under strict concurrency (do not override the data which can be stale on other nodes)
                    // ~ we will push the data back shortly
                    //
                    boolean toPut = true;
                    CachedBeanData current = (CachedBeanData) cache.getIfPresent(key);
                    if (Objects.nonNull(current)) {
                        toPut = read.getVersion() > current.getVersion(); // ~ READ committed
                    }

                    if (toPut) {
                        log.trace("onPut {} by key: {} bean value: {}", cacheKey, key, read);
                        cache.put(key, read);
                    }
                } catch (ClassNotFoundException | IOException err) {
                    ExceptionUtils.wrapAndThrow(err);
                }
                break;
            }
            case COLLECTION_IDS: {
                try (ObjectInputStream ois = new ObjectInputStream(vstream)) {
                    CachedManyIds read = new CachedManyIds();
                    read.readExternal(ois);

                    log.trace("onPut {} by key: {} ids value: {}", cacheKey, key, read);
                    cache.put(key, read);
                } catch (ClassNotFoundException | IOException err) {
                    ExceptionUtils.wrapAndThrow(err);
                }
                break;
            }
            default: {
                throw new IllegalArgumentException("unexpected cache type: " + type());
            }
        }
    }
    protected String key(Object key) {
        return tenantAwareKey.key(key).toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy