sounds good to me.


On Tue, Jul 22, 2008 at 6:19 PM, Edouard De Oliveira <[EMAIL PROTECTED]>
wrote:

> So we agree on ConcurrentHashMap use : all of the conditions you wrote
> should be met
> when correctly using this filter. The uneasy parameter is MAX_THREADS. I
> think there's
> no magical value so as an API service provider we should provide default
> implementation and let
> the user provide its own params for the ConcurrentHashMap instantiation or
> even its own
> instance.
>
> I think adding the following constructor should close the debate :
> public BufferedWriteFilter(int bufferSize, final ConcurrentMap<IoSession,
> IoBuffer> buffersMap);
>
>
> WDYT ?
>
> Cordialement, Regards,
> -Edouard De Oliveira-
> http://tedorg.free.fr/en/main.php
>
>
>
> ----- Message d'origine ----
> De : Bogdan Ciprian Pistol <[EMAIL PROTECTED]>
> À : dev@mina.apache.org
> Envoyé le : Mardi, 22 Juillet 2008, 12h41mn 46s
> Objet : Re: Re : svn commit: r678238 - in
> /mina/trunk/core/src/main/java/org/apache/mina/filter/buffer: ./
> BufferedWriteFilter.java
>
> From my experience ConcurrentHashMap outperforms
> Collections.synchronizedMap(...) only if:
> - you know in advance how many maximum threads (MAX_THREADS) could
> simultaneously modify the ConcurrentHashMap
> - MAX_THREADS is small compared to the number of threads that are
> accessing the ConcurrentHashMap (reads)
> - the accesses (reads) vastly outnumbers the modifications (writes)
> ConcurrentHashMap also consumes more memory (increases proportional
> with MAX_THREADS)
>
> Bogdan
>
> On Tue, Jul 22, 2008 at 2:24 AM, Edouard De Oliveira
> <[EMAIL PROTECTED]> wrote:
> > Perfectly legitimate question Mark :
> >
> > Stop me if i'm not correct, but i think it would be an error using
> CopyOnWriteMap in this usecase
> > as the map grows when the number of sessions grows and as buffering takes
> full meaning in long
> > lived sessions, then each new session would duplicate a potentially
> larger map hence
> > hitting the bad side of CopyOnWriteMap.
> >
> >
> > So ConcurrentHashMap should be more appropriate.
> >
> > WDYT ?
> >
> > ps: i'm commiting right now the proposed fix
> > and a test class on trunk to ease any further review
> >
> > Cordialement, Regards,
> > -Edouard De Oliveira-
> > http://tedorg.free.fr/en/main.php
> >
> >
> >
> > ----- Message d'origine ----
> > De : Mark Webb <[EMAIL PROTECTED]>
> > À : dev@mina.apache.org
> > Envoyé le : Lundi, 21 Juillet 2008, 2h47mn 54s
> > Objet : Re: svn commit: r678238 - in
> /mina/trunk/core/src/main/java/org/apache/mina/filter/buffer: ./
> BufferedWriteFilter.java
> >
> > I have a question on this class.
> >
> > Why not use ConcurrentHashMap for this instead of synchronizing?  Or
> > CopyOnWriteMap?
> >
> >
> >
> >
> > On Sat, Jul 19, 2008 at 7:19 PM, <[EMAIL PROTECTED]> wrote:
> >
> >> Author: edeoliveira
> >> Date: Sat Jul 19 16:19:14 2008
> >> New Revision: 678238
> >>
> >> URL: http://svn.apache.org/viewvc?rev=678238&view=rev
> >> Log:
> >> New IoFilter that implements DIRMINA-519
> >>
> >> Added:
> >>    mina/trunk/core/src/main/java/org/apache/mina/filter/buffer/
> >>
> >>
>  
> mina/trunk/core/src/main/java/org/apache/mina/filter/buffer/BufferedWriteFilter.java
> >>   (with props)
> >>
> >> Added:
> >>
> mina/trunk/core/src/main/java/org/apache/mina/filter/buffer/BufferedWriteFilter.java
> >> URL:
> >>
> http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/buffer/BufferedWriteFilter.java?rev=678238&view=auto
> >>
> >>
> ==============================================================================
> >> ---
> >>
> mina/trunk/core/src/main/java/org/apache/mina/filter/buffer/BufferedWriteFilter.java
> >> (added)
> >> +++
> >>
> mina/trunk/core/src/main/java/org/apache/mina/filter/buffer/BufferedWriteFilter.java
> >> Sat Jul 19 16:19:14 2008
> >> @@ -0,0 +1,243 @@
> >> +/*
> >> + *  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.mina.filter.buffer;
> >> +
> >> +import java.io.BufferedOutputStream;
> >> +import java.util.HashMap;
> >> +import java.util.Map;
> >> +
> >> +import org.apache.mina.core.buffer.IoBuffer;
> >> +import org.apache.mina.core.filterchain.IoFilter;
> >> +import org.apache.mina.core.filterchain.IoFilterAdapter;
> >> +import org.apache.mina.core.session.IoSession;
> >> +import org.apache.mina.core.write.DefaultWriteRequest;
> >> +import org.apache.mina.core.write.WriteRequest;
> >> +import org.apache.mina.filter.codec.ProtocolCodecFilter;
> >> +
> >> +/**
> >> + * An [EMAIL PROTECTED] IoFilter} implementation used to buffer outgoing 
> >> [EMAIL PROTECTED]
> >> WriteRequest} almost
> >> + * like what [EMAIL PROTECTED] BufferedOutputStream} does. Using this 
> >> filter
> allows
> >> to be less dependent
> >> + * from network latency. It is also useful when a session is generating
> >> very small messages
> >> + * too frequently and consequently generating unnecessary traffic
> >> overhead.
> >> + *
> >> + * Please note that it should always be placed before the [EMAIL 
> >> PROTECTED]
> >> ProtocolCodecFilter}
> >> + * as it only handles [EMAIL PROTECTED] WriteRequest}'s carrying [EMAIL 
> >> PROTECTED] IoBuffer}
> >> objects.
> >> + *
> >> + * @author The Apache MINA Project (dev@mina.apache.org)
> >> + * @version $Rev: $, $Date: $
> >> + * @since MINA 2.0.0-M2
> >> + */
> >> +public final class BufferedWriteFilter extends IoFilterAdapter {
> >> +
> >> +    /**
> >> +     * Default buffer size value in bytes.
> >> +     */
> >> +    public final static int DEFAULT_BUFFER_SIZE = 8192;
> >> +
> >> +    /**
> >> +     * The buffer size allocated for each new session's buffer.
> >> +     */
> >> +    private int bufferSize = DEFAULT_BUFFER_SIZE;
> >> +
> >> +    /**
> >> +     * The map that matches an [EMAIL PROTECTED] IoSession} and it's 
> >> [EMAIL PROTECTED]
> IoBuffer}
> >> +     * buffer.
> >> +     */
> >> +    protected Map<IoSession, IoBuffer> buffersMap = new
> HashMap<IoSession,
> >> IoBuffer>();
> >> +
> >> +    /**
> >> +     * Default constructor. Sets buffer size to [EMAIL PROTECTED]
> >> #DEFAULT_BUFFER_SIZE}
> >> +     * bytes.
> >> +     */
> >> +    public BufferedWriteFilter() {
> >> +        this(DEFAULT_BUFFER_SIZE);
> >> +    }
> >> +
> >> +    /**
> >> +     * Constructor which sets buffer size to <code>bufferSize</code>.
> >> +     *
> >> +     * @param bufferSize the new buffer size
> >> +     */
> >> +    public BufferedWriteFilter(int bufferSize) {
> >> +        super();
> >> +        this.bufferSize = bufferSize;
> >> +    }
> >> +
> >> +    /**
> >> +     * Returns buffer size.
> >> +     */
> >> +    public int getBufferSize() {
> >> +        return bufferSize;
> >> +    }
> >> +
> >> +    /**
> >> +     * Sets the buffer size but only for the newly created buffers.
> >> +     *
> >> +     * @param bufferSize the new buffer size
> >> +     */
> >> +    public void setBufferSize(int bufferSize) {
> >> +        this.bufferSize = bufferSize;
> >> +    }
> >> +
> >> +    /**
> >> +     * [EMAIL PROTECTED]
> >> +     *
> >> +     * @throws Exception if <code>writeRequest.message</code> isn't an
> >> +     *                   [EMAIL PROTECTED] IoBuffer} instance.
> >> +     */
> >> +    @Override
> >> +    public void filterWrite(NextFilter nextFilter, IoSession session,
> >> +            WriteRequest writeRequest) throws Exception {
> >> +
> >> +        Object data = writeRequest.getMessage();
> >> +
> >> +        if (data instanceof IoBuffer) {
> >> +            write(session, (IoBuffer) data);
> >> +        } else {
> >> +            throw new IllegalArgumentException(
> >> +                    "This filter should only buffer IoBuffer objects");
> >> +        }
> >> +    }
> >> +
> >> +    /**
> >> +     * Writes an [EMAIL PROTECTED] IoBuffer} to the session's buffer.
> >> +     *
> >> +     * @param session the session to which a write is requested
> >> +     * @param data the data to buffer
> >> +     */
> >> +    private void write(IoSession session, IoBuffer data) {
> >> +        IoBuffer dest = null;
> >> +        synchronized (buffersMap) {
> >> +            dest = buffersMap.get(session);
> >> +            if (dest == null) {
> >> +                // Enforce the creation of a non-expandable buffer
> >> +                dest =
> IoBuffer.allocate(bufferSize).setAutoExpand(false);
> >> +                buffersMap.put(session, dest);
> >> +            }
> >> +        }
> >> +
> >> +        write(session, data, dest);
> >> +    }
> >> +
> >> +    /**
> >> +     * Writes <code>data</code> [EMAIL PROTECTED] IoBuffer} to the
> <code>buf</code>
> >> +     * [EMAIL PROTECTED] IoBuffer} which buffers write requests for the
> >> +     * <code>session</code> {@ link IoSession} until buffer is full
> >> +     * or manually flushed.
> >> +     *
> >> +     * @param session the session where buffer will be written
> >> +     * @param data the data to buffer
> >> +     * @param buf the buffer where data will be temporarily written
> >> +     */
> >> +    private void write(IoSession session, IoBuffer data, IoBuffer buf)
> {
> >> +        synchronized (buf) {
> >> +            try {
> >> +                int len = data.remaining();
> >> +                if (len >= buf.capacity()) {
> >> +                    /*
> >> +                     * If the request length exceeds the size of the
> >> output buffer,
> >> +                     * flush the output buffer and then write the data
> >> directly.
> >> +                     */
> >> +                    NextFilter nextFilter = session.getFilterChain()
> >> +                            .getNextFilter(this);
> >> +                    internalFlush(nextFilter, session, buf);
> >> +                    nextFilter.filterWrite(session,
> >> +                            new DefaultWriteRequest(buf));
> >> +                    return;
> >> +                }
> >> +                if (len > (buf.limit() - buf.position())) {
> >> +
> >>  internalFlush(session.getFilterChain().getNextFilter(this),
> >> +                            session, buf);
> >> +                }
> >> +                buf.put(data);
> >> +            } catch (Throwable e) {
> >> +                session.getFilterChain().fireExceptionCaught(e);
> >> +            }
> >> +        }
> >> +    }
> >> +
> >> +    /**
> >> +     * Internal method that actually flushes the buffered data.
> >> +     *
> >> +     * @param nextFilter the [EMAIL PROTECTED] NextFilter} of this filter
> >> +     * @param session the session where buffer will be written
> >> +     * @param data the data to write
> >> +     * @throws Exception if a write operation fails
> >> +     */
> >> +    private void internalFlush(NextFilter nextFilter, IoSession
> session,
> >> +            IoBuffer data) throws Exception {
> >> +        if (data != null) {
> >> +            nextFilter.filterWrite(session, new
> >> DefaultWriteRequest(data));
> >> +            data.clear();
> >> +        }
> >> +    }
> >> +
> >> +    /**
> >> +     * Flushes the buffered data.
> >> +     *
> >> +     * @param session the session where buffer will be written
> >> +     */
> >> +    public void flush(IoSession session) {
> >> +        try {
> >> +            IoBuffer data = null;
> >> +            synchronized (session) {
> >> +                data = buffersMap.get(session);
> >> +            }
> >> +            internalFlush(session.getFilterChain().getNextFilter(this),
> >> +                    session, data);
> >> +
> >> +        } catch (Throwable e) {
> >> +            session.getFilterChain().fireExceptionCaught(e);
> >> +        }
> >> +    }
> >> +
> >> +    /**
> >> +     * Internal method that actually frees the [EMAIL PROTECTED] 
> >> IoBuffer} that
> >> contains
> >> +     * the buffered data that has not been flushed.
> >> +     *
> >> +     * @param session the session we operate on
> >> +     */
> >> +    private void clear(IoSession session) {
> >> +        synchronized (session) {
> >> +            IoBuffer buf = buffersMap.remove(session);
> >> +            if (buf != null) {
> >> +                buf.free();
> >> +            }
> >> +        }
> >> +    }
> >> +
> >> +    /**
> >> +     * [EMAIL PROTECTED]
> >> +     */
> >> +    @Override
> >> +    public void exceptionCaught(NextFilter nextFilter, IoSession
> session,
> >> +            Throwable cause) throws Exception {
> >> +        clear(session);
> >> +    }
> >> +
> >> +    /**
> >> +     * [EMAIL PROTECTED]
> >> +     */
> >> +    @Override
> >> +    public void sessionClosed(NextFilter nextFilter, IoSession session)
> >> +            throws Exception {
> >> +        clear(session);
> >> +    }
> >> +}
> >> \ No newline at end of file
> >>
> >> Propchange:
> >>
> mina/trunk/core/src/main/java/org/apache/mina/filter/buffer/BufferedWriteFilter.java
> >>
> >>
> ------------------------------------------------------------------------------
> >>    svn:eol-style = native
> >>
> >> Propchange:
> >>
> mina/trunk/core/src/main/java/org/apache/mina/filter/buffer/BufferedWriteFilter.java
> >>
> >>
> ------------------------------------------------------------------------------
> >>    svn:mime-type = text/plain
> >>
> >>
> >>
> >
> >
> >
> >
>  _____________________________________________________________________________
> > Envoyez avec Yahoo! Mail. Une boite mail plus intelligente
> http://mail.yahoo.fr
> >
>
>
>
>
>  _____________________________________________________________________________
> Envoyez avec Yahoo! Mail. Une boite mail plus intelligente
> http://mail.yahoo.fr
>

Reply via email to