details:   https://code.openbravo.com/erp/devel/pi/rev/5aed2a398dac
changeset: 32412:5aed2a398dac
user:      Asier Lostalé <asier.lostale <at> openbravo.com>
date:      Wed Jul 05 14:47:20 2017 +0200
summary:   related to bug 36419: no request processed while killing abandoned 
sessions

  Deactivate abandoned sessions in a separate DB transaction, in this manner the
  time locks in ad_session are held is reduced to only this action, before those
  locks were held till the thread was terminated.

details:   https://code.openbravo.com/erp/devel/pi/rev/76e0f1c4b33e
changeset: 32413:76e0f1c4b33e
user:      Asier Lostalé <asier.lostale <at> openbravo.com>
date:      Thu Jul 06 07:41:00 2017 +0200
summary:   fixed bug 36419: no request processed while killing abandoned 
sessions

  * ActivationKey.getInstance is not synchronized anymore
  * Synchronization is now reduced to the places changing state
  * Session deactivation monitored by a lock to ensure there is at most one
    thread in this block, in this way, at most one thread can be wating for
    DB lock at this position

details:   https://code.openbravo.com/erp/devel/pi/rev/79ddd2858936
changeset: 32414:79ddd2858936
user:      Asier Lostalé <asier.lostale <at> openbravo.com>
date:      Thu Jul 06 08:11:02 2017 +0200
summary:   related to bug 36419: no request processed while killing abandoned 
sessions

  Removed synchronization in WS call counter

details:   https://code.openbravo.com/erp/devel/pi/rev/0d877e9b8212
changeset: 32415:0d877e9b8212
user:      Asier Lostalé <asier.lostale <at> openbravo.com>
date:      Thu Jul 06 08:21:45 2017 +0200
summary:   related to bug 36419: no request processed while killing abandoned 
sessions

  Log stack traces in case of error

details:   https://code.openbravo.com/erp/devel/pi/rev/8b2480998f02
changeset: 32416:8b2480998f02
user:      Asier Lostalé <asier.lostale <at> openbravo.com>
date:      Thu Jul 06 10:02:38 2017 +0200
summary:   fixed bug 36425: mobile sessions can be kicked out in cluster

  Don't try to invalidate those sessions not present in current node.

details:   https://code.openbravo.com/erp/devel/pi/rev/c557445d5d66
changeset: 32417:c557445d5d66
user:      Asier Lostalé <asier.lostale <at> openbravo.com>
date:      Thu Jul 06 14:07:15 2017 +0200
summary:   fixed bug 36434: unlikely argument type warnings

diffstat:

 src-core/src/org/openbravo/base/VariablesBase.java       |    2 +-
 src/org/openbravo/dal/xml/EntityResolver.java            |    4 +-
 src/org/openbravo/erpCommon/obps/ActivationKey.java      |  211 +++++++++-----
 src/org/openbravo/erpCommon/obps/ActivationKey_data.xsql |   36 ++
 src/org/openbravo/service/web/UserContextCache.java      |    8 +-
 5 files changed, 175 insertions(+), 86 deletions(-)

diffs (truncated from 439 to 300 lines):

diff -r 01727c5b58ac -r c557445d5d66 
src-core/src/org/openbravo/base/VariablesBase.java
--- a/src-core/src/org/openbravo/base/VariablesBase.java        Wed Jul 05 
14:16:09 2017 +0200
+++ b/src-core/src/org/openbravo/base/VariablesBase.java        Thu Jul 06 
14:07:15 2017 +0200
@@ -1043,7 +1043,7 @@
       }
     }
 
-    if (auxStr == null || auxStr.length == 0 || auxStr.equals("")) {
+    if (auxStr == null || auxStr.length == 0) {
       if (required) {
         throw new ServletException("Request IN parameter required: " + 
parameter);
       } else {
diff -r 01727c5b58ac -r c557445d5d66 
src/org/openbravo/dal/xml/EntityResolver.java
--- a/src/org/openbravo/dal/xml/EntityResolver.java     Wed Jul 05 14:16:09 
2017 +0200
+++ b/src/org/openbravo/dal/xml/EntityResolver.java     Thu Jul 06 14:07:15 
2017 +0200
@@ -11,7 +11,7 @@
  * under the License. 
  * The Original Code is Openbravo ERP. 
  * The Initial Developer of the Original Code is Openbravo SLU 
- * All portions are Copyright (C) 2008-2011 Openbravo SLU 
+ * All portions are Copyright (C) 2008-2017 Openbravo SLU 
  * All Rights Reserved. 
  * Contributor(s):  ______________________________________.
  ************************************************************************
@@ -360,7 +360,7 @@
       List<RefDataLoaded> refLoadeds) {
     BaseOBObject result = null;
     for (RefDataLoaded refLoaded : refLoadeds) {
-      if (refLoaded.getClientId().equals('0') && 
refLoaded.getOrgId().equals("0")) {
+      if (refLoaded.getClientId().equals("0") && 
refLoaded.getOrgId().equals("0")) {
         result = doSearch(refLoaded.getSpecificId(), entity, "0", "0");
         if (result != null) {
           return result;
diff -r 01727c5b58ac -r c557445d5d66 
src/org/openbravo/erpCommon/obps/ActivationKey.java
--- a/src/org/openbravo/erpCommon/obps/ActivationKey.java       Wed Jul 05 
14:16:09 2017 +0200
+++ b/src/org/openbravo/erpCommon/obps/ActivationKey.java       Thu Jul 06 
14:07:15 2017 +0200
@@ -35,6 +35,8 @@
 import java.security.PublicKey;
 import java.security.Signature;
 import java.security.spec.X509EncodedKeySpec;
+import java.sql.Connection;
+import java.sql.SQLException;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -47,11 +49,15 @@
 import java.util.Map;
 import java.util.Properties;
 import java.util.UUID;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.zip.CRC32;
 
 import javax.crypto.Cipher;
 import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.BeanManager;
+import javax.servlet.ServletException;
 import javax.servlet.http.HttpSession;
 
 import org.apache.commons.io.FileUtils;
@@ -82,6 +88,7 @@
 import org.openbravo.erpCommon.utility.OBMessageUtils;
 import org.openbravo.erpCommon.utility.SystemInfo;
 import org.openbravo.erpCommon.utility.Utility;
+import org.openbravo.exception.NoConnectionAvailableException;
 import org.openbravo.model.ad.access.Session;
 import org.openbravo.model.ad.module.Module;
 import org.openbravo.model.ad.system.HeartbeatLog;
@@ -133,7 +140,7 @@
   private boolean inconsistentInstance = false;
 
   private long maxWsCalls;
-  private long wsDayCounter;
+  private AtomicLong wsDayCounter;
   private Date initWsCountTime;
   private List<Date> exceededInLastDays;
 
@@ -144,6 +151,9 @@
   private static final String GOLDEN_EXCLUDED = "GOLDENEXCLUDED";
   private static final SimpleDateFormat sDateFormat = new 
SimpleDateFormat("yyyy-MM-dd");
 
+  private Lock deactivateSessionsLock = new ReentrantLock();
+  private Object wsCountLock = new Object();
+
   /**
    * Number of minutes since last license refresh to wait before doing it again
    */
@@ -252,7 +262,7 @@
    * @see ActivationKey#getInstance(boolean)
    * 
    */
-  public static synchronized ActivationKey getInstance() {
+  public static ActivationKey getInstance() {
     return getInstance(false);
   }
 
@@ -266,7 +276,7 @@
    *          refresh license if needed to
    * 
    */
-  public static synchronized ActivationKey getInstance(boolean 
refreshIfNeeded) {
+  public static ActivationKey getInstance(boolean refreshIfNeeded) {
     if (refreshIfNeeded) {
       instance.refreshIfNeeded();
     }
@@ -313,7 +323,7 @@
     }
   }
 
-  private void loadFromDB() {
+  private synchronized void loadFromDB() {
     org.openbravo.model.ad.system.System sys = OBDal.getInstance().get(
         org.openbravo.model.ad.system.System.class, "0");
     strPublicKey = sys.getInstanceKey();
@@ -328,7 +338,7 @@
     loadRestrictions();
   }
 
-  private void loadInfo(String activationKey) {
+  private synchronized void loadInfo(String activationKey) {
     reset();
 
     if (strPublicKey == null || activationKey == null || 
strPublicKey.equals("")
@@ -1072,41 +1082,69 @@
    * PING_TIMEOUT_SECS is hardcoded to 120s, pings are hardcoded in front-end 
to 50s.
    */
   private boolean deactivateTimeOutSessions(String currentSessionId) {
-    // Last valid ping time is current time substract timeout seconds
-    Calendar cal = Calendar.getInstance();
-    cal.add(Calendar.SECOND, (-1) * PING_TIMEOUT_SECS);
-    Date lastValidPingTime = new Date(cal.getTimeInMillis());
+    if (!deactivateSessionsLock.tryLock()) {
+      // another thread is already trying to deactivate sessions, don't do 
anything
+      return false;
+    }
+    try {
+      // Last valid ping time is current time substract timeout seconds
+      Calendar cal = Calendar.getInstance();
+      cal.add(Calendar.SECOND, (-1) * PING_TIMEOUT_SECS);
+      Date lastValidPingTime = new Date(cal.getTimeInMillis());
 
-    OBCriteria<Session> obCriteria = 
OBDal.getInstance().createCriteria(Session.class);
+      OBCriteria<Session> obCriteria = 
OBDal.getInstance().createCriteria(Session.class);
 
-    // sesion_active='Y' and (lastPing is null or lastPing<lastValidPing)
-    obCriteria.add(Restrictions.and(
-        Restrictions.eq(Session.PROPERTY_SESSIONACTIVE, true),
-        Restrictions.or(Restrictions.isNull(Session.PROPERTY_LASTPING),
-            Restrictions.lt(Session.PROPERTY_LASTPING, lastValidPingTime))));
-    
obCriteria.add(Restrictions.not(Restrictions.in(Session.PROPERTY_LOGINSTATUS,
-        NO_CU_SESSION_TYPES)));
+      // sesion_active='Y' and (lastPing is null or lastPing<lastValidPing)
+      obCriteria.add(Restrictions.and(
+          Restrictions.eq(Session.PROPERTY_SESSIONACTIVE, true),
+          Restrictions.or(Restrictions.isNull(Session.PROPERTY_LASTPING),
+              Restrictions.lt(Session.PROPERTY_LASTPING, lastValidPingTime))));
+      
obCriteria.add(Restrictions.not(Restrictions.in(Session.PROPERTY_LOGINSTATUS,
+          NO_CU_SESSION_TYPES)));
 
-    if (currentSessionId != null) {
-      obCriteria.add(Restrictions.ne(Session.PROPERTY_ID, currentSessionId));
+      if (currentSessionId != null) {
+        obCriteria.add(Restrictions.ne(Session.PROPERTY_ID, currentSessionId));
+      }
+
+      List<Session> exipiredCandidates = obCriteria.list();
+      ArrayList<String> sessionsToDeactivate = new 
ArrayList<>(exipiredCandidates.size());
+      for (Session expiredSession : exipiredCandidates) {
+        if (shouldDeactivateSession(expiredSession, lastValidPingTime)) {
+          sessionsToDeactivate.add(expiredSession.getId());
+          log4j.info("Deactivating session: " + expiredSession.getId()
+              + " beacuse of ping time out. Last ping: " + 
expiredSession.getLastPing()
+              + ". Last valid ping time: " + lastValidPingTime);
+        }
+      }
+
+      if (!sessionsToDeactivate.isEmpty()) {
+        // deactivate sessions is a separate DB trx not to hold locks for a 
long time
+        DalConnectionProvider cp = new DalConnectionProvider(false);
+        Connection trxConn = null;
+        boolean success = false;
+        try {
+          trxConn = cp.getTransactionConnection();
+          ActivationKeyData.deactivateSessions(trxConn, cp,
+              Utility.arrayListToString(sessionsToDeactivate, true));
+          cp.releaseCommitConnection(trxConn);
+          success = true;
+        } catch (NoConnectionAvailableException | SQLException | 
ServletException e) {
+          log.error("couldn't deactivate timed out sessions: " + 
sessionsToDeactivate, e);
+        } finally {
+          if (!success && trxConn != null) {
+            try {
+              cp.releaseRollbackConnection(trxConn);
+            } catch (SQLException e) {
+              log.error("couldn't rollback failed trx to deactivate timed out 
sessions: "
+                  + sessionsToDeactivate, e);
+            }
+          }
+        }
+      }
+      return !sessionsToDeactivate.isEmpty();
+    } finally {
+      deactivateSessionsLock.unlock();
     }
-
-    boolean sessionDeactivated = false;
-    for (Session expiredSession : obCriteria.list()) {
-      if (shouldDeactivateSession(expiredSession, lastValidPingTime)) {
-        expiredSession.setSessionActive(false);
-        sessionDeactivated = true;
-        log4j.info("Deactivated session: " + expiredSession.getId()
-            + " beacuse of ping time out. Last ping: " + 
expiredSession.getLastPing()
-            + ". Last valid ping time: " + lastValidPingTime);
-      }
-    }
-    if (sessionDeactivated) {
-      OBDal.getInstance().flush();
-    } else {
-      log4j.debug("No ping timeout sessions");
-    }
-    return sessionDeactivated;
   }
 
   /**
@@ -1118,7 +1156,9 @@
     HttpSession session = SessionListener.getActiveSession(sessionId);
     if (session == null) {
       log4j.debug("Session " + sessionId + " not found in context");
-      return true;
+      // we cannot deactivate this session because it might have been created 
in a different node
+      // from cluster and we cannot know when was used last time
+      return false;
     }
     Date lastRequestTime = new Date(session.getLastAccessedTime());
     log4j.debug("Last request received from session " + sessionId + ": " + 
lastRequestTime);
@@ -1830,7 +1870,7 @@
    * @param updateCounter
    *          daily calls should be updated
    */
-  public synchronized WSRestriction checkNewWSCall(boolean updateCounter) {
+  public WSRestriction checkNewWSCall(boolean updateCounter) {
     if (hasExpired) {
       return WSRestriction.EXPIRED;
     }
@@ -1850,55 +1890,61 @@
     }
 
     long checkCalls = maxWsCalls;
+    long currentDayCount;
     if (updateCounter) {
-      wsDayCounter += 1;
+      currentDayCount = wsDayCounter.incrementAndGet();
       // Adding 1 to maxWsCalls because session is already saved in DB
       checkCalls += 1;
+    } else {
+      currentDayCount = wsDayCounter.get();
     }
 
-    if (wsDayCounter > checkCalls) {
-      // clean up old days
-      while (!exceededInLastDays.isEmpty()
-          && exceededInLastDays.get(0).getTime() < today.getTime() - 
WS_MS_EXCEEDING_ALLOWED_PERIOD) {
-        Date removed = exceededInLastDays.remove(0);
-        log.info("Removed date from exceeded days " + removed);
-      }
+    if (currentDayCount > checkCalls) {
+      synchronized (wsCountLock) {
+        // clean up old days
+        while (!exceededInLastDays.isEmpty()
+            && exceededInLastDays.get(0).getTime() < today.getTime()
+                - WS_MS_EXCEEDING_ALLOWED_PERIOD) {
+          Date removed = exceededInLastDays.remove(0);
+          log.info("Removed date from exceeded days " + removed);
+        }
 
-      if (!exceededInLastDays.contains(today)) {
-        exceededInLastDays.add(today);
+        if (!exceededInLastDays.contains(today)) {
+          exceededInLastDays.add(today);
 
-        // Adding a new failing day, send a new beat to butler
-        Runnable sendBeatProcess = new Runnable() {
-          @Override
-          public void run() {
-            try {
-              String content = "beatType=CWSR";
-              content += "&systemIdentifier="
-                  + URLEncoder.encode(SystemInfo.getSystemIdentifier(), 
"utf-8");
-              content += "&dbIdentifier="
-                  + URLEncoder.encode(SystemInfo.getDBIdentifier(), "utf-8");
-              content += "&macId=" + 
URLEncoder.encode(SystemInfo.getMacAddress(), "utf-8");
-              content += "&obpsId=" + 
URLEncoder.encode(SystemInfo.getOBPSInstance(), "utf-8");
-              content += "&instanceNo="
-                  + URLEncoder.encode(SystemInfo.getOBPSIntanceNumber(), 
"utf-8");
+          // Adding a new failing day, send a new beat to butler
+          Runnable sendBeatProcess = new Runnable() {
+            @Override
+            public void run() {
+              try {

------------------------------------------------------------------------------
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
Openbravo-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openbravo-commits

Reply via email to