/*
 * JBoss, Home of Professional Open Source
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.cache.buddyreplication;

import org.jboss.cache.Fqn;
import org.jboss.cache.util.TestingUtil;
import static org.jboss.cache.util.TestingUtil.dumpCacheContents;
import static org.testng.AssertJUnit.assertTrue;
import org.testng.annotations.Test;

import javax.transaction.TransactionManager;

/**
 * @author <a href="mailto:manik@jboss.org">Manik Surtani (manik@jboss.org)</a>
 */
@Test(groups = {"functional", "jgroups"})
public class BuddyReplicationWithTransactionsTest extends BuddyReplicationTestsBase
{
   private Fqn fqn = Fqn.fromString("test");
   private String key = "key";
   private String value = "value";
   BuddyFqnTransformer fqnTransformer = new BuddyFqnTransformer();

   public void testTransactionsCommit() throws Exception
   {
      caches = createCaches(3, false, true, false);

      caches.get(0).put(fqn, key, value);
      Fqn oldBackupFqn = Fqn.fromString("/" + BuddyManager.BUDDY_BACKUP_SUBTREE + "/" + fqnTransformer.getGroupNameFromAddress(caches.get(0).getLocalAddress()) + "/test");
      Fqn newBackupFqn = Fqn.fromString("/" + BuddyManager.BUDDY_BACKUP_SUBTREE + "/" + fqnTransformer.getGroupNameFromAddress(caches.get(2).getLocalAddress()) + "/test");

      dumpCacheContents(caches);

      TransactionManager txman = caches.get(2).getTransactionManager();


      assertTrue(caches.get(0).exists(fqn));
      assertTrue(!caches.get(1).exists(fqn));
      assertTrue(!caches.get(2).exists(fqn));
      assertTrue(!caches.get(0).exists(oldBackupFqn));
      assertTrue(caches.get(1).exists(oldBackupFqn));
      assertTrue(!caches.get(2).exists(oldBackupFqn));
      assertTrue(!caches.get(0).exists(newBackupFqn));
      assertTrue(!caches.get(1).exists(newBackupFqn));
      assertTrue(!caches.get(2).exists(newBackupFqn));


      txman.begin();

      dumpCacheContents(caches);
      // will cause gravitation
      caches.get(2).get(fqn, key);
      dumpCacheContents(caches);

      assertTrue(caches.get(0).exists(fqn));
      assertTrue(!caches.get(1).exists(fqn));
      assertTrue(caches.get(2).exists(fqn));
      assertTrue(!caches.get(0).exists(oldBackupFqn));
      assertTrue(caches.get(1).exists(oldBackupFqn));
      assertTrue(!caches.get(2).exists(oldBackupFqn));
      assertTrue(!caches.get(0).exists(newBackupFqn));
      assertTrue(!caches.get(1).exists(newBackupFqn));
      assertTrue(!caches.get(2).exists(newBackupFqn));

      txman.commit();
      cleanupDelay(); // cleanup commands are async

      dumpCacheContents(caches);

      assertTrue(!caches.get(0).exists(fqn));
      assertTrue(!caches.get(1).exists(fqn));
      assertTrue(caches.get(2).exists(fqn));
      assertTrue(!caches.get(0).exists(oldBackupFqn));
      assertTrue(!caches.get(1).exists(oldBackupFqn));
      assertTrue(!caches.get(2).exists(oldBackupFqn));
      assertTrue(caches.get(0).exists(newBackupFqn));
      assertTrue(!caches.get(1).exists(newBackupFqn));
      assertTrue(!caches.get(2).exists(newBackupFqn));

      dumpCacheContents(caches);

      assertNoLocks(caches);
   }

   private void cleanupDelay()
   {
      TestingUtil.sleepThread(250);
   }

   public void testTransactionsRollback() throws Exception
   {
      caches = createCaches(3, false, true, false);

      caches.get(0).put(fqn, key, value);
      Fqn oldBackupFqn = Fqn.fromString("/" + BuddyManager.BUDDY_BACKUP_SUBTREE + "/" + fqnTransformer.getGroupNameFromAddress(caches.get(0).getLocalAddress()) + "/test");
      Fqn newBackupFqn = Fqn.fromString("/" + BuddyManager.BUDDY_BACKUP_SUBTREE + "/" + fqnTransformer.getGroupNameFromAddress(caches.get(2).getLocalAddress()) + "/test");

      dumpCacheContents(caches);

      TransactionManager txman = caches.get(2).getTransactionManager();


      assertTrue(caches.get(0).exists(fqn));
      assertTrue(!caches.get(1).exists(fqn));
      assertTrue(!caches.get(2).exists(fqn));
      assertTrue(!caches.get(0).exists(oldBackupFqn));
      assertTrue(caches.get(1).exists(oldBackupFqn));
      assertTrue(!caches.get(2).exists(oldBackupFqn));
      assertTrue(!caches.get(0).exists(newBackupFqn));
      assertTrue(!caches.get(1).exists(newBackupFqn));
      assertTrue(!caches.get(2).exists(newBackupFqn));


      txman.begin();

      dumpCacheContents(caches);
      caches.get(2).get(fqn, key);
      dumpCacheContents(caches);

      assertTrue(caches.get(0).exists(fqn));
      assertTrue(!caches.get(1).exists(fqn));
      assertTrue(caches.get(2).exists(fqn));
      assertTrue(!caches.get(0).exists(oldBackupFqn));
      assertTrue(caches.get(1).exists(oldBackupFqn));
      assertTrue(!caches.get(2).exists(oldBackupFqn));
      assertTrue(!caches.get(0).exists(newBackupFqn));
      assertTrue(!caches.get(1).exists(newBackupFqn));
      assertTrue(!caches.get(2).exists(newBackupFqn));

      txman.rollback();

      dumpCacheContents(caches);

      assertTrue(caches.get(0).exists(fqn));
      assertTrue(!caches.get(1).exists(fqn));
      assertTrue(!caches.get(2).exists(fqn));
      assertTrue(!caches.get(0).exists(oldBackupFqn));
      assertTrue(caches.get(1).exists(oldBackupFqn));
      assertTrue(!caches.get(2).exists(oldBackupFqn));
      assertTrue(!caches.get(0).exists(newBackupFqn));
      assertTrue(!caches.get(1).exists(newBackupFqn));
      assertTrue(!caches.get(2).exists(newBackupFqn));

      assertNoLocks(caches);
   }

}
