mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Fixed JobLockService refresh callback code
- Fallout from ALF-4898 - Unit tests perform and check callback counts git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@22966 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -228,7 +228,7 @@ public interface JobLockService
|
|||||||
* to terminate.
|
* to terminate.
|
||||||
* <p/>
|
* <p/>
|
||||||
* This method is also called if the initiating process is self-terminated i.e. if the originating
|
* This method is also called if the initiating process is self-terminated i.e. if the originating
|
||||||
* process releases the lock itself. This method is not called if the process is not
|
* process releases the lock itself. This method is <b>not</b> called if the process is not
|
||||||
* {@link #isActive() active}.
|
* {@link #isActive() active}.
|
||||||
*
|
*
|
||||||
* @since 3.4.0b
|
* @since 3.4.0b
|
||||||
|
@@ -287,7 +287,7 @@ public class JobLockServiceImpl implements JobLockService
|
|||||||
// First check the VM
|
// First check the VM
|
||||||
if (shutdownListener.isVmShuttingDown())
|
if (shutdownListener.isVmShuttingDown())
|
||||||
{
|
{
|
||||||
callback.lockReleased();
|
callLockReleased(callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean isActive = false;
|
boolean isActive = false;
|
||||||
@@ -324,13 +324,13 @@ public class JobLockServiceImpl implements JobLockService
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
releaseLock(lockToken, lockQName);
|
releaseLock(lockToken, lockQName);
|
||||||
|
// The callback must be informed as we released the lock automatically
|
||||||
|
callLockReleased(callback);
|
||||||
}
|
}
|
||||||
catch (LockAcquisitionException e)
|
catch (LockAcquisitionException e)
|
||||||
{
|
{
|
||||||
// The lock is already gone: job done
|
// The lock is already gone: job done
|
||||||
}
|
}
|
||||||
// The callback must be informed
|
|
||||||
callLockReleased(callback);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -338,6 +338,8 @@ public class JobLockServiceImpl implements JobLockService
|
|||||||
{
|
{
|
||||||
refreshLock(lockToken, lockQName, timeToLive);
|
refreshLock(lockToken, lockQName, timeToLive);
|
||||||
// Success. The callback does not need to know.
|
// Success. The callback does not need to know.
|
||||||
|
// NB: Reschedule this task
|
||||||
|
scheduler.schedule(this, delay, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
catch (LockAcquisitionException e)
|
catch (LockAcquisitionException e)
|
||||||
{
|
{
|
||||||
|
@@ -305,20 +305,22 @@ public class JobLockServiceTest extends TestCase
|
|||||||
final long lockTTL = 1000L;
|
final long lockTTL = 1000L;
|
||||||
final String lockToken = jobLockService.getLock(lockQName, lockTTL);
|
final String lockToken = jobLockService.getLock(lockQName, lockTTL);
|
||||||
|
|
||||||
final boolean[] released = new boolean[1];
|
final int[] checked = new int[1];
|
||||||
|
final int[] released = new int[1];
|
||||||
// Immediately-inactive job
|
// Immediately-inactive job
|
||||||
JobLockRefreshCallback callback = new JobLockRefreshCallback()
|
JobLockRefreshCallback callback = new JobLockRefreshCallback()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive()
|
public boolean isActive()
|
||||||
{
|
{
|
||||||
|
checked[0]++;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void lockReleased()
|
public void lockReleased()
|
||||||
{
|
{
|
||||||
released[0] = true;
|
released[0]++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -326,7 +328,7 @@ public class JobLockServiceTest extends TestCase
|
|||||||
// The first refresh will occur in 500ms
|
// The first refresh will occur in 500ms
|
||||||
wait(1000L);
|
wait(1000L);
|
||||||
// Should have been released by now
|
// Should have been released by now
|
||||||
assertTrue("Expected lockReleased to have been called", released[0]);
|
assertTrue("Expected lockReleased to have been called", released[0] > 0);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
jobLockService.getLock(lockQName, lockTTL);
|
jobLockService.getLock(lockQName, lockTTL);
|
||||||
@@ -335,6 +337,13 @@ public class JobLockServiceTest extends TestCase
|
|||||||
{
|
{
|
||||||
fail("Lock should have been released by callback infrastructure");
|
fail("Lock should have been released by callback infrastructure");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that the timed callback is killed properly
|
||||||
|
int checkedCount = checked[0];
|
||||||
|
int releasedCount = released[0];
|
||||||
|
wait(2000L);
|
||||||
|
assertEquals("Lock callback timer was not terminated", checkedCount, checked[0]);
|
||||||
|
assertEquals("Lock callback timer was not terminated", releasedCount, released[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void testLockCallbackReleaseSelf() throws Exception
|
public synchronized void testLockCallbackReleaseSelf() throws Exception
|
||||||
@@ -343,13 +352,15 @@ public class JobLockServiceTest extends TestCase
|
|||||||
final long lockTTL = 1000L;
|
final long lockTTL = 1000L;
|
||||||
final String lockToken = jobLockService.getLock(lockQName, lockTTL);
|
final String lockToken = jobLockService.getLock(lockQName, lockTTL);
|
||||||
|
|
||||||
final boolean[] released = new boolean[1];
|
final int[] checked = new int[1];
|
||||||
|
final int[] released = new int[1];
|
||||||
// Immediately-inactive job, releasing the lock
|
// Immediately-inactive job, releasing the lock
|
||||||
JobLockRefreshCallback callback = new JobLockRefreshCallback()
|
JobLockRefreshCallback callback = new JobLockRefreshCallback()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive()
|
public boolean isActive()
|
||||||
{
|
{
|
||||||
|
checked[0]++;
|
||||||
jobLockService.releaseLock(lockToken, lockQName);
|
jobLockService.releaseLock(lockToken, lockQName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -357,15 +368,15 @@ public class JobLockServiceTest extends TestCase
|
|||||||
@Override
|
@Override
|
||||||
public void lockReleased()
|
public void lockReleased()
|
||||||
{
|
{
|
||||||
released[0] = true;
|
released[0]++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
jobLockService.refreshLock(lockToken, lockQName, lockTTL, callback);
|
jobLockService.refreshLock(lockToken, lockQName, lockTTL, callback);
|
||||||
// The first refresh will occur in 500ms
|
// The first refresh will occur in 500ms
|
||||||
wait(1000L);
|
wait(1000L);
|
||||||
// Should have been released by now
|
// Should NOT get a callback saying that the lock has been released
|
||||||
assertTrue("Expected lockReleased to have been called", released[0]);
|
assertFalse("DID NOT expect lockReleased to have been called", released[0] > 0);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
jobLockService.getLock(lockQName, lockTTL);
|
jobLockService.getLock(lockQName, lockTTL);
|
||||||
@@ -374,39 +385,57 @@ public class JobLockServiceTest extends TestCase
|
|||||||
{
|
{
|
||||||
fail("Lock should have been released by callback infrastructure");
|
fail("Lock should have been released by callback infrastructure");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that the timed callback is killed properly
|
||||||
|
int checkedCount = checked[0];
|
||||||
|
int releasedCount = released[0];
|
||||||
|
wait(2000L);
|
||||||
|
assertEquals("Lock callback timer was not terminated", checkedCount, checked[0]);
|
||||||
|
assertEquals("Lock callback timer was not terminated", releasedCount, released[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lets job "run" for 3 seconds and checks at 2s and 4s.
|
||||||
|
*/
|
||||||
public synchronized void testLockCallbackReleaseTimed() throws Exception
|
public synchronized void testLockCallbackReleaseTimed() throws Exception
|
||||||
{
|
{
|
||||||
final QName lockQName = QName.createQName(NAMESPACE, getName());
|
final QName lockQName = QName.createQName(NAMESPACE, getName());
|
||||||
final long lockTTL = 1000L;
|
final long lockTTL = 1000L;
|
||||||
|
final long lockNow = System.currentTimeMillis();
|
||||||
final String lockToken = jobLockService.getLock(lockQName, lockTTL);
|
final String lockToken = jobLockService.getLock(lockQName, lockTTL);
|
||||||
|
|
||||||
final boolean[] checked = new boolean[1];
|
final int[] checked = new int[1];
|
||||||
final boolean[] released = new boolean[1];
|
final int[] released = new int[1];
|
||||||
// Do not release and remain active
|
// Do not release and remain active
|
||||||
JobLockRefreshCallback callback = new JobLockRefreshCallback()
|
JobLockRefreshCallback callback = new JobLockRefreshCallback()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive()
|
public boolean isActive()
|
||||||
{
|
{
|
||||||
checked[0] = true;
|
checked[0]++;
|
||||||
|
if (System.currentTimeMillis() - lockNow > 3000L)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void lockReleased()
|
public void lockReleased()
|
||||||
{
|
{
|
||||||
released[0] = true;
|
released[0]++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
jobLockService.refreshLock(lockToken, lockQName, lockTTL, callback);
|
jobLockService.refreshLock(lockToken, lockQName, lockTTL, callback);
|
||||||
// The first refresh will occur in 500ms
|
// The first refresh will occur in 500ms
|
||||||
wait(1000L);
|
wait(2000L);
|
||||||
|
|
||||||
assertTrue("Active check has not occured", checked[0]);
|
assertTrue("Expected at least 2 active checks; only got " + checked[0], checked[0] >= 2);
|
||||||
assertFalse("lockReleased should NOT have been called", released[0]);
|
assertFalse("lockReleased should NOT have been called", released[0] > 0);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
jobLockService.getLock(lockQName, lockTTL);
|
jobLockService.getLock(lockQName, lockTTL);
|
||||||
@@ -416,5 +445,15 @@ public class JobLockServiceTest extends TestCase
|
|||||||
{
|
{
|
||||||
// Expected
|
// Expected
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait for another 2s to be sure that the lock is run to completion
|
||||||
|
wait(2000L);
|
||||||
|
|
||||||
|
// Check that the timed callback is killed properly
|
||||||
|
int checkedCount = checked[0];
|
||||||
|
int releasedCount = released[0];
|
||||||
|
wait(2000L);
|
||||||
|
assertEquals("Lock callback timer was not terminated", checkedCount, checked[0]);
|
||||||
|
assertEquals("Lock callback timer was not terminated", releasedCount, released[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user