details:   https://code.openbravo.com/erp/devel/pi/rev/ca9d0d95c9b7
changeset: 33451:ca9d0d95c9b7
user:      Asier Lostalé <asier.lostale <at> openbravo.com>
date:      Thu Feb 15 14:37:32 2018 +0100
summary:   fiexed bug 37919: contention on session creation, deactivation and 
check

  Replaced HashSet that required to be externally synchronized with a Set backed
  with a ConcurrentHashMap which better handles synchronization.

diffstat:

 src-test/src/org/openbravo/test/system/Sessions.java      |  11 ++++-
 src/org/openbravo/erpCommon/security/SessionListener.java |  32 ++++++--------
 2 files changed, 23 insertions(+), 20 deletions(-)

diffs (149 lines):

diff -r 037253b579a3 -r ca9d0d95c9b7 
src-test/src/org/openbravo/test/system/Sessions.java
--- a/src-test/src/org/openbravo/test/system/Sessions.java      Thu Feb 15 
13:01:08 2018 +0100
+++ b/src-test/src/org/openbravo/test/system/Sessions.java      Thu Feb 15 
14:37:32 2018 +0100
@@ -19,7 +19,7 @@
 
 package org.openbravo.test.system;
 
-import static org.hamcrest.Matchers.is;
+import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
 
 import java.util.ArrayList;
@@ -37,21 +37,27 @@
 import org.junit.Test;
 import org.openbravo.erpCommon.security.SessionListener;
 import org.openbravo.erpCommon.utility.SequenceIdData;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /** Test cases covering Session management */
 public class Sessions {
+  private static final Logger log = LoggerFactory.getLogger(Sessions.class);
   private static int NUMBER_OF_THREADS = 4;
   private static int NUMBER_OF_SESSIONS_PER_THREAD = 1_000;
 
   /** Covers bug #37893 */
   @Test
   public void canCreateAndCheckSessionsInParallel() throws 
InterruptedException, ExecutionException {
+    log.info("Starting {} threads to create {} sessions each", 
NUMBER_OF_THREADS,
+        NUMBER_OF_SESSIONS_PER_THREAD);
     SessionListener sl = new SessionListener();
     List<SessionCreatorAndChecker> tasks = new ArrayList<>();
     for (int i = 0; i < NUMBER_OF_THREADS; i++) {
       tasks.add(new SessionCreatorAndChecker(sl));
     }
 
+    long t = System.currentTimeMillis();
     ExecutorService es = Executors.newFixedThreadPool(NUMBER_OF_THREADS);
     List<Future<Void>> executions = es.invokeAll(tasks);
 
@@ -59,6 +65,7 @@
       // if assertion failed, this will throw exception
       e.get();
     }
+    log.info("All finished in {} ms", System.currentTimeMillis() - t);
   }
 
   private class SessionCreatorAndChecker implements Callable<Void> {
@@ -70,6 +77,7 @@
 
     @Override
     public Void call() {
+      long t = System.currentTimeMillis();
       for (int i = 0; i < NUMBER_OF_SESSIONS_PER_THREAD; i++) {
         String sessionId = SequenceIdData.getUUID();
 
@@ -84,6 +92,7 @@
         assertThat(sessionFromContext, is(s));
       }
 
+      log.info("Thread finished in {} ms", System.currentTimeMillis() - t);
       return null;
     }
   }
diff -r 037253b579a3 -r ca9d0d95c9b7 
src/org/openbravo/erpCommon/security/SessionListener.java
--- a/src/org/openbravo/erpCommon/security/SessionListener.java Thu Feb 15 
13:01:08 2018 +0100
+++ b/src/org/openbravo/erpCommon/security/SessionListener.java Thu Feb 15 
14:37:32 2018 +0100
@@ -21,8 +21,9 @@
 
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
-import java.util.HashSet;
+import java.util.Collections;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
@@ -48,8 +49,10 @@
 
   private static final Logger log = Logger.getLogger(SessionListener.class);
 
-  private static Set<String> sessionsInContext = new HashSet<String>();
-  private static Set<HttpSession> activeHttpSessions = new 
HashSet<HttpSession>();
+  private static Set<String> sessionsInContext = Collections
+      .newSetFromMap(new ConcurrentHashMap<String, Boolean>());
+  private static Set<HttpSession> activeHttpSessions = Collections
+      .newSetFromMap(new ConcurrentHashMap<HttpSession, Boolean>());
   private static ServletContext context = null;
 
   /**
@@ -64,10 +67,7 @@
     if (sessionId != null) {
       deactivateSession(sessionId);
     }
-    synchronized (activeHttpSessions) {
-      activeHttpSessions.remove(session);
-    }
-
+    activeHttpSessions.remove(session);
     log.debug("Session destroyed. Active sessions count: " + 
activeHttpSessions.size());
   }
 
@@ -102,7 +102,7 @@
    * @param sessionId
    *          db id for the session to keep track
    */
-  public static synchronized void addSession(String sessionId) {
+  public static void addSession(String sessionId) {
     sessionsInContext.add(sessionId);
   }
 
@@ -155,9 +155,7 @@
 
   @Override
   public void sessionCreated(HttpSessionEvent event) {
-    synchronized (activeHttpSessions) {
-      activeHttpSessions.add(event.getSession());
-    }
+    activeHttpSessions.add(event.getSession());
 
     if (RequestContext.get().getRequest() != null
         && 
AuthenticationManager.isStatelessRequest(RequestContext.get().getRequest())) {
@@ -175,11 +173,9 @@
    */
   public static HttpSession getActiveSession(String sessionId) {
     try {
-      synchronized (activeHttpSessions) {
-        for (HttpSession session : activeHttpSessions) {
-          if (sessionId.equals(session.getAttribute("#AD_SESSION_ID"))) {
-            return session;
-          }
+      for (HttpSession session : activeHttpSessions) {
+        if (sessionId.equals(session.getAttribute("#AD_SESSION_ID"))) {
+          return session;
         }
       }
     } catch (Exception e) {
@@ -191,9 +187,7 @@
 
   private void deactivateSession(String sessionId) {
     try {
-      synchronized (sessionsInContext) {
-        sessionsInContext.remove(sessionId);
-      }
+      sessionsInContext.remove(sessionId);
 
       // Do not use DAL here
       SessionLoginData.deactivate((ConnectionProvider) 
context.getAttribute("openbravoPool"),

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Openbravo-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openbravo-commits

Reply via email to