package org.infinispan.transaction.xa; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.Collection; import java.util.Collections; import java.util.Objects; import java.util.Set; import org.infinispan.commons.util.Util; import org.infinispan.marshall.core.Ids; import org.infinispan.remoting.transport.Address; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; /** * This class is used when deadlock detection is enabled. * * @author Mircea.Markus@jboss.com * @deprecated Since 9.0, no longer used. */ @Deprecated public class DldGlobalTransaction extends GlobalTransaction { private static final Log log = LogFactory.getLog(DldGlobalTransaction.class); private static final boolean trace = log.isTraceEnabled(); private volatile long coinToss; private transient volatile Collection<Object> lockIntention = Collections.emptySet(); private volatile Collection<?> remoteLockIntention = Collections.emptySet(); protected volatile Collection<?> locksAtOrigin = Collections.emptySet(); public DldGlobalTransaction() { } public DldGlobalTransaction(Address addr, boolean remote) { super(addr, remote); } /** * Sets the random number that defines the coin toss. A coin toss is a random number that is used when a deadlock is * detected for deciding which transaction should commit and which should rollback. */ public void setCoinToss(long coinToss) { this.coinToss = coinToss; } public long getCoinToss() { return coinToss; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof DldGlobalTransaction)) return false; if (!super.equals(o)) return false; DldGlobalTransaction that = (DldGlobalTransaction) o; if (coinToss != that.coinToss) return false; return true; } @Override public int hashCode() { int result = super.hashCode(); result = 31 * result + (int) (coinToss ^ (coinToss >>> 32)); return result; } @Override public String toString() { return super.toString() + ":dld:" + coinToss; } /** * Returns the key this transaction intends to lock. */ public Collection<Object> getLockIntention() { return lockIntention; } public void setLockIntention(Collection<Object> lockIntention) { Objects.requireNonNull(lockIntention, "Local lock Intention must be non-null."); if (trace) log.tracef("Setting local lock intention to %s", lockIntention); this.lockIntention = lockIntention; } public boolean wouldLose(DldGlobalTransaction other) { return this.coinToss < other.coinToss; } public void setRemoteLockIntention(Collection<?> remoteLockIntention) { Objects.requireNonNull(lockIntention, "Remote lock intention must be non-null."); if (trace) { log.tracef("Setting the remote lock intention: %s", remoteLockIntention); } this.remoteLockIntention = remoteLockIntention; } public Collection<?> getRemoteLockIntention() { return remoteLockIntention; } public boolean hasAnyLockAtOrigin(DldGlobalTransaction otherTx) { if (trace) { log.tracef("Our(%s) locks at origin are: %s. Others remote lock intention is: %s", this, locksAtOrigin, otherTx.getRemoteLockIntention()); } for (Object key : otherTx.getRemoteLockIntention()) { if (this.locksAtOrigin.contains(key)) { return true; } } return false; } public void setLocksHeldAtOrigin(Collection<?> locksAtOrigin) { Objects.requireNonNull(locksAtOrigin, "Locks at origin must be non-null."); if (trace) log.tracef("Setting locks at origin for (%s) to %s", this, locksAtOrigin); this.locksAtOrigin = locksAtOrigin; } public Collection<?> getLocksHeldAtOrigin() { return this.locksAtOrigin; } @Deprecated public static class Externalizer extends GlobalTransaction.AbstractGlobalTxExternalizer<DldGlobalTransaction> { @Override protected DldGlobalTransaction createGlobalTransaction() { return new DldGlobalTransaction(); } @Override public void writeObject(ObjectOutput output, DldGlobalTransaction ddGt) throws IOException { super.writeObject(output, ddGt); output.writeLong(ddGt.getCoinToss()); if (ddGt.locksAtOrigin.isEmpty()) { output.writeObject(null); } else { output.writeObject(ddGt.locksAtOrigin); } } @Override @SuppressWarnings("unchecked") public DldGlobalTransaction readObject(ObjectInput input) throws IOException, ClassNotFoundException { DldGlobalTransaction ddGt = super.readObject(input); ddGt.setCoinToss(input.readLong()); Object locksAtOriginObj = input.readObject(); if (locksAtOriginObj == null) { ddGt.setLocksHeldAtOrigin(Collections.emptySet()); } else { ddGt.setLocksHeldAtOrigin((Set<Object>) locksAtOriginObj); } return ddGt; } @Override public Integer getId() { return Ids.DEADLOCK_DETECTING_GLOBAL_TRANSACTION; } @Override public Set<Class<? extends DldGlobalTransaction>> getTypeClasses() { return Util.<Class<? extends DldGlobalTransaction>>asSet(DldGlobalTransaction.class); } } }