Merge pull request #4729 from sfc-gh-etschannen/feature-bypass-unreadable

Added a new option to bypass unreadable protection in read your writes for calls to get
This commit is contained in:
A.J. Beamon 2021-05-04 11:35:44 -07:00 committed by GitHub
commit 1537019237
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 35 additions and 4 deletions

View File

@ -42,7 +42,7 @@ const RYWIterator::SEGMENT_TYPE RYWIterator::typeMap[12] = {
};
RYWIterator::SEGMENT_TYPE RYWIterator::type() const {
if (is_unreadable())
if (is_unreadable() && !bypassUnreadable)
throw accessed_unreadable();
return typeMap[writes.type() * 3 + cache.type()];
@ -72,7 +72,7 @@ ExtStringRef RYWIterator::endKey() {
}
const KeyValueRef* RYWIterator::kv(Arena& arena) {
if (is_unreadable())
if (is_unreadable() && !bypassUnreadable)
throw accessed_unreadable();
if (writes.is_unmodified_range()) {

View File

@ -28,7 +28,7 @@
class RYWIterator {
public:
RYWIterator(SnapshotCache* snapshotCache, WriteMap* writeMap)
: cache(snapshotCache), writes(writeMap), begin_key_cmp(0), end_key_cmp(0) {}
: cache(snapshotCache), writes(writeMap), begin_key_cmp(0), end_key_cmp(0), bypassUnreadable(false) {}
enum SEGMENT_TYPE { UNKNOWN_RANGE, EMPTY_RANGE, KV };
static const SEGMENT_TYPE typeMap[12];
@ -59,6 +59,8 @@ public:
void skipContiguousBack(KeyRef key);
void bypassUnreadableProtection() { bypassUnreadable = true; }
WriteMap::iterator& extractWriteMapIterator();
// Really this should return an iterator by value, but for performance it's convenient to actually grab the internal
// one. Consider copying the return value if performance isn't critical. If you modify the returned iterator, it
@ -72,6 +74,8 @@ private:
SnapshotCache::iterator cache;
WriteMap::iterator writes;
KeyValueRef temp;
bool bypassUnreadable; // When set, allows read from sections of keyspace that have become unreadable because of
// versionstamp operations
void updateCmp();
};

View File

@ -84,6 +84,9 @@ public:
static Future<Optional<Value>> read(ReadYourWritesTransaction* ryw, GetValueReq read, Iter* it) {
// This overload is required to provide postcondition: it->extractWriteMapIterator().segmentContains(read.key)
if (ryw->options.bypassUnreadable) {
it->bypassUnreadableProtection();
}
it->skip(read.key);
state bool dependent = it->is_dependent();
if (it->is_kv()) {
@ -2232,6 +2235,10 @@ void ReadYourWritesTransaction::setOptionImpl(FDBTransactionOptions::Option opti
validateOptionValue(value, false);
options.specialKeySpaceChangeConfiguration = true;
break;
case FDBTransactionOptions::BYPASS_UNREADABLE:
validateOptionValue(value, false);
options.bypassUnreadable = true;
break;
default:
break;
}

View File

@ -42,6 +42,7 @@ struct ReadYourWritesTransactionOptions {
double timeoutInSeconds;
int maxRetries;
int snapshotRywEnabled;
bool bypassUnreadable : 1;
ReadYourWritesTransactionOptions() {}
explicit ReadYourWritesTransactionOptions(Transaction const& tr);

View File

@ -203,6 +203,7 @@ public:
bool is_empty_range() const { return type() == EMPTY_RANGE; }
bool is_dependent() const { return false; }
bool is_unreadable() const { return false; }
void bypassUnreadableProtection() {}
ExtStringRef beginKey() const {
if (offset == 0) {

View File

@ -192,6 +192,9 @@ description is not currently required but encouraged.
description="Enable tracing for all transactions. This is the default." />
<Option name="distributed_transaction_trace_disable" code="601"
description="Disable tracing for all transactions." />
<Option name="transaction_bypass_unreadable" code="700"
description="Allows ``get`` operations to read from sections of keyspace that have become unreadable because of versionstamp operations. This sets the ``bypass_unreadable`` option of each transaction created by this database. See the transaction option description for more information."
defaultFor="1100"/>
</Scope>
<Scope name="TransactionOption">
@ -284,6 +287,8 @@ description is not currently required but encouraged.
description="Adds a parent to the Span of this transaction. Used for transaction tracing. A span can be identified with any 16 bytes"/>
<Option name="expensive_clear_cost_estimation_enable" code="1000"
description="Asks storage servers for how many bytes a clear key range contains. Otherwise uses the location cache to roughly estimate this." />
<Option name="bypass_unreadable" code="1100"
description="Allows ``get`` operations to read from sections of keyspace that have become unreadable because of versionstamp operations. These reads will view versionstamp operations as if they were set operations that did not fill in the versionstamp." />
</Scope>
<!-- The enumeration values matter - do not change them without

View File

@ -313,6 +313,10 @@ struct UnreadableWorkload : TestWorkload {
state bool snapshot;
state KeySelectorRef begin;
state KeySelectorRef end;
state bool bypassUnreadable = deterministicRandom()->coinflip();
if (bypassUnreadable) {
tr.setOption(FDBTransactionOptions::BYPASS_UNREADABLE);
}
setMap[normalKeys.begin] = ValueRef();
setMap[normalKeys.end] = ValueRef();
@ -377,6 +381,9 @@ struct UnreadableWorkload : TestWorkload {
setMap = std::map<KeyRef, ValueRef>();
unreadableMap = KeyRangeMap<bool>();
tr = ReadYourWritesTransaction(cx);
if (bypassUnreadable) {
tr.setOption(FDBTransactionOptions::BYPASS_UNREADABLE);
}
arena = Arena();
setMap[normalKeys.begin] = ValueRef();
@ -421,6 +428,9 @@ struct UnreadableWorkload : TestWorkload {
setMap = std::map<KeyRef, ValueRef>();
unreadableMap = KeyRangeMap<bool>();
tr = ReadYourWritesTransaction(cx);
if (bypassUnreadable) {
tr.setOption(FDBTransactionOptions::BYPASS_UNREADABLE);
}
arena = Arena();
setMap[normalKeys.begin] = ValueRef();
@ -440,7 +450,7 @@ struct UnreadableWorkload : TestWorkload {
if (!value.isError() || value.getError().code() == error_code_accessed_unreadable) {
//TraceEvent("RYWT_Get").detail("Key", printable(key)).detail("IsUnreadable", value.isError());
if (snapshot) {
if (snapshot || bypassUnreadable) {
ASSERT(!value.isError());
} else {
ASSERT(unreadableMap[key] == value.isError());
@ -450,6 +460,9 @@ struct UnreadableWorkload : TestWorkload {
setMap = std::map<KeyRef, ValueRef>();
unreadableMap = KeyRangeMap<bool>();
tr = ReadYourWritesTransaction(cx);
if (bypassUnreadable) {
tr.setOption(FDBTransactionOptions::BYPASS_UNREADABLE);
}
arena = Arena();
setMap[normalKeys.begin] = ValueRef();