Package com.hazelcast.hibernate.distributed

Source Code of com.hazelcast.hibernate.distributed.IMapRegionCache

/*
* Copyright (c) 2008-2013, 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.hibernate.distributed;

import com.hazelcast.core.EntryView;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IMap;
import com.hazelcast.hibernate.CacheEnvironment;
import com.hazelcast.hibernate.HazelcastTimestamper;
import com.hazelcast.hibernate.RegionCache;
import com.hazelcast.logging.ILogger;
import com.hazelcast.logging.Logger;
import org.hibernate.cache.spi.CacheDataDescription;
import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.cache.spi.entry.CacheEntry;

import java.util.Comparator;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

/**
* A {@link RegionCache} implementation based on the underlying IMap
*/
public class IMapRegionCache implements RegionCache {

    private static final long COMPARISON_VALUE = 500;

    private static final SoftLock LOCK_SUCCESS = new SoftLock() {
    };

    private static final SoftLock LOCK_FAILURE = new SoftLock() {
    };

    private final String name;
    private final HazelcastInstance hazelcastInstance;
    private final IMap<Object, Object> map;
    private final Comparator versionComparator;
    private final int lockTimeout;
    private final long tryLockAndGetTimeout;
    private final boolean explicitVersionCheckEnabled;
    private final ILogger logger;

    public IMapRegionCache(final String name, final HazelcastInstance hazelcastInstance,
                           final Properties props, final CacheDataDescription metadata) {
        this.name = name;
        this.hazelcastInstance = hazelcastInstance;
        this.versionComparator = metadata != null && metadata.isVersioned() ? metadata.getVersionComparator() : null;
        this.map = hazelcastInstance.getMap(this.name);
        lockTimeout = CacheEnvironment.getLockTimeoutInMillis(props);
        final long maxOperationTimeout = HazelcastTimestamper.getMaxOperationTimeout(hazelcastInstance);
        tryLockAndGetTimeout = Math.min(maxOperationTimeout, COMPARISON_VALUE);
        explicitVersionCheckEnabled = CacheEnvironment.isExplicitVersionCheckEnabled(props);
        logger = createLogger(name, hazelcastInstance);
    }

    public Object get(final Object key) {
        return map.get(key);
    }

    public boolean put(final Object key, final Object value, final Object currentVersion) {
        return update(key, value, currentVersion, null, null);
    }

    public boolean update(final Object key, final Object value, final Object currentVersion,
                          final Object previousVersion, final SoftLock lock) {
        if (lock == LOCK_FAILURE) {
            logger.warning("Cache lock could not be acquired!");
            return false;
        }
        if (versionComparator != null && currentVersion != null) {
            if (explicitVersionCheckEnabled && value instanceof CacheEntry) {
                return compareVersion(key, value);
            } else if (previousVersion == null || versionComparator.compare(currentVersion, previousVersion) > 0) {
                map.set(key, value);
                return true;
            }
            return false;
        } else {
            map.set(key, value);
            return true;
        }
    }

    public boolean remove(final Object key) {
        return map.remove(key) != null;
    }

    public SoftLock tryLock(final Object key, final Object version) {
        try {
            return map.tryLock(key, lockTimeout, TimeUnit.MILLISECONDS) ? LOCK_SUCCESS : LOCK_FAILURE;
        } catch (InterruptedException e) {
            return LOCK_FAILURE;
        }
    }

    public void unlock(final Object key, SoftLock lock) {
        if (lock == LOCK_SUCCESS) {
            map.unlock(key);
        }
    }

    public boolean contains(final Object key) {
        return map.containsKey(key);
    }

    public void clear() {
        map.evictAll();
    }

    public long size() {
        return map.size();
    }

    public long getSizeInMemory() {
        long size = 0;
        for (final Object key : map.keySet()) {
            final EntryView entry = map.getEntryView(key);
            if (entry != null) {
                size += entry.getCost();
            }
        }
        return size;
    }

    public Map asMap() {
        return map;
    }

    private ILogger createLogger(final String name, final HazelcastInstance hazelcastInstance) {
        try {
            return hazelcastInstance.getLoggingService().getLogger(name);
        } catch (UnsupportedOperationException e) {
            return Logger.getLogger(name);
        }
    }

    private boolean compareVersion(Object key, Object value) {
        final CacheEntry currentEntry = (CacheEntry) value;
        try {
            return compareVersionUnderRowLock(key, value, currentEntry);
        } catch (InterruptedException e) {
            return false;
        }
    }

    private boolean compareVersionUnderRowLock(Object key, Object value, CacheEntry currentEntry) throws InterruptedException {
        if (map.tryLock(key, tryLockAndGetTimeout, TimeUnit.MILLISECONDS)) {
            try {
                final CacheEntry previousEntry = (CacheEntry) map.get(key);
                if (previousEntry == null
                        || versionComparator.compare(currentEntry.getVersion(), previousEntry.getVersion()) > 0) {
                    map.set(key, value);
                    return true;
                } else {
                    return false;
                }
            } finally {
                map.unlock(key);
            }
        } else {
            return false;
        }
    }
}
TOP

Related Classes of com.hazelcast.hibernate.distributed.IMapRegionCache

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.