001: /*
002: * Copyright (c) 2002-2003 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.oscache.plugins.clustersupport;
006:
007: import com.opensymphony.oscache.base.*;
008: import com.opensymphony.oscache.base.events.*;
009:
010: import org.apache.commons.logging.Log;
011: import org.apache.commons.logging.LogFactory;
012:
013: import java.util.Date;
014:
015: /**
016: * Implementation of a CacheEntryEventListener. It broadcasts the flush events
017: * across a cluster to other listening caches. Note that this listener cannot
018: * be used in conjection with session caches.
019: *
020: * @version $Revision: 254 $
021: * @author <a href="mailto:chris@swebtec.com">Chris Miller</a>
022: */
023: public abstract class AbstractBroadcastingListener implements
024: CacheEntryEventListener, LifecycleAware {
025: private final static Log log = LogFactory
026: .getLog(AbstractBroadcastingListener.class);
027:
028: /**
029: * The name to use for the origin of cluster events. Using this ensures
030: * events are not fired recursively back over the cluster.
031: */
032: protected static final String CLUSTER_ORIGIN = "CLUSTER";
033: protected Cache cache = null;
034:
035: public AbstractBroadcastingListener() {
036: if (log.isInfoEnabled()) {
037: log.info("AbstractBroadcastingListener registered");
038: }
039: }
040:
041: /**
042: * Event fired when an entry is flushed from the cache. This broadcasts
043: * the flush message to any listening nodes on the network.
044: */
045: public void cacheEntryFlushed(CacheEntryEvent event) {
046: if (!Cache.NESTED_EVENT.equals(event.getOrigin())
047: && !CLUSTER_ORIGIN.equals(event.getOrigin())) {
048: if (log.isDebugEnabled()) {
049: log.debug("cacheEntryFlushed called (" + event + ")");
050: }
051:
052: sendNotification(new ClusterNotification(
053: ClusterNotification.FLUSH_KEY, event.getKey()));
054: }
055: }
056:
057: /**
058: * Event fired when an entry is removed from the cache. This broadcasts
059: * the remove method to any listening nodes on the network, as long as
060: * this event wasn't from a broadcast in the first place.
061: */
062: public void cacheGroupFlushed(CacheGroupEvent event) {
063: if (!Cache.NESTED_EVENT.equals(event.getOrigin())
064: && !CLUSTER_ORIGIN.equals(event.getOrigin())) {
065: if (log.isDebugEnabled()) {
066: log.debug("cacheGroupFushed called (" + event + ")");
067: }
068:
069: sendNotification(new ClusterNotification(
070: ClusterNotification.FLUSH_GROUP, event.getGroup()));
071: }
072: }
073:
074: public void cachePatternFlushed(CachePatternEvent event) {
075: if (!Cache.NESTED_EVENT.equals(event.getOrigin())
076: && !CLUSTER_ORIGIN.equals(event.getOrigin())) {
077: if (log.isDebugEnabled()) {
078: log.debug("cachePatternFushed called (" + event + ")");
079: }
080:
081: sendNotification(new ClusterNotification(
082: ClusterNotification.FLUSH_PATTERN, event
083: .getPattern()));
084: }
085: }
086:
087: public void cacheFlushed(CachewideEvent event) {
088: if (!Cache.NESTED_EVENT.equals(event.getOrigin())
089: && !CLUSTER_ORIGIN.equals(event.getOrigin())) {
090: if (log.isDebugEnabled()) {
091: log.debug("cacheFushed called (" + event + ")");
092: }
093:
094: sendNotification(new ClusterNotification(
095: ClusterNotification.FLUSH_CACHE, event.getDate()));
096: }
097: }
098:
099: // --------------------------------------------------------
100: // The remaining events are of no interest to this listener
101: // --------------------------------------------------------
102: public void cacheEntryAdded(CacheEntryEvent event) {
103: }
104:
105: public void cacheEntryRemoved(CacheEntryEvent event) {
106: }
107:
108: public void cacheEntryUpdated(CacheEntryEvent event) {
109: }
110:
111: public void cacheGroupAdded(CacheGroupEvent event) {
112: }
113:
114: public void cacheGroupEntryAdded(CacheGroupEvent event) {
115: }
116:
117: public void cacheGroupEntryRemoved(CacheGroupEvent event) {
118: }
119:
120: public void cacheGroupRemoved(CacheGroupEvent event) {
121: }
122:
123: public void cacheGroupUpdated(CacheGroupEvent event) {
124: }
125:
126: /**
127: * Called by the cache administrator class when a cache is instantiated.
128: *
129: * @param cache the cache instance that this listener is attached to.
130: * @param config The cache's configuration details. This allows the event handler
131: * to initialize itself based on the cache settings, and also to receive <em>additional</em>
132: * settings that were part of the cache configuration but that the cache
133: * itself does not care about. If you are using <code>cache.properties</code>
134: * for your configuration, simply add any additional properties that your event
135: * handler requires and they will be passed through in this parameter.
136: *
137: * @throws InitializationException thrown when there was a problem initializing the
138: * listener. The cache administrator will log this error and disable the listener.
139: */
140: public void initialize(Cache cache, Config config)
141: throws InitializationException {
142: this .cache = cache;
143: }
144:
145: /**
146: * Handles incoming notification messages. This method should be called by the
147: * underlying broadcasting implementation when a message is received from another
148: * node in the cluster.
149: *
150: * @param message The incoming cluster notification message object.
151: */
152: public void handleClusterNotification(ClusterNotification message) {
153: if (cache == null) {
154: log
155: .warn("A cluster notification ("
156: + message
157: + ") was received, but no cache is registered on this machine. Notification ignored.");
158:
159: return;
160: }
161:
162: if (log.isInfoEnabled()) {
163: log.info("Cluster notification (" + message
164: + ") was received.");
165: }
166:
167: switch (message.getType()) {
168: case ClusterNotification.FLUSH_KEY:
169: cache
170: .flushEntry((String) message.getData(),
171: CLUSTER_ORIGIN);
172: break;
173: case ClusterNotification.FLUSH_GROUP:
174: cache
175: .flushGroup((String) message.getData(),
176: CLUSTER_ORIGIN);
177: break;
178: case ClusterNotification.FLUSH_PATTERN:
179: cache.flushPattern((String) message.getData(),
180: CLUSTER_ORIGIN);
181: break;
182: case ClusterNotification.FLUSH_CACHE:
183: cache.flushAll((Date) message.getData(), CLUSTER_ORIGIN);
184: break;
185: default:
186: log.error("The cluster notification (" + message
187: + ") is of an unknown type. Notification ignored.");
188: }
189: }
190:
191: /**
192: * Called when a cluster notification message is to be broadcast. Implementing
193: * classes should use their underlying transport to broadcast the message across
194: * the cluster.
195: *
196: * @param message The notification message to broadcast.
197: */
198: abstract protected void sendNotification(ClusterNotification message);
199: }
|