asmuts      02/01/14 22:38:11

  Added:       src/java/org/apache/stratum/jcs/engine/group
                        GroupAttrName.java GroupCache.java
                        GroupCacheManager.java
                        GroupCacheManagerFactory.java GroupId.java
                        GroupRWLockManager.java
  Log:
  grouping funcitonality built on top of the cache hub
  allows for getting the list of items in a group without keeping the entire group 
local
  could be cleaned up
  
  Revision  Changes    Path
  1.1                  
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/engine/group/GroupAttrName.java
  
  Index: GroupAttrName.java
  ===================================================================
  package  org.apache.stratum.jcs.engine.group;
  
  import java.io.*;
  
  /////////////////////////////////////////////////
  public class GroupAttrName implements Serializable {
    //final GroupId groupId;
    public final String groupId;
    final String attrName;
  
    //////////////////////////////////////////////////////
   public GroupAttrName(String groupId, String attrName) {
      //this.groupId = new GroupId(groupId);
      this.groupId = groupId;
      this.attrName = attrName;
  
      if (groupId == null || attrName == null)
        throw new IllegalArgumentException("groupId " + groupId + " and attrName " + 
attrName + ", must not be null.");
    }
  
    /////////////////////////////////////////////////////////////
        public boolean equals(Object obj) {
                if (obj == null || !(obj instanceof GroupAttrName))
                        return false;
                GroupAttrName to = (GroupAttrName)obj;
                return groupId.equals(to.groupId) && attrName.equals(to.attrName);
        }
  
    ////////////////////////////////////////////////
        public int hashCode() {
                return groupId.hashCode() ^ attrName.hashCode();
        }
  
    ////////////////////////////////////////////////
    public String toString() {
      return "[groupId="+groupId+", attrName="+attrName+"]";
    }
  
  }
  
  
  
  1.1                  
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/engine/group/GroupCache.java
  
  Index: GroupCache.java
  ===================================================================
  package  org.apache.stratum.jcs.engine.group;
  
  import  java.io.*;
  import  java.util.*;
  
  import org.apache.stratum.jcs.engine.behavior.*;
  import org.apache.stratum.jcs.engine.control.*;
  import org.apache.stratum.jcs.engine.*;
  import org.apache.stratum.jcs.access.*;
  import org.apache.stratum.jcs.access.exception.*;
  import org.apache.stratum.jcs.engine.control.Cache;
  import org.apache.stratum.jcs.auxiliary.disk.*;
  import org.apache.stratum.jcs.auxiliary.remote.*;
  import org.apache.stratum.jcs.auxiliary.remote.behavior.*;
  import  org.apache.stratum.jcs.utils.reuse.*;
  
  import org.apache.stratum.jcs.utils.log.*;
  
  
  /**
   * Group cache is basically a composite cache with the additional
   * capability of providing automatic and safe attribute name list update
   * for each GroupAttrName cache item.
   *
   * TODO: reduce the number of methods or describe them better.  The complexity
   * of this points to group design problems.  I need to fix the locking and the
   * maintenance of the remote list.  The list can be infered fromt he contents of
   * the cache.  Iterating through the hashtable could be problematic but easier.
   */
  public class GroupCache extends Cache implements ICompositeCache {
    //////////////// debug MUST BE SET TO false in production! ///////////////////
  
    private static final boolean debug = false;//true;
    private static final boolean debuggan = false;
    private ReadWriteLockManager locker = GroupRWLockManager.getInstance();
  
    private String source_id = "org.apache.stratum.jcs.engine.group.GroupCache";
  
    // declare a group_id cache here, so ids and elements don't compete
    // for first
    ICompositeCache systemGroupIdCache;
  
    ///////////////////////////////////////////////////
    public Serializable getSourceId() {
      return this.source_id;
    }
  
    ///////////////////////////////////////////////////////////////
    public GroupCache(String cacheName, ICache[] auxCaches, ICompositeCacheAttributes 
cattr, Attributes attr ) {
      super(cacheName, auxCaches, cattr, attr);
      if ( debug ) {
        p( "constructed groupcache " + cacheName + " from super" );
      }
      //ICompositeCache systemGroupIdCache = (ICompositeCache)systemCaches.get( 
"groupIdCache" );
    }
  
  
    ///////////////////////////////////////////////////////////////
    public GroupCache(String cacheName, ICache[] auxCaches, ICompositeCacheAttributes 
cattr, Attributes attr, ICompositeCache systemGroupIdCache ) {
      super(cacheName, auxCaches, cattr, attr);
      if ( debug ) {
        p( "constructed (2) groupcache " + cacheName + " from super" );
      }
      this.systemGroupIdCache = systemGroupIdCache;
    }
  
    /**
     * Overrides to provide read lock on both GroupAttrName read-operation
     * and String read-operation.
     */
    public Serializable get (Serializable key)  {
      return get( key, false, this.LOCAL_INVOKATION );
    }
    public Serializable get (Serializable key, boolean container) {
      return get( key, false, this.LOCAL_INVOKATION );
    }
    public Serializable get( Serializable key, boolean container, boolean invocation ) 
{
  
      if (key instanceof GroupAttrName) {
        return  getGAN( (GroupAttrName)key, container );
      }
      if (key instanceof GroupId) {
        return  getGI( (GroupId)key, container );
      }
      if ( debug ) {
        p( this.getCacheName() + " getting " + key + " from super, invocation = " + 
invocation );
      }
      return  super.get( key, container, invocation );
    }
  
    /** Places a read lock on the group id for a GroupAttrName get-operation. */
    public Serializable getGAN (GroupAttrName key, boolean container) {
      return getGAN( key, container, this.LOCAL_INVOKATION );
    }
    public Serializable getGAN (GroupAttrName key, boolean container, boolean 
invocation) {
      if ( debug ) {
        p( "in getGAN, invocation = " + invocation );
      }
      Object obj = null;
      // not necessary?, stops at getaux
      readLock(key.groupId);
      try {
        obj =  super.get(key, container, invocation);
        //p( "got obj" );
      } finally {
        locker.done(key.groupId);
      }
      return (Serializable)obj;
    }
  
    /** Places a read lock on the key for a GroupId get-operation. */
    // get list from remote if it isn't present
    public Serializable getGI (GroupId gid, boolean container)   {
      return getGI( gid, container, this.LOCAL_INVOKATION );
    }
    // stay local if this is a remote operation
    // removal of a group element will call this to get the list to edit
    public Serializable getGI (GroupId gid, boolean container, boolean invocation)   {
      if ( debug ) {
        p( "in getGi" );
      }
      Object obj = null;
      readLock(gid.key);
      try {
        //obj = super.get(gid.key, container);
        obj = systemGroupIdCache.get(gid.key, container, invocation);
        if ( debug ) {
          p( "got obj in getGi " + obj );
        }
      } catch( IOException ioeg ) {
      } finally {
        locker.done(gid.key);
      }
      return (Serializable)obj;
    }
  
    /////////////////////////////////////////////
    private void readLock (String id) {
      try {
        locker.readLock(id);
      } catch (InterruptedException ex) {
        // should never happen.
        ex.printStackTrace();
        //////////////// debug MUST BE SET TO false in production! ///////////////////
        if (debug) {
          try {
            System.in.read();
          } catch (IOException ignore) {}
        }
        throw  new IllegalStateException(ex.getMessage());
      }
    }
  
    //////////////////////////////////////
    private void writeLock (String id) {
      try {
        locker.writeLock(id);
      } catch (InterruptedException ex) {
        // should never happen.
        ex.printStackTrace();
        //////////////// debug MUST BE SET TO false in production! ///////////////////
        if (debug) {
          try {
            System.in.read();
          } catch (IOException ignore) {}
        }
        throw  new IllegalStateException(ex.getMessage());
      }
    }
  
    /** Overrides to special handling for GroupAttrName put-operation. */
    public void put (Serializable key, Serializable val, Attributes attr) throws 
IOException {
      if (key instanceof GroupAttrName) {
        try {
          if ( debug ) {
            p( "putting via putGAN((GroupAttrName)key, val, attr) method" );
          }
          putGAN((GroupAttrName)key, val, attr);
        } catch ( IOException ioe ) {}
        return;
      }
      if ( debug ) {
        p( "updating " + key + " via super method" );
      }
      //super.put(key, val);
      try {
        updateCaches(key, val, attr);
      } catch( IOException ioe ) {}
      return;
    }
    public void put (Serializable key, Serializable val) throws IOException {
    //public void put (Object key, Object val) throws IOException {
  
      if (key instanceof GroupAttrName) {
        try {
          if ( debug ) {
            p( "putting via putGAN((GroupAttrName)key, val) method" );
          }
          putGAN((GroupAttrName)key, val);
        } catch ( IOException ioe ) {}
        return;
      }
      if ( debug ) {
        p( "updating " + key + " via super method" );
      }
      //super.put(key, val);
      Attributes attrE = (Attributes)this.attr.copy();
      try {
        updateCaches(key, val, attrE);
      } catch( IOException ioe ) {}
      return;
  
    }
  
  
      ///////////////////////////////////////////////////////////
    public synchronized void update( ICacheElement ce ) throws IOException {
      update( ce, true );
    }
    ///////////////////////////////////////////////////////////
    public synchronized void update( ICacheElement ce, boolean localInvocation ) 
throws IOException {
      Object key = ce.getKey();
      if (key instanceof GroupAttrName) {
        try {
          if ( debug ) {
            p( "putting via ga method" );
          }
          putGAN((GroupAttrName)key, ce.getVal());
        } catch ( IOException ioe ) {}
        return;
      }
      if ( debug ) {
        p( "updating " + key + " via super method" );
      }
      //super.put(key, val);
      Attributes attrE = (Attributes)this.attr.copy();
      try {
        super.update(ce, localInvocation);
      } catch( IOException ioe ) {}
      return;
  
    } // end update
  
  
    /** GroupAttrName specific put-operation. */
    public void putGAN (GroupAttrName key, Serializable val) throws IOException {
      if ( debug ) {
        p( "in putGAN(GroupAttrName key, Serializable val) method" );
      }
      if (key == null || val == null) {
        NullPointerException ex = new NullPointerException("key=" + key + " and val="
            + val + " must not be null.");
        log.error(ex);
        throw  ex;
      }
  
      Attributes attrE = (Attributes)this.attr.copy();
      putGAN(key, val, attrE);
      return;
    }
  
    /**
     * Special handling for GroupAttrName put-operation.
     * Provides write lock and automatic attribute name set update.
     */
    // TODO: DistCacheMulticaster,etc. currently only supports key of String type
    // Needs to support GroupAttrName type, or do we ?
    private void putGAN(GroupAttrName key, Serializable val, Attributes attrE ) throws 
IOException {
      if ( debug ) {
        p( "in putGAN( gan,val,attr) " );
      }
      putGAN( key, val, attrE, true );
    }
    public void putGAN(GroupAttrName key, Serializable val, Attributes attrE, boolean 
updateRemote ) throws IOException {
      if ( debug ) {
        p( "in putGAN( gan,val,attr,boolean updateRemote) " );
      }
      writeLock(key.groupId);
      try {
  
        // update the attribute.
        //updateCaches(key, val, attrE, INCLUDE_REMOTE_CACHE);
        CacheElement ce = new CacheElement( this.getCacheName(), key, val );
        ce.setAttributes( attrE );
        if ( debuggan ) {
          p( "updating group attribute via super, updateRemote = " + updateRemote );
        }
        super.update( ce, updateRemote );
        //updateCaches(key, val, attrE, updateRemote);
  
        // update the attribute name set.
        // Note: use super.get to avoid read lock.
        //GroupId groupId = key.groupId;//new GroupId(key.groupId);
  
        GroupId groupId = new GroupId(this.getCacheName(),key.groupId);
        HashSet attrNameSet = null;
  
        // avoid lock of getGI, call super
        //attrNameSet = (HashSet)super.get(groupId.key, false);
        attrNameSet = (HashSet)systemGroupIdCache.get(groupId.key, false);
  
        if (attrNameSet == null) {
          //p( "couldn't find group attrnameSet" );
          attrNameSet = new HashSet();
        }
        attrNameSet.add(key.attrName);
        if ( debuggan ) {
          p( "attrNameSet.size()  = " + attrNameSet.size() );
        }
        // problem, this sets the group attr to the item
        // maintain the core list ont he remote.
        //updateCaches(groupId.key, attrNameSet, attrE, EXCLUDE_REMOTE_CACHE );
  
        CacheElement ceID = new CacheElement( this.getCacheName(), groupId.key, 
attrNameSet );
        ceID.setAttributes( attrE );
        //super.update( ceID, EXCLUDE_REMOTE_CACHE );
        //updateCaches(groupId.key, attrNameSet, attrE, EXCLUDE_REMOTE_CACHE );
  
        systemGroupIdCache.update( ceID, EXCLUDE_REMOTE_CACHE );
        //systemGroupIdCache.update( ceID, !EXCLUDE_REMOTE_CACHE  );
  
      } finally {
        locker.done(key.groupId);
      }
    }
  
  
    /////////////////////////////////////////////////////////////////////
    protected void createGroup( String group ) throws CacheException {
      createGroup( group, this.attr );
    }
    /////////////////////////////////////////////////////////////////////
    protected void createGroup( String group, Attributes attrE ) throws CacheException 
{
      // update the attribute name set.
      GroupId groupId = new GroupId(this.getCacheName(),group);
      HashSet attrNameSet = null;
  
      //attrNameSet = (HashSet)super.get(groupId.key);
      try {
        attrNameSet = (HashSet)systemGroupIdCache.get(groupId.key);
      } catch ( IOException ioe ) {}
  
      if (attrNameSet == null) {
        attrNameSet = new HashSet();
      } else {
        throw new CacheException( "group " + group + " already exists " );
      }
      try {
        CacheElement ceID = new CacheElement( this.getCacheName(), groupId.key, 
attrNameSet );
        ceID.setAttributes( attrE );
        //updateCaches(groupId.key, attrNameSet, attrE );
        //super.update( ceID, EXCLUDE_REMOTE_CACHE );
        systemGroupIdCache.update( ceID, EXCLUDE_REMOTE_CACHE );
  
      } catch ( IOException ioe ) {}
    }
  
  
  
    /** Overrides to provide special handling for GroupAttrName remove-operation. */
    public boolean remove (Serializable key) {
      if ( debug ) {
        p( "in basic remove" );
      }
      // if expired super will call remove and we can't have a lock
      // need a third method
      return remove( key, ICache.LOCAL_INVOKATION );
    }
  
    /** Easier to classify and send to other methods than relying on type
     * overriding.  removeGAN could be called remove
     */
    public boolean remove(Serializable key, boolean invocation ) {
      if (key instanceof GroupAttrName) {
        if ( debug ) {
          p( "calling removeGAN, invocation = " + invocation );
        }
        return  removeGAN((GroupAttrName)key, invocation);
      }
      if (key instanceof GroupId) {
        if ( debug ) {
          p( "call removeGI" );
        }
        return removeGI((GroupId)key, invocation);
      }
      if ( debug ) {
        p( "call super.remove, " + invocation + " for " + key );
      }
      return super.remove(key, invocation);
    }
  
    /**
     * Special handling for GroupAttrName remove-operation.
     * Provides write lock and automatic attribute name set update.
     * <br><br>
     * Note: there is the possibility that all the remove-cache-events for all
     * group attribute names are queued and pending to be processed.  Meanwhile,
     * the get-opeation for the attrbute name set will return with a size > 0.
     * Hence, when a groupn is invalidated, it's necessary to queue a
     * remove-attribute-name-set request to clean up garbage due to this race 
condition.
     */
    public boolean removeGAN (GroupAttrName key, boolean invokation) {
      boolean ret;
      if ( debug ) {
        p( "in removeGAN, invokation = " + invokation );
      }
      //writeLock(key.groupId);
      try {
        // remove the attribute.
        //ret = remove(key, LOCAL_INVOKATION);
  
        ret = super.remove(key, invokation);
        updateGroupAttrNameSet( key, invokation, true );
  
      } finally {
        //locker.done(key.groupId);
      }
      return  ret;
    }
  
    ////////////////////////////////////////////////////////////
    /** Handles removal, update, and insertion of items into the attrNameSet
     *  for a group cache region.  The Group Cache listener called the add when it 
gets a put
     *  though it may remove the item it referes to, depending ont he configuration.
     *  This saves on local cache space and keeps the list up to date.
     */
    public void updateGroupAttrNameSet( GroupAttrName key, boolean invokation, boolean 
remove ) {
        // update the attribute name set.
        // Note: necessary to use super.get to avoid read lock within the current 
write lock.
        GroupId groupId = new GroupId(this.getCacheName(),key.groupId);
        HashSet attrNameSet = null;
        CacheElement ce = null;
  
        //ce = (CacheElement)get(groupId.key, true );
        //attrNameSet = (HashSet)systemGroupIdCache.get(groupId.key);
        try {
          //ce = (CacheElement)systemGroupIdCache.get(groupId.key, true, invokation );
          //p( "systemGroupIdCache = " + systemGroupIdCache );
          //p( "groupId.key " + groupId.key );
          //p( "this.cacheAttr.getCacheName() = " + this.cacheAttr.getCacheName() );
          ce = (CacheElement)systemGroupIdCache.get(groupId.key, true, invokation );
        } catch ( IOException ioe ) {}
  
        if ( ce != null ) {
            attrNameSet = (HashSet)ce.val;
            if (attrNameSet != null || !remove) {
              if ( attrNameSet == null ) {
                attrNameSet = new HashSet();
              }
  
              if ( remove ) {
                attrNameSet.remove(key.attrName);
              } else {
                attrNameSet.add( key.attrName );
              }
              if (attrNameSet.size() > 0) {
                // update the changed name set.
                try {
                  //nonLocal = true
                  // last arg her is whether to update the remote
                  // shouldn't update remote if not local
                  // LOCAL_INVOKATION = false
  
                  // remove gi list for now if it the element is remotely changed
                  // otherwsie it will lack elements, since they are not moved
                  // with the items.  Otherwise add the keys on the
                  // remote listener handlePut method.  ya that's better.
                  //boolean updateRemote = !invokation;
                  //updateCaches(groupId.key, attrNameSet, ce.attr, updateRemote );
  
                  CacheElement ceID = new CacheElement( this.getCacheName(), 
groupId.key, attrNameSet );
                  ceID.setAttributes( ce.attr );
                  if ( debug ) {
                    p( "calling systemGroupIdCache.update( ceID, EXCLUDE_REMOTE_CACHE 
)" );
                  }
                  systemGroupIdCache.update( ceID, EXCLUDE_REMOTE_CACHE );
  
                } catch ( IOException ioe ) {}
              }
              else if ( remove ) {
                // no more attribute, so remove the name set all together, skipLock = 
true.
                //super.remove(groupId, invokation );
                //removeGI(groupId, invokation, true );
                try {
                  if ( debug ) {
                    p( "calling systemGroupIdCache.remove( groupId.key, 
EXCLUDE_REMOTE_CACHE )" );
                  }
                  systemGroupIdCache.remove( groupId.key, EXCLUDE_REMOTE_CACHE );
                } catch ( IOException ioe ) {}
              }
            }
        }
    } // end updateGroupAttrNameSet
  
  
  
    /**
     * Special handling for GroupId remove-operation.
     * Removes the attribute name set of the session.
     */
    public void removeGI (GroupId groupId ) {
      if ( debug ) {
        p( "removeGI" );
      }
      removeGI( groupId, false );
    }
  
    ///////////////////////////////////////
    /**
     * Skip the lock from the normal remove that is called from the
     * super when an element expires.  Keep the read lock method for
     * calls from groupaccess.
     */
    protected boolean removeGI (GroupId groupId, boolean nonLocal) {
      return removeGI( groupId, nonLocal, false );
    }
  
    protected boolean removeGI (GroupId groupId, boolean nonLocal, boolean skipLock) {
  
      boolean ok = false;
  
      // loop back, shouldn't of go here
      //if (!(key instanceof GroupId)) {
      //  ok = super.remove( (GroupId)groupId, nonLocal );
      //  return ok;
      //}
  
      // problem with removing expired while getting!
      skipLock = false;
  
      if ( debug ) {
        p( "in removeGI" );
      }
      if ( !skipLock ) {
        writeLock(groupId.key);
      }
      try {
        //ok = super.remove(groupId.key, nonLocal);
        ok = systemGroupIdCache.remove(groupId.key, nonLocal);
      } catch( IOException ioeg ) {
      } finally {
        if ( !skipLock ) {
          locker.done(groupId.key);
        }
      }
      return ok;
    }
  
      ////////////////////////////////////////////////
     public Attributes getElementAttributes( Serializable key ) throws CacheException, 
IOException {
      CacheElement ce = (CacheElement)getCacheElement( key );
      if ( ce == null ) {
        throw new ObjectNotFoundException( "key " + key + " is not found" );
      }
      return ce.getAttributes();
    }
  
  
    ////////////////////////////////////////
    public static void p( String s ) {
      System.out.println( "GroupCache: " + s );
    }
  
  
  }
  
  
  
  
  
  
  1.1                  
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/engine/group/GroupCacheManager.java
  
  Index: GroupCacheManager.java
  ===================================================================
  package org.apache.stratum.jcs.engine.group;
  
  import java.io.*;
  
  /////////////////////////////////////
  import org.apache.stratum.jcs.engine.behavior.*;
  import org.apache.stratum.jcs.engine.control.*;
  import org.apache.stratum.jcs.engine.*;
  import org.apache.stratum.jcs.access.*;
  import org.apache.stratum.jcs.engine.control.Cache;
  import org.apache.stratum.jcs.auxiliary.disk.*;
  import org.apache.stratum.jcs.auxiliary.remote.*;
  import org.apache.stratum.jcs.auxiliary.remote.behavior.*;
  
  //////////////////////////////////////////////////////////////////
  public class GroupCacheManager extends CompositeCacheManager implements Serializable 
{
  
    private static GroupCacheManager instance;
  
    ///////////////////////////////////////////
    protected GroupCacheManager() {
      super();
    }
  
    ///////////////////////////////////////////////
    protected GroupCacheManager(String propFile) {
      super(propFile);
    }
  
    /** Factory method to create the actual GroupCache instance. */
    protected Cache createSystemCache (String cacheName, ICache[] auxCaches, 
ICompositeCacheAttributes cattr, Attributes attr ) {
      p( "called create cache in groupcachemanager" );
      ICompositeCache systemGroupIdCache = (ICompositeCache)systemCaches.get( 
"groupIdCache" );
      return new GroupCache( cacheName, auxCaches, cattr, attr, systemGroupIdCache );
    }
  
    protected Cache createCache (String cacheName, ICache[] auxCaches, 
ICompositeCacheAttributes cattr, Attributes attr ) {
      p( "called create cache in groupcachemanager" );
      // sort of add hoc
      ICompositeCache systemGroupIdCache = (ICompositeCache)systemCaches.get( 
"groupIdCache" );
      return new GroupCache( cacheName, auxCaches, cattr, attr, systemGroupIdCache );
    }
  
    protected void incrementClients() {
      super.incrementClients();
    }
  
  } // end class
  
  
  
  1.1                  
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/engine/group/GroupCacheManagerFactory.java
  
  Index: GroupCacheManagerFactory.java
  ===================================================================
  package  org.apache.stratum.jcs.engine.group;
  
  import java.io.*;
  import java.rmi.*;
  import java.rmi.registry.*;
  import java.rmi.server.*;
  import java.util.*;
  import java.sql.*;
  
  /////////////////////////////////////
  import org.apache.stratum.jcs.engine.behavior.*;
  import org.apache.stratum.jcs.engine.control.*;
  import org.apache.stratum.jcs.engine.*;
  import org.apache.stratum.jcs.access.*;
  import org.apache.stratum.jcs.engine.control.Cache;
  import org.apache.stratum.jcs.auxiliary.disk.*;
  import org.apache.stratum.jcs.auxiliary.remote.*;
  import org.apache.stratum.jcs.auxiliary.remote.behavior.*;
  import org.apache.stratum.jcs.utils.reuse.*;
  
  import org.apache.stratum.jcs.utils.log.*;
  
  /////////////////////////////////////////////////////////////
  public class GroupCacheManagerFactory {
  
    private static final boolean pOut = false; //true;
  
    private static GroupCacheManager instance;
  
    //////////////////////////////////////////
    private GroupCacheManagerFactory() {
    }
  
    ///////////////////////////////////////////
    public static GroupCacheManager getInstance() {
      return getInstance(null);
    }
  
    //////////////////////////////////////////////
    public static GroupCacheManager getInstance(String propFile) {
      p ( "getting GroupCacheManger instance" );
      if (instance == null) {
        synchronized(GroupCacheManager.class) {
          if (instance == null) {
            instance = propFile == null ? new GroupCacheManager() : new 
GroupCacheManager(propFile);
          }
        }
      }
      if ( instance.log.logLevel >= instance.log.DEBUG ) {
        instance.log.debug( "Manager stats : " + instance.getStats() + "<br> -- in 
getInstance()" );
      }
      instance.incrementClients();
      return instance;
    }
  
    //////////////////////////////////////////////////////////
    private static void p(String s) {
      if ( pOut ) {
        System.out.println("GroupCacheManagerFactory:"+s+" 
>"+Thread.currentThread().getName());
      }
    }
  
  } // end class
  
  
  
  1.1                  
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/engine/group/GroupId.java
  
  Index: GroupId.java
  ===================================================================
  package org.apache.stratum.jcs.engine.group;
  
  import java.io.*;
  
  /**
   * Used to avoid name conflict when group cache items are mixed with
   * non-group cache items in the same cache.
   */
  public class GroupId implements Serializable {
  
    public final String key;
  
    public GroupId(String cacheName, String key ) {
      this.key = cacheName + key;
  
      if (key == null)
        throw new IllegalArgumentException("key must not be null.");
    }
        public boolean equals(Object obj) {
                if (obj == null || !(obj instanceof GroupId))
                        return false;
                GroupId to = (GroupId)obj;
                return key.equals(to.key);
        }
        public int hashCode() {
                return key.hashCode();
        }
    public String toString() {
      return "[grouId="+key+"]";
    }
  }
  
  
  
  1.1                  
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/engine/group/GroupRWLockManager.java
  
  Index: GroupRWLockManager.java
  ===================================================================
  package org.apache.stratum.jcs.engine.group;
  
  import org.apache.stratum.jcs.utils.reuse.*;
  import java.util.*;
  
  /** The ReadWriteLock Manager for distributed group list management. */
  class GroupRWLockManager extends ReadWriteLockManager {
  
      public static final boolean debug = false;
      private static GroupRWLockManager instance;
      private final Hashtable ht = new Hashtable();
  
      /** Returns the lock table of all the resources managed by this manager. */
      protected Hashtable getLocks() {
        return ht;
      }
      private GroupRWLockManager() {
      }
      static GroupRWLockManager getInstance() {
        if (instance == null) {
          synchronized(GroupRWLockManager.class) {
            if (instance == null) {
              instance = new GroupRWLockManager();
              if (debug) {
                p("   >> GroupRWLockManager instanciated.");
              }
            }
          }
        }
        return instance;
      }
      private static void p(String s) {
        System.out.println("GroupRWLockManager:"+s);
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to