Author: markt Date: Wed May 13 17:44:47 2015 New Revision: 1679251 URL: http://svn.apache.org/r1679251 Log: Lay some groundwork for processing priority frames
Added: tomcat/trunk/java/org/apache/coyote/http2/AbstractStream.java (with props) tomcat/trunk/test/org/apache/coyote/http2/TestAbstractStream.java (with props) Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java tomcat/trunk/java/org/apache/coyote/http2/Stream.java Added: tomcat/trunk/java/org/apache/coyote/http2/AbstractStream.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/AbstractStream.java?rev=1679251&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/AbstractStream.java (added) +++ tomcat/trunk/java/org/apache/coyote/http2/AbstractStream.java Wed May 13 17:44:47 2015 @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.coyote.http2; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +/** + * Used to managed prioritisation. + */ +abstract class AbstractStream { + + private static final int DEFAULT_WEIGHT = 16; + + private final Integer identifier; + + private volatile AbstractStream parentStream = null; + private final Set<AbstractStream> childStreams = new HashSet<>(); + private volatile int weight = DEFAULT_WEIGHT; + + public Integer getIdentifier() { + return identifier; + } + + + public AbstractStream(Integer identifier) { + this.identifier = identifier; + } + + + public void rePrioritise(Stream parent, boolean exclusive, int weight) { + // Check if new parent is a descendant of this stream + if (isDescendant(parent)) { + parent.detachFromParent(); + parentStream.addChild(parent); + } + + if (exclusive) { + // Need to move children of the new parent to be children of this + // stream. Slightly convoluted to avoid concurrent modification. + Iterator<AbstractStream> parentsChildren = parent.getChildStreams().iterator(); + while (parentsChildren.hasNext()) { + AbstractStream parentsChild = parentsChildren.next(); + parentsChildren.remove(); + this.addChild(parentsChild); + } + } + parent.addChild(this); + this.weight = weight; + } + + + void detachFromParent() { + if (parentStream != null) { + parentStream.getChildStreams().remove(this); + parentStream = null; + } + } + + + void addChild(AbstractStream child) { + child.setParent(this); + childStreams.add(child); + } + + + private void setParent(AbstractStream parent) { + this.parentStream = parent; + } + + + boolean isDescendant(AbstractStream stream) { + if (childStreams.contains(stream)) { + return true; + } + for (AbstractStream child : childStreams) { + if (child.isDescendant(stream)) { + return true; + } + } + return false; + } + + + AbstractStream getParentStream() { + return parentStream; + } + + + void setParentStream(AbstractStream parentStream) { + this.parentStream = parentStream; + } + + + Set<AbstractStream> getChildStreams() { + return childStreams; + } +} Propchange: tomcat/trunk/java/org/apache/coyote/http2/AbstractStream.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java?rev=1679251&r1=1679250&r2=1679251&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java (original) +++ tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java Wed May 13 17:44:47 2015 @@ -45,11 +45,13 @@ import org.apache.tomcat.util.res.String * network.http.spdy.enforce-tls-profile=false in order for FireFox to be able * to connect. */ -public class Http2UpgradeHandler implements InternalHttpUpgradeHandler { +public class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeHandler { private static final Log log = LogFactory.getLog(Http2UpgradeHandler.class); private static final StringManager sm = StringManager.getManager(Http2UpgradeHandler.class); + private static final Integer STREAM_ID_ZERO = Integer.valueOf(0); + private static final int FRAME_TYPE_SETTINGS = 4; private static final int FRAME_TYPE_WINDOW_UPDATE = 8; @@ -68,6 +70,12 @@ public class Http2UpgradeHandler impleme private final Map<Integer,Stream> streams = new HashMap<>(); + + public Http2UpgradeHandler() { + super (STREAM_ID_ZERO); + } + + @Override public void init(WebConnection unused) { initialized = true; @@ -271,7 +279,7 @@ public class Http2UpgradeHandler impleme Integer key = Integer.valueOf(streamId); Stream stream = streams.get(key); if (stream == null) { - stream = new Stream(key, remoteSettings.getInitialWindowSize()); + stream = new Stream(key, this); } stream.incrementWindowSize(windowSizeIncrement); } @@ -362,6 +370,11 @@ public class Http2UpgradeHandler impleme } + ConnectionSettings getRemoteSettings() { + return remoteSettings; + } + + @Override public void destroy() { // NO-OP Modified: tomcat/trunk/java/org/apache/coyote/http2/Stream.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Stream.java?rev=1679251&r1=1679250&r2=1679251&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/Stream.java (original) +++ tomcat/trunk/java/org/apache/coyote/http2/Stream.java Wed May 13 17:44:47 2015 @@ -16,20 +16,15 @@ */ package org.apache.coyote.http2; -public class Stream { - - private final Integer identifier; +public class Stream extends AbstractStream { private volatile long flowControlWindowSize; - public Stream(Integer identifier, long intitalWindowSize) { - this.identifier = identifier; - flowControlWindowSize = intitalWindowSize; - } - - public Integer getIdentifier() { - return identifier; + public Stream(Integer identifier, Http2UpgradeHandler handler) { + super(identifier); + setParentStream(handler); + flowControlWindowSize = handler.getRemoteSettings().getInitialWindowSize(); } Added: tomcat/trunk/test/org/apache/coyote/http2/TestAbstractStream.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestAbstractStream.java?rev=1679251&view=auto ============================================================================== --- tomcat/trunk/test/org/apache/coyote/http2/TestAbstractStream.java (added) +++ tomcat/trunk/test/org/apache/coyote/http2/TestAbstractStream.java Wed May 13 17:44:47 2015 @@ -0,0 +1,172 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.coyote.http2; + +import org.junit.Assert; +import org.junit.Test; + +/* + * This tests use A=1, B=2, etc to map stream IDs to the names used in the + * figures. + */ +public class TestAbstractStream { + + @Test + public void testDependenciesFig3() { + // Setup + Http2UpgradeHandler handler = new Http2UpgradeHandler(); + Stream a = new Stream(Integer.valueOf(1), handler); + Stream b = new Stream(Integer.valueOf(2), handler); + Stream c = new Stream(Integer.valueOf(3), handler); + Stream d = new Stream(Integer.valueOf(4), handler); + b.rePrioritise(a, false, 16); + c.rePrioritise(a, false, 16); + + // Action + d.rePrioritise(a, false, 16); + + // Check parents + Assert.assertEquals(handler, a.getParentStream()); + Assert.assertEquals(a, b.getParentStream()); + Assert.assertEquals(a, c.getParentStream()); + Assert.assertEquals(a, d.getParentStream()); + + // Check children + Assert.assertEquals(3, a.getChildStreams().size()); + Assert.assertTrue(a.getChildStreams().contains(b)); + Assert.assertTrue(a.getChildStreams().contains(c)); + Assert.assertTrue(a.getChildStreams().contains(d)); + Assert.assertEquals(0, b.getChildStreams().size()); + Assert.assertEquals(0, c.getChildStreams().size()); + Assert.assertEquals(0, d.getChildStreams().size()); + } + + + @Test + public void testDependenciesFig4() { + // Setup + Http2UpgradeHandler handler = new Http2UpgradeHandler(); + Stream a = new Stream(Integer.valueOf(1), handler); + Stream b = new Stream(Integer.valueOf(2), handler); + Stream c = new Stream(Integer.valueOf(3), handler); + Stream d = new Stream(Integer.valueOf(4), handler); + b.rePrioritise(a, false, 16); + c.rePrioritise(a, false, 16); + + // Action + d.rePrioritise(a, true, 16); + + // Check parents + Assert.assertEquals(handler, a.getParentStream()); + Assert.assertEquals(d, b.getParentStream()); + Assert.assertEquals(d, c.getParentStream()); + Assert.assertEquals(a, d.getParentStream()); + + // Check children + Assert.assertEquals(1, a.getChildStreams().size()); + Assert.assertTrue(a.getChildStreams().contains(d)); + Assert.assertEquals(2, d.getChildStreams().size()); + Assert.assertTrue(d.getChildStreams().contains(b)); + Assert.assertTrue(d.getChildStreams().contains(c)); + Assert.assertEquals(0, b.getChildStreams().size()); + Assert.assertEquals(0, c.getChildStreams().size()); + } + + + @Test + public void testDependenciesFig5NonExclusive() { + // Setup + Http2UpgradeHandler handler = new Http2UpgradeHandler(); + Stream a = new Stream(Integer.valueOf(1), handler); + Stream b = new Stream(Integer.valueOf(2), handler); + Stream c = new Stream(Integer.valueOf(3), handler); + Stream d = new Stream(Integer.valueOf(4), handler); + Stream e = new Stream(Integer.valueOf(5), handler); + Stream f = new Stream(Integer.valueOf(6), handler); + b.rePrioritise(a, false, 16); + c.rePrioritise(a, false, 16); + d.rePrioritise(c, false, 16); + e.rePrioritise(c, false, 16); + f.rePrioritise(d, false, 16); + + // Action + a.rePrioritise(d, false, 16); + + // Check parents + Assert.assertEquals(handler, d.getParentStream()); + Assert.assertEquals(d, f.getParentStream()); + Assert.assertEquals(d, a.getParentStream()); + Assert.assertEquals(a, b.getParentStream()); + Assert.assertEquals(a, c.getParentStream()); + Assert.assertEquals(c, e.getParentStream()); + + // Check children + Assert.assertEquals(2, d.getChildStreams().size()); + Assert.assertTrue(d.getChildStreams().contains(a)); + Assert.assertTrue(d.getChildStreams().contains(f)); + Assert.assertEquals(0, f.getChildStreams().size()); + Assert.assertEquals(2, a.getChildStreams().size()); + Assert.assertTrue(a.getChildStreams().contains(b)); + Assert.assertTrue(a.getChildStreams().contains(c)); + Assert.assertEquals(0, b.getChildStreams().size()); + Assert.assertEquals(1, c.getChildStreams().size()); + Assert.assertTrue(c.getChildStreams().contains(e)); + Assert.assertEquals(0, e.getChildStreams().size()); + } + + + @Test + public void testDependenciesFig5Exclusive() { + // Setup + Http2UpgradeHandler handler = new Http2UpgradeHandler(); + Stream a = new Stream(Integer.valueOf(1), handler); + Stream b = new Stream(Integer.valueOf(2), handler); + Stream c = new Stream(Integer.valueOf(3), handler); + Stream d = new Stream(Integer.valueOf(4), handler); + Stream e = new Stream(Integer.valueOf(5), handler); + Stream f = new Stream(Integer.valueOf(6), handler); + b.rePrioritise(a, false, 16); + c.rePrioritise(a, false, 16); + d.rePrioritise(c, false, 16); + e.rePrioritise(c, false, 16); + f.rePrioritise(d, false, 16); + + // Action + a.rePrioritise(d, true, 16); + + // Check parents + Assert.assertEquals(handler, d.getParentStream()); + Assert.assertEquals(d, a.getParentStream()); + Assert.assertEquals(a, b.getParentStream()); + Assert.assertEquals(a, c.getParentStream()); + Assert.assertEquals(a, f.getParentStream()); + Assert.assertEquals(c, e.getParentStream()); + + // Check children + Assert.assertEquals(1, d.getChildStreams().size()); + Assert.assertTrue(d.getChildStreams().contains(a)); + Assert.assertEquals(3, a.getChildStreams().size()); + Assert.assertTrue(a.getChildStreams().contains(b)); + Assert.assertTrue(a.getChildStreams().contains(c)); + Assert.assertTrue(a.getChildStreams().contains(f)); + Assert.assertEquals(0, b.getChildStreams().size()); + Assert.assertEquals(0, f.getChildStreams().size()); + Assert.assertEquals(1, c.getChildStreams().size()); + Assert.assertTrue(c.getChildStreams().contains(e)); + Assert.assertEquals(0, e.getChildStreams().size()); + } +} Propchange: tomcat/trunk/test/org/apache/coyote/http2/TestAbstractStream.java ------------------------------------------------------------------------------ svn:eol-style = native --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org