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 _preserveOnStop; 44 private boolean _saveAllAttributes; 45 46 /* ------------------------------------------------------------ */ 47 /* (non-Javadoc) 48 * @see org.eclipse.jetty.server.session.AbstractSessionManager#doStart() 49 */ 50 @Override 51 public void doStart() throws Exception 52 { 53 super.doStart(); 54 55 } 56 57 /* ------------------------------------------------------------ */ 58 @Override 59 protected void addSession(AbstractSession session) 60 { 61 if (isRunning()) 62 _sessions.put(session.getClusterId(),(NoSqlSession)session); 63 } 64 65 /* ------------------------------------------------------------ */ 66 @Override 67 public AbstractSession getSession(String idInCluster) 68 { 69 NoSqlSession session = _sessions.get(idInCluster); 70 71 __log.debug("getSession: " + session ); 72 73 if (session==null) 74 { 75 session=loadSession(idInCluster); 76 77 if (session!=null) 78 { 79 NoSqlSession race=_sessions.putIfAbsent(idInCluster,session); 80 if (race!=null) 81 { 82 session.willPassivate(); 83 session.clearAttributes(); 84 session=race; 85 } 86 } 87 } 88 89 return session; 90 } 91 92 /* ------------------------------------------------------------ */ 93 @Override 94 protected void invalidateSessions() throws Exception 95 { 96 // Invalidate all sessions to cause unbind events 97 ArrayList<NoSqlSession> sessions=new ArrayList<NoSqlSession>(_sessions.values()); 98 int loop=100; 99 while (sessions.size()>0 && loop-->0) 100 { 101 // If we are called from doStop 102 if (isStopping()) 103 { 104 // Then we only save and remove the session - it is not invalidated. 105 for (NoSqlSession session : sessions) 106 { 107 session.save(false); 108 109 if (!_preserveOnStop) { 110 removeSession(session,false); 111 } 112 } 113 } 114 else 115 { 116 for (NoSqlSession session : sessions) 117 session.invalidate(); 118 } 119 120 // check that no new sessions were created while we were iterating 121 sessions=new ArrayList<NoSqlSession>(_sessions.values()); 122 } 123 } 124 125 /* ------------------------------------------------------------ */ 126 @Override 127 protected AbstractSession newSession(HttpServletRequest request) 128 { 129 long created=System.currentTimeMillis(); 130 return new NoSqlSession(this,request); 131 } 132 133 /* ------------------------------------------------------------ */ 134 @Override 135 protected boolean removeSession(String idInCluster) 136 { 137 synchronized (this) 138 { 139 NoSqlSession session = _sessions.remove(idInCluster); 140 141 try 142 { 143 if (session != null) 144 { 145 return remove(session); 146 } 147 } 148 catch (Exception e) 149 { 150 __log.warn("Problem deleting session id=" + idInCluster,e); 151 } 152 153 return session != null; 154 } 155 } 156 157 /* ------------------------------------------------------------ */ 158 protected void invalidateSession( String idInCluster ) 159 { 160 synchronized (this) 161 { 162 NoSqlSession session = _sessions.remove(idInCluster); 163 164 try 165 { 166 if (session != null) 167 { 168 remove(session); 169 } 170 } 171 catch (Exception e) 172 { 173 __log.warn("Problem deleting session id=" + idInCluster,e); 174 } 175 } 176 177 /* 178 * ought we not go to cluster and mark it invalid? 179 */ 180 181 } 182 183 184 /* ------------------------------------------------------------ */ 185 /** 186 * The State Period is the maximum time in seconds that an in memory session is allows to be stale: 187 * <ul> 188 * <li>If this period is exceeded, the DB will be checked to see if a more recent version is available.</li> 189 * <li>If the state period is set to a value < 0, then no staleness check will be made.</li> 190 * <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> 191 * </ul> 192 * @return the stalePeriod in seconds 193 */ 194 public int getStalePeriod() 195 { 196 return _stalePeriod; 197 } 198 199 /* ------------------------------------------------------------ */ 200 /** 201 * The State Period is the maximum time in seconds that an in memory session is allows to be stale: 202 * <ul> 203 * <li>If this period is exceeded, the DB will be checked to see if a more recent version is available.</li> 204 * <li>If the state period is set to a value < 0, then no staleness check will be made.</li> 205 * <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> 206 * </ul> 207 * @param stalePeriod the stalePeriod in seconds 208 */ 209 public void setStalePeriod(int stalePeriod) 210 { 211 _stalePeriod = stalePeriod; 212 } 213 214 /* ------------------------------------------------------------ */ 215 /** 216 * The Save Period is the time in seconds between saves of a dirty session to the DB. 217 * When this period is exceeded, the a dirty session will be written to the DB: <ul> 218 * <li>a save period of -2 means the session is written to the DB whenever setAttribute is called.</li> 219 * <li>a save period of -1 means the session is never saved to the DB other than on a shutdown</li> 220 * <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> 221 * <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> 222 * <li>a save period of > 1 means the session is written after that period in seconds of being dirty.</li> 223 * </ul> 224 * @return the savePeriod -2,-1,0,1 or the period in seconds >=2 225 */ 226 public int getSavePeriod() 227 { 228 return _savePeriod; 229 } 230 231 /* ------------------------------------------------------------ */ 232 /** 233 * The Save Period is the time in seconds between saves of a dirty session to the DB. 234 * When this period is exceeded, the a dirty session will be written to the DB: <ul> 235 * <li>a save period of -2 means the session is written to the DB whenever setAttribute is called.</li> 236 * <li>a save period of -1 means the session is never saved to the DB other than on a shutdown</li> 237 * <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> 238 * <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> 239 * <li>a save period of > 1 means the session is written after that period in seconds of being dirty.</li> 240 * </ul> 241 * @param savePeriod the savePeriod -2,-1,0,1 or the period in seconds >=2 242 */ 243 public void setSavePeriod(int savePeriod) 244 { 245 _savePeriod = savePeriod; 246 } 247 248 /* ------------------------------------------------------------ */ 249 /** 250 * The Idle Period is the time in seconds before an in memory session is passivated. 251 * 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. 252 * If the idle period is set to a value < 0, then the session is never idled. 253 * If the save period is set to 0, then the session is idled whenever the active request count goes from 1 to 0. 254 * @return the idlePeriod 255 */ 256 public int getIdlePeriod() 257 { 258 return _idlePeriod; 259 } 260 261 /* ------------------------------------------------------------ */ 262 /** 263 * The Idle Period is the time in seconds before an in memory session is passivated. 264 * 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. 265 * If the idle period is set to a value < 0, then the session is never idled. 266 * If the save period is set to 0, then the session is idled whenever the active request count goes from 1 to 0. 267 * @param idlePeriod the idlePeriod in seconds 268 */ 269 public void setIdlePeriod(int idlePeriod) 270 { 271 _idlePeriod = idlePeriod; 272 } 273 274 /* ------------------------------------------------------------ */ 275 /** 276 * Invalidate sessions when the session manager is stopped otherwise save them to the DB. 277 * @return the invalidateOnStop 278 */ 279 public boolean isInvalidateOnStop() 280 { 281 return _invalidateOnStop; 282 } 283 284 /* ------------------------------------------------------------ */ 285 /** 286 * Preserve sessions when the session manager is stopped otherwise remove them from the DB. 287 * @return the removeOnStop 288 */ 289 public boolean isPreserveOnStop() 290 { 291 return _preserveOnStop; 292 } 293 294 /* ------------------------------------------------------------ */ 295 /** 296 * Invalidate sessions when the session manager is stopped otherwise save them to the DB. 297 * @param invalidateOnStop the invalidateOnStop to set 298 */ 299 public void setInvalidateOnStop(boolean invalidateOnStop) 300 { 301 _invalidateOnStop = invalidateOnStop; 302 } 303 304 /* ------------------------------------------------------------ */ 305 /** 306 * Preserve sessions when the session manager is stopped otherwise remove them from the DB. 307 * @param removeOnStop the removeOnStop to set 308 */ 309 public void setPreserveOnStop(boolean preserveOnStop) 310 { 311 _preserveOnStop = preserveOnStop; 312 } 313 314 /* ------------------------------------------------------------ */ 315 /** 316 * Save all attributes of a session or only update the dirty attributes. 317 * @return the saveAllAttributes 318 */ 319 public boolean isSaveAllAttributes() 320 { 321 return _saveAllAttributes; 322 } 323 324 /* ------------------------------------------------------------ */ 325 /** 326 * Save all attributes of a session or only update the dirty attributes. 327 * @param saveAllAttributes the saveAllAttributes to set 328 */ 329 public void setSaveAllAttributes(boolean saveAllAttributes) 330 { 331 _saveAllAttributes = saveAllAttributes; 332 } 333 334 /* ------------------------------------------------------------ */ 335 @Override 336 public void renewSessionId(String oldClusterId, String oldNodeId, String newClusterId, String newNodeId) 337 { 338 339 // Take the old session out of the list of sessions 340 // Change to the new id 341 // Put it back into the list of sessions 342 // Update permanent storage 343 344 synchronized (this) 345 { 346 try 347 { 348 NoSqlSession session = _sessions.remove(oldClusterId); 349 update (session, newClusterId, newNodeId); 350 session.setClusterId(newClusterId); 351 session.setNodeId(newNodeId); 352 _sessions.put(newClusterId, session); 353 } 354 catch (Exception e) 355 { 356 __log.warn(e); 357 } 358 } 359 } 360 361 362 /* ------------------------------------------------------------ */ 363 abstract protected NoSqlSession loadSession(String clusterId); 364 365 /* ------------------------------------------------------------ */ 366 abstract protected Object save(NoSqlSession session,Object version, boolean activateAfterSave); 367 368 /* ------------------------------------------------------------ */ 369 abstract protected Object refresh(NoSqlSession session, Object version); 370 371 /* ------------------------------------------------------------ */ 372 abstract protected boolean remove(NoSqlSession session); 373 374 /* ------------------------------------------------------------ */ 375 abstract protected void update(NoSqlSession session, String newClusterId, String newNodeId) throws Exception; 376 377 }