protected Scheduler startScheduler() throws ServletException {
   try {
     Scheduler result = new ScheduledExecutorScheduler();
     result.start();
     return result;
   } catch (Exception x) {
     throw new ServletException(x);
   }
 }
 @After
 public void destroy() throws Exception {
   if (scheduler != null) scheduler.stop();
   if (selectorManager != null) selectorManager.stop();
   if (connector != null) connector.close();
   if (threadPool != null) threadPool.stop();
 }
  @Test
  public void testWaitingProcessSpuriousInterate() throws Exception {
    final TestCB cb =
        new TestCB() {
          int i = 4;

          @Override
          protected State process() throws Exception {
            processed++;
            if (i-- > 1) {
              scheduler.schedule(successTask, 50, TimeUnit.MILLISECONDS);
              return State.SCHEDULED;
            }
            return State.SUCCEEDED;
          }
        };

    cb.iterate();
    scheduler.schedule(
        new Runnable() {
          @Override
          public void run() {
            cb.iterate();
            if (!cb.isSucceeded()) scheduler.schedule(this, 50, TimeUnit.MILLISECONDS);
          }
        },
        49,
        TimeUnit.MILLISECONDS);

    Assert.assertTrue(cb.waitForComplete());

    Assert.assertEquals(4, cb.processed);
  }
 protected void stopScheduler() {
   try {
     _scheduler.stop();
   } catch (Exception x) {
     LOG.ignore(x);
   }
 }
 @After
 public void stopManager() throws Exception {
   _scheduler.stop();
   _manager.stop();
   _threadPool.stop();
   _connector.close();
 }
 @Override
 public void data(
     IStream stream, DataInfo dataInfo, long timeout, TimeUnit unit, Callback callback) {
   LOG.debug("Queuing {} on {}", dataInfo, stream);
   DataFrameBytes frameBytes = new DataFrameBytes(stream, callback, dataInfo);
   if (timeout > 0) frameBytes.task = scheduler.schedule(frameBytes, timeout, unit);
   append(frameBytes);
   flush();
 }
 @Before
 public void startManager() throws Exception {
   _writeCount = 1;
   _lastEndPoint = null;
   _lastEndPointLatch = new CountDownLatch(1);
   _connector = ServerSocketChannel.open();
   _connector.socket().bind(null);
   _scheduler.start();
   _threadPool.start();
   _manager.start();
 }
  public void init(final Interested interested) throws Exception {
    threadPool = new QueuedThreadPool();
    threadPool.start();

    scheduler = new TimerScheduler();
    scheduler.start();

    connector = ServerSocketChannel.open();
    connector.bind(new InetSocketAddress("localhost", 0));

    selectorManager =
        new SelectorManager(threadPool, scheduler) {

          @Override
          protected EndPoint newEndPoint(
              SelectableChannel channel, ManagedSelector selector, SelectionKey key)
              throws IOException {
            SocketChannelEndPoint endp =
                new SocketChannelEndPoint(channel, selector, key, getScheduler()) {
                  @Override
                  protected void onIncompleteFlush() {
                    super.onIncompleteFlush();
                    interested.onIncompleteFlush();
                  }
                };

            endp.setIdleTimeout(60000);
            return endp;
          }

          @Override
          public Connection newConnection(
              SelectableChannel channel, final EndPoint endPoint, Object attachment) {
            return new AbstractConnection(endPoint, getExecutor()) {
              @Override
              public void onOpen() {
                super.onOpen();
                fillInterested();
              }

              @Override
              public void onFillable() {
                interested.onFillable(endPoint, this);
              }
            };
          }
        };
    selectorManager.start();
  }
  /**
   * Return a request rate tracker associated with this connection; keeps track of this connection's
   * request rate. If this is not the first request from this connection, return the existing object
   * with the stored stats. If it is the first request, then create a new request tracker.
   *
   * <p>Assumes that each connection has an identifying characteristic, and goes through them in
   * order, taking the first that matches: user id (logged in), session id, client IP address.
   * Unidentifiable connections are lumped into one.
   *
   * <p>When a session expires, its rate tracker is automatically deleted.
   *
   * @param request the current request
   * @return the request rate tracker for the current connection
   */
  public RateTracker getRateTracker(ServletRequest request) {
    HttpSession session = ((HttpServletRequest) request).getSession(false);

    String loadId = extractUserId(request);
    final int type;
    if (loadId != null) {
      type = USER_AUTH;
    } else {
      if (isTrackSessions() && session != null && !session.isNew()) {
        loadId = session.getId();
        type = USER_SESSION;
      } else {
        loadId =
            isRemotePort()
                ? (request.getRemoteAddr() + request.getRemotePort())
                : request.getRemoteAddr();
        type = USER_IP;
      }
    }

    RateTracker tracker = _rateTrackers.get(loadId);

    if (tracker == null) {
      boolean allowed = checkWhitelist(request.getRemoteAddr());
      int maxRequestsPerSec = getMaxRequestsPerSec();
      tracker =
          allowed
              ? new FixedRateTracker(loadId, type, maxRequestsPerSec)
              : new RateTracker(loadId, type, maxRequestsPerSec);
      RateTracker existing = _rateTrackers.putIfAbsent(loadId, tracker);
      if (existing != null) tracker = existing;

      if (type == USER_IP) {
        // USER_IP expiration from _rateTrackers is handled by the _scheduler
        _scheduler.schedule(tracker, getMaxIdleTrackerMs(), TimeUnit.MILLISECONDS);
      } else if (session != null) {
        // USER_SESSION expiration from _rateTrackers are handled by the HttpSessionBindingListener
        session.setAttribute(__TRACKER, tracker);
      }
    }

    return tracker;
  }
 protected void doFilterChain(
     FilterChain chain, final HttpServletRequest request, final HttpServletResponse response)
     throws IOException, ServletException {
   final Thread thread = Thread.currentThread();
   Runnable requestTimeout =
       new Runnable() {
         @Override
         public void run() {
           closeConnection(request, response, thread);
         }
       };
   Scheduler.Task task =
       _scheduler.schedule(requestTimeout, getMaxRequestMs(), TimeUnit.MILLISECONDS);
   try {
     chain.doFilter(request, response);
   } finally {
     task.cancel();
   }
 }
  private void generateAndEnqueueControlFrame(
      IStream stream, ControlFrame frame, long timeout, TimeUnit unit, Callback callback) {
    try {
      // Synchronization is necessary, since we may have concurrent replies
      // and those needs to be generated and enqueued atomically in order
      // to maintain a correct compression context
      synchronized (this) {
        ByteBuffer buffer = generator.control(frame);
        LOG.debug("Queuing {} on {}", frame, stream);
        ControlFrameBytes frameBytes = new ControlFrameBytes(stream, callback, frame, buffer);
        if (timeout > 0) frameBytes.task = scheduler.schedule(frameBytes, timeout, unit);

        // Special handling for PING frames, they must be sent as soon as possible
        if (ControlFrameType.PING == frame.getType()) prepend(frameBytes);
        else append(frameBytes);
      }
    } catch (Exception x) {
      notifyCallbackFailed(callback, x);
    }
  }
 @AfterClass
 public static void afterClass() throws Exception {
   scheduler.stop();
 }
 @BeforeClass
 public static void beforeClass() throws Exception {
   scheduler.start();
 }
 protected void scheduleTimeout(AsyncContextEvent event) {
   Scheduler scheduler = _channel.getScheduler();
   if (scheduler != null && _timeoutMs > 0)
     event.setTimeoutTask(scheduler.schedule(event, _timeoutMs, TimeUnit.MILLISECONDS));
 }