/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.catalina.session;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom;

import org.junit.Assert;
import org.junit.Test;

import org.apache.catalina.Context;
import org.apache.catalina.Host;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Session;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardHost;

/**
 * Named Benchmarks so it is not automatically executed as part of the unit
 * tests.
 */
public class Benchmarks {

    /*
     * Results on markt's 4-core Windows dev box
     *  1 thread  -  ~1,400ms
     *  2 threads -  ~2,100ms
     *  4 threads -  ~3,100ms
     * 16 threads - ~14,700ms
     *
     * Results on markt's 2-core OSX dev box
     *  1 thread  -   ~1,400ms
     *  2 threads -   ~1,700ms
     *  4 threads -   ~3,500ms
     * 16 threads -  ~14,465ms
     */
    @Test
    public void testManagerBaseGenerateSessionId() throws Exception {
        doTestManagerBaseGenerateSessionId(1, 1000000);
        doTestManagerBaseGenerateSessionId(1, 1000000);
        doTestManagerBaseGenerateSessionId(1, 1000000);
        doTestManagerBaseGenerateSessionId(2, 1000000);
        doTestManagerBaseGenerateSessionId(2, 1000000);
        doTestManagerBaseGenerateSessionId(2, 1000000);
        doTestManagerBaseGenerateSessionId(4, 1000000);
        doTestManagerBaseGenerateSessionId(4, 1000000);
        doTestManagerBaseGenerateSessionId(4, 1000000);
        doTestManagerBaseGenerateSessionId(16, 1000000);
        // Reduce iterations as context switching will slow things down
        doTestManagerBaseGenerateSessionId(100, 100000);
        doTestManagerBaseGenerateSessionId(400, 10000);
    }


    private void doTestManagerBaseGenerateSessionId(int threadCount,
            int iterCount) throws Exception {

        // Create a default session manager
        StandardManager mgr = new StandardManager();
        try {
            mgr.startInternal();
        } catch (LifecycleException e) {
            // Ignore - this is expected
        }
        mgr.generateSessionId();
        while (mgr.sessionCreationTiming.size() <
                ManagerBase.TIMING_STATS_CACHE_SIZE) {
            mgr.sessionCreationTiming.add(null);
        }
        while (mgr.sessionExpirationTiming.size() <
                ManagerBase.TIMING_STATS_CACHE_SIZE) {
            mgr.sessionExpirationTiming.add(null);
        }


        Thread[] threads = new Thread[threadCount];

        for (int i = 0; i < threadCount; i++) {
            threads[i] = new Thread(
                    new TestThreadGenerateSessionId(mgr, iterCount));
        }

        long start = System.currentTimeMillis();

        for (int i = 0; i < threadCount; i++) {
            threads[i].start();
        }
        for (int i = 0; i < threadCount; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
                Assert.fail(e.getMessage());
            }
        }
        long end = System.currentTimeMillis();

        StringBuilder result = new StringBuilder();
        result.append("Threads: ");
        result.append(threadCount);
        result.append(", Time(ms): ");
        result.append(end-start);
        System.out.println(result.toString());
    }


    private static final class TestThreadGenerateSessionId implements Runnable {

        private ManagerBase mgr;
        private int count;

        TestThreadGenerateSessionId(ManagerBase mgr, int count) {
            this.mgr = mgr;
            this.count = count;
        }

        @Override
        public void run() {
            for (int i = 0; i < count; i++) {
                mgr.generateSessionId();
            }
        }
    }


    /*
     * Results on markt's 4-core Windows dev box
     *  1 thread  -  ~3,800ms
     *  2 threads -  ~6,700ms
     *  4 threads - ~11,000ms
     * 16 threads - ~43,500ms
     *
     * Results on markt's 2-core OSX dev box
     *  1 thread  -  ~4,100ms
     *  2 threads -  ~5,700ms
     *  4 threads - ~11,700ms
     * 16 threads - ~45,600ms
     */
    @Test
    public void testManagerBaseCreateSession() throws LifecycleException {
        doTestManagerBaseCreateSession(1, 100000);
        doTestManagerBaseCreateSession(2, 1000000);
        doTestManagerBaseCreateSession(4, 1000000);
        doTestManagerBaseCreateSession(16, 1000000);
        // Reduce iterations as context switching will slow things down
        doTestManagerBaseCreateSession(100, 100000);
        doTestManagerBaseCreateSession(400, 10000);
    }


    private void doTestManagerBaseCreateSession(int threadCount,
            int iterCount) throws LifecycleException {

        // Create a default session manager
        StandardManager mgr = new StandardManager();
        mgr.setPathname(null);
        Host host = new StandardHost();
        host.setName("unittest");
        Context context = new StandardContext();
        context.setPath("");
        context.setParent(host);
        mgr.setContext(context);
        mgr.start();
        mgr.generateSessionId();
        while (mgr.sessionCreationTiming.size() <
                ManagerBase.TIMING_STATS_CACHE_SIZE) {
            mgr.sessionCreationTiming.add(null);
        }
        while (mgr.sessionExpirationTiming.size() <
                ManagerBase.TIMING_STATS_CACHE_SIZE) {
            mgr.sessionExpirationTiming.add(null);
        }

        Thread[] threads = new Thread[threadCount];

        for (int i = 0; i < threadCount; i++) {
            threads[i] = new Thread(
                    new TestThreadCreateSession(mgr, iterCount));
        }

        long start = System.currentTimeMillis();

        for (int i = 0; i < threadCount; i++) {
            threads[i].start();
        }
        for (int i = 0; i < threadCount; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
                Assert.fail(e.getMessage());
            }
        }
        long end = System.currentTimeMillis();

        StringBuilder result = new StringBuilder();
        result.append("Threads: ");
        result.append(threadCount);
        result.append(", Time(ms): ");
        result.append(end-start);
        System.out.println(result.toString());
    }

    private static final class TestThreadCreateSession implements Runnable {

        private ManagerBase mgr;
        private int count;

        TestThreadCreateSession(ManagerBase mgr, int count) {
            this.mgr = mgr;
            this.count = count;
        }

        @Override
        public void run() {
            for (int i = 0; i < count; i++) {
                Session session = mgr.createSession(mgr.generateSessionId());
                session.expire();
            }
        }
    }


    /*
     * SecureRandom vs. reading /dev/urandom. Very different performance noted
     * on some platforms.
     *
     * Results on markt's 4-core Windows dev box
     *              SecureRandom  /dev/urandom
     *  1 thread  -    ~766ms        N/A
     *  2 threads -    ~843ms        N/A
     *  4 threads -    ~766ms        N/A
     *
     * Results on markt's 2-core OSX dev box
     *              SecureRandom  /dev/urandom
     *  1 thread  -     ~759ms      ~3,500ms
     *  2 threads -     ~725ms      ~5,200ms
     *  4 threads -   ~1,265ms     ~10,500ms
     */
    @Test
    public void testSecureRandomVsDevURandom() throws Exception {
        doTestSecureRandomVsDevURandom(1, 1000000);
        doTestSecureRandomVsDevURandom(2, 1000000);
        doTestSecureRandomVsDevURandom(4, 1000000);
    }

    private void doTestSecureRandomVsDevURandom(int threadCount, int iterCount)
            throws Exception {
        doTestSecureRandomVsDevURandomInner(threadCount, iterCount, true);
        doTestSecureRandomVsDevURandomInner(threadCount, iterCount, false);
    }

    private void doTestSecureRandomVsDevURandomInner(int threadCount,
            int iterCount, boolean useSecureRandom) throws Exception {

        Thread[] threads = new Thread[threadCount];

        for (int i = 0; i < threadCount; i++) {
            if (useSecureRandom) {
                threads[i] = new Thread(new TestThreadSecureRandom(iterCount));
            } else {
                threads[i] = new Thread(new TestThreadDevUrandom(iterCount));
            }
        }

        long start = System.currentTimeMillis();

        for (int i = 0; i < threadCount; i++) {
            threads[i].start();
        }
        for (int i = 0; i < threadCount; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
                Assert.fail(e.getMessage());
            }
        }
        long end = System.currentTimeMillis();

        StringBuilder result = new StringBuilder();
        if (useSecureRandom) {
            result.append("SecureRandom ");
        } else {
            result.append("/dev/urandom ");
        }
        result.append("Threads: ");
        result.append(threadCount);
        result.append(", Time(ms): ");
        result.append(end-start);
        System.out.println(result.toString());
    }

    private static final class TestThreadSecureRandom implements Runnable {

        private SecureRandom secureRandom;
        private byte[] bytes = new byte[16];
        private int count;

        TestThreadSecureRandom(int iterCount) throws Exception {
            this.count = iterCount;
            this.secureRandom = SecureRandom.getInstance("SHA1PRNG");
        }

        @Override
        public void run() {
            for (int i = 0; i < count; i++) {
                secureRandom.nextBytes(bytes);
            }
        }

    }

    private static final class TestThreadDevUrandom implements Runnable {

        private InputStream is;
        private byte[] bytes = new byte[16];
        private int count;

        TestThreadDevUrandom(int iterCount) {
            try {
                is = new FileInputStream("/dev/urandom");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            this.count = iterCount;
        }

        @Override
        public void run() {
            try {
                int read = 0;
                for (int i = 0; i < count; i++) {
                    read = is.read(bytes);
                    if (read < bytes.length) {
                        throw new IOException("Only read " + read + " bytes");
                    }
                }
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }
}
