[jboss-cvs] JBossCache/src-50/org/jboss/cache/pojo/collection ...

Elias Ross genman at noderunner.net
Mon Nov 6 18:32:16 EST 2006


  User: genman  
  Date: 06/11/06 18:32:16

  Modified:    src-50/org/jboss/cache/pojo/collection   
                        CachedListImpl.java CachedSetImpl.java
  Added:       src-50/org/jboss/cache/pojo/collection    IntegerCache.java
  Log:
  JBCACHE-485 - Set.contains() remove() and add() O(1) ops now
  
  Revision  Changes    Path
  1.11      +13 -13    JBossCache/src-50/org/jboss/cache/pojo/collection/CachedListImpl.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: CachedListImpl.java
  ===================================================================
  RCS file: /cvsroot/jboss/JBossCache/src-50/org/jboss/cache/pojo/collection/CachedListImpl.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -b -r1.10 -r1.11
  --- CachedListImpl.java	10 Oct 2006 08:08:23 -0000	1.10
  +++ CachedListImpl.java	6 Nov 2006 23:32:16 -0000	1.11
  @@ -69,7 +69,7 @@
         checkIndex();
         try
         {
  -         return Null.toNullValue(pCache_.getObject(AopUtil.constructFqn(getFqn(), Integer.toString(index))));
  +         return Null.toNullValue(pCache_.getObject(AopUtil.constructFqn(getFqn(), IntegerCache.toString(index))));
         } catch (Exception e)
         {
            throw new RuntimeException(e);
  @@ -108,7 +108,7 @@
            if (index != 0)
               checkIndex(); // Since index can be size().
            return Null.toNullValue(pCache_.attach(AopUtil.constructFqn(getFqn(),
  -                 Integer.toString(index)), Null.toNullObject(element)));
  +                 IntegerCache.toString(index)), Null.toNullObject(element)));
         } catch (Exception e)
         {
            throw new RuntimeException(e);
  @@ -123,10 +123,10 @@
               checkIndex(); // Since index can be size().
            for (int i = size(); i > index; i--)
            {
  -            Object obj = pCache_.detach(AopUtil.constructFqn(getFqn(), Integer.toString(i - 1)));
  -            pCache_.attach(AopUtil.constructFqn(getFqn(), Integer.toString(i)), obj);
  +            Object obj = pCache_.detach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(i - 1)));
  +            pCache_.attach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(i)), obj);
            }
  -         pCache_.attach(AopUtil.constructFqn(getFqn(), Integer.toString(index)), Null.toNullObject(element));
  +         pCache_.attach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(index)), Null.toNullObject(element));
         } catch (Exception e)
         {
            throw new RuntimeException(e);
  @@ -181,15 +181,15 @@
            checkIndex();
            // Object result = cache.removeObject(((Fqn) fqn.clone()).add(new Integer(index)));
            int size = size();
  -         Object result = Null.toNullValue(pCache_.detach(AopUtil.constructFqn(getFqn(), Integer.toString(index))));
  +         Object result = Null.toNullValue(pCache_.detach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(index))));
            if (size == (index + 1))
            {
               return result; // We are the last one.
            }
            for (int i = index; i < size - 1; i++)
            {
  -            Object obj = pCache_.detach(AopUtil.constructFqn(getFqn(), Integer.toString(i + 1)));
  -            pCache_.attach(AopUtil.constructFqn(getFqn(), Integer.toString(i)), obj);
  +            Object obj = pCache_.detach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(i + 1)));
  +            pCache_.attach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(i)), obj);
            }
            return result;
         } catch (Exception e)
  @@ -225,7 +225,7 @@
   
               try
               {
  -               return Null.toNullValue(pCache_.getObject(AopUtil.constructFqn(getFqn(), Integer.toString(++current))));
  +               return Null.toNullValue(pCache_.getObject(AopUtil.constructFqn(getFqn(), IntegerCache.toString(++current))));
               } catch (Exception e)
               {
                  throw new RuntimeException(e);
  @@ -244,16 +244,16 @@
                  if (current < (size - 1))
                  {
                     // Need to reshuffle the items.
  -                  Object last = pCache_.detach(AopUtil.constructFqn(getFqn(), Integer.toString(current)));
  +                  Object last = pCache_.detach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(current)));
                     for (int i = current + 1; i < size; i++)
                     {
  -                     last = pCache_.detach(AopUtil.constructFqn(getFqn(), Integer.toString(i)));
  -                     pCache_.attach(AopUtil.constructFqn(getFqn(), Integer.toString(i - 1)), last);
  +                     last = pCache_.detach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(i)));
  +                     pCache_.attach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(i - 1)), last);
                     }
                  } else
                  { // we are the last index.
                     // Need to move back the cursor.
  -                  pCache_.detach(AopUtil.constructFqn(getFqn(), Integer.toString(current)));
  +                  pCache_.detach(AopUtil.constructFqn(getFqn(), IntegerCache.toString(current)));
                  }
                  current--;
                  size--;
  
  
  
  1.10      +120 -120  JBossCache/src-50/org/jboss/cache/pojo/collection/CachedSetImpl.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: CachedSetImpl.java
  ===================================================================
  RCS file: /cvsroot/jboss/JBossCache/src-50/org/jboss/cache/pojo/collection/CachedSetImpl.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -b -r1.9 -r1.10
  --- CachedSetImpl.java	13 Oct 2006 10:24:46 -0000	1.9
  +++ CachedSetImpl.java	6 Nov 2006 23:32:16 -0000	1.10
  @@ -25,10 +25,14 @@
   import java.util.Iterator;
   import java.util.Map;
   import java.util.Set;
  -import java.util.LinkedList;
  +import java.util.ArrayList;
   
   /**
  - * Set that uses cache as a underlying backend store
  + * Set implementation that uses a cache as an underlying backend store.
  + * Set data is stored in children nodes named based on the attached Object's hash code
  + * in hexidecimal string form.
  + * If there are conflicts between two Objects with the same hash code, then a
  + * counter (upper 32 bits of 64) is used.
    *
    * @author Ben Wang
    * @author Scott Marlow
  @@ -52,100 +56,132 @@
   
      private Node getNode()
      {
  -      try
  -      {
            return CacheApiUtil.getDataNode(cache_, getFqn());
  -      } catch (Exception e)
  -      {
  -         throw new RuntimeException(e);
  -      }
      }
   
      private Fqn getFqn()
      {
  -      // Need this since fqn can be reset.
  +      // Cannot cache this as this can be reset
         return interceptor_.getFqn();
      }
   
  -   // implementation of the java.util.Set interface
  -   public int size()
  +   // java.util.Set implementation
  +
  +   public boolean add(Object o)
      {
  -      Node node = getNode();
  -      if (node == null)
  +	  o = Null.toNullObject(o);
  +	  int hashCode = o.hashCode();
  +	  int size = size();
  +	  for (int i = 0; i < size + 1; i++)
  +	  {
  +		 Object key = toLong(hashCode, i);
  +		 Object o2 = getNoUnmask(key);
  +		 if (o2 == null)
         {
  -         return 0;
  +			putNoMask(key, o);
  +			return true;
         }
  -
  -      Collection<Node> children = node.getChildren();
  -      return children == null ? 0 : children.size();
  +		 if (o.equals(o2))
  +			return false;
      }
  -
  -   public Iterator iterator()
  -   {
  -      return new IteratorImpl(keySet());
  +	  // should never reach here
  +	  throw new CacheException();
      }
   
  +   public void clear()
  +   {
  +      Node node = getNode();
  +      if (node == null)
  +		 return;
   
  -   public boolean add(Object o)
  +	  Collection<Node> children = node.getChildren();
  +	  for (Node n : children)
      {
  -      Collection keys = keySet();
  +         pCache_.detach(n.getFqn());
  +	  }
  +   }
   
  -      // This could be done with 'contains(o)' but it would invoke 'keySet()'
  -      // twice
  -      for (Iterator iter = new IteratorImpl(keys); iter.hasNext();)
  -         if (iter.next() == o)
  +   public boolean contains(Object o)
  +   {
  +	  o = Null.toNullObject(o);
  +	  int hashCode = o.hashCode();
  +	  int size = size();
  +	  for (int i = 0; i < size; i++)
  +	  {
  +		 Object key = toLong(hashCode, i);
  +		 Object o2 = getNoUnmask(key);
  +		 if (o2 == null)
               return false;
  -
  -      // Search for an available key. This is a fast operation as the key set
  -      // is already available. Start with the size of the key set and go
  -      // up as this will be the fastest way to find an unused key. Gaps
  -      // in the keys don't matter, as this is a Set not a List
  -      int key = keys.size();
  -      String keyString;
  -      while (keys.contains((keyString = Integer.toString(key))))
  -         key++;
  -
  -      pCache_.attach(AopUtil.constructFqn(getFqn(), keyString), Null.toNullObject(o));
  +		 if (o.equals(o2))
         return true;
      }
  +	  return false;
  +   }
   
  -   public boolean contains(Object o)
  +   public Iterator iterator()
      {
  -      Iterator iter = iterator();
  -      if (o == null)
  +      Node node = getNode();
  +      if (node == null)
  +         return Collections.EMPTY_SET.iterator();
  +      return new IteratorImpl(node);
  +   }
  +
  +   public boolean remove(Object o)
         {
  -         while (iter.hasNext())
  +	  o = Null.toNullObject(o);
  +	  int hashCode = o.hashCode();
  +	  int size = size();
  +	  boolean removed = false;
  +	  Object oldkey = null;
  +	  for (int i = 0; i < size; i++)
            {
  -            if (iter.next() == null)
  +		 Object key = toLong(hashCode, i);
  +		 Object o2 = getNoUnmask(key);
  +		 if (o2 == null)
  +			break;
  +		 if (removed)
               {
  -               return true;
  -            }
  +			// move o2 to old key 
  +			pCache_.detach(AopUtil.constructFqn(getFqn(), key));
  +			pCache_.attach(AopUtil.constructFqn(getFqn(), oldkey), o2);
            }
  -      } else
  -      {
  -         while (iter.hasNext())
  -         {
  -            if (o.equals(iter.next()))
  +		 if (o.equals(o2))
               {
  -               return true;
  +			pCache_.detach(AopUtil.constructFqn(getFqn(), key));
  +			removed = true;
               }
  +		 oldkey = key;
            }
  +	  return removed;
         }
  -      return false;
  +
  +   public int size()
  +   {
  +      Node node = getNode();
  +      if (node == null)
  +         return 0;
  +
  +      return node.getChildren().size();
      }
   
  +   /**
  +	* Return a long with "count" as the high 32 bits.
  +	* TODO should be able to use java.lang.Long, but some CacheLoader don't
  +	* support non-String keys
  +	*/
  +   private String toLong(long hashCode, long count) {
  +	  long key = (hashCode & 0xFFFFL) | (count << 32);
  +	  return Long.toHexString(key);
  +   }
   
  -   public String toString()
  -   {
  -      StringBuffer buf = new StringBuffer();
  -      for (Iterator it = iterator(); it.hasNext();)
  +   private Object putNoMask(Object key, Object pojo)
         {
  -         Object key = it.next();
  -         buf.append("[").append(key).append("]");
  -         if (it.hasNext()) buf.append(", ");
  +	  return pCache_.putObject(AopUtil.constructFqn(getFqn(), key), pojo);
         }
   
  -      return buf.toString();
  +   private Object getNoUnmask(Object key)
  +   {
  +	  return pCache_.getObject(AopUtil.constructFqn(getFqn(), key));
      }
   
      public int hashCode()
  @@ -158,18 +194,14 @@
   
      public boolean equals(Object o)
      {
  -      if (o == null)
  -         return false;
  -
         if (o == this)
            return true;
   
         try
         {
  -         Set set = (Set) o;
  -
  -         return (set.size() == keySet().size() && this.containsAll(set));
  -      } catch (ClassCastException e)
  +		 return super.equals(o);
  +      }
  +	  catch (ClassCastException e)
         {
            return false;
         }
  @@ -179,37 +211,17 @@
         }
      }
   
  -   private Collection keySet()
  -   {
  -      Node node = getNode();
  -
  -      // TODO Not efficient here!!
  -      if (node != null)
  -      {
  -         Collection<Node> children = node.getChildren();
  -         if (children == null) return null;
  -
  -         LinkedList keys = new LinkedList();
  -         for(Node n : children)
  -         {
  -            keys.add(n.getFqn().getLast());
  -         }
  -
  -         return keys;
  -      }
  -
  -      return Collections.EMPTY_SET;
  -   }
  -
      private class IteratorImpl implements Iterator
      {
  -      private Iterator iterator;
  +      private Iterator<Node> iterator;
   
  -      private Object key;
  +      private Node node;
  +      private Object o;
   
  -      private IteratorImpl(Collection keys)
  +      private IteratorImpl(Node node)
         {
  -         iterator = keys.iterator();
  +		 Collection<Node> children = node.getChildren();
  +         iterator = children.iterator();
         }
   
         public boolean hasNext()
  @@ -219,30 +231,18 @@
   
         public Object next()
         {
  -         // (Brian) Removed Jussi's call to iterator.hasNext() followed by
  -         // an NSOE if false.  That approach was slightly more efficient if
  -         // hasNext() were false, but in the vast majority of cases iterators
  -         // are used correctly and it was an extra step.
  -
  -         this.key = iterator.next();
  -
  -         try
  -         {
  -            return Null.toNullValue(pCache_.getObject(AopUtil.constructFqn(getFqn(), this.key)));
  -         } catch (CacheException e)
  -         {
  -            throw new RuntimeException(e);
  -         }
  +         node = iterator.next();
  +		 o = Null.toNullValue(pCache_.getObject(node.getFqn()));
  +		 return o;
         }
   
         public void remove() throws IllegalStateException
         {
  -         if (this.key == null)
  +         if (node == null)
            {
               throw new IllegalStateException();
            }
  -
  -         pCache_.detach(AopUtil.constructFqn(getFqn(), this.key));
  +		 CachedSetImpl.this.remove(o);
         }
   
      }
  
  
  
  1.1      date: 2006/11/06 23:32:16;  author: genman;  state: Exp;JBossCache/src-50/org/jboss/cache/pojo/collection/IntegerCache.java
  
  Index: IntegerCache.java
  ===================================================================
  package org.jboss.cache.pojo.collection;
  
  /**
   * Cache of integers in String format from 0-99.
   */
  public class IntegerCache
  {
     
     private IntegerCache() {}
     private static final String values[] = new String[100];
     static 
     {
        for (int i = 0; i < values.length; i++)
           values[i] = Integer.toString(i).intern();
     }
     
     public static String toString(int i)
     {
        if (i >= 0 && i < values.length)
           return values[i];
        return Integer.toString(i);
     }
     
  }
  
  
  



More information about the jboss-cvs-commits mailing list