/** Resume this {@link Controller} and associated {@link SelectorHandler}s */
  public void resume() throws IOException {
    if (!State.PAUSED.equals(stateHolder.getState(false))) {
      throw new IllegalStateException(
          "Controller is not in PAUSED state, but: " + stateHolder.getState(false));
    }

    stateHolder.setState(State.STARTED);
  }
Example #2
0
  /** {@inheritDoc} */
  public void resume() {
    if (!State.PAUSED.equals(stateHolder.getState(false))) {
      throw new IllegalStateException(
          "SelectorHandler is not in PAUSED state, but: " + stateHolder.getState(false));
    }

    stateHolder.setState(State.STARTED);
  }
 /**
  * Add a {@link SelectorHandler}
  *
  * @param selectorHandler - the {@link SelectorHandler}
  */
 public void addSelectorHandler(SelectorHandler selectorHandler) {
   selectorHandlers.add(selectorHandler);
   if (stateHolder.getState(false) != null && !State.STOPPED.equals(stateHolder.getState())) {
     addSelectorHandlerOnReadControllers(selectorHandler);
     if (readySelectorHandlerCounter != null) {
       readySelectorHandlerCounter.incrementAndGet();
     }
     if (stoppedSelectorHandlerCounter != null) {
       stoppedSelectorHandlerCounter.incrementAndGet();
     }
     startSelectorHandlerRunner(selectorHandler, true);
   }
 }
  /**
   * Register a SelectionKey.
   *
   * @param key <tt>SelectionKey</tt> to register
   * @param ops - the interest op to register
   * @param protocol specified protocol SelectorHandler key should be registered on
   */
  public void registerKey(SelectionKey key, int ops, Protocol protocol) {
    if (stateHolder.getState() == State.STOPPED) {
      return;
    }

    getSelectorHandler(protocol).register(key, ops);
  }
 /** Method waits until all initialized {@link SelectorHandler}s will not get stopped */
 protected void waitUntilSeletorHandlersStop() {
   synchronized (stoppedSelectorHandlerCounter) {
     while (stoppedSelectorHandlerCounter.get() > 0
         || !State.STOPPED.equals(stateHolder.getState())) {
       try {
         stoppedSelectorHandlerCounter.wait(1000);
       } catch (InterruptedException ex) {
       }
     }
   }
 }
  /**
   * @param e
   * @param selectorHandler
   * @param key
   */
  private void handleSelectException(
      Throwable e, SelectorHandler selectorHandler, SelectionKey key) {
    if (e instanceof ClosedSelectorException) {
      // TODO: This could indicate that the Controller is
      //       shutting down. Hence, we need to handle this Exception
      //       appropriately. Perhaps check the state before logging
      //       what's happening ?
      if (stateHolder.getState() == State.STARTED
          && selectorHandler.getStateHolder().getState() == State.STARTED) {
        logger.log(Level.SEVERE, "Selector was unexpectedly closed.");
        notifyException(e);
      } else {
        logger.log(Level.FINE, "doSelect Selector closed");
      }

    } else if (e instanceof ClosedChannelException) {
      // Don't use stateLock. This case is not strict
      if (stateHolder.getState() == State.STARTED
          && selectorHandler.getStateHolder().getState() == State.STARTED) {
        logger.log(Level.WARNING, "Channel was unexpectedly closed");
        if (key != null) {
          selectorHandler.getSelectionKeyHandler().cancel(key);
        }
        notifyException(e);
      }
    } else {
      try {
        if (key != null) {
          selectorHandler.getSelectionKeyHandler().cancel(key);
        }
        notifyException(e);
        logger.log(Level.SEVERE, "doSelect exception", e);
      } catch (Throwable t2) {
        // An unexpected exception occured, most probably caused by
        // a bad logger. Since logger can be externally configurable,
        // just output the exception on the screen and continue the
        // normal execution.
        t2.printStackTrace();
      }
    }
  }
  /**
   * Cancel a SelectionKey
   *
   * @param key <tt>SelectionKey</tt> to cancel
   * @deprecated
   */
  public void cancelKey(SelectionKey key) {
    if (stateHolder.getState() == State.STOPPED) {
      return;
    }

    SelectorHandler selectorHandler = getSelectorHandler(key.selector());
    if (selectorHandler != null) {
      selectorHandler.getSelectionKeyHandler().cancel(key);
    } else {
      throw new IllegalStateException(
          "SelectionKey is not associated " + "with known SelectorHandler");
    }
  }
  /**
   * This method handle the processing of all Selector's interest op
   * (OP_ACCEPT,OP_READ,OP_WRITE,OP_CONNECT) by delegating to its Handler. By default, all
   * java.nio.channels.Selector operations are implemented using SelectorHandler. All SelectionKey
   * operations are implemented by SelectionKeyHandler. Finally, ProtocolChain creation/re-use are
   * implemented by InstanceHandler.
   *
   * @param selectorHandler - the {@link SelectorHandler}
   */
  protected void doSelect(SelectorHandler selectorHandler) {
    final NIOContext serverCtx = pollContext(null, null);
    serverCtx.setSelectorHandler(selectorHandler);
    try {
      // Set the SelectionKeyHandler only if the SelectorHandler doesn't define one.
      if (selectorHandler.getSelectionKeyHandler() == null) {
        if (logger.isLoggable(Level.FINE)) {
          logger.log(
              Level.FINE, "Set DefaultSelectionKeyHandler to SelectorHandler: " + selectorHandler);
        }
        SelectionKeyHandler assgnSelectionKeyHandler = null;
        if (selectorHandler.getPreferredSelectionKeyHandler() != null) {
          Class<? extends SelectionKeyHandler> keyHandlerClass =
              selectorHandler.getPreferredSelectionKeyHandler();
          try {
            assgnSelectionKeyHandler = keyHandlerClass.newInstance();
            assgnSelectionKeyHandler.setSelectorHandler(selectorHandler);
          } catch (Exception e) {
            if (logger.isLoggable(Level.WARNING)) {
              logger.log(
                  Level.WARNING,
                  "Exception initializing preffered SelectionKeyHandler '"
                      + keyHandlerClass
                      + "' for the SelectorHandler '"
                      + selectorHandler
                      + "'");
            }
          }
        }
        if (assgnSelectionKeyHandler == null) {
          assgnSelectionKeyHandler = new DefaultSelectionKeyHandler(selectorHandler);
        }
        selectorHandler.setSelectionKeyHandler(assgnSelectionKeyHandler);
      }
      selectorHandler.preSelect(serverCtx);

      Set<SelectionKey> readyKeys = selectorHandler.select(serverCtx);
      if (readyKeys.size() != 0
          && stateHolder.getState(false) == State.STARTED
          && selectorHandler.getStateHolder().getState(false) == State.STARTED) {
        handleSelectedKeys(readyKeys, selectorHandler, serverCtx);
        readyKeys.clear();
      }
      selectorHandler.postSelect(serverCtx);
    } catch (Throwable e) {
      handleSelectException(e, selectorHandler, null);
    } finally {
      contexts.offer(serverCtx);
    }
  }
  /**
   * Stop the Controller by canceling all the registered keys.
   *
   * @param isAsync, true if controller should be stopped asynchrounously and control returned
   *     immediately. If false - control will be returned after Controller will be completely
   *     stoped.
   */
  public void stop(boolean isAsync) throws IOException {
    final CountDownLatch latch = new CountDownLatch(1);
    stateHolder.getStateLocker().writeLock().lock();
    try {
      if (stateHolder.getState(false) == State.STOPPED) {
        logger.log(Level.FINE, "Controller is already in stopped state");
        return;
      }

      if (!isAsync) {
        addStateListener(
            new ControllerStateListenerAdapter() {
              @Override
              public void onException(Throwable e) {
                removeStateListener(this);
                latch.countDown();
              }

              @Override
              public void onStopped() {
                removeStateListener(this);
                latch.countDown();
              }
            });
      }
      stateHolder.setState(State.STOPPED, false);
    } finally {
      stateHolder.getStateLocker().writeLock().unlock();
    }

    if (!isAsync) {
      try {
        latch.await();
      } catch (InterruptedException e) {
      }
    }
  }
  /**
   * Start the Controller. If the thread pool and/or Handler has not been defined, the default will
   * be used.
   */
  public void start() throws IOException {
    stateHolder.getStateLocker().writeLock().lock();
    boolean isUnlocked = false;
    try {
      if (stateHolder.getState(false) == null || stateHolder.getState(false) == State.STOPPED) {
        // if selectorHandlers were not set by user explicitly,
        // add TCPSelectorHandler by default
        if (selectorHandlers.isEmpty()) {
          SelectorHandler selectorHandler = new TCPSelectorHandler();
          selectorHandlers.add(selectorHandler);
        }

        if (readThreadsCount > 0) {
          initReadThreads();
          multiReadThreadSelectorHandler = new RoundRobinSelectorHandler(readThreadControllers);
        }

        stateHolder.setState(State.STARTED, false);
        notifyStarted();

        int selectorHandlerCount = selectorHandlers.size();
        readySelectorHandlerCounter = new AtomicInteger(selectorHandlerCount);
        stoppedSelectorHandlerCounter = new AtomicInteger(selectorHandlerCount);

        Iterator<SelectorHandler> it = selectorHandlers.iterator();
        if (selectorHandlerCount > 1) {
          for (; it.hasNext() && selectorHandlerCount-- > 0; ) {
            SelectorHandler selectorHandler = it.next();
            startSelectorHandlerRunner(selectorHandler, true);
          }
        } else if (it.hasNext()) {
          SelectorHandler selectorHandler = it.next();
          stateHolder.getStateLocker().writeLock().unlock();
          isUnlocked = true;
          startSelectorHandlerRunner(selectorHandler, false);
        }
      }
    } finally {
      if (!isUnlocked) {
        stateHolder.getStateLocker().writeLock().unlock();
      }
    }

    waitUntilSeletorHandlersStop();

    if (readThreadsCount > 0) {
      multiReadThreadSelectorHandler.shutdown();
      multiReadThreadSelectorHandler = null;

      for (Controller readController : readThreadControllers) {
        try {
          readController.stop();
        } catch (IOException e) {
          logger.log(Level.WARNING, "Exception occured when stopping read Controller!", e);
        }
      }

      readThreadControllers = null;
    }

    selectorHandlers.clear();
    threadPool.shutdown();
    attributes = null;

    // Notify Controller listeners
    for (ControllerStateListener stateListener : stateListeners) {
      stateListener.onStopped();
    }
  }
 /**
  * Is this Controller started?
  *
  * @return <code>boolean</code> true / false
  */
 public boolean isStarted() {
   return stateHolder.getState() == State.STARTED;
 }