Re: BufferedOutputStream

2008-06-09 Thread Joerg Heinicke

On 07.06.2008 03:13, Andy Stevens wrote:

Out of interest, have you raised an enhancement request and/or a patch 
with the OpenJDK project[1]?  It seems to me this increasing buffer 
behaviour would be useful more generally...


Done.

Joerg


Re: BufferedOutputStream

2008-06-07 Thread Andy Stevens

Joerg Heinicke wrote:

On 02.06.2008 05:56, Sylvain Wallez wrote:

Stupid question: why do we need a special BufferedOutputStream?


For being able to reset the response buffer for error handling. This is 
also possible with java.io.BufferedOutputStream, if the buffer size is 
big enough (current default value is 1MB), but then the buffer byte[] is 
always that big rather than increasing. That's what's happening right 
now, if you don't specify -1 as buffer size. -1 means complete buffering 
which on the other hand might lead to OutOfMemoryError [1]. In addition 
our BOS counts the bytes so that we can use the value to set the content 
length header.


Joerg

[1] https://issues.apache.org/jira/browse/COCOON-2168


Out of interest, have you raised an enhancement request and/or a patch 
with the OpenJDK project[1]?  It seems to me this increasing buffer 
behaviour would be useful more generally...



Andy.

[1] http://openjdk.java.net/
--
http://pseudoq.sourceforge.net/  Open source Sudoku solver


Re: BufferedOutputStream

2008-06-03 Thread Reinhard Pötz

Joerg Heinicke wrote:

Reinhard Pötz reinhard at apache.org writes:

Is my understanding right that the content length header can only be set 
as long as you haven't written into the underlying output stream?


Yes, it is. That's why the buffering has to be big enough, i.e. nothing must
have been flushed yet.


What happens when the buffer size is exceeded? Does it mean that the 
output is streamed and the content length parameter can't be set?


--
Reinhard Pötz   Managing Director, {Indoqa} GmbH
 http://www.indoqa.com/en/people/reinhard.poetz/

Member of the Apache Software Foundation
Apache Cocoon Committer, PMC member  [EMAIL PROTECTED]



Re: BufferedOutputStream

2008-06-03 Thread Sylvain Wallez

Joerg Heinicke wrote:

On 02.06.2008 05:56, Sylvain Wallez wrote:

Only issue I want to solve before the release is the 
BufferedOutputStream issue. I planned to do it this weekend.


Done. Please review the file attached. It's still completely 
untested. At the moment I need some sleep ;) I will write junit 
tests for it this week and eventually commit it.


Stupid question: why do we need a special BufferedOutputStream?


For being able to reset the response buffer for error handling. This 
is also possible with java.io.BufferedOutputStream, if the buffer size 
is big enough (current default value is 1MB), but then the buffer 
byte[] is always that big rather than increasing. That's what's 
happening right now, if you don't specify -1 as buffer size. -1 means 
complete buffering which on the other hand might lead to 
OutOfMemoryError [1]. In addition our BOS counts the bytes so that we 
can use the value to set the content length header.


Got it. I'm using a similar technique with a servlet filter providing 
the response with a ByteArrayOutputStream that gives the size and has 
the convenient writeTo(OutputStream) method. Now in my case [1] pages 
are always small and I don't need to put a high limit on the size of the 
buffer.


Sylvain

[1] http://bluxte.net/blog/2008-04/29-54-29.html

--
Sylvain Wallez - http://bluxte.net



Re: BufferedOutputStream

2008-06-03 Thread Joerg Heinicke
Reinhard Pötz reinhard at apache.org writes:

  Is my understanding right that the content length header can only be set 
  as long as you haven't written into the underlying output stream?
  
  Yes, it is. That's why the buffering has to be big enough, i.e. nothing must
  have been flushed yet.
 
 What happens when the buffer size is exceeded? Does it mean that the 
 output is streamed and the content length parameter can't be set?

If the buffer size is exceeded the output stream is flushed and eventually
written to the response. A header like the content-length can no longer be set.

That's why Cocoon's BufferedOutputStream was setup to buffer all and everything
by default which lead to COCOON-2168 [1] with Cocoon's default setting. With the
change to a buffer of 1 MB rather than endless buffering we switched back to
java.io.BufferedOutputStream, but this allocates the memory for the buffer
immediately. So even with 10 KB pages you always end up with 1 MB byte[]. I
intend to fix this in our BufferedOutputStream with an increasing buffer and the
two configuration parameters initial buffer size and flush buffer size.

Just to make it clear: We talk about default configuration of Cocoon here. You
still can enforce complete buffering by setting flush buffer size to -1 again.
But it's up to the user to enforce this and potentially run into OOME. It's also
up to the users to find a reasonable flush buffer size as it always used to be
when they haven't used the endless buffering. Only thing that is going to change
is in case of not endless buffering: The full buffer is not allocated
immediately but step by step.

Joerg

[1] https://issues.apache.org/jira/browse/COCOON-2168



Re: BufferedOutputStream

2008-06-02 Thread Sylvain Wallez

Joerg Heinicke wrote:

On 29.05.2008 00:06, Joerg Heinicke wrote:

Only issue I want to solve before the release is the 
BufferedOutputStream issue. I planned to do it this weekend.


Done. Please review the file attached. It's still completely untested. 
At the moment I need some sleep ;) I will write junit tests for it 
this week and eventually commit it.


Stupid question: why do we need a special BufferedOutputStream?

Sylvain

--
Sylvain Wallez - http://bluxte.net



Re: BufferedOutputStream

2008-06-02 Thread Joerg Heinicke

On 02.06.2008 05:56, Sylvain Wallez wrote:

Only issue I want to solve before the release is the 
BufferedOutputStream issue. I planned to do it this weekend.


Done. Please review the file attached. It's still completely untested. 
At the moment I need some sleep ;) I will write junit tests for it 
this week and eventually commit it.


Stupid question: why do we need a special BufferedOutputStream?


For being able to reset the response buffer for error handling. This is 
also possible with java.io.BufferedOutputStream, if the buffer size is 
big enough (current default value is 1MB), but then the buffer byte[] is 
always that big rather than increasing. That's what's happening right 
now, if you don't specify -1 as buffer size. -1 means complete buffering 
which on the other hand might lead to OutOfMemoryError [1]. In addition 
our BOS counts the bytes so that we can use the value to set the content 
length header.


Joerg

[1] https://issues.apache.org/jira/browse/COCOON-2168


Re: BufferedOutputStream

2008-06-02 Thread Reinhard Pötz

Joerg Heinicke wrote:

On 02.06.2008 05:56, Sylvain Wallez wrote:

Only issue I want to solve before the release is the 
BufferedOutputStream issue. I planned to do it this weekend.


Done. Please review the file attached. It's still completely 
untested. At the moment I need some sleep ;) I will write junit tests 
for it this week and eventually commit it.


Stupid question: why do we need a special BufferedOutputStream?


For being able to reset the response buffer for error handling. This is 
also possible with java.io.BufferedOutputStream, if the buffer size is 
big enough (current default value is 1MB), but then the buffer byte[] is 
always that big rather than increasing. That's what's happening right 
now, if you don't specify -1 as buffer size. -1 means complete buffering 
which on the other hand might lead to OutOfMemoryError [1]. In addition 
our BOS counts the bytes so that we can use the value to set the content 
length header.


Is my understanding right that the content length header can only be set 
as long as you haven't written into the underlying output stream?


--
Reinhard Pötz   Managing Director, {Indoqa} GmbH
 http://www.indoqa.com/en/people/reinhard.poetz/

Member of the Apache Software Foundation
Apache Cocoon Committer, PMC member  [EMAIL PROTECTED]



Re: BufferedOutputStream

2008-06-02 Thread Joerg Heinicke
Reinhard Pötz reinhard at apache.org writes:

 Is my understanding right that the content length header can only be set 
 as long as you haven't written into the underlying output stream?

Yes, it is. That's why the buffering has to be big enough, i.e. nothing must
have been flushed yet.

Joerg



BufferedOutputStream (was: Releasing 2.1.12 - a new release manager?)

2008-06-01 Thread Joerg Heinicke

On 29.05.2008 00:06, Joerg Heinicke wrote:

Only issue I want to solve before the release is the 
BufferedOutputStream issue. I planned to do it this weekend.


Done. Please review the file attached. It's still completely untested. 
At the moment I need some sleep ;) I will write junit tests for it this 
week and eventually commit it.


Joerg
/*
 * 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.cocoon.util;

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * This class is similar to the [EMAIL PROTECTED] 
java.io.BufferedOutputStream}. In
 * addition it provides an increasing buffer, the possibility to reset the
 * buffer and it counts the number of bytes written to the output stream.
 * 
 * @author a href=mailto:[EMAIL PROTECTED]Carsten Ziegeler/a
 * @version CVS $Id: BufferedOutputStream.java 433543 2006-08-22 06:22:54Z 
crossley $
 * @since   2.1
 */
public class BufferedOutputStream extends FilterOutputStream {

private byte buffer[];

private int count;
private int totalCount;

private final int flushBufferSize;

/**
 * Creates a new buffered output stream to write data to the 
 * specified underlying output stream with a default 8192-byte
 * buffer size.
 *
 * @param   out   the underlying output stream.
 */
public BufferedOutputStream(final OutputStream out) {
this(out, 8192, 32768);
}

/**
 * Creates a new buffered output stream to write data to the specified
 * underlying output stream with the specified buffer sizes.
 *
 * @param outthe underlying output stream.
 * @param initialBufferSize  the initial buffer size. Must be greater than 
0.
 *   Will be limited to the flush buffer size.
 * @param flushBufferSize  the buffer size when the stream is flushed. Must
 * be greater than 0 or -1 meaning the stream never
 * flushes itself.
 */
public BufferedOutputStream(final OutputStream out,
final int initialBufferSize,
final int flushBufferSize) {
super(out);
if (initialBufferSize = 0) {
throw new IllegalArgumentException(Initial buffer size = 0);
}
if (flushBufferSize = 0  flushBufferSize != -1) {
throw new IllegalArgumentException(Flush buffer size = 0  != 
-1);
}
this.buffer =
new byte[initialBufferSize  flushBufferSize ? flushBufferSize : 
initialBufferSize];
this.flushBufferSize = flushBufferSize;
}

/**
 * Writes the specified byte to this buffered output stream. 
 *
 * @param  b   the byte to be written.
 * @exception  IOException  if an I/O error occurs.
 */
public void write(int b) throws IOException {
if (this.count == this.buffer.length) {
// No need to check return value, can NEVER be 0.
this.increaseBuffer(1);
}

this.buffer[this.count++] = (byte)b;
this.totalCount++;

if (this.count == this.flushBufferSize) {
flush();
}
}

/**
 * Writes codelen/code bytes from the specified byte array 
 * starting at offset codeoff/code to this buffered output stream.
 *
 * p Ordinarily this method stores bytes from the given array into this
 * stream's buffer, flushing the buffer to the underlying output stream as
 * needed.  If the requested length is at least as large as this stream's
 * buffer, however, then this method will flush the buffer and write the
 * bytes directly to the underlying output stream.  Thus redundant
 * codeBufferedOutputStream/codes will not copy data unnecessarily.
 *
 * @param  b the data.
 * @param  off   the start offset in the data.
 * @param  len   the number of bytes to write.
 * @exception  IOException  if an I/O error occurs.
 */
public void write(final byte[] b, final int off, final int len) throws 
IOException {
if (len  this.buffer.length - this.count) {
int actualIncrease = this.increaseBuffer(len