/*
 * Copyright 1996 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package sun.rmi.transport.tcp;

import java.io.*;

/**
 * MultiplexOutputStream manages sending data over a conection managed
 * by a ConnectionMultiplexer object.  Data written is buffered until the
 * internal buffer is full or the flush() method is called, at which
 * point it attempts to push a packet of bytes through to the remote
 * endpoint.  This will never push more bytes than the amount already
 * requested by the remote endpoint (to prevent receive buffer from
 * overflowing), so if the write() and flush() methods will block
 * until their operation can complete if enough bytes cannot be
 * pushed immediately.
 *
 * @author Peter Jones
 */
final class MultiplexOutputStream extends OutputStream {

    /** object managing multiplexed connection */
    private ConnectionMultiplexer manager;

    /** information about the connection this is the output stream for */
    private MultiplexConnectionInfo info;

    /** output buffer */
    private byte buffer[];

    /** current position to write to in output buffer */
    private int pos = 0;

    /** pending number of bytes requested by remote endpoint */
    private int requested = 0;

    /** true if this connection has been disconnected */
    private boolean disconnected = false;

    /**
     * lock acquired to access shared variables:
     * requested & disconnected
     * WARNING:  Any of the methods manager.send*() should not be
     * invoked while this lock is held, since they could potentially
     * block if the underlying connection's transport buffers are
     * full, and the manager may need to acquire this lock to process
     * and consume data coming over the underlying connection.
     */
    private Object lock = new Object();

    /**
     * Create a new MultiplexOutputStream for the given manager.
     * @param manager object that manages this connection
     * @param info structure for connection this stream writes to
     * @param bufferLength length of output buffer
     */
    MultiplexOutputStream(
        ConnectionMultiplexer    manager,
        MultiplexConnectionInfo  info,
        int                      bufferLength)
    {
        this.manager = manager;
        this.info    = info;

        buffer = new byte[bufferLength];
        pos = 0;
    }

    /**
     * Write a byte over connection.
     * @param b byte of data to write
     */
    public synchronized void write(int b) throws IOException
    {
        while (pos >= buffer.length)
            push();
        buffer[pos ++] = (byte) b;
    }

    /**
     * Write a subarray of bytes over connection.
     * @param b array containing bytes to write
     * @param off offset of beginning of bytes to write
     * @param len number of bytes to write
     */
    public synchronized void write(byte b[], int off, int len)
        throws IOException
    {
        if (len <= 0)
            return;

        // if enough free space in output buffer, just copy into there
        int freeSpace = buffer.length - pos;
        if (len <= freeSpace) {
            System.arraycopy(b, off, buffer, pos, len);
            pos += len;
            return;
        }

        // else, flush buffer and send rest directly to avoid array copy
        flush();
        int local_requested;
        while (true) {
            synchronized (lock) {
                while ((local_requested = requested) < 1 && !disconnected) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                    }
                }
                if (disconnected)
                    throw new IOException("Connection closed");
            }

            if (local_requested < len) {
                manager.sendTransmit(info, b, off, local_requested);
                off += local_requested;
                len -= local_requested;
                synchronized (lock) {
                    requested -= local_requested;
                }
            }
            else {
                manager.sendTransmit(info, b, off, len);
                synchronized (lock) {
                    requested -= len;
                }
                // len = 0;
                break;
            }
        }
    }

    /**
     * Guarantee that all data written to this stream has been pushed
     * over and made available to the remote endpoint.
     */
    public synchronized void flush() throws IOException {
        while (pos > 0)
            push();
    }

    /**
     * Close this connection.
     */
    public void close() throws IOException
    {
        manager.sendClose(info);
    }

    /**
     * Take note of more bytes requested by conection at remote endpoint.
     * @param num number of additional bytes requested
     */
    void request(int num)
    {
        synchronized (lock) {
            requested += num;
            lock.notifyAll();
        }
    }

    /**
     * Disconnect this stream from all connection activity.
     */
    void disconnect()
    {
        synchronized (lock) {
            disconnected = true;
            lock.notifyAll();
        }
    }

    /**
     * Push bytes in output buffer to connection at remote endpoint.
     * This method blocks until at least one byte has been pushed across.
     */
    private void push() throws IOException
    {
        int local_requested;
        synchronized (lock) {
            while ((local_requested = requested) < 1 && !disconnected) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                }
            }
            if (disconnected)
                throw new IOException("Connection closed");
        }

        if (local_requested < pos) {
            manager.sendTransmit(info, buffer, 0, local_requested);
            System.arraycopy(buffer, local_requested,
                             buffer, 0, pos - local_requested);
            pos -= local_requested;
            synchronized (lock) {
                requested -= local_requested;
            }
        }
        else {
            manager.sendTransmit(info, buffer, 0, pos);
            synchronized (lock) {
                requested -= pos;
            }
            pos = 0;
        }
    }
}
