If you have your cvs access worked out, you should modify the project.xml and add yourself to the committer list.
Cheers, Aaron > -----Original Message----- > From: Travis Savo [mailto:[EMAIL PROTECTED] > Sent: Saturday, July 17, 2004 6:09 PM > To: 'Turbine JCS Developers List' > Subject: RE: CachingWorker > > Some excellent suggestions. I'll refine my design and get back to you. > > I'll also look into the group/key problem if I get a chance. > > -T > > -----Original Message----- > From: Aaron Smuts [mailto:[EMAIL PROTECTED] > Sent: Saturday, July 17, 2004 11:37 AM > To: 'Turbine JCS Developers List' > Subject: RE: CachingWorker > > > This is interesting. I don't like getting the region everytime you do a > get. This slows things down dramatically. I posted on the javaworld > article on caching about this. Their timings were way off because of > it. We might be able to make it more efficient. I'd prefer issuing a > get on a region I have has a static variable, and then calling something > like this if it returns null. Would that work? > > I see how it could be useful. You can always put anything in the > experiemental package or, maybe better, something like this in a > subpackage of utils on the main src. org.apache.jcs.utils.access or > worker or something that makes sense, say org.apache.control.loader . > > We should also look into the idea of implementing pluggable cacheLoaders > for a region. > > Have you looked at the FutureResult in Doug Lea's util concurrent > package. It may be useful here. > > I'm still looking over your idea. > > On another issue, we need to make items in groups returnable by jus the > key, without referencing the group. Otherwise a group is just an > inefficient region. To do this we need to create a CacheKey object for > the CacheElement. The CacheKey and the GroupAttrName classes need > equals methods that can match on the same key. > > Cheers, > > Aaron > > > -----Original Message----- > > From: Travis Savo [mailto:[EMAIL PROTECTED] > > Sent: Friday, July 16, 2004 7:04 PM > > To: 'Turbine JCS Developers List' > > Subject: CachingWorker > > > > Did you want my CachingWorker? > > > > It's a wrapper around JCS to encapsulate the most common set of > actions > > performed with JCS. > > > > Given a region and a key, do the following psudo-code: > > > > if(region.get(key) != null) > > return region.get(key) > > otherwise > > doTheWork() > > region.put(result) > > return result > > > > It also ensures that if a CachingWorker is in the middle of doing the > work > > for the same region and key, the second (or Nth) CachingWorker will > wait > > and > > use the results from that instead of doing the get/work/put again. > > > > Using JCS to do this might look like: > > > > final String key = "some:key"; > > MyObject myObject = null; > > JCS myRegion = JCS.getInstance("myRegion"); > > if((myObject = (MyObject) myRegion.get(key)) == null){ > > myObject = makeSomeObject(key); > > myRegion.put(key, myObject); > > } > > > > With the caching worker it's: > > > > final String key = "some:key"; > > CachingWorker worker = new CachingWorker("myRegion", key) { > > public Object doWork() throws Exception { > > return makeSomeObject(key); > > } > > }; > > MyObject myObject = (MyObject) worker.getResult(); > > > > The advantage is with the CachingWorker, if two (or more) threads > execute > > this code in parallel, only one will do the work, while the second > > CachingWorker waits, and mooches off the result of the first. > > > > I stuck it in the org.apache.jcs package in my project because it's > just > > an > > advanced interface for org.apache.jcs.JCS and has no dependencies on > > anything but org.apache.jcs.JCS and commons.logging. > > > > Here's the code. It's well javadoced. Of course I'd be happy to commit > it > > myself if you want. > > > > /* > > * Created on Oct 8, 2003 > > * > > */ > > package org.apache.jcs; > > import java.io.Serializable; > > import java.util.HashMap; > > import java.util.Map; > > import org.apache.commons.logging.Log; > > import org.apache.commons.logging.LogFactory; > > /** > > * Utility class to encapsulate doing a piece of work, and caching the > > results > > * in JCS. Simply implement this class and override protected Object > > doWork(), > > * and do the work in there, returning the object to be cached. Then > call > > * .getResult() to get the result of the work. If the object isn't > > allready > > in > > * the Cache, doWork() will get called, and the result will be put > into > > the > > * cache. If the object is allready in cache, the cached result will > be > > returned > > * instead. As an added bonus, multiple CachingWorkers with the same > > region, > > * group, and key won't do the work multiple times: The first > > CachingWorker > > to > > * get started will do the work, and all subsequent workers with the > same > > * region, group, and key will wait on the first one and use his > resulting > > work > > * instead of doing the work themselves. > > * > > * This is ideal when the work being done is a query to the database > where > > the > > * results may take time to be retrieved. > > * > > * For example: <br> > > * > > * <code> > > * CachingWorker cachingWorker = new CachingWorker("example > region", > > aKey) {<br> > > * public Object doWork() throws Exception { <br> > > * // Do some (DB?) work here which results in a list <br> > > * // This only happens if the cache dosn't have a item in > this > > region for aKey <br> > > * // Note this is especially useful with Hibernate, which > will > > cache indiviual <br> > > * // Objects, but not entire query result sets. <br> > > * List results = query.list(); <br> > > * // Whatever we return here get's cached with aKey, and > future > > calls to <br> > > * // getResult() on a CachedWorker with the same region and > key > > will return that instead. <br> > > * return results; <br> > > * } <br> > > * }; <br> > > * List results = (List) cachingWorker.getResult();<br> > > * </code> > > * > > * This is essentially the same as doing: JCS jcs = > > JCS.getInstance("example > > * region"); List results = (List) jcs.get(aKey); if(results != null){ > > //do > > the > > * work here results = query.list(); jcs.put(aKey, results); } > > * > > * > > * But has the added benifit of the work-load sharing; under normal > > * circumstances if multiple threads all tried to do the same query at > the > > same > > * time, the same query would happen multiple times on the database, > and > > the > > * resulting object would get put into JCS multiple times. > > * > > * Using the Caching worker eliminates this senario entirely. > > * > > * @author Travis Savo > > */ > > public abstract class CachingWorker { > > private static final Log logger = > > LogFactory.getLog(CachingWorker.class); > > /** > > * Object to hold the result of the work. > > */ > > private Object result = null; > > public boolean wasCached = false; > > /** > > * Map to hold who's doing work presently. > > */ > > private static volatile Map map = new HashMap(); > > /** > > * Boolean to let us know if we need to wait or if it's > finished. > > */ > > private volatile boolean finished = false; > > /** > > * Region for the JCS cache. > > */ > > private String region; > > /** > > * Key for caching the results with. > > */ > > private Serializable key; > > /** > > * Optional Group to store the result under. > > */ > > private String group = null; > > /** > > * Constructor which takes a region and a key, but no group. > > * > > * @param aName > > * The Region to use for the JCS cache. > > * @param aKey > > * The key to store the result under. > > */ > > public CachingWorker(String aRegion, Serializable aKey) { > > this(aRegion, aKey, null); > > } > > /** > > * Constructor which takes a region, a key, and a group. > > * > > * @param aName > > * The Region to use for the JCS cache. > > * @param aKey > > * The key to store the result under. > > * @param aGroup > > * The group to store the result under. > > */ > > public CachingWorker(String aRegion, Serializable aKey, String > > aGroup) { > > region = aRegion; > > key = aKey; > > group = aGroup; > > finished = false; > > } > > /** > > * Abstract method to implement for the case where the object > has > > not been > > * cached yet, and we need to get it from somewhere else and > stick > > the result > > * in the cache. > > * > > * You should not be calling this yourself! Call getResult() > > instead. > > * > > * @return The result of doing the work to be cached and > returned in > > * getResult() > > * @throws Exception > > * If something goes wrong, throw an Exception and > nothing > > will get > > * cached. > > */ > > protected abstract Object doWork() throws Exception; > > /** > > * Getter for the region of the JCS Cache. > > * > > * @return The JCS region in which the result will be cached. > > */ > > public String getRegion() { > > return region; > > } > > /** > > * Getter for the key used to store the result of doing the work > in > > JCS. > > * > > * @return The key used to cache the result of the work. > > */ > > public Serializable getKey() { > > return key; > > } > > /** > > * Getter for the group used to store the result of doing the > work > > in JCS. > > * > > * @return The key group used to cache the result of the work > (could > > be null). > > */ > > public String getGroup() { > > return group; > > } > > /** > > * Gets the cached result for this region/key OR does the work > and > > caches the > > * result, returning the result. If the result has not been > cached > > yet, this > > * calls doWork() to do the work and cache the result. > > * > > * This is also an opertunity to do any post processing of the > > result in your > > * CachedWorker implementation. > > * > > * @return The result of doing the work, or the cached result. > > * @throws Exception > > * Throws an exception if anything goes wrong while > doing > > the work. > > */ > > public Object getResult() throws Exception { > > return run(); > > } > > /** > > * Try and get the object from the cache, and if it's not there, > do > > the work > > * and cache it. This also ensures that only one CachedWorker is > > doing the > > * work and subsequent calls to a CachedWorker with identical > > region/key/group > > * will wait on the results of this call. > > * > > * @return Either the result of doing the work, or the cached > > result. > > * @throws Exception > > * If something goes wrong while doing the work, throw > an > > exception. > > */ > > private Object run() throws Exception { > > long start = 0; > > long dbTime = 0; > > CachingWorker thread = null; > > synchronized (map) { > > //Check to see if we allready have a thread > doing > > this work. > > thread = (CachingWorker) map.get(getRegion() + > > getKey()); > > if (thread == null) { > > //If not, add ourselves as the Worker so > > //calls in another thread will use this > > worker's result > > map.put(getRegion() + getKey(), this); > > } > > } > > if (thread != null) { > > synchronized (thread) { > > if (logger.isDebugEnabled()) { > > logger.debug("Found a worker > > allready doing this work (" + thread.getRegion() + ":" + > thread.getKey() + > > ")."); > > } > > if (!thread.finished) { > > thread.wait(); > > } > > if (logger.isDebugEnabled()) { > > logger.debug("Another thread > > finished our work for us. Using thoes results instead. (" + > > thread.getRegion() + ":" + thread.getKey() + ")."); > > } > > //Get the result and return it. > > result = thread.result; > > wasCached = thread.wasCached; > > return result; > > } > > } > > //Do the work > > try { > > if (logger.isDebugEnabled()) { > > logger.debug(getRegion() + " is doing > the > > work."); > > } > > result = null; > > //Get the cache > > JCS cache = JCS.getInstance(getRegion()); > > //Try to get the item from the cache > > if (group != null) { > > result = cache.getFromGroup(getKey(), > > group); > > } else { > > result = cache.get(getKey()); > > } > > //If the cache dosn't have it, do the work. > > wasCached = true; > > if (result == null) { > > wasCached = false; > > result = doWork(); > > if (logger.isDebugEnabled()) { > > logger.debug("Work Done, > caching: > > key:" + getKey() + ", group:" + getGroup() + ", result:" + result + > "."); > > } > > //Stick the result of the work in the > cache. > > if (group != null) { > > cache.putInGroup(getKey(), > group, > > result); > > } else { > > cache.put(getKey(), result); > > } > > } > > //return the result > > return result; > > } finally { > > if (logger.isDebugEnabled()) { > > logger.debug(getRegion() + ":" + > getKey() + > > " entered finally."); > > } > > synchronized (map) { > > //Remove ourselves as the worker. > > map.remove(getRegion() + getKey()); > > synchronized (this) { > > finished = true; > > //Wake everyone waiting on us > > notifyAll(); > > } > > } > > } > > } > > } > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > For additional commands, e-mail: > [EMAIL PROTECTED] > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
