View Javadoc

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 }