Uploaded image for project: 'Blazegraph (by SYSTAP)'
  1. Blazegraph (by SYSTAP)
  2. BLZG-1195

Read/write tx support in NSS and BigdataSailRemoteRepositoryConnection




      This ticket is to add support for full read/write transactions into the NSS REST API and to bring the BigdataSailRemoteRepositoryConnection interface up to compliance with the new openrdf begin(), prepare(), and isActive() transaction semantics. The workbench also needs to be modified to allow people to select either throughput oriented transactions (unisolated updates) or fully isolated read/write transactions on a namespace by namespace basis. This configuration option amounts to specifying BigdataSail.Options.ISOLATABLE_INDICES:=true for that namespace. Isolation is ONLY supported for Journal and HAJournal (it is not supported for the JiniFederation since we never implemented distributed 2-phase commits for that architecture which relies on shard-local ACID commits).

      BlazeGraph has two different kinds of ACID update operations: Unisolated and Isolated.

      - Unisolated operations directly modify the live index objects and do not support concurrent modification.

      - Isolated operations use an index in front of the live index object to buffer mutations, validate the write set against the live indices during a prepare operation, and then merge down the updates onto the live indices during the commit. This capability corresponds closely to the semantics of the new begin(), prepare(), and isActive() methods for the SailConnection.

      BlazeGraph also supports two different kinds of commit control: application driven commit and group commit.

      - Application driven commit is the historical mode used by embedded applications. In this mode, a commit() on an unisolated connection directly drives an ACID commit by the database. Further, concurrent writers on different namespaces are not allowed in order to preserve ACID semantics for writes. Without this restriction, unisolated writes that had modified indices in other namespaces would become visible as soon as any namespace was driven to a commit point.

      - Group commit allows concurrent writers on different namespaces using a job-oriented concurrency model. To achieve this, it provides isolation for the Name2Addr index such that an index does not appear to be dirty when going through a commit unless the task has finished execution and checkpointed its indices. When the task checkpoints its indices, the new checkpoint record for those indices is atomically published to the Name2Addr index such that the touched indices will be melded into the next group commit. Indices that have been modified but which are not yet checkpointed do not participate in a commit group.

      The new methods in the sail connection api are:

      	 * Begins a transaction requiring {@link #commit()} or {@link #rollback()} to
      	 * be called to close the transaction.
      	 * @since 2.7.0
      	 * @throws SailException
      	 *         If the connection could not start a transaction or if a
      	 *         transaction is already active on this connection.
      	public void begin()
      		throws SailException;


      { /** * Checks for an error state in the active transaction that would force the * transaction to be rolled back. This is an optional call; calling or not * calling this method should have no effect on the outcome of * \{@link #commit()}

      or {@link #rollback()}. A call to this method must be

      • followed by (in the same thread) with a call to {@link #prepare()} ,
      • {@link #commit()}, {@link #rollback()}, or {@link #close()}. This method
      • may be called multiple times within the same transaction by the same
      • thread. If this method returns normally, the caller can reasonably expect
      • that a subsequent call to {@link #commit()} will also return normally. If
      • this method returns with an exception the caller should treat the
      • exception as if it came from a call to {@link #commit()}.
      • @since 2.7.0
      • @throws UnknownSailTransactionStateException
      • If the transaction state can not be determined (this can happen
      • for instance when communication between client and server fails or
      • times-out). It does not indicate a problem with the integrity of
      • the store.
      • @throws SailException
      • If there is an active transaction and it cannot be committed.
      • @throws IllegalStateException
      • If the connection has been closed or prepare was already called by
      • another thread.
        public void prepare()
        throws SailException;
        }}}{{ { /** * Indicates if a transaction is currently active on the connection. A * transaction is active if \{@link #begin()}

        has been called, and becomes

      • inactive after {@link #commit()} or {@link #rollback()} has been called.
      • @since 2.7.0
      • @return <code>true</code> iff a transaction is active, <code>false</code>
      • iff no transaction is active.
      • @throws UnknownSailTransactionStateException
      • if the transaction state can not be determined (this can happen
      • for instance when communication between client and server fails or
      • times out).
        public boolean isActive()
        throws UnknownSailTransactionStateException;

      When isolation is enabled for a namespace:
      - begin() is mapped onto CREATE_TX(0L) to create a read/write transaction.
      - isActive() is mapped onto journal.getTx(txId).isActive()
      - prepare() might be mappable onto tx validation (if that can be separated from the merge down to the unisolated indices
      - currently calling Tx.prepare() also merges down the write set to the unisolated indices such that the tx is restart safe at the next group commit, but the validation of the write set is its own idempotent method
      - it is just not exposed). For the user to invoke prepare() without forcing a commit, it needs to be submitted as an AbstractTask (just as does commit). This is all about having the locks on the unisolated indices touched by the Tx. Without those locks we can neither prepare (validate against the unisolated indices) nor commit (merge down onto the unisolated indices).
      - commit() is mapped onto Journal.commit(txId). This gets pass through into an AbstractTask that invokes Tx.prepare().
      - rollback() is mapped onto Journal.abort(txId);

      Write unit tests for mixed mode transactions. The database internally uses revision timestamps to detect conflicts in fully isolated read/write transactions. This mechanism is compatible with the unisolated transaction model (that is, unisolated transactions also update revision timestamps if they are enabled for a given index). Thus it should be possible to use unisolated transactions to bulk load data into either an empty namespace or a namespace with existing data without requiring the transaction write set to be buffered and validated. Achieving this from the BigdataSailRemoteRepositoryConnection will require extension methods to differentiate fully isolated vs unisolated transactions. The blazegraph RemoteRepository would likewise need to expose additional methods to manage the life cycle of transactions and to distinguish between transactions that are and are not fully isolated.

      The following classes will be touched by this ticket:

      - StressTestConcurrentTx
      - This is the stress test for concurrent fully isolated read/write transaction support on the Journal. The test suite uses the job-oriented concurrency control pattern (submitting an AbstractTask from within a Callable).
      - Tx
      - This is the core transaction class for the journal. It needs to be modified to separate out validation and commit.
      - AbstractTask
      - we need to reduce the overhead associated with full tx isolation (there is one TemporaryStore per Tx
      - use a MemStore instead).
      - BigdataSail (especially the BigdataSailRWTxConnection)

      - All mutation interfaces for the REST API need to be reviewed and modified to ensure that they support full read-write connections and not only unisolated updates.
      - All read-only interfaces for the REST API need to be reviewed to ensure that they support an optional transaction identifier and that when given the operation is isolated by that transaction.
      - TxServlet: (a) Define a new servlet that exposes methods to create and destroy a fully isolated read/write transaction (iff the namespace is configured for that support). (b) Since it is all too easy for a remote client to leave open a read/write transaction, we would need to track open read/write transactions (the Journal can self-report them) and expose them for cancellation to recover resources that would otherwise be leaked by a client failing to abort/commit a tx. We might want to offer an option to group the txIds by their declared locks. This will naturally organize them namespace.
      - SD: (This is already reported.) Extend the service description to indicate whether a given namespace supports fully isolated read/write transactions.
      - index.html and workspace.js: Modified to expose the option to enable isolatable indices.

      Remote clients:
      - RemoteRepository (should support tx, includeInferred, etc. We need unit tests for tx isolation on all REST API methods).
      - RemoteRepositoryManager
      - BigdataSailRemoteRepository
      - BigdataSailRemoteRepositoryConnection (full compliance plus we need a test suite for this class
      - it is completely lacking tests. hopefully we can reuse the openrdf test suite through a modified version that gets invoked from within our remote client package)

      See BLZG-461 AbstractTask uses one TemporaryStoreFactory per read-only or read/write tx task.
      See BLZG-789 BigdataSailRemoteRepositoryConnection should implement interface methods
      See BLZG-1099 BigdataSailUpdate.execute() commits the connection
      See BLZG-1155 RemoteRepository.hasStatements can overestimate if the namespace uses fully isolated read/write transactions.
      See BLZG-1170 Add REST API method for exact range counts
      See BLZG-1107 Add ability to set RIO options to REST API and workbench
      See BLZG-1106 Change RDFParser configuration to use BasicParserSettings
      See BLZG-29 HA test suite for transaction management API
      See BLZG-199 Refactor RemoteRepository / RemoteRepositoryManager

      TODO Update NSS wiki page to reflect new API. See http://wiki.blazegraph.com/wiki/index.php/NanoSparqlServer#Transaction_Management

      Created branch: TICKET_1156


          Issue Links



              bryanthompson bryanthompson
              bryanthompson bryanthompson
              0 Vote for this issue
              3 Start watching this issue