/*
 * 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.lifecycle;

import java.util.Map;
import java.util.Set;
import javax.jdo.Extent;
import javax.jdo.JDOException;
import javax.jdo.JDOFatalException;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Transaction;
import junit.framework.AssertionFailedError;
import org.apache.jdo.tck.JDO_Test;
import org.apache.jdo.tck.pc.lifecycle.StateTransitionObj;
import org.apache.jdo.tck.util.BatchTestRunner;
import org.apache.jdo.tck.util.ThreadExceptionHandler;

/**
 * <B>Title:</B> Test PM ability to share PC classes but not PC instances <br>
 * <B>Keywords:</B> PM share PC class <br>
 * <B>Assertion IDs:</B> A5.2-1,A5.2-2,A5.2-3 <br>
 * <B>Assertion Description: </B> Several JDO PersistenceManagers might be coresident and might
 * share the same persistence capable classes] (although a JDO instance can be associated with only
 * one PersistenceManager at a time)
 */
public class PMsCanSharePCClassesButNotPCInstances extends JDO_Test {

  /** */
  private static final String ASSERTION_FAILED =
      "Assertions A5.2-1,A5.2-2,A5.2-3 (PMsCanSharePCClassesButNotPCInstances) failed: ";

  /** The number of active threads. Each thread has its own PM. */
  private int threads = 0;

  /** The total number of attempts to insert PC instances */
  private int attempts = 0;

  /** The number of inserters. Each inserter runs in its own thread. */
  private final int inserters = 5;

  /** The number of objects inserted. */
  protected int insertedCount = 0;

  /** The number of objects that is expected to have been inserted. */
  protected int insertedCountExpected = 0;

  /**
   * 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(PMsCanSharePCClassesButNotPCInstances.class);
  }

  /**
   * @see org.apache.jdo.tck.JDO_Test#localSetUp()
   */
  @Override
  protected void localSetUp() {
    addTearDownClass(StateTransitionObj.class);
  }

  public void testSharedPC() {
    // test shared PC - only one PM should succeed to insert the shared PC
    threads = 0;
    attempts = 0;
    insertedCount = 0;
    insertedCountExpected = 1;
    insertObjects(true);
  }

  public void testNonSharedPC() {
    // test non-shared PCs - each PM should succeed to insert its own non-shared PC
    threads = 0;
    attempts = 0;
    // insertedCount = 0; //Don't reset this value since we have not deleted the inserted object
    // from the shared PC test above
    insertedCountExpected += inserters;
    insertObjects(false);
  }

  protected void insertObjects(boolean sharedPC) {
    Object pc = null;

    ThreadExceptionHandler threadGroup = new ThreadExceptionHandler();
    for (int i = 0; i < inserters; i++) {
      if (sharedPC) { // each thread shares one PC
        if (pc == null) pc = new StateTransitionObj(i);
      } else { // each thread has its own PC
        pc = new StateTransitionObj(i);
      }
      threads++;
      Thread t = new Thread(threadGroup, new Inserter(pmf, pc, sharedPC));
      t.setName("Inserter-" + i);
      t.start();
    }

    Thread.yield();

    while (!attemptsComplete()) {
      try {
        Thread.sleep(100);
      } catch (InterruptedException ex) {
        logger.debug("interrupted while waiting for threads to insert");
      }
    }

    while (threads > 0) {
      try {
        Thread.sleep(100);
      } catch (InterruptedException ex) {
        logger.debug("interrupted while waiting for threads to finish");
      }
    }

    Set<Map.Entry<Thread, Throwable>> exceptions = threadGroup.getAllUncaughtExceptions();
    for (Map.Entry<Thread, Throwable> entry : exceptions) {
      Thread thread = entry.getKey();
      Throwable throwable = entry.getValue();
      String message = "Uncaught exception " + throwable + " in thread " + thread;
      if (throwable instanceof AssertionFailedError) fail(ASSERTION_FAILED, message);
      else throw new JDOFatalException(message, throwable);
    }
  }

  synchronized void signal() {
    threads--;
  }

  protected synchronized void incrAttempts() {
    attempts++;
  }

  protected synchronized boolean attemptsComplete() {
    return attempts == inserters;
  }

  class Inserter implements Runnable {
    private final PersistenceManager pm;
    private final Object pc;
    private final Class<?> instanceClass;
    private final boolean sharedPC;

    Inserter(PersistenceManagerFactory pmf, Object pc, boolean sharedPC) {
      this.pm = pmf.getPersistenceManager();
      this.pc = pc;
      this.instanceClass = pc.getClass();
      this.sharedPC = sharedPC;
    }

    protected synchronized void announce(String msg, Object pc) {
      insertedCount++;
      Object oid = JDOHelper.getObjectId(pc);
      if (debug) logger.debug(msg + this.getClass().getName() + ": " + oid + ", " + pc);
    }

    public void run() {
      Transaction tx = null;
      try {
        if (debug) logger.debug("running");
        tx = pm.currentTransaction();
        tx.begin();
        try {
          pm.makePersistent(pc);
          announce("inserted ", pc);
          tx.commit();
        } catch (JDOException ex) {
          if (!sharedPC) // we expect an exception for all but one of the inserters in the case of a
            // shared PC
            throw ex;
        } finally {
          incrAttempts();
          if (tx != null && tx.isActive()) tx.rollback();
        }

        while (!attemptsComplete()) {
          try {
            Thread.sleep(100);
          } catch (InterruptedException ex) {
            if (debug) logger.debug(" interrupted");
          }
        }

        // Verify that the number of inserted objects matches the expected number
        if (insertedCount != insertedCountExpected) {
          fail(
              ASSERTION_FAILED,
              "Wrong number of objects in extent. Inserted="
                  + insertedCount
                  + " Expected="
                  + insertedCountExpected);
        }

        if (debug) logger.debug("getting Extent");
        int objCount = 0;
        if (debug) logger.debug("getting Extent of " + instanceClass.getName());
        tx.begin();
        Extent<?> e = pm.getExtent(instanceClass, false);
        for (Object instance : e) {
          objCount++;
        }
        tx.commit();

        // Verify that the number of inserted objects matches the number of objects in the extent
        if (insertedCount != objCount) {
          fail(
              ASSERTION_FAILED,
              "Wrong number of objects in extent. Inserted="
                  + insertedCount
                  + " Found="
                  + objCount);
        }
      } finally {
        if (tx != null && tx.isActive()) tx.rollback();
        if (pm != null && !pm.isClosed()) pm.close();
        PMsCanSharePCClassesButNotPCInstances.this.signal();
      }
    }

    public String toString() {
      String rc = "Inserter ";
      if (debug) {
        rc += Thread.currentThread().toString();
      }
      return rc;
    }
  }
}
