Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source
   * Copyright 2006, Red Hat Middleware LLC, and individual contributors 
   * as indicated by the @author tags. 
   * See the copyright.txt in the distribution for a
   * full listing of individual contributors. 
   * This copyrighted material is made available to anyone wishing to use,
   * modify, copy, or redistribute it subject to the terms and conditions
   * of the GNU Lesser General Public License, v. 2.1.
  * This program is distributed in the hope that it will be useful, but WITHOUT A 
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
  * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
  * You should have received a copy of the GNU Lesser General Public License,
  * v.2.1 along with this distribution; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
  * MA  02110-1301, USA.
  * 
  * (C) 2005-2006,
  * @author JBoss Inc.
  */
 /*
  * Copyright (C) 2003, 2004,
  *
  * Arjuna Technologies Limited,
  * Newcastle upon Tyne,
  * Tyne and Wear,
  * UK.
  *
  * $Id: CacheStore.java 2342 2006-03-30 13:06:17Z  $
  */
 
 package com.arjuna.ats.internal.arjuna.objectstore;
 
 
A cached object store implementation.

Author(s):
Mark Little (mark@arjuna.com)
Version:
$Id: CacheStore.java 2342 2006-03-30 13:06:17Z $
Since:
JTS 3.0.
 
 
 public class CacheStore extends HashedStore
 {
     static final int NO_STATE_TYPE = -1;
 
     public boolean commit_state (Uid objUidString tName)
             throws ObjectStoreException
     {
         return ..addWork(this.,
                 objUidtNamenull.);
     }
 
     public void sync () throws java.io.SyncFailedException,
             ObjectStoreException
     {
         ..flush();
     }
 
     protected boolean remove_state (Uid objUidString nameint ft)
             throws ObjectStoreException
     {
         /*
          * Is it in the cache?
          */
 
         int status = ..removeState(objUidft);
 
         if (status == .)
             return true;
 
         /*
          * Check to see if there's a state on disk. If there is, then we still
          * need to add a remove work item to the cache queue.
          */
 
         int fileState = currentState(objUidname);
 
         if ((fileState != .)
                 || (status == .))
         {
             return ..addWork(this.,
                     objUidnamenullfileState);
         }
         else
         {
             if (fileState == .)
                 return false;
            else
                return true;
        }
    }
    protected boolean write_state (Uid objUidString tName,
            OutputObjectState stateint ftthrows ObjectStoreException
    {
        /*
         * If there is already a write operation in the cache for exactly this
         * state and type, then remove it and any corresponding remove_state
         * there might be. This is because write_state overwrites the state
         * rather than appending some operational work. If we used an appender
         * log then obviously this isn't appropriate.
         */
        int status = ..removeWriteState(objUidft);
        return ..addWork(this.objUid,
                tNamestateft);
    }

    
Before we look at the disk let's look in the state cache first for the state, just in case it hasn't been written out to persistent store yet.
    protected InputObjectState read_state (Uid objUidString tNameint ft)
            throws ObjectStoreException
    {
        OutputObjectState state = ..getState(objUidft);
        if (state == null// not in the cache
            return super.read_state(objUidtNameft);
        else
            return new InputObjectState(state);
    }
    /*
     * The methods that do the real work when the thread gets round to it.
     */
    protected boolean commitState (Uid objUidString tName)
            throws ObjectStoreException
    {
        return super.commit_state(objUidtName);
    }
    protected boolean removeState (Uid objUidString nameint ft)
            throws ObjectStoreException
    {
        return super.remove_state(objUidnameft);
    }
    protected boolean writeState (Uid objUidString tName,
            OutputObjectState stateint ftthrows ObjectStoreException
    {
        return super.write_state(objUidtNamestateft);
    }
    public CacheStore(ObjectStoreEnvironmentBean objectStoreEnvironmentBeanthrows ObjectStoreException
    {
        super(objectStoreEnvironmentBean);
        super. = objectStoreEnvironmentBean.isCacheStoreSync();
    }
    static AsyncStore _storeManager = new AsyncStore();
    public StoreElement(CacheStore sint towUid ouString tn,
            OutputObjectState stint ft)
    {
         = s;
         = tow;
         = new Uid(ou);
         = tn;
         = st;
         = ft;
         = false;
    }
    public void remove ()
    {
         = null;
         = .;
         = null;
         = null;
         = null;
         = .;
         = true;
    }
    public String toString ()
    {
        return "< " +  + ", " +  + ", " +  + ", "
                +  + ", " +  + " >";
    }
    public CacheStore store;
    public int typeOfWork;
    public Uid objUid;
    public String tName;
    public OutputObjectState state;
    public int fileType;
    public boolean removed;
class ShutdownThread extends Thread // used to flush on exit
    public ShutdownThread()
    {
        super("CacheStoreShutdownThread");
    }
    public void run ()
    {
        ..flush();
        synchronized (.)
        {
            ..notifyAll();
        }
        synchronized (..)
        {
            /*
             * We don't want to exit the VM if the worker thread is currently
             * writing to the disk. That would be very bad :-(! So, just check
             * that the thread isn't actively doing work.
             */
          if (..isTraceEnabled()) {
              ..trace("ShutdownThread.run () - terminating");
          }
      }
   }
class AsyncStore extends Thread // keep priority same as app. threads
    public static final int NO_WORK = -1;
    public static final int COMMIT = 0;
    public static final int REMOVE = 1;
    public static final int WRITE = 2;
    public static final int IN_USE = 3;
    public static final int REMOVED = 4;
    public static final int NOT_PRESENT = 5;
    public AsyncStore()
    {
        super("AsyncStoreThread");
         = ;
         = new LinkedList[];
        setDaemon(true);
        Runtime.getRuntime().addShutdownHook(new ShutdownThread());
        start();
    }
    public final void flush ()
    {
        /*
         * Do it this way because by the time we get here the daemon thread has
         * been removed by the system.
         */
        boolean stop = false;
        do
        {
            synchronized ()
            {
                stop =  <= 0;
            }
            if (!stop)
            {
                doWork();
            }
        }
        while (!stop);
         = true;
    }
    public final boolean addWork (CacheStore storeint workTypeUid objUid,
            String tNameOutputObjectState stateint ft)
    {
        /*
         * If the cache is full already, then wait until it has drained. We sit
         * in a while/do loop because many threads could be blocked and only one
         * may get a chance to add something to the queue before it goes full
         * again.
         */
        boolean stop = false;
        do
        {
            synchronized ()
            {
                if (cacheIsFull())
                {
                    try
                    {
                        .wait();
                    }
                    catch (Exception ex)
                    {
                    }
                }
                else
                    stop = true;
            }
        }
        while (!stop);
        StoreElement toAdd = new StoreElement(storeworkTypeobjUidtName,
                stateft);
        getList(objUid).addFirst(toAdd);
        synchronized ()
        {
            if (state != null)
                 += state.size();
            ++;
        }
        return true;
    }

    
Remove any item in the cache that operates on this state (must be identical uid and file type (shadowed, hidden etc.) This could potentially leave us with states on disk that should have been deleted but weren't because a crash happened before we could do that. Crash recovery should fix this up later though.
    public final int removeState (Uid objUidint ft)
    {
        Object[] elements = null;
        /*
         * Check the cache first. Take a snapshot.
         */
        try
        {
            elements = getList(objUid).toArray();
        }
        catch (Exception ex)
        {
            elements = null;
        }
        int status = ;
        
        if (elements == null)
            return status;
        synchronized (elements)
        {
            for (int i = 0; i < elements.lengthi++)
            {
                StoreElement element = (StoreElementelements[i];
    
                if ((element != null) && !element.removed
                        && element.objUid.equals(objUid))
                {
                    switch (element.typeOfWork)
                    {
                    case .:
                        element.remove();
    
                        synchronized ()
                        {
                            ++;
                        }
    
                        if (status != )
                            status = ;
    
                        break;
                    case .:
                        // if (element.fileType == ft)
                    {
                        synchronized ()
                        {
                            if (element.state != null)
                                 -= element.state.size();
    
                            ++;
                        }
    
                        element.remove();
    
                        if (status != )
                            status = ;
                    }
    
                        break;
                    default:
                        break;
                    }
                }
            }
        }
        if (cacheIsFull())
        {
            synchronized ()
            {
                .notify();
            }
        }
        
        /*
         * Does the worker thread currently have it?
         */
        if (..currentWork(objUidft))
        {
            status = ;
        }
        return status;
    }
    public final int removeWriteState (Uid objUidint ft)
    {
        int status = ;
        Object[] elements = null;
        try
        {
            elements = getList(objUid).toArray();
        }
        catch (Exception ex)
        {
            elements = null;
        }
        if (elements == null)
            return status;
        for (int i = 0; i < elements.lengthi++)
        {
            StoreElement element = (StoreElementelements[i];
            if ((element != null) && !element.removed
                    && element.objUid.equals(objUid))
            {
                switch (element.typeOfWork)
                {
                case .:
                    if (ft == element.fileType)
                    {
                        synchronized ()
                        {
                            if (element.state != null)
                                 -= element.state.size();
                            ++;
                        }
                        element.remove();
                        status = ;
                    }
                    else
                    {
                        if (ft == .)
                        {
                            if (element.fileType == .)
                            {
                                synchronized ()
                                {
                                    if (element.state != null)
                                         -= element.state
                                                .size();
                                    ++;
                                }
                                element.remove();
                                status = ;
                            }
                        }
                    }
                    break;
                case .:
                    if (ft == .)
                    {
                        synchronized ()
                        {
                            if (element.state != null)
                                 -= element.state.size();
                            ++;
                        }
                        element.remove();
                        status = ;
                    }
                    break;
                default:
                    break;
                }
            }
        }
        if (cacheIsFull())
        {
            synchronized ()
            {
                .notify();
            }
        }
        
        return status;
    }
    public final OutputObjectState getState (Uid objUidint ft)
    {
        LinkedList list = getList(objUid);
        synchronized (list)
        {
            for (int i = 0; i < list.size(); i++)
            {
                StoreElement element = (StoreElementlist.get(i);
                if ((element != null) && !element.removed && (element.objUid.equals(objUid)))
                {
                    if (element.fileType == ft)
                        return element.state;
                }
            }
            /*
             * If not in cache then maybe we're working on it?
             */
            synchronized ()
            {
                if (( != null) && (objUid.equals(.)))
                    return .;
            }
        }
        return null;
    }
    public void run ()
    {
        synchronized ()
        {
            try
            {
                .wait();
            }
            catch (Exception ex)
            {
            }
        }
        while (!)
        {
            synchronized ()
            {
                while (!queueIsEmpty()) // drain the queue
                {
                    doWork();
                }
                /*
                 * We've drained the queue, so notify any blocked threads so
                 * that they get a chance to add something to the queue again.
                 */
                synchronized ()
                {
                    .notifyAll();
                }
            }
            synchronized ()
            {
                if (!cacheIsFull())
                {
                    try
                    {
                        .wait();
                    }
                    catch (Exception ex)
                    {
                    }
                }
            }
        }
    }
    public boolean currentWork (Uid objUidint ft)
    {
        try
        {
            synchronized ()
            {
                if ( != null)
                {
                    if (..equals(objUid) && (. == ft))
                    {
                        return true;
                    }
                }
            }
        }
        catch (Exception ex)
        {
        }
        return false;
    }
    private final void doWork ()
    {
        synchronized ()
        {
            LinkedList list = getList();
            if (list != null)
            {
                try
                {
                     = (StoreElementlist.removeLast();
                    --;
                    if ((. != null) && !.)
                         -= ..size();
                    if (.)
                    {
                        --;
                    }
                }
                catch (java.util.NoSuchElementException ex)
                {
                     = null;
                }
            }
            else
                 = null;
        }
        if (( != null) && !.)
        {
            /*
             * Should write any errors to a persistent log so that an admin tool
             * can pick up the pieces later.
             */
            try
            {
                switch (.) {
                    case .: {
                        if (!..commitState(..)) {
                            ..warn_objectstore_CacheStore_1(..);
                        }
                    }
                    break;
                    case .: {
                        if (!..removeState(..,
                                .)) {
                            ..warn_objectstore_CacheStore_2(..,
                                    Integer.toString(.));
                        }
                    }
                    break;
                    case .: {
                        if (!..writeState(..,
                                ..)) {
                            ..warn_objectstore_CacheStore_3(..,
                                    ..toString(), Integer.toString(.));
                        }
                    }
                    break;
                    default:
                        ..warn_objectstore_CacheStore_4(Integer.toString(.));
                        break;
                }
            }
            catch (ObjectStoreException ex)
            {
                ex.printStackTrace();
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
        }
         = null;
    }

    

Returns:
true if the queue is empty, false otherwise.
    private final boolean queueIsEmpty ()
    {
        synchronized ()
        {
            if ( == 0)
                return true;
            else
                return false;
        }
    }

    

Returns:
true if the cache is full, false otherwise.
    private final boolean cacheIsFull ()
    {
        synchronized ()
        {
            if (( >= )
                    || ( >= )
                    || ( -  >= ))
            {
                .notifyAll();
                return true// cache is full, so wait
            }
            else
                return false// cache is ok
        }
    }
    private final LinkedList getList ()
    {
        for (int i = 0; i < i++)
        {
            if (([i] != null) && ([i].size() > 0))
                return [i];
        }
        return null;
    }
    private final LinkedList getList (Uid objUid)
    {
        int index = objUid.hashCode() % ;
        synchronized ()
        {
            if ([index] == null)
                [index] = new LinkedList();
            return [index];
        }
    }
    public Object _activeLock = new Object();
    private LinkedList[] _workList = null;
    private int _numberOfEntries = 0;
    private boolean _terminated = false;
    private int _currentCacheSize = 0;
    private int _maximumCacheSize = 0;
    private int _maximumWorkItems = 0;
    private int _maximumRemovedItems = 0;
    private int _scanPeriod = 0;
    private Object _overflowLock = new Object();
    private StoreElement _work = null;
    private int _removedItems = 0;
    private static int HASH_SIZE = 128;
    private static int _defaultCacheSize = 10240; // size in bytes
    private static int _defaultRemovedItems = 2 * ;
    private static int _defaultWorkItems = 100;
    private static int _defaultScanPeriod = 120000;
    static
    {
         = arjPropertyManager.getObjectStoreEnvironmentBean()
                .getCacheStoreHash();
        if ( <= 0)
             = 128;
         = arjPropertyManager.getObjectStoreEnvironmentBean()
                .getCacheStoreSize();
        if ( < 0)
             = 0;
         = arjPropertyManager
                .getObjectStoreEnvironmentBean().getCacheStoreRemovedItems();
        if ( < 0)
             = 0;
         = arjPropertyManager.getObjectStoreEnvironmentBean()
                .getCacheStoreWorkItems();
        if ( < 0)
             = 0;
         = arjPropertyManager.getObjectStoreEnvironmentBean()
                .getCacheStoreScanPeriod();
    }