Refactor name of SesstionStore than supports cache of data.
This commit is contained in:
parent
970798b879
commit
c99db5797f
|
@ -1,179 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.server.session;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* CachingSessionDataStore
|
||||
*
|
||||
* A SessionDataStore is a mechanism for (persistently) storing data associated with sessions.
|
||||
* This implementation delegates to a pluggable SessionDataStore for actually storing the
|
||||
* session data. It also uses a pluggable JCache implementation in front of the
|
||||
* delegate SessionDataStore to improve performance: accessing most persistent store
|
||||
* technology can be expensive time-wise, so introducing a fronting cache
|
||||
* can increase performance. The cache implementation can either be a local cache,
|
||||
* a remote cache, or a clustered cache.
|
||||
*/
|
||||
public class CachingSessionDataStore extends AbstractSessionStore
|
||||
{
|
||||
|
||||
public interface SessionDataCache
|
||||
{
|
||||
public SessionData get (String id); //get mapped value
|
||||
public boolean putIfAbsent (String id, SessionData data); //only insert if no mapping for key already
|
||||
public boolean remove (String id); //remove the mapping for key, returns false if no mapping
|
||||
public void put (String id, SessionData data); //overwrite or add the mapping
|
||||
public void initialize(SessionContext context);
|
||||
}
|
||||
|
||||
|
||||
protected SessionStore _delegateDataStore;
|
||||
protected SessionDataCache _cache;
|
||||
|
||||
|
||||
public void setSessionDataStore (SessionStore store)
|
||||
{
|
||||
checkStarted();
|
||||
_delegateDataStore = store;
|
||||
}
|
||||
|
||||
public SessionStore getSessionDataStore()
|
||||
{
|
||||
return _delegateDataStore;
|
||||
}
|
||||
|
||||
|
||||
public void setSessionDataCache (SessionDataCache cache)
|
||||
{
|
||||
checkStarted();
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
public SessionDataCache getSessionDataCache ()
|
||||
{
|
||||
return _cache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionStore#load(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public SessionData load(String id) throws Exception
|
||||
{
|
||||
//check to see if the session data is already in our cache
|
||||
SessionData d = _cache.get(id);
|
||||
if (d == null)
|
||||
{
|
||||
//not in the cache, go get it from the store
|
||||
d = _delegateDataStore.load(id);
|
||||
|
||||
//put it into the cache, unless another thread/node has put it into the cache
|
||||
boolean inserted = _cache.putIfAbsent(id, d);
|
||||
if (!inserted)
|
||||
{
|
||||
//some other thread/node put this data into the cache, so get it from there
|
||||
SessionData d2 = _cache.get(id);
|
||||
|
||||
if (d2 != null)
|
||||
d = d2;
|
||||
//else: The cache either timed out the entry, or maybe the session data was being removed, and we're about to resurrect it!
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionStore#delete(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public boolean delete(String id) throws Exception
|
||||
{
|
||||
//delete from the store and from the cache
|
||||
_delegateDataStore.delete(id);
|
||||
_cache.remove(id);
|
||||
//TODO need to check removal at each level?
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionStore#getExpired(Set)
|
||||
*/
|
||||
@Override
|
||||
public Set<String> doGetExpired(Set<String> candidates)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.AbstractSessionStore#doStore(java.lang.String, org.eclipse.jetty.server.session.SessionData, long)
|
||||
*/
|
||||
@Override
|
||||
public void doStore(String id, SessionData data, long lastSaveTime) throws Exception
|
||||
{
|
||||
//write to the SessionDataStore first
|
||||
if (_delegateDataStore instanceof AbstractSessionStore)
|
||||
((AbstractSessionStore)_delegateDataStore).doStore(id, data, lastSaveTime);
|
||||
|
||||
//else??????
|
||||
|
||||
//then update the cache with written data
|
||||
_cache.put(id,data);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
_cache.initialize(_context);
|
||||
_delegateDataStore.initialize(_context);
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
super.doStop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionStore#isPassivating()
|
||||
*/
|
||||
@Override
|
||||
public boolean isPassivating()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionStore#exists(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public boolean exists(String id) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,220 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.server.session;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
|
||||
/**
|
||||
* CachingSessionStore
|
||||
*
|
||||
* A SessionStore is a mechanism for (persistently) storing data associated with sessions.
|
||||
* This implementation delegates to a pluggable SessionStore for actually storing the
|
||||
* session data. It also uses a pluggable cache implementation in front of the
|
||||
* delegate SessionStore to improve performance: accessing most persistent store
|
||||
* technology can be expensive time-wise, so introducing a fronting cache
|
||||
* can increase performance. The cache implementation can either be a local cache,
|
||||
* a remote cache, or a clustered cache.
|
||||
*/
|
||||
public class CachingSessionStore extends AbstractLifeCycle implements SessionStore
|
||||
{
|
||||
|
||||
/**
|
||||
* Cache
|
||||
*
|
||||
* An interface that represents the contract with the particular cache
|
||||
* implementation, eg memcache, infinispan etc
|
||||
*/
|
||||
public interface Cache
|
||||
{
|
||||
public SessionData get (String id); //get cached value
|
||||
public boolean putIfAbsent (String id, SessionData data); //only insert if no mapping for key already
|
||||
public boolean remove (String id); //remove the mapping for key, returns false if no mapping
|
||||
public void put (String id, SessionData data); //overwrite or add the mapping
|
||||
public void initialize(SessionContext context);
|
||||
}
|
||||
|
||||
|
||||
protected SessionStore _store;
|
||||
protected Cache _cache;
|
||||
|
||||
|
||||
/**
|
||||
* @param cache
|
||||
* @param store
|
||||
*/
|
||||
public CachingSessionStore (Cache cache, SessionStore store)
|
||||
{
|
||||
_cache = cache;
|
||||
_store = store;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public SessionStore getSessionStore()
|
||||
{
|
||||
return _store;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public Cache getSessionStoreCache ()
|
||||
{
|
||||
return _cache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionStore#load(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public SessionData load(String id) throws Exception
|
||||
{
|
||||
//check to see if the session data is already in the cache
|
||||
SessionData d = _cache.get(id);
|
||||
if (d == null)
|
||||
{
|
||||
//not in the cache, go get it from the store
|
||||
d = _store.load(id);
|
||||
|
||||
if (d != null)
|
||||
{
|
||||
//put it into the cache, unless another thread/node has put it into the cache
|
||||
boolean inserted = _cache.putIfAbsent(id, d);
|
||||
if (!inserted)
|
||||
{
|
||||
//some other thread/node put this data into the cache, so get it from there
|
||||
SessionData d2 = _cache.get(id);
|
||||
|
||||
if (d2 != null)
|
||||
d = d2;
|
||||
//else: The cache either timed out the entry, or maybe the session data was being removed, and we're about to resurrect it!
|
||||
}
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionStore#delete(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public boolean delete(String id) throws Exception
|
||||
{
|
||||
//delete from the store and from the cache
|
||||
boolean deleted = _store.delete(id);
|
||||
|
||||
//TODO what to do if couldn't remove from the cache?
|
||||
_cache.remove(id);
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionStore#getExpired(Set)
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getExpired(Set<String> candidates)
|
||||
{
|
||||
//pass thru to the delegate store
|
||||
return _store.getExpired(candidates);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionStore#store(java.lang.String, org.eclipse.jetty.server.session.SessionData)
|
||||
*/
|
||||
@Override
|
||||
public void store(String id, SessionData data) throws Exception
|
||||
{
|
||||
//write to the SessionDataStore first
|
||||
_store.store(id, data);
|
||||
|
||||
//then update the cache with written data
|
||||
_cache.put(id,data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
super.doStop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionStore#isPassivating()
|
||||
*/
|
||||
@Override
|
||||
public boolean isPassivating()
|
||||
{
|
||||
return _store.isPassivating();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionStore#exists(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public boolean exists(String id) throws Exception
|
||||
{
|
||||
//check the cache first
|
||||
SessionData data = _cache.get(id);
|
||||
if (data != null)
|
||||
return true;
|
||||
|
||||
//then the delegate store
|
||||
return _store.exists(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionStore#initialize(org.eclipse.jetty.server.session.SessionContext)
|
||||
*/
|
||||
@Override
|
||||
public void initialize(SessionContext context)
|
||||
{
|
||||
//pass through
|
||||
_store.initialize(context);
|
||||
_cache.initialize(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.SessionStore#newSessionData(java.lang.String, long, long, long, long)
|
||||
*/
|
||||
@Override
|
||||
public SessionData newSessionData(String id, long created, long accessed, long lastAccessed, long maxInactiveMs)
|
||||
{
|
||||
return _store.newSessionData(id, created, accessed, lastAccessed, maxInactiveMs);
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue