001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.catalina.ha.session;
018:
019: import java.io.ByteArrayInputStream;
020: import java.io.IOException;
021:
022: import org.apache.catalina.LifecycleException;
023: import org.apache.catalina.Session;
024: import org.apache.catalina.ha.CatalinaCluster;
025: import org.apache.catalina.ha.ClusterManager;
026: import org.apache.catalina.ha.ClusterMessage;
027: import org.apache.catalina.session.StandardManager;
028: import org.apache.catalina.tribes.Channel;
029: import org.apache.catalina.tribes.io.ReplicationStream;
030: import org.apache.catalina.tribes.tipis.LazyReplicatedMap;
031:
032: /**
033: *@author Filip Hanik
034: *@version 1.0
035: */
036: public class BackupManager extends StandardManager implements
037: ClusterManager {
038: public static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory
039: .getLog(BackupManager.class);
040:
041: protected static long DEFAULT_REPL_TIMEOUT = 15000;//15 seconds
042:
043: /** Set to true if we don't want the sessions to expire on shutdown */
044: protected boolean mExpireSessionsOnShutdown = true;
045:
046: /**
047: * The name of this manager
048: */
049: protected String name;
050:
051: /**
052: * A reference to the cluster
053: */
054: protected CatalinaCluster cluster;
055:
056: /**
057: * Should listeners be notified?
058: */
059: private boolean notifyListenersOnReplication;
060: /**
061: *
062: */
063: private int mapSendOptions = Channel.SEND_OPTIONS_SYNCHRONIZED_ACK
064: | Channel.SEND_OPTIONS_USE_ACK;
065:
066: /**
067: * Constructor, just calls super()
068: *
069: */
070: public BackupManager() {
071: super ();
072: }
073:
074: //******************************************************************************/
075: // ClusterManager Interface
076: //******************************************************************************/
077:
078: public void messageDataReceived(ClusterMessage msg) {
079: }
080:
081: public boolean doDomainReplication() {
082: return false;
083: }
084:
085: /**
086: * @param sendClusterDomainOnly The sendClusterDomainOnly to set.
087: */
088: public void setDomainReplication(boolean sendClusterDomainOnly) {
089: }
090:
091: /**
092: * @return Returns the defaultMode.
093: */
094: public boolean isDefaultMode() {
095: return false;
096: }
097:
098: /**
099: * @param defaultMode The defaultMode to set.
100: */
101: public void setDefaultMode(boolean defaultMode) {
102: }
103:
104: public void setExpireSessionsOnShutdown(
105: boolean expireSessionsOnShutdown) {
106: mExpireSessionsOnShutdown = expireSessionsOnShutdown;
107: }
108:
109: public void setCluster(CatalinaCluster cluster) {
110: if (log.isDebugEnabled())
111: log
112: .debug("Cluster associated with SimpleTcpReplicationManager");
113: this .cluster = cluster;
114: }
115:
116: public boolean getExpireSessionsOnShutdown() {
117: return mExpireSessionsOnShutdown;
118: }
119:
120: /**
121: * Override persistence since they don't go hand in hand with replication for now.
122: */
123: public void unload() throws IOException {
124: }
125:
126: public ClusterMessage requestCompleted(String sessionId) {
127: if (!this .started)
128: return null;
129: LazyReplicatedMap map = (LazyReplicatedMap) sessions;
130: map.replicate(sessionId, false);
131: return null;
132: }
133:
134: //=========================================================================
135: // OVERRIDE THESE METHODS TO IMPLEMENT THE REPLICATION
136: //=========================================================================
137:
138: public Session createEmptySession() {
139: return new DeltaSession(this );
140: }
141:
142: public ClassLoader[] getClassLoaders() {
143: return ClusterManagerBase.getClassLoaders(this .container);
144: }
145:
146: /**
147: * Open Stream and use correct ClassLoader (Container) Switch
148: * ThreadClassLoader
149: *
150: * @param data
151: * @return The object input stream
152: * @throws IOException
153: */
154: public ReplicationStream getReplicationStream(byte[] data)
155: throws IOException {
156: return getReplicationStream(data, 0, data.length);
157: }
158:
159: public ReplicationStream getReplicationStream(byte[] data,
160: int offset, int length) throws IOException {
161: ByteArrayInputStream fis = new ByteArrayInputStream(data,
162: offset, length);
163: return new ReplicationStream(fis, getClassLoaders());
164: }
165:
166: public String getName() {
167: return this .name;
168: }
169:
170: /**
171: * Prepare for the beginning of active use of the public methods of this
172: * component. This method should be called after <code>configure()</code>,
173: * and before any of the public methods of the component are utilized.<BR>
174: * Starts the cluster communication channel, this will connect with the other nodes
175: * in the cluster, and request the current session state to be transferred to this node.
176: * @exception IllegalStateException if this component has already been
177: * started
178: * @exception LifecycleException if this component detects a fatal error
179: * that prevents this component from being used
180: */
181: public void start() throws LifecycleException {
182: if (this .started)
183: return;
184:
185: try {
186: cluster.registerManager(this );
187: CatalinaCluster catclust = (CatalinaCluster) cluster;
188: LazyReplicatedMap map = new LazyReplicatedMap(this ,
189: catclust.getChannel(), DEFAULT_REPL_TIMEOUT,
190: getMapName(), getClassLoaders());
191: map.setChannelSendOptions(mapSendOptions);
192: this .sessions = map;
193: super .start();
194: this .started = true;
195: } catch (Exception x) {
196: log.error("Unable to start BackupManager", x);
197: throw new LifecycleException(
198: "Failed to start BackupManager", x);
199: }
200: }
201:
202: public String getMapName() {
203: CatalinaCluster catclust = (CatalinaCluster) cluster;
204: String name = catclust.getManagerName(getName(), this ) + "-"
205: + "map";
206: if (log.isDebugEnabled())
207: log.debug("Backup manager, Setting map name to:" + name);
208: return name;
209: }
210:
211: /**
212: * Gracefully terminate the active use of the public methods of this
213: * component. This method should be the last one called on a given
214: * instance of this component.<BR>
215: * This will disconnect the cluster communication channel and stop the listener thread.
216: * @exception IllegalStateException if this component has not been started
217: * @exception LifecycleException if this component detects a fatal error
218: * that needs to be reported
219: */
220: public void stop() throws LifecycleException {
221:
222: LazyReplicatedMap map = (LazyReplicatedMap) sessions;
223: if (map != null) {
224: map.breakdown();
225: }
226: if (!this .started)
227: return;
228: try {
229: } catch (Exception x) {
230: log.error("Unable to stop BackupManager", x);
231: throw new LifecycleException(
232: "Failed to stop BackupManager", x);
233: } finally {
234: super .stop();
235: }
236: cluster.removeManager(this );
237:
238: }
239:
240: public void setDistributable(boolean dist) {
241: this .distributable = dist;
242: }
243:
244: public boolean getDistributable() {
245: return distributable;
246: }
247:
248: public void setName(String name) {
249: this .name = name;
250: }
251:
252: public boolean isNotifyListenersOnReplication() {
253: return notifyListenersOnReplication;
254: }
255:
256: public void setNotifyListenersOnReplication(
257: boolean notifyListenersOnReplication) {
258: this .notifyListenersOnReplication = notifyListenersOnReplication;
259: }
260:
261: public void setMapSendOptions(int mapSendOptions) {
262: this .mapSendOptions = mapSendOptions;
263: }
264:
265: /*
266: * @see org.apache.catalina.ha.ClusterManager#getCluster()
267: */
268: public CatalinaCluster getCluster() {
269: return cluster;
270: }
271:
272: public int getMapSendOptions() {
273: return mapSendOptions;
274: }
275:
276: public String[] getInvalidatedSessions() {
277: return new String[0];
278: }
279:
280: public ClusterManager cloneFromTemplate() {
281: BackupManager result = new BackupManager();
282: result.mExpireSessionsOnShutdown = mExpireSessionsOnShutdown;
283: result.name = "Clone-from-" + name;
284: result.cluster = cluster;
285: result.notifyListenersOnReplication = notifyListenersOnReplication;
286: result.mapSendOptions = mapSendOptions;
287: return result;
288: }
289:
290: }
|