Package org.jboss.test.cluster.lock

Source Code of org.jboss.test.cluster.lock.ClusteredLockManagerTestBase$RemoteLockCaller

package org.jboss.test.cluster.lock;

import static org.easymock.EasyMock.and;
import static org.easymock.EasyMock.anyLong;
import static org.easymock.EasyMock.aryEq;
import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.isA;
import static org.easymock.EasyMock.makeThreadSafe;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.resetToNice;
import static org.easymock.EasyMock.resetToStrict;
import static org.easymock.EasyMock.same;
import static org.easymock.EasyMock.verify;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import junit.framework.TestCase;

import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.easymock.IArgumentMatcher;
import org.jboss.ha.framework.interfaces.ClusterNode;
import org.jboss.ha.framework.interfaces.HAPartition;
import org.jboss.ha.framework.server.ClusterNodeImpl;
import org.jboss.ha.framework.server.lock.AbstractClusterLockSupport;
import org.jboss.ha.framework.server.lock.LocalLockHandler;
import org.jboss.ha.framework.server.lock.RemoteLockResponse;
import org.jboss.ha.framework.server.lock.AbstractClusterLockSupport.RpcTarget;
import org.jgroups.stack.IpAddress;

public abstract class ClusteredLockManagerTestBase<T extends AbstractClusterLockSupport> extends TestCase
{

   protected ClusterNode node1;
   protected ClusterNode node2;
   protected ClusterNode node3;

   public static Object[] eqLockParams(ClusterNode node, long timeout)
   {
      EasyMock.reportMatcher(new LockParamsMatcher(node, timeout));
      return null;
   }

   protected static class LockParamsMatcher implements IArgumentMatcher
   {
      private final ClusterNode node;
      private final long timeout;
     
      LockParamsMatcher(ClusterNode node, long timeout)
      {
         this.node = node;
         this.timeout = timeout;
      }
     
      public void appendTo(StringBuffer buffer)
      {
         buffer.append("eqRemoteLockParams({\"test\",");
         buffer.append(node);
         buffer.append(',');
         buffer.append(timeout);
         buffer.append("})");        
      }

      public boolean matches(Object arg)
      {
         if (arg instanceof Object[])
         {
            Object[] args = (Object[]) arg;
            if (args.length == 3)
            {
               if ("test".equals(args[0]) && node.equals(args[1])
                     && args[2] instanceof Long)
               {
                  long l = ((Long) args[2]).longValue();
                  return l >= 0 && l <= timeout;
               }
            }
         }
         return false;
      }
     
   }

   public ClusteredLockManagerTestBase()
   {
      super();
   }

   public ClusteredLockManagerTestBase(String name)
   {
      super(name);
   }

   protected void setUp() throws Exception
   {
      super.setUp();
      node1 = new ClusterNodeImpl(new IpAddress("localhost", 1));
      node2 = new ClusterNodeImpl(new IpAddress("localhost", 2));
      node3 = new ClusterNodeImpl(new IpAddress("localhost", 3));
   }

   protected void tearDown() throws Exception
   {
      super.tearDown();
   }

   public void testConstructor() throws Exception
   {
      HAPartition haPartition = createNiceMock(HAPartition.class);     
      LocalLockHandler handler = createNiceMock(LocalLockHandler.class);
     
      try
      {
         createClusteredLockManager(null, haPartition, handler);
         fail("Null serviceHAName should prevent construction");
      }
      catch (IllegalArgumentException good) {}
     
      try
      {
         createClusteredLockManager("test", null, handler);
         fail("Null HAPartition should prevent construction");
      }
      catch (IllegalArgumentException good) {}    
     
      try
      {
         createClusteredLockManager("test", haPartition, null);
         fail("Null LocalLockHandler should prevent construction");
      }
      catch (IllegalArgumentException good) {} 
     
      expect(haPartition.getClusterNode()).andReturn(node1);
      expect(haPartition.getPartitionName()).andReturn("TestPartition");
     
      replay(haPartition);
      replay(handler);
     
      T testee = createClusteredLockManager("test", haPartition, handler);
     
      assertEquals("test", testee.getServiceHAName());
      assertEquals("TestPartition", testee.getPartitionName());
   }

   public void testStart() throws Exception
   {
      HAPartition haPartition = createNiceMock(HAPartition.class);     
      LocalLockHandler handler = createNiceMock(LocalLockHandler.class);      
      expect(haPartition.getClusterNode()).andReturn(node1);
      expect(haPartition.getPartitionName()).andReturn("TestPartition");
     
      replay(haPartition);
      replay(handler);     
     
      T testee = createClusteredLockManager("test", haPartition, handler);
     
      try
      {
         testee.lock("id", 1000);
         fail("Call to lock() should fail if not started");
      }
      catch (IllegalStateException good) {}
     
      try
      {
         testee.unlock("id");
         fail("Call to unlock() should fail if not started");
      }
      catch (IllegalStateException good) {}
     
      reset(haPartition);
     
      assertEquals("Current view is empty when unstarted", 0, testee.getCurrentView().size());
     
      haPartition.registerRPCHandler(eq("test"), isA(RpcTarget.class));
      haPartition.registerMembershipListener(testee);
      expect(haPartition.getClusterNodes()).andReturn(new ClusterNode[]{node1});
      replay(haPartition);
     
      testee.start();
     
      verify(haPartition);
     
      assertEquals("Current view is correct", 1, testee.getCurrentView().size());
      assertTrue(testee.getCurrentView().contains(node1));
     
   }

   public void testStop() throws Exception
   {
      TesteeSet<T> testeeSet = getTesteeSet(node1, 0, 1);
      T testee = testeeSet.impl;
      HAPartition haPartition = testee.getPartition();     
     
      reset(haPartition);
  
      haPartition.unregisterMembershipListener(testee);
      haPartition.unregisterRPCHandler(eq("test"), same(testeeSet.target));
     
      replay(haPartition);
     
      testee.stop();
     
      verify(haPartition);
     
      assertEquals("Current view is empty when stopped", 0, testee.getCurrentView().size());
     
      try
      {
         testee.lock("id", 1000);
         fail("Call to lock() should fail if stopped");
      }
      catch (IllegalStateException good) {}
     
      try
      {
         testee.unlock("id");
         fail("Call to unlock() should fail if stopped");
      }
      catch (IllegalStateException good) {}
     
   }

   public void testGetMembers() throws Exception
   {
      TesteeSet<T> testeeSet = getTesteeSet(node1, 1, 2);
      T testee = testeeSet.impl;
     
      List<ClusterNode> members = testee.getCurrentView();
      assertEquals(2, members.size());
      assertEquals(node1, members.get(1));
     
      ClusterNode dead = members.get(0);
      assertFalse(node1.equals(dead));
     
      Vector<ClusterNode> newView = getView(node1, 0, 3);
      newView.remove(dead);
     
      Vector<ClusterNode> addedMembers = new Vector<ClusterNode>(newView);
      addedMembers.removeAll(members);
     
      Vector<ClusterNode> deadMembers = new Vector<ClusterNode>();
      deadMembers.add(dead);
     
      testee.membershipChanged(deadMembers, addedMembers, newView);
     
      members = testee.getCurrentView();
      assertEquals(2, members.size());
      assertEquals(node1, members.get(0));
      assertFalse(node1.equals(members.get(1)));
      assertFalse(members.contains(dead));
     
   }
  
   /**
    * Simple test of acquiring a cluster-wide lock in a two node cluster
    * where local-only locks are supported.
    *
    * @throws Exception
    */
   public void testBasicClusterLock() throws Exception
   {
      basicClusterLockTest(2);
   }
  
   /**
    * Simple test of acquiring a cluster-wide lock in a cluster where the
    * caller is the only member and where local-only locks are supported.
    *
    * @throws Exception
    */
   public void testStandaloneClusterLock() throws Exception
   {
      basicClusterLockTest(1);
   }

   private void basicClusterLockTest(int viewSize) throws Exception
   {
      int viewPos = viewSize == 1 ? 0 : 1;
      TesteeSet<T> testeeSet = getTesteeSet(node1, viewPos, viewSize);
      AbstractClusterLockSupport testee = testeeSet.impl;
      HAPartition partition = testee.getPartition();
      LocalLockHandler handler = testee.getLocalHandler();
     
      resetToStrict(partition);
      resetToStrict(handler);
     
      ArrayList<RemoteLockResponse> rspList = new ArrayList<RemoteLockResponse>();
      for (int i = 0; i < viewSize - 1; i++)
      {
         rspList.add(new RemoteLockResponse(null, RemoteLockResponse.Flag.OK));
      }
     
      expect(partition.callMethodOnCluster(eq("test"),
                                           eq("remoteLock"),
                                           eqLockParams(node1, 200000),
                                           aryEq(AbstractClusterLockSupport.REMOTE_LOCK_TYPES),
                                           eq(true))).andReturn(rspList);
     
      handler.lockFromCluster(eq("test"), eq(node1), anyLong());
     
      replay(partition);
      replay(handler);
     
      assertTrue(testee.lock("test", 200000));
     
      verify(partition);
      verify(handler);
     
   }
  
   public void testRemoteRejectionFromSuperiorCaller() throws Exception
   {
      TesteeSet<T> testeeSet = getTesteeSet(node1, 1, 3);
      AbstractClusterLockSupport testee = testeeSet.impl;
      HAPartition partition = testee.getPartition();
      LocalLockHandler handler = testee.getLocalHandler();
     
      resetToNice(partition);
      resetToStrict(handler);
     
      ClusterNode superior = testee.getCurrentView().get(0);
     
      ArrayList<RemoteLockResponse> rspList = new ArrayList<RemoteLockResponse>();
      rspList.add(new RemoteLockResponse(null, RemoteLockResponse.Flag.OK));
      rspList.add(new RemoteLockResponse(null, RemoteLockResponse.Flag.REJECT, superior));
     
     
      expect(partition.callMethodOnCluster(eq("test"),
                                           eq("remoteLock"),
                                           eqLockParams(node1, 200000),
                                           aryEq(AbstractClusterLockSupport.REMOTE_LOCK_TYPES),
                                           eq(true))).andReturn(rspList).atLeastOnce();
     
      replay(partition);
      replay(handler);
     
      assertFalse(testee.lock("test", 50));
     
      verify(partition);
      verify(handler);
     
   }
  
   public void testRemoteRejectionFromInferiorCaller() throws Exception
   {
      TesteeSet<T> testeeSet = getTesteeSet(node1, 1, 3);
      AbstractClusterLockSupport testee = testeeSet.impl;
      HAPartition partition = testee.getPartition();
      LocalLockHandler handler = testee.getLocalHandler();
     
      resetToStrict(partition);
      resetToStrict(handler);
     
      ClusterNode inferior = testee.getCurrentView().get(2);
     
      ArrayList<RemoteLockResponse> rspList = new ArrayList<RemoteLockResponse>();
      rspList.add(new RemoteLockResponse(null, RemoteLockResponse.Flag.OK));
      rspList.add(new RemoteLockResponse(null, RemoteLockResponse.Flag.REJECT, inferior));
     
     
      expect(partition.callMethodOnCluster(eq("test"),
                                           eq("remoteLock"),
                                           eqLockParams(node1, 200000),
                                           aryEq(AbstractClusterLockSupport.REMOTE_LOCK_TYPES),
                                           eq(true))).andReturn(rspList);

     
      expect(partition.callMethodOnCluster(eq("test"),
                                           eq("releaseRemoteLock"),
                                           aryEq(new Object[]{"test", node1}),
                                           aryEq(AbstractClusterLockSupport.RELEASE_REMOTE_LOCK_TYPES),
                                           eq(true))).andReturn(rspList);
     
      rspList = new ArrayList<RemoteLockResponse>();
      rspList.add(new RemoteLockResponse(null, RemoteLockResponse.Flag.OK));
      rspList.add(new RemoteLockResponse(null, RemoteLockResponse.Flag.OK));
     
      expect(partition.callMethodOnCluster(eq("test"),
                                           eq("remoteLock"),
                                           eqLockParams(node1, 200000),
                                           aryEq(AbstractClusterLockSupport.REMOTE_LOCK_TYPES),
                                           eq(true))).andReturn(rspList);
     
      handler.lockFromCluster(eq("test"), eq(node1), anyLong());     
      expectLastCall().atLeastOnce();
     
      replay(partition);
      replay(handler);
     
      assertTrue(testee.lock("test", 50));
     
      verify(partition);
      verify(handler);
     
   }
  
   public void testLocalLockingStateRejectsSuperiorRemoteCaller() throws Exception
   {
      TesteeSet<T> testeeSet = getTesteeSet(node1, 1, 3);
      T testee = testeeSet.impl;
      HAPartition partition = testee.getPartition();
      LocalLockHandler handler = testee.getLocalHandler();
      final RpcTarget target = testeeSet.target;
     
      ClusterNode superiorCaller = testee.getCurrentView().get(0);
      assertFalse(node1.equals(superiorCaller));

      resetToStrict(partition);   
      makeThreadSafe(partition, true);
      resetToStrict(handler);  
      makeThreadSafe(handler, true);
     
      ArrayList<RemoteLockResponse> rspList = new ArrayList<RemoteLockResponse>();
      rspList.add(new RemoteLockResponse(null, RemoteLockResponse.Flag.OK));
     
      expect(partition.callMethodOnCluster(eq("test"),
                                           eq("remoteLock"),
                                           eqLockParams(node1, 200000),
                                           aryEq(AbstractClusterLockSupport.REMOTE_LOCK_TYPES),
                                           eq(true))).andReturn(rspList);
     
      // When caller 1 invokes, block before giving response
      CountDownLatch answerAwaitLatch = new CountDownLatch(1);
      CountDownLatch answerStartLatch = new CountDownLatch(1);
      CountDownLatch answerDoneLatch = new CountDownLatch(1);
      BlockingAnswer<Boolean> caller1Answer = new BlockingAnswer<Boolean>(Boolean.TRUE, answerAwaitLatch, answerStartLatch, null);
      handler.lockFromCluster(eq("test"), eq(node1), anyLong());
      expectLastCall().andAnswer(caller1Answer);
     
      replay(partition);
      replay(handler);
     
      LocalLockCaller winner = new LocalLockCaller(testee, null, null, answerDoneLatch, 500);
     
      Thread t1 = new Thread(winner);
      t1.setDaemon(true);
     
      try
      {
         t1.start();        
         assertTrue(answerStartLatch.await(500, TimeUnit.SECONDS));
         // t1 should now be blocking in caller1Answer
        
         RemoteLockResponse rsp = target.remoteLock("test", superiorCaller, 1);
         assertEquals(RemoteLockResponse.Flag.REJECT, rsp.flag);
         assertEquals(node1, rsp.holder);
        
         // release t1
         answerAwaitLatch.countDown();
        
         // wait for t1 to complete
         assertTrue(answerDoneLatch.await(5, TimeUnit.SECONDS));
        
         verify(handler);
        
         rethrow("winner had an exception", winner.getException());
        
         Boolean locked = winner.getResult();        
         assertEquals(Boolean.TRUE, locked);
      }
      finally
      {
         if (t1.isAlive())
            t1.interrupt();
      }
   }
  
   public void testRemoteLockingStateAllowsSuperiorRemoteCaller() throws Exception
   {
      TesteeSet<T> testeeSet = getTesteeSet(node1, 1, 3);
      T testee = testeeSet.impl;
      HAPartition partition = testee.getPartition();
      LocalLockHandler handler = testee.getLocalHandler();
      final RpcTarget target = testeeSet.target;
     
      ClusterNode superiorCaller = testee.getCurrentView().get(0);
      assertFalse(node1.equals(superiorCaller));

      resetToNice(partition);   // nice as we may loop retrying and failing
      makeThreadSafe(partition, true);
      resetToStrict(handler);  
      makeThreadSafe(handler, true);
     
      // When caller 1 invokes, block before giving response
      CountDownLatch answerAwaitLatch = new CountDownLatch(1);
      CountDownLatch answerStartLatch = new CountDownLatch(1);
     
      ArrayList<RemoteLockResponse> rspList = new ArrayList<RemoteLockResponse>();
      rspList.add(new RemoteLockResponse(null, RemoteLockResponse.Flag.OK));
      rspList.add(new RemoteLockResponse(null, RemoteLockResponse.Flag.REJECT, superiorCaller));
     
      BlockingAnswer<ArrayList<RemoteLockResponse>> caller1Answer = new BlockingAnswer<ArrayList<RemoteLockResponse>>(rspList, answerAwaitLatch, answerStartLatch, null);
     
      expect(partition.callMethodOnCluster(eq("test"),
                                           eq("remoteLock"),
                                           eqLockParams(node1, 200000),
                                           aryEq(AbstractClusterLockSupport.REMOTE_LOCK_TYPES),
                                           eq(true))).andAnswer(caller1Answer).atLeastOnce();
     
      handler.lockFromCluster(eq("test"), eq(superiorCaller), anyLong());  
     
      expect(partition.callMethodOnCluster(eq("test"),
            eq("releaseRemoteLock"),
            aryEq(new Object[]{"test", node1}),
            aryEq(AbstractClusterLockSupport.RELEASE_REMOTE_LOCK_TYPES),
            eq(true))).andReturn(new ArrayList<Object>()).atLeastOnce();
         
      replay(partition);
      replay(handler);

      CountDownLatch finishedLatch = new CountDownLatch(1);
      LocalLockCaller loser = new LocalLockCaller(testee, null, null, finishedLatch);
     
      Thread t1 = new Thread(loser);
      t1.setDaemon(true);
     
      try
      {
         t1.start();        
         assertTrue(answerStartLatch.await(1, TimeUnit.SECONDS));
         // t1 should now be blocking in caller1Answer
        
         RemoteLockResponse rsp = target.remoteLock("test", superiorCaller, 1);
         assertEquals(RemoteLockResponse.Flag.OK, rsp.flag);
        
         // release t1
         answerAwaitLatch.countDown();
        
         // wait for t1 to complete
         assertTrue(finishedLatch.await(5, TimeUnit.SECONDS));
        
         verify(handler);
        
         rethrow("winner had an exception", loser.getException());
        
         Boolean locked = loser.getResult();        
         assertEquals(Boolean.FALSE, locked);
      }
      finally
      {
         if (t1.isAlive())
            t1.interrupt();
      }
   }
  
   public void testRemoteLockingStateRejectsInferiorRemoteCaller() throws Exception
   {
      TesteeSet<T> testeeSet = getTesteeSet(node1, 1, 3);
      T testee = testeeSet.impl;
      HAPartition partition = testee.getPartition();
      LocalLockHandler handler = testee.getLocalHandler();
      final RpcTarget target = testeeSet.target;
     
      ClusterNode inferiorNode = testee.getCurrentView().get(2);
      assertFalse(node1.equals(inferiorNode));
     
      ClusterNode superiorNode = testee.getCurrentView().get(0);
      assertFalse(node1.equals(superiorNode));

      resetToStrict(partition);   
      makeThreadSafe(partition, true);
      resetToStrict(handler);  
      makeThreadSafe(handler, true);
     
      // When caller 1 invokes, block before giving response
      CountDownLatch answerAwaitLatch = new CountDownLatch(1);
      CountDownLatch answerStartLatch = new CountDownLatch(1);
     
      ArrayList<RemoteLockResponse> rspList = new ArrayList<RemoteLockResponse>();
      rspList.add(new RemoteLockResponse(superiorNode, RemoteLockResponse.Flag.OK));
      rspList.add(new RemoteLockResponse(inferiorNode, RemoteLockResponse.Flag.REJECT, inferiorNode));
     
      BlockingAnswer<ArrayList<RemoteLockResponse>> caller1Answer =
         new BlockingAnswer<ArrayList<RemoteLockResponse>>(rspList, answerAwaitLatch, answerStartLatch, null);
     
      expect(partition.callMethodOnCluster(eq("test"),
                                           eq("remoteLock"),
                                           eqLockParams(node1, 200000),
                                           aryEq(AbstractClusterLockSupport.REMOTE_LOCK_TYPES),
                                           eq(true))).andAnswer(caller1Answer)
     
      expect(partition.callMethodOnCluster(eq("test"),
            eq("releaseRemoteLock"),
            aryEq(new Object[]{"test", node1}),
            aryEq(AbstractClusterLockSupport.RELEASE_REMOTE_LOCK_TYPES),
            eq(true))).andReturn(new ArrayList<Object>());
     
      rspList = new ArrayList<RemoteLockResponse>();
      rspList.add(new RemoteLockResponse(superiorNode, RemoteLockResponse.Flag.OK));
      rspList.add(new RemoteLockResponse(inferiorNode, RemoteLockResponse.Flag.OK));
     
      expect(partition.callMethodOnCluster(eq("test"),
                                           eq("remoteLock"),
                                           eqLockParams(node1, 200000),
                                           aryEq(AbstractClusterLockSupport.REMOTE_LOCK_TYPES),
                                           eq(true))).andReturn(rspList)
     
      handler.lockFromCluster(eq("test"), eq(node1), anyLong());
     
      replay(partition);
      replay(handler);

      CountDownLatch finishedLatch = new CountDownLatch(1);
      LocalLockCaller winner = new LocalLockCaller(testee, null, null, finishedLatch);
     
      Thread t1 = new Thread(winner);
      t1.setDaemon(true);
     
      try
      {
         t1.start();        
         assertTrue(answerStartLatch.await(1, TimeUnit.SECONDS));
         // t1 should now be blocking in caller1Answer
        
         RemoteLockResponse rsp = target.remoteLock("test", inferiorNode, 1);
         assertEquals(RemoteLockResponse.Flag.REJECT, rsp.flag);
         assertEquals(node1, rsp.holder);
        
         // release t1
         answerAwaitLatch.countDown();
        
         // wait for t1 to complete
         assertTrue(finishedLatch.await(5, TimeUnit.SECONDS));
        
         verify(handler);
        
         rethrow("winner had an exception", winner.getException());
        
         Boolean locked = winner.getResult();        
         assertEquals(Boolean.TRUE, locked);
      }
      finally
      {
         if (t1.isAlive())
            t1.interrupt();
      }
   }
  
   /**
    * Local node acquires a lock; remote node tries to releasem which is ignored.
    *
    * @throws Exception
    */
   public void testSpuriousRemoteLockReleaseIgnored() throws Exception
   {
      TesteeSet<T> testeeSet = getTesteeSet(node1, 1, 2);
      AbstractClusterLockSupport testee = testeeSet.impl;
      HAPartition partition = testee.getPartition();
      LocalLockHandler handler = testee.getLocalHandler();
     
      ClusterNode other = testee.getCurrentView().get(0);
      resetToStrict(partition);
      resetToStrict(handler);
     
      ArrayList<RemoteLockResponse> rspList = new ArrayList<RemoteLockResponse>();
      rspList.add(new RemoteLockResponse(null, RemoteLockResponse.Flag.OK));
     
     
      expect(partition.callMethodOnCluster(eq("test"),
                                           eq("remoteLock"),
                                           eqLockParams(node1, 200000),
                                           aryEq(AbstractClusterLockSupport.REMOTE_LOCK_TYPES),
                                           eq(true))).andReturn(rspList);
     
      handler.lockFromCluster(eq("test"), eq(node1), anyLong());
     
      expect(handler.getLockHolder("test")).andReturn(node1);
     
      replay(partition);
      replay(handler);
     
      assertTrue(testee.lock("test", 200000));
      testeeSet.target.releaseRemoteLock("test", other);
     
      verify(partition);
      verify(handler);
   }

   protected TesteeSet<T> getTesteeSet(ClusterNode node, int viewPos, int viewSize) throws Exception
   {
      HAPartition haPartition = createNiceMock(HAPartition.class);     
      LocalLockHandler handler = createNiceMock(LocalLockHandler.class);      
      expect(haPartition.getClusterNode()).andReturn(node);
      expect(haPartition.getPartitionName()).andReturn("TestPartition");
     
      Capture<RpcTarget>  c = new Capture<RpcTarget>();
      haPartition.registerRPCHandler(eq("test"), and(isA(RpcTarget.class), capture(c)));
      Vector<ClusterNode> view = getView(node, viewPos, viewSize);
      expect(haPartition.getClusterNodes()).andReturn(view.toArray(new ClusterNode[view.size()]));
     
      replay(haPartition);
      replay(handler);     
     
      T testee = createClusteredLockManager("test", haPartition, handler);
     
      testee.start();
     
      reset(haPartition);
      reset(handler);
     
      return new TesteeSet<T>(testee, c.getValue());    
   }
  
   protected abstract T createClusteredLockManager(String serviceHAName, HAPartition partition, LocalLockHandler handler);
  
   private Vector<ClusterNode> getView(ClusterNode member, int viewPos, int numMembers)
   {
      Vector<ClusterNode> all = new Vector<ClusterNode>(Arrays.asList(new ClusterNode[]{node1, node2, node3}));
      all.remove(member);
      while (all.size() > numMembers - 1) // -1 'cause we'll add one in a sec
      {
         all.remove(all.size() - 1);
      }
      all.add(viewPos, member);
     
      return all;
   }
  
   protected static void rethrow(String msg, Throwable t) throws Exception
   {
      if (t != null)
      {  
         if (t instanceof AssertionError)
         {
            AssertionError rethrow = new AssertionError(msg);
            rethrow.initCause(t);
            throw rethrow;
         }
        
         throw new RuntimeException(msg, t);
      }
   }
  
   protected class TesteeSet<C extends AbstractClusterLockSupport>
   {
      public final C impl;
      public final RpcTarget target;
     
      TesteeSet(C impl, RpcTarget target)
      {
         this.impl = impl;
         this.target = target;
      }
   }
  
   /**
    * Allows EasyMock to block before returning.
    *
    * @author Brian Stansberry
    *
    * @param <T>
    */
   protected class BlockingAnswer<C>  implements IAnswer<C>
   {
      private final C answer;
      private final Exception toThrow;
      private final CountDownLatch startLatch;
      private final CountDownLatch awaitlatch;
      private final CountDownLatch endLatch;
      private final long timeout;
     
      public BlockingAnswer(C answer, CountDownLatch awaitLatch, CountDownLatch startLatch, CountDownLatch endLatch)
      {
         this(answer, awaitLatch, 0, startLatch, endLatch);
      }
     
      public BlockingAnswer(C answer, CountDownLatch awaitLatch, long timeout, CountDownLatch startLatch, CountDownLatch endLatch)
      {
         this.awaitlatch = awaitLatch;
         this.startLatch = startLatch;
         this.endLatch = endLatch;
         this.timeout = timeout;
         this.answer = answer;
         this.toThrow = null;
      }
     
      public BlockingAnswer(Exception toThrow, CountDownLatch awaitLatch, long timeout, CountDownLatch startLatch, CountDownLatch endLatch)
      {
         this.awaitlatch = awaitLatch;
         this.startLatch = startLatch;
         this.endLatch = endLatch;
         this.timeout = timeout;
         this.answer = null;
         this.toThrow = toThrow;
      }
     
      public C answer() throws Throwable
      {
         if (startLatch != null)
         {
            startLatch.countDown();
         }
        
         try
         {
            if (timeout > 0)
            {
               awaitlatch.await(timeout, TimeUnit.MILLISECONDS);
            }
            else
            {
               awaitlatch.await();
            }
           
            if (toThrow != null)
            {
               throw toThrow;
            }
           
            return answer;
         }
         finally
         {
            if (endLatch != null)
            {
               endLatch.countDown();
            }
         }
      }     
   }
  
   protected abstract class AbstractCaller<C> implements Runnable
   {
      private final CountDownLatch startLatch;
      private final CountDownLatch proceedLatch;
      private final CountDownLatch finishLatch;
      private C result;
      private Throwable exception;
     
      AbstractCaller(CountDownLatch startLatch,
            CountDownLatch proceedLatch, CountDownLatch finishLatch)
      {
         this.startLatch = startLatch;
         this.proceedLatch = proceedLatch;
         this.finishLatch = finishLatch;
      }
     
      public void run()
      {        
         try
         {
            if (startLatch != null)
            {
               startLatch.countDown();
            }
           
            if (proceedLatch != null)
            {
               proceedLatch.await();
            }
           
            result = execute();
         }
         catch (Throwable t)
         {
            exception = t;
         }
         finally
         {           
            if (finishLatch != null)
            {
               finishLatch.countDown();
            }
           
         }
      }
     
      protected abstract C execute();

      public C getResult()
      {
         return result;
      }

      public Throwable getException()
      {
         return exception;
      }     
     
   }
  
   protected class RemoteLockCaller extends AbstractCaller<RemoteLockResponse>
   {
      private final RpcTarget target;
      private final ClusterNode caller;
     
      public RemoteLockCaller(RpcTarget target, ClusterNode caller, CountDownLatch startLatch,
            CountDownLatch proceedLatch, CountDownLatch finishLatch)
      {
         super(startLatch, proceedLatch, finishLatch);
         this.target = target;
         this.caller = caller;
      }
     
      protected RemoteLockResponse execute()
      {        
         return target.remoteLock("test", caller, 1000);
      }
   }
  
   protected class LocalLockCaller extends AbstractCaller<Boolean>
   {
      private final AbstractClusterLockSupport target;
      private final long timeout;
     
      public LocalLockCaller(AbstractClusterLockSupport target, CountDownLatch startLatch,
            CountDownLatch proceedLatch, CountDownLatch finishLatch)
      {
         this(target, startLatch, proceedLatch, finishLatch, 3000);
      }
     
      public LocalLockCaller(AbstractClusterLockSupport target, CountDownLatch startLatch,
            CountDownLatch proceedLatch, CountDownLatch finishLatch, long timeout)
      {
         super(startLatch, proceedLatch, finishLatch);
         this.target = target;
         this.timeout = timeout;
      }
     
      protected Boolean execute()
      {        
         return Boolean.valueOf(target.lock("test", timeout));
      }
   }

}
TOP

Related Classes of org.jboss.test.cluster.lock.ClusteredLockManagerTestBase$RemoteLockCaller

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.