mirror of
https://github.com/minetest/minetestmapper.git
synced 2024-11-22 15:33:49 +01:00
DBRedis: add HMGET
Redis HMGET command allows to query multiple fields in the same request. Limit to a maximum of DB_REDIS_HMGET_NUMKEYS fields per HMGET request.
This commit is contained in:
parent
53706e811b
commit
fabde97847
58
db-redis.cpp
58
db-redis.cpp
@ -5,6 +5,8 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#define DB_REDIS_HMGET_NUMFIELDS 30
|
||||||
|
|
||||||
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);
|
||||||
@ -109,6 +111,62 @@ void DBRedis::loadPosCache()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DBRedis::HMGET(const std::vector<BlockPos> &positions, std::vector<ustring> *result)
|
||||||
|
{
|
||||||
|
const char *argv[DB_REDIS_HMGET_NUMFIELDS + 2];
|
||||||
|
argv[0] = "HMGET";
|
||||||
|
argv[1] = hash.c_str();
|
||||||
|
|
||||||
|
std::vector<BlockPos>::const_iterator position = positions.begin();
|
||||||
|
std::size_t remaining = positions.size();
|
||||||
|
while (remaining > 0) {
|
||||||
|
const std::size_t batch_size =
|
||||||
|
(remaining > DB_REDIS_HMGET_NUMFIELDS) ? DB_REDIS_HMGET_NUMFIELDS : remaining;
|
||||||
|
redisReply *reply;
|
||||||
|
{
|
||||||
|
// storage to preserve std::string::c_str() validity
|
||||||
|
std::vector<std::string> keys;
|
||||||
|
keys.reserve(batch_size);
|
||||||
|
for (std::size_t i = 0; i < batch_size; ++i) {
|
||||||
|
keys.push_back(i64tos(encodeBlockPos(*position++)));
|
||||||
|
argv[i+2] = keys.back().c_str();
|
||||||
|
}
|
||||||
|
reply = (redisReply*) redisCommandArgv(ctx, batch_size + 2, argv, NULL);
|
||||||
|
}
|
||||||
|
if(!reply) {
|
||||||
|
throw std::runtime_error("HMGET failed");
|
||||||
|
}
|
||||||
|
if (reply->type != REDIS_REPLY_ARRAY) {
|
||||||
|
freeReplyObject(reply);
|
||||||
|
throw std::runtime_error(std::string("HMGET unexpected reply type ")
|
||||||
|
+ replyTypeStr(reply->type));
|
||||||
|
}
|
||||||
|
if (reply->elements != batch_size) {
|
||||||
|
freeReplyObject(reply);
|
||||||
|
throw std::runtime_error("HMGET wrong number of elements");
|
||||||
|
}
|
||||||
|
for (std::size_t i = 0; i < batch_size; ++i) {
|
||||||
|
redisReply *subreply = reply->element[i];
|
||||||
|
if(!subreply) {
|
||||||
|
throw std::runtime_error("HMGET failed");
|
||||||
|
}
|
||||||
|
if (subreply->type != REDIS_REPLY_STRING) {
|
||||||
|
freeReplyObject(reply);
|
||||||
|
throw std::runtime_error(std::string("HMGET wrong subreply type ")
|
||||||
|
+ replyTypeStr(subreply->type));
|
||||||
|
}
|
||||||
|
if (subreply->len == 0) {
|
||||||
|
freeReplyObject(reply);
|
||||||
|
throw std::runtime_error("HMGET empty string");
|
||||||
|
}
|
||||||
|
result->push_back(ustring((const unsigned char *) subreply->str, subreply->len));
|
||||||
|
}
|
||||||
|
freeReplyObject(reply);
|
||||||
|
remaining -= batch_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DBRedis::getBlocksOnZ(std::map<int16_t, BlockList> &blocks, int16_t zPos)
|
void DBRedis::getBlocksOnZ(std::map<int16_t, BlockList> &blocks, int16_t zPos)
|
||||||
{
|
{
|
||||||
redisReply *reply;
|
redisReply *reply;
|
||||||
|
@ -14,6 +14,7 @@ private:
|
|||||||
static std::string replyTypeStr(int type);
|
static std::string replyTypeStr(int type);
|
||||||
|
|
||||||
void loadPosCache();
|
void loadPosCache();
|
||||||
|
void HMGET(const std::vector<BlockPos> &positions, std::vector<ustring> *result);
|
||||||
|
|
||||||
std::vector<BlockPos> posCache;
|
std::vector<BlockPos> posCache;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user