Author: markt Date: Sat Apr 5 11:39:30 2008 New Revision: 645159 URL: http://svn.apache.org/viewvc?rev=645159&view=rev Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=44646 Get this valve working for a basic comet app.
Modified: tomcat/tc6.0.x/trunk/STATUS.txt tomcat/tc6.0.x/trunk/java/org/apache/catalina/valves/CometConnectionManagerValve.java tomcat/tc6.0.x/trunk/java/org/apache/catalina/valves/LocalStrings.properties tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Modified: tomcat/tc6.0.x/trunk/STATUS.txt URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=645159&r1=645158&r2=645159&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/STATUS.txt (original) +++ tomcat/tc6.0.x/trunk/STATUS.txt Sat Apr 5 11:39:30 2008 @@ -60,12 +60,6 @@ +1: markt, fhanik -1: -* Get o.a.c.valves.CometConnectionManagerValve working - Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=44646 - http://svn.apache.org/viewvc?rev=640273&view=rev - +1: markt, remm, fhanik - -1: - * Prevent the connector entering an infinite loop https://issues.apache.org/bugzilla/show_bug.cgi?id=44620 http://svn.apache.org/viewvc?rev=640572&view=rev Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/valves/CometConnectionManagerValve.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/valves/CometConnectionManagerValve.java?rev=645159&r1=645158&r2=645159&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/valves/CometConnectionManagerValve.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/valves/CometConnectionManagerValve.java Sat Apr 5 11:39:30 2008 @@ -20,8 +20,10 @@ import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; -import java.util.concurrent.ConcurrentHashMap; +import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpSession; @@ -29,6 +31,7 @@ import javax.servlet.http.HttpSessionListener; import org.apache.catalina.CometEvent; +import org.apache.catalina.CometProcessor; import org.apache.catalina.Context; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleEvent; @@ -86,12 +89,19 @@ /** - * Connection list. + * List of current Coment connections. */ - protected ConcurrentHashMap<String, ConnectionInfo[]> connections - = new ConcurrentHashMap<String, ConnectionInfo[]>(); + protected List<Request> cometRequests = + Collections.synchronizedList(new ArrayList<Request>()); + /** + * Name of session attribute used to store list of comet connections. + */ + protected String cometRequestsAttribute = + "org.apache.tomcat.comet.connectionList"; + + // ------------------------------------------------------------- Properties @@ -178,54 +188,36 @@ ((Lifecycle) container).removeLifecycleListener(this); } - // The webapp is getting stopped, so all current connections - // should be closed - // Close all Comet connections associated with this session - // Note: this will only be done if the container was not a Context - // (otherwise, this needs to be done before stop, as the servlet would - // be deallocated already) - Iterator<ConnectionInfo[]> iterator = connections.values().iterator(); - while (iterator.hasNext()) { - ConnectionInfo[] connectionInfos = iterator.next(); - if (connectionInfos != null) { - for (int i = 0; i < connectionInfos.length; i++) { - ConnectionInfo connectionInfo = connectionInfos[i]; - try { - connectionInfo.event.close(); - } catch (Exception e) { - container.getLogger().warn(sm.getString("cometConnectionManagerValve.event"), e); - } - } - } - } - connections.clear(); - } public void lifecycleEvent(LifecycleEvent event) { if (event.getType() == Lifecycle.BEFORE_STOP_EVENT) { - // The webapp is getting stopped, so all current connections - // should be closed - // Close all Comet connections associated with this session - Iterator<ConnectionInfo[]> iterator = connections.values().iterator(); + // The container is getting stopped, close all current connections + Iterator<Request> iterator = cometRequests.iterator(); while (iterator.hasNext()) { - ConnectionInfo[] connectionInfos = iterator.next(); - if (connectionInfos != null) { - for (int i = 0; i < connectionInfos.length; i++) { - ConnectionInfo connectionInfo = connectionInfos[i]; - try { - ((CometEventImpl) connectionInfo.event).setEventType(CometEvent.EventType.END); - ((CometEventImpl) connectionInfo.event).setEventSubType(CometEvent.EventSubType.WEBAPP_RELOAD); - getNext().event(connectionInfo.request, connectionInfo.response, connectionInfo.event); - connectionInfo.event.close(); - } catch (Exception e) { - container.getLogger().warn(sm.getString("cometConnectionManagerValve.event"), e); - } - } + Request request = iterator.next(); + // Remove the session tracking attribute as it isn't + // serializable or required. + HttpSession session = request.getSession(false); + if (session != null) { + session.removeAttribute(cometRequestsAttribute); + } + // Close the comet connection + try { + CometEventImpl cometEvent = request.getEvent(); + cometEvent.setEventType(CometEvent.EventType.END); + cometEvent.setEventSubType( + CometEvent.EventSubType.WEBAPP_RELOAD); + getNext().event(request, request.getResponse(), cometEvent); + cometEvent.close(); + } catch (Exception e) { + container.getLogger().warn( + sm.getString("cometConnectionManagerValve.event"), + e); } } - connections.clear(); + cometRequests.clear(); } } @@ -259,25 +251,27 @@ // Start tracking this connection, since this is a // begin event, and Comet mode is on HttpSession session = request.getSession(true); - ConnectionInfo newConnectionInfo = new ConnectionInfo(); - newConnectionInfo.request = request; - newConnectionInfo.response = response; - newConnectionInfo.event = request.getEvent(); + + // Track the conection for webapp reload + cometRequests.add(request); + + // Track the connection for session expiration synchronized (session) { - String id = session.getId(); - ConnectionInfo[] connectionInfos = connections.get(id); - if (connectionInfos == null) { - connectionInfos = new ConnectionInfo[1]; - connectionInfos[0] = newConnectionInfo; - connections.put(id, connectionInfos); + Request[] requests = (Request[]) + session.getAttribute(cometRequestsAttribute); + if (requests == null) { + requests = new Request[1]; + requests[0] = request; + session.setAttribute(cometRequestsAttribute, + requests); } else { - ConnectionInfo[] newConnectionInfos = - new ConnectionInfo[connectionInfos.length + 1]; - for (int i = 0; i < connectionInfos.length; i++) { - newConnectionInfos[i] = connectionInfos[i]; + Request[] newRequests = + new Request[requests.length + 1]; + for (int i = 0; i < requests.length; i++) { + newRequests[i] = requests[i]; } - newConnectionInfos[connectionInfos.length] = newConnectionInfo; - connections.put(id, newConnectionInfos); + newRequests[requests.length] = request; + session.setAttribute(cometRequestsAttribute, newRequests); } } } @@ -306,32 +300,48 @@ if (!ok || response.isClosed() || (event.getEventType() == CometEvent.EventType.END) || (event.getEventType() == CometEvent.EventType.ERROR - && !(event.getEventSubType() == CometEvent.EventSubType.TIMEOUT))) { - // Remove from tracked list, the connection is done - HttpSession session = request.getSession(true); - synchronized (session) { - ConnectionInfo[] connectionInfos = connections.get(session.getId()); - if (connectionInfos != null) { - boolean found = false; - for (int i = 0; !found && (i < connectionInfos.length); i++) { - found = (connectionInfos[i].request == request); - } - if (found) { - ConnectionInfo[] newConnectionInfos = - new ConnectionInfo[connectionInfos.length - 1]; - int pos = 0; - for (int i = 0; i < connectionInfos.length; i++) { - if (connectionInfos[i].request != request) { - newConnectionInfos[pos++] = connectionInfos[i]; + && !(event.getEventSubType() == + CometEvent.EventSubType.TIMEOUT))) { + + // Remove the connection from webapp reload tracking + cometRequests.remove(request); + + // Remove connection from session expiration tracking + // Note: can't get the session if it has been invalidated but + // OK since session listener will have done clean-up + HttpSession session = request.getSession(false); + if (session != null) { + synchronized (session) { + Request[] reqs = (Request[]) + session.getAttribute(cometRequestsAttribute); + if (reqs != null) { + boolean found = false; + for (int i = 0; !found && (i < reqs.length); i++) { + found = (reqs[i] == request); + } + if (found) { + if (reqs.length > 1) { + Request[] newConnectionInfos = + new Request[reqs.length - 1]; + int pos = 0; + for (int i = 0; i < reqs.length; i++) { + if (reqs[i] != request) { + newConnectionInfos[pos++] = reqs[i]; + } + } + session.setAttribute(cometRequestsAttribute, + newConnectionInfos); + } else { + session.removeAttribute( + cometRequestsAttribute); } } - connections.put(session.getId(), newConnectionInfos); } } - } + } } } - + } @@ -341,31 +351,24 @@ public void sessionDestroyed(HttpSessionEvent se) { // Close all Comet connections associated with this session - ConnectionInfo[] connectionInfos = connections.remove(se.getSession().getId()); - if (connectionInfos != null) { - for (int i = 0; i < connectionInfos.length; i++) { - ConnectionInfo connectionInfo = connectionInfos[i]; + Request[] reqs = (Request[]) + se.getSession().getAttribute(cometRequestsAttribute); + if (reqs != null) { + for (int i = 0; i < reqs.length; i++) { + Request req = reqs[i]; try { - ((CometEventImpl) connectionInfo.event).setEventType(CometEvent.EventType.END); - ((CometEventImpl) connectionInfo.event).setEventSubType(CometEvent.EventSubType.SESSION_END); - getNext().event(connectionInfo.request, connectionInfo.response, connectionInfo.event); - connectionInfo.event.close(); + CometEventImpl event = req.getEvent(); + event.setEventType(CometEvent.EventType.END); + event.setEventSubType(CometEvent.EventSubType.SESSION_END); + ((CometProcessor) + req.getWrapper().getServlet()).event(event); + event.close(); } catch (Exception e) { - container.getLogger().warn(sm.getString("cometConnectionManagerValve.event"), e); + req.getWrapper().getParent().getLogger().warn(sm.getString( + "cometConnectionManagerValve.listenerEvent"), e); } } } } - - - // --------------------------------------------- ConnectionInfo Inner Class - - - protected class ConnectionInfo { - public CometEvent event; - public Request request; - public Response response; - } - } Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/valves/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/valves/LocalStrings.properties?rev=645159&r1=645158&r2=645159&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/valves/LocalStrings.properties (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/valves/LocalStrings.properties Sat Apr 5 11:39:30 2008 @@ -27,6 +27,7 @@ jdbcAccessLogValve.exception=Exception performing insert access entry jdbcAccessLogValve.close=Exception closing database connection cometConnectionManagerValve.event=Exception processing event +cometConnectionManagerValve.listenerEvent=Exception processing session listener event # Error report valve errorReportValve.errorReport=Error report Modified: tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml?rev=645159&r1=645158&r2=645159&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Sat Apr 5 11:39:30 2008 @@ -75,6 +75,10 @@ be loaded due to a version error. (rjung/markt) </fix> <fix> + <bug>44646</bug>: Correct various issues, including an ISE, in + CometConnectionManagerValve. (markt) + </fix> + <fix> <bug>44673</bug>: ServletInputStream is no longer readable once closed. (markt) </fix> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]