blob: 4c0ffb8c7aa6ec3a314f26f96b781e1ab9753980 [file] [log] [blame]
/*
* Copyright (c) 2014, 2018 Eike Stepper (Loehne, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.emf.cdo.tests;
import org.eclipse.emf.cdo.CDOLock;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.tests.model1.SalesOrder;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.net4j.util.io.IOUtil;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeoutException;
/**
* @author Eike Stepper
*/
public class LockingSequenceTest extends AbstractLockingTest
{
private static final int USERS = 10;
private static final int ALLOCATIONS = 30;
private static final int RETRIES = 5;
@Override
protected void doSetUp() throws Exception
{
disableConsole();
super.doSetUp();
}
@Override
protected void doTearDown() throws Exception
{
disableConsole();
super.doTearDown();
}
public void testSafeCounter() throws Exception
{
disableConsole();
final SalesOrder sequence = getModel1Factory().createSalesOrder();
final CDOSession session = openSession();
CDOTransaction transaction = session.openTransaction();
CDOResource resource = transaction.createResource(getResourcePath("/res1"));
resource.getContents().add(sequence);
transaction.commit();
CountDownLatch latch = new CountDownLatch(USERS);
User[] users = new User[USERS];
for (int userID = 0; userID < USERS; userID++)
{
users[userID] = new User(userID, latch, sequence);
}
for (int userID = 0; userID < USERS; userID++)
{
users[userID].start();
}
await(latch);
IOUtil.OUT().println("FINISHED");
Exception exception = null;
for (int userID = 0; userID < USERS; userID++)
{
Exception ex = users[userID].getException();
if (ex != null)
{
exception = ex;
ex.printStackTrace();
}
}
if (exception != null)
{
throw exception;
}
IOUtil.OUT().println("SUCCESS");
}
/**
* @author Eike Stepper
*/
private static final class User extends Thread
{
private final CountDownLatch latch;
private final CDOTransaction transaction;
private final SalesOrder sequence;
private Exception exception;
public User(int userID, CountDownLatch latch, SalesOrder sequence)
{
super("User" + userID);
this.latch = latch;
transaction = CDOUtil.getCDOObject(sequence).cdoView().getSession().openTransaction();
this.sequence = transaction.getObject(sequence);
}
public Exception getException()
{
return exception;
}
@Override
public void run()
{
try
{
CDOLock lock = CDOUtil.getCDOObject(sequence).cdoWriteLock();
for (int allocation = 0; allocation < ALLOCATIONS; allocation++)
{
for (int retry = 0; retry < RETRIES; retry++)
{
try
{
lock.lock(1000);
break;
}
catch (TimeoutException ex)
{
if (retry == RETRIES)
{
exception = ex;
return;
}
msg("Lock timed out. Trying again...");
}
}
int id = sequence.getId() + 1;
sequence.setId(id);
msg("Allocated " + id);
try
{
transaction.commit();
yield();
}
catch (Exception ex)
{
exception = ex;
return;
}
}
}
finally
{
transaction.close();
latch.countDown();
}
}
private void msg(String string)
{
IOUtil.OUT().println(getName() + ": " + string);
}
}
}