Improve logging in order to better analyze this issue when it's occur.
authorMathieu Baudier <mbaudier@argeo.org>
Wed, 10 Dec 2008 20:22:34 +0000 (20:22 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Wed, 10 Dec 2008 20:22:34 +0000 (20:22 +0000)
Synchronize more method within the server.

ASSIGNED - bug 73: Detached getRequest crash
https://www.spartadn.com/bugzilla/show_bug.cgi?id=73

git-svn-id: https://svn.argeo.org/slc/trunk@2000 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

runtime/org.argeo.slc.detached/src/main/java/org/argeo/slc/detached/DetachedAnswer.java
runtime/org.argeo.slc.detached/src/main/java/org/argeo/slc/detached/DetachedCommunication.java
runtime/org.argeo.slc.detached/src/main/java/org/argeo/slc/detached/DetachedContextImpl.java
runtime/org.argeo.slc.detached/src/main/java/org/argeo/slc/detached/DetachedExecutionServer.java
runtime/org.argeo.slc.detached/src/main/java/org/argeo/slc/detached/DetachedExecutionServerImpl.java
runtime/org.argeo.slc.detached/src/main/java/org/argeo/slc/detached/DetachedRequest.java
runtime/org.argeo.slc.detached/src/main/java/org/argeo/slc/detached/DetachedSession.java

index 55789a04696f0b3d1b6a92694547aacc222938e5..51162c44f0929ae56a9da0dc5760ee2fb7b8c311 100644 (file)
@@ -2,6 +2,7 @@ package org.argeo.slc.detached;
 
 import java.util.Properties;
 
+/** An answer returned by the detached server. Always related to a request. */
 public class DetachedAnswer implements DetachedCommunication {
        static final long serialVersionUID = 1l;
 
@@ -54,6 +55,11 @@ public class DetachedAnswer implements DetachedCommunication {
                this.log = log;
        }
 
+       public void addToLog(String msg) {
+               this.log = new StringBuffer(this.log).append(msg).toString();
+       }
+
+       /** The unique identifier of this answer. */
        public String getUuid() {
                return uuid;
        }
@@ -82,4 +88,14 @@ public class DetachedAnswer implements DetachedCommunication {
                        throw new DetachedException("Unkown status " + status);
                }
        }
+
+       public String toString() {
+               StringBuffer buf = new StringBuffer(getClass().getName());
+               buf.append('#').append(uuid);
+               buf.append(" status=").append(convertStatus(status));
+               buf.append(" properties=").append(properties);
+               buf.append(" log=").append(log);
+               return buf.toString();
+       }
+
 }
index 8bdba36e28b6478b4e5e8815e21b8186bc19633b..0c1d59952aea7b775749e94461fe865cc0723878 100644 (file)
@@ -2,6 +2,11 @@ package org.argeo.slc.detached;
 
 import java.io.Serializable;
 
+/**
+ * Common interface for all communications between the source context and the
+ * detached server.
+ */
 public interface DetachedCommunication extends Serializable {
+       /** The unique identifier of this answer. */
        public String getUuid();
 }
index 595b3379c42649b13684225cb8ae1feb02b8602d..cb4149b9c31ccd514c734c18e7075106e3b06c9e 100644 (file)
@@ -30,4 +30,10 @@ public class DetachedContextImpl implements DetachedContext {
                return new ArrayList(executedPaths);
        }
 
+       public String toString() {
+               StringBuffer buf = new StringBuffer(getClass().getName());
+               buf.append(" currentPath=").append(currentPath);
+               buf.append(" executedPaths=").append(executedPaths);
+               return buf.toString();
+       }
 }
index ec5f3c50623a06620e38b3fbbe5f0c6f2d1b5845..9107676404b3a7dd8c5f29030c040f515561de86 100644 (file)
@@ -1,5 +1,10 @@
 package org.argeo.slc.detached;
 
+/**
+ * Interface between the detached and the source context via request and
+ * answers.
+ */
 public interface DetachedExecutionServer {
+       /** Actually executes the request. */
        public DetachedAnswer executeRequest(DetachedRequest request);
 }
index 35b9d63d537ffb6d5ce15e792b04907a9588fa78..0a2e866a5793e2850423f162feba4df13310f88f 100644 (file)
@@ -1,8 +1,11 @@
 package org.argeo.slc.detached;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.List;
 import java.util.Vector;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.slc.detached.admin.CloseSession;
@@ -12,6 +15,7 @@ import org.osgi.framework.ServiceReference;
 import org.springframework.context.ApplicationContext;
 import org.springframework.osgi.context.BundleContextAware;
 
+/** Default implementation of a detached server. */
 public class DetachedExecutionServerImpl implements DetachedExecutionServer,
                BundleContextAware {
        private final static Log log = LogFactory
@@ -73,8 +77,31 @@ public class DetachedExecutionServerImpl implements DetachedExecutionServer,
                } catch (Exception e) {
                        answer = new DetachedAnswer(request);
                        answer.setStatus(DetachedAnswer.ERROR);
-                       answer.setLog(e.getMessage());
+                       StringWriter writer = new StringWriter();
+                       e.printStackTrace(new PrintWriter(writer));
+                       answer.setLog(writer.toString());
+                       IOUtils.closeQuietly(writer);
                }
+
+               // Case where current session is unexpectly null
+               if (getCurrentSession() == null) {
+                       log
+                                       .error("CURRENT SESSION IS NULL."
+                                                       + " Detached status is inconsistent dumping sessions history:");
+                       log.error(dumpSessionsHistory(request, answer));
+                       if (answer != null) {
+                               answer.setStatus(DetachedAnswer.ERROR);
+                               answer
+                                               .addToLog("CURRENT SESSION IS NULL."
+                                                               + " Detached status is inconsistent, see detached log for more details.");
+                               return answer;
+                       } else {
+                               throw new DetachedException(
+                                               "Answer is null. Cannot return it. See log for more details.");
+                       }
+
+               }
+
                getCurrentSession().getRequests().add(request);
                getCurrentSession().getAnswers().add(answer);
                if (log.isDebugEnabled())
@@ -84,7 +111,7 @@ public class DetachedExecutionServerImpl implements DetachedExecutionServer,
                return answer;
        }
 
-       protected DetachedAnswer processStep(DetachedStep obj,
+       protected synchronized DetachedAnswer processStep(DetachedStep obj,
                        DetachedRequest request) {
                DetachedAnswer answer;
                if (getCurrentSession() == null)
@@ -135,6 +162,7 @@ public class DetachedExecutionServerImpl implements DetachedExecutionServer,
 
                if (execute) {
                        DetachedStep step = (DetachedStep) obj;
+                       // Actually execute the step
                        answer = step.execute(detachedContext, request);
                } else {
                        answer = new DetachedAnswer(request);
@@ -144,8 +172,8 @@ public class DetachedExecutionServerImpl implements DetachedExecutionServer,
                return answer;
        }
 
-       protected DetachedAnswer processAdminCommand(DetachedAdminCommand obj,
-                       DetachedRequest request) {
+       protected synchronized DetachedAnswer processAdminCommand(
+                       DetachedAdminCommand obj, DetachedRequest request) {
                DetachedAnswer answer;
                if (obj instanceof OpenSession) {
                        if (getCurrentSession() != null)
@@ -167,7 +195,13 @@ public class DetachedExecutionServerImpl implements DetachedExecutionServer,
                return answer;
        }
 
-       protected final DetachedSession getCurrentSession() {
+       /**
+        * Returns the current session based on the list of previous sessions.
+        * 
+        * @return the current session or null if there is no session yet defined or
+        *         if the last registered session is null or in error.
+        */
+       protected synchronized final DetachedSession getCurrentSession() {
                if (sessions.size() == 0) {
                        return null;
                } else {
@@ -185,7 +219,41 @@ public class DetachedExecutionServerImpl implements DetachedExecutionServer,
                }
        }
 
-       protected final DetachedSession getPreviousSession() {
+       protected synchronized String dumpSessionsHistory(
+                       DetachedRequest requestCurrent, DetachedAnswer answerCurrent) {
+               StringBuffer buf = new StringBuffer("## SESSIONS HISTORY DUMP\n");
+               buf.append("# CURRENT\n");
+               buf.append("Current session: ").append(getCurrentSession())
+                               .append('\n');
+               buf.append("Current request: ").append(requestCurrent).append('\n');
+               buf.append("Current answer: ").append(requestCurrent).append('\n');
+               buf.append("Skip count: ").append(skipCount).append('\n');
+
+               buf.append("# SESSIONS\n");
+               for (int i = 0; i < sessions.size(); i++) {
+                       DetachedSession session = (DetachedSession) sessions.get(i);
+                       buf.append(i).append(". ").append(session).append('\n');
+                       List requests = session.getRequests();
+                       List answers = session.getAnswers();
+                       for (int j = 0; j < requests.size(); j++) {
+                               DetachedRequest request = (DetachedRequest) requests.get(j);
+                               buf.append('\t').append(j).append(". ").append(request).append(
+                                               '\n');
+                               if (answers.size() > j) {
+                                       DetachedAnswer answer = (DetachedAnswer) answers.get(j);
+                                       buf.append('\t').append(j).append(". ").append(answer)
+                                                       .append('\n');
+                               }
+                       }
+               }
+
+               buf.append("# DETACHED CONTEXT\n");
+               buf.append(detachedContext).append('\n');
+
+               return buf.toString();
+       }
+
+       protected synchronized final DetachedSession getPreviousSession() {
                if (sessions.size() < 2)
                        return null;
                else
index 99427bf1d12c1f7d56187c4b936590e396cb0116..8a1976817ae803bfd20cb9f87cf8b531e09039c5 100644 (file)
@@ -2,6 +2,7 @@ package org.argeo.slc.detached;
 
 import java.util.Properties;
 
+/** A request sent to the detached server. */
 public class DetachedRequest implements DetachedCommunication {
        static final long serialVersionUID = 1l;
 
@@ -18,6 +19,7 @@ public class DetachedRequest implements DetachedCommunication {
                this.uuid = uuid;
        }
 
+       /** The properties configuring this request. */
        public Properties getProperties() {
                return properties;
        }
@@ -26,6 +28,10 @@ public class DetachedRequest implements DetachedCommunication {
                this.properties = inputParameters;
        }
 
+       /**
+        * A reference to the underlying implementation which will process the
+        * request.
+        */
        public String getRef() {
                return ref;
        }
@@ -34,6 +40,7 @@ public class DetachedRequest implements DetachedCommunication {
                this.ref = stepRef;
        }
 
+       /** A path identifying the request within its source context. */
        public String getPath() {
                return path;
        }
@@ -42,6 +49,7 @@ public class DetachedRequest implements DetachedCommunication {
                this.path = path;
        }
 
+       /** The unique identifier of this request. */
        public String getUuid() {
                return uuid;
        }
@@ -49,4 +57,13 @@ public class DetachedRequest implements DetachedCommunication {
        public void setUuid(String uuid) {
                this.uuid = uuid;
        }
+
+       public String toString() {
+               StringBuffer buf = new StringBuffer(getClass().getName());
+               buf.append('#').append(uuid);
+               buf.append(" ref=").append(ref);
+               buf.append(" path=").append(path);
+               buf.append(" properties=").append(properties);
+               return buf.toString();
+       }
 }
index 76e894b1617fac28e776505dc0fe57f913a6907a..5c7884fe56f327baa771dbed287ab76854dea671 100644 (file)
@@ -3,6 +3,7 @@ package org.argeo.slc.detached;
 import java.util.List;
 import java.util.Vector;
 
+/** A session within the detached context. */
 public class DetachedSession {
        public final static String PROP_DO_IT_AGAIN_POLICY = "slc.detached.doItAgainPolicy";
        public final static String SKIP_UNTIL_ERROR = "skipUntilError";
@@ -47,4 +48,10 @@ public class DetachedSession {
                return answers;
        }
 
+       public String toString() {
+               StringBuffer buf = new StringBuffer(getClass().getName());
+               buf.append("#").append(uuid);
+               buf.append(" doItAgainPolicy=").append(doItAgainPolicy);
+               return buf.toString();
+       }
 }