Package org.apache.olio.webapp.cache

Source Code of org.apache.olio.webapp.cache.MemCachedFactory$MemCache

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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 org.apache.olio.webapp.cache;

import com.danga.MemCached.Logger;
import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;
import java.util.Date;

/**
* The MemCachedFactory uses Memcached as the object cache in the back.
*/
public class MemCachedFactory extends CacheFactory {

    // Danga's implementation of the client is thread safe and designed
    // for single instance use. So we won't waste instances. Keep it static.
    private static MemCachedClient cache = null;

    public MemCachedFactory() {
        if (cache == null) {
            // the env memcachedInstances is in the
            // form host1:port1, host2:port2, etc.
            String servers = locator.getString("memcachedInstances");
            String[] serverList = servers.split(",?[ *]");
            //SockIOPool pool = SockIOPool.getInstance("livePool");
            SockIOPool pool = SockIOPool.getInstance();
           
            // Set equal weight for all servers
            if (serverList.length > 1) {
                Integer[] wts = new Integer[serverList.length];
                for (int i=0; i<wts.length; i++)
                    wts[i] = Integer.valueOf(1);
                pool.setWeights(wts);
            }
            pool.setServers(serverList);
           
            // The following options have been set based on the Whalin doc
            pool.setInitConn( 8 );
            pool.setMinConn( 8 );
            pool.setMaxConn( 128 );
            pool.setMaxIdle( 1000 * 60 * 60 * 6 );

            // set some TCP settings
            // disable nagle
            // set the read timeout to 3 secs
            // and don't set a connect timeout
            pool.setNagle( false );
            pool.setSocketTO( 3000 );
            pool.setSocketConnectTO( 0 );

            pool.initialize();

            cache = new MemCachedClient();
            MemCachedClient.getLogger().setLevel(Logger.LEVEL_WARN);
           
            // Set thelog level to WARNING -- The defautl is INFO which causes unecessary logging
           

            //Logger log = cache.getLogger();
           
            //log.setLevel(Logger.LEVEL_WARN);
           
            // lets set some compression on for the client
        // compress anything larger than 1MB
            cache.setCompressEnable( true );
            cache.setCompressThreshold( 1024 * 1024 );
           
        }
    }
   
    /**
     * Obtains the cache instance.
     *
     * @return The cache instance
     * @param type
     */
    public Cache createCache(String type) {
        return new MemCache(type);
    }

    static class MemCache implements Cache {

        private String prefix;

        private MemCache(String type) {
            prefix = type + ':';
        }

        /**
         * Gets the cached value based on a key.
         *
         * @param key The key
         * @return The cached object, or null if none is available
         */
        public Object get(String key) {
            Object value = cache.get(prefix + key);
            if (value != null)
                logHit(prefix, key);
            return value;
        }

        /**
         * Sets a cached item using a key.
         *
         * @param key   The key
         * @param value The object to cache.
         */
        public void put(String key, Object value) {
            if (!cache.set(prefix + key, value))
                throw new CacheException("Error putting object key=" + prefix +
                                        key + ", value=" + value + " to cache");
        }
       
        /** Sets a cached item using a key and specifies a timeout
         *
         * @param key The key
         * @param value The object to cache
         * @param timeToLive The time to live for this object in seconds
         */
        public void put (String key, Object value, long timeToLive) {
            Date expiry = new Date (System.currentTimeMillis() + timeToLive * 1000);

            if (!cache.set(prefix + key, value, expiry))
                throw new CacheException("Error putting object key=" + prefix +
                                        key + ", value=" + value + " to cache");
        }

        /** Invalidates a cached item using a key
         *
         * @param key The key
         * @return success
         */
        public boolean invalidate(String key) {
            // Only remove the Semaphore
            return cache.delete(prefix + key + ".UpdateSema");
        }

        /*
         * Check if cache needs refresh based on existence cached object and of Semaphore
         * @param key The key
         * @param cacheObjPresent false if the cache object for this key exists
         * @return true if the object needs a refresh and if we have the lock
         */
        public boolean needsRefresh(boolean cacheObjPresent, String key) {
            // Was a double checked lock. First set the lock, then check  we own the lock
            // Now using memcached's add which is an atomic get/set
            // If updateSema is not null, then we don't need to update the cache.
            // updateSema is stored with a timeout, so it will expire based on
            // cache expiry time
            String updateSema = prefix + key + ".UpdateSema";
            String updateLock = prefix + key + ".UpdateLock";
            if (!cacheObjPresent || cache.get(updateSema) == null) {
               // the lockId is based on the threadId
               String lockId = CacheFactory.getInstance().getLockId();

               Date expiryTime = new Date (System.currentTimeMillis()
                   + CacheFactory.getInstance().getCacheLockExpireInSeconds()*1000);

               // Memcached's add is an atomic get/set and can be used for locking
               if (!cache.add(updateLock, lockId, expiryTime)) {
                   // someone else has the lock, hopefully they are doing
                   // what we are trying to do
                   return false;
               }
               else
                   // we got the lock
                   return true;
            }
            // no refresh required
            return false;
        }

        /** Resets  the cache lock
         *
         * @param key The key
         * @param timeToNextRefresh The time to live for this object in seconds
         */
        public void doneRefresh(String key, long timeToNextRefresh) throws CacheException {
            String updateSema = prefix + key + ".UpdateSema";
            String updateLock = prefix + key + ".UpdateLock";
            String lockId = CacheFactory.getInstance().getLockId();
           
            if (!cache.get(updateLock).equals(lockId)) {
                throw new CacheException ("UpdateLock for key = " + (prefix + key) +
                        " is not locked by this process");
            }
            Date expiryTime = new Date (System.currentTimeMillis() + timeToNextRefresh * 1000);
            cache.set(updateSema, 1, expiryTime);
            cache.delete(updateLock);
        }

        public boolean isLocal() {
            return false;
        }
    }
}
TOP

Related Classes of org.apache.olio.webapp.cache.MemCachedFactory$MemCache

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.