DBRedis: Move some common code into macros

This commit is contained in:
sfan5 2016-10-21 21:11:46 +02:00
parent 9bbc4466ef
commit 89ed5494cc
1 changed files with 21 additions and 19 deletions

View File

@ -7,6 +7,11 @@
#define DB_REDIS_HMGET_NUMFIELDS 30 #define DB_REDIS_HMGET_NUMFIELDS 30
#define REPLY_TYPE_ERR(reply, desc) do { \
throw std::runtime_error(std::string("Unexpected type for " desc ": ") \
+ replyTypeStr((reply)->type)); \
} while(0)
static inline int64_t stoi64(const std::string &s) static inline int64_t stoi64(const std::string &s)
{ {
std::stringstream tmp(s); std::stringstream tmp(s);
@ -88,7 +93,7 @@ std::string DBRedis::replyTypeStr(int type) {
case REDIS_REPLY_ARRAY: case REDIS_REPLY_ARRAY:
return "REDIS_REPLY_ARRAY"; return "REDIS_REPLY_ARRAY";
default: default:
return "UNKNOWN_REPLY_TYPE"; return "unknown";
} }
} }
@ -98,12 +103,12 @@ void DBRedis::loadPosCache()
redisReply *reply; redisReply *reply;
reply = (redisReply*) redisCommand(ctx, "HKEYS %s", hash.c_str()); reply = (redisReply*) redisCommand(ctx, "HKEYS %s", hash.c_str());
if(!reply) if(!reply)
throw std::runtime_error(std::string("redis command 'HKEYS %s' failed: ") + ctx->errstr); throw std::runtime_error("Redis command HKEYS failed");
if(reply->type != REDIS_REPLY_ARRAY) if(reply->type != REDIS_REPLY_ARRAY)
throw std::runtime_error("Failed to get keys from database"); REPLY_TYPE_ERR(reply, "HKEYS reply");
for(size_t i = 0; i < reply->elements; i++) { for(size_t i = 0; i < reply->elements; i++) {
if(reply->element[i]->type != REDIS_REPLY_STRING) if(reply->element[i]->type != REDIS_REPLY_STRING)
throw std::runtime_error("Got wrong response to 'HKEYS %s' command"); REPLY_TYPE_ERR(reply->element[i], "HKEYS subreply");
posCache.push_back(decodeBlockPos(stoi64(reply->element[i]->str))); posCache.push_back(decodeBlockPos(stoi64(reply->element[i]->str)));
} }
@ -122,24 +127,23 @@ void DBRedis::HMGET(const std::vector<BlockPos> &positions, std::vector<ustring>
while (remaining > 0) { while (remaining > 0) {
const std::size_t batch_size = const std::size_t batch_size =
(remaining > DB_REDIS_HMGET_NUMFIELDS) ? DB_REDIS_HMGET_NUMFIELDS : remaining; (remaining > DB_REDIS_HMGET_NUMFIELDS) ? DB_REDIS_HMGET_NUMFIELDS : remaining;
redisReply *reply; redisReply *reply;
{ {
// storage to preserve std::string::c_str() validity // storage to preserve validity of .c_str()
std::vector<std::string> keys; std::string keys[batch_size];
keys.reserve(batch_size);
for (std::size_t i = 0; i < batch_size; ++i) { for (std::size_t i = 0; i < batch_size; ++i) {
keys.push_back(i64tos(encodeBlockPos(*position++))); keys[i] = i64tos(encodeBlockPos(*position++));
argv[i+2] = keys.back().c_str(); argv[i+2] = keys[i].c_str();
} }
reply = (redisReply*) redisCommandArgv(ctx, batch_size + 2, argv, NULL); reply = (redisReply*) redisCommandArgv(ctx, batch_size + 2, argv, NULL);
} }
if(!reply) {
throw std::runtime_error("HMGET failed"); if(!reply)
} throw std::runtime_error("Redis command HMGET failed");
if (reply->type != REDIS_REPLY_ARRAY) { if (reply->type != REDIS_REPLY_ARRAY) {
freeReplyObject(reply); freeReplyObject(reply);
throw std::runtime_error(std::string("HMGET unexpected reply type ") REPLY_TYPE_ERR(reply, "HKEYS subreply");
+ replyTypeStr(reply->type));
} }
if (reply->elements != batch_size) { if (reply->elements != batch_size) {
freeReplyObject(reply); freeReplyObject(reply);
@ -147,13 +151,11 @@ void DBRedis::HMGET(const std::vector<BlockPos> &positions, std::vector<ustring>
} }
for (std::size_t i = 0; i < batch_size; ++i) { for (std::size_t i = 0; i < batch_size; ++i) {
redisReply *subreply = reply->element[i]; redisReply *subreply = reply->element[i];
if(!subreply) { if(!subreply)
throw std::runtime_error("HMGET failed"); throw std::runtime_error("Redis command HMGET failed");
}
if (subreply->type != REDIS_REPLY_STRING) { if (subreply->type != REDIS_REPLY_STRING) {
freeReplyObject(reply); freeReplyObject(reply);
throw std::runtime_error(std::string("HMGET wrong subreply type ") REPLY_TYPE_ERR(reply, "HKEYS subreply");
+ replyTypeStr(subreply->type));
} }
if (subreply->len == 0) { if (subreply->len == 0) {
freeReplyObject(reply); freeReplyObject(reply);