/** Write all the pending messages */
  private void flush(long currentTime) {
    if (flushingSessions.isEmpty()) {
      return;
    }

    do {
      S session = flushingSessions.poll(); // the same one with firstSession

      if (session == null) {
        // Just in case ... It should not happen.
        break;
      }

      // Reset the Schedule for flush flag for this session,
      // as we are flushing it now
      session.unscheduledForFlush();

      SessionState state = getState(session);

      switch (state) {
        case OPENED:
          try {
            boolean flushedAll = flushNow(session, currentTime);

            if (flushedAll
                && !session.getWriteRequestQueue().isEmpty(session)
                && !session.isScheduledForFlush()) {
              scheduleFlush(session);
            }
          } catch (Exception e) {
            scheduleRemove(session);
            IoFilterChain filterChain = session.getFilterChain();
            filterChain.fireExceptionCaught(e);
          }

          break;

        case CLOSING:
          // Skip if the channel is already closed.
          break;

        case OPENING:
          // Retry later if session is not yet fully initialized.
          // (In case that Session.write() is called before addSession()
          // is processed)
          scheduleFlush(session);
          return;

        default:
          throw new IllegalStateException(String.valueOf(state));
      }

    } while (!flushingSessions.isEmpty());
  }