[ 1897512 ] CLogger not thread safe

- replace use of static and instance variable with context. Context should then be implemented as inheritable thread local in server environment ( done for ZK client, need to check the EJB & Servlet implementation ).
This commit is contained in:
Heng Sin Low 2008-07-15 09:42:35 +00:00
parent d8a3f9b6d3
commit c9fea0e495
2 changed files with 87 additions and 48 deletions

View File

@ -30,6 +30,12 @@ import org.compiere.model.*;
*/
public class CLogErrorBuffer extends Handler
{
private static final String ISSUE_ERROR_KEY = "org.compiere.util.CLogErrorBuffer.issueError";
private static final String HISTORY_KEY = "org.compiere.util.CLogErrorBuffer.history";
private static final String ERRORS_KEY = "org.compiere.util.CLogErrorBuffer.errors";
private static final String LOGS_KEY = "org.compiere.util.CLogErrorBuffer.logs";
/**
* Get Client Log Handler
* @param create create if not exists
@ -62,17 +68,9 @@ public class CLogErrorBuffer extends Handler
/** Error Buffer Size */
private static final int ERROR_SIZE = 20;
/** The Error Buffer */
private LinkedList<LogRecord> m_errors = new LinkedList<LogRecord>();
/** The Error Buffer History */
private LinkedList<LogRecord[]> m_history = new LinkedList<LogRecord[]>();
/** Log Size */
private static final int LOG_SIZE = 100;
/** The Log Buffer */
private LinkedList<LogRecord> m_logs = new LinkedList<LogRecord>();
/** Issue Error */
private volatile boolean m_issueError = true;
/**
* Initialize
@ -95,7 +93,13 @@ public class CLogErrorBuffer extends Handler
*/
public boolean isIssueError()
{
return m_issueError;
Boolean b = (Boolean) Env.getCtx().get(ISSUE_ERROR_KEY);
if (b == null)
{
b = Boolean.TRUE;
setIssueError(b);
}
return b;
} // isIssueError
/**
@ -104,7 +108,7 @@ public class CLogErrorBuffer extends Handler
*/
public void setIssueError(boolean issueError)
{
m_issueError = issueError;
Env.getCtx().put(ISSUE_ERROR_KEY, issueError);
} // setIssueError
/**
@ -134,6 +138,9 @@ public class CLogErrorBuffer extends Handler
*/
public void publish (LogRecord record)
{
checkContext();
LinkedList<LogRecord> m_logs = (LinkedList<LogRecord>) Env.getCtx().get(LOGS_KEY);
if (!isLoggable (record) || m_logs == null)
return;
@ -148,6 +155,8 @@ public class CLogErrorBuffer extends Handler
// We have an error
if (record.getLevel() == Level.SEVERE)
{
LinkedList<LogRecord> m_errors = (LinkedList<LogRecord>) Env.getCtx().get(ERRORS_KEY);
LinkedList<LogRecord[]> m_history = (LinkedList<LogRecord[]>) Env.getCtx().get(HISTORY_KEY);
if (m_errors.size() >= ERROR_SIZE)
{
m_errors.removeFirst();
@ -183,7 +192,7 @@ public class CLogErrorBuffer extends Handler
historyArray[no++] = (LogRecord)history.get(i);
m_history.add(historyArray);
// Issue Reporting
if (m_issueError)
if (isIssueError())
{
String loggerName = record.getLoggerName(); // class name
String className = record.getSourceClassName(); // physical class
@ -196,16 +205,16 @@ public class CLogErrorBuffer extends Handler
&& loggerName.indexOf("CConnection") == -1
)
{
m_issueError = false;
setIssueError(false);
try
{
MIssue.create(record);
m_issueError = true;
setIssueError(true);
} catch (Throwable e)
{
//failed to save exception to db, print to console
System.err.println(getFormatter().format(record));
m_issueError = false;
setIssueError(false);
}
}
else
@ -239,15 +248,9 @@ public class CLogErrorBuffer extends Handler
*/
public void close () throws SecurityException
{
if (m_logs != null)
m_logs.clear();
m_logs = null;
if (m_errors != null)
m_errors.clear();
m_errors = null;
if (m_history != null)
m_history.clear();
m_history = null;
Env.getCtx().remove(LOGS_KEY);
Env.getCtx().remove(ERRORS_KEY);
Env.getCtx().remove(HISTORY_KEY);
} // close
@ -308,6 +311,10 @@ public class CLogErrorBuffer extends Handler
*/
public LogRecord[] getRecords (boolean errorsOnly)
{
checkContext();
LinkedList<LogRecord> m_logs = (LinkedList<LogRecord>) Env.getCtx().get(LOGS_KEY);
LinkedList<LogRecord> m_errors = (LinkedList<LogRecord>) Env.getCtx().get(ERRORS_KEY);
LogRecord[] retValue = null;
if (errorsOnly)
{
@ -334,6 +341,11 @@ public class CLogErrorBuffer extends Handler
*/
public void resetBuffer (boolean errorsOnly)
{
checkContext();
LinkedList<LogRecord> m_logs = (LinkedList<LogRecord>) Env.getCtx().get(LOGS_KEY);
LinkedList<LogRecord> m_errors = (LinkedList<LogRecord>) Env.getCtx().get(ERRORS_KEY);
LinkedList<LogRecord[]> m_history = (LinkedList<LogRecord[]>) Env.getCtx().get(HISTORY_KEY);
synchronized (m_errors)
{
m_errors.clear();
@ -356,10 +368,13 @@ public class CLogErrorBuffer extends Handler
*/
public String getErrorInfo (Properties ctx, boolean errorsOnly)
{
checkContext();
StringBuffer sb = new StringBuffer();
//
if (errorsOnly)
{
LinkedList<LogRecord[]> m_history = (LinkedList<LogRecord[]>) Env.getCtx().get(HISTORY_KEY);
for (int i = 0; i < m_history.size(); i++)
{
sb.append("-------------------------------\n");
@ -373,6 +388,7 @@ public class CLogErrorBuffer extends Handler
}
else
{
LinkedList<LogRecord> m_logs = (LinkedList<LogRecord>) Env.getCtx().get(LOGS_KEY);
for (int i = 0; i < m_logs.size(); i++)
{
LogRecord record = (LogRecord)m_logs.get(i);
@ -386,12 +402,38 @@ public class CLogErrorBuffer extends Handler
return sb.toString();
} // getErrorInfo
private void checkContext()
{
if (!Env.getCtx().containsKey(LOGS_KEY))
{
LinkedList<LogRecord> m_logs = new LinkedList<LogRecord>();
Env.getCtx().put(LOGS_KEY, m_logs);
}
if (!Env.getCtx().containsKey(ERRORS_KEY))
{
LinkedList<LogRecord> m_errors = new LinkedList<LogRecord>();
Env.getCtx().put(ERRORS_KEY, m_errors);
}
if (!Env.getCtx().containsKey(HISTORY_KEY))
{
LinkedList<LogRecord[]> m_history = new LinkedList<LogRecord[]>();
Env.getCtx().put(HISTORY_KEY, m_history);
}
}
/**
* String Representation
* @return info
*/
public String toString ()
{
checkContext();
LinkedList<LogRecord> m_logs = (LinkedList<LogRecord>) Env.getCtx().get(LOGS_KEY);
LinkedList<LogRecord> m_errors = (LinkedList<LogRecord>) Env.getCtx().get(ERRORS_KEY);
LinkedList<LogRecord[]> m_history = (LinkedList<LogRecord[]>) Env.getCtx().get(HISTORY_KEY);
StringBuffer sb = new StringBuffer ("CLogErrorBuffer[");
sb.append("Errors=").append(m_errors.size())
.append(",History=").append(m_history.size())

View File

@ -28,6 +28,12 @@ import java.util.logging.*;
*/
public class CLogger extends Logger implements Serializable
{
private static final String LAST_INFO = "org.compiere.util.CLogger.lastInfo";
private static final String LAST_WARNING = "org.compiere.util.CLogger.lastWarning";
private static final String LAST_ERROR = "org.compiere.util.CLogger.lastError";
private static final String LAST_EXCEPTION = "org.compiere.util.CLogger.lastException";
/**
* Get Logger
* @param className class name
@ -91,15 +97,6 @@ public class CLogger extends Logger implements Serializable
/*************************************************************************/
/** Last Error Message */
private static ValueNamePair s_lastError = null;
/** Last Exception */
private static Exception s_lastException = null;
/** Last Warning Message */
private static ValueNamePair s_lastWarning = null;
/** Last Info Message */
private static ValueNamePair s_lastInfo = null;
/**
* Set and issue Error and save as ValueNamePair
* @param AD_Message message key
@ -119,7 +116,7 @@ public class CLogger extends Logger implements Serializable
*/
public boolean saveError (String AD_Message, Exception ex)
{
s_lastException = ex;
Env.getCtx().put(LAST_EXCEPTION, ex);
return saveError (AD_Message, ex.getLocalizedMessage(), true);
} // saveError
@ -132,7 +129,8 @@ public class CLogger extends Logger implements Serializable
*/
public boolean saveError (String AD_Message, String message, boolean issueError)
{
s_lastError = new ValueNamePair (AD_Message, message);
ValueNamePair lastError = new ValueNamePair (AD_Message, message);
Env.getCtx().put(LAST_ERROR, lastError);
// print it
if (issueError)
severe(AD_Message + " - " + message);
@ -145,8 +143,7 @@ public class CLogger extends Logger implements Serializable
*/
public static ValueNamePair retrieveError()
{
ValueNamePair vp = s_lastError;
s_lastError = null;
ValueNamePair vp = (ValueNamePair) Env.getCtx().remove(LAST_ERROR);
return vp;
} // retrieveError
@ -170,8 +167,7 @@ public class CLogger extends Logger implements Serializable
*/
public static Exception retrieveException()
{
Exception ex = s_lastException;
s_lastException = null;
Exception ex = (Exception) Env.getCtx().remove(LAST_EXCEPTION);
return ex;
} // retrieveError
@ -183,7 +179,8 @@ public class CLogger extends Logger implements Serializable
*/
public boolean saveWarning (String AD_Message, String message)
{
s_lastWarning = new ValueNamePair (AD_Message, message);
ValueNamePair lastWarning = new ValueNamePair(AD_Message, message);
Env.getCtx().put(LAST_WARNING, lastWarning);
// print it
if (true) // issueError
warning(AD_Message + " - " + message);
@ -196,8 +193,7 @@ public class CLogger extends Logger implements Serializable
*/
public static ValueNamePair retrieveWarning()
{
ValueNamePair vp = s_lastWarning;
s_lastWarning = null;
ValueNamePair vp = (ValueNamePair) Env.getCtx().remove(LAST_WARNING);
return vp;
} // retrieveWarning
@ -209,7 +205,9 @@ public class CLogger extends Logger implements Serializable
*/
public boolean saveInfo (String AD_Message, String message)
{
s_lastInfo = new ValueNamePair (AD_Message, message);
// s_lastInfo = new ValueNamePair (AD_Message, message);
ValueNamePair lastInfo = new ValueNamePair (AD_Message, message);
Env.getCtx().put(LAST_INFO, lastInfo);
return true;
} // saveInfo
@ -219,8 +217,7 @@ public class CLogger extends Logger implements Serializable
*/
public static ValueNamePair retrieveInfo()
{
ValueNamePair vp = s_lastInfo;
s_lastInfo = null;
ValueNamePair vp = (ValueNamePair) Env.getCtx().remove(LAST_INFO);
return vp;
} // retrieveInfo
@ -229,10 +226,10 @@ public class CLogger extends Logger implements Serializable
*/
public static void resetLast()
{
s_lastError = null;
s_lastException = null;
s_lastWarning = null;
s_lastInfo = null;
Env.getCtx().remove(LAST_ERROR);
Env.getCtx().remove(LAST_EXCEPTION);
Env.getCtx().remove(LAST_WARNING);
Env.getCtx().remove(LAST_INFO);
} // resetLast
/**