Package com.starlight.intrepid.spi.mina

Source Code of com.starlight.intrepid.spi.mina.CloseHandler$CloseRunnable

package com.starlight.intrepid.spi.mina;

import com.starlight.thread.NamingThreadFactory;
import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.session.IoSession;

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


/**
* It's been found (at least on Linux, unsure on other platforms) that closing a session
* too quickly after it is opened can cause the connection to get "stuck" and require
* a timeout to pass. If we ensure that a session is open for at least a second or so
* (on our test linux system, Fedora 15) there are no issues. So, this class is used
* to ensure a session has been open a reasonable amount of time before it is closed.
*/
class CloseHandler {
  private static final long SESSION_MIN_CLOSE_TIME =
    Long.getLong( "intrepid.spi.mina.close_min_time", 5000 ).longValue();

  private static final int SESSION_CLOSE_THREADS =
    Integer.getInteger( "intrepid.spi.min.close_threads", 2 ).intValue();

  private static final ScheduledExecutorService schedule_executor;
  static {
    if ( SESSION_MIN_CLOSE_TIME <= 0 ) schedule_executor = null;
    else {
      schedule_executor = new ScheduledThreadPoolExecutor( SESSION_CLOSE_THREADS,
        new NamingThreadFactory( "Intrepid CloseHandler-", true ) );
    }
  }


  /**
   * Close the session using a default amount of "nice" time before a forceful close.
   */
  static void close( IoSession session ) {
    close( session, 2000 );
  }

  /**
   * Close the session, first trying to close it "nicely" (allowing messages in the
   * queue to be sent) and then closing it forcefully if a nice close doesn't finish
   * in the allotted time.
   *
   * @param nice_close_time_ms    The amount of time (in milliseconds) to allow the
   *                              "nice" close to finish before forcefully closing the
   *                              session, if the nice close hasn't completed.
   */
  static void close( IoSession session, long nice_close_time_ms ) {
    CloseRunnable runnable = new CloseRunnable( session, nice_close_time_ms );
    if ( SESSION_MIN_CLOSE_TIME <= 0 ) schedule_executor.execute( runnable );
    else {
      Long create_time =
        ( Long ) session.getAttribute( MINAIntrepidSPI.CREATED_TIME_KEY );
      if ( create_time == null ) {
        assert false : "Null create time: " + session;
        create_time = Long.valueOf( System.nanoTime() );    // assume worst case
      }

      long elapse_ms = TimeUnit.NANOSECONDS.toMillis(
        System.nanoTime() - create_time.longValue() );
      if ( elapse_ms < 0 ) elapse_ms = 0; // sanity check

      long delay = nice_close_time_ms - elapse_ms;
      if ( delay > 0 ) {
        schedule_executor.schedule( runnable, delay, TimeUnit.MILLISECONDS );
      }
      else schedule_executor.execute( runnable );
    }
  }


  static class CloseRunnable implements Runnable {
    private final IoSession session;
    private final long nice_close_time_ms;

    CloseRunnable( IoSession session, long nice_close_time_ms ) {
      this.session = session;
      this.nice_close_time_ms = nice_close_time_ms;
    }


    @Override
    public void run() {
      if ( nice_close_time_ms >= 0 ) {
        CloseFuture future = session.close( false );
        future.awaitUninterruptibly( nice_close_time_ms );
        if ( future.isDone() ) return;
      }

      session.close( true );
    }
  }
}
TOP

Related Classes of com.starlight.intrepid.spi.mina.CloseHandler$CloseRunnable

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.