diff --git a/rapidoid-http-fast/src/main/java/org/rapidoid/http/customize/DefaultSessionManager.java b/rapidoid-http-fast/src/main/java/org/rapidoid/http/customize/DefaultSessionManager.java index aedb9f7a88..dada749aaf 100644 --- a/rapidoid-http-fast/src/main/java/org/rapidoid/http/customize/DefaultSessionManager.java +++ b/rapidoid-http-fast/src/main/java/org/rapidoid/http/customize/DefaultSessionManager.java @@ -30,28 +30,57 @@ import java.io.Serializable; import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; @Authors("Nikolche Mihajlovski") @Since("5.2.0") public class DefaultSessionManager extends RapidoidThing implements SessionManager { - private final Map sessions = Coll.concurrentMap(); + public static class SessionHolder { + volatile byte[] serialized; + volatile Map session; + final AtomicLong refCounter = new AtomicLong(); + } + + private final Map sessions = Coll.autoExpandingMap(SessionHolder.class); @Override public Map loadSession(Req req, String sessionId) throws Exception { - byte[] bytes = sessions.get(sessionId); + SessionHolder holder = sessions.get(sessionId); - if (bytes != null) { - return U.cast(Msc.deserialize(bytes)); - } else { - return U.map(); + if (holder.session == null) { + synchronized (holder) { + if (holder.session == null) { + + if (holder.serialized != null) { + holder.session = U.cast(Msc.deserialize(holder.serialized)); + } else { + holder.session = Coll.concurrentMap(); + } + } + } } + + holder.refCounter.incrementAndGet(); + + return holder.session; } @Override public void saveSession(Req req, String sessionId, Map session) throws Exception { - byte[] bytes = Msc.serialize(session); - sessions.put(sessionId, bytes); + SessionHolder holder = sessions.get(sessionId); + long refN = holder.refCounter.decrementAndGet(); + + U.must(refN >= 0, "The session has negative reference counter!"); + + if (refN == 0) { + synchronized (holder) { + if (holder.refCounter.get() == 0) { + holder.serialized = Msc.serialize(session); + holder.session = null; + } + } + } } }