private void prepend(FrameBytes frameBytes) { Throwable failure; synchronized (queue) { failure = this.failure; if (failure == null) { int index = 0; while (index < queue.size()) { FrameBytes element = queue.get(index); if (element.compareTo(frameBytes) <= 0) break; ++index; } queue.add(index, frameBytes); } } if (failure != null) frameBytes.fail(new SPDYException(failure)); }
@Override public void failed(Throwable x) { List<FrameBytes> frameBytesToFail = new ArrayList<>(); frameBytesToFail.add(this); synchronized (queue) { failure = x; if (LOG.isDebugEnabled()) { String logMessage = String.format( "Failed write of %s, failing all %d frame(s) in queue", this, queue.size()); LOG.debug(logMessage, x); } frameBytesToFail.addAll(queue); queue.clear(); flushing = false; } for (FrameBytes fb : frameBytesToFail) fb.fail(x); }
@Override public int compareTo(FrameBytes that) { // FrameBytes may have or not have a related stream (for example, PING do not have a related // stream) // FrameBytes without related streams have higher priority IStream thisStream = getStream(); IStream thatStream = that.getStream(); if (thisStream == null) return thatStream == null ? 0 : -1; if (thatStream == null) return 1; // If this.stream.priority > that.stream.priority => this.stream has less priority than // that.stream return thatStream.getPriority() - thisStream.getPriority(); }
private void append(FrameBytes frameBytes) { Throwable failure; synchronized (queue) { failure = this.failure; if (failure == null) { // Frames containing headers must be send in the order the headers have been generated. We // don't need // to do this check in StandardSession.prepend() as no frames containing headers will be // prepended. if (frameBytes instanceof ControlFrameBytes) queue.addLast(frameBytes); else { int index = queue.size(); while (index > 0) { FrameBytes element = queue.get(index - 1); if (element.compareTo(frameBytes) >= 0) break; --index; } queue.add(index, frameBytes); } } } if (failure != null) frameBytes.fail(new SPDYException(failure)); }
@Override public void flush() { FrameBytes frameBytes = null; ByteBuffer buffer = null; boolean failFrameBytes = false; synchronized (queue) { if (flushing || queue.isEmpty()) return; Set<IStream> stalledStreams = null; for (int i = 0; i < queue.size(); ++i) { frameBytes = queue.get(i); IStream stream = frameBytes.getStream(); if (stream != null && stalledStreams != null && stalledStreams.contains(stream)) continue; buffer = frameBytes.getByteBuffer(); if (buffer != null) { queue.remove(i); if (stream != null && stream.isReset() && !(frameBytes instanceof ControlFrameBytes)) failFrameBytes = true; break; } if (stalledStreams == null) stalledStreams = new HashSet<>(); if (stream != null) stalledStreams.add(stream); LOG.debug("Flush stalled for {}, {} frame(s) in queue", frameBytes, queue.size()); } if (buffer == null) return; if (!failFrameBytes) { flushing = true; LOG.debug("Flushing {}, {} frame(s) in queue", frameBytes, queue.size()); } } if (failFrameBytes) { frameBytes.fail( new StreamException( frameBytes.getStream().getId(), StreamStatus.INVALID_STREAM, "Stream: " + frameBytes.getStream() + " is reset!")); } else { write(buffer, frameBytes); } }