/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.tests;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.jboss.cache.TreeCache;
import org.jboss.cache.transaction.DummyTransactionManager;
import org.jgroups.util.Util;

import javax.transaction.NotSupportedException;
import javax.transaction.Transaction;
import javax.transaction.SystemException;
import javax.transaction.RollbackException;
import java.util.Set;

/**
 * Created by IntelliJ IDEA.
 * User: bela
 * Date: Jun 9, 2004
 * Time: 9:05:19 AM
 */
public class TxCacheLoaderTest extends TestCase {
   TreeCache cache1, cache2;

   protected void setUp() throws Exception {
      super.setUp();
      cache1=new TreeCache();
      cache1.setCacheMode("repl_sync");
      cache1.setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup");
      // cache1.setReplQueueInterval(3000);
      cache1.createService();
      cache1.startService();

      cache2=new TreeCache();
      cache2.setCacheMode("repl_sync");
      cache2.setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup");
      cache2.setLockAcquisitionTimeout(2000);
      // cache2.setReplQueueInterval(3000);
      cache2.createService();
      cache2.startService();
   }

   protected void tearDown() throws Exception {
      super.tearDown();
      cache1.stopService();
      cache1.destroyService();
      cache2.stopService();
      cache2.destroyService();
   }





   public void testTxPutCommit() throws Exception, NotSupportedException {
      DummyTransactionManager mgr=DummyTransactionManager.getInstance();
      mgr.begin();
      Transaction tx=mgr.getTransaction();


      cache1.put("/one/two/three", "key1", "val1");
      cache1.put("/one/two/three/four", "key2", "val2");
      assertNull(cache2.get("/one/two/three", "key1"));
      assertNull(cache2.get("/one/two/three/four", "key2"));
      tx.commit();
      assertNotNull(cache1.getKeys("/one/two/three"));
      Set children=cache1.getChildrenNames("/one");
      assertEquals(1, children.size());
      Util.sleep(100);
      assertEquals("val1", cache2.get("/one/two/three", "key1"));
      assertEquals("val2", cache2.get("/one/two/three/four", "key2"));
   }



   public void testTxPrepareAndRollback() throws Exception, NotSupportedException {
      final DummyTransactionManager mgr=DummyTransactionManager.getInstance();
      mgr.begin();
      Transaction tx1=mgr.getTransaction();

      cache1.setLockAcquisitionTimeout(1500);
      cache2.setLockAcquisitionTimeout(1500);


      Thread locker=new Thread() {
         Transaction tx2=null;
         public void run() {
            try {
               mgr.begin();
               tx2=mgr.getTransaction();
               cache2.put("/one/two/three", "block-key1", "block-val1"); // acquires a lock on cache2./one/two/three
               Util.sleep(5000);
            }
            catch(Exception e) {
               e.printStackTrace();
            }
            finally {
               if(tx2 != null) {
                  try {
                     tx2.rollback();
                  }
                  catch(SystemException e) {
                     e.printStackTrace();
                  }
               }
            }
         }
      };

      locker.start();
      Util.sleep(1000);

      cache1.put("/one/two/three", "key1", "val1");
      cache1.put("/one/two/three/four", "key2", "val2");

      try {
         tx1.commit(); // prepare() on cache2 will fail due to lock held by locker thread
         fail("commit() should fail because we cannot acquire the lock on cache2");
      }
      catch(RollbackException rollback) {
         System.out.println("--- TX was rolled back (as expected)");
         assertTrue(true);
      }

      assertNull(cache1.get("/one/two/three", "key1"));
      assertNull(cache1.get("/one/two/three/four", "key1"));

   }


   public void testPutAfterTxCommit() throws Exception, NotSupportedException {
      DummyTransactionManager mgr=DummyTransactionManager.getInstance();
      mgr.begin();
      Transaction tx=mgr.getTransaction();

      cache1.put("/one/two/three", "key1", "val1");
      assertTrue(cache1.exists("/one/two/three"));
      tx.commit();
      assertTrue(cache1.exists("/one/two/three"));
      cache1.put("/a/b/c", null); // should be run outside a TX !
      assertTrue(cache1.exists("/a/b/c"));
   }

   public void testPutAfterTxRollback() throws Exception, NotSupportedException {
      DummyTransactionManager mgr=DummyTransactionManager.getInstance();
      mgr.begin();
      Transaction tx=mgr.getTransaction();

      cache1.put("/one/two/three", "key1", "val1");
      assertTrue(cache1.exists("/one/two/three"));
      tx.rollback();
      assertFalse(cache1.exists("/one/two/three"));
      cache1.put("/a/b/c", null); // should be run outside a TX !
      assertTrue(cache1.exists("/a/b/c"));
   }




   public static Test suite() {
      return new TestSuite(TxCacheLoaderTest.class);
   }

   public static void main(String[] args) {
      junit.textui.TestRunner.run(suite());
   }

}