first cleanup of cache code - implemented a new CacheMap which uses
SoftReferences
This commit is contained in:
		
							parent
							
								
									9558f0722b
								
							
						
					
					
						commit
						7e0f7b441f
					
				@ -15,8 +15,9 @@
 | 
			
		||||
 * 
 | 
			
		||||
 * Contributor(s): 
 | 
			
		||||
 */
 | 
			
		||||
package com.silverwrist.util.cachemap;
 | 
			
		||||
package com.silverwrist.util.cache;
 | 
			
		||||
 | 
			
		||||
import java.lang.ref.*;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
public class CacheMap implements Map
 | 
			
		||||
@ -92,6 +93,7 @@ public class CacheMap implements Map
 | 
			
		||||
  private CacheMapStrategy strategy;   // strategy routine to use to purge entries
 | 
			
		||||
  private HashMap base_map;            // maps keys to CacheMapEntry values
 | 
			
		||||
  private ArrayList element_list;      // the actual elements
 | 
			
		||||
  private ReferenceQueue rq;           // holds references that the garbage collector has cleared
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Constructors
 | 
			
		||||
@ -112,6 +114,7 @@ public class CacheMap implements Map
 | 
			
		||||
    this.strategy = strategy;
 | 
			
		||||
    this.base_map = new HashMap(10);
 | 
			
		||||
    this.element_list = new ArrayList(10);
 | 
			
		||||
    this.rq = new ReferenceQueue();
 | 
			
		||||
 | 
			
		||||
  } // end constructor
 | 
			
		||||
 | 
			
		||||
@ -127,6 +130,66 @@ public class CacheMap implements Map
 | 
			
		||||
 | 
			
		||||
  } // end constructor
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Internal operations
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private void doSweep()
 | 
			
		||||
  {
 | 
			
		||||
    Reference r = rq.poll();
 | 
			
		||||
    ArrayList ditch = new ArrayList();
 | 
			
		||||
    Iterator it;
 | 
			
		||||
 | 
			
		||||
    while (r!=null)
 | 
			
		||||
    { // look for the dead reference in the element list
 | 
			
		||||
      it = element_list.iterator();
 | 
			
		||||
      while (it.hasNext())
 | 
			
		||||
      { // check each cache map entry in return
 | 
			
		||||
	CacheMapEntry ntry = (CacheMapEntry)(it.next());
 | 
			
		||||
	if (ntry.matchReference(r))
 | 
			
		||||
	{ // remove the offending entry and save it in the temporary list
 | 
			
		||||
	  it.remove();
 | 
			
		||||
	  ditch.add(ntry);
 | 
			
		||||
	  break;
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
 | 
			
		||||
      } // end while
 | 
			
		||||
 | 
			
		||||
      r = rq.poll();  // get next dead reference
 | 
			
		||||
 | 
			
		||||
    } // end while
 | 
			
		||||
 | 
			
		||||
    if (ditch.isEmpty())
 | 
			
		||||
      return;  // nothing to prune
 | 
			
		||||
 | 
			
		||||
    it = ditch.iterator();
 | 
			
		||||
    while (it.hasNext())
 | 
			
		||||
    { // clear all entries from the base hashmap as well
 | 
			
		||||
      CacheMapEntry ntry = (CacheMapEntry)(it.next());
 | 
			
		||||
      base_map.remove(ntry.getKey());
 | 
			
		||||
      ntry.discard();
 | 
			
		||||
 | 
			
		||||
    } // end while
 | 
			
		||||
 | 
			
		||||
  } // end doSweep
 | 
			
		||||
 | 
			
		||||
  public synchronized void doShrink(int num_remove)
 | 
			
		||||
  {
 | 
			
		||||
    // Sort the element list to figure out which elements to remove.
 | 
			
		||||
    Collections.sort(element_list,new CacheOrdering(strategy));
 | 
			
		||||
    
 | 
			
		||||
    // The elements we want to remove are at the end of the array, so start from there.
 | 
			
		||||
    for (int i=0; i<num_remove; i++)
 | 
			
		||||
    { // remove the "removed" entries from the hash map
 | 
			
		||||
      CacheMapEntry cme = (CacheMapEntry)(element_list.remove(element_list.size() - 1));
 | 
			
		||||
      base_map.remove(cme.getKey());
 | 
			
		||||
 | 
			
		||||
    } // end for
 | 
			
		||||
 | 
			
		||||
  } // end doShrink
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementations from interface Map
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
@ -134,24 +197,28 @@ public class CacheMap implements Map
 | 
			
		||||
 | 
			
		||||
  public int size()
 | 
			
		||||
  {
 | 
			
		||||
    doSweep();
 | 
			
		||||
    return base_map.size();
 | 
			
		||||
 | 
			
		||||
  } // end size
 | 
			
		||||
 | 
			
		||||
  public boolean isEmpty()
 | 
			
		||||
  {
 | 
			
		||||
    doSweep();
 | 
			
		||||
    return base_map.isEmpty();
 | 
			
		||||
 | 
			
		||||
  } // end isEmpty
 | 
			
		||||
 | 
			
		||||
  public boolean containsKey(Object key)
 | 
			
		||||
  {
 | 
			
		||||
    doSweep();
 | 
			
		||||
    return base_map.containsKey(key);
 | 
			
		||||
 | 
			
		||||
  } // end containsKey
 | 
			
		||||
 | 
			
		||||
  public boolean containsValue(Object value)
 | 
			
		||||
  {
 | 
			
		||||
    doSweep();
 | 
			
		||||
    Iterator it = element_list.iterator();
 | 
			
		||||
    while (it.hasNext())
 | 
			
		||||
    { // look at all the CacheMapEntry values we have
 | 
			
		||||
@ -178,6 +245,7 @@ public class CacheMap implements Map
 | 
			
		||||
 | 
			
		||||
  public Object get(Object key)
 | 
			
		||||
  {
 | 
			
		||||
    doSweep();
 | 
			
		||||
    CacheMapEntry cme = (CacheMapEntry)(base_map.get(key));
 | 
			
		||||
    if (cme==null)
 | 
			
		||||
      return null;
 | 
			
		||||
@ -188,16 +256,17 @@ public class CacheMap implements Map
 | 
			
		||||
 | 
			
		||||
  public Object put(Object key, Object value)
 | 
			
		||||
  {
 | 
			
		||||
    doSweep();
 | 
			
		||||
    Object rc = null;
 | 
			
		||||
    CacheMapEntry cme = (CacheMapEntry)(base_map.get(key));
 | 
			
		||||
    if (cme==null)
 | 
			
		||||
    { // create a new CacheMapEntry for this key
 | 
			
		||||
      cme = new CacheMapEntry(key,value);
 | 
			
		||||
      cme = new CacheMapEntry(key,value,rq);
 | 
			
		||||
 | 
			
		||||
      synchronized (this)
 | 
			
		||||
      { // insert it into the basic object
 | 
			
		||||
	if (base_map.size()==capacity)
 | 
			
		||||
	  shrink();
 | 
			
		||||
	  doShrink((element_list.size() * shrink_percentage) / 100);
 | 
			
		||||
	element_list.add(cme);
 | 
			
		||||
	base_map.put(cme.getKey(),cme);
 | 
			
		||||
 | 
			
		||||
@ -207,7 +276,7 @@ public class CacheMap implements Map
 | 
			
		||||
    else
 | 
			
		||||
    { // we have an old value - replace it and touch the entry
 | 
			
		||||
      cme.touch();
 | 
			
		||||
      rc = cme.setValue(value);
 | 
			
		||||
      rc = cme.setValue(value,rq);
 | 
			
		||||
 | 
			
		||||
    } // end else
 | 
			
		||||
 | 
			
		||||
@ -217,6 +286,7 @@ public class CacheMap implements Map
 | 
			
		||||
 | 
			
		||||
  public Object remove(Object key)
 | 
			
		||||
  {
 | 
			
		||||
    doSweep();
 | 
			
		||||
    Object rc = null;
 | 
			
		||||
    CacheMapEntry cme = (CacheMapEntry)(base_map.get(key));
 | 
			
		||||
    if (cme!=null)
 | 
			
		||||
@ -230,6 +300,8 @@ public class CacheMap implements Map
 | 
			
		||||
 | 
			
		||||
      } // end synchronized block
 | 
			
		||||
 | 
			
		||||
      cme.discard();  // zap the reference
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    return rc;
 | 
			
		||||
@ -238,10 +310,12 @@ public class CacheMap implements Map
 | 
			
		||||
 | 
			
		||||
  public void putAll(Map map)
 | 
			
		||||
  {
 | 
			
		||||
    doSweep();
 | 
			
		||||
    synchronized (this)
 | 
			
		||||
    { // make sure we have enough space in the CacheMap for all the new elements!
 | 
			
		||||
      while ((map.size() + base_map.size()) > capacity)
 | 
			
		||||
	shrink();
 | 
			
		||||
      int nover = (map.size() + base_map.size()) - capacity;
 | 
			
		||||
      if (nover>0)
 | 
			
		||||
	doShrink(nover);
 | 
			
		||||
 | 
			
		||||
    } // end synchronized block
 | 
			
		||||
 | 
			
		||||
@ -258,6 +332,14 @@ public class CacheMap implements Map
 | 
			
		||||
  public synchronized void clear()
 | 
			
		||||
  {
 | 
			
		||||
    base_map.clear();
 | 
			
		||||
    Iterator it = element_list.iterator();
 | 
			
		||||
    while (it.hasNext())
 | 
			
		||||
    { // discard all entries we have
 | 
			
		||||
      CacheMapEntry cme = (CacheMapEntry)(it.next());
 | 
			
		||||
      cme.discard();
 | 
			
		||||
 | 
			
		||||
    } // end while
 | 
			
		||||
 | 
			
		||||
    element_list.clear();
 | 
			
		||||
 | 
			
		||||
  } // end clear
 | 
			
		||||
@ -270,13 +352,13 @@ public class CacheMap implements Map
 | 
			
		||||
 | 
			
		||||
  public Collection values()
 | 
			
		||||
  {
 | 
			
		||||
    return null;  // not implemented
 | 
			
		||||
    throw new UnsupportedOperationException("CacheMap.values() is not implemented");
 | 
			
		||||
 | 
			
		||||
  } // end values
 | 
			
		||||
 | 
			
		||||
  public Set entrySet()
 | 
			
		||||
  {
 | 
			
		||||
    return null;  // not implemented
 | 
			
		||||
    throw new UnsupportedOperationException("CacheMap.entrySet() is not implemented");
 | 
			
		||||
 | 
			
		||||
  } // end entrySet
 | 
			
		||||
 | 
			
		||||
@ -284,6 +366,7 @@ public class CacheMap implements Map
 | 
			
		||||
  {
 | 
			
		||||
    if ((o==null) || !(o instanceof Map))
 | 
			
		||||
      return false;  // not a map
 | 
			
		||||
    doSweep();
 | 
			
		||||
    Map other = (Map)o;
 | 
			
		||||
    if (other.size()!=base_map.size())
 | 
			
		||||
      return false;  // size does matter!
 | 
			
		||||
@ -314,6 +397,7 @@ public class CacheMap implements Map
 | 
			
		||||
 | 
			
		||||
  public int hashCode()
 | 
			
		||||
  {
 | 
			
		||||
    doSweep();
 | 
			
		||||
    int rc = 0;
 | 
			
		||||
    Iterator it = base_map.values().iterator();
 | 
			
		||||
    while (it.hasNext())
 | 
			
		||||
@ -384,17 +468,16 @@ public class CacheMap implements Map
 | 
			
		||||
    // Figure out how many elements to remove.
 | 
			
		||||
    int num_remove = (element_list.size() * shrink_percentage) / 100;
 | 
			
		||||
 | 
			
		||||
    // Sort the element list to figure out which elements to remove.
 | 
			
		||||
    Collections.sort(element_list,new CacheOrdering(strategy));
 | 
			
		||||
    
 | 
			
		||||
    // The elements we want to remove are at the end of the array, so start from there.
 | 
			
		||||
    for (int i=0; i<num_remove; i++)
 | 
			
		||||
    { // remove the "removed" entries from the hash map
 | 
			
		||||
      CacheMapEntry cme = (CacheMapEntry)(element_list.remove(element_list.size() - 1));
 | 
			
		||||
      base_map.remove(cme.getKey());
 | 
			
		||||
 | 
			
		||||
    } // end for
 | 
			
		||||
    // Try a sweep first.
 | 
			
		||||
    int n1 = base_map.size();
 | 
			
		||||
    doSweep();
 | 
			
		||||
    n1 -= base_map.size();
 | 
			
		||||
    if (n1<num_remove)
 | 
			
		||||
      doShrink(num_remove - n1);
 | 
			
		||||
 | 
			
		||||
  } // end shrink
 | 
			
		||||
 | 
			
		||||
} // end class CacheMap
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -15,31 +15,40 @@
 | 
			
		||||
 * 
 | 
			
		||||
 * Contributor(s): 
 | 
			
		||||
 */
 | 
			
		||||
package com.silverwrist.util.cachemap;
 | 
			
		||||
package com.silverwrist.util.cache;
 | 
			
		||||
 | 
			
		||||
import java.lang.ref.*;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
class CacheMapEntry implements Map.Entry
 | 
			
		||||
final class CacheMapEntry implements Map.Entry
 | 
			
		||||
{
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Attributes
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private Object key;
 | 
			
		||||
  private Object value;
 | 
			
		||||
  private int hits = 0;
 | 
			
		||||
  private long timestamp;
 | 
			
		||||
  private Object key;               // the key for this entry
 | 
			
		||||
  private SoftReference value;      // reference to (discardable) value
 | 
			
		||||
  private int hits = 0;             // number of hits on this entry
 | 
			
		||||
  private long timestamp;           // timestamp of this entry
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Constructor
 | 
			
		||||
   * Constructors
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  CacheMapEntry(Object key, Object value)
 | 
			
		||||
  {
 | 
			
		||||
    this.key = key;
 | 
			
		||||
    this.value = value;
 | 
			
		||||
    this.value = new SoftReference(value);
 | 
			
		||||
    this.timestamp = System.currentTimeMillis();
 | 
			
		||||
 | 
			
		||||
  } // end constructor
 | 
			
		||||
 | 
			
		||||
  CacheMapEntry(Object key, Object value, ReferenceQueue q)
 | 
			
		||||
  {
 | 
			
		||||
    this.key = key;
 | 
			
		||||
    this.value = new SoftReference(value,q);
 | 
			
		||||
    this.timestamp = System.currentTimeMillis();
 | 
			
		||||
 | 
			
		||||
  } // end constructor
 | 
			
		||||
@ -52,12 +61,13 @@ class CacheMapEntry implements Map.Entry
 | 
			
		||||
  protected void finalize()
 | 
			
		||||
  {
 | 
			
		||||
    key = null;
 | 
			
		||||
    value.clear();
 | 
			
		||||
    value = null;
 | 
			
		||||
 | 
			
		||||
  } // end finalize
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementations from interface MapEntry
 | 
			
		||||
   * Implementations from interface Map.Entry
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
@ -69,14 +79,14 @@ class CacheMapEntry implements Map.Entry
 | 
			
		||||
 | 
			
		||||
  public final Object getValue()
 | 
			
		||||
  {
 | 
			
		||||
    return value;
 | 
			
		||||
    return value.get();
 | 
			
		||||
 | 
			
		||||
  } // end getValue
 | 
			
		||||
 | 
			
		||||
  public final Object setValue(Object o)
 | 
			
		||||
  {
 | 
			
		||||
    Object rc = value;
 | 
			
		||||
    value = o;
 | 
			
		||||
    Object rc = value.get();
 | 
			
		||||
    value = new SoftReference(o);
 | 
			
		||||
    return rc;
 | 
			
		||||
 | 
			
		||||
  } // end setValue
 | 
			
		||||
@ -88,36 +98,17 @@ class CacheMapEntry implements Map.Entry
 | 
			
		||||
      return false;
 | 
			
		||||
    Map.Entry other = (Map.Entry)o;
 | 
			
		||||
 | 
			
		||||
    // compare the keys
 | 
			
		||||
    // compare the keys only (the values may change)
 | 
			
		||||
    if (key==null)
 | 
			
		||||
    { // the other key must be null
 | 
			
		||||
      if (other.getKey()!=null)
 | 
			
		||||
	return false;
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
      return (other.getKey()==null);
 | 
			
		||||
    else
 | 
			
		||||
    { // the other key must be equal to us
 | 
			
		||||
      if ((other.getKey()==null) || (!(key.equals(other.getKey()))))
 | 
			
		||||
	return false;
 | 
			
		||||
 | 
			
		||||
    } // end else
 | 
			
		||||
 | 
			
		||||
    // compare the values
 | 
			
		||||
    if (value==null)
 | 
			
		||||
      return (other.getValue()==null);
 | 
			
		||||
    else
 | 
			
		||||
      return ((other.getValue()!=null) && value.equals(other.getValue()));
 | 
			
		||||
      return ((other.getKey()!=null) && key.equals(other.getKey()));
 | 
			
		||||
 | 
			
		||||
  } // end equals
 | 
			
		||||
 | 
			
		||||
  public final int hashCode()
 | 
			
		||||
  {
 | 
			
		||||
    int rc = 0;
 | 
			
		||||
    if (key!=null)
 | 
			
		||||
      rc ^= key.hashCode();
 | 
			
		||||
    if (value!=null)
 | 
			
		||||
      rc ^= value.hashCode();
 | 
			
		||||
    return rc;
 | 
			
		||||
    return ((key==null) ? 0 : key.hashCode());
 | 
			
		||||
 | 
			
		||||
  } // end hashCode
 | 
			
		||||
 | 
			
		||||
@ -126,6 +117,38 @@ class CacheMapEntry implements Map.Entry
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  final Object setValue(Object o, ReferenceQueue q)
 | 
			
		||||
  {
 | 
			
		||||
    Object rc = value.get();
 | 
			
		||||
    value.clear();
 | 
			
		||||
    value = new SoftReference(o,q);
 | 
			
		||||
    return rc;
 | 
			
		||||
 | 
			
		||||
  } // end setValue
 | 
			
		||||
 | 
			
		||||
  final boolean isCleared()
 | 
			
		||||
  {
 | 
			
		||||
    return (value.get()==null);
 | 
			
		||||
 | 
			
		||||
  } // end isCleared
 | 
			
		||||
 | 
			
		||||
  final boolean matchReference(Reference r)
 | 
			
		||||
  {
 | 
			
		||||
    if (r instanceof SoftReference)
 | 
			
		||||
      return (value==(SoftReference)r);
 | 
			
		||||
    else
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
  } // end matchReference
 | 
			
		||||
 | 
			
		||||
  final void discard()
 | 
			
		||||
  {
 | 
			
		||||
    key = null;
 | 
			
		||||
    value.clear();
 | 
			
		||||
    value = null;
 | 
			
		||||
 | 
			
		||||
  } // end discard
 | 
			
		||||
 | 
			
		||||
  final int getHits()
 | 
			
		||||
  {
 | 
			
		||||
    return hits;
 | 
			
		||||
@ -15,7 +15,7 @@
 | 
			
		||||
 * 
 | 
			
		||||
 * Contributor(s): 
 | 
			
		||||
 */
 | 
			
		||||
package com.silverwrist.util.cachemap;
 | 
			
		||||
package com.silverwrist.util.cache;
 | 
			
		||||
 | 
			
		||||
public interface CacheMapStrategy
 | 
			
		||||
{
 | 
			
		||||
@ -19,7 +19,7 @@ package com.silverwrist.venice.core.impl;
 | 
			
		||||
 | 
			
		||||
import java.sql.*;
 | 
			
		||||
import java.util.Random;
 | 
			
		||||
import com.silverwrist.util.cachemap.*;
 | 
			
		||||
import com.silverwrist.util.cache.CacheMap;
 | 
			
		||||
import com.silverwrist.venice.core.*;
 | 
			
		||||
import com.silverwrist.venice.db.*;
 | 
			
		||||
 | 
			
		||||
@ -38,12 +38,12 @@ class AdvertisementImpl implements Advertisement
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private DataPool datapool;
 | 
			
		||||
  private int adid;
 | 
			
		||||
  private String imagepath;
 | 
			
		||||
  private short style;
 | 
			
		||||
  private String caption;
 | 
			
		||||
  private String linkurl;
 | 
			
		||||
  private DataPool datapool;         // data pool reference
 | 
			
		||||
  private int adid;                  // ad ID
 | 
			
		||||
  private String imagepath;          // image path
 | 
			
		||||
  private short style;               // ad style
 | 
			
		||||
  private String caption;            // ad caption
 | 
			
		||||
  private String linkurl;            // ad link URL
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Constructor
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,7 @@ package com.silverwrist.venice.servlets.format;
 | 
			
		||||
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import com.silverwrist.util.IOUtil;
 | 
			
		||||
import com.silverwrist.util.cachemap.CacheMap;
 | 
			
		||||
import com.silverwrist.util.cache.CacheMap;
 | 
			
		||||
 | 
			
		||||
public class StaticRender implements ContentRender
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user