Package com.sun.sgs.impl.protocol.simple

Source Code of com.sun.sgs.impl.protocol.simple.SimpleSgsProtocolAcceptor$MonitorDisconnectingSessionsTask

/*
* Copyright 2010 The RedDwarf Authors.  All rights reserved
* Portions of this file have been modified as part of RedDwarf
* The source code is governed by a GPLv2 license that can be found
* in the LICENSE file.
*/
/*
* Copyright 2007-2010 Sun Microsystems, Inc.
*
* This file is part of Project Darkstar Server.
*
* Project Darkstar Server is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation and
* distributed hereunder to you.
*
* Project Darkstar Server 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*
* --
*/

package com.sun.sgs.impl.protocol.simple;

import com.sun.sgs.app.Delivery;
import com.sun.sgs.auth.Identity;
import com.sun.sgs.auth.IdentityCoordinator;
import com.sun.sgs.impl.auth.NamePasswordCredentials;
import com.sun.sgs.impl.sharedutil.LoggerWrapper;
import com.sun.sgs.impl.sharedutil.PropertiesWrapper;
import com.sun.sgs.impl.util.AbstractKernelRunnable;
import com.sun.sgs.impl.util.AbstractService;
import com.sun.sgs.kernel.ComponentRegistry;
import com.sun.sgs.kernel.KernelRunnable;
import com.sun.sgs.kernel.RecurringTaskHandle;
import com.sun.sgs.nio.channels.AsynchronousByteChannel;
import com.sun.sgs.protocol.ProtocolAcceptor;
import com.sun.sgs.protocol.ProtocolDescriptor;
import com.sun.sgs.protocol.ProtocolListener;
import com.sun.sgs.protocol.SessionProtocol;
import com.sun.sgs.protocol.simple.SimpleSgsProtocol;
import com.sun.sgs.service.TransactionProxy;
import com.sun.sgs.transport.ConnectionHandler;
import com.sun.sgs.transport.Transport;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.login.LoginException;

/**
* A protocol acceptor for connections that speak the {@link
* SimpleSgsProtocol}. The {@link #SimpleSgsProtocolAcceptor constructors}
* support the following properties: <p>
*
* <dl style="margin-left: 1em">
*
* <dt> <i>Property:</i> <code><b>
*  {@value #TRANSPORT_PROPERTY}
</b></code><br>
<i>Default:</i> {@value #DEFAULT_TRANSPORT}
*
* <dd style="padding-top: .5em">Specifies the transport. The
*      specified transport must support {@link Delivery#RELIABLE}.<p>
*
* <dt> <i>Property:</i> <code><b>
*  {@value #PROTOCOL_VERSION_PROPERTY}
</b></code><br>
<i>Default:</i> {@value #DEFAULT_PROTOCOL_VERSION}
*
* <dd style="padding-top: .5em">Specifies the <code>SimpleSgsProtocol</code>
*  version for this acceptor's connections. Valid values for the protocol
*  version are <b><code>0x05</code></b> which supports client session
*  relocation, and <b><code>0x04</code></b>, which does not
*  support client session relocation but is compatible with clients
*  using the older protocol version.  Protocol version
<b><code>0x05</code></b> is incompatible with clients using
*  protocol version <b><code>0x04</code></b>.<p>
*
* <dt> <i>Property:</i> <code><b>
*  {@value #READ_BUFFER_SIZE_PROPERTY}
</b></code><br>
<i>Default:</i> {@value #DEFAULT_READ_BUFFER_SIZE}<br>
*      <i>Minimum:</i> {@value #MIN_READ_BUFFER_SIZE}<br>
*
* <dd style="padding-top: .5em">
*  Specifies the read buffer size.<p>
*
* <dt> <i>Property:</i> <code><b>
*  {@value #DISCONNECT_DELAY_PROPERTY}
</b></code><br>
<i>Default:</i> {@value #DEFAULT_DISCONNECT_DELAY}<br>
*      <i>Minimum:</i> {@value #MIN_DISCONNECT_DELAY}<br>
*
* <dd style="padding-top: .5em">
*  Specifies the disconnect delay (in milliseconds) for disconnecting
*      sessions.<p>
* </dl> <p>
*/
public class SimpleSgsProtocolAcceptor
    extends AbstractService
    implements ProtocolAcceptor
{
    /** The package name. */
    private static final String PKG_NAME = "com.sun.sgs.impl.protocol.simple";
   
    /** The logger for this class. */
    private static final LoggerWrapper staticLogger =
  new LoggerWrapper(Logger.getLogger(PKG_NAME + ".acceptor"));
   
    /** The name of the version key. */
    private static final String VERSION_KEY = PKG_NAME + ".service.version";

    /** The major version. */
    private static final int MAJOR_VERSION = 1;
   
    /** The minor version. */
    private static final int MINOR_VERSION = 0;

    /** The name of the read buffer size property. */
    public static final String READ_BUFFER_SIZE_PROPERTY =
        PKG_NAME + ".read.buffer.size";

    /** The default read buffer size: {@value #DEFAULT_READ_BUFFER_SIZE}. */
    public static final int DEFAULT_READ_BUFFER_SIZE = 128 * 1024;
   
    /** The minimum read buffer size value. */
    public static final int MIN_READ_BUFFER_SIZE = 8192;
   
    /**
     * The transport property. The specified transport must support
     * RELIABLE delivery.
     */
    public static final String TRANSPORT_PROPERTY =
        PKG_NAME + ".transport";
   
    /** The default transport. */
    public static final String DEFAULT_TRANSPORT =
        "com.sun.sgs.impl.transport.tcp.TcpTransport";

    /** The protocol version property.  Valid values are 4 and 5. */
    public static final String PROTOCOL_VERSION_PROPERTY =
  PKG_NAME + ".protocol.version";

    /** The protocol version 4. */
    public static final int PROTOCOL4 = 4;

    /** The default protocol version: {@value #DEFAULT_PROTOCOL_VERSION}. */
    public static final int DEFAULT_PROTOCOL_VERSION = 5;
           
    /** The name of the disconnect delay property. */
    public static final String DISCONNECT_DELAY_PROPERTY =
  PKG_NAME + ".disconnect.delay";
   
    /** The time (in milliseconds) that a disconnecting connection is
     * allowed before this service forcibly disconnects it.
     */
    public static final long DEFAULT_DISCONNECT_DELAY = 1000;
   
    /** The minimum disconnect delay value. */
    public static final long MIN_DISCONNECT_DELAY = 1000;

    /** The identity manager. */
    private final IdentityCoordinator identityManager;

    /** The read buffer size for new connections. */
    protected final int readBufferSize;
   
    /** The transport. */
    protected final Transport transport;
   
    /** The disconnect delay (in milliseconds) for disconnecting sessions. */
    private final long disconnectDelay;

    /** The {@code SimpleSgsProtocol} version for the protocol impl. */
    private final int protocolVersion;

    /** The protocol descriptor. */
    private ProtocolDescriptor protocolDesc;
 
    /** The map of disconnecting {@code ClientSessionHandler}s, keyed by
     * the time the connection should expire.
     */
    private final ConcurrentSkipListMap<Long, SessionProtocol>
  disconnectingHandlersMap =
      new ConcurrentSkipListMap<Long, SessionProtocol>();

    /** The handle for the task that monitors disconnecting client sessions. */
    private final RecurringTaskHandle monitorDisconnectingSessionsTaskHandle;

    /**
     * Constructs an instance with the specified {@code properties},
     * {@code systemRegistry}, and {@code txnProxy}.
     *
     * @param  properties the configuration properties
     * @param  systemRegistry the system registry
     * @param  txnProxy a transaction proxy
     *
     * @throws  Exception if a problem occurs
     */
    public SimpleSgsProtocolAcceptor(Properties properties,
             ComponentRegistry systemRegistry,
             TransactionProxy txnProxy)
  throws Exception
    {
  this(properties, systemRegistry, txnProxy, staticLogger);
 
    }

    /**
     * Constructs an instance with the specified {@code properties},
     * {@code systemRegistry}, {@code txnProxy}, and {@code logger}.
     *
     * @param  properties the configuration properties
     * @param  systemRegistry the system registry
     * @param  txnProxy a transaction proxy
     * @param  logger a logger for this instance
     *
     * @throws  Exception if a problem occurs
     */
    protected SimpleSgsProtocolAcceptor(Properties properties,
          ComponentRegistry systemRegistry,
          TransactionProxy txnProxy,
          LoggerWrapper logger)
  throws Exception
    {
  super(properties, systemRegistry, txnProxy, logger);
        logger.log(Level.CONFIG, "Creating SimpleSgsProtocolAcceptor");

  PropertiesWrapper wrappedProps = new PropertiesWrapper(properties);
  try {
            readBufferSize = wrappedProps.getIntProperty(
                READ_BUFFER_SIZE_PROPERTY, DEFAULT_READ_BUFFER_SIZE,
                MIN_READ_BUFFER_SIZE, Integer.MAX_VALUE);
      disconnectDelay = wrappedProps.getLongProperty(
    DISCONNECT_DELAY_PROPERTY, DEFAULT_DISCONNECT_DELAY,
    MIN_DISCONNECT_DELAY, Long.MAX_VALUE);
      identityManager =
    systemRegistry.getComponent(IdentityCoordinator.class);
              
            transport =
                wrappedProps.getClassInstanceProperty(
        TRANSPORT_PROPERTY, DEFAULT_TRANSPORT, Transport.class,
        new Class[] {Properties.class}, properties);

      protocolVersion =
    wrappedProps.getIntProperty(
    PROTOCOL_VERSION_PROPERTY, DEFAULT_PROTOCOL_VERSION,
    PROTOCOL4, SimpleSgsProtocol.VERSION);

            if (!transport.getDelivery().equals(Delivery.RELIABLE)) {
                transport.shutdown();
                throw new IllegalArgumentException(
        "transport must support RELIABLE delivery");
            }
      /*
       * Set up recurring task to monitor disconnecting client sessions.
       */
      monitorDisconnectingSessionsTaskHandle =
    taskScheduler.scheduleRecurringTask(
         new MonitorDisconnectingSessionsTask(),
        taskOwner, System.currentTimeMillis(),
        disconnectDelay);
      monitorDisconnectingSessionsTaskHandle.start();
     
      /*
       * Check service version.
       */
      transactionScheduler.runTask(
    new AbstractKernelRunnable("CheckServiceVersion") {
        public void run() {
      checkServiceVersion(
          VERSION_KEY, MAJOR_VERSION, MINOR_VERSION);
        } },  taskOwner);

            logger.log(Level.CONFIG,
                       "Created SimpleSgsProtocolAcceptor with properties:" +
           "\n  " + PROTOCOL_VERSION_PROPERTY + "=" +
           protocolVersion +
                       "\n  " + DISCONNECT_DELAY_PROPERTY + "=" +
                       disconnectDelay +
                       "\n  " + READ_BUFFER_SIZE_PROPERTY + "=" +
                       readBufferSize +
                       "\n  " + TRANSPORT_PROPERTY + "=" +
                       transport.getClass().getName());
     
  } catch (RuntimeException e) {
      if (logger.isLoggable(Level.CONFIG)) {
    logger.logThrow(
        Level.CONFIG, e,
        "Failed to create SimpleSgsProtocolAcceptor");
      }
      throw e;
  }
    }
   
    /* -- Implement AbstractService -- */
   
    /** {@inheritDoc} */
    protected void handleServiceVersionMismatch(
  Version oldVersion, Version currentVersion)
    {
  throw new IllegalStateException(
      "unable to convert version:" + oldVersion +
      " to current version:" + currentVersion);
    }
   
    /** {@inheritDoc} */
    public void doReady() {
    }
   
    /** {@inheritDoc} */
    public void doShutdown() {
        transport.shutdown();
        monitorDisconnectingSessionsTaskHandle.cancel();
  disconnectingHandlersMap.clear();
    }

    /* -- Implement ProtocolAcceptor -- */

    /** {@inheritDoc} */
    public synchronized ProtocolDescriptor getDescriptor() {
  if (protocolDesc == null) {
            protocolDesc =
    new SimpleSgsProtocolDescriptor(transport.getDescriptor());
  }
        return protocolDesc;
    }
   
    /** {@inheritDoc} */
    public void accept(ProtocolListener protocolListener) throws IOException {
        transport.accept(new ConnectionHandlerImpl(protocolListener));
    }

    /** {@inheritDoc} */
    public void close() {
  shutdown();
    }

    /**
     * Transport connection handler.
     */
    private class ConnectionHandlerImpl implements ConnectionHandler {

        private final ProtocolListener protocolListener;

        ConnectionHandlerImpl(ProtocolListener protocolListener) {
            if (protocolListener == null) {
                throw new NullPointerException("null protocolListener");
            }
            this.protocolListener = protocolListener;
        }
       
        /** {@inheritDoc} */
        public void newConnection(AsynchronousByteChannel byteChannel)
            throws Exception
        {
      if (protocolVersion == PROTOCOL4) {
    new SimpleSgsProtocolImpl(
        protocolListener, SimpleSgsProtocolAcceptor.this,
        byteChannel, readBufferSize);
      } else /* latest SimpleSgsProtocol version */ {
    new SimpleSgsRelocationProtocolImpl(
        protocolListener, SimpleSgsProtocolAcceptor.this,
        byteChannel, readBufferSize);
      }
        }

        /** {@inheritDoc} */
        public void shutdown() {
            logger.log(Level.SEVERE, "transport unexpectly shutdown");
            close();
        }
    }
   
    /**
     * Returns the authenticated identity for the specified {@code name} and
     * {@code password}.
     *
     * @param  name a name
     * @param  password a password
     * @return  the authenticated identity
     * @throws  LoginException if a problem occurs authenticating the name and
     *    password
     */
    public Identity authenticate(String name, String password)
  throws LoginException
    {
  return identityManager.authenticateIdentity(
      new NamePasswordCredentials(name, password.toCharArray()));
    }

    /**
     * Adds the specified {@code protocol} to the map containing {@code
     * SessionProtocol}s that are disconnecting.  The map is keyed by
     * connection expiration time.  The connection will expire after a fixed
     * delay and will be forcibly terminated if the client hasn't already
     * closed the connection.
     *
     * @param  protocol a {@code SessionProtocol} that is disconnecting
     */
    public void monitorDisconnection(SessionProtocol protocol) {
  disconnectingHandlersMap.put(
      System.currentTimeMillis() + disconnectDelay,  protocol);
    }
   
    /**
     * Schedules a non-durable, non-transactional {@code task}.
     *
     * @param  task a non-durable, non-transactional task
     */
    public void scheduleNonTransactionalTask(KernelRunnable task) {
        taskScheduler.scheduleTask(task, taskOwner);
    }
   
    /* -- Private methods and classes -- */

    /**
     * A task to monitor disconnecting sessions to ensure that their
     * associated connections are closed by the client in a timely manner.
     * If a connection is not terminated by the expiration time, then the
     * connection is forcibly closed.
     */
    private class MonitorDisconnectingSessionsTask
  extends AbstractKernelRunnable
    {
  /** Constructs and instance. */
  MonitorDisconnectingSessionsTask() {
      super(null);
  }
 
  /** {@inheritDoc} */
  public void run() {
      long now = System.currentTimeMillis();
      if (!disconnectingHandlersMap.isEmpty() &&
    disconnectingHandlersMap.firstKey() < now) {

    Map<Long, SessionProtocol> expiredSessions =
        disconnectingHandlersMap.headMap(now);
    for (SessionProtocol protocol : expiredSessions.values()) {
        try {
      protocol.close();
        } catch (IOException e) {
        }
    }
    expiredSessions.clear();
      }
  }
    }
}
TOP

Related Classes of com.sun.sgs.impl.protocol.simple.SimpleSgsProtocolAcceptor$MonitorDisconnectingSessionsTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.