2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
5 package org.opendaylight.controller.clustersession.impl;
7 import java.util.ArrayList;
8 import java.util.Collection;
9 import java.util.EnumSet;
10 import java.util.Enumeration;
11 import java.util.HashMap;
12 import java.util.concurrent.ConcurrentMap;
14 import org.apache.catalina.Session;
15 import org.apache.catalina.util.SessionIdGenerator;
16 import org.opendaylight.controller.clustering.services.CacheConfigException;
17 import org.opendaylight.controller.clustering.services.CacheExistException;
18 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
19 import org.opendaylight.controller.clustering.services.IClusterServices;
20 import org.opendaylight.controller.clustersession.ClusterSession;
21 import org.opendaylight.controller.clustersession.ClusterSessionData;
22 import org.opendaylight.controller.clustersession.ClusterSessionManager;
23 import org.opendaylight.controller.clustersession.ClusterSessionUtil;
24 import org.opendaylight.controller.clustersession.service.ClusterSessionService;
25 import org.osgi.framework.BundleContext;
26 import org.osgi.framework.FrameworkUtil;
27 import org.osgi.framework.ServiceReference;
28 import org.osgi.util.tracker.ServiceTracker;
29 import org.osgi.util.tracker.ServiceTrackerCustomizer;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
34 * Implementation to persist and retrieve session data from infinispan cache
35 * @author harman singh
38 public class ClusterSessionServiceImpl implements ClusterSessionService,
39 ServiceTrackerCustomizer<IClusterGlobalServices, IClusterGlobalServices>{
41 private IClusterGlobalServices clusterGlobalServices = null;
42 private static final Logger LOGGER = LoggerFactory.getLogger(ClusterSessionServiceImpl.class);
43 private ConcurrentMap<String, ClusterSessionData> sessions = null;
44 private static final String SESSION_CACHE = "customSessionManager.sessionData";
45 private ClusterSessionManager manager = null;
46 private SessionIdGenerator sessionIdGenerator = null;
47 private BundleContext context = null;
48 private ServiceTracker<IClusterGlobalServices, IClusterGlobalServices> clusterTracker;
49 public ClusterSessionServiceImpl(ClusterSessionManager manager) {
50 this.manager = manager;
53 * This method initialize the cluster service of opendaylight and
54 * create a cache map in infinispan
58 public void startInternal(SessionIdGenerator sessionIdGenerator){
59 this.sessionIdGenerator = sessionIdGenerator;
60 context = FrameworkUtil.getBundle(ClusterSessionManager.class).getBundleContext();
66 * Removes the cluster service tracker while shut down
69 public void stopInternal(){
70 if(clusterTracker != null){
71 clusterTracker.close();
78 public Session findSession(final String id){
82 if(sessions == null) {
83 LOGGER.debug("Session cache not present, try to create.");
87 ClusterSessionData sessionData = sessions.get(id);
88 if(sessionData != null) {
89 LOGGER.debug("SESSION FOUND : ", id);
91 LOGGER.debug("SESSION NOTFOUND : ", id);
93 return ClusterSessionUtil.getDeserializedSession(sessionData, this, this.manager);
100 public Session[] findSessions() {
101 if(sessions == null) {
102 LOGGER.debug("Session cache not present, try to create.");
104 return new Session[0];
106 Collection<ClusterSessionData> sessionDataList = sessions.values();
107 ArrayList<ClusterSession> sessionList = new ArrayList<ClusterSession>();
108 for(ClusterSessionData sessionData : sessionDataList){
109 sessionList.add(ClusterSessionUtil.getDeserializedSession(sessionData, this, this.manager));
111 return sessionList.toArray(new Session[0]);
118 public void removeSession(final String id){
119 if(sessions == null) {
120 LOGGER.debug("Session cache not present, try to create.");
131 public void expireSession(final String id){
132 if(sessions == null) {
133 LOGGER.debug("Session cache not present, try to create.");
137 ClusterSessionData sessionData = sessions.get(id);
138 if(sessionData != null) {
139 sessionData.getSession().expire();
148 public Session createSession(final String sessionId){
149 if(sessions == null) {
150 LOGGER.debug("Session cache not present, try to create.");
154 Session session = createEmptySession();
155 session.setNew(true);
156 session.setValid(true);
157 session.setCreationTime(System.currentTimeMillis());
158 String id = sessionId;
160 id = generateSessionId();
170 public void addSession(final ClusterSession session){
171 if(sessions == null) {
172 LOGGER.debug("Session cache not present, try to create.");
176 ClusterSessionData sessionData = ClusterSessionUtil.getSerializableSession(session);
177 sessions.put(session.getId(), sessionData);
184 public Session createEmptySession(){
185 return getNewSession();
189 * Returns information about the session with the given session id.
191 * <p>The session information is organized as a HashMap, mapping
192 * session attribute names to the String representation of their values.
194 * @param sessionId Session id
196 * @return HashMap mapping session attribute names to the String
197 * representation of their values, or null if no session with the
198 * specified id exists, or if the session does not have any attributes
200 public HashMap<String, String> getSession(String sessionId) {
201 if(sessions == null) {
202 LOGGER.debug("Session cache not present, try to create.");
206 ClusterSessionData sessionData = sessions.get(sessionId);
207 if (sessionData == null) {
210 ClusterSession s = ClusterSessionUtil.getDeserializedSession(sessionData, this, this.manager);
211 Enumeration<String> ee = s.getAttributeNames();
212 if (ee == null || !ee.hasMoreElements()) {
215 HashMap<String, String> map = new HashMap<String, String>();
216 while (ee.hasMoreElements()) {
217 String attrName = ee.nextElement();
218 map.put(attrName, s.getAttribute(attrName).toString());
227 public void updateSession(ClusterSession session) {
228 if(sessions == null) {
229 LOGGER.debug("Session cache not present, try to create.");
233 if(session.getId() != null && sessions.get(session.getId()) != null){
234 ClusterSessionData sessionData = ClusterSessionUtil.getSerializableSession(session);
235 sessions.put(session.getId(), sessionData);
240 public IClusterGlobalServices addingService(ServiceReference<IClusterGlobalServices> reference) {
241 if (clusterGlobalServices == null) {
242 this.clusterGlobalServices = context.getService(reference);
244 return clusterGlobalServices;
250 public void modifiedService(ServiceReference<IClusterGlobalServices> reference, IClusterGlobalServices service) {
251 // This method is added from ServiceTracker interface, We don't have to modify service.
255 public void removedService(ServiceReference<IClusterGlobalServices> reference, IClusterGlobalServices service) {
256 if (clusterGlobalServices == service) {
257 clusterGlobalServices = null;
262 * Return an instance of Standard Session object with current session manager
264 private ClusterSession getNewSession() {
265 return new ClusterSession(this.manager, this);
269 * Generate and return a new session identifier.
271 private String generateSessionId() {
272 String result = null;
274 result = sessionIdGenerator.generateSessionId();
275 } while (sessions.containsKey(result));
279 private void createCache() {
285 * This is a fragment bundle, so We can't use Activator to set Service.
286 * This is the alternative to get registered clustered service
288 private void getClusterService(){
289 if (context != null) {
290 clusterTracker = new ServiceTracker<>(context, IClusterGlobalServices.class, this);
291 clusterTracker.open();
296 * Allocate space in infinispan to persist session data
298 private void allocateCache() {
299 if (clusterGlobalServices == null) {
300 LOGGER.trace("un-initialized clusterGlobalService, can't create cache");
304 clusterGlobalServices.createCache(SESSION_CACHE,
305 EnumSet.of(IClusterServices.cacheMode.SYNC , IClusterServices.cacheMode.TRANSACTIONAL));
307 } catch (CacheConfigException cce) {
308 LOGGER.error("Cache configuration invalid - check cache mode", cce.toString());
309 } catch (CacheExistException ce) {
310 LOGGER.debug("Skipping cache creation as already present", ce.toString());
315 * Fetch cached session data map object from infinispan
317 @SuppressWarnings("unchecked")
318 private void retrieveCache(){
319 if (clusterGlobalServices == null) {
320 LOGGER.trace("un-initialized clusterGlobalService, can't retrieve cache");
323 sessions = (ConcurrentMap<String, ClusterSessionData>)clusterGlobalServices.getCache(SESSION_CACHE);
324 if(sessions == null){
325 LOGGER.warn("Failed to get session cache");