/*
 * 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.jdo.tck.api.persistencemanager;

import java.util.Map;
import java.util.Set;
import javax.jdo.JDOUserException;
import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;
import org.apache.jdo.tck.pc.mylib.PCPoint;
import org.apache.jdo.tck.util.BatchTestRunner;
import org.apache.jdo.tck.util.RogueBarrier;
import org.apache.jdo.tck.util.ThreadExceptionHandler;

/**
 * <B>Title:</B> Thread Safe <br>
 * <B>Keywords:</B> multithreaded <br>
 * <B>Assertion ID:</B> A12.4-1. <br>
 * <B>Assertion Description: </B> It is a requirement for all JDO implementations to be thread-safe.
 * That is, the behavior of the implementation must be predictable in the presence of multiple
 * application threads. This assertion will generate multiple test cases to be evaluated.
 */
public class ThreadSafe extends PersistenceManagerTest {

  /** */
  private static final String ASSERTION_FAILED = "Assertion A12.4-1 (ThreadSafe) failed: ";

  /**
   * The <code>main</code> is called when the class is directly executed from the command line.
   *
   * @param args The arguments passed to the program.
   */
  public static void main(String[] args) {
    BatchTestRunner.run(ThreadSafe.class);
  }

  private final int threadCount = 10;
  private final ThreadExceptionHandler group = new ThreadExceptionHandler();
  private final RogueBarrier barrier = new RogueBarrier(threadCount);
  private int successCount = 0;
  private int exceptionCount = 0;

  /** */
  public void testThreadSafe() {
    if (debug) logger.debug("\nSTART testThreadSafe");

    // test thread-safety of PMF.getPersistenceManager():
    //   pmf.getPM(), pm.close()
    final PCPoint[] nullPC = new PCPoint[threadCount];
    runThreads(nullPC, "Concurrent PMF.getPersistenceManager()", threadCount);

    // test thread-safety of PMF.getPersistenceManager():
    //   pmf.getPM(), pm.makePersistent(private transient PC), pm.close()
    final PCPoint[] localPC = new PCPoint[threadCount];
    for (int i = 0; i < threadCount; i++) {
      localPC[i] = new PCPoint(1, i);
    }
    runThreads(
        localPC, "Concurrent PMF.getPersistenceManager()" + ".makePersistent()", threadCount);

    // test thread-safety of PM.makePersistent():
    //   pmf.getPM(), pm.makePersistent(shared transient PC), pm.close()
    final PCPoint[] sharedPC = new PCPoint[threadCount];
    final PCPoint p1 = new PCPoint(3, 3);
    for (int i = 0; i < threadCount; i++) {
      sharedPC[i] = p1;
    }
    runThreads(sharedPC, "Concurrent PM.makePersistent(" + "shared transient PC)", 1);
  }

  /**
   * @param pc objects
   * @param header header
   * @param toSucceed to succeed
   */
  public void runThreads(Object[] pc, String header, int toSucceed) {
    // start threads with their pc instance
    final Thread[] threads = new Thread[threadCount];
    for (int i = 0; i < threadCount; i++) {
      Thread t = new Thread(group, new PMThread(pc[i]));
      t.setName("ThreadSafeID-" + i);
      threads[i] = t;
      t.start();
    }

    // wait for all threads to finish
    for (int i = 0; i < threadCount; i++) {
      while (true) {
        try {
          threads[i].join();
          break;
        } catch (InterruptedException e) { // swallow
        }
      }
    }

    checkResults(header, toSucceed);
  }

  /**
   * @param header header
   * @param toSucceed to succeed
   */
  protected synchronized void checkResults(String header, int toSucceed) {
    // check unhandled exceptions
    final Set<Map.Entry<Thread, Throwable>> uncaught = group.getAllUncaughtExceptions();
    if ((uncaught != null) && !uncaught.isEmpty()) {
      StringBuilder report = new StringBuilder("Uncaught exceptions:\n");
      for (Map.Entry<Thread, Throwable> next : uncaught) {
        Thread thread = next.getKey();
        Throwable problem = next.getValue();
        report.append(header + ": Uncaught exception " + problem + " in thread " + thread + "\n");
      }
      fail(ASSERTION_FAILED, report.toString());
      group.clear();
    }

    // check success count
    if (successCount != toSucceed) {
      fail(
          ASSERTION_FAILED,
          header
              + ": Incorrect number of "
              + "\"succeeding\" threads; expected="
              + toSucceed
              + " found="
              + successCount);
    }
    successCount = 0;

    // check exception count
    final int toExcept = threadCount - toSucceed;
    if (exceptionCount != toExcept) {
      fail(
          ASSERTION_FAILED,
          header
              + ": Incorrect number of "
              + "\"failing\" threads; expected="
              + toExcept
              + " found="
              + exceptionCount);
    }
    exceptionCount = 0;
  }

  /** */
  protected synchronized void markSuccess() {
    logger.debug("[" + Thread.currentThread().getName() + "]: success");
    successCount++;
  }

  /** */
  protected synchronized void markExpectedException() {
    logger.debug("[" + Thread.currentThread().getName() + "]: expected exception");
    exceptionCount++;
  }

  /** */
  class PMThread implements Runnable {
    private final Object pc;

    /** */
    PMThread(Object pc) {
      this.pc = pc;
    }

    /** */
    public void run() {
      ThreadSafe.this.logger.debug("[" + Thread.currentThread().getName() + "]: running");
      final PersistenceManager pm = pmf.getPersistenceManager();
      try {
        Transaction tx = pm.currentTransaction();
        tx.begin();
        if (pc != null) {
          pm.makePersistent(pc);
        }
        tx.commit();
        markSuccess();
      } catch (JDOUserException ex) {
        markExpectedException();
      } finally {
        barrier.await();
        cleanupPM(pm);
      }
    }
  }
}
