comparison src/org/eclipse/jetty/http/HttpGenerator.java @ 1070:a44fc6b53757

fix use of HttpGenerator._buffer
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 10 Nov 2016 01:23:37 -0700
parents 7dd6ec499000
children b4ba8a4d5a16
comparison
equal deleted inserted replaced
1069:7dd6ec499000 1070:a44fc6b53757
176 if (_head) 176 if (_head)
177 { 177 {
178 // content.clear(); 178 // content.clear();
179 _content = null; 179 _content = null;
180 } 180 }
181 else if ((_buffer==null || _buffer.remaining()==0) && _content.hasRemaining() && (_last || isCommitted() && _content.remaining()>1024)) 181 else if ((_buffer.position()==0) && _content.hasRemaining() && (_last || isCommitted() && _content.remaining()>1024))
182 { 182 {
183 _bypass = true; 183 _bypass = true;
184 } 184 }
185 else if (!_bufferChunked) 185 else if (!_bufferChunked)
186 { 186 {
187 //System.out.println("qqqqqqqqqqqqqqqqqqq c"); 187 //System.out.println("qqqqqqqqqqqqqqqqqqq c");
188 // Copy _content to buffer; 188 // Copy _content to buffer;
189 int len = _buffer.put(_content); 189 _buffer.putQ(_content);
190 _content.skip(len);
191 if (!_content.hasRemaining()) 190 if (!_content.hasRemaining())
192 _content = null; 191 _content = null;
193 } 192 }
194 } 193 }
195 194
215 flushBuffer(); 214 flushBuffer();
216 if (_content != null && _content.hasRemaining() || _bufferChunked) 215 if (_content != null && _content.hasRemaining() || _bufferChunked)
217 throw new IllegalStateException("FULL"); 216 throw new IllegalStateException("FULL");
218 } 217 }
219 218
220 _contentWritten -= _buffer.remaining(); 219 _contentWritten -= _buffer.position();
221 /* 220 /*
222 // Handle the _content 221 // Handle the _content
223 if (_head) 222 if (_head)
224 return Integer.MAX_VALUE; 223 return Integer.MAX_VALUE;
225 224
228 } 227 }
229 228
230 public boolean isBufferFull() 229 public boolean isBufferFull()
231 { 230 {
232 // Should we flush the buffers? 231 // Should we flush the buffers?
233 return isBufferFull2() || _bufferChunked || _bypass /* || (_contentLength == HttpTokens.CHUNKED_CONTENT && _buffer != null && _buffer.space() < CHUNK_SPACE)*/; 232 return isBufferFull2() || _bufferChunked || _bypass /* || (_contentLength == HttpTokens.CHUNKED_CONTENT && _buffer.remaining() < CHUNK_SPACE)*/;
234 } 233 }
235 234
236 public void send1xx(int code) throws IOException 235 public void send1xx(int code) throws IOException
237 { 236 {
238 if (_state != STATE_HEADER) 237 if (_state != STATE_HEADER)
332 331
333 if (_status<200 && _status>=100 ) 332 if (_status<200 && _status>=100 )
334 { 333 {
335 _noContent = true; 334 _noContent = true;
336 _content = null; 335 _content = null;
337 if (_buffer!=null) 336 _buffer.clear();
338 _buffer.clearJ();
339 // end the header. 337 // end the header.
340 338
341 if (_status!=101 ) 339 if (_status!=101 )
342 { 340 {
343 _header.putQ(HttpTokens.CRLF); 341 _header.putQ(HttpTokens.CRLF);
347 } 345 }
348 else if (_status==204 || _status==304) 346 else if (_status==204 || _status==304)
349 { 347 {
350 _noContent = true; 348 _noContent = true;
351 _content = null; 349 _content = null;
352 if (_buffer!=null) 350 _buffer.clear();
353 _buffer.clearJ();
354 } 351 }
355 } 352 }
356 353
357 // key field values 354 // key field values
358 HttpFields.Field content_length = null; 355 HttpFields.Field content_length = null;
668 //qqq 665 //qqq
669 case 7: 666 case 7:
670 throw new IllegalStateException(); // should never happen! 667 throw new IllegalStateException(); // should never happen!
671 case 6: 668 case 6:
672 _header.flip(); 669 _header.flip();
670 _buffer.flip();
673 len = _endp.flush(_header, _buffer, null); 671 len = _endp.flush(_header, _buffer, null);
674 _header.compact(); 672 _header.compact();
673 _buffer.compact();
675 break; 674 break;
676 case 5: 675 case 5:
677 _header.flip(); 676 _header.flip();
678 len = _endp.flush(_header, _content, null); 677 len = _endp.flush(_header, _content, null);
679 _header.compact(); 678 _header.compact();
682 _header.flip(); 681 _header.flip();
683 len = _endp.flush(_header); 682 len = _endp.flush(_header);
684 _header.compact(); 683 _header.compact();
685 break; 684 break;
686 case 3: 685 case 3:
686 _buffer.flip();
687 len = _endp.flush(_buffer, _content, null); 687 len = _endp.flush(_buffer, _content, null);
688 _buffer.compact();
688 break; 689 break;
689 case 2: 690 case 2:
691 _buffer.flip();
690 len = _endp.flush(_buffer); 692 len = _endp.flush(_buffer);
693 _buffer.compact();
691 break; 694 break;
692 case 1: 695 case 1:
693 len = _endp.flush(_content); 696 len = _endp.flush(_content);
694 break; 697 break;
695 case 0: 698 case 0:
696 { 699 {
697 len=0; 700 len = 0;
698 // Nothing more we can write now. 701 // Nothing more we can write now.
699 _header.clear(); 702 _header.clear();
700 703
701 _bypass = false; 704 _bypass = false;
702 _bufferChunked = false; 705 _bufferChunked = false;
703 706
704 if (_buffer != null) 707 _buffer.clear(); // ?
708 if (_contentLength == HttpTokens.CHUNKED_CONTENT)
705 { 709 {
706 _buffer.clearJ(); 710 // Special case handling for small left over buffer from
707 if (_contentLength == HttpTokens.CHUNKED_CONTENT) 711 // an addContent that caused a buffer flush.
712 if (_content != null && _content.remaining() < _buffer.remaining() && _state != STATE_FLUSHING)
708 { 713 {
709 // Special case handling for small left over buffer from 714 _buffer.putQ(_content);
710 // an addContent that caused a buffer flush. 715 _content = null;
711 if (_content != null && _content.remaining() < _buffer.space() && _state != STATE_FLUSHING)
712 {
713 _buffer.put(_content);
714 _content = null;
715 }
716 } 716 }
717 } 717 }
718 718
719 // Are we completely finished for now? 719 // Are we completely finished for now?
720 if (!_needCRLF && !_needEOC && (_content==null || !_content.hasRemaining())) 720 if (!_needCRLF && !_needEOC && (_content==null || !_content.hasRemaining()))
743 return total; 743 return total;
744 } 744 }
745 catch (IOException e) 745 catch (IOException e)
746 { 746 {
747 LOG.trace("",e); 747 LOG.trace("",e);
748 throw (e instanceof EofException) ? e:new EofException(e); 748 throw (e instanceof EofException) ? e : new EofException(e);
749 } 749 }
750 } 750 }
751 751
752 private int flushMask() 752 private int flushMask()
753 { 753 {
754 return ((_header.position() > 0)?4:0) 754 return ((_header.position() > 0)?4:0)
755 | ((_buffer != null && _buffer.remaining() > 0)?2:0) 755 | ((_buffer.position() > 0)?2:0)
756 | ((_bypass && _content != null && _content.hasRemaining())?1:0); 756 | ((_bypass && _content != null && _content.hasRemaining())?1:0);
757 } 757 }
758 758
759 private void prepareBuffers() 759 private void prepareBuffers()
760 { 760 {
761 // if we are not flushing an existing chunk 761 // if we are not flushing an existing chunk
762 if (!_bufferChunked) 762 if (!_bufferChunked)
763 { 763 {
764 // Refill buffer if possible 764 // Refill buffer if possible
765 if (!_bypass && _content != null && _content.hasRemaining() && _buffer != null && _buffer.space() > 0) 765 if (!_bypass && _content != null && _content.hasRemaining() && _buffer.hasRemaining())
766 { 766 {
767 int len = _buffer.put(_content); 767 _buffer.putQ(_content);
768 _content.skip(len);
769 if (!_content.hasRemaining()) 768 if (!_content.hasRemaining())
770 _content = null; 769 _content = null;
771 } 770 }
772 771
773 // Chunk buffer if need be 772 // Chunk buffer if need be
774 if (_contentLength == HttpTokens.CHUNKED_CONTENT) 773 if (_contentLength == HttpTokens.CHUNKED_CONTENT)
775 { 774 {
776 if (_bypass && (_buffer==null||_buffer.remaining()==0) && _content!=null) 775 if (_bypass && _buffer.position()==0 && _content!=null)
777 { 776 {
778 // this is a bypass write 777 // this is a bypass write
779 int size = _content.remaining(); 778 int size = _content.remaining();
780 _bufferChunked = true; 779 _bufferChunked = true;
781 780
791 _header.putQ(HttpTokens.CRLF); 790 _header.putQ(HttpTokens.CRLF);
792 791
793 // Need a CRLF after the content 792 // Need a CRLF after the content
794 _needCRLF = true; 793 _needCRLF = true;
795 } 794 }
796 else if (_buffer!=null) 795 else
797 { 796 {
798 int size = _buffer.remaining(); 797 int size = _buffer.position();
799 if (size > 0) 798 if (size > 0)
800 { 799 {
801 // Prepare a chunk! 800 // Prepare a chunk!
802 _bufferChunked = true; 801 _bufferChunked = true;
803 802
809 } 808 }
810 BufferUtil.putHexInt(_header, size); 809 BufferUtil.putHexInt(_header, size);
811 _header.putQ(HttpTokens.CRLF); 810 _header.putQ(HttpTokens.CRLF);
812 811
813 // Add end chunk trailer. 812 // Add end chunk trailer.
814 if (_buffer.space() >= 2) 813 if (_buffer.remaining() >= 2)
815 _buffer.put(HttpTokens.CRLF); 814 _buffer.putQ(HttpTokens.CRLF);
816 else 815 else
817 _needCRLF = true; 816 _needCRLF = true;
818 } 817 }
819 } 818 }
820 819
821 // If we need EOC and everything written 820 // If we need EOC and everything written
822 if (_needEOC && (_content == null || !_content.hasRemaining())) 821 if (_needEOC && (_content == null || !_content.hasRemaining()))
823 { 822 {
824 if (_needCRLF) 823 if (_needCRLF && _buffer.remaining() >= HttpTokens.CRLF.length) {
825 { 824 _buffer.putQ(HttpTokens.CRLF);
826 if (_buffer == null && _header.remaining() >= HttpTokens.CRLF.length) 825 _needCRLF = false;
826 }
827
828 if (!_needCRLF && _needEOC && _buffer.remaining() >= LAST_CHUNK.length) {
829 if (!_head)
827 { 830 {
828 _header.putQ(HttpTokens.CRLF); 831 _buffer.putQ(LAST_CHUNK);
829 _needCRLF = false; 832 _bufferChunked = true;
830 } 833 }
831 else if (_buffer!=null && _buffer.space() >= HttpTokens.CRLF.length) 834 _needEOC = false;
832 {
833 _buffer.put(HttpTokens.CRLF);
834 _needCRLF = false;
835 }
836 }
837
838 if (!_needCRLF && _needEOC)
839 {
840 if (_buffer == null && _header.remaining() >= LAST_CHUNK.length)
841 {
842 if (!_head)
843 {
844 _header.putQ(LAST_CHUNK);
845 _bufferChunked=true;
846 }
847 _needEOC = false;
848 }
849 else if (_buffer!=null && _buffer.space() >= LAST_CHUNK.length)
850 {
851 if (!_head)
852 {
853 _buffer.put(LAST_CHUNK);
854 _bufferChunked=true;
855 }
856 _needEOC = false;
857 }
858 } 835 }
859 } 836 }
860 } 837 }
861 } 838 }
862 839
867 844
868 @Override 845 @Override
869 public String toString() 846 public String toString()
870 { 847 {
871 JBuffer header = _header; 848 JBuffer header = _header;
872 JBuffer buffer=_buffer; 849 JBuffer buffer = _buffer;
873 JBuffer content = _content; 850 JBuffer content = _content;
874 return String.format("%s{s=%d,h=%d,b=%d,c=%d}", 851 return String.format("%s{s=%d,h=%d,b=%d,c=%d}",
875 getClass().getSimpleName(), 852 getClass().getSimpleName(),
876 _state, 853 _state,
877 header == null ? -1 : header.position(), 854 header == null ? -1 : header.position(),
878 buffer == null ? -1 : buffer.remaining(), 855 buffer == null ? -1 : buffer.position(),
879 content == null ? -1 : content.remaining()); 856 content == null ? -1 : content.remaining());
880 } 857 }
881 858
882 859
883 860
928 { 905 {
929 this._buffers = buffers; 906 this._buffers = buffers;
930 this._endp = io; 907 this._endp = io;
931 _header = _buffers.getHeader(); 908 _header = _buffers.getHeader();
932 _buffer = _buffers.getBuffer(); 909 _buffer = _buffers.getBuffer();
933 _buffer.limit(0);
934 } 910 }
935 911
936 public final boolean isOpen() 912 public final boolean isOpen()
937 { 913 {
938 return _endp.isOpen(); 914 return _endp.isOpen();
946 _last = false; 922 _last = false;
947 _persistent = null; 923 _persistent = null;
948 _contentWritten = 0; 924 _contentWritten = 0;
949 _contentLength = HttpTokens.UNKNOWN_CONTENT; 925 _contentLength = HttpTokens.UNKNOWN_CONTENT;
950 _content = null; 926 _content = null;
951 if (_buffer!=null) 927 _buffer.clear();
952 _buffer.clearJ();
953 } 928 }
954 929
955 /* ------------------------------------------------------------ */ 930 /* ------------------------------------------------------------ */
956 /** 931 /**
957 * @return Returns the contentBufferSize. 932 * @return Returns the contentBufferSize.
1050 } 1025 }
1051 } 1026 }
1052 1027
1053 public final void completeUncheckedAddContent() 1028 public final void completeUncheckedAddContent()
1054 { 1029 {
1055 _contentWritten += _buffer.remaining(); 1030 _contentWritten += _buffer.position();
1056 if (_head) 1031 if (_head)
1057 _buffer.clearJ(); 1032 _buffer.clear();
1058 } 1033 }
1059 1034
1060 private boolean isBufferFull2() 1035 private boolean isBufferFull2()
1061 { 1036 {
1062 if (_buffer != null && _buffer.space()==0) 1037 return !_buffer.hasRemaining() || _content!=null && _content.remaining()>0;
1063 {
1064 if (_buffer.remaining()==0)
1065 _buffer.limit(0);
1066 return _buffer.space()==0;
1067 }
1068
1069 return _content!=null && _content.remaining()>0;
1070 } 1038 }
1071 1039
1072 public final boolean isWritten() 1040 public final boolean isWritten()
1073 { 1041 {
1074 return _contentWritten>0; 1042 return _contentWritten>0;
1097 1065
1098 1066
1099 public final void flush(long maxIdleTime) throws IOException 1067 public final void flush(long maxIdleTime) throws IOException
1100 { 1068 {
1101 // block until everything is flushed 1069 // block until everything is flushed
1102 long now=System.currentTimeMillis(); 1070 long now = System.currentTimeMillis();
1103 long end=now+maxIdleTime; 1071 long end = now+maxIdleTime;
1104 JBuffer content = _content; 1072 JBuffer content = _content;
1105 JBuffer buffer = _buffer; 1073 JBuffer buffer = _buffer;
1106 if (content!=null && content.remaining()>0 || buffer!=null && buffer.remaining()>0 || isBufferFull()) 1074 if (content!=null && content.remaining()>0 || buffer.position()>0 || isBufferFull())
1107 { 1075 {
1108 flushBuffer(); 1076 flushBuffer();
1109 1077
1110 while (now<end && (content!=null && content.remaining()>0 ||buffer!=null && buffer.remaining()>0) && _endp.isOpen()&& !_endp.isOutputShutdown()) 1078 while (now<end && (content!=null && content.remaining()>0 || buffer.position()>0) && _endp.isOpen()&& !_endp.isOutputShutdown())
1111 { 1079 {
1112 blockForOutput(end-now); 1080 blockForOutput(end-now);
1113 now=System.currentTimeMillis(); 1081 now = System.currentTimeMillis();
1114 } 1082 }
1115 } 1083 }
1116 } 1084 }
1117 1085
1118 /* ------------------------------------------------------------ */ 1086 /* ------------------------------------------------------------ */