/**
 *  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.geronimo.transaction.log;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Collections;
import java.util.List;

import javax.transaction.xa.Xid;

import junit.framework.TestCase;
import org.apache.geronimo.transaction.manager.TransactionLog;

/**
 *
 *
 * @version $Rev$ $Date$
 *
 * */
public abstract class AbstractLogTest extends TestCase {
    private Object startBarrier = new Object();
    private Object stopBarrier = new Object();
    private int startedThreads = 0;
    private int stoppedThreads = 0;
    long totalDuration = 0;
    private Xid xid;
    private List names;
    final Object mutex = new Object();
    long totalXidCount = 0;
    private Writer resultsXML;
    private Writer resultsCSV;

    public void testDummy() throws Exception {}

    public void testTransactionLog() throws Exception {
        File resultFileXML = new File(getResultFileName() + ".xml");
        resultsXML = new FileWriter(resultFileXML);
        resultsXML.write("<log-test>\n");
        File resultFileCSV = new File(getResultFileName() + ".csv");
        resultsCSV = new FileWriter(resultFileCSV);
        resultsCSV.write("workerCount,xidCount,TotalXids,missingXids,DurationMilliseconds,XidsPerSecond,AverageForceTime,AverageBytesPerForce,AverageLatency\n");
        int xidCount = Integer.getInteger("xa.log.test.xid.count", 50).intValue();
        int minWorkerCount = Integer.getInteger("xa.log.test.worker.count.min", 20).intValue();
        int maxWorkerCount = Integer.getInteger("xa.log.test.worker.count.max", 40).intValue();
        int workerCountStep = Integer.getInteger("xa.log.test.worker.count.step", 20).intValue();
        int repCount = Integer.getInteger("xa.log.test.repetition.count", 1).intValue();
        long maxTime = Long.getLong("xa.log.test.max.time.seconds", 30).longValue() * 1000;
        int overtime = 0;
        try {
            for (int workers = minWorkerCount; workers <= maxWorkerCount; workers += workerCountStep) {
                for (int reps = 0; reps < repCount; reps++) {
                    if (testTransactionLog(workers, xidCount) > maxTime) {
                        overtime++;
                        if (overtime > 1) {
                            return;
                        }
                    }
                    resultsCSV.flush();
                    resultsXML.flush();
                }
            }
        } finally {
            resultsXML.write("</log-test>\n");
            resultsXML.flush();
            resultsXML.close();
            resultsCSV.flush();
            resultsCSV.close();
        }
    }

    protected abstract String getResultFileName();

    public long testTransactionLog(int workers, int xidCount) throws Exception {
        TransactionLog transactionLog = createTransactionLog();

        xid = new XidImpl2(new byte[Xid.MAXGTRIDSIZE]);
        //TODO Supply an actual list
        names = Collections.EMPTY_LIST;

        long startTime = journalTest(transactionLog, workers, xidCount);

        long stopTime = System.currentTimeMillis();

        printSpeedReport(transactionLog, startTime, stopTime, workers, xidCount);
        closeTransactionLog(transactionLog);
        return stopTime - startTime;
    }

    protected abstract void closeTransactionLog(TransactionLog transactionLog) throws Exception ;

    protected abstract TransactionLog createTransactionLog() throws Exception;

    private long journalTest(final TransactionLog logger, final int workers, final int xidCount)
            throws Exception {
        totalXidCount = 0;
        startedThreads = 0;
        stoppedThreads = 0;
        totalDuration = 0;
        for (int i = 0; i < workers; i++) {
            new Thread() {
                public void run() {
                    long localXidCount = 0;
                    boolean exception = false;
                    long localDuration = 0;
                    try {
                        synchronized (startBarrier) {
                            ++startedThreads;
                            startBarrier.notifyAll();
                            while (startedThreads < (workers + 1)) startBarrier.wait();
                        }
                        long localStartTime = System.currentTimeMillis();

                        for (int i = 0; i < xidCount; i++) {
                            // journalize COMMITTING record
                            Object logMark = logger.prepare(xid, names);
                            //localXidCount++;

                            // journalize FORGET record
                            logger.commit(xid, logMark);
                            localXidCount++;
                        }
                        localDuration = System.currentTimeMillis() - localStartTime;
                    } catch (Exception e) {
                        //
                        // FIXME: Remove System.err usage
                        //
                        
                        System.err.println(Thread.currentThread().getName());
                        e.printStackTrace(System.err);
                        exception = true;
                    } finally {
                        synchronized (mutex) {
                            totalXidCount += localXidCount;
                            totalDuration += localDuration;
                        }
                        synchronized (stopBarrier) {
                            ++stoppedThreads;
                            stopBarrier.notifyAll();
                        }
                    }

                }
            }
                    .start();
        }

        // Wait for all the workers to be ready..
        long startTime = 0;
        synchronized (startBarrier) {
            while (startedThreads < workers) startBarrier.wait();
            ++startedThreads;
            startBarrier.notifyAll();
            startTime = System.currentTimeMillis();
        }

        // Wait for all the workers to finish.
        synchronized (stopBarrier) {
            while (stoppedThreads < workers) stopBarrier.wait();
        }

        return startTime;

    }

    void printSpeedReport(TransactionLog logger, long startTime, long stopTime, int workers, int xidCount) throws IOException {
        long mc = ((long) xidCount) * workers;
        long duration = (stopTime - startTime);
        long xidsPerSecond = (totalXidCount * 1000 / (duration));
        int averageForceTime = logger.getAverageForceTime();
        int averageBytesPerForce = logger.getAverageBytesPerForce();
        long averageLatency = totalDuration/totalXidCount;
        resultsXML.write("<run><workers>" + workers + "</workers><xids-per-thread>" + xidCount + "</xids-per-thread><expected-total-xids>" + mc + "</expected-total-xids><missing-xids>" + (mc - totalXidCount) + "</missing-xids><totalDuration-milliseconds>" + duration + "</totalDuration-milliseconds><xids-per-second>" + xidsPerSecond + "</xids-per-second></run>\n");
        resultsXML.write(logger.getXMLStats() + "\n");
        resultsCSV.write("" + workers + "," + xidCount + "," + mc + "," + (mc - totalXidCount) + "," + duration + "," + xidsPerSecond + "," + averageForceTime + "," + averageBytesPerForce  + "," + averageLatency + "\n");

    }
}
