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 _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 }