Hi Oleg,

*public final class SharedOutputBuffer extends ExpandableBuffer implements
ContentOutputBuffer*

Above method definition (*extends ExpandableBuffer*) made me think that
SharedOutputBuffer is expandable.

Regards,
Sreenivas

On Thu, Mar 9, 2023 at 8:20 PM sreenivas somavarapu <
soma.sreeni...@gmail.com> wrote:

> Hi Oleg,
>
> *if (src.remaining() < 1024 && buffer().remaining() > src.remaining()) {*
>
> Problem with this above condition is that even though buffer has capacity
> to store complete contents of src, this condition will not satisfy if src
> has 1024 bytes or more data (may well be in limit of actual size provided
> during creation of buffer) to be written to buffer
>
> Simple way to reproduce the problem is (Same has been demonstrated with
> sample program in previous mail)
> -    Create SharedOutputBuffer with 4096 bytes of capacity
> -    Now try to write 1024 bytes of data to above created buffer
>
> second step still will cause in a hang as first if condition is not
> satisfied due to *src.remaining() < 1024* even though there is enough
> capacity to store data and it proceeds to second condition which will cause
> the program to wait on a condition for flush (even though this is the first
> write we are performing)
>
>
> *if (buffer().position() > 0 || dataStreamChannel == null) {*
>
> *                         waitFlush();*
> *}*
>
> Regards,
> Sreenivas
>
> On Mon, Mar 6, 2023 at 9:12 PM Oleg Kalnichevski <ol...@apache.org> wrote:
>
>> On Mon, 2023-03-06 at 21:03 +0530, sreenivas somavarapu wrote:
>> > Hi Oleg,
>> >
>> > My sample program (it's a kind of unit test for SharedOutputBuffer to
>> > demonstrate that it is not able to write single byte if input byte
>> > array
>> > size is greater than 1023) doesn't have flush as my intention is to
>> > show
>> > the issue with SharedOutputBuffer alone and it is not a complete
>> > program
>> > which sends the data to the actual server and get response back. Main
>> > issue
>> > lies while writing data greater than 1023 bytes at first go itself
>> > to SharedOutputBuffer from the byte array.
>> >
>> > I think the below conditions in SharedOutputBuffer is causing this
>> > behavior
>> >
>> >             while (src.hasRemaining()) {
>> >                 // always buffer small chunks
>> >                 *if (src.remaining() < 1024 && buffer().remaining() >
>> > src.remaining()) {*
>> >                     buffer().put(src);
>> >                 } else {
>> >                    * if (buffer().position() > 0 || dataStreamChannel
>> > ==
>> > null) {*
>> >                         waitFlush();
>> >                     }
>> >
>>
>> What behavior? This code blocks if it is unable to store input data
>> until the internal buffer gets flushed and space in it frees up, which
>> is what is it supposed to do.
>>
>> If you think SharedOutputBuffer is wrong, please just use your own
>> custom buffer implementation.
>>
>> Oleg
>>
>>
>> > Regards,
>> > Sreenivas
>> >
>> > On Mon, Mar 6, 2023 at 8:52 PM Oleg Kalnichevski <ol...@apache.org>
>> > wrote:
>> >
>> > > On Mon, 2023-03-06 at 20:20 +0530, sreenivas somavarapu wrote:
>> > > > Hi Oleg,
>> > > >
>> > > > It looks like some issue with SharedOutputBuffer implementation
>> > > > and
>> > > > it is
>> > > > also not expandable as we have to allocate complete size during
>> > > > initialization itself. If I change below two lines from my
>> > > > program it
>> > > > proceeds further and completes the request (Basically
>> > > > SharedOutputBuffer is
>> > > > not able to write 1024 or above bytes of data at single go (If we
>> > > > declare
>> > > > temp block size as 1023 also it works)). It looks like there is
>> > > > an
>> > > > explicit 1024 length check in SharedOutputBuffer which is causing
>> > > > this
>> > > > behavior.
>> > > >
>> > > > SharedOutputBuffer buffer = new
>> > > > SharedOutputBuffer(req.contentLength() +
>> > > > 1024);
>> > >
>> > > What you are doing is _completely_ wrong. SharedOutputBuffer is not
>> > > meant to be expandable.
>> > >
>> > > You cannot just write into the buffer and expect it to work by
>> > > magic.
>> > > You also must flush the buffer.
>> > >
>> > > Oleg
>> > >
>> > > >
>> > > > byte[] tmp = new byte[512];
>> > > >
>> > > > Earlier those 2 lines were as below
>> > > >
>> > > >  SharedOutputBuffer buffer = new SharedOutputBuffer(1024);
>> > > >
>> > > > byte[] tmp = new byte[4 * 1024];
>> > > >
>> > > > Below is my sample program on SharedOutputBuffer  which
>> > > > demonstrated
>> > > > this
>> > > > behavior
>> > > >
>> > > >         final StringBuilder sbuffer = new StringBuilder("123");
>> > > >         System.out.println("O/P: " + sbuffer.toString());
>> > > >         for (long i = 0; i < (64 * 1000); ++i) {
>> > > >             sbuffer.append('A');
>> > > >         }
>> > > >
>> > > >         String postData = sbuffer.toString();
>> > > >         System.out.println("O/P1: " + postData);
>> > > >
>> > > >         byte[] inputData =
>> > > > postData.getBytes(StandardCharsets.UTF_8);
>> > > >         ByteArrayInputStream inputStream = new
>> > > > ByteArrayInputStream(inputData);
>> > > >         SharedOutputBuffer outputStream = new
>> > > > SharedOutputBuffer(100
>> > > > *
>> > > > 1024); *<-- If we keep this as 4 * 1024 also it hangs.*
>> > > >         *byte[] tmp = new byte[1024];  <-- If we change this to
>> > > > 1023
>> > > > then
>> > > > it works*
>> > > >         int l = -1;
>> > > >         while ((l = inputStream.read(tmp)) != -1) {
>> > > >             System.out.println("Writing Data");
>> > > >             System.out.println(l);
>> > > >             outputStream.write(tmp, 0, l);
>> > > >             System.out.println("Wrote Data");
>> > > >         }
>> > > >
>> > > >         System.out.println("Done Writing Data");
>> > > >         outputStream.writeCompleted();
>> > > >         System.out.println(outputStream.toString());
>> > > >
>> > > > Regards,
>> > > > Sreenivas
>> > > >
>> > > > On Mon, Mar 6, 2023 at 7:17 PM Oleg Kalnichevski
>> > > > <ol...@apache.org>
>> > > > wrote:
>> > > >
>> > > > > On Mon, 2023-03-06 at 16:26 +0530, sreenivas somavarapu wrote:
>> > > > > > Hi Team,
>> > > > > >
>> > > > > > We are using AbstractClassicEntityProducer with a
>> > > > > > customization
>> > > > > > of
>> > > > > > storing
>> > > > > > / computing contentLength as well which works fine if we have
>> > > > > > small
>> > > > > > POST
>> > > > > > data, but when POST data is big (for example 64 KB), it seems
>> > > > > > OutPutstream
>> > > > > > (internally using ContentOutputStream a wrapper over
>> > > > > > SharedOutputBuffer of
>> > > > > > initial size 1024) is not able to write data (We are using
>> > > > > > temporary
>> > > > > > buffer
>> > > > > > block of 4kb but still it is not able to write 4KB of data).
>> > > > > > Is
>> > > > > > there
>> > > > > > any
>> > > > > > limitation or some configuration problem?
>> > > > > >
>> > > > > > *Code being used*
>> > > > > >         SharedOutputBuffer buffer = new
>> > > > > > SharedOutputBuffer(1024);
>> > > > > >
>> > > > > >         produceData(contentType, new
>> > > > > > ContentOutputStream(buffer));
>> > > > > >
>> > > > > > protected void produceData(ContentType contentType,
>> > > > > > OutputStream
>> > > > > > outputStream) throws IOException {
>> > > > > >         byte[] tmp = new byte[4 * 1024];
>> > > > > >         int l = -1;
>> > > > > >         while ((l = inputStream.read(tmp)) != -1) {
>> > > > > > *            outputStream.write(tmp, 0, l);  <---- This is
>> > > > > > where
>> > > > > > request
>> > > > > > hangs / waits*
>> > > > >
>> > > > > This is likely due to a bug in your code that prevents the
>> > > > > shared
>> > > > > buffer from being flushed.
>> > > > >
>> > > > > Oleg
>> > > > >
>> > > > >
>> > > > > ---------------------------------------------------------------
>> > > > > ----
>> > > > > --
>> > > > > To unsubscribe, e-mail:
>> > > > > httpclient-users-unsubscr...@hc.apache.org
>> > > > > For additional commands, e-mail:
>> > > > > httpclient-users-h...@hc.apache.org
>> > > > >
>> > > > >
>> > > >
>> > >
>> > >
>> > > -------------------------------------------------------------------
>> > > --
>> > > To unsubscribe, e-mail: httpclient-users-unsubscr...@hc.apache.org
>> > > For additional commands, e-mail:
>> > > httpclient-users-h...@hc.apache.org
>> > >
>> > >
>> >
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: httpclient-users-unsubscr...@hc.apache.org
>> For additional commands, e-mail: httpclient-users-h...@hc.apache.org
>>
>>
>
> --
> Cheers,
> S. Sreenivas
>


-- 
Cheers,
S. Sreenivas

Reply via email to