org.infinispan.transaction.xa.GlobalTransaction Maven / Gradle / Ivy
package org.infinispan.transaction.xa;
import org.infinispan.commons.marshall.AbstractExternalizer;
import org.infinispan.commons.util.Util;
import org.infinispan.marshall.core.Ids;
import org.infinispan.remoting.transport.Address;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
/**
* Uniquely identifies a transaction that spans all JVMs in a cluster. This is used when replicating all modifications
* in a transaction; the PREPARE and COMMIT (or ROLLBACK) messages have to have a unique identifier to associate the
* changes with
. GlobalTransaction should be instantiated thorough {@link TransactionFactory} class,
* as their type depends on the runtime configuration.
*
* @author Bela Ban Apr 12, 2003
* @author Manik Surtani ([email protected])
* @author [email protected]
* @since 4.0
*/
public class GlobalTransaction implements Cloneable {
private static final AtomicLong sid = new AtomicLong(0);
protected long id = -1;
protected Address addr = null;
private int hash_code = -1; // in the worst case, hashCode() returns 0, then increases, so we're safe here
private boolean remote = false;
/**
* empty ctor used by externalization.
*/
protected GlobalTransaction() {
}
protected GlobalTransaction(Address addr, boolean remote) {
this.id = sid.incrementAndGet();
this.addr = addr;
this.remote = remote;
}
public Address getAddress() {
return addr;
}
public long getId() {
return id;
}
public boolean isRemote() {
return remote;
}
public void setRemote(boolean remote) {
this.remote = remote;
}
@Override
public int hashCode() {
if (hash_code == -1) {
hash_code = (addr != null ? addr.hashCode() : 0) + (int) id;
}
return hash_code;
}
@Override
public boolean equals(Object other) {
if (this == other)
return true;
if (!(other instanceof GlobalTransaction))
return false;
GlobalTransaction otherGtx = (GlobalTransaction) other;
boolean aeq = (addr == null) ? (otherGtx.addr == null) : addr.equals(otherGtx.addr);
return aeq && (id == otherGtx.id);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("GlobalTransaction:<").append(addr).append(">:").append(id).append(isRemote() ? ":remote" : ":local");
return sb.toString();
}
/**
* Returns a simplified representation of the transaction.
*/
public final String globalId() {
return getAddress() + ":" + getId();
}
public void setId(long id) {
this.id = id;
}
public void setAddress(Address address) {
this.addr = address;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new IllegalStateException("Impossible!");
}
}
protected abstract static class AbstractGlobalTxExternalizer extends AbstractExternalizer {
@Override
public void writeObject(ObjectOutput output, T gtx) throws IOException {
output.writeLong(gtx.id);
output.writeObject(gtx.addr);
}
/**
* Factory method for GlobalTransactions
* @return a newly constructed instance of GlobalTransaction or one of its subclasses
**/
protected abstract T createGlobalTransaction();
@Override
public T readObject(ObjectInput input) throws IOException, ClassNotFoundException {
T gtx = createGlobalTransaction();
gtx.id = input.readLong();
gtx.addr = (Address) input.readObject();
return gtx;
}
}
public static class Externalizer extends AbstractGlobalTxExternalizer {
@Override
@SuppressWarnings("unchecked")
public Set> getTypeClasses() {
return Util.>asSet(GlobalTransaction.class);
}
@Override
public Integer getId() {
return Ids.GLOBAL_TRANSACTION;
}
@Override
protected GlobalTransaction createGlobalTransaction() {
return TransactionFactory.TxFactoryEnum.NODLD_NORECOVERY_XA.newGlobalTransaction();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy