Commit 9843df7a authored by Georgios Bitzes's avatar Georgios Bitzes
Browse files

Implement TYPE command

parent 42f5ea85
Pipeline #517216 passed with stages
in 28 minutes and 43 seconds
......@@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
## Unreleased
- Updated rocksdb dependency to v5.15.10.
- Added `TYPE` command.
## 0.3.3 (2018-09-14)
......
......@@ -65,6 +65,7 @@ struct cmdMapInit {
redis_cmd_map["raw_scan"] = {RedisCommand::RAW_SCAN, CommandType::READ};
redis_cmd_map["raw_get_all_versions"] = {RedisCommand::RAW_GET_ALL_VERSIONS, CommandType::READ};
redis_cmd_map["clock_get"] = {RedisCommand::CLOCK_GET, CommandType::READ};
redis_cmd_map["type"] = {RedisCommand::TYPE, CommandType::READ};
redis_cmd_map["flushall"] = {RedisCommand::FLUSHALL, CommandType::WRITE};
redis_cmd_map["set"] = {RedisCommand::SET, CommandType::WRITE};
......
......@@ -95,6 +95,8 @@ enum class RedisCommand {
RAW_SCAN,
RAW_GET_ALL_VERSIONS,
TYPE,
EXEC,
DISCARD,
MULTI,
......
......@@ -452,6 +452,13 @@ RedisEncodedResponse RedisDispatcher::dispatchLHGET(StagingArea &stagingArea, co
RedisEncodedResponse RedisDispatcher::dispatchRead(StagingArea &stagingArea, RedisRequest &request) {
switch(request.getCommand()) {
case RedisCommand::TYPE: {
if(request.size() != 2) return errArgs(request);
std::string retval;
store.getType(stagingArea, request[1], retval);
return Formatter::status(retval);
}
case RedisCommand::GET: {
if(request.size() != 2) return errArgs(request);
......
......@@ -1257,6 +1257,11 @@ void StateMachine::getClock(StagingArea &stagingArea, ClockValue &value) {
value = binaryStringToUnsignedInt(prevValue.c_str());
}
void StateMachine::getType(StagingArea &stagingArea, std::string_view key, std::string &keyType) {
KeyDescriptor keyinfo = getKeyDescriptor(stagingArea, key);
keyType = keyTypeAsString(keyinfo.getKeyType());
}
void StateMachine::getClock(ClockValue &value) {
StagingArea stagingArea(*this, true);
getClock(stagingArea, value);
......
......@@ -118,6 +118,7 @@ public:
rocksdb::Status rawScan(StagingArea &stagingArea, const std::string &key, size_t count, std::vector<std::string> &elements);
rocksdb::Status dequeScanBack(StagingArea &stagingArea, std::string_view key, std::string_view cursor, size_t count, std::string &newCursor, std::vector<std::string> &results);
void getClock(StagingArea &stagingArea, ClockValue &value);
void getType(StagingArea &stagingArea, std::string_view key, std::string& keyType);
//----------------------------------------------------------------------------
// Simple API
......
......@@ -68,6 +68,37 @@ inline KeyType parseKeyType(char c) {
}
}
inline std::string keyTypeAsString(KeyType key) {
switch(key) {
case KeyType::kNull: {
return "none";
}
case KeyType::kParseError: {
qdb_throw("given KeyType == kParseError, not representable as string");
}
case KeyType::kString: {
return "string";
}
case KeyType::kSet: {
return "set";
}
case KeyType::kHash: {
return "hash";
}
case KeyType::kDeque: {
return "deque";
}
case KeyType::kLocalityHash: {
return "locality hash";
}
case KeyType::kLease: {
return "lease";
}
}
qdb_throw("should never reach here");
}
// Helper enum for selecting which of startIndex, endIndex to pick
enum class Direction : int {
kLeft = -1,
......
......@@ -357,6 +357,7 @@ TEST_F(Raft_e2e, test_many_redis_commands) {
std::vector<std::future<redisReplyPtr>> futures;
futures.emplace_back(tunnel(leaderID)->exec("SADD", "myset", "a", "b", "c"));
futures.emplace_back(tunnel(leaderID)->exec("TYPE", "myset"));
futures.emplace_back(tunnel(leaderID)->exec("SCARD", "myset"));
futures.emplace_back(tunnel(leaderID)->exec("Smembers", "myset"));
futures.emplace_back(tunnel(leaderID)->exec("srem", "myset", "a", "b"));
......@@ -368,17 +369,19 @@ TEST_F(Raft_e2e, test_many_redis_commands) {
futures.emplace_back(tunnel(leaderID)->exec("timestamped-lease-get", "123"));
futures.emplace_back(tunnel(leaderID)->exec("timestamped-lease-release", "123"));
ASSERT_REPLY(futures[0], 3);
ASSERT_REPLY(futures[1], 3);
ASSERT_REPLY(futures[2], make_vec("a", "b", "c"));
ASSERT_REPLY(futures[3], 2);
ASSERT_REPLY(futures[4], 0);
ASSERT_REPLY(futures[5], 1);
ASSERT_REPLY(futures[6], make_vec("c"));
ASSERT_NIL(futures[7]);
ASSERT_REPLY(futures[8], "ERR unknown command 'timestamped-lease-acquire'" );
ASSERT_REPLY(futures[9], "ERR unknown command 'timestamped-lease-get'" );
ASSERT_REPLY(futures[10], "ERR unknown command 'timestamped-lease-release'" );
size_t count = 0;
ASSERT_REPLY(futures[count++], 3);
ASSERT_REPLY(futures[count++], "set");
ASSERT_REPLY(futures[count++], 3);
ASSERT_REPLY(futures[count++], make_vec("a", "b", "c"));
ASSERT_REPLY(futures[count++], 2);
ASSERT_REPLY(futures[count++], 0);
ASSERT_REPLY(futures[count++], 1);
ASSERT_REPLY(futures[count++], make_vec("c"));
ASSERT_NIL(futures[count++]);
ASSERT_REPLY(futures[count++], "ERR unknown command 'timestamped-lease-acquire'" );
ASSERT_REPLY(futures[count++], "ERR unknown command 'timestamped-lease-get'" );
ASSERT_REPLY(futures[count++], "ERR unknown command 'timestamped-lease-release'" );
futures.clear();
......@@ -407,7 +410,7 @@ TEST_F(Raft_e2e, test_many_redis_commands) {
futures.emplace_back(tunnel(leaderID)->exec("quarkdb_invalid_command"));
futures.emplace_back(tunnel(leaderID)->exec("raft-fetch-last", "7", "raw"));
size_t count = 0;
count = 0;
ASSERT_REPLY(futures[count++], 1);
ASSERT_REPLY(futures[count++], 1);
ASSERT_REPLY(futures[count++], 1);
......
......@@ -983,6 +983,16 @@ TEST(KeyDescriptor, BasicSanity) {
ASSERT_EQ(leaseDescr.getEndIndex(), 15u);
}
TEST(KeyType, AsString) {
ASSERT_THROW(keyTypeAsString(KeyType::kParseError), FatalException);
ASSERT_EQ(keyTypeAsString(KeyType::kLease), "lease");
ASSERT_EQ(keyTypeAsString(KeyType::kString), "string");
ASSERT_EQ(keyTypeAsString(KeyType::kSet), "set");
ASSERT_EQ(keyTypeAsString(KeyType::kHash), "hash");
ASSERT_EQ(keyTypeAsString(KeyType::kLocalityHash), "locality hash");
ASSERT_EQ(keyTypeAsString(KeyType::kDeque), "deque");
}
TEST(FieldLocator, BasicSanity) {
FieldLocator locator1(KeyType::kHash, "some_key");
locator1.resetField("my_field");
......
Markdown is supported
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