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 abstract protected NoSqlSession loadSession(String clusterId);
312
313 /* ------------------------------------------------------------ */
314 abstract protected Object save(NoSqlSession session,Object version, boolean activateAfterSave);
315
316 /* ------------------------------------------------------------ */
317 abstract protected Object refresh(NoSqlSession session, Object version);
318
319 /* ------------------------------------------------------------ */
320 abstract protected boolean remove(NoSqlSession session);
321
322 }