costin 01/09/16 21:56:02 Modified: src/facade22/org/apache/tomcat/facade HttpSessionFacade.java src/share/org/apache/tomcat/modules/server Http10Interceptor.java src/share/org/apache/tomcat/util/buf DateTool.java MessageBytes.java Log: Number 7 on the todo list, keep DateFormat as a local variable in the response. The request/response is recycled and there is only one HttpResponse per thread - so no synchronization is needed. Initial fix for #1 ( I'm refering to Larry's "Remaining issues" ), it needs to be verified. I tried to avoid sync() on the typical case, and have the overhead only if the value implements the listener. Revision Changes Path 1.13 +29 -19 jakarta-tomcat/src/facade22/org/apache/tomcat/facade/HttpSessionFacade.java Index: HttpSessionFacade.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/HttpSessionFacade.java,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- HttpSessionFacade.java 2001/09/01 03:20:55 1.12 +++ HttpSessionFacade.java 2001/09/17 04:56:02 1.13 @@ -184,22 +184,24 @@ public void setAttribute(String name, Object value) { checkValid(); Object oldValue; - // ServerSessionManager ssm=(ServerSessionManager) - // realSession.getManager(); - // Original code - it's up to session manager to decide - // what it can handle. - // if (ssm.isDistributable() && - // !(value instanceof Serializable)) - // throw new IllegalArgumentException - // (sm.getString("standardSession.setAttribute.iae")); - oldValue=realSession.getAttribute( name) ; - if (oldValue!=null) { - removeAttribute(name); - } - if (value instanceof HttpSessionBindingListener) - ((HttpSessionBindingListener) value).valueBound - (new HttpSessionBindingEvent( this, name)); - realSession.setAttribute( name, value ); + if (value instanceof HttpSessionBindingListener) { + synchronized( this ) { + oldValue=realSession.getAttribute( name) ; + if (oldValue!=null) { + removeAttribute(name); + } + ((HttpSessionBindingListener) value).valueBound + (new HttpSessionBindingEvent( this, name)); + realSession.setAttribute( name, value ); + } + } else { + oldValue=realSession.getAttribute( name) ; + if (oldValue!=null) { + removeAttribute(name); + } + // no sync overhead + realSession.setAttribute( name, value ); + } } @@ -264,10 +266,18 @@ public void removeAttribute(String name) { checkValid(); Object object=realSession.getAttribute( name ); - realSession.removeAttribute(name); if (object instanceof HttpSessionBindingListener) { - ((HttpSessionBindingListener) object).valueUnbound - (new HttpSessionBindingEvent( this, name)); + synchronized( this ) { + // double check ( probably not needed since setAttribute calls + // remove if it detects a value + object=realSession.getAttribute( name ); + realSession.removeAttribute(name); + ((HttpSessionBindingListener) object).valueUnbound + (new HttpSessionBindingEvent( this, name)); + } + } else { + // Regular object, no sync overhead + realSession.removeAttribute(name); } } 1.23 +30 -20 jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Http10Interceptor.java Index: Http10Interceptor.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Http10Interceptor.java,v retrieving revision 1.22 retrieving revision 1.23 diff -u -r1.22 -r1.23 --- Http10Interceptor.java 2001/09/01 13:03:06 1.22 +++ Http10Interceptor.java 2001/09/17 04:56:02 1.23 @@ -63,9 +63,10 @@ import java.io.*; import java.net.*; import java.util.*; +import java.text.*; import org.apache.tomcat.core.*; import org.apache.tomcat.util.res.StringManager; -import org.apache.tomcat.util.buf.MessageBytes; +import org.apache.tomcat.util.buf.*; import org.apache.tomcat.util.http.*; import org.apache.tomcat.util.net.*; import org.apache.tomcat.util.net.ServerSocketFactory; @@ -127,8 +128,8 @@ Object thData[]=new Object[3]; HttpRequest reqA=new HttpRequest(); HttpResponse resA=new HttpResponse(); - if (reportedname != null) - resA.setReported(reportedname); + if (reportedname != null) + resA.setReported(reportedname); cm.initRequest( reqA, resA ); thData[0]=reqA; thData[1]=resA; @@ -333,11 +334,19 @@ class HttpResponse extends Response { Http10 http; String reportedname; + DateFormat dateFormat; public HttpResponse() { super(); } + public void init() { + super.init(); + dateFormat=new SimpleDateFormat(DateTool.RFC1123_PATTERN, + Locale.US); + dateFormat.setTimeZone(DateTool.GMT_ZONE); + } + public void setSocket( Socket s ) { http=((HttpRequest)request).http; } @@ -358,25 +367,26 @@ http.sendStatus( status, HttpMessages.getMessage( status )); - // Check if a Date is to be added - MessageBytes dateH=getMimeHeaders().getValue("Date"); - if( dateH == null ) { - // no date header set by user - getMimeHeaders().setValue( "Date" ).setTime( System.currentTimeMillis()); - } + // Check if a Date is to be added + MessageBytes dateH=getMimeHeaders().getValue("Date"); + if( dateH == null ) { + // no date header set by user + MessageBytes dateHeader=getMimeHeaders().setValue( "Date" ); + dateHeader.setTime( System.currentTimeMillis(), dateFormat); + } - // return server name (or the reported one) - if (reportedname == null) { - Context ctx = request.getContext(); - String server = ctx != null ? ctx.getEngineHeader() : + // return server name (or the reported one) + if (reportedname == null) { + Context ctx = request.getContext(); + String server = ctx != null ? ctx.getEngineHeader() : ContextManager.TOMCAT_NAME + "/" + ContextManager.TOMCAT_VERSION; - getMimeHeaders().setValue( "Server" ).setString(server); - } else { - if (reportedname.length() != 0) - getMimeHeaders().setValue( "Server" ).setString(reportedname); - } - - http.sendHeaders( getMimeHeaders() ); + getMimeHeaders().setValue( "Server" ).setString(server); + } else { + if (reportedname.length() != 0) + getMimeHeaders().setValue( "Server" ).setString(reportedname); + } + + http.sendHeaders( getMimeHeaders() ); } public void doWrite( byte buffer[], int pos, int count) 1.8 +10 -1 jakarta-tomcat/src/share/org/apache/tomcat/util/buf/DateTool.java Index: DateTool.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/buf/DateTool.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- DateTool.java 2001/09/15 01:31:32 1.7 +++ DateTool.java 2001/09/17 04:56:02 1.8 @@ -84,7 +84,7 @@ /** GMT timezone - all HTTP dates are on GMT */ - private final static TimeZone GMT_ZONE = TimeZone.getTimeZone("GMT"); + public final static TimeZone GMT_ZONE = TimeZone.getTimeZone("GMT"); /** format for RFC 1123 date string -- "Sun, 06 Nov 1994 08:49:37 GMT" */ @@ -146,6 +146,15 @@ if ((rfc1123DS != null) && (dt == rfc1123Sec)) return rfc1123DS; rfc1123DS = rfc1123Format.format( d ); + rfc1123Sec = dt; + return rfc1123DS; + } + + public static String format1123( Date d,DateFormat df ) { + long dt = d.getTime() % 1000; + if ((rfc1123DS != null) && (dt == rfc1123Sec)) + return rfc1123DS; + rfc1123DS = df.format( d ); rfc1123Sec = dt; return rfc1123DS; } 1.7 +11 -3 jakarta-tomcat/src/share/org/apache/tomcat/util/buf/MessageBytes.java Index: MessageBytes.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/buf/MessageBytes.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- MessageBytes.java 2001/08/31 04:11:56 1.6 +++ MessageBytes.java 2001/09/17 04:56:02 1.7 @@ -503,19 +503,27 @@ /** * @deprecated The buffer are general purpose, caching for headers should - * be done in headers + * be done in headers. The second parameter allows us to pass a date format + * instance to avoid synchronization problems. */ - public void setTime(long t) { + public void setTime(long t, DateFormat df) { // XXX replace it with a byte[] tool recycle(); if( dateValue==null) dateValue=new Date(t); else dateValue.setTime(t); - strValue=DateTool.format1123(dateValue); + if( df==null ) + strValue=DateTool.format1123(dateValue); + else + strValue=DateTool.format1123(dateValue,df); hasStrValue=true; hasDateValue=true; type=T_STR; + } + + public void setTime(long t) { + setTime( t, null ); } /** Set the buffer to the representation of an int