|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||
java.lang.Objectcom.bigdata.service.AbstractService
com.bigdata.service.AbstractTransactionService
com.bigdata.service.DistributedTransactionService
public abstract class DistributedTransactionService
Implementation for an IBigdataFederation supporting both single-phase
commits (for transactions that execute on a single IDataService) and
distributed commits.
| Nested Class Summary | |
|---|---|
protected class |
DistributedTransactionService.NotifyReleaseTimeTask
Task periodically notifies the discovered IDataServices of the
new release time. |
static interface |
DistributedTransactionService.Options
Options understood by this service. |
static class |
DistributedTransactionService.SnapshotHelper
A helper class for reading and writing snapshots of the commit time index. |
| Nested classes/interfaces inherited from class com.bigdata.service.AbstractTransactionService |
|---|
AbstractTransactionService.TxState |
| Field Summary | |
|---|---|
protected static String |
BASENAME
Basename for the files written in the dataDir containing images
of the commitTimeIndex. |
protected CommitTimeIndex |
commitTimeIndex
A BTree containing a log of the historical commit points. |
protected File |
dataDir
The data directory -or- null iff the service is transient. |
protected static String |
EXT
Extension for the files written in the dataDir containing
snapshots of the commitTimeIndex. |
| Fields inherited from class com.bigdata.service.AbstractTransactionService |
|---|
countersRoot, DEBUG, ERR_NO_SUCH, ERR_NOT_ACTIVE, ERR_READ_ONLY, ERR_SERVICE_NOT_AVAIL, INFO, lock, log, startTimeIndex, txDeactivate |
| Constructor Summary | |
|---|---|
DistributedTransactionService(Properties properties)
|
|
| Method Summary | |
|---|---|
protected void |
abortImpl(AbstractTransactionService.TxState state)
Implementation must abort the tx on the journal (standalone) or on each data service (federation) on which it has written. |
protected void |
addScheduledTasks()
Adds the scheduled tasks. |
protected long |
commitImpl(AbstractTransactionService.TxState state)
There are two distinct commit protocols depending on whether the transaction write set is distributed across more than one IDataService. |
boolean |
committed(long tx,
UUID dataService)
Wait at "committed" barrier. |
void |
destroy()
Immediate/fast shutdown of the service and then destroys any persistent state associated with the service. |
protected long |
findCommitTime(long timestamp)
Find the commit time from which the tx will read (largest commitTime LTE timestamp). |
protected long |
findNextCommitTime(long commitTime)
Return the commit time for the successor of that commit point have the specified timestamp (a commit time strictly GT the given value). |
CounterSet |
getCounters()
Adds counters for the LockManager. |
protected ITxCommitProtocol[] |
getDataServices(UUID[] uuids)
Return the proxies for the services participating in a distributed transaction commit or abort. |
long |
getLastCommitTime()
Note: Declared abstract so that we can hide the IOException. |
void |
notifyCommit(long commitTime)
The basic implementation advances the release time periodically as commits occur even when there are no transactions in use. |
long |
prepared(long tx,
UUID dataService)
Waits at "prepared" barrier. |
protected void |
setReleaseTime(long releaseTime)
Extended to truncate the head of the commitTimeIndex such only
the commit times requires for reading on timestamps GTE to the new
releaseTime are retained. |
void |
shutdown()
Polite shutdown. |
void |
shutdownNow()
Fast shutdown (not immediate since it must abort active transactions). |
protected long |
singlePhaseCommit(AbstractTransactionService.TxState state)
Prepare and commit a read-write transaction that has written on a single data service. |
void |
snapshot()
Runs the SnapshotTask once. |
DistributedTransactionService |
start()
Verifies that AbstractTransactionService.nextTimestamp() will not report a time before
AbstractTransactionService.getLastCommitTime() and then changes the TxServiceRunState
to TxServiceRunState.Running. |
| Methods inherited from class com.bigdata.service.AbstractTransactionService |
|---|
abort, activateTx, assertOpen, assignTransactionIdentifier, commit, deactivateTx, declareResources, findUnusedTimestamp, getAbortCount, getActiveCount, getCommitCount, getMinReleaseAge, getProperties, getReadOnlyActiveCount, getReadWriteActiveCount, getReleaseTime, getRunState, getServiceIface, getStartCount, getStartTime, isOpen, newTx, nextTimestamp, setRunState, updateReleaseTime |
| Methods inherited from class com.bigdata.service.AbstractService |
|---|
clearLoggingContext, getFederation, getHostname, getServiceName, getServiceUUID, setServiceUUID, setupLoggingContext |
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Methods inherited from interface com.bigdata.service.IService |
|---|
getHostname, getServiceName, getServiceUUID |
| Field Detail |
|---|
protected final CommitTimeIndex commitTimeIndex
BTree containing a log of the historical commit points.
The main things that it gives us are (a) the half-open ranges within which we can allocate read-historical transactions; and (b) the last commit time on record. It seems that creating an image of the log every N seconds should be sufficient.
Note: Read and write operations on this index MUST be synchronized on the index object.
protected final File dataDir
null iff the service is transient.
protected static final String BASENAME
dataDir containing images
of the commitTimeIndex.
protected static final String EXT
dataDir containing
snapshots of the commitTimeIndex.
| Constructor Detail |
|---|
public DistributedTransactionService(Properties properties)
properties - | Method Detail |
|---|
public void snapshot()
SnapshotTask once.
public DistributedTransactionService start()
AbstractTransactionServiceAbstractTransactionService.nextTimestamp() will not report a time before
AbstractTransactionService.getLastCommitTime() and then changes the TxServiceRunState
to TxServiceRunState.Running.
start in class AbstractTransactionServiceprotected void addScheduledTasks()
public void shutdown()
AbstractTransactionService
shutdown in interface IServiceShutdownshutdown in class AbstractTransactionServicepublic void shutdownNow()
AbstractTransactionService
New transactions will not start and active transactions will be aborted.
Transactions which are concurrently committing MAY fail (throwing
exceptions from various methods, including AbstractTransactionService.nextTimestamp())
when the service halts.
shutdownNow in interface IServiceShutdownshutdownNow in class AbstractTransactionServicepublic void destroy()
AbstractTransactionService
destroy in interface IServicedestroy in class AbstractTransactionServiceprotected void setReleaseTime(long releaseTime)
commitTimeIndex such only
the commit times requires for reading on timestamps GTE to the new
releaseTime are retained.
setReleaseTime in class AbstractTransactionServicereleaseTime - The new value.protected ITxCommitProtocol[] getDataServices(UUID[] uuids)
Note: This method is here so that it may be readily overriden for unit tests.
uuids - The UUIDs of the participating services.
protected void abortImpl(AbstractTransactionService.TxState state)
throws Exception
AbstractTransactionServicePre-conditions:
RunState.Active; andAbstractTransactionService.TxState.lock.Post-conditions:
RunState.Aborted; andJournal
or IDataService or which it has written (applicable for
read-write transactions only).
abortImpl in class AbstractTransactionServicestate - The transaction state as maintained by the transaction server.
Exception
protected long commitImpl(AbstractTransactionService.TxState state)
throws Exception
IDataService. When write set of the transaction lies entirely on
a single IDataService, an optimized commit protocol is used.
When the write set of the transaction is distributed, a 3-phase commit is
used with most of the work occurring during the "prepare" phase and a
very rapid "commit" phase. If a distributed commit fails, even during the
"commit", then the transaction will be rolled back on all participating
IDataServices.
IDataService. Such commits DO NOT
contend for named resource locks (either on the index names or on the
IDataService UUIDs). Since such transactions DO NOT have
dependencies outside of the specific IDataService, a necessary
and sufficient partial order will be imposed on the executing tasks
locally by the IDataService on which they are executing based
solely on the named resources which they declare. Without dependencies on
distributed resources, this can not deadlock.
indexLockManager. The named index locks
are pre-declared at the start of the distributed commit protocol and are
held through both the prepare and commit phases until the end of the
commit protocol. The distributed commit must obtain a lock on all of the
necessary named index resources before proceeding. If there is an
existing commit using some of those resources, then any concurrent commit
requiring any of those resources will block. The LockManager is
configured to require pre-declaration of locks. Deadlocks are NOT
possible when the locks are pre-declared.
A secondary partial ordering is established based on the
IDataService UUIDs during the commit phase. This partial
order is necessary to avoid deadlocks for concurrently executing commit
phases of distributed transactions that DO NOT share named index locks.
Without a partial order over the participating IDataServices,
deadlocks could arise because each transaction will grab an exclusive
lock on the write service for each participating IDataService.
By ordering those lock requests, we again ensure that deadlocks can not
occur.
Note: The prepare phase for distributed commits allows the maximum possible concurrency. This is especially important as validation and merging down onto the unisolated indices can have significant length for large transactions.
The commit phase should be very fast, with syncing the disk providing the
primary source of latency. All participating indices on the participating
data services have already been checkpointed. Once the commitTime is
assigned by the DistributedTransactionService, the group commit
need only update the root block on the live journal and sync to disk.
commitImpl in class AbstractTransactionServiceException - if something else goes wrong. This will be (or will wrap) a
ValidationError if validation fails.Name2Addr before requesting the commitTime to remove even
more latency.
protected long singlePhaseCommit(AbstractTransactionService.TxState state)
throws Exception
Exception
public long prepared(long tx,
UUID dataService)
throws IOException,
InterruptedException,
BrokenBarrierException
TxState. If the transaction is aborted, then throw an
InterruptedException. Otherwise return the commitTime assigned
to the transaction.
tx - The transaction identifier.dataService - The UUID of the IDataService which sent the
message.
InterruptedException - if the barrier is reset while the caller is waiting.
IOException - if there is an RMI problem.
BrokenBarrierException
public boolean committed(long tx,
UUID dataService)
throws IOException,
InterruptedException,
BrokenBarrierException
TxState. If the transaction is aborted, then return
false. Otherwise return true.
Note: The TxState will be aborted if any of the committers throws
an exception of their ITxCommitProtocol.prepare(long, long)
method.
tx - The transaction identifier.dataService - The UUID of the IDataService which sent the
message.
true if the distributed commit was successfull and
false if there was a problem.
IOException
InterruptedException
BrokenBarrierExceptionprotected long findCommitTime(long timestamp)
AbstractTransactionService
findCommitTime in class AbstractTransactionServicetimestamp - The timestamp.
protected long findNextCommitTime(long commitTime)
AbstractTransactionService
findNextCommitTime in class AbstractTransactionServicecommitTime - The probe.
public final void notifyCommit(long commitTime)
AbstractTransactionServiceNote: This needs to be a fairly low-latency operation since this method is invoked for all commits on all data services and will otherwise be a global hotspot.
notifyCommit in interface ITransactionServicenotifyCommit in class AbstractTransactionServicecommitTime - The commit time.
The danger is that we could assign a read-historical transaction
start time based on the commitTimeIndex and then have
commit timestamps arrive that are within the interval in which we
made the assignment. Essentially, our interval was too large and
the assigned start time may have been on either side of a
concurrent commit. However, this can only occur for unisolated
operations (non-transactional commits). The selected timestamp will
always be coherent with respect to transaction commits since those
are coordinated and use a shared commit time.
This issue can only arise when requesting historical reads for
timestamps that are "close" to the most recent commit point since
the latency involve would otherwise not effect the assignment of
transaction start times. However, it can occur either when
specifying the symbolic constant ITx.READ_COMMITTED to
AbstractTransactionService.newTx(long) or when specifying the exact commitTime
reported by a transaction commit.
Simply stated, there is NO protection against concurrently
unisolated operations committing. If such operations are used on
the same indices as transactions, then it IS possible that the
application will be unable to read from exactly the post-commit
state of the transaction for a brief period (10s of milliseconds)
until the unisolated commit notices have been propagated to the
DistributedTransactionService. This issue will only occur
when there is also a lot of contention for reading on the desired
timestamp since otherwise the commitTime itself may be used as a
transaction start time., depending on the latency involved and the issue described
immediately above, it might be possible to simply queue these
notices and consume them in an async thread. some operations (such
as a distributed commit) might require that we catch up on the
commit time notices in the queue. just thinking out loud here.
public final long getLastCommitTime()
AbstractTransactionServiceIOException.
getLastCommitTime in interface ITransactionServicegetLastCommitTime in class AbstractTransactionServicepublic CounterSet getCounters()
LockManager.
getCounters in class AbstractTransactionService
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||