1 // 2 // ======================================================================== 3 // Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd. 4 // ------------------------------------------------------------------------ 5 // All rights reserved. This program and the accompanying materials 6 // are made available under the terms of the Eclipse Public License v1.0 7 // and Apache License v2.0 which accompanies this distribution. 8 // 9 // The Eclipse Public License is available at 10 // http://www.eclipse.org/legal/epl-v10.html 11 // 12 // The Apache License v2.0 is available at 13 // http://www.opensource.org/licenses/apache2.0.php 14 // 15 // You may elect to redistribute this code under either of these licenses. 16 // ======================================================================== 17 // 18 19 package org.eclipse.jetty.nosql; 20 21 import java.util.ArrayList; 22 import java.util.concurrent.ConcurrentHashMap; 23 import java.util.concurrent.ConcurrentMap; 24 25 import javax.servlet.http.HttpServletRequest; 26 27 import org.eclipse.jetty.server.SessionManager; 28 import org.eclipse.jetty.server.session.AbstractSession; 29 import org.eclipse.jetty.server.session.AbstractSessionManager; 30 import org.eclipse.jetty.util.log.Log; 31 import org.eclipse.jetty.util.log.Logger; 32 33 public abstract class NoSqlSessionManager extends AbstractSessionManager implements SessionManager 34 { 35 private final static Logger __log = Log.getLogger("org.eclipse.jetty.server.session"); 36 37 protected final ConcurrentMap<String,NoSqlSession> _sessions=new ConcurrentHashMap<String,NoSqlSession>(); 38 39 private int _stalePeriod=0; 40 private int _savePeriod=0; 41 private int _idlePeriod=-1; 42 private boolean _invalidateOnStop; 43 private boolean _saveAllAttributes; 44 45 /* ------------------------------------------------------------ */ 46 /* (non-Javadoc) 47 * @see org.eclipse.jetty.server.session.AbstractSessionManager#doStart() 48 */ 49 @Override 50 public void doStart() throws Exception 51 { 52 super.doStart(); 53 54 } 55 56 /* ------------------------------------------------------------ */ 57 @Override 58 protected void addSession(AbstractSession session) 59 { 60 if (isRunning()) 61 _sessions.put(session.getClusterId(),(NoSqlSession)session); 62 } 63 64 /* ------------------------------------------------------------ */ 65 @Override 66 public AbstractSession getSession(String idInCluster) 67 { 68 NoSqlSession session = _sessions.get(idInCluster); 69 70 __log.debug("getSession: " + session ); 71 72 if (session==null) 73 { 74 session=loadSession(idInCluster); 75 76 if (session!=null) 77 { 78 NoSqlSession race=_sessions.putIfAbsent(idInCluster,session); 79 if (race!=null) 80 { 81 session.willPassivate(); 82 session.clearAttributes(); 83 session=race; 84 } 85 } 86 } 87 88 return session; 89 } 90 91 /* ------------------------------------------------------------ */ 92 @Override 93 protected void invalidateSessions() throws Exception 94 { 95 // Invalidate all sessions to cause unbind events 96 ArrayList<NoSqlSession> sessions=new ArrayList<NoSqlSession>(_sessions.values()); 97 int loop=100; 98 while (sessions.size()>0 && loop-->0) 99 { 100 // If we are called from doStop 101 if (isStopping()) 102 { 103 // Then we only save and remove the session - it is not invalidated. 104 for (NoSqlSession session : sessions) 105 { 106 session.save(false); 107 removeSession(session,false); 108 } 109 } 110 else 111 { 112 for (NoSqlSession session : sessions) 113 session.invalidate(); 114 } 115 116 // check that no new sessions were created while we were iterating 117 sessions=new ArrayList<NoSqlSession>(_sessions.values()); 118 } 119 } 120 121 /* ------------------------------------------------------------ */ 122 @Override 123 protected AbstractSession newSession(HttpServletRequest request) 124 { 125 long created=System.currentTimeMillis(); 126 return new NoSqlSession(this,request); 127 } 128 129 /* ------------------------------------------------------------ */ 130 @Override 131 protected boolean removeSession(String idInCluster) 132 { 133 synchronized (this) 134 { 135 NoSqlSession session = _sessions.remove(idInCluster); 136 137 try 138 { 139 if (session != null) 140 { 141 return remove(session); 142 } 143 } 144 catch (Exception e) 145 { 146 __log.warn("Problem deleting session id=" + idInCluster,e); 147 } 148 149 return session != null; 150 } 151 } 152 153 /* ------------------------------------------------------------ */ 154 protected void invalidateSession( String idInCluster ) 155 { 156 synchronized (this) 157 { 158 NoSqlSession session = _sessions.remove(idInCluster); 159 160 try 161 { 162 if (session != null) 163 { 164 remove(session); 165 } 166 } 167 catch (Exception e) 168 { 169 __log.warn("Problem deleting session id=" + idInCluster,e); 170 } 171 } 172 173 /* 174 * ought we not go to cluster and mark it invalid? 175 */ 176 177 } 178 179 180 /* ------------------------------------------------------------ */ 181 /** 182 * The State Period is the maximum time in seconds that an in memory session is allows to be stale: 183 * <ul> 184 * <li>If this period is exceeded, the DB will be checked to see if a more recent version is available.</li> 185 * <li>If the state period is set to a value < 0, then no staleness check will be made.</li> 186 * <li>If the state period is set to 0, then a staleness check is made whenever the active request count goes from 0 to 1.</li> 187 * </ul> 188 * @return the stalePeriod in seconds 189 */ 190 public int getStalePeriod() 191 { 192 return _stalePeriod; 193 } 194 195 /* ------------------------------------------------------------ */ 196 /** 197 * The State Period is the maximum time in seconds that an in memory session is allows to be stale: 198 * <ul> 199 * <li>If this period is exceeded, the DB will be checked to see if a more recent version is available.</li> 200 * <li>If the state period is set to a value < 0, then no staleness check will be made.</li> 201 * <li>If the state period is set to 0, then a staleness check is made whenever the active request count goes from 0 to 1.</li> 202 * </ul> 203 * @param stalePeriod the stalePeriod in seconds 204 */ 205 public void setStalePeriod(int stalePeriod) 206 { 207 _stalePeriod = stalePeriod; 208 } 209 210 /* ------------------------------------------------------------ */ 211 /** 212 * The Save Period is the time in seconds between saves of a dirty session to the DB. 213 * When this period is exceeded, the a dirty session will be written to the DB: <ul> 214 * <li>a save period of -2 means the session is written to the DB whenever setAttribute is called.</li> 215 * <li>a save period of -1 means the session is never saved to the DB other than on a shutdown</li> 216 * <li>a save period of 0 means the session is written to the DB whenever the active request count goes from 1 to 0.</li> 217 * <li>a save period of 1 means the session is written to the DB whenever the active request count goes from 1 to 0 and the session is dirty.</li> 218 * <li>a save period of > 1 means the session is written after that period in seconds of being dirty.</li> 219 * </ul> 220 * @return the savePeriod -2,-1,0,1 or the period in seconds >=2 221 */ 222 public int getSavePeriod() 223 { 224 return _savePeriod; 225 } 226 227 /* ------------------------------------------------------------ */ 228 /** 229 * The Save Period is the time in seconds between saves of a dirty session to the DB. 230 * When this period is exceeded, the a dirty session will be written to the DB: <ul> 231 * <li>a save period of -2 means the session is written to the DB whenever setAttribute is called.</li> 232 * <li>a save period of -1 means the session is never saved to the DB other than on a shutdown</li> 233 * <li>a save period of 0 means the session is written to the DB whenever the active request count goes from 1 to 0.</li> 234 * <li>a save period of 1 means the session is written to the DB whenever the active request count goes from 1 to 0 and the session is dirty.</li> 235 * <li>a save period of > 1 means the session is written after that period in seconds of being dirty.</li> 236 * </ul> 237 * @param savePeriod the savePeriod -2,-1,0,1 or the period in seconds >=2 238 */ 239 public void setSavePeriod(int savePeriod) 240 { 241 _savePeriod = savePeriod; 242 } 243 244 /* ------------------------------------------------------------ */ 245 /** 246 * The Idle Period is the time in seconds before an in memory session is passivated. 247 * When this period is exceeded, the session will be passivated and removed from memory. If the session was dirty, it will be written to the DB. 248 * If the idle period is set to a value < 0, then the session is never idled. 249 * If the save period is set to 0, then the session is idled whenever the active request count goes from 1 to 0. 250 * @return the idlePeriod 251 */ 252 public int getIdlePeriod() 253 { 254 return _idlePeriod; 255 } 256 257 /* ------------------------------------------------------------ */ 258 /** 259 * The Idle Period is the time in seconds before an in memory session is passivated. 260 * When this period is exceeded, the session will be passivated and removed from memory. If the session was dirty, it will be written to the DB. 261 * If the idle period is set to a value < 0, then the session is never idled. 262 * If the save period is set to 0, then the session is idled whenever the active request count goes from 1 to 0. 263 * @param idlePeriod the idlePeriod in seconds 264 */ 265 public void setIdlePeriod(int idlePeriod) 266 { 267 _idlePeriod = idlePeriod; 268 } 269 270 /* ------------------------------------------------------------ */ 271 /** 272 * Invalidate sessions when the session manager is stopped otherwise save them to the DB. 273 * @return the invalidateOnStop 274 */ 275 public boolean isInvalidateOnStop() 276 { 277 return _invalidateOnStop; 278 } 279 280 /* ------------------------------------------------------------ */ 281 /** 282 * Invalidate sessions when the session manager is stopped otherwise save them to the DB. 283 * @param invalidateOnStop the invalidateOnStop to set 284 */ 285 public void setInvalidateOnStop(boolean invalidateOnStop) 286 { 287 _invalidateOnStop = invalidateOnStop; 288 } 289 290 /* ------------------------------------------------------------ */ 291 /** 292 * Save all attributes of a session or only update the dirty attributes. 293 * @return the saveAllAttributes 294 */ 295 public boolean isSaveAllAttributes() 296 { 297 return _saveAllAttributes; 298 } 299 300 /* ------------------------------------------------------------ */ 301 /** 302 * Save all attributes of a session or only update the dirty attributes. 303 * @param saveAllAttributes the saveAllAttributes to set 304 */ 305 public void setSaveAllAttributes(boolean saveAllAttributes) 306 { 307 _saveAllAttributes = saveAllAttributes; 308 } 309 310 /* ------------------------------------------------------------ */ 311 @Override 312 public void renewSessionId(String oldClusterId, String oldNodeId, String newClusterId, String newNodeId) 313 { 314 315 // Take the old session out of the list of sessions 316 // Change to the new id 317 // Put it back into the list of sessions 318 // Update permanent storage 319 320 synchronized (this) 321 { 322 try 323 { 324 NoSqlSession session = _sessions.remove(oldClusterId); 325 update (session, newClusterId, newNodeId); 326 session.setClusterId(newClusterId); 327 session.setNodeId(newNodeId); 328 _sessions.put(newClusterId, session); 329 } 330 catch (Exception e) 331 { 332 __log.warn(e); 333 } 334 } 335 } 336 337 338 /* ------------------------------------------------------------ */ 339 abstract protected NoSqlSession loadSession(String clusterId); 340 341 /* ------------------------------------------------------------ */ 342 abstract protected Object save(NoSqlSession session,Object version, boolean activateAfterSave); 343 344 /* ------------------------------------------------------------ */ 345 abstract protected Object refresh(NoSqlSession session, Object version); 346 347 /* ------------------------------------------------------------ */ 348 abstract protected boolean remove(NoSqlSession session); 349 350 /* ------------------------------------------------------------ */ 351 abstract protected void update(NoSqlSession session, String newClusterId, String newNodeId) throws Exception; 352 353 }