Resolves #775: Support setting Transaction options at the Database level

This selects a few useful transaction options that users may want to set for every transaction and adds them to the database options.
This commit is contained in:
Alec Grieser 2019-03-19 09:15:41 -07:00
parent 797ccea546
commit 5f73b7d6ae
No known key found for this signature in database
GPG Key ID: CAF63551C60D3462
7 changed files with 128 additions and 28 deletions

View File

@ -276,6 +276,49 @@ func (o DatabaseOptions) SetDatacenterId(param string) error {
return o.setOpt(22, []byte(param))
}
// Set a timeout in milliseconds which, when elapsed, will cause each transaction automatically to be cancelled. This sets the ``timeout`` option of each transaction created by this database. See the transaction option description for more information.
//
// Parameter: value in milliseconds of timeout
func (o DatabaseOptions) SetTransactionTimeout(param int64) error {
b, e := int64ToBytes(param)
if e != nil {
return e
}
return o.setOpt(500, b)
}
// Set a timeout in milliseconds which, when elapsed, will cause a transaction automatically to be cancelled. This sets the ``retry_limit`` option of each transaction created by this database. See the transaction option description for more information.
//
// Parameter: number of times to retry
func (o DatabaseOptions) SetTransactionRetryLimit(param int64) error {
b, e := int64ToBytes(param)
if e != nil {
return e
}
return o.setOpt(501, b)
}
// Set the maximum amount of backoff delay incurred in the call to ``onError`` if the error is retryable. This sets the ``max_retry_delay`` option of each transaction created by this database. See the transaction option description for more information.
//
// Parameter: value in milliseconds of maximum delay
func (o DatabaseOptions) SetTransactionMaxRetryDelay(param int64) error {
b, e := int64ToBytes(param)
if e != nil {
return e
}
return o.setOpt(502, b)
}
// Snapshot read operations will see the results of writes done in the same transaction. This is the default behavior.
func (o DatabaseOptions) SetSnapshotRywEnable() error {
return o.setOpt(26, nil)
}
// Snapshot read operations will not see the results of writes done in the same transaction. This was the default behavior prior to API version 300.
func (o DatabaseOptions) SetSnapshotRywDisable() error {
return o.setOpt(27, nil)
}
// The transaction, if not self-conflicting, may be committed a second time after commit succeeds, in the event of a fault
func (o TransactionOptions) SetCausalWriteRisky() error {
return o.setOpt(10, nil)
@ -370,7 +413,7 @@ func (o TransactionOptions) SetLogTransaction() error {
return o.setOpt(404, nil)
}
// Set a timeout in milliseconds which, when elapsed, will cause the transaction automatically to be cancelled. Valid parameter values are ``[0, INT_MAX]``. If set to 0, will disable all timeouts. All pending and any future uses of the transaction will throw an exception. The transaction can be used again after it is reset. Like all transaction options, a timeout must be reset after a call to onError. This behavior allows the user to make the timeout dynamic.
// Set a timeout in milliseconds which, when elapsed, will cause the transaction automatically to be cancelled. Valid parameter values are ``[0, INT_MAX]``. If set to 0, will disable all timeouts. All pending and any future uses of the transaction will throw an exception. The transaction can be used again after it is reset. Like all transaction options, a timeout must be reset after a call to ``onError``. This behavior allows the user to make the timeout dynamic.
//
// Parameter: value in milliseconds of timeout
func (o TransactionOptions) SetTimeout(param int64) error {
@ -381,7 +424,7 @@ func (o TransactionOptions) SetTimeout(param int64) error {
return o.setOpt(500, b)
}
// Set a maximum number of retries after which additional calls to onError will throw the most recently seen error code. Valid parameter values are ``[-1, INT_MAX]``. If set to -1, will disable the retry limit. Like all transaction options, the retry limit must be reset after a call to onError. This behavior allows the user to make the retry limit dynamic.
// Set a maximum number of retries after which additional calls to ``onError`` will throw the most recently seen error code. Valid parameter values are ``[-1, INT_MAX]``. If set to -1, will disable the retry limit. Like all transaction options, the retry limit must be reset after a call to ``onError``. This behavior allows the user to make the retry limit dynamic.
//
// Parameter: number of times to retry
func (o TransactionOptions) SetRetryLimit(param int64) error {
@ -392,7 +435,7 @@ func (o TransactionOptions) SetRetryLimit(param int64) error {
return o.setOpt(501, b)
}
// Set the maximum amount of backoff delay incurred in the call to onError if the error is retryable. Defaults to 1000 ms. Valid parameter values are ``[0, INT_MAX]``. Like all transaction options, the maximum retry delay must be reset after a call to onError. If the maximum retry delay is less than the current retry delay of the transaction, then the current retry delay will be clamped to the maximum retry delay.
// Set the maximum amount of backoff delay incurred in the call to ``onError`` if the error is retryable. Defaults to 1000 ms. Valid parameter values are ``[0, INT_MAX]``. Like all transaction options, the maximum retry delay must be reset after a call to ``onError``. If the maximum retry delay is less than the current retry delay of the transaction, then the current retry delay will be clamped to the maximum retry delay.
//
// Parameter: value in milliseconds of maximum delay
func (o TransactionOptions) SetMaxRetryDelay(param int64) error {
@ -403,12 +446,12 @@ func (o TransactionOptions) SetMaxRetryDelay(param int64) error {
return o.setOpt(502, b)
}
// Snapshot read operations will see the results of writes done in the same transaction.
// Snapshot read operations will see the results of writes done in the same transaction. This is the default behavior.
func (o TransactionOptions) SetSnapshotRywEnable() error {
return o.setOpt(600, nil)
}
// Snapshot read operations will not see the results of writes done in the same transaction.
// Snapshot read operations will not see the results of writes done in the same transaction. This was the default behavior prior to API version 300.
func (o TransactionOptions) SetSnapshotRywDisable() error {
return o.setOpt(601, nil)
}

View File

@ -152,6 +152,11 @@ public:
int outstandingWatches;
int maxOutstandingWatches;
double transactionTimeout;
int transactionMaxRetries;
double transactionMaxBackoff;
int snapshotRywEnabled;
Future<Void> logger;
int taskID;

View File

@ -513,13 +513,16 @@ DatabaseContext::DatabaseContext(
lockAware(lockAware), apiVersion(apiVersion), provisional(false),
transactionReadVersions(0), transactionLogicalReads(0), transactionPhysicalReads(0), transactionCommittedMutations(0), transactionCommittedMutationBytes(0),
transactionsCommitStarted(0), transactionsCommitCompleted(0), transactionsTooOld(0), transactionsFutureVersions(0), transactionsNotCommitted(0),
transactionsMaybeCommitted(0), transactionsResourceConstrained(0), outstandingWatches(0),
transactionsMaybeCommitted(0), transactionsResourceConstrained(0), outstandingWatches(0), transactionTimeout(0.0), transactionMaxRetries(-1),
latencies(1000), readLatencies(1000), commitLatencies(1000), GRVLatencies(1000), mutationsPerCommit(1000), bytesPerCommit(1000), mvCacheInsertLocation(0),
healthMetricsLastUpdated(0), detailedHealthMetricsLastUpdated(0)
{
metadataVersionCache.resize(CLIENT_KNOBS->METADATA_VERSION_CACHE_SIZE);
maxOutstandingWatches = CLIENT_KNOBS->DEFAULT_MAX_OUTSTANDING_WATCHES;
transactionMaxBackoff = CLIENT_KNOBS->FAILURE_MAX_DELAY;
snapshotRywEnabled = apiVersionAtLeast(300) ? 1 : 0;
logger = databaseLogger( this );
locationCacheSize = g_network->isSimulated() ?
CLIENT_KNOBS->LOCATION_CACHE_EVICTION_SIZE_SIM :
@ -731,6 +734,24 @@ void DatabaseContext::setOption( FDBDatabaseOptions::Option option, Optional<Str
server_interf.clear();
locationCache.insert( allKeys, Reference<LocationInfo>() );
break;
case FDBDatabaseOptions::TRANSACTION_TIMEOUT:
transactionTimeout = extractIntOption(value, 0, std::numeric_limits<int>::max())/1000.0;
break;
case FDBDatabaseOptions::TRANSACTION_RETRY_LIMIT:
transactionMaxRetries = (int)extractIntOption(value, -1, std::numeric_limits<int>::max());
break;
case FDBDatabaseOptions::TRANSACTION_MAX_RETRY_DELAY:
validateOptionValue(value, true);
transactionMaxBackoff = extractIntOption(value, 0, std::numeric_limits<int32_t>::max()) / 1000.0;
break;
case FDBDatabaseOptions::SNAPSHOT_RYW_ENABLE:
validateOptionValue(value, false);
snapshotRywEnabled++;
break;
case FDBDatabaseOptions::SNAPSHOT_RYW_DISABLE:
validateOptionValue(value, false);
snapshotRywEnabled--;
break;
}
}
@ -1938,12 +1959,13 @@ Future<Standalone<RangeResultRef>> getRange( Database const& cx, Future<Version>
}
Transaction::Transaction( Database const& cx )
: cx(cx), info(cx->taskID), backoff(CLIENT_KNOBS->DEFAULT_BACKOFF), committedVersion(invalidVersion), versionstampPromise(Promise<Standalone<StringRef>>()), numErrors(0), trLogInfo(createTrLogInfoProbabilistically(cx))
: cx(cx), info(cx->taskID), backoff(CLIENT_KNOBS->DEFAULT_BACKOFF), committedVersion(invalidVersion), versionstampPromise(Promise<Standalone<StringRef>>()), options(cx), numErrors(0), trLogInfo(createTrLogInfoProbabilistically(cx))
{
setPriority(GetReadVersionRequest::PRIORITY_DEFAULT);
if(cx->lockAware) {
options.lockAware = true;
}
options.maxBackoff = cx->transactionMaxBackoff;
}
Transaction::~Transaction() {
@ -2335,6 +2357,16 @@ double Transaction::getBackoff(int errCode) {
return b;
}
void TransactionOptions::reset(Database const& cx) {
memset(this, 0, sizeof(*this));
maxBackoff = cx->transactionMaxBackoff;
}
void TransactionOptions::reset() {
memset(this, 0, sizeof(*this));
maxBackoff = CLIENT_KNOBS->DEFAULT_MAX_BACKOFF;
}
void Transaction::reset() {
tr = CommitTransactionRequest();
readVersion = Future<Version>();
@ -2350,7 +2382,7 @@ void Transaction::reset() {
cancelWatches();
if(apiVersionAtLeast(16)) {
options.reset();
options.reset(cx);
setPriority(GetReadVersionRequest::PRIORITY_DEFAULT);
if(cx->lockAware)
options.lockAware = true;

View File

@ -150,17 +150,21 @@ struct TransactionOptions {
bool readOnly : 1;
bool firstInBatch : 1;
TransactionOptions() {
reset();
TransactionOptions(Database const& cx) {
reset(cx);
if (BUGGIFY) {
commitOnFirstProxy = true;
}
}
void reset() {
memset(this, 0, sizeof(*this));
maxBackoff = CLIENT_KNOBS->DEFAULT_MAX_BACKOFF;
TransactionOptions() {
reset();
}
void reset(Database const& cx);
private:
void reset();
};
struct TransactionInfo {
@ -301,7 +305,7 @@ public:
void checkDeferredError();
Database getDatabase(){
Database getDatabase() const {
return cx;
}
static Reference<TransactionLogInfo> createTrLogInfoProbabilistically(const Database& cx);

View File

@ -1469,6 +1469,14 @@ void ReadYourWritesTransaction::writeRangeToNativeTransaction( KeyRangeRef const
}
}
void ReadYourWritesTransactionOptions::reset(Transaction const& tr) {
memset(this, 0, sizeof(*this));
Database cx = tr.getDatabase();
timeoutInSeconds = cx->transactionTimeout;
maxRetries = cx->transactionMaxRetries;
snapshotRywEnabled = cx->snapshotRywEnabled;
}
bool ReadYourWritesTransactionOptions::getAndResetWriteConflictDisabled() {
bool disabled = nextWriteDisableConflictRange;
nextWriteDisableConflictRange = false;

View File

@ -43,12 +43,7 @@ struct ReadYourWritesTransactionOptions {
ReadYourWritesTransactionOptions() {}
explicit ReadYourWritesTransactionOptions(Transaction const& tr) { reset(tr); }
void reset(Transaction const& tr) {
memset(this, 0, sizeof(*this));
timeoutInSeconds = 0.0;
maxRetries = -1;
snapshotRywEnabled = tr.apiVersionAtLeast(300) ? 1 : 0;
}
void reset(Transaction const& tr);
bool getAndResetWriteConflictDisabled();
};

View File

@ -133,6 +133,19 @@ description is not currently required but encouraged.
<Option name="datacenter_id" code="22"
paramType="String" paramDescription="Hexadecimal ID"
description="Specify the datacenter ID that was passed to fdbserver processes running in the same datacenter as this client, for better location-aware load balancing." />
<Option name="transaction_timeout" code="500"
paramType="Int" paramDescription="value in milliseconds of timeout"
description="Set a timeout in milliseconds which, when elapsed, will cause each transaction automatically to be cancelled. This sets the ``timeout`` option of each transaction created by this database. See the transaction option description for more information." />
<Option name="transaction_retry_limit" code="501"
paramType="Int" paramDescription="number of times to retry"
description="Set a timeout in milliseconds which, when elapsed, will cause a transaction automatically to be cancelled. This sets the ``retry_limit`` option of each transaction created by this database. See the transaction option description for more information." />
<Option name="transaction_max_retry_delay" code="502"
paramType="Int" paramDescription="value in milliseconds of maximum delay"
description="Set the maximum amount of backoff delay incurred in the call to ``onError`` if the error is retryable. This sets the ``max_retry_delay`` option of each transaction created by this database. See the transaction option description for more information." />
<Option name="snapshot_ryw_enable" code="26"
description="Snapshot read operations will see the results of writes done in the same transaction. This is the default behavior." />
<Option name="snapshot_ryw_disable" code="27"
description="Snapshot read operations will not see the results of writes done in the same transaction. This was the default behavior prior to API version 300." />
</Scope>
<Scope name="TransactionOption">
@ -177,17 +190,17 @@ description is not currently required but encouraged.
description="Enables tracing for this transaction and logs results to the client trace logs. The DEBUG_TRANSACTION_IDENTIFIER option must be set before using this option, and client trace logging must be enabled and to get log output." />
<Option name="timeout" code="500"
paramType="Int" paramDescription="value in milliseconds of timeout"
description="Set a timeout in milliseconds which, when elapsed, will cause the transaction automatically to be cancelled. Valid parameter values are ``[0, INT_MAX]``. If set to 0, will disable all timeouts. All pending and any future uses of the transaction will throw an exception. The transaction can be used again after it is reset. Like all transaction options, a timeout must be reset after a call to onError. This behavior allows the user to make the timeout dynamic." />
description="Set a timeout in milliseconds which, when elapsed, will cause the transaction automatically to be cancelled. Valid parameter values are ``[0, INT_MAX]``. If set to 0, will disable all timeouts. All pending and any future uses of the transaction will throw an exception. The transaction can be used again after it is reset. Like all transaction options, a timeout must be reset after a call to ``onError``. This behavior allows the user to make the timeout dynamic." />
<Option name="retry_limit" code="501"
paramType="Int" paramDescription="number of times to retry"
description="Set a maximum number of retries after which additional calls to onError will throw the most recently seen error code. Valid parameter values are ``[-1, INT_MAX]``. If set to -1, will disable the retry limit. Like all transaction options, the retry limit must be reset after a call to onError. This behavior allows the user to make the retry limit dynamic." />
description="Set a maximum number of retries after which additional calls to ``onError`` will throw the most recently seen error code. Valid parameter values are ``[-1, INT_MAX]``. If set to -1, will disable the retry limit. Like all transaction options, the retry limit must be reset after a call to ``onError``. This behavior allows the user to make the retry limit dynamic." />
<Option name="max_retry_delay" code="502"
paramType="Int" paramDescription="value in milliseconds of maximum delay"
description="Set the maximum amount of backoff delay incurred in the call to onError if the error is retryable. Defaults to 1000 ms. Valid parameter values are ``[0, INT_MAX]``. Like all transaction options, the maximum retry delay must be reset after a call to onError. If the maximum retry delay is less than the current retry delay of the transaction, then the current retry delay will be clamped to the maximum retry delay."/>
description="Set the maximum amount of backoff delay incurred in the call to ``onError`` if the error is retryable. Defaults to 1000 ms. Valid parameter values are ``[0, INT_MAX]``. Like all transaction options, the maximum retry delay must be reset after a call to ``onError``. If the maximum retry delay is less than the current retry delay of the transaction, then the current retry delay will be clamped to the maximum retry delay."/>
<Option name="snapshot_ryw_enable" code="600"
description="Snapshot read operations will see the results of writes done in the same transaction." />
description="Snapshot read operations will see the results of writes done in the same transaction. This is the default behavior." />
<Option name="snapshot_ryw_disable" code="601"
description="Snapshot read operations will not see the results of writes done in the same transaction." />
description="Snapshot read operations will not see the results of writes done in the same transaction. This was the default behavior prior to API version 300." />
<Option name="lock_aware" code="700"
description="The transaction can read and write to locked databases, and is resposible for checking that it took the lock."/>
<Option name="used_during_commit_protection_disable" code="701"