/** 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); }
/** {@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; }