/* 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.dtxn; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.voltcore.messaging.Mailbox; import org.voltcore.messaging.TransactionInfoBaseMessage; import org.voltdb.ClientResponseImpl; import org.voltdb.SiteProcedureConnection; import org.voltdb.StoredProcedureInvocation; import org.voltdb.VoltTable; import org.voltdb.iv2.Site; import org.voltdb.messaging.FragmentTaskMessage; /** * Controls the state of a transaction. Encapsulates from the SimpleDTXNConnection * all the logic about what needs to happen next in a transaction. The DTXNConn just * pumps events into the TransactionState and it takes the appropriate actions, * ultimately it will return true from finished(). * */ public abstract class TransactionState extends OrderableTransaction { protected final boolean m_isReadOnly; protected final TransactionInfoBaseMessage m_notice; protected int m_nextDepId = 1; protected final Mailbox m_mbox; volatile protected boolean m_done = false; protected long m_beginUndoToken; volatile protected boolean m_needsRollback = false; protected ClientResponseImpl m_response = null; protected final boolean m_isForReplay; protected int m_hash = -1; // -1 shows where the value comes from (they only have to match) // IZZY: make me protected/private public final long m_spHandle; private ArrayList<UndoAction> m_undoLog; /** * Set up the final member variables from the parameters. This will * be called exclusively by subclasses. * * @param mbox The mailbox for the site. * @param notice The information about the new transaction. */ protected TransactionState(Mailbox mbox, TransactionInfoBaseMessage notice) { this(mbox, notice, notice.isReadOnly()); } /** * This constructor is only reserved for BorrowTransactionState, which is read only now. * @param mbox * @param notice * @param readOnly */ protected TransactionState(Mailbox mbox, TransactionInfoBaseMessage notice, boolean readOnly) { super(notice.getTxnId(), notice.getUniqueId(), notice.getInitiatorHSId()); m_spHandle = notice.getSpHandle(); m_mbox = mbox; m_notice = notice; m_isReadOnly = readOnly; m_beginUndoToken = Site.kInvalidUndoToken; m_isForReplay = notice.isForReplay(); } final public TransactionInfoBaseMessage getNotice() { return m_notice; } // Assume that done-ness is a latch. public void setDone() { m_done = true; } final public boolean isDone() { return m_done; } public boolean isReadOnly() { return m_isReadOnly; } public boolean isForReplay() { return m_isForReplay; } public int getHash() { return m_hash; } /** * Indicate whether or not the transaction represented by this * TransactionState is single-partition. Should be overridden to provide * sane results by subclasses. */ public abstract boolean isSinglePartition(); public void setHash(Integer hash) { m_hash = hash == null ? 0 : hash; // don't allow null } public void storeResults(ClientResponseImpl response) { m_response = response; } public ClientResponseImpl getResults() { return m_response; } public void setBeginUndoToken(long undoToken) { m_beginUndoToken = undoToken; } public long getBeginUndoToken() { return m_beginUndoToken; } public void setNeedsRollback(boolean rollback) { m_needsRollback = rollback; } public boolean needsRollback() { return m_needsRollback; } public abstract StoredProcedureInvocation getInvocation(); public void createFragmentWork(long[] partitions, FragmentTaskMessage task) { String msg = "The current transaction context of type " + this.getClass().getName(); msg += " doesn't support creating fragment tasks."; throw new UnsupportedOperationException(msg); } public void createAllParticipatingFragmentWork(FragmentTaskMessage task) { String msg = "The current transaction context of type " + this.getClass().getName(); msg += " doesn't support creating fragment tasks."; throw new UnsupportedOperationException(msg); } public void createLocalFragmentWork(FragmentTaskMessage task, boolean nonTransactional) { String msg = "The current transaction context of type " + this.getClass().getName(); msg += " doesn't support accepting fragment tasks."; throw new UnsupportedOperationException(msg); } public void setupProcedureResume(boolean isFinal, int[] dependencies) { String msg = "The current transaction context of type " + this.getClass().getName(); msg += " doesn't support receiving dependencies."; throw new UnsupportedOperationException(msg); } public int getNextDependencyId() { return m_nextDepId++; } /** * IV2 implementation: in iv2, recursable run is a function on the * transaction state; we block in the transaction state recording * until all dependencies / workunits are received. * IV2's SiteProcedureConnection.recursableRun(TransactionState) delegates * to this recursableRun method. * * The IV2 initiator mailbox knows how to offer() incoming fragment * responses to the waiting transaction state. * @return */ public Map<Integer, List<VoltTable>> recursableRun(SiteProcedureConnection siteConnection) { return null; } public void registerUndoAction(UndoAction action) { if (m_undoLog == null) { m_undoLog = new ArrayList<UndoAction>(); } m_undoLog.add(action); } public List<UndoAction> getUndoLog() { return m_undoLog; } }