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.geronimo.clustering.wadi;
018
019 import java.util.HashMap;
020 import java.util.HashSet;
021 import java.util.Iterator;
022 import java.util.Map;
023 import java.util.Set;
024 import java.util.concurrent.CopyOnWriteArrayList;
025
026 import org.apache.commons.logging.Log;
027 import org.apache.commons.logging.LogFactory;
028 import org.apache.geronimo.clustering.Node;
029 import org.apache.geronimo.clustering.Session;
030 import org.apache.geronimo.clustering.SessionAlreadyExistException;
031 import org.apache.geronimo.clustering.SessionListener;
032 import org.apache.geronimo.clustering.SessionManager;
033 import org.apache.geronimo.gbean.GBeanInfo;
034 import org.apache.geronimo.gbean.GBeanInfoBuilder;
035 import org.apache.geronimo.gbean.GBeanLifecycle;
036 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
037 import org.codehaus.wadi.core.assembler.StackContext;
038 import org.codehaus.wadi.core.manager.Manager;
039 import org.codehaus.wadi.core.manager.SessionMonitor;
040 import org.codehaus.wadi.group.Dispatcher;
041 import org.codehaus.wadi.group.Peer;
042 import org.codehaus.wadi.replication.strategy.BackingStrategyFactory;
043 import org.codehaus.wadi.servicespace.ServiceSpace;
044 import org.codehaus.wadi.servicespace.ServiceSpaceName;
045
046 /**
047 *
048 * @version $Rev$ $Date$
049 */
050 public class BasicWADISessionManager implements GBeanLifecycle, SessionManager, WADISessionManager {
051 private static final Log log = LogFactory.getLog(BasicWADISessionManager.class);
052
053 private final ClassLoader cl;
054 private final WADICluster cluster;
055 private final WADISessionManagerConfigInfo configInfo;
056 private final BackingStrategyFactory backingStrategyFactory;
057 private final CopyOnWriteArrayList<SessionListener> listeners;
058
059 private Manager manager;
060 private SessionMonitor sessionMonitor;
061 private ServiceSpace serviceSpace;
062
063
064 public BasicWADISessionManager(ClassLoader cl,
065 WADISessionManagerConfigInfo configInfo,
066 WADICluster cluster,
067 BackingStrategyFactory backingStrategyFactory) {
068 this.cl = cl;
069 this.configInfo = configInfo;
070 this.cluster = cluster;
071 this.backingStrategyFactory = backingStrategyFactory;
072
073 listeners = new CopyOnWriteArrayList<SessionListener>();
074 }
075
076 public void doStart() throws Exception {
077 Dispatcher underlyingDisp = cluster.getCluster().getDispatcher();
078
079 ServiceSpaceName serviceSpaceName = new ServiceSpaceName(configInfo.getServiceSpaceURI());
080 StackContext stackContext = new StackContext(cl,
081 serviceSpaceName,
082 underlyingDisp,
083 configInfo.getSessionTimeoutSeconds(),
084 configInfo.getNumPartitions(),
085 configInfo.getSweepInterval(),
086 backingStrategyFactory);
087 stackContext.build();
088
089 serviceSpace = stackContext.getServiceSpace();
090 manager = stackContext.getManager();
091
092 sessionMonitor = stackContext.getSessionMonitor();
093 sessionMonitor.addSessionListener(new SessionListenerAdapter());
094
095 serviceSpace.start();
096 }
097
098 public void doStop() throws Exception {
099 serviceSpace.stop();
100 }
101
102 public void doFail() {
103 try {
104 serviceSpace.stop();
105 } catch (Exception e) {
106 log.error(e);
107 }
108 }
109
110 public Session createSession(String sessionId) throws SessionAlreadyExistException {
111 org.codehaus.wadi.core.session.Session session;
112 try {
113 session = manager.createWithName(sessionId);
114 } catch (org.codehaus.wadi.core.manager.SessionAlreadyExistException e) {
115 throw new SessionAlreadyExistException("Session " + sessionId + " already exists", e);
116 }
117 return new WADISessionAdaptor(session);
118 }
119
120 public Manager getManager() {
121 return manager;
122 }
123
124 public Node getNode() {
125 return cluster.getLocalNode();
126 }
127
128 public Set<Node> getRemoteNodes() {
129 Map<Peer, RemoteNode> peerToRemoteNode = new HashMap<Peer, RemoteNode>();
130 Set<Node> clusterNodes = cluster.getRemoteNodes();
131 for (Iterator<Node> iterator = clusterNodes.iterator(); iterator.hasNext();) {
132 RemoteNode remoteNode = (RemoteNode) iterator.next();
133 peerToRemoteNode.put(remoteNode.getPeer(), remoteNode);
134 }
135
136 Set<Node> nodes = new HashSet<Node>();
137 Set<Peer> peers = serviceSpace.getHostingPeers();
138 for (Peer peer : peers) {
139 RemoteNode remoteNode = peerToRemoteNode.get(peer);
140 if (null == remoteNode) {
141 throw new AssertionError("remoteNode is null");
142 }
143 nodes.add(remoteNode);
144 }
145 return nodes;
146 }
147
148 public void registerListener(SessionListener listener) {
149 listeners.add(listener);
150 }
151
152 public void unregisterListener(SessionListener listener) {
153 listeners.remove(listener);
154 }
155
156 private void notifyInboundSessionMigration(org.codehaus.wadi.core.session.Session session) {
157 for (SessionListener listener : listeners) {
158 listener.notifyInboundSessionMigration(new WADISessionAdaptor(session));
159 }
160 }
161
162 private void notifyOutboundSessionMigration(org.codehaus.wadi.core.session.Session session) {
163 for (SessionListener listener : listeners) {
164 listener.notifyOutboundSessionMigration(new WADISessionAdaptor(session));
165 }
166 }
167
168 private void notifySessionDestruction(org.codehaus.wadi.core.session.Session session) {
169 for (SessionListener listener : listeners) {
170 listener.notifySessionDestruction(new WADISessionAdaptor(session));
171 }
172 }
173
174 private class SessionListenerAdapter implements org.codehaus.wadi.core.manager.SessionListener {
175
176 public void onSessionCreation(org.codehaus.wadi.core.session.Session session) {
177 }
178
179 public void onSessionDestruction(org.codehaus.wadi.core.session.Session session) {
180 notifySessionDestruction(session);
181 }
182
183 public void onInboundSessionMigration(org.codehaus.wadi.core.session.Session session) {
184 notifyInboundSessionMigration(session);
185 }
186
187 public void onOutbountSessionMigration(org.codehaus.wadi.core.session.Session session) {
188 notifyOutboundSessionMigration(session);
189 }
190
191 }
192
193 public static final GBeanInfo GBEAN_INFO;
194
195 public static final String GBEAN_ATTR_WADI_CONFIG_INFO = "wadiConfigInfo";
196
197 public static final String GBEAN_REF_CLUSTER = "Cluster";
198 public static final String GBEAN_REF_BACKING_STRATEGY_FACTORY = "BackingStrategyFactory";
199
200 static {
201 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic("WADI Session Manager",
202 BasicWADISessionManager.class, NameFactory.GERONIMO_SERVICE);
203
204 infoBuilder.addAttribute("classLoader", ClassLoader.class, false);
205 infoBuilder.addAttribute(GBEAN_ATTR_WADI_CONFIG_INFO, WADISessionManagerConfigInfo.class, true);
206
207 infoBuilder.addReference(GBEAN_REF_CLUSTER, WADICluster.class, NameFactory.GERONIMO_SERVICE);
208 infoBuilder.addReference(GBEAN_REF_BACKING_STRATEGY_FACTORY, BackingStrategyFactory.class,
209 NameFactory.GERONIMO_SERVICE);
210
211 infoBuilder.addInterface(SessionManager.class);
212 infoBuilder.addInterface(WADISessionManager.class);
213
214 infoBuilder.setConstructor(new String[] { "classLoader",
215 GBEAN_ATTR_WADI_CONFIG_INFO,
216 GBEAN_REF_CLUSTER,
217 GBEAN_REF_BACKING_STRATEGY_FACTORY });
218
219 GBEAN_INFO = infoBuilder.getBeanInfo();
220 }
221
222 public static GBeanInfo getGBeanInfo() {
223 return GBEAN_INFO;
224 }
225
226 }