add a parameter indicating whether keys are prefixed with \xff\xff

This commit is contained in:
chaoguang 2020-04-07 00:08:47 -07:00
parent 8b46326713
commit 86c66a4fca
3 changed files with 38 additions and 31 deletions

View File

@ -64,19 +64,16 @@ ACTOR Future<Void> SpecialKeyRangeBaseImpl::normalizeKeySelectorActor(const Spec
ACTOR Future<Standalone<RangeResultRef>> SpecialKeySpace::getRangeAggregationActor(
SpecialKeySpace* pks, Reference<ReadYourWritesTransaction> ryw, KeySelector begin, KeySelector end,
GetRangeLimits limits, bool reverse) {
GetRangeLimits limits, bool reverse, bool withPrefix) {
// This function handles ranges which cover more than one keyrange and aggregates all results
// KeySelector, GetRangeLimits and reverse are all handled here
state Standalone<RangeResultRef> result;
state RangeMap<Key, SpecialKeyRangeBaseImpl*, KeyRangeRef>::Iterator iter;
state int actualBeginOffset;
state int actualEndOffset;
state bool prefixFlag = false;
// remove specialKeys prefix
if (begin.getKey().startsWith(specialKeys.begin)) {
prefixFlag = true;
ASSERT(end.getKey().startsWith(specialKeys.begin));
if (withPrefix) {
begin.setKey(begin.getKey().removePrefix(specialKeys.begin));
end.setKey(end.getKey().removePrefix(specialKeys.begin));
}
@ -157,11 +154,12 @@ ACTOR Future<Standalone<RangeResultRef>> SpecialKeySpace::getRangeAggregationAct
KeyRef keyStart = kr.contains(begin.getKey()) ? begin.getKey() : kr.begin;
KeyRef keyEnd = kr.contains(end.getKey()) ? end.getKey() : kr.end;
Standalone<RangeResultRef> pairs = wait(iter->value()->getRange(ryw, KeyRangeRef(keyStart, keyEnd)));
result.arena().dependsOn(pairs.arena());
// limits handler
for (int i = pairs.size() - 1; i >= 0; --i) {
// TODO : use depends on with push_back
KeyValueRef element =
prefixFlag ? KeyValueRef(pairs[i].key.withPrefix(specialKeys.begin, result.arena()), pairs[i].value)
withPrefix ? KeyValueRef(pairs[i].key.withPrefix(specialKeys.begin, result.arena()), pairs[i].value)
: pairs[i];
result.push_back(result.arena(), element);
// Note : behavior here is even the last k-v pair makes total bytes larger than specified, it is still
@ -182,11 +180,12 @@ ACTOR Future<Standalone<RangeResultRef>> SpecialKeySpace::getRangeAggregationAct
KeyRef keyStart = kr.contains(begin.getKey()) ? begin.getKey() : kr.begin;
KeyRef keyEnd = kr.contains(end.getKey()) ? end.getKey() : kr.end;
Standalone<RangeResultRef> pairs = wait(iter->value()->getRange(ryw, KeyRangeRef(keyStart, keyEnd)));
result.arena().dependsOn(pairs.arena());
// limits handler
for (int i = 0; i < pairs.size(); ++i) {
// TODO : use depends on with push_back
KeyValueRef element =
prefixFlag ? KeyValueRef(pairs[i].key.withPrefix(specialKeys.begin, result.arena()), pairs[i].value)
withPrefix ? KeyValueRef(pairs[i].key.withPrefix(specialKeys.begin, result.arena()), pairs[i].value)
: pairs[i];
result.push_back(result.arena(), element);
// Note : behavior here is even the last k-v pair makes total bytes larger than specified, it is still
@ -206,26 +205,28 @@ ACTOR Future<Standalone<RangeResultRef>> SpecialKeySpace::getRangeAggregationAct
Future<Standalone<RangeResultRef>> SpecialKeySpace::getRange(Reference<ReadYourWritesTransaction> ryw,
KeySelector begin, KeySelector end, GetRangeLimits limits,
bool reverse) {
bool reverse, bool withPrefix) {
// validate limits here
if (!limits.isValid()) return range_limits_invalid();
if (limits.isReached()) {
TEST(true); // read limit 0
return Standalone<RangeResultRef>();
}
if (withPrefix)
ASSERT(begin.getKey().startsWith(specialKeys.begin) && end.getKey().startsWith(specialKeys.begin));
// make sure orEqual == false
begin.removeOrEqual(begin.arena());
end.removeOrEqual(end.arena());
return getRangeAggregationActor(this, ryw, begin, end, limits, reverse);
return getRangeAggregationActor(this, ryw, begin, end, limits, reverse, withPrefix);
}
ACTOR Future<Optional<Value>> SpecialKeySpace::getActor(SpecialKeySpace* pks, Reference<ReadYourWritesTransaction> ryw,
KeyRef key) {
KeyRef key, bool withPrefix) {
// use getRange to workaround this
Standalone<RangeResultRef> result =
wait(pks->getRange(ryw, KeySelector(firstGreaterOrEqual(key)), KeySelector(firstGreaterOrEqual(keyAfter(key))),
GetRangeLimits(CLIENT_KNOBS->TOO_MANY)));
GetRangeLimits(CLIENT_KNOBS->TOO_MANY), false, withPrefix));
ASSERT(result.size() <= 1);
if (result.size()) {
return Optional<Value>(result[0].value);
@ -234,8 +235,9 @@ ACTOR Future<Optional<Value>> SpecialKeySpace::getActor(SpecialKeySpace* pks, Re
}
}
Future<Optional<Value>> SpecialKeySpace::get(Reference<ReadYourWritesTransaction> ryw, const Key& key) {
return getActor(this, ryw, key);
Future<Optional<Value>> SpecialKeySpace::get(Reference<ReadYourWritesTransaction> ryw, const Key& key,
bool withPrefix) {
return getActor(this, ryw, key, withPrefix);
}
ConflictingKeysImpl::ConflictingKeysImpl(KeyRef start, KeyRef end) : SpecialKeyRangeBaseImpl(start, end) {}
@ -291,11 +293,11 @@ private:
};
TEST_CASE("/fdbclient/SpecialKeySpace/Unittest") {
SpecialKeySpace pks(LiteralStringRef("\xff\xff"), LiteralStringRef("\xff\xff\xff"));
SpecialKeyRangeTestImpl pkr1(LiteralStringRef("\xff\xff/cat/"), LiteralStringRef("\xff\xff/cat/\xff"), "small", 10);
SpecialKeyRangeTestImpl pkr2(LiteralStringRef("\xff\xff/dog/"), LiteralStringRef("\xff\xff/dog/\xff"), "medium",
SpecialKeySpace pks(normalKeys.begin, normalKeys.end);
SpecialKeyRangeTestImpl pkr1(LiteralStringRef("/cat/"), LiteralStringRef("/cat/\xff"), "small", 10);
SpecialKeyRangeTestImpl pkr2(LiteralStringRef("/dog/"), LiteralStringRef("/dog/\xff"), "medium",
100);
SpecialKeyRangeTestImpl pkr3(LiteralStringRef("\xff\xff/pig/"), LiteralStringRef("\xff\xff/pig/\xff"), "large",
SpecialKeyRangeTestImpl pkr3(LiteralStringRef("/pig/"), LiteralStringRef("/pig/\xff"), "large",
1000);
pks.registerKeyRange(pkr1.getKeyRange(), &pkr1);
pks.registerKeyRange(pkr2.getKeyRange(), &pkr2);
@ -303,20 +305,20 @@ TEST_CASE("/fdbclient/SpecialKeySpace/Unittest") {
auto nullRef = Reference<ReadYourWritesTransaction>();
// get
{
auto resultFuture = pks.get(nullRef, LiteralStringRef("\xff\xff/cat/small0000000009"));
auto resultFuture = pks.get(nullRef, LiteralStringRef("/cat/small0000000009"), false);
ASSERT(resultFuture.isReady());
auto result = resultFuture.getValue().get();
ASSERT(result == pkr1.getKeyValueForIndex(9).value);
auto emptyFuture = pks.get(nullRef, LiteralStringRef("\xff\xff/cat/small0000000010"));
auto emptyFuture = pks.get(nullRef, LiteralStringRef("/cat/small0000000010"), false);
ASSERT(emptyFuture.isReady());
auto emptyResult = emptyFuture.getValue();
ASSERT(!emptyResult.present());
}
// general getRange
{
KeySelector start = KeySelectorRef(LiteralStringRef("\xff\xff/elepant"), false, -9);
KeySelector end = KeySelectorRef(LiteralStringRef("\xff\xff/frog"), false, +11);
auto resultFuture = pks.getRange(nullRef, start, end, GetRangeLimits());
KeySelector start = KeySelectorRef(LiteralStringRef("/elepant"), false, -9);
KeySelector end = KeySelectorRef(LiteralStringRef("/frog"), false, +11);
auto resultFuture = pks.getRange(nullRef, start, end, GetRangeLimits(), false, false);
ASSERT(resultFuture.isReady());
auto result = resultFuture.getValue();
ASSERT(result.size() == 20);
@ -327,7 +329,7 @@ TEST_CASE("/fdbclient/SpecialKeySpace/Unittest") {
{
KeySelector start = KeySelectorRef(pkr3.getKeyForIndex(999), true, -1110);
KeySelector end = KeySelectorRef(pkr1.getKeyForIndex(0), false, +1112);
auto resultFuture = pks.getRange(nullRef, start, end, GetRangeLimits());
auto resultFuture = pks.getRange(nullRef, start, end, GetRangeLimits(), false, false);
ASSERT(resultFuture.isReady());
auto result = resultFuture.getValue();
ASSERT(result.size() == 1110);
@ -338,7 +340,7 @@ TEST_CASE("/fdbclient/SpecialKeySpace/Unittest") {
{
KeySelector start = KeySelectorRef(pkr2.getKeyForIndex(0), true, 0);
KeySelector end = KeySelectorRef(pkr3.getKeyForIndex(0), false, 0);
auto resultFuture = pks.getRange(nullRef, start, end, GetRangeLimits(2));
auto resultFuture = pks.getRange(nullRef, start, end, GetRangeLimits(2), false, false);
ASSERT(resultFuture.isReady());
auto result = resultFuture.getValue();
ASSERT(result.size() == 2);
@ -349,7 +351,7 @@ TEST_CASE("/fdbclient/SpecialKeySpace/Unittest") {
{
KeySelector start = KeySelectorRef(pkr2.getKeyForIndex(0), true, 0);
KeySelector end = KeySelectorRef(pkr3.getKeyForIndex(0), false, 0);
auto resultFuture = pks.getRange(nullRef, start, end, GetRangeLimits(10, 100));
auto resultFuture = pks.getRange(nullRef, start, end, GetRangeLimits(10, 100), false, false);
ASSERT(resultFuture.isReady());
auto result = resultFuture.getValue();
int bytes = 0;
@ -361,7 +363,7 @@ TEST_CASE("/fdbclient/SpecialKeySpace/Unittest") {
{
KeySelector start = KeySelectorRef(pkr2.getKeyForIndex(0), true, 0);
KeySelector end = KeySelectorRef(pkr3.getKeyForIndex(999), true, +1);
auto resultFuture = pks.getRange(nullRef, start, end, GetRangeLimits(1100), true);
auto resultFuture = pks.getRange(nullRef, start, end, GetRangeLimits(1100), true, false);
ASSERT(resultFuture.isReady());
auto result = resultFuture.getValue();
for (int i = 0; i < pkr3.getSize(); ++i) ASSERT(result[i] == pkr3.getKeyValueForIndex(pkr3.getSize() - 1 - i));

View File

@ -32,10 +32,13 @@ protected:
class SpecialKeySpace {
public:
Future<Optional<Value>> get(Reference<ReadYourWritesTransaction> ryw, const Key& key);
// withPrefix is true if the passing keys are prefixed with \xff\xff (cases from RYW),
// otherwise, false(cases from tests)
Future<Optional<Value>> get(Reference<ReadYourWritesTransaction> ryw, const Key& key, bool withPrefix = true);
Future<Standalone<RangeResultRef>> getRange(Reference<ReadYourWritesTransaction> ryw, KeySelector begin,
KeySelector end, GetRangeLimits limits, bool reverse = false);
KeySelector end, GetRangeLimits limits, bool reverse = false,
bool withPrefix = true);
SpecialKeySpace(KeyRef spaceStartKey = Key(), KeyRef spaceEndKey = normalKeys.end) {
// Default value is nullptr, begin of KeyRangeMap is Key()
@ -49,12 +52,14 @@ public:
}
private:
ACTOR Future<Optional<Value>> getActor(SpecialKeySpace* pks, Reference<ReadYourWritesTransaction> ryw, KeyRef key);
ACTOR Future<Optional<Value>> getActor(SpecialKeySpace* pks, Reference<ReadYourWritesTransaction> ryw, KeyRef key,
bool withPrefix);
ACTOR Future<Standalone<RangeResultRef>> getRangeAggregationActor(SpecialKeySpace* pks,
Reference<ReadYourWritesTransaction> ryw,
KeySelector begin, KeySelector end,
GetRangeLimits limits, bool reverse);
GetRangeLimits limits, bool reverse,
bool withPrefix);
KeyRangeMap<SpecialKeyRangeBaseImpl*> impls;
KeyRange range;

View File

@ -90,7 +90,7 @@ struct SpecialKeySpaceCorrectnessWorkload : TestWorkload {
auto correctResultFuture = self->ryw->getRange(begin, end, limit, false, reverse);
ASSERT(correctResultFuture.isReady());
auto correctResult = correctResultFuture.getValue();
auto testResultFuture = cx->specialKeySpace->getRange(self->ryw, begin, end, limit, reverse);
auto testResultFuture = cx->specialKeySpace->getRange(self->ryw, begin, end, limit, reverse, false);
ASSERT(testResultFuture.isReady());
auto testResult = testResultFuture.getValue();