![JAR search and dependency download from the Maven repository](/logo.png)
com.gs.fw.common.mithra.transaction.FutureXaResource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of reladomo Show documentation
Show all versions of reladomo Show documentation
Reladomo is an object-relational mapping framework.
/*
Copyright 2018 Goldman Sachs.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package com.gs.fw.common.mithra.transaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.util.concurrent.*;
public class FutureXaResource
{
private static Logger logger = LoggerFactory.getLogger(FutureXaResource.class.getName());
private final MultiThreadedTm multiThreadedTm;
private final XAResource xaResource;
private final ResourceThread resourceThread;
public FutureXaResource(MultiThreadedTm multiThreadedTm, XAResource xaResource, String name)
{
this.multiThreadedTm = multiThreadedTm;
this.xaResource = xaResource;
this.resourceThread = new ResourceThread(name);
this.resourceThread.start();
}
public XAResource getDelegated()
{
return this.xaResource;
}
public Future executeOnResourceThread(Callable callable)
{
checkLiveness();
return this.resourceThread.scheduleTask(callable);
}
private void checkLiveness()
{
if (!this.resourceThread.isAlive())
{
throw new RuntimeException("Resource thread is no longer running");
}
}
public Future commit(final Xid xid, final boolean b) throws XAException
{
Callable callable = new Callable()
{
@Override
public Void call() throws Exception
{
try
{
xaResource.commit(xid, b);
}
finally
{
multiThreadedTm.disassociateTransactionWithThread();
}
return null;
}
};
return this.resourceThread.scheduleTask(callable);
}
public Future setTransactionTimeout(final int i) throws XAException
{
Callable callable = new Callable()
{
@Override
public Boolean call() throws Exception
{
return xaResource.setTransactionTimeout(i);
}
};
return this.resourceThread.scheduleTask(callable);
}
public Future forget(final Xid xid) throws XAException
{
Callable callable = new Callable()
{
@Override
public Void call() throws Exception
{
try
{
xaResource.forget(xid);
}
finally
{
multiThreadedTm.disassociateTransactionWithThread();
}
return null;
}
};
return this.resourceThread.scheduleTask(callable);
}
public Future prepare(final Xid xid) throws XAException
{
Callable callable = new Callable()
{
@Override
public Integer call() throws Exception
{
int prepare = xaResource.prepare(xid);
return prepare;
}
};
return this.resourceThread.scheduleTask(callable);
}
public Future start(final Xid xid, final int i, final Future parentToWaitFor) throws XAException
{
final MultiThreadedTx localTransaction = multiThreadedTm.getLocalTransaction();
Callable callable = new Callable()
{
@Override
public Boolean call() throws Exception
{
parentToWaitFor.get();
multiThreadedTm.associateTransactionWithThread(localTransaction);
xaResource.start(xid, i);
return true;
}
};
return this.resourceThread.scheduleTask(callable);
}
public Future end(final Xid xid, final int i) throws XAException
{
Callable callable = new Callable()
{
@Override
public Boolean call() throws Exception
{
xaResource.end(xid, i);
return true;
}
};
return this.resourceThread.scheduleTask(callable);
}
public Future rollback(final Xid xid) throws XAException
{
Callable callable = new Callable()
{
@Override
public Void call() throws Exception
{
try
{
xaResource.rollback(xid);
}
finally
{
multiThreadedTm.disassociateTransactionWithThread();
}
return null;
}
};
return this.resourceThread.scheduleTask(callable);
}
public Future getTransactionTimeout() throws XAException
{
Callable callable = new Callable()
{
@Override
public Integer call() throws Exception
{
return xaResource.getTransactionTimeout();
}
};
return this.resourceThread.scheduleTask(callable);
}
public Future recover(final int i) throws XAException
{
Callable callable = new Callable()
{
@Override
public Xid[] call() throws Exception
{
return xaResource.recover(i);
}
};
return this.resourceThread.scheduleTask(callable);
}
public void shutdown()
{
if (!resourceThread.isAlive())
{
return;
}
Callable callable = new Callable()
{
@Override
public Void call() throws Exception
{
resourceThread.shutdown();
return null;
}
};
try
{
this.resourceThread.scheduleTask(callable).get();
}
catch (InterruptedException e)
{
//ignore
}
catch (ExecutionException e)
{
logger.error("Could not shutdown resource thread", e);
}
try
{
this.resourceThread.join();
}
catch (InterruptedException e)
{
//ignore
}
}
private static class ResourceThread extends Thread
{
private LinkedBlockingQueue todo = new LinkedBlockingQueue();
private boolean shutdown = false;
private ResourceThread(String name)
{
super(name);
}
@Override
public void run()
{
while(!shutdown)
{
FutureTask futureTask = null;
try
{
futureTask = todo.take();
futureTask.run();
}
catch (InterruptedException e)
{
//ignore
}
}
}
public Future scheduleTask(Callable callable)
{
FutureTask task = new FutureTaskOnThread(callable, this);
try
{
this.todo.put(task);
}
catch (InterruptedException e)
{
throw new RuntimeException("must not happen!", e);
}
return task;
}
public void shutdown()
{
shutdown = true;
}
}
private static class FutureTaskOnThread extends FutureTask
{
private final Thread executionThread;
private FutureTaskOnThread(Callable callable, Thread executionThread)
{
super(callable);
this.executionThread = executionThread;
}
@Override
public V get() throws InterruptedException, ExecutionException
{
if (Thread.currentThread() == this.executionThread)
{
this.run();
}
return super.get();
}
@Override
public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
{
if (Thread.currentThread() == this.executionThread)
{
this.run();
}
return super.get(timeout, unit);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy