Package org.apache.stratum.jcs.auxiliary.disk.jisp

Source Code of org.apache.stratum.jcs.auxiliary.disk.jisp.JISPCache

package org.apache.stratum.jcs.auxiliary.disk.jisp;

/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Velocity", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
import com.coyotegulch.jisp.BTreeIndex;
import com.coyotegulch.jisp.IndexedObjectDatabase;
import com.coyotegulch.jisp.KeyObject;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

import org.apache.stratum.jcs.auxiliary.disk.jisp.behavior.IJISPCacheAttributes;
import org.apache.stratum.jcs.auxiliary.disk.PurgatoryElement;

import org.apache.stratum.jcs.engine.behavior.IElementAttributes;
import org.apache.stratum.jcs.engine.CacheElement;

import org.apache.stratum.jcs.engine.behavior.ICache;
import org.apache.stratum.jcs.engine.behavior.ICacheElement;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* JISP disk cache implementation. Slow as hell with this type of key.
*
* @author <a href="mailto:asmuts@yahoo.com">Aaron Smuts</a>
* @created January 15, 2002
* @version $Id: ILateralCacheTCPListener.java,v 1.2 2002/01/18 22:08:26
*/
public class JISPCache implements ICache, Serializable
{
    private final static Log log =
        LogFactory.getLog( JISPCache.class );

    private static int numCreated = 0;
    private int numInstances = 0;

    private String cacheName;

    /** Description of the Field */
    public boolean isAlive = false;

    IJISPCacheAttributes cattr;

    // disk cache buffer, need to remove key from buffer on update, if its there
    JISPCacheNoWaitBuffer buffer;

    //JISP ACCESS
    IndexedObjectDatabase database;
    BTreeIndex index1;
    private static int s_order = 101;

    String jispDataFileName = "default_this_is_BAD";
    String jispIndexFileName = "default_this_is_BAD";

    private final static JISPLockManager locker = JISPLockManager.getInstance();

    // should use this method
    /**
     * Constructor for the JISPCache object
     *
     * @param buffer
     * @param cattr
     */
    public JISPCache( JISPCacheNoWaitBuffer buffer, IJISPCacheAttributes cattr )
    {
        //this( cattr.getCacheName(), cattr.getDiskPath() );
        this( cattr );
        this.cattr = cattr;
        this.buffer = buffer;
    }

    /**
     * Constructor for the JISPCache object
     *
     * @param cattr
     */
    protected JISPCache( IJISPCacheAttributes cattr )
    {
        numInstances++;

        String rafroot = cattr.getDiskPath();

        this.cacheName = cattr.getCacheName();

        if ( rafroot == null )
        {
            log.warn( "The JISP directory was not defined in the cache.ccf " );
            rafroot = "";
        }

        jispDataFileName = rafroot + cacheName + "DATA.jisp";
        jispIndexFileName = rafroot + cacheName + "INDEX.jisp";

        log.debug( "jispDataFileName = " + jispDataFileName );

        // See if the JISP Cache has already been created.
        // build b-tree database if it doesn't already exist
        try
        {

            File finddb = new File( jispDataFileName );

            if ( !finddb.exists() || cattr.getClearOnStart() )
            {
                setupTABLE();
            }

            try
            {
                createDB( cattr.getClearOnStart() );
            }
            catch ( Exception e )
            {
                log.error( e );
                reset();
            }

            isAlive = true;

        }
        catch ( Exception e )
        {
            log.error( "QueryTool.init", e );

            reset();
        }

    }
    // end constructor

    /** SETUP TABLE FOR CACHE */
    void setupTABLE()
    {

        try
        {

            // delete old files
            File killit = new File( jispDataFileName );

            if ( killit.exists() )
            {
                killit.delete();
            }

            killit = new File( jispIndexFileName );

            if ( killit.exists() )
            {
                killit.delete();
            }
        }
        catch ( Exception e )
        {
            System.out.println( "Exception: " + e );
            log.error( e );
        }

    }
    // end setupTable

    /** Description of the Method */
    public void createDB( boolean clear )
        throws Exception
    {
        try
        {

            // create database
            // it seems to alwasy lose the data on retstart
            database = new IndexedObjectDatabase( jispDataFileName, clear );

            index1 = new BTreeIndex( jispIndexFileName, s_order, new JISPKey(), false );
            database.attachIndex( index1 );
        }
        catch ( Exception e )
        {
            System.out.println( "Exception: " + e );
            log.error( e );
            throw e;
        }
    }


    /** Description of the Method */
    public void add( Serializable key, Serializable value )
        throws IOException
    {
        put( key, value );
    }


    // ignore the multicast field.
    /** Description of the Method */
    public void put( Serializable key, Serializable value, boolean multicast )
        throws IOException
    {
        put( key, value );
    }


    /** Description of the Method */
    public void put( Serializable key, Serializable value )
        throws IOException
    {
        put( key, value, null );
    }


    /** Description of the Method */
    public void put( Serializable key, Serializable value, IElementAttributes attr )
        throws IOException
    {
        CacheElement ce = null;
        ce = new CacheElement( cacheName, key, value );
        ce.setElementAttributes( attr );
        update( ce );
    }


    /** Description of the Method */
    public void update( ICacheElement ce )
        throws IOException
    {
        log.debug( "update" );

        if ( !isAlive )
        {
            log.warn( "not alive" );
            return;
        }

        if ( ce instanceof PurgatoryElement )
        {
            PurgatoryElement pe = ( PurgatoryElement ) ce;
            ce = pe.getCacheElement();
            if ( ! pe.isSpoolable() )
            {
                log.debug( "pe is not spoolable" );

                // it has been plucked from purgatory
                return;
            }
        }

        // remove item from purgatory since we are putting it on disk
        // assume that the disk cache will never break
        // disk breakage is akin to an out of memory exception
        buffer.purgatory.remove( ce.getKey() );
        if ( log.isDebugEnabled() )
        {
            log.debug( "\n putting " + ce.getKey() + " on disk, removing from purgatory" );
        }

        // make sure this only locks for one particular cache region
        //locker.writeLock();

        try
        {

            KeyObject[] keyArray = new JISPKey[1];
            keyArray[0] = new JISPKey( ce.getKey() );

            // akin to an update, should insert as well
            database.write( keyArray, ( Serializable ) ce );
            //p( "put " + ce.getKey() );

        }
        catch ( Exception e )
        {
            log.error( e );
        }
        finally
        {
            //locker.done();          // release write lock.
        }

        return;
    }


    /** Description of the Method */
    public Serializable get( Serializable key )
    {
        return get( key, true, true );
    }


    /** Description of the Method */
    public Serializable get( Serializable key, boolean container )
    {
        return get( key, true, true );
    }


    /** Description of the Method */
    private Serializable get( Serializable key, boolean container, final boolean lock )
    {

        if ( log.isDebugEnabled() )
        {
            log.debug( "getting " + key + " from disk" );
        }

        if ( !isAlive )
        {
            return null;
        }

        ICacheElement obj = null;

        try
        {

            obj = ( ICacheElement ) database.read( new JISPKey( key ), index1 );

        }
        catch ( Exception e )
        {
            log.error( e );
        }

        if ( obj == null )
        {
            return null;
        }

        if ( log.isDebugEnabled() )
        {
            log.debug( " " + key + ", val = " + obj.getVal() );
        }

        if ( container )
        {
            return ( Serializable ) obj;
        }
        return obj.getVal();
    }


    /**
     * Returns true if the removal was succesful; or false if there is nothing
     * to remove. Current implementation always result in a disk orphan.
     */
    public boolean remove( Serializable key )
    {

        KeyObject[] keyArray = new JISPKey[1];
        keyArray[0] = new JISPKey( key );

        try
        {

            if ( key instanceof String && key.toString().endsWith( NAME_COMPONENT_DELIMITER ) )
            {
                // remove all keys of the same name group.
                //sql = "delete from " + cacheName + " where KEY = like '" + key + "%'";
                // need to figure how to do this in JISP
            }
            else
            {
                database.remove( keyArray );
            }

        }
        catch ( Exception e )
        {
            log.error( e );
            reset();
        }
        return false;
    }


    /** Description of the Method */
    public void removeAll()
    {
        try
        {
            reset();
        }
        catch ( Exception e )
        {
            log.error( e );
            //reset();
        }
        finally
        {
        }
    }
    // end removeAll

    // handle error by last resort, force content update, or removeall
    /** Description of the Method */
    public void reset()
    {

        try
        {
            setupTABLE();
            createDB( true );
        }
        catch ( Exception e )
        {
            //log.error( e );
            log.warn( "Trying to create error files, two programs must be using the same JISP directory" );
            // Move to error directory, someone else must be using the file.
            try
            {
                this.jispDataFileName += ".error";
                this.jispIndexFileName += ".error";
                setupTABLE();
                createDB( true );
            }
            catch ( Exception e2 )
            {
                log.error( "Could not create error files!", e2 );
            }
        }
    }
    // end reset

    /**
     * Gets the stats attribute of the JISPCache object
     *
     * @return The stats value
     */
    public String getStats()
    {
        return "numInstances = " + numInstances;
    }


    // shold be called by cachemanager, since it knows how
    // many are checked out
    /** Description of the Method */
    public void dispose()
    {

        if ( !isAlive )
        {
            log.error( "is not alive and close() was called -- " + this.jispDataFileName );
            return;
        }

        try
        {
            database.close();
        }
        catch ( Exception e )
        {
            log.error( e );
        }
        finally
        {
            isAlive = false;
        }

        // TODO: can we defragment here?

    }
    // end dispose

    /**
     * Returns the cache status.
     *
     * @return The status value
     */
    public int getStatus()
    {
        return isAlive ? STATUS_ALIVE : STATUS_DISPOSED;
    }


    /**
     * Returns the current cache size.
     *
     * @return The size value
     */
    public int getSize()
    {
        return 0;
        // need to get count
    }


    /**
     * Gets the cacheType attribute of the JISPCache object
     *
     * @return The cacheType value
     */
    public int getCacheType()
    {
        return DISK_CACHE;
    }


    /** For debugging. */
    public void dump()
    {
        // TODO: not sure this is possible with JISP
//    log.debug("keyHash.size()=" + keyHash.size());
//    for (Iterator itr = keyHash.entrySet().iterator(); itr.hasNext();) {
//      Map.Entry e = (Map.Entry)itr.next();
//      Serializable key = (Serializable)e.getKey();
//      DiskElementDescriptor ded = (DiskElementDescriptor)e.getValue();
//      Serializable val = get(key);
//      log.debug("disk dump> key=" + key + ", val=" + val + ", pos=" + ded.pos);
//    }
    }

    /**
     * Returns cache name, ha
     *
     * @return The cacheName value
     */
    public String getCacheName()
    {
        return cacheName;
    }
}
TOP

Related Classes of org.apache.stratum.jcs.auxiliary.disk.jisp.JISPCache

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.