/* KqueueSelectorImpl.java -- Selector for systems with kqueue event notification.
   Copyright (C) 2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.java.nio;


import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.ClosedSelectorException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.nio.channels.spi.AbstractSelector;
import java.nio.channels.spi.SelectorProvider;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * A {@link Selector} implementation that uses the <code>kqueue</code>
 * event notification facility.
 *
 * @author Casey Marshall (csm@gnu.org)
 */
public class KqueueSelectorImpl extends AbstractSelector
{
  // Prepended underscore to field name to make it distinct
  // from the method with the similar name.
  private static final int _sizeof_struct_kevent;

  private static final int MAX_DOUBLING_CAPACITY = 16384;
  private static final int CAP_INCREMENT = 1024;
  private static final int INITIAL_CAPACITY;

  static
  {
    try
      {
        System.loadLibrary("javanio");
      }
    catch (Exception x)
      {
        x.printStackTrace();
      }

    if (kqueue_supported ())
      _sizeof_struct_kevent = sizeof_struct_kevent();
    else
      _sizeof_struct_kevent = -1;
    INITIAL_CAPACITY = 16 * _sizeof_struct_kevent;
  }

  /**
   * Tell if kqueue-based selectors are supported on this system.
   *
   * @return True if this system has kqueue support, and support for it was
   *  compiled in to Classpath.
   */
  public static native boolean kqueue_supported();

  /* Our native file descriptor. */
  private int kq;

  private HashMap/*<Integer,KqueueSelectionKeyImpl>*/ keys;
  private HashSet/*<KqueueSelectionKeyImpl>*/ selected;
  private Thread blockedThread;
  private ByteBuffer events;

  private static final int OP_ACCEPT  = SelectionKey.OP_ACCEPT;
  private static final int OP_CONNECT = SelectionKey.OP_CONNECT;
  private static final int OP_READ    = SelectionKey.OP_READ;
  private static final int OP_WRITE   = SelectionKey.OP_WRITE;

  public KqueueSelectorImpl(SelectorProvider provider) throws IOException
  {
    super(provider);
    kq = implOpen();
    keys = new HashMap/*<KqueueSelectionKeyImpl>*/();
    events = ByteBuffer.allocateDirect(INITIAL_CAPACITY);
  }

  protected void implCloseSelector() throws IOException
  {
    implClose(kq);
    kq = -1;
  }

  /* (non-Javadoc)
   * @see java.nio.channels.Selector#keys()
   */
  public Set keys()
  {
    if (!isOpen())
      throw new ClosedSelectorException();

    return new HashSet(keys.values());
  }

  /* (non-Javadoc)
   * @see java.nio.channels.Selector#select()
   */
  public int select() throws IOException
  {
    return doSelect(-1);
  }

  /* (non-Javadoc)
   * @see java.nio.channels.Selector#select(long)
   */
  public int select(long timeout) throws IOException
  {
    if (timeout == 0)
      timeout = -1;
    return doSelect(timeout);
  }

  /* (non-Javadoc)
   * @see java.nio.channels.Selector#selectedKeys()
   */
  public Set selectedKeys()
  {
    if (!isOpen())
      throw new ClosedSelectorException();

    return selected;
  }

  /* (non-Javadoc)
   * @see java.nio.channels.Selector#selectNow()
   */
  public int selectNow() throws IOException
  {
    return doSelect(0);
  }

  /* (non-Javadoc)
   * @see java.nio.channels.Selector#wakeup()
   */
  public Selector wakeup()
  {
    if (blockedThread != null)
      blockedThread.interrupt();
    return this;
  }

  public String toString()
  {
    return super.toString() + " [ fd: " + kq + " ]";
  }

  public boolean equals(Object o)
  {
    if (!(o instanceof KqueueSelectorImpl))
      return false;

    return ((KqueueSelectorImpl) o).kq == kq;
  }

  int doSelect(long timeout) throws IOException
  {
    Set cancelled = cancelledKeys();
    synchronized (cancelled)
    {
      synchronized (keys)
      {
        for (Iterator it = cancelled.iterator(); it.hasNext(); )
          {
            KqueueSelectionKeyImpl key = (KqueueSelectionKeyImpl) it.next();
            key.interestOps = 0;
          }

        int events_size = (2 * _sizeof_struct_kevent) * keys.size();
        int num_events = 0;

        for (Iterator it = keys.entrySet().iterator(); it.hasNext(); )
          {
            Map.Entry e = (Map.Entry) it.next();
            KqueueSelectionKeyImpl key = (KqueueSelectionKeyImpl) e.getValue();

            SelectableChannel ch = key.channel();
            if (ch instanceof VMChannelOwner)
              {
                if (!((VMChannelOwner) ch).getVMChannel().getState().isValid())
                  {
                    // closed channel; removed from kqueue automatically.
                    it.remove();
                    continue;
                  }
              }

            // If this key is registering a read filter, add it to the buffer.
            if (key.needCommitRead())
              {
                kevent_set(events, num_events, key.fd,
                           key.interestOps & (OP_READ | OP_ACCEPT),
                           key.activeOps & (OP_READ | OP_ACCEPT), key.key);
                num_events++;
              }

            // If this key is registering a write filter, add it to the buffer.
            if (key.needCommitWrite())
              {
                kevent_set(events, num_events, key.fd,
                           key.interestOps & (OP_WRITE | OP_CONNECT),
                           key.activeOps & (OP_WRITE | OP_CONNECT), key.key);
                num_events++;
              }
          }
        events.rewind().limit(events.capacity());

        //System.out.println("dump of keys to select:");
        //dump_selection_keys(events.duplicate());

        int n = 0;
        try
          {
            //System.out.println("[" + kq + "] kevent enter selecting from " + keys.size());
            begin();
            blockedThread = Thread.currentThread();
            if (blockedThread.isInterrupted())
              timeout = 0;
            n = kevent(kq, events, num_events,
                       events.capacity() / _sizeof_struct_kevent, timeout);
          }
        finally
          {
            end();
            blockedThread = null;
            Thread.interrupted();
            //System.out.println("[" + kq + "kevent exit selected " + n);
          }

        //System.out.println("dump of keys selected:");
        //dump_selection_keys((ByteBuffer) events.duplicate().limit(n * _sizeof_struct_kevent));

        // Commit the operations we've just added in the call to kevent.
        for (Iterator it = keys.values().iterator(); it.hasNext(); )
          {
            KqueueSelectionKeyImpl key = (KqueueSelectionKeyImpl) it.next();
            key.activeOps = key.interestOps;
          }

        selected = new HashSet/*<KqueueSelectionKeyImpl>*/(n);
        int x = 0;
        for (int i = 0; i < n; i++)
          {
            events.position(x).limit(x + _sizeof_struct_kevent);
            x += _sizeof_struct_kevent;
            int y = fetch_key(events.slice());
            KqueueSelectionKeyImpl key =
              (KqueueSelectionKeyImpl) keys.get(new Integer(y));

            if (key == null)
              {
                System.out.println("WARNING! no key found for selected key " + y);
                continue;
              }
            // Keys that have been cancelled may be returned here; don't
            // add them to the selected set.
            if (!key.isValid())
              continue;
            key.readyOps = ready_ops(events.slice(), key.interestOps);
            selected.add(key);
          }

        // Finally, remove the cancelled keys.
        for (Iterator it = cancelled.iterator(); it.hasNext(); )
          {
            KqueueSelectionKeyImpl key = (KqueueSelectionKeyImpl) it.next();
            keys.remove(new Integer(key.key));
            deregister(key);
            it.remove();
          }

        reallocateBuffer();

        return selected.size();
      }
    }
  }

  protected SelectionKey register(AbstractSelectableChannel channel,
                                  int interestOps,
                                  Object attachment)
  {
    int native_fd = -1;
    try
      {
        if (channel instanceof VMChannelOwner)
          native_fd = ((VMChannelOwner) channel).getVMChannel()
            .getState().getNativeFD();
        else
          throw new IllegalArgumentException("cannot handle channel type " +
                                             channel.getClass().getName());
      }
    catch (IOException ioe)
      {
        throw new IllegalArgumentException("channel is closed or invalid");
      }

    KqueueSelectionKeyImpl result = new KqueueSelectionKeyImpl(this, channel);
    result.interestOps = interestOps;
    result.attach(attachment);
    result.fd = native_fd;
    result.key = System.identityHashCode(result);
    synchronized (keys)
    {
      while (keys.containsKey(new Integer(result.key)))
        result.key++;
      keys.put(new Integer(result.key), result);
      reallocateBuffer();
    }
    return result;
  }

  void setInterestOps(KqueueSelectionKeyImpl key, int ops)
  {
    synchronized (keys)
    {
      key.interestOps = ops;
    }
  }

  /**
   * Reallocate the events buffer. This is the destination buffer for
   * events returned by kevent. This method will:
   *
   *   * Grow the buffer if there is insufficent space for all registered
   *     events.
   *   * Shrink the buffer if it is more than twice the size needed.
   *
   */
  private void reallocateBuffer()
  {
    synchronized (keys)
    {
      if (events.capacity() < (2 * _sizeof_struct_kevent) * keys.size())
        {
          int cap = events.capacity();
          if (cap >= MAX_DOUBLING_CAPACITY)
            cap += CAP_INCREMENT;
          else
            cap = cap << 1;

          events = ByteBuffer.allocateDirect(cap);
        }
      else if (events.capacity() > 4 * (_sizeof_struct_kevent) * keys.size() + 1
               && events.capacity() > INITIAL_CAPACITY)
        {
          int cap = events.capacity();
          cap = cap >>> 1;
          events = ByteBuffer.allocateDirect(cap);
        }
    }
  }

  //synchronized void updateOps(KqueueSelectionKeyImpl key, int interestOps)
  //{
  //  updateOps(key, interestOps, 0, false);
  //}

  /*void updateOps(KqueueSelectionKeyImpl key, int interestOps,
                 int activeOps, int fd)
  {
    //System.out.println(">> updating kqueue selection key:");
    //dump_selection_keys(key.nstate.duplicate());
    //System.out.println("<<");
    synchronized (keys)
    {
      kevent_set(key.nstate, fd, interestOps, activeOps, key.key);
    }
    //System.out.println(">> updated kqueue selection key:");
    //dump_selection_keys(key.nstate.duplicate());
    //System.out.println("<<");
  }*/

  private void dump_selection_keys(ByteBuffer keys)
  {
    // WARNING! This method is not guaranteed to be portable! This works
    // on darwin/x86, but the sizeof and offsetof these fields may be
    // different on other platforms!
    int i = 0;
    keys.order(ByteOrder.nativeOrder());
    while (keys.hasRemaining())
      {
        System.out.println("struct kevent { ident: "
                           + Integer.toString(keys.getInt())
                           + " filter: "
                           + Integer.toHexString(keys.getShort() & 0xFFFF)
                           + " flags: "
                           + Integer.toHexString(keys.getShort() & 0xFFFF)
                           + " fflags: "
                           + Integer.toHexString(keys.getInt())
                           + " data: "
                           + Integer.toHexString(keys.getInt())
                           + " udata: "
                           + Integer.toHexString(keys.getInt())
                           + " }");
      }
  }

  /**
   * Return the size of a <code>struct kevent</code> on this system.
   *
   * @return The size of <code>struct kevent</code>.
   */
  private static native int sizeof_struct_kevent();

  /**
   * Opens a kqueue descriptor.
   *
   * @return The new kqueue descriptor.
   * @throws IOException If opening fails.
   */
  private static native int implOpen() throws IOException;

  /**
   * Closes the kqueue file descriptor.
   *
   * @param kq The kqueue file descriptor.
   * @throws IOException
   */
  private static native void implClose(int kq) throws IOException;

  /**
   * Initialize the specified native state for the given interest ops.
   *
   * @param nstate The native state structures; in this buffer should be
   *  the <code>struct kevent</code>s created for a key.
   * @param fd The file descriptor. If 0, the native FD is unmodified.
   * @param interestOps The operations to enable.
   * @param key A unique key that will reference the associated key later.
   * @param delete Set to true if this event should be deleted from the
   *  kqueue (if false, this event is added/updated).
   */
  private static native void kevent_set(ByteBuffer nstate, int i, int fd,
                                        int interestOps, int activeOps, int key);

  /**
   * Poll for events. The source events are stored in <code>events</code>,
   * which is also where polled events will be placed.
   *
   * @param events The events to poll. This buffer is also the destination
   *  for events read from the queue.
   * @param nevents The number of events to poll (that is, the number of
   *  events in the <code>events</code> buffer).
   * @param nout The maximum number of events that may be returned.
   * @param timeout The timeout. A timeout of -1 returns immediately; a timeout
   *  of 0 waits indefinitely.
   * @return The number of events read.
   */
  private static native int kevent(int kq, ByteBuffer events, int nevents,
                                   int nout, long timeout);

  /**
   * Fetch a polled key from a native state buffer. For each kevent key we
   * create, we put the native state info (one or more <code>struct
   *  kevent</code>s) in that key's {@link KqueueSelectionKeyImpl#nstate}
   * buffer, and place the pointer of the key in the <code>udata</code> field
   * of that structure. This method fetches that pointer from the given
   * buffer (assumed to be a <code>struct kqueue</code>) and returns it.
   *
   * @param nstate The buffer containing the <code>struct kqueue</code> to read.
   * @return The key object.
   */
  private static native int fetch_key(ByteBuffer nstate);

  /**
   * Fetch the ready ops of the associated native state. That is, this
   * inspects the first argument as a <code>struct kevent</code>, looking
   * at its operation (the input is assumed to have been returned via a
   * previous call to <code>kevent</code>), and translating that to the
   * appropriate Java bit set, based on the second argument.
   *
   * @param nstate The native state.
   * @param interestOps The enabled operations for the key.
   * @return The bit set representing the ready operations.
   */
  private static native int ready_ops(ByteBuffer nstate, int interestOps);

  /**
   * Check if kevent returned EV_EOF for a selection key.
   *
   * @param nstate The native state.
   * @return True if the kevent call returned EOF.
   */
  private static native boolean check_eof(ByteBuffer nstate);
}
