/* This file is part of VoltDB.
* Copyright (C) 2008-2017 VoltDB Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with VoltDB. If not, see <http://www.gnu.org/licenses/>.
*/
package org.voltdb.messaging;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.voltcore.messaging.TransactionInfoBaseMessage;
import org.voltcore.utils.CoreUtils;
import org.voltdb.iv2.TxnEgo;
public class CompleteTransactionMessage extends TransactionInfoBaseMessage
{
boolean m_isRollback;
boolean m_requiresAck;
boolean m_rollbackForFault;
int m_hash;
int m_flags = 0;
static final int ISROLLBACK = 0;
static final int REQUIRESACK = 1;
static final int ISRESTART = 2;
private void setBit(int position, boolean value)
{
if (value) {
m_flags |= (1 << position);
}
else {
m_flags &= ~(1 << position);
}
}
private boolean getBit(int position)
{
return (((m_flags >> position) & 0x1) == 1);
}
/** Empty constructor for de-serialization */
CompleteTransactionMessage() {
super();
}
/**
* These four args needed for base class
* @param initiatorHSId
* @param coordinatorHSId
* @param txnId
* @param isReadOnly
*
* @param isRollback Should the recipient rollback this transaction to complete it?
* @param requiresAck Does the recipient need to respond to this message
* with a CompleteTransactionResponseMessage?
* @param isRestart Does this CompleteTransactionMessage indicate a restart of this transaction?
*/
public CompleteTransactionMessage(long initiatorHSId, long coordinatorHSId,
long txnId, boolean isReadOnly, int hash,
boolean isRollback, boolean requiresAck,
boolean isRestart, boolean isForReplay)
{
super(initiatorHSId, coordinatorHSId, txnId, 0, isReadOnly, isForReplay);
m_hash = hash;
setBit(ISROLLBACK, isRollback);
setBit(REQUIRESACK, requiresAck);
setBit(ISRESTART, isRestart);
}
public CompleteTransactionMessage(long initiatorHSId, long coordinatorHSId, CompleteTransactionMessage msg)
{
super(initiatorHSId, coordinatorHSId, msg);
m_hash = msg.m_hash;
m_flags = msg.m_flags;
}
public boolean isRollback()
{
return getBit(ISROLLBACK);
}
public boolean requiresAck()
{
return getBit(REQUIRESACK);
}
public boolean isRestart()
{
return getBit(ISRESTART);
}
public int getHash() {
return m_hash;
}
@Override
public int getSerializedSize()
{
int msgsize = super.getSerializedSize();
msgsize += 4 + 4;
return msgsize;
}
@Override
public void flattenToBuffer(ByteBuffer buf) throws IOException
{
buf.put(VoltDbMessageFactory.COMPLETE_TRANSACTION_ID);
super.flattenToBuffer(buf);
buf.putInt(m_hash);
buf.putInt(m_flags);
assert(buf.capacity() == buf.position());
buf.limit(buf.position());
}
@Override
public void initFromBuffer(ByteBuffer buf) throws IOException
{
super.initFromBuffer(buf);
m_hash = buf.getInt();
m_flags = buf.getInt();
assert(buf.capacity() == buf.position());
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("COMPLETE_TRANSACTION (FROM COORD: ");
sb.append(CoreUtils.hsIdToString(m_coordinatorHSId));
sb.append(") FOR TXN ");
sb.append(TxnEgo.txnIdToString(m_txnId));
sb.append("\n SP HANDLE: ");
sb.append(TxnEgo.txnIdToString(getSpHandle()));
sb.append("\n FLAGS: ").append(m_flags);
sb.append("\n HASH: " + String.valueOf(m_hash));
if (isRollback())
sb.append("\n THIS IS AN ROLLBACK REQUEST");
if (requiresAck())
sb.append("\n THIS MESSAGE REQUIRES AN ACK");
if (isRestart()) {
sb.append("\n THIS IS A TRANSACTION RESTART");
}
return sb.toString();
}
}