1 //
2 // ========================================================================
3 // Copyright (c) 1995-2014 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 abstract protected NoSqlSession loadSession(String clusterId);
336
337 /* ------------------------------------------------------------ */
338 abstract protected Object save(NoSqlSession session,Object version, boolean activateAfterSave);
339
340 /* ------------------------------------------------------------ */
341 abstract protected Object refresh(NoSqlSession session, Object version);
342
343 /* ------------------------------------------------------------ */
344 abstract protected boolean remove(NoSqlSession session);
345
346 }