2017-05-26 04:48:44 +08:00
|
|
|
/*
|
|
|
|
* RYWIterator.h
|
|
|
|
*
|
|
|
|
* This source file is part of the FoundationDB open source project
|
|
|
|
*
|
2022-03-22 04:36:23 +08:00
|
|
|
* Copyright 2013-2022 Apple Inc. and the FoundationDB project authors
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef FDBCLIENT_RYWITERATOR_H
|
|
|
|
#define FDBCLIENT_RYWITERATOR_H
|
|
|
|
#pragma once
|
|
|
|
|
2018-10-20 01:30:13 +08:00
|
|
|
#include "fdbclient/SnapshotCache.h"
|
|
|
|
#include "fdbclient/WriteMap.h"
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
class RYWIterator {
|
|
|
|
public:
|
2021-03-11 02:06:03 +08:00
|
|
|
RYWIterator(SnapshotCache* snapshotCache, WriteMap* writeMap)
|
2021-07-23 13:48:27 +08:00
|
|
|
: begin_key_cmp(0), end_key_cmp(0), cache(snapshotCache), writes(writeMap), bypassUnreadable(false) {}
|
2021-03-11 02:06:03 +08:00
|
|
|
|
2017-05-26 04:48:44 +08:00
|
|
|
enum SEGMENT_TYPE { UNKNOWN_RANGE, EMPTY_RANGE, KV };
|
|
|
|
static const SEGMENT_TYPE typeMap[12];
|
|
|
|
|
2020-06-18 05:45:38 +08:00
|
|
|
SEGMENT_TYPE type() const;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2020-06-18 05:45:38 +08:00
|
|
|
bool is_kv() const;
|
|
|
|
bool is_unknown_range() const;
|
|
|
|
bool is_empty_range() const;
|
|
|
|
bool is_unreadable() const;
|
|
|
|
bool is_dependent() const;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
ExtStringRef beginKey();
|
|
|
|
ExtStringRef endKey();
|
|
|
|
|
2022-03-11 02:05:44 +08:00
|
|
|
virtual const KeyValueRef* kv(Arena& arena);
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
RYWIterator& operator++();
|
|
|
|
|
|
|
|
RYWIterator& operator--();
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
bool operator==(const RYWIterator& r) const;
|
2020-07-11 05:37:47 +08:00
|
|
|
bool operator!=(const RYWIterator& r) const;
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
void skip(KeyRef key);
|
|
|
|
|
|
|
|
void skipContiguous(KeyRef key);
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
void skipContiguousBack(KeyRef key);
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-04-29 07:22:34 +08:00
|
|
|
void bypassUnreadableProtection() { bypassUnreadable = true; }
|
|
|
|
|
2022-03-11 02:05:44 +08:00
|
|
|
virtual WriteMap::iterator& extractWriteMapIterator();
|
2021-03-11 02:06:03 +08:00
|
|
|
// 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
|
|
|
|
// invalidates this iterator until the next call to skip()
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
void dbg();
|
|
|
|
|
2022-03-11 02:05:44 +08:00
|
|
|
protected:
|
2021-03-11 02:06:03 +08:00
|
|
|
int begin_key_cmp; // -1 if cache.beginKey() < writes.beginKey(), 0 if ==, +1 if >
|
|
|
|
int end_key_cmp; //
|
2017-05-26 04:48:44 +08:00
|
|
|
SnapshotCache::iterator cache;
|
|
|
|
WriteMap::iterator writes;
|
|
|
|
KeyValueRef temp;
|
2021-05-05 00:26:09 +08:00
|
|
|
bool bypassUnreadable; // When set, allows read from sections of keyspace that have become unreadable because of
|
|
|
|
// versionstamp operations
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
void updateCmp();
|
|
|
|
};
|
|
|
|
|
|
|
|
class RandomTestImpl {
|
|
|
|
public:
|
|
|
|
static ValueRef getRandomValue(Arena& arena) {
|
2019-05-11 05:01:52 +08:00
|
|
|
return ValueRef(arena, std::string(deterministicRandom()->randomInt(0, 1000), 'x'));
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static ValueRef getRandomVersionstampValue(Arena& arena) {
|
2019-05-11 05:01:52 +08:00
|
|
|
int len = deterministicRandom()->randomInt(10, 98);
|
2018-02-16 13:35:00 +08:00
|
|
|
std::string value = std::string(len, 'x');
|
2019-05-11 05:01:52 +08:00
|
|
|
int32_t pos = deterministicRandom()->randomInt(0, len - 9);
|
|
|
|
if (deterministicRandom()->random01() < 0.01) {
|
2018-02-16 13:35:00 +08:00
|
|
|
pos = value.size() - 10;
|
|
|
|
}
|
2018-02-24 10:17:53 +08:00
|
|
|
pos = littleEndian32(pos);
|
|
|
|
value += std::string((const char*)&pos, sizeof(int32_t));
|
2018-02-16 13:35:00 +08:00
|
|
|
return ValueRef(arena, value);
|
|
|
|
}
|
|
|
|
|
2017-05-26 04:48:44 +08:00
|
|
|
static ValueRef getRandomVersionstampKey(Arena& arena) {
|
2019-05-11 05:01:52 +08:00
|
|
|
int idx = deterministicRandom()->randomInt(0, 100);
|
2017-05-26 04:48:44 +08:00
|
|
|
std::string key = format("%010d", idx / 3);
|
|
|
|
if (idx % 3 >= 1)
|
|
|
|
key += '\x00';
|
|
|
|
if (idx % 3 >= 2)
|
|
|
|
key += '\x00';
|
2019-05-11 05:01:52 +08:00
|
|
|
int32_t pos = key.size() - deterministicRandom()->randomInt(0, 3);
|
|
|
|
if (deterministicRandom()->random01() < 0.01) {
|
2017-05-26 04:48:44 +08:00
|
|
|
pos = 0;
|
|
|
|
}
|
|
|
|
key = key.substr(0, pos);
|
|
|
|
key += "XXXXXXXXYY";
|
2019-05-11 05:01:52 +08:00
|
|
|
key += std::string(deterministicRandom()->randomInt(0, 3), 'z');
|
2018-03-22 09:58:19 +08:00
|
|
|
pos = littleEndian32(pos);
|
|
|
|
key += std::string((const char*)&pos, sizeof(int32_t));
|
2017-05-26 04:48:44 +08:00
|
|
|
return ValueRef(arena, key);
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
static KeyRef getRandomKey(Arena& arena) { return getKeyForIndex(arena, deterministicRandom()->randomInt(0, 100)); }
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
static KeyRef getKeyForIndex(Arena& arena, int idx) {
|
|
|
|
std::string key = format("%010d", idx / 3);
|
|
|
|
if (idx % 3 >= 1)
|
|
|
|
key += '\x00';
|
|
|
|
if (idx % 3 >= 2)
|
|
|
|
key += '\x00';
|
|
|
|
return KeyRef(arena, key);
|
|
|
|
}
|
|
|
|
|
|
|
|
static KeyRangeRef getRandomRange(Arena& arena) {
|
2019-05-11 05:01:52 +08:00
|
|
|
int startLocation = deterministicRandom()->randomInt(0, 100);
|
|
|
|
int endLocation = startLocation + deterministicRandom()->randomInt(1, 1 + 100 - startLocation);
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
return KeyRangeRef(getKeyForIndex(arena, startLocation), getKeyForIndex(arena, endLocation));
|
|
|
|
}
|
|
|
|
|
|
|
|
static KeySelectorRef getRandomKeySelector(Arena& arena) {
|
2021-03-11 02:06:03 +08:00
|
|
|
return KeySelectorRef(
|
|
|
|
getRandomKey(arena), deterministicRandom()->random01() < 0.5, deterministicRandom()->randomInt(-10, 10));
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void testESR();
|
|
|
|
void testSnapshotCache();
|
|
|
|
|
2018-02-16 13:35:00 +08:00
|
|
|
#endif
|