/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.foundationdb.server.service.transaction;
import com.foundationdb.ais.model.ForeignKey;
import com.foundationdb.server.service.Service;
import com.foundationdb.server.service.session.Session;
import com.foundationdb.sql.parser.IsolationLevel;
import java.util.concurrent.Callable;
public interface TransactionService extends Service {
interface Callback {
void run(Session session, long timestamp);
}
interface CloseableTransaction extends AutoCloseable {
void commit();
void rollback();
@Override
void close();
}
enum CallbackType {
/** Invoked <i>before</i> attempting to commit. */
PRE_COMMIT,
/** Invoked <i>after</i> commit completes successfully. */
COMMIT,
/** Invoked <i>after</i> a commit fails or rollback is manually invoked. */
ROLLBACK,
/** Invoked <i>after</i> a transaction ends, either by commit or rollback. */
END
}
/** Returns true if there is a transaction active for the given Session */
boolean isTransactionActive(Session session);
/** Returns true if there is a transaction active for the given Session */
boolean isRollbackPending(Session session);
/** Returns the start timestamp for the open transaction. */
long getTransactionStartTimestamp(Session session);
/** Begin a new transaction. */
void beginTransaction(Session session);
/** Begin a new transaction that will rollback upon close if not committed. */
CloseableTransaction beginCloseableTransaction(Session session);
/** Commit the open transaction. */
void commitTransaction(Session session);
/**
* Commit the transaction and reset for immediate use if a retryable exception occurs.
*
* <p>
* If the commit was successful <i>or</i> a non-retryable exception occurred, the
* session's transaction state is cleared and {@link #beginTransaction} must be
* called before further use. A non-retryable exception is immediately propagated.
* Otherwise, the state is reset and ready for use.
* </p>
*
* @return <code>true</code> if the caller should retry.
*/
boolean commitOrRetryTransaction(Session session);
/** Rollback an open transaction. */
void rollbackTransaction(Session session);
/** Rollback the current transaction if open, otherwise do nothing. */
void rollbackTransactionIfOpen(Session session);
/**
* Commit the transaction if this is a good time.
*
* <p>
* If the commit was successful, the transaction state is reset and ready
* for reuse. Otherwise, the exception is propagated and
* {@link #rollbackTransaction} must be called be called before reuse.
* </p>
*
* @return {@code true} if a commit was performed, false otherwise
*/
boolean periodicallyCommit(Session session);
/** @return {@code true} if this is a good time to commit, {@code false} otherwise */
boolean shouldPeriodicallyCommit(Session session);
/** Add a callback to transaction. */
void addCallback(Session session, CallbackType type, Callback callback);
/** Add a callback to transaction that is required to be active. */
void addCallbackOnActive(Session session, CallbackType type, Callback callback);
/** Add a callback to transaction that is required to be inactive. */
void addCallbackOnInactive(Session session, CallbackType type, Callback callback);
/** Wrap <code>runnable</code> in a <code>Callable</code> and invoke {@link #run(Session, Callable)}. */
void run(Session session, Runnable runnable);
/**
* Execute in a new transaction and automatically retry if a rollback exception occurs.
* <p>Note: A plain <code>Exception</code> from <code>callable</code> will be <i>rethrown</i>, not retried.</p>
*/
<T> T run(Session session, Callable<T> callable);
enum SessionOption {
/** Control when / how constraints like uniqueness are checked. */
CONSTRAINT_CHECK_TIME
}
/** Set user option on <code>Session</code>. */
void setSessionOption(Session session, SessionOption option, String value);
/** If a transaction can fail with a rollback transaction after
* actually having succeeded, store a unique counter associated
* with the given session persistently so that it can be checked.
*/
int markForCheck(Session session);
/** Check for success from given counter stored in previous
* transaction that failed due with the given exception.
*/
boolean checkSucceeded(Session session, Exception retryException, int sessionCounter);
/** Defer some foreign key checks within this transaction. */
void setDeferredForeignKey(Session session, ForeignKey foreignKey, boolean deferred);
/** Repeat any checks that are scoped to the statement. */
void checkStatementConstraints(Session session);
/** Check if checks should be performed immediately. */
boolean getForceImmediateForeignKeyCheck(Session session);
/** Set if checks should be performed immediately (true disables all deferring). Return previous value. */
boolean setForceImmediateForeignKeyCheck(Session session, boolean force);
/** Return the isolation level that would be in effect if the given one were requested. */
IsolationLevel actualIsolationLevel(IsolationLevel level);
/** Set isolation level for the session's transaction. */
IsolationLevel setIsolationLevel(Session session, IsolationLevel level);
/** Does this isolation level only work with read-only transactions? */
boolean isolationLevelRequiresReadOnly(Session session, boolean commitNow);
}