Commit 2f4350bd authored by Georgios Bitzes's avatar Georgios Bitzes
Browse files

Allow scanning through the raw keyspace in rocksdb

Could come in handy for debugging.
parent a2740552
Pipeline #387711 passed with stages
in 29 minutes and 35 seconds
......@@ -57,6 +57,7 @@ struct cmdMapInit {
redis_cmd_map["lhget"] = {RedisCommand::LHGET, CommandType::READ};
redis_cmd_map["lhlen"] = {RedisCommand::LHLEN, CommandType::READ};
redis_cmd_map["lhget_with_fallback"] = {RedisCommand::LHGET_WITH_FALLBACK, CommandType::READ};
redis_cmd_map["raw_scan"] = {RedisCommand::RAW_SCAN, CommandType::READ};
redis_cmd_map["flushall"] = {RedisCommand::FLUSHALL, CommandType::WRITE};
redis_cmd_map["set"] = {RedisCommand::SET, CommandType::WRITE};
......
......@@ -84,6 +84,8 @@ enum class RedisCommand {
RPOP,
LLEN,
RAW_SCAN,
EXEC,
DISCARD,
MULTI,
......
......@@ -23,6 +23,7 @@
#include "storage/StagingArea.hh"
#include "utils/CommandParsing.hh"
#include "utils/ParseUtils.hh"
#include "redis/MultiOp.hh"
#include "redis/ArrayResponseBuilder.hh"
#include "StateMachine.hh"
......@@ -482,6 +483,30 @@ RedisEncodedResponse RedisDispatcher::dispatchRead(StagingArea &stagingArea, Red
if(!st.ok()) return Formatter::fromStatus(st);
return Formatter::integer(len);
}
case RedisCommand::RAW_SCAN: {
if(request.size() != 2 && request.size() != 4) return errArgs(request);
rocksdb::Status st;
std::vector<std::string> results;
if(request.size() == 2) {
st = store.rawScan(stagingArea, request[1], 50, results);
}
else {
if(!caseInsensitiveEquals(request[2], "count")) {
return Formatter::err("syntax error");
}
int64_t count;
if(!ParseUtils::parseInt64(request[3], count) || count <= 0) {
return Formatter::err("syntax error");
}
st = store.rawScan(stagingArea, request[1], count, results);
}
if(!st.ok()) return Formatter::fromStatus(st);
return Formatter::vector(results);
}
default: {
return dispatchingError(request, 0);
}
......
......@@ -540,6 +540,25 @@ rocksdb::Status StateMachine::lhlen(StagingArea &stagingArea, const std::string
return rocksdb::Status::OK();
}
rocksdb::Status StateMachine::rawScan(StagingArea &stagingArea, const std::string &key, size_t count, std::vector<std::string> &elements) {
elements.clear();
IteratorPtr iter(db->NewIterator(stagingArea.snapshot->opts()));
size_t items = 0;
for(iter->Seek(key); iter->Valid(); iter->Next()) {
DBG(items);
if(items >= 1000000u || items >= count) break;
items++;
elements.emplace_back(iter->key().ToString());
elements.emplace_back(iter->value().ToString());
}
return rocksdb::Status::OK();
}
rocksdb::Status StateMachine::hscan(StagingArea &stagingArea, const std::string &key, const std::string &cursor, size_t count, std::string &newCursor, std::vector<std::string> &res) {
if(!assertKeyType(stagingArea, key, KeyType::kHash)) return wrong_type();
......
......@@ -98,6 +98,7 @@ public:
rocksdb::Status llen(StagingArea &stagingArea, const std::string &key, size_t &len);
rocksdb::Status lhget(StagingArea &stagingArea, const std::string &key, const std::string &field, const std::string &hint, std::string &value);
rocksdb::Status lhlen(StagingArea &stagingArea, const std::string &key, size_t &len);
rocksdb::Status rawScan(StagingArea &stagingArea, const std::string &key, size_t count, std::vector<std::string> &elements);
//----------------------------------------------------------------------------
// Simple API
......
......@@ -1128,4 +1128,31 @@ TEST_F(Raft_e2e, LocalityHash) {
ASSERT_REPLY(tunnel(leaderID)->exec("lhlen", "mykey"), 3);
ASSERT_REPLY(tunnel(leaderID)->exec("hlen", "fb"), 0);
ASSERT_REPLY(tunnel(leaderID)->exec("hget", "fb", "f8"), "");
redisReplyPtr reply = tunnel(leaderID)->exec("raw-scan", "\x01", "count", "2000").get();
ASSERT_EQ(
qclient::describeRedisReply(reply),
"1) \"!mykey\"\n"
"2) \"e\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\"\n"
"3) \"__format\"\n"
"4) \"0\"\n"
"5) \"__in-bulkload\"\n"
"6) \"FALSE\"\n"
"7) \"__last-applied\"\n"
"8) \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\"\n"
"9) \"emykey##dhint1##f3\"\n"
"10) \"v6\"\n"
"11) \"emykey##dhint2##f2\"\n"
"12) \"v5\"\n"
"13) \"emykey##dhint3##f1\"\n"
"14) \"v3\"\n"
"15) \"emykey##if1\"\n"
"16) \"hint3\"\n"
"17) \"emykey##if2\"\n"
"18) \"hint2\"\n"
"19) \"emykey##if3\"\n"
"20) \"hint1\"\n"
);
qdb_info(qclient::describeRedisReply(reply));
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment