diff --git a/modules/http2/src/main/java/org/glassfish/grizzly/http2/Http2OutputQueueRecord.java b/modules/http2/src/main/java/org/glassfish/grizzly/http2/Http2OutputQueueRecord.java new file mode 100644 index 0000000000..c4d9aea8a8 --- /dev/null +++ b/modules/http2/src/main/java/org/glassfish/grizzly/http2/Http2OutputQueueRecord.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014, 2019 Oracle and/or its affiliates and others. + * All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + * + * Contributors: + * Payara Services - Separated out into new class file. + */ +package org.glassfish.grizzly.http2; + +import java.util.List; + +import org.glassfish.grizzly.Buffer; +import org.glassfish.grizzly.CompletionHandler; +import org.glassfish.grizzly.WriteResult; +import org.glassfish.grizzly.asyncqueue.AsyncQueueRecord; +import org.glassfish.grizzly.http2.frames.DataFrame; +import org.glassfish.grizzly.http2.frames.Http2Frame; +import org.glassfish.grizzly.http2.utils.ChunkedCompletionHandler; + +public class Http2OutputQueueRecord extends AsyncQueueRecord { + + private final int streamId; + + private ChunkedCompletionHandler chunkedCompletionHandler; + private final CompletionHandler originalCompletionHandler; + private Buffer buffer; + private final boolean isLast; + + private final boolean isZeroSizeData; + + Http2OutputQueueRecord(final int streamId, final Buffer buffer, + final CompletionHandler completionHandler, final boolean isLast) { + super(null, null, null); + + this.streamId = streamId; + this.buffer = buffer; + this.isZeroSizeData = !buffer.hasRemaining(); + this.originalCompletionHandler = completionHandler; + this.isLast = isLast; + } + + @Override + public void notifyFailure(final Throwable e) { + final CompletionHandler chLocal = getCompletionHandler(); + if (chLocal != null) { + chLocal.failed(e); + } + } + + @Override + public void recycle() { + } + + @Override + public WriteResult getCurrentResult() { + return null; + } + + CompletionHandler getCompletionHandler() { + return chunkedCompletionHandler != null ? chunkedCompletionHandler : originalCompletionHandler; + } + + boolean isZeroSizeData() { + return isZeroSizeData; + } + + boolean isFinished() { + return buffer == null; + } + + int serializeTo(final List frames, final int maxDataSize) { + + final int recordSize = buffer.remaining(); + + if (recordSize <= maxDataSize) { + final DataFrame dataFrame = DataFrame.builder().streamId(streamId).data(buffer).endStream(isLast).build(); + + frames.add(dataFrame); + + buffer = null; + + return recordSize; + } else { + if (originalCompletionHandler != null && chunkedCompletionHandler == null) { + chunkedCompletionHandler = new ChunkedCompletionHandler(originalCompletionHandler); + } + + if (chunkedCompletionHandler != null) { + chunkedCompletionHandler.incChunks(); + } + + final Buffer remainder = buffer.split(buffer.position() + maxDataSize); + + final DataFrame dataFrame = DataFrame.builder().streamId(streamId).data(buffer).endStream(false).build(); + + frames.add(dataFrame); + + buffer = remainder; + + return maxDataSize; + } + } +} diff --git a/modules/http2/src/main/java/org/glassfish/grizzly/http2/Http2ServerFilter.java b/modules/http2/src/main/java/org/glassfish/grizzly/http2/Http2ServerFilter.java index f58296676a..28a6fb88ba 100644 --- a/modules/http2/src/main/java/org/glassfish/grizzly/http2/Http2ServerFilter.java +++ b/modules/http2/src/main/java/org/glassfish/grizzly/http2/Http2ServerFilter.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2015, 2017 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019 Oracle and/or its affiliates and others. + * All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -12,6 +13,9 @@ * https://www.gnu.org/software/classpath/license.html. * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + * + * Contributors: + * Payara Services - Fix to PUSH_PROMISE handling. */ package org.glassfish.grizzly.http2; @@ -1036,10 +1040,10 @@ private void doPush(final FilterChainContext ctx, final PushEvent pushEvent) { } } } + pushStream.onSendPushPromise(); http2Session.getOutputSink().writeDownStream(pushPromiseFrames); } finally { - pushStream.onSendPushPromise(); http2Session.getDeflaterLock().unlock(); } } finally { diff --git a/modules/http2/src/main/java/org/glassfish/grizzly/http2/Http2SessionOutputSink.java b/modules/http2/src/main/java/org/glassfish/grizzly/http2/Http2SessionOutputSink.java index ebefe28652..b7562edbd1 100644 --- a/modules/http2/src/main/java/org/glassfish/grizzly/http2/Http2SessionOutputSink.java +++ b/modules/http2/src/main/java/org/glassfish/grizzly/http2/Http2SessionOutputSink.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2014, 2017 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2019 Oracle and/or its affiliates and others. + * All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -12,6 +13,9 @@ * https://www.gnu.org/software/classpath/license.html. * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + * + * Contributors: + * Payara Services - Moved internal OutputQueueRecord into new class. */ package org.glassfish.grizzly.http2; @@ -52,7 +56,7 @@ public class Http2SessionOutputSink { private static final int MAX_OUTPUT_QUEUE_SIZE = 65536; // async output queue - private final TaskQueue outputQueue = + private final TaskQueue outputQueue = TaskQueue.createTaskQueue(new TaskQueue.MutableMaxQueueSize() { @Override @@ -182,7 +186,7 @@ protected void writeDataDownStream(final Http2Stream stream, data = messageCloner.clone(http2Session.getConnection(), data); } - final Http2SessionOutputSink.OutputQueueRecord record = new Http2SessionOutputSink.OutputQueueRecord( + final Http2OutputQueueRecord record = new Http2OutputQueueRecord( stream.getId(), data, completionHandler, isLast); @@ -227,7 +231,7 @@ private void flushOutputQueue() { while (availWindowSize > bytesToTransfer && queueSize > queueSizeToFree) { - final Http2SessionOutputSink.OutputQueueRecord record = outputQueue.poll(); + final Http2OutputQueueRecord record = outputQueue.poll(); if (record == null) { // keep this warning for now @@ -315,98 +319,4 @@ public void close() { outputQueue.onClose(); } - private static class OutputQueueRecord extends AsyncQueueRecord { - private final int streamId; - - private ChunkedCompletionHandler chunkedCompletionHandler; - private final CompletionHandler originalCompletionHandler; - private Buffer buffer; - private final boolean isLast; - - private final boolean isZeroSizeData; - - public OutputQueueRecord(final int streamId, - final Buffer buffer, - final CompletionHandler completionHandler, - final boolean isLast) { - super(null, null, null); - - this.streamId = streamId; - this.buffer = buffer; - this.isZeroSizeData = !buffer.hasRemaining(); - this.originalCompletionHandler = completionHandler; - this.isLast = isLast; - } - - public CompletionHandler getCompletionHandler() { - return chunkedCompletionHandler != null ? - chunkedCompletionHandler : - originalCompletionHandler; - } - - @Override - public void notifyFailure(final Throwable e) { - final CompletionHandler chLocal = getCompletionHandler(); - if (chLocal != null) { - chLocal.failed(e); - } - } - - @Override - public void recycle() { - } - - @Override - public WriteResult getCurrentResult() { - return null; - } - - private boolean isZeroSizeData() { - return isZeroSizeData; - } - - private boolean isFinished() { - return buffer == null; - } - - private int serializeTo(final List frames, - final int maxDataSize) { - - final int recordSize = buffer.remaining(); - - if (recordSize <= maxDataSize) { - final DataFrame dataFrame = DataFrame.builder() - .streamId(streamId) - .data(buffer).endStream(isLast) - .build(); - - frames.add(dataFrame); - - buffer = null; - - return recordSize; - } else { - if (originalCompletionHandler != null && chunkedCompletionHandler == null) { - chunkedCompletionHandler = new ChunkedCompletionHandler(originalCompletionHandler); - } - - if (chunkedCompletionHandler != null) { - chunkedCompletionHandler.incChunks(); - } - - final Buffer remainder = buffer.split(buffer.position() + maxDataSize); - - final DataFrame dataFrame = DataFrame.builder() - .streamId(streamId) - .data(buffer).endStream(false) - .build(); - - frames.add(dataFrame); - - buffer = remainder; - - return maxDataSize; - } - } - } }