/*
* Copyright Terracotta, Inc.
*
* 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 org.ehcache.transactions.xa.internal;
import org.ehcache.spi.serialization.Serializer;
import java.io.Serializable;
import java.nio.ByteBuffer;
/**
* {@link SoftLock}s are the value containers stored in the underlying store by the {@link XAStore}.
* A {@link SoftLock} contains three essential things:
* <ul>
* <li>The transaction ID responsible for inserting the {@link SoftLock}, or null if the transaction is terminated.</li>
* <li>The old value, i.e.: the value that is going to be stored upon transaction rollback, or null if there was no value.</li>
* <li>The new value holder, i.e.: the value holder that is going to be stored upon transaction commit, or null if the mapping is to be removed.</li>
* </ul>
*
* @author Ludovic Orban
*/
public class SoftLock<V> implements Serializable {
private final TransactionId transactionId;
private final V oldValue;
private final byte[] oldValueSerialized;
private final XAValueHolder<V> newValueHolder;
public SoftLock(TransactionId transactionId, V oldValue, XAValueHolder<V> newValueHolder) {
this.transactionId = transactionId;
this.oldValue = oldValue;
this.oldValueSerialized = null;
this.newValueHolder = newValueHolder;
}
private SoftLock(TransactionId transactionId, ByteBuffer serializedOldValue, XAValueHolder<V> serializedNewValueHolder) {
this.transactionId = transactionId;
this.oldValue = null;
if (serializedOldValue != null) {
this.oldValueSerialized = new byte[serializedOldValue.remaining()];
serializedOldValue.get(oldValueSerialized);
} else {
oldValueSerialized = null;
}
this.newValueHolder = serializedNewValueHolder;
}
protected SoftLock<V> copyForSerialization(Serializer<V> valueSerializer) {
ByteBuffer serializedOldValue = null;
if (oldValue != null) {
serializedOldValue = valueSerializer.serialize(oldValue);
}
XAValueHolder<V> serializedXaValueHolder = null;
if (newValueHolder != null) {
serializedXaValueHolder = newValueHolder.copyForSerialization(valueSerializer);
}
return new SoftLock<V>(transactionId, serializedOldValue, serializedXaValueHolder);
}
protected SoftLock<V> copyAfterDeserialization(Serializer<V> valueSerializer, SoftLock<V> serializedSoftLock) throws ClassNotFoundException {
V oldValue = null;
if (serializedSoftLock.oldValueSerialized != null) {
oldValue = valueSerializer.read(ByteBuffer.wrap(serializedSoftLock.oldValueSerialized));
}
XAValueHolder<V> newValueHolder = null;
if (this.newValueHolder != null) {
newValueHolder = this.newValueHolder.copyAfterDeserialization(valueSerializer);
}
return new SoftLock<V>(transactionId, oldValue, newValueHolder);
}
public V getOldValue() {
return oldValue;
}
public XAValueHolder<V> getNewValueHolder() {
return newValueHolder;
}
public TransactionId getTransactionId() {
return transactionId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SoftLock<?> softLock = (SoftLock<?>) o;
if (transactionId != null ? !transactionId.equals(softLock.transactionId) : softLock.transactionId != null)
return false;
if (oldValue != null ? !oldValue.equals(softLock.oldValue) : softLock.oldValue != null)
return false;
return !(newValueHolder != null ? !newValueHolder.equals(softLock.newValueHolder) : softLock.newValueHolder != null);
}
@Override
public int hashCode() {
int result = transactionId != null ? transactionId.hashCode() : 0;
result = 31 * result + (oldValue != null ? oldValue.hashCode() : 0);
result = 31 * result + (newValueHolder != null ? newValueHolder.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "SoftLock TxId[" + transactionId + "] Old[" + oldValue + "] New[" + newValueHolder + "]";
}
}