Open Source Repository

Home /hibernate/hibernate-3.2.4.ga | Repository Home



org/hibernate/cache/TreeCache.java
//$Id: TreeCache.java 9965 2006-05-30 18:00:28Z [email protected] $
package org.hibernate.cache;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.Fqn;
import org.jboss.cache.lock.TimeoutException;

/**
 * Represents a particular region within the given JBossCache TreeCache.
 *
 @author Gavin King
 */
public class TreeCache implements Cache {
  
  private static final Log log = LogFactory.getLog(TreeCache.class);

  private static final String ITEM = "item";

  private org.jboss.cache.TreeCache cache;
  private final String regionName;
  private final Fqn regionFqn;
  private final TransactionManager transactionManager;

  public TreeCache(org.jboss.cache.TreeCache cache, String regionName, TransactionManager transactionManager
  throws CacheException {
    this.cache = cache;
    this.regionName = regionName;
    this.regionFqn = Fqn.fromStringregionName.replace'.''/' ) );
    this.transactionManager = transactionManager;
  }

  public Object get(Object keythrows CacheException {
    Transaction tx = suspend();
    try {
      return read(key);
    }
    finally {
      resumetx );
    }
  }
  
  public Object read(Object keythrows CacheException {
    try {
      return cache.getnew FqnregionFqn, key ), ITEM );
    }
    catch (Exception e) {
      throw new CacheException(e);
    }
  }

  public void update(Object key, Object valuethrows CacheException {
    try {
      cache.putnew FqnregionFqn, key ), ITEM, value );
    }
    catch (Exception e) {
      throw new CacheException(e);
    }
  }

  public void put(Object key, Object valuethrows CacheException {
    Transaction tx = suspend();
    try {
      //do the failfast put outside the scope of the JTA txn
      cache.putFailFastnew FqnregionFqn, key ), ITEM, value, );
    }
    catch (TimeoutException te) {
      //ignore!
      log.debug("ignoring write lock acquisition failure");
    }
    catch (Exception e) {
      throw new CacheException(e);
    }
    finally {
      resumetx );
    }
  }

  private void resume(Transaction tx) {
    try {
      if (tx!=nulltransactionManager.resume(tx);
    }
    catch (Exception e) {
      throw new CacheException("Could not resume transaction", e);
    }
  }

  private Transaction suspend() {
    Transaction tx = null;
    try {
      if transactionManager!=null ) {
        tx = transactionManager.suspend();
      }
    }
    catch (SystemException se) {
      throw new CacheException("Could not suspend transaction", se);
    }
    return tx;
  }

  public void remove(Object keythrows CacheException {
    try {
      cache.removenew FqnregionFqn, key ) );
    }
    catch (Exception e) {
      throw new CacheException(e);
    }
  }

  public void clear() throws CacheException {
    try {
      cache.removeregionFqn );
    }
    catch (Exception e) {
      throw new CacheException(e);
    }
  }

  public void destroy() throws CacheException {
    try {
      // NOTE : evict() operates locally only (i.e., does not propogate
      // to any other nodes in the potential cluster).  This is
      // exactly what is needed when we destroy() here; destroy() is used
      // as part of the process of shutting down a SessionFactory; thus
      // these removals should not be propogated
      cache.evictregionFqn );
    }
    catchException e ) {
      throw new CacheException);
    }
  }

  public void lock(Object keythrows CacheException {
    throw new UnsupportedOperationException"TreeCache is a fully transactional cache" + regionName );
  }

  public void unlock(Object keythrows CacheException {
    throw new UnsupportedOperationException"TreeCache is a fully transactional cache: " + regionName );
  }

  public long nextTimestamp() {
    return System.currentTimeMillis() 100;
  }

  public int getTimeout() {
    return 600//60 seconds
  }

  public String getRegionName() {
    return regionName;
  }

  public long getSizeInMemory() {
    return -1;
  }

  public long getElementCountInMemory() {
    try {
      Set children = cache.getChildrenNamesregionFqn );
      return children == null : children.size();
    }
    catch (Exception e) {
      throw new CacheException(e);
    }
  }

  public long getElementCountOnDisk() {
    return 0;
  }
  
  public Map toMap() {
    try {
      Map result = new HashMap();
      Set childrenNames = cache.getChildrenNamesregionFqn );
      if (childrenNames != null) {
        Iterator iter = childrenNames.iterator();
        while iter.hasNext() ) {
          Object key = iter.next();
          result.put
              key, 
              cache.getnew FqnregionFqn, key ), ITEM )
            );
        }
      }
      return result;
    }
    catch (Exception e) {
      throw new CacheException(e);
    }
  }
  
  public String toString() {
    return "TreeCache(" + regionName + ')';
  }
  
}