001: package org.shiftone.cache.decorator.cluster;
002:
003: import org.shiftone.cache.Cache;
004: import org.shiftone.cache.CacheException;
005: import org.shiftone.cache.CacheFactory;
006: import org.shiftone.cache.util.Log;
007: import org.shiftone.cache.util.WeakMap;
008:
009: import java.util.Random;
010:
011: /**
012: * @version $Revision: 1.12 $
013: * @author <a href="mailto:jeff@shiftone.org">Jeff Drost</a>
014: */
015: public class ClusterCacheFactory implements CacheFactory {
016:
017: private static final Log LOG = new Log(ClusterCacheFactory.class);
018: private static final Random random = new Random();
019: public static final String DEFAULT_BUS_NAME = "shiftone-cache";
020: private WeakMap registeredCacheMap = new WeakMap();
021: private final long instanceId = random.nextLong();
022: private ClusterBus bus;
023: private CacheFactory delegate = null; // configured
024: private String channelProperties = ""; // configured
025: private String busName = DEFAULT_BUS_NAME; // configured
026:
027: private void init() throws CacheException {
028:
029: // if the bus has not been initialized, do so now
030: if (bus == null) {
031: try {
032: bus = new ClusterBus(this );
033: } catch (Exception e) {
034: throw new CacheException(
035: "error initializing JGroups NotificationBus", e);
036: }
037: }
038: }
039:
040: public Cache newInstance(String cacheName,
041: long timeoutMilliSeconds, int maxSize) {
042:
043: Cache delegateCache;
044: ClusterCache clusterCache;
045:
046: try {
047: init();
048:
049: clusterCache = getRegisteredCache(cacheName);
050:
051: // if another cache of the same name has been registered
052: // then return it. The down side of this is that the second
053: // version time the cache is returned, the timeout and max size
054: // has no effect on the returned cache.
055: // Also, this class does not extends AbstractDecoratorCacheFactory
056: // because it needs to decide if the delegate cache should be
057: // created.
058: if (clusterCache == null) {
059: delegateCache = delegate.newInstance(cacheName,
060: timeoutMilliSeconds, maxSize);
061: clusterCache = new ClusterCache(cacheName,
062: delegateCache, this );
063:
064: registerCache(cacheName, clusterCache);
065: } else {
066: LOG.info("returning existing cache : " + cacheName);
067: }
068: } catch (Exception e) {
069: throw new RuntimeException(
070: "unable to create cluster decorator");
071: }
072:
073: return clusterCache;
074: }
075:
076: private synchronized void registerCache(String cacheName,
077: ClusterCache clusterCache) {
078: registeredCacheMap.put(cacheName, clusterCache);
079: }
080:
081: private synchronized ClusterCache getRegisteredCache(
082: String cacheName) {
083: return (ClusterCache) registeredCacheMap.get(cacheName);
084: }
085:
086: public String getBusName() {
087: return busName;
088: }
089:
090: public void setBusName(String busName) {
091: this .busName = busName;
092: }
093:
094: public String getChannelProperties() {
095: return channelProperties;
096: }
097:
098: public void setChannelProperties(String channelProperties) {
099: this .channelProperties = channelProperties;
100: }
101:
102: public void setDelegate(CacheFactory delegate) {
103: this .delegate = delegate;
104: }
105:
106: public String toString() {
107: return "ClusterCacheFactory[" + busName + "]->" + delegate;
108: }
109:
110: //-----------------------------------------------------------
111: public void sendRemoveNotification(String cacheName, Object key) {
112: bus.sendNotification(new RemoveNotification(instanceId,
113: cacheName, key));
114: }
115:
116: public void sendClearNotification(String cacheName) {
117: bus.sendNotification(new ClearNotification(instanceId,
118: cacheName));
119: }
120:
121: public void handleNotification(Notification notification) {
122:
123: ClusterCache clusterCache;
124:
125: // don't process self notification
126: if (notification.getSenderInstanceId() != instanceId) {
127: clusterCache = getRegisteredCache(notification
128: .getCacheName());
129:
130: // if this factory doesn't have this cache, it isn't
131: // really possible to execute a notification on it
132: if (clusterCache != null) {
133: LOG.debug("execute : " + notification);
134: notification.execute(clusterCache.getCache());
135: }
136: }
137: }
138: }
|