@Override
  public io.undertow.server.session.Session createSession(
      HttpServerExchange exchange, SessionConfig config) {
    if (config == null) {
      throw UndertowMessages.MESSAGES.couldNotFindSessionCookieConfig();
    }
    String id = this.findSessionId(exchange, config);

    if (id != null) {
      if (this.manager.containsSession(id)) {
        throw UndertowMessages.MESSAGES.sessionAlreadyExists(id);
      }
    } else {
      id = this.manager.createSessionId();
    }

    Batcher batcher = this.manager.getBatcher();
    boolean started = batcher.startBatch();
    try {
      Session<Void> session = this.manager.createSession(id);
      io.undertow.server.session.Session facade = this.getSession(session, exchange, config);
      this.sessionListeners.sessionCreated(facade, exchange);
      return facade;
    } catch (RuntimeException | Error e) {
      if (started) {
        batcher.endBatch(false);
      }
      throw e;
    }
  }
  @Override
  public io.undertow.server.session.Session createSession(
      HttpServerExchange exchange, SessionConfig config) {
    if (config == null) {
      throw UndertowMessages.MESSAGES.couldNotFindSessionCookieConfig();
    }

    String id = config.findSessionId(exchange);

    if (id == null) {
      int attempts = 0;
      do {
        if (++attempts > MAX_SESSION_ID_GENERATION_ATTEMPTS) {
          throw UndertowMessages.MESSAGES.couldNotGenerateUniqueSessionId();
        }
        id = this.manager.createIdentifier();
      } while (this.manager.containsSession(id));

      config.setSessionId(exchange, id);
    }

    Batch batch = this.manager.getBatcher().createBatch();
    try {
      Session<LocalSessionContext> session = this.manager.createSession(id);
      io.undertow.server.session.Session adapter =
          new DistributableSession(this, session, config, batch);
      this.sessionListeners.sessionCreated(adapter, exchange);
      return adapter;
    } catch (RuntimeException | Error e) {
      batch.discard();
      throw e;
    }
  }
  @Override
  public Session createSession(
      final HttpServerExchange serverExchange, final SessionConfig config) {
    if (evictionQueue != null) {
      if (expireOldestUnusedSessionOnMax) {
        while (sessions.size() >= maxSize && !evictionQueue.isEmpty()) {

          String key = evictionQueue.poll();
          UndertowLogger.REQUEST_LOGGER.debugf("Removing session %s as max size has been hit", key);
          SessionImpl toRemove = sessions.get(key);
          if (toRemove != null) {
            toRemove.invalidate(
                null, SessionListener.SessionDestroyedReason.TIMEOUT); // todo: better reason
          }
        }
      } else if (sessions.size() >= maxSize) {
        if (statisticsEnabled) {
          rejectedSessionCount.incrementAndGet();
        }
        throw UndertowMessages.MESSAGES.tooManySessions(maxSize);
      }
    }
    if (config == null) {
      throw UndertowMessages.MESSAGES.couldNotFindSessionCookieConfig();
    }
    String sessionID = config.findSessionId(serverExchange);
    int count = 0;
    while (sessionID == null) {
      sessionID = sessionIdGenerator.createSessionId();
      if (sessions.containsKey(sessionID)) {
        sessionID = null;
      }
      if (count++ == 100) {
        // this should never happen
        // but we guard against pathalogical session id generators to prevent an infinite loop
        throw UndertowMessages.MESSAGES.couldNotGenerateUniqueSessionId();
      }
    }
    Object evictionToken;
    if (evictionQueue != null) {
      evictionToken = evictionQueue.offerLastAndReturnToken(sessionID);
    } else {
      evictionToken = null;
    }
    if (statisticsEnabled) {
      createdSessionCount.incrementAndGet();
    }
    final SessionImpl session =
        new SessionImpl(
            this,
            sessionID,
            config,
            serverExchange.getIoThread(),
            serverExchange.getConnection().getWorker(),
            evictionToken,
            defaultSessionTimeout);
    sessions.put(sessionID, session);
    config.setSessionId(serverExchange, session.getId());
    session.lastAccessed = System.currentTimeMillis();
    session.bumpTimeout();
    sessionListeners.sessionCreated(session, serverExchange);
    serverExchange.putAttachment(NEW_SESSION, session);
    return session;
  }