All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bigdata.service.ITxCommitProtocol Maven / Gradle / Ivy

/**

Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016.  All rights reserved.

Contact:
     SYSTAP, LLC DBA Blazegraph
     2501 Calvert ST NW #106
     Washington, DC 20008
     [email protected]

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.

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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
/*
 * Created on Mar 22, 2007
 */

package com.bigdata.service;

import java.io.IOException;
import java.rmi.Remote;
import java.util.concurrent.ExecutionException;

import com.bigdata.btree.ITuple;
import com.bigdata.journal.ITransactionService;
import com.bigdata.journal.ValidationError;

/**
 * Remote interface by which the {@link ITransactionService} manages the state
 * of transactions on the distributed {@link IDataService}s.
 * 
 * @author Bryan Thompson
 * @version $Id$
 */
public interface ITxCommitProtocol extends Remote {

    /**
     * Notify a data service that it MAY release data required to support views
     * for up to the specified releaseTime . This is the mechanism by
     * which read locks are released. In effect, a read lock is a requirement
     * that the releaseTime not be advanced as far as the start time of the
     * transaction holding that read lock. Periodically and as transactions
     * complete, the transaction manager will advance the releaseTime, thereby
     * releasing read locks.
     * 
     * @param releaseTime
     *            The new release time (strictly advanced by the transaction
     *            manager).
     * 
     * @throws IllegalStateException
     *             if the read lock is set to a time earlier than its current
     *             value.
     * @throws IOException
     *             if there is an RMI problem.
     */
    public void setReleaseTime(long releaseTime) throws IOException;

    /**
     * Request abort of the transaction by the data service. This message is
     * sent in response to {@link ITransactionService#abort(long)} to each
     * {@link IDataService} on which the transaction has written. It is NOT sent
     * for read-only transactions since they have no local state on the
     * {@link IDataService}s.
     * 
     * @param tx
     *            The transaction identifier.
     * 
     * @throws IllegalArgumentException
     *             if the transaction has not been started on this data service.
     * @throws IOException
     *             if there is an RMI problem.
     */
    public void abort(long tx) throws IOException;

    /**
     * Request commit of the transaction by the data service. In the case where
     * the transaction is entirely contained on the data service this method may
     * be used to both prepare (validate) and commit the transaction (a single
     * phase commit). Otherwise a 2-/3- phase commit is required and a separate
     * {@link #prepare(long)} message MUST be used.
     * 
     * @param tx
     *            The transaction identifier.
     * 
     * @return The commit time assigned to that transaction.
     * 
     * @throws IllegalArgumentException
     *             if the transaction is read-only.
     * @throws IllegalStateException
     *             if the transaction is not known to the data service.
     * @throws InterruptedException
     *             if interrupted.
     * @throws ExecutionException
     *             This will wrap a {@link ValidationError} if validation fails.
     * @throws IOException
     *             if there is an RMI problem.
     */
    public long singlePhaseCommit(long tx) throws InterruptedException,
            ExecutionException, IOException;

    /**
     * Request that the {@link IDataService} participate in a 3-phase commit.
     * 

* When the {@link IDataService} is sent the {@link #prepare(long, long)} * message it executes a task which will handle commit processing for the * transaction. That task MUST hold exclusive locks for the unisolated * indices to which the transaction write sets will be applied. While * holding those locks, the task must first validate the transaction's write * set and then merge down the write set onto the corresponding unisolated * indices using the specified revisionTime and checkpoint the * indices in order to reduce all possible sources of latency. Note that * each {@link IDataService} is able to independently prepare exactly those * parts of the transaction's write set which are mapped onto index * partitions hosted by a given {@link IDataService}. *

* Once validation is complete and all possible steps have been taken to * reduce sources of latency (e.g., checkpoint the indices and pre-extending * the store if necessary), the task notifies the * {@link ITransactionService} that it has prepared using * {@link ITransactionService#prepared(long)}. The * {@link ITransactionService} will wait until all tasks have prepared. If a * task CAN NOT prepare the transaction, then it MUST throw an exception out * of its {@link #prepare(long, long)} method. *

* Once all tasks have send an {@link ITransactionService#prepared(long)} * message to the {@link ITransactionService}, it will assign a commitTime * to the transaction and permit those methods to return that commitTime to * the {@link IDataService}s. Once the task receives the assigned commit * time, it must obtain an exclusive write lock for the live journal (this * is a higher requirement than just an exclusive lock on the necessary * indices and will lock out all other write requests for the journal), * register the checkpointed indices on the commit list and then request a * commit of the journal using the specified commitTime. The task then * notifies the transaction service that it has completed its commit using * {@link ITransactionService#committed(long)} and awaits a response. If the * {@link ITransactionService} indicates that the commit was not successful, * the task rolls back the live journal to the prior commit point and throws * an exception out of {@link #prepare(long, long)}. *

* A sample flow for successful a distributed transaction commit is shown * below. This example shows two {@link IDataService}s on which the client * has written. (If the client only writes on a single data service then we * use a single-phase commit protocol). * *

     * client -------+----txService----+--dataService1--+--dataService2--+...           
     *   | [1]                    
     *   | commit(tx) -------- + [2]
     *   |                     | prepare(tx,rev) +
     *   |                     | [3]             |
     *   |                     | prepare(tx,rev) ------------------+
     *   |                     |                 |                 |
     *   |                     | <--prepared(tx) +                 |
     *   |                     |                                   |
     *   |                     | <------------------- prepared(tx) +
     *   |                     |  
     *   |       "prepared" barrier [4]
     *   |                     |
     *   |                     | -- (commitTime) +  
     *   |                     | -------------------- (commitTime) +
     *   |                     | [5]             |                 |
     *   |                     | <--committed(tx)------------------+  
     *   |                     | [6]             |
     *   |                     | <--committed(tx)+
     *   |                     | 
     *   |       "committed" barrier [7]
     *   |                     | [8]
     *   |                     | ------ (success)+  
     *   |                     | [9]             |
     *   |                     | (void)----------+
     *   |                     |                 halt
     *   |                     | [10]             
     *   |                     | ------------------------ (success)+
     *   |                     | [11]                              |
     *   |                     | (void)----------------------------+
     *   |                [12] |                                   halt
     *   | (commitTime)--------+  
     *   |                   
     * 
* *
    *
  • [1] The client issues an {@link ITransactionService#commit(long)} * request, in which it specifies the transaction identifier (tx).
  • *
  • [2,3] The transaction service issues concurrent * {@link #prepare(long, long)} requests to the participating * {@link IDataService}s, specifying the transaction identifier (tx) and * the revision timestamp (rev) to be used and then waits at a barrier until * it receives {@link ITransactionService#prepared(long)} messages from * those {@link IDataService}s.
  • *
  • [4] When all participants have prepared, the barrier breaks and the * {@link ITransactionService} assigns a commitTime and returns that * commitTime as the return value for the prepared messages.
  • *
  • [5,6] Once the {@link IDataService} obtains that commitTime, it * proceeds with its atomic commit using the specified commitTime and then * sends an {@link ITransactionService#committed(long)} message to the * {@link ITransactionService}.
  • *
  • [7] The {@link ITransactionService} waits at another barrier.
  • *
  • [8,10] Once it has received an * {@link ITransactionService#committed(long)} message from each * participating {@link IDataService} the transaction has been successfully * committed and the barrier breaks. The {@link ITransactionService} now * lets the {@link ITransactionService#committed(long)} messages return * true, indicating success.
  • *
  • [9,11] The {@link IDataService}s return (void) from their * {@link #prepare(long, long)} message and the threads running their side * of the commit protocol halt.
  • *
  • [12] The {@link ITransactionService} returns the commit time which * it assigned and which was used by each participating {@link IDataService} * to the client. *
* There are many points in the protocol where commit processing can fail. * However, there are two primary failure classifications that are of * interest for error handling. Up until the first barrier is satisified, * there is no side-effect on the persistent state so error handling need * only halt processing on the {@link IDataService}s and discard any local * state associated with the transaction and throw an exception out of * {@link #prepare(long, long)}. Once the first barrier has been * satisfied, persistent side-effects MAY occur. Error handling in this * case must rollback the state of the live journal for each of the * participating {@link IDataService}s. If error handling was performed in * response to a local error, then the {@link IDataService} must throw that * error out of {@link #prepare(long, long)}. However, if error handling * was initiated because {@link ITransactionService#committed(long)} * returned false then it should return normally (after * rolling back the journal). * * @param tx * The transaction identifier. * @param revisionTime * The timestamp that will be written into the {@link ITuple}s * when the write set of the validated transaction is merged down * onto the unisolated indices. * * @throws Throwable * if there is a problem during the execution of the commit * protocol by the {@link IDataService}. * @throws IOException * if there is an RMI problem. * * @todo it may be possible to set the desired commit time on the abstract * task (or a subclass specific to the distributed commit protocol) * and then use that timestamp rather than requesting one from the * {@link ITransactionService} in the group commit. This would allow * us to use the normal commit processing. *

* If each distributed transaction gets its own commit time then we * can not allow more than one distributed transaction into a given * commit group. Therefore it seems that the * {@link ITransactionService} would have to be able to assign the * same commitTime to a set of distributed transactions that it knew * were prepared together and would commit together. I can't quite see * how that would work. *

* Failing that, we will need to exclude other tasks (or at least * other distributed commit processing tasks) from the commit group. */ public void prepare(long tx, long revisionTime) throws Throwable, IOException; // /** // * Cancel a 2-phase commit. // * // * @param tx // * The transaction identifier. // * // * @throws IllegalArgumentException // * if the transaction has not been started on this data service. // * @throws IllegalStateException // * if the transaction is not participating in a 2-phase commit. // * @throws IOException // * if there is an RMI problem. // */ // public void twoPhaseCancel(long tx) throws IOException; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy