mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-10 18:05:44 +02:00
refactor: add cluster namespace (#2948)
* refactor: add cluster namespace, remove extra includes
This commit is contained in:
parent
1a5eacca87
commit
2230397a12
43 changed files with 330 additions and 297 deletions
|
@ -52,7 +52,7 @@ add_library(dragonfly_lib bloom_family.cc engine_shard_set.cc channel_store.cc
|
||||||
zset_family.cc version.cc bitops_family.cc container_utils.cc io_utils.cc
|
zset_family.cc version.cc bitops_family.cc container_utils.cc io_utils.cc
|
||||||
top_keys.cc multi_command_squasher.cc hll_family.cc cluster/cluster_config.cc
|
top_keys.cc multi_command_squasher.cc hll_family.cc cluster/cluster_config.cc
|
||||||
cluster/cluster_family.cc cluster/incoming_slot_migration.cc
|
cluster/cluster_family.cc cluster/incoming_slot_migration.cc
|
||||||
cluster/outgoing_slot_migration.cc
|
cluster/outgoing_slot_migration.cc cluster/cluster_defs.cc
|
||||||
acl/user.cc acl/user_registry.cc acl/acl_family.cc
|
acl/user.cc acl/user_registry.cc acl/acl_family.cc
|
||||||
acl/validator.cc acl/helpers.cc)
|
acl/validator.cc acl/helpers.cc)
|
||||||
|
|
||||||
|
|
|
@ -1,64 +1,17 @@
|
||||||
#include <optional>
|
#include "cluster_config.h"
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "redis/crc16.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <absl/container/flat_hash_set.h>
|
#include <absl/container/flat_hash_set.h>
|
||||||
|
|
||||||
#include <jsoncons/json.hpp>
|
#include <jsoncons/json.hpp>
|
||||||
#include <shared_mutex>
|
#include <optional>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include "absl/strings/match.h"
|
|
||||||
#include "base/flags.h"
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "cluster_config.h"
|
|
||||||
#include "core/json/json_object.h"
|
#include "core/json/json_object.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
ABSL_FLAG(string, cluster_mode, "", "Cluster mode supported. Default: \"\"");
|
namespace dfly::cluster {
|
||||||
|
|
||||||
namespace dfly {
|
|
||||||
namespace {
|
|
||||||
enum class ClusterMode {
|
|
||||||
kUninitialized,
|
|
||||||
kNoCluster,
|
|
||||||
kEmulatedCluster,
|
|
||||||
kRealCluster,
|
|
||||||
};
|
|
||||||
|
|
||||||
ClusterMode cluster_mode = ClusterMode::kUninitialized;
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void ClusterConfig::Initialize() {
|
|
||||||
string cluster_mode_str = absl::GetFlag(FLAGS_cluster_mode);
|
|
||||||
|
|
||||||
if (cluster_mode_str == "emulated") {
|
|
||||||
cluster_mode = ClusterMode::kEmulatedCluster;
|
|
||||||
} else if (cluster_mode_str == "yes") {
|
|
||||||
cluster_mode = ClusterMode::kRealCluster;
|
|
||||||
} else if (cluster_mode_str.empty()) {
|
|
||||||
cluster_mode = ClusterMode::kNoCluster;
|
|
||||||
} else {
|
|
||||||
LOG(ERROR) << "Invalid value for flag --cluster_mode. Exiting...";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClusterConfig::IsEnabled() {
|
|
||||||
return cluster_mode == ClusterMode::kRealCluster;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClusterConfig::IsEmulated() {
|
|
||||||
return cluster_mode == ClusterMode::kEmulatedCluster;
|
|
||||||
}
|
|
||||||
|
|
||||||
SlotId ClusterConfig::KeySlot(string_view key) {
|
|
||||||
string_view tag = LockTagOptions::instance().Tag(key);
|
|
||||||
return crc16(tag.data(), tag.length()) & kMaxSlotNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
bool HasValidNodeIds(const ClusterShardInfos& new_config) {
|
bool HasValidNodeIds(const ClusterShardInfos& new_config) {
|
||||||
|
@ -87,7 +40,7 @@ bool HasValidNodeIds(const ClusterShardInfos& new_config) {
|
||||||
|
|
||||||
bool IsConfigValid(const ClusterShardInfos& new_config) {
|
bool IsConfigValid(const ClusterShardInfos& new_config) {
|
||||||
// Make sure that all slots are set exactly once.
|
// Make sure that all slots are set exactly once.
|
||||||
array<bool, ClusterConfig::kMaxSlotNum + 1> slots_found = {};
|
array<bool, cluster::kMaxSlotNum + 1> slots_found = {};
|
||||||
|
|
||||||
if (!HasValidNodeIds(new_config)) {
|
if (!HasValidNodeIds(new_config)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -347,7 +300,7 @@ std::shared_ptr<ClusterConfig> ClusterConfig::CloneWithChanges(
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClusterConfig::IsMySlot(SlotId id) const {
|
bool ClusterConfig::IsMySlot(SlotId id) const {
|
||||||
if (id > ClusterConfig::kMaxSlotNum) {
|
if (id > cluster::kMaxSlotNum) {
|
||||||
DCHECK(false) << "Requesting a non-existing slot id " << id;
|
DCHECK(false) << "Requesting a non-existing slot id " << id;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -360,7 +313,7 @@ bool ClusterConfig::IsMySlot(std::string_view key) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
ClusterNodeInfo ClusterConfig::GetMasterNodeForSlot(SlotId id) const {
|
ClusterNodeInfo ClusterConfig::GetMasterNodeForSlot(SlotId id) const {
|
||||||
CHECK_LE(id, ClusterConfig::kMaxSlotNum) << "Requesting a non-existing slot id " << id;
|
CHECK_LE(id, cluster::kMaxSlotNum) << "Requesting a non-existing slot id " << id;
|
||||||
|
|
||||||
for (const auto& shard : config_) {
|
for (const auto& shard : config_) {
|
||||||
for (const auto& range : shard.slot_ranges) {
|
for (const auto& range : shard.slot_ranges) {
|
||||||
|
@ -417,4 +370,4 @@ std::vector<MigrationInfo> ClusterConfig::GetFinishedIncomingMigrations(
|
||||||
: std::vector<MigrationInfo>();
|
: std::vector<MigrationInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly::cluster
|
||||||
|
|
|
@ -11,63 +11,10 @@
|
||||||
#include "src/server/cluster/slot_set.h"
|
#include "src/server/cluster/slot_set.h"
|
||||||
#include "src/server/common.h"
|
#include "src/server/common.h"
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly::cluster {
|
||||||
|
|
||||||
// MigrationState constants are ordered in state changing order
|
|
||||||
enum class MigrationState : uint8_t {
|
|
||||||
C_NO_STATE,
|
|
||||||
C_CONNECTING,
|
|
||||||
C_SYNC,
|
|
||||||
C_FINISHED,
|
|
||||||
C_CANCELLED,
|
|
||||||
C_MAX_INVALID = std::numeric_limits<uint8_t>::max()
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ClusterNodeInfo {
|
|
||||||
std::string id;
|
|
||||||
std::string ip;
|
|
||||||
uint16_t port = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MigrationInfo {
|
|
||||||
std::vector<SlotRange> slot_ranges;
|
|
||||||
std::string node_id;
|
|
||||||
std::string ip;
|
|
||||||
uint16_t port = 0;
|
|
||||||
|
|
||||||
bool operator==(const MigrationInfo& r) const {
|
|
||||||
return ip == r.ip && port == r.port && slot_ranges == r.slot_ranges && node_id == r.node_id;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ClusterShardInfo {
|
|
||||||
SlotRanges slot_ranges;
|
|
||||||
ClusterNodeInfo master;
|
|
||||||
std::vector<ClusterNodeInfo> replicas;
|
|
||||||
std::vector<MigrationInfo> migrations;
|
|
||||||
};
|
|
||||||
|
|
||||||
using ClusterShardInfos = std::vector<ClusterShardInfo>;
|
|
||||||
|
|
||||||
class ClusterConfig {
|
class ClusterConfig {
|
||||||
public:
|
public:
|
||||||
static constexpr SlotId kMaxSlotNum = 0x3FFF;
|
|
||||||
static constexpr SlotId kInvalidSlotId = kMaxSlotNum + 1;
|
|
||||||
|
|
||||||
static SlotId KeySlot(std::string_view key);
|
|
||||||
|
|
||||||
static void Initialize();
|
|
||||||
static bool IsEnabled();
|
|
||||||
static bool IsEmulated();
|
|
||||||
|
|
||||||
static bool IsEnabledOrEmulated() {
|
|
||||||
return IsEnabled() || IsEmulated();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IsShardedByTag() {
|
|
||||||
return IsEnabledOrEmulated() || LockTagOptions::instance().enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns an instance with `config` if it is valid.
|
// Returns an instance with `config` if it is valid.
|
||||||
// Returns heap-allocated object as it is too big for a stack frame.
|
// Returns heap-allocated object as it is too big for a stack frame.
|
||||||
static std::shared_ptr<ClusterConfig> CreateFromConfig(std::string_view my_id,
|
static std::shared_ptr<ClusterConfig> CreateFromConfig(std::string_view my_id,
|
||||||
|
@ -119,4 +66,4 @@ class ClusterConfig {
|
||||||
std::vector<MigrationInfo> my_incoming_migrations_;
|
std::vector<MigrationInfo> my_incoming_migrations_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly::cluster
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace testing;
|
using namespace testing;
|
||||||
using Node = dfly::ClusterNodeInfo;
|
using Node = dfly::cluster::ClusterNodeInfo;
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly::cluster {
|
||||||
|
|
||||||
MATCHER_P(NodeMatches, expected, "") {
|
MATCHER_P(NodeMatches, expected, "") {
|
||||||
return arg.id == expected.id && arg.ip == expected.ip && arg.port == expected.port;
|
return arg.id == expected.id && arg.ip == expected.ip && arg.port == expected.port;
|
||||||
|
@ -558,4 +558,4 @@ TEST_F(ClusterConfigTest, InvalidConfigMigrationsWithoutIP) {
|
||||||
EXPECT_EQ(config, nullptr);
|
EXPECT_EQ(config, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly::cluster
|
||||||
|
|
63
src/server/cluster/cluster_defs.cc
Normal file
63
src/server/cluster/cluster_defs.cc
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "redis/crc16.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "base/flags.h"
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "cluster_defs.h"
|
||||||
|
#include "src/server/common.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
ABSL_FLAG(string, cluster_mode, "", "Cluster mode supported. Default: \"\"");
|
||||||
|
|
||||||
|
namespace dfly::cluster {
|
||||||
|
namespace {
|
||||||
|
enum class ClusterMode {
|
||||||
|
kUninitialized,
|
||||||
|
kNoCluster,
|
||||||
|
kEmulatedCluster,
|
||||||
|
kRealCluster,
|
||||||
|
};
|
||||||
|
|
||||||
|
ClusterMode cluster_mode = ClusterMode::kUninitialized;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void InitializeCluster() {
|
||||||
|
string cluster_mode_str = absl::GetFlag(FLAGS_cluster_mode);
|
||||||
|
|
||||||
|
if (cluster_mode_str == "emulated") {
|
||||||
|
cluster_mode = ClusterMode::kEmulatedCluster;
|
||||||
|
} else if (cluster_mode_str == "yes") {
|
||||||
|
cluster_mode = ClusterMode::kRealCluster;
|
||||||
|
} else if (cluster_mode_str.empty()) {
|
||||||
|
cluster_mode = ClusterMode::kNoCluster;
|
||||||
|
} else {
|
||||||
|
LOG(ERROR) << "Invalid value for flag --cluster_mode. Exiting...";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsClusterEnabled() {
|
||||||
|
return cluster_mode == ClusterMode::kRealCluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsClusterEmulated() {
|
||||||
|
return cluster_mode == ClusterMode::kEmulatedCluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
SlotId KeySlot(std::string_view key) {
|
||||||
|
string_view tag = LockTagOptions::instance().Tag(key);
|
||||||
|
return crc16(tag.data(), tag.length()) & kMaxSlotNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsClusterEnabledOrEmulated() {
|
||||||
|
return IsClusterEnabled() || IsClusterEmulated();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsClusterShardedByTag() {
|
||||||
|
return IsClusterEnabledOrEmulated() || LockTagOptions::instance().enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dfly::cluster
|
90
src/server/cluster/cluster_defs.h
Normal file
90
src/server/cluster/cluster_defs.h
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
// Copyright 2024, DragonflyDB authors. All rights reserved.
|
||||||
|
// See LICENSE for licensing terms.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <absl/strings/str_cat.h>
|
||||||
|
#include <absl/strings/str_join.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace dfly::cluster {
|
||||||
|
|
||||||
|
using SlotId = uint16_t;
|
||||||
|
|
||||||
|
constexpr SlotId kMaxSlotNum = 0x3FFF;
|
||||||
|
constexpr SlotId kInvalidSlotId = kMaxSlotNum + 1;
|
||||||
|
|
||||||
|
struct SlotRange {
|
||||||
|
static constexpr SlotId kMaxSlotId = 0x3FFF;
|
||||||
|
SlotId start = 0;
|
||||||
|
SlotId end = 0;
|
||||||
|
|
||||||
|
bool operator==(const SlotRange& r) const {
|
||||||
|
return start == r.start && end == r.end;
|
||||||
|
}
|
||||||
|
bool IsValid() {
|
||||||
|
return start <= end && start <= kMaxSlotId && end <= kMaxSlotId;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ToString() const {
|
||||||
|
return absl::StrCat("[", start, ", ", end, "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string ToString(const std::vector<SlotRange>& ranges) {
|
||||||
|
return absl::StrJoin(ranges, ", ", [](std::string* out, SlotRange range) {
|
||||||
|
absl::StrAppend(out, range.ToString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using SlotRanges = std::vector<SlotRange>;
|
||||||
|
|
||||||
|
struct ClusterNodeInfo {
|
||||||
|
std::string id;
|
||||||
|
std::string ip;
|
||||||
|
uint16_t port = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MigrationInfo {
|
||||||
|
std::vector<SlotRange> slot_ranges;
|
||||||
|
std::string node_id;
|
||||||
|
std::string ip;
|
||||||
|
uint16_t port = 0;
|
||||||
|
|
||||||
|
bool operator==(const MigrationInfo& r) const {
|
||||||
|
return ip == r.ip && port == r.port && slot_ranges == r.slot_ranges && node_id == r.node_id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ClusterShardInfo {
|
||||||
|
SlotRanges slot_ranges;
|
||||||
|
ClusterNodeInfo master;
|
||||||
|
std::vector<ClusterNodeInfo> replicas;
|
||||||
|
std::vector<MigrationInfo> migrations;
|
||||||
|
};
|
||||||
|
|
||||||
|
using ClusterShardInfos = std::vector<ClusterShardInfo>;
|
||||||
|
|
||||||
|
// MigrationState constants are ordered in state changing order
|
||||||
|
enum class MigrationState : uint8_t {
|
||||||
|
C_NO_STATE,
|
||||||
|
C_CONNECTING,
|
||||||
|
C_SYNC,
|
||||||
|
C_FINISHED,
|
||||||
|
C_MAX_INVALID = std::numeric_limits<uint8_t>::max()
|
||||||
|
};
|
||||||
|
|
||||||
|
SlotId KeySlot(std::string_view key);
|
||||||
|
|
||||||
|
void InitializeCluster();
|
||||||
|
bool IsClusterEnabled();
|
||||||
|
bool IsClusterEmulated();
|
||||||
|
bool IsClusterEnabledOrEmulated();
|
||||||
|
bool IsClusterShardedByTag();
|
||||||
|
|
||||||
|
} // namespace dfly::cluster
|
|
@ -32,6 +32,17 @@ ABSL_FLAG(std::string, cluster_node_id, "",
|
||||||
ABSL_DECLARE_FLAG(int32_t, port);
|
ABSL_DECLARE_FLAG(int32_t, port);
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly {
|
||||||
|
namespace acl {
|
||||||
|
constexpr uint32_t kCluster = SLOW;
|
||||||
|
// Reconsider to maybe more sensible defaults
|
||||||
|
constexpr uint32_t kDflyCluster = ADMIN | SLOW;
|
||||||
|
constexpr uint32_t kReadOnly = FAST | CONNECTION;
|
||||||
|
constexpr uint32_t kReadWrite = FAST | CONNECTION;
|
||||||
|
constexpr uint32_t kDflyMigrate = ADMIN | SLOW | DANGEROUS;
|
||||||
|
} // namespace acl
|
||||||
|
} // namespace dfly
|
||||||
|
|
||||||
|
namespace dfly::cluster {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -52,12 +63,12 @@ thread_local shared_ptr<ClusterConfig> tl_cluster_config;
|
||||||
ClusterFamily::ClusterFamily(ServerFamily* server_family) : server_family_(server_family) {
|
ClusterFamily::ClusterFamily(ServerFamily* server_family) : server_family_(server_family) {
|
||||||
CHECK_NOTNULL(server_family_);
|
CHECK_NOTNULL(server_family_);
|
||||||
|
|
||||||
ClusterConfig::Initialize();
|
InitializeCluster();
|
||||||
|
|
||||||
id_ = absl::GetFlag(FLAGS_cluster_node_id);
|
id_ = absl::GetFlag(FLAGS_cluster_node_id);
|
||||||
if (id_.empty()) {
|
if (id_.empty()) {
|
||||||
id_ = server_family_->master_replid();
|
id_ = server_family_->master_replid();
|
||||||
} else if (ClusterConfig::IsEmulated()) {
|
} else if (IsClusterEmulated()) {
|
||||||
LOG(ERROR) << "Setting --cluster_node_id in emulated mode is unsupported";
|
LOG(ERROR) << "Setting --cluster_node_id in emulated mode is unsupported";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -68,7 +79,7 @@ ClusterConfig* ClusterFamily::cluster_config() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ClusterShardInfo ClusterFamily::GetEmulatedShardInfo(ConnectionContext* cntx) const {
|
ClusterShardInfo ClusterFamily::GetEmulatedShardInfo(ConnectionContext* cntx) const {
|
||||||
ClusterShardInfo info{.slot_ranges = {{.start = 0, .end = ClusterConfig::kMaxSlotNum}},
|
ClusterShardInfo info{.slot_ranges = {{.start = 0, .end = kMaxSlotNum}},
|
||||||
.master = {},
|
.master = {},
|
||||||
.replicas = {},
|
.replicas = {},
|
||||||
.migrations = {}};
|
.migrations = {}};
|
||||||
|
@ -166,7 +177,7 @@ void ClusterShardsImpl(const ClusterShardInfos& config, ConnectionContext* cntx)
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ClusterFamily::ClusterShards(ConnectionContext* cntx) {
|
void ClusterFamily::ClusterShards(ConnectionContext* cntx) {
|
||||||
if (ClusterConfig::IsEmulated()) {
|
if (IsClusterEmulated()) {
|
||||||
return ClusterShardsImpl({GetEmulatedShardInfo(cntx)}, cntx);
|
return ClusterShardsImpl({GetEmulatedShardInfo(cntx)}, cntx);
|
||||||
} else if (tl_cluster_config != nullptr) {
|
} else if (tl_cluster_config != nullptr) {
|
||||||
return ClusterShardsImpl(tl_cluster_config->GetConfig(), cntx);
|
return ClusterShardsImpl(tl_cluster_config->GetConfig(), cntx);
|
||||||
|
@ -210,7 +221,7 @@ void ClusterSlotsImpl(const ClusterShardInfos& config, ConnectionContext* cntx)
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ClusterFamily::ClusterSlots(ConnectionContext* cntx) {
|
void ClusterFamily::ClusterSlots(ConnectionContext* cntx) {
|
||||||
if (ClusterConfig::IsEmulated()) {
|
if (IsClusterEmulated()) {
|
||||||
return ClusterSlotsImpl({GetEmulatedShardInfo(cntx)}, cntx);
|
return ClusterSlotsImpl({GetEmulatedShardInfo(cntx)}, cntx);
|
||||||
} else if (tl_cluster_config != nullptr) {
|
} else if (tl_cluster_config != nullptr) {
|
||||||
return ClusterSlotsImpl(tl_cluster_config->GetConfig(), cntx);
|
return ClusterSlotsImpl(tl_cluster_config->GetConfig(), cntx);
|
||||||
|
@ -265,7 +276,7 @@ void ClusterNodesImpl(const ClusterShardInfos& config, string_view my_id, Connec
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ClusterFamily::ClusterNodes(ConnectionContext* cntx) {
|
void ClusterFamily::ClusterNodes(ConnectionContext* cntx) {
|
||||||
if (ClusterConfig::IsEmulated()) {
|
if (IsClusterEmulated()) {
|
||||||
return ClusterNodesImpl({GetEmulatedShardInfo(cntx)}, id_, cntx);
|
return ClusterNodesImpl({GetEmulatedShardInfo(cntx)}, id_, cntx);
|
||||||
} else if (tl_cluster_config != nullptr) {
|
} else if (tl_cluster_config != nullptr) {
|
||||||
return ClusterNodesImpl(tl_cluster_config->GetConfig(), id_, cntx);
|
return ClusterNodesImpl(tl_cluster_config->GetConfig(), id_, cntx);
|
||||||
|
@ -284,7 +295,7 @@ void ClusterInfoImpl(const ClusterShardInfos& config, ConnectionContext* cntx) {
|
||||||
|
|
||||||
// Initialize response variables to emulated mode.
|
// Initialize response variables to emulated mode.
|
||||||
string_view state = "ok"sv;
|
string_view state = "ok"sv;
|
||||||
SlotId slots_assigned = ClusterConfig::kMaxSlotNum + 1;
|
SlotId slots_assigned = kMaxSlotNum + 1;
|
||||||
size_t known_nodes = 1;
|
size_t known_nodes = 1;
|
||||||
long epoch = 1;
|
long epoch = 1;
|
||||||
size_t cluster_size = 1;
|
size_t cluster_size = 1;
|
||||||
|
@ -329,7 +340,7 @@ void ClusterInfoImpl(const ClusterShardInfos& config, ConnectionContext* cntx) {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ClusterFamily::ClusterInfo(ConnectionContext* cntx) {
|
void ClusterFamily::ClusterInfo(ConnectionContext* cntx) {
|
||||||
if (ClusterConfig::IsEmulated()) {
|
if (IsClusterEmulated()) {
|
||||||
return ClusterInfoImpl({GetEmulatedShardInfo(cntx)}, cntx);
|
return ClusterInfoImpl({GetEmulatedShardInfo(cntx)}, cntx);
|
||||||
} else if (tl_cluster_config != nullptr) {
|
} else if (tl_cluster_config != nullptr) {
|
||||||
return ClusterInfoImpl(tl_cluster_config->GetConfig(), cntx);
|
return ClusterInfoImpl(tl_cluster_config->GetConfig(), cntx);
|
||||||
|
@ -343,7 +354,7 @@ void ClusterFamily::KeySlot(CmdArgList args, ConnectionContext* cntx) {
|
||||||
return cntx->SendError(WrongNumArgsError("CLUSTER KEYSLOT"));
|
return cntx->SendError(WrongNumArgsError("CLUSTER KEYSLOT"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SlotId id = ClusterConfig::KeySlot(ArgS(args, 1));
|
SlotId id = cluster::KeySlot(ArgS(args, 1));
|
||||||
return cntx->SendLong(id);
|
return cntx->SendLong(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,7 +365,7 @@ void ClusterFamily::Cluster(CmdArgList args, ConnectionContext* cntx) {
|
||||||
ToUpper(&args[0]);
|
ToUpper(&args[0]);
|
||||||
string_view sub_cmd = ArgS(args, 0);
|
string_view sub_cmd = ArgS(args, 0);
|
||||||
|
|
||||||
if (!ClusterConfig::IsEnabledOrEmulated()) {
|
if (!IsClusterEnabledOrEmulated()) {
|
||||||
return cntx->SendError(kClusterDisabled);
|
return cntx->SendError(kClusterDisabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,21 +387,21 @@ void ClusterFamily::Cluster(CmdArgList args, ConnectionContext* cntx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClusterFamily::ReadOnly(CmdArgList args, ConnectionContext* cntx) {
|
void ClusterFamily::ReadOnly(CmdArgList args, ConnectionContext* cntx) {
|
||||||
if (!ClusterConfig::IsEmulated()) {
|
if (!IsClusterEmulated()) {
|
||||||
return cntx->SendError(kClusterDisabled);
|
return cntx->SendError(kClusterDisabled);
|
||||||
}
|
}
|
||||||
cntx->SendOk();
|
cntx->SendOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClusterFamily::ReadWrite(CmdArgList args, ConnectionContext* cntx) {
|
void ClusterFamily::ReadWrite(CmdArgList args, ConnectionContext* cntx) {
|
||||||
if (!ClusterConfig::IsEmulated()) {
|
if (!IsClusterEmulated()) {
|
||||||
return cntx->SendError(kClusterDisabled);
|
return cntx->SendError(kClusterDisabled);
|
||||||
}
|
}
|
||||||
cntx->SendOk();
|
cntx->SendOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClusterFamily::DflyCluster(CmdArgList args, ConnectionContext* cntx) {
|
void ClusterFamily::DflyCluster(CmdArgList args, ConnectionContext* cntx) {
|
||||||
if (!ClusterConfig::IsEnabledOrEmulated()) {
|
if (!IsClusterEnabledOrEmulated()) {
|
||||||
return cntx->SendError(kClusterDisabled);
|
return cntx->SendError(kClusterDisabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,7 +581,7 @@ void ClusterFamily::DflyClusterGetSlotInfo(CmdArgList args, ConnectionContext* c
|
||||||
vector<std::pair<SlotId, SlotStats>> slots_stats;
|
vector<std::pair<SlotId, SlotStats>> slots_stats;
|
||||||
do {
|
do {
|
||||||
auto sid = parser.Next<uint32_t>();
|
auto sid = parser.Next<uint32_t>();
|
||||||
if (sid > ClusterConfig::kMaxSlotNum)
|
if (sid > kMaxSlotNum)
|
||||||
return rb->SendError("Invalid slot id");
|
return rb->SendError("Invalid slot id");
|
||||||
slots_stats.emplace_back(sid, SlotStats{});
|
slots_stats.emplace_back(sid, SlotStats{});
|
||||||
} while (parser.HasNext());
|
} while (parser.HasNext());
|
||||||
|
@ -646,8 +657,6 @@ static string_view StateToStr(MigrationState state) {
|
||||||
return "SYNC"sv;
|
return "SYNC"sv;
|
||||||
case MigrationState::C_FINISHED:
|
case MigrationState::C_FINISHED:
|
||||||
return "FINISHED"sv;
|
return "FINISHED"sv;
|
||||||
case MigrationState::C_CANCELLED:
|
|
||||||
return "CANCELLED"sv;
|
|
||||||
case MigrationState::C_MAX_INVALID:
|
case MigrationState::C_MAX_INVALID:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -924,15 +933,6 @@ inline CommandId::Handler HandlerFunc(ClusterFamily* se, EngineFunc f) {
|
||||||
|
|
||||||
#define HFUNC(x) SetHandler(HandlerFunc(this, &ClusterFamily::x))
|
#define HFUNC(x) SetHandler(HandlerFunc(this, &ClusterFamily::x))
|
||||||
|
|
||||||
namespace acl {
|
|
||||||
constexpr uint32_t kCluster = SLOW;
|
|
||||||
// Reconsider to maybe more sensible defaults
|
|
||||||
constexpr uint32_t kDflyCluster = ADMIN | SLOW;
|
|
||||||
constexpr uint32_t kReadOnly = FAST | CONNECTION;
|
|
||||||
constexpr uint32_t kReadWrite = FAST | CONNECTION;
|
|
||||||
constexpr uint32_t kDflyMigrate = ADMIN | SLOW | DANGEROUS;
|
|
||||||
} // namespace acl
|
|
||||||
|
|
||||||
void ClusterFamily::Register(CommandRegistry* registry) {
|
void ClusterFamily::Register(CommandRegistry* registry) {
|
||||||
registry->StartFamily();
|
registry->StartFamily();
|
||||||
*registry << CI{"CLUSTER", CO::READONLY, -2, 0, 0, acl::kCluster}.HFUNC(Cluster)
|
*registry << CI{"CLUSTER", CO::READONLY, -2, 0, 0, acl::kCluster}.HFUNC(Cluster)
|
||||||
|
@ -945,4 +945,4 @@ void ClusterFamily::Register(CommandRegistry* registry) {
|
||||||
DflyMigrate);
|
DflyMigrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly::cluster
|
||||||
|
|
|
@ -15,9 +15,12 @@
|
||||||
#include "server/common.h"
|
#include "server/common.h"
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly {
|
||||||
|
class ServerFamily;
|
||||||
class CommandRegistry;
|
class CommandRegistry;
|
||||||
class ConnectionContext;
|
class ConnectionContext;
|
||||||
class ServerFamily;
|
} // namespace dfly
|
||||||
|
|
||||||
|
namespace dfly::cluster {
|
||||||
|
|
||||||
class ClusterFamily {
|
class ClusterFamily {
|
||||||
public:
|
public:
|
||||||
|
@ -105,4 +108,4 @@ class ClusterFamily {
|
||||||
ServerFamily* server_family_ = nullptr;
|
ServerFamily* server_family_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly::cluster
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include "facade/facade_test.h"
|
#include "facade/facade_test.h"
|
||||||
#include "server/test_utils.h"
|
#include "server/test_utils.h"
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly::cluster {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -395,7 +395,7 @@ TEST_F(ClusterFamilyTest, ClusterConfigFullMultipleInstances) {
|
||||||
absl::InsecureBitGen eng;
|
absl::InsecureBitGen eng;
|
||||||
while (true) {
|
while (true) {
|
||||||
string random_key = GetRandomHex(eng, 40);
|
string random_key = GetRandomHex(eng, 40);
|
||||||
SlotId slot = ClusterConfig::KeySlot(random_key);
|
SlotId slot = KeySlot(random_key);
|
||||||
if (slot > 10'000) {
|
if (slot > 10'000) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -407,7 +407,7 @@ TEST_F(ClusterFamilyTest, ClusterConfigFullMultipleInstances) {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
string random_key = GetRandomHex(eng, 40);
|
string random_key = GetRandomHex(eng, 40);
|
||||||
SlotId slot = ClusterConfig::KeySlot(random_key);
|
SlotId slot = KeySlot(random_key);
|
||||||
if (slot <= 10'000) {
|
if (slot <= 10'000) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -429,7 +429,7 @@ TEST_F(ClusterFamilyTest, ClusterGetSlotInfo) {
|
||||||
ConfigSingleNodeCluster(GetMyId());
|
ConfigSingleNodeCluster(GetMyId());
|
||||||
|
|
||||||
constexpr string_view kKey = "some-key";
|
constexpr string_view kKey = "some-key";
|
||||||
const SlotId slot = ClusterConfig::KeySlot(kKey);
|
const SlotId slot = KeySlot(kKey);
|
||||||
EXPECT_NE(slot, 0) << "We need to choose another key";
|
EXPECT_NE(slot, 0) << "We need to choose another key";
|
||||||
|
|
||||||
const string value(1'000, '#'); // Long string - to use heap
|
const string value(1'000, '#'); // Long string - to use heap
|
||||||
|
@ -740,4 +740,4 @@ TEST_F(ClusterFamilyEmulatedTest, ClusterNodes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace dfly
|
} // namespace dfly::cluster
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include "server/journal/tx_executor.h"
|
#include "server/journal/tx_executor.h"
|
||||||
#include "server/main_service.h"
|
#include "server/main_service.h"
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly::cluster {
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace util;
|
using namespace util;
|
||||||
|
@ -140,4 +140,4 @@ void IncomingSlotMigration::StartFlow(uint32_t shard, util::FiberSocketBase* sou
|
||||||
shard_flows_[shard]->Start(&cntx_, source, bc_);
|
shard_flows_[shard]->Start(&cntx_, source, bc_);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly::cluster
|
||||||
|
|
|
@ -5,12 +5,15 @@
|
||||||
|
|
||||||
#include "helio/io/io.h"
|
#include "helio/io/io.h"
|
||||||
#include "helio/util/fiber_socket_base.h"
|
#include "helio/util/fiber_socket_base.h"
|
||||||
#include "server/cluster/cluster_config.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
|
#include "server/common.h"
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly {
|
||||||
class ClusterShardMigration;
|
|
||||||
|
|
||||||
class Service;
|
class Service;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace dfly::cluster {
|
||||||
|
class ClusterShardMigration;
|
||||||
|
|
||||||
// The main entity on the target side that manage slots migration process
|
// The main entity on the target side that manage slots migration process
|
||||||
// Manage connections between the target and source node,
|
// Manage connections between the target and source node,
|
||||||
|
@ -55,4 +58,4 @@ class IncomingSlotMigration {
|
||||||
util::fb2::BlockingCounter bc_;
|
util::fb2::BlockingCounter bc_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly::cluster
|
||||||
|
|
|
@ -23,7 +23,7 @@ using namespace std;
|
||||||
using namespace facade;
|
using namespace facade;
|
||||||
using namespace util;
|
using namespace util;
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly::cluster {
|
||||||
|
|
||||||
class OutgoingMigration::SliceSlotMigration : private ProtocolClient {
|
class OutgoingMigration::SliceSlotMigration : private ProtocolClient {
|
||||||
public:
|
public:
|
||||||
|
@ -221,4 +221,4 @@ std::error_code OutgoingMigration::Start(ConnectionContext* cntx) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly::cluster
|
||||||
|
|
|
@ -4,18 +4,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "io/io.h"
|
#include "io/io.h"
|
||||||
#include "server/cluster/cluster_config.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
#include "server/common.h"
|
|
||||||
#include "server/protocol_client.h"
|
#include "server/protocol_client.h"
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly {
|
||||||
|
class DbSlice;
|
||||||
|
class ServerFamily;
|
||||||
|
|
||||||
namespace journal {
|
namespace journal {
|
||||||
class Journal;
|
class Journal;
|
||||||
}
|
}
|
||||||
|
} // namespace dfly
|
||||||
class DbSlice;
|
namespace dfly::cluster {
|
||||||
class ServerFamily;
|
|
||||||
class ClusterFamily;
|
class ClusterFamily;
|
||||||
|
|
||||||
// Whole outgoing slots migration manager
|
// Whole outgoing slots migration manager
|
||||||
|
@ -76,4 +76,4 @@ class OutgoingMigration : private ProtocolClient {
|
||||||
std::atomic<MigrationState> state_ = MigrationState::C_NO_STATE;
|
std::atomic<MigrationState> state_ = MigrationState::C_NO_STATE;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly::cluster
|
||||||
|
|
|
@ -6,40 +6,11 @@
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "absl/strings/str_cat.h"
|
#include "cluster_defs.h"
|
||||||
#include "absl/strings/str_join.h"
|
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly::cluster {
|
||||||
|
|
||||||
using SlotId = uint16_t;
|
|
||||||
|
|
||||||
struct SlotRange {
|
|
||||||
static constexpr SlotId kMaxSlotId = 0x3FFF;
|
|
||||||
SlotId start = 0;
|
|
||||||
SlotId end = 0;
|
|
||||||
|
|
||||||
bool operator==(const SlotRange& r) const {
|
|
||||||
return start == r.start && end == r.end;
|
|
||||||
}
|
|
||||||
bool IsValid() {
|
|
||||||
return start <= end && start <= kMaxSlotId && end <= kMaxSlotId;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ToString() const {
|
|
||||||
return absl::StrCat("[", start, ", ", end, "]");
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string ToString(const std::vector<SlotRange>& ranges) {
|
|
||||||
return absl::StrJoin(ranges, ", ", [](std::string* out, SlotRange range) {
|
|
||||||
absl::StrAppend(out, range.ToString());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using SlotRanges = std::vector<SlotRange>;
|
|
||||||
|
|
||||||
class SlotSet {
|
class SlotSet {
|
||||||
public:
|
public:
|
||||||
|
@ -117,4 +88,4 @@ class SlotSet {
|
||||||
std::unique_ptr<TBitSet> slots_{std::make_unique<TBitSet>()};
|
std::unique_ptr<TBitSet> slots_{std::make_unique<TBitSet>()};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly::cluster
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
#include "server/cluster/unique_slot_checker.h"
|
#include "server/cluster/unique_slot_checker.h"
|
||||||
|
|
||||||
#include "server/cluster/cluster_config.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly::cluster {
|
||||||
|
|
||||||
void UniqueSlotChecker::Add(std::string_view key) {
|
void UniqueSlotChecker::Add(std::string_view key) {
|
||||||
if (!ClusterConfig::IsEnabled()) {
|
if (!IsClusterEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Add(ClusterConfig::KeySlot(key));
|
Add(KeySlot(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UniqueSlotChecker::Add(SlotId slot_id) {
|
void UniqueSlotChecker::Add(SlotId slot_id) {
|
||||||
if (!ClusterConfig::IsEnabled()) {
|
if (!IsClusterEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,16 +25,16 @@ void UniqueSlotChecker::Add(SlotId slot_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*slot_id_ != slot_id) {
|
if (*slot_id_ != slot_id) {
|
||||||
slot_id_ = ClusterConfig::kInvalidSlotId;
|
slot_id_ = kInvalidSlotId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<SlotId> UniqueSlotChecker::GetUniqueSlotId() const {
|
optional<SlotId> UniqueSlotChecker::GetUniqueSlotId() const {
|
||||||
if (slot_id_.has_value() && *slot_id_ == ClusterConfig::kInvalidSlotId) {
|
if (slot_id_.has_value() && *slot_id_ == kInvalidSlotId) {
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return slot_id_;
|
return slot_id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly::cluster
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include "server/cluster/slot_set.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly::cluster {
|
||||||
|
|
||||||
// A simple utility class that "aggregates" SlotId-s and can tell whether all inputs were the same.
|
// A simple utility class that "aggregates" SlotId-s and can tell whether all inputs were the same.
|
||||||
// Only works when cluster is enabled.
|
// Only works when cluster is enabled.
|
||||||
|
@ -24,4 +24,4 @@ class UniqueSlotChecker {
|
||||||
std::optional<SlotId> slot_id_;
|
std::optional<SlotId> slot_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly::cluster
|
||||||
|
|
|
@ -18,7 +18,7 @@ extern "C" {
|
||||||
#include "base/flags.h"
|
#include "base/flags.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "core/compact_object.h"
|
#include "core/compact_object.h"
|
||||||
#include "server/cluster/cluster_config.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
#include "server/engine_shard_set.h"
|
#include "server/engine_shard_set.h"
|
||||||
#include "server/error.h"
|
#include "server/error.h"
|
||||||
#include "server/journal/journal.h"
|
#include "server/journal/journal.h"
|
||||||
|
@ -269,7 +269,7 @@ void RecordJournalFinish(const OpArgs& op_args, uint32_t shard_cnt) {
|
||||||
void RecordExpiry(DbIndex dbid, string_view key) {
|
void RecordExpiry(DbIndex dbid, string_view key) {
|
||||||
auto journal = EngineShard::tlocal()->journal();
|
auto journal = EngineShard::tlocal()->journal();
|
||||||
CHECK(journal);
|
CHECK(journal);
|
||||||
journal->RecordEntry(0, journal::Op::EXPIRED, dbid, 1, ClusterConfig::KeySlot(key),
|
journal->RecordEntry(0, journal::Op::EXPIRED, dbid, 1, cluster::KeySlot(key),
|
||||||
make_pair("DEL", ArgSlice{key}), false);
|
make_pair("DEL", ArgSlice{key}), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "base/flags.h"
|
#include "base/flags.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "generic_family.h"
|
#include "generic_family.h"
|
||||||
#include "server/cluster/cluster_config.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
#include "server/engine_shard_set.h"
|
#include "server/engine_shard_set.h"
|
||||||
#include "server/error.h"
|
#include "server/error.h"
|
||||||
#include "server/journal/journal.h"
|
#include "server/journal/journal.h"
|
||||||
|
@ -60,8 +60,8 @@ void AccountObjectMemory(string_view key, unsigned type, int64_t size, DbTable*
|
||||||
|
|
||||||
stats.AddTypeMemoryUsage(type, size);
|
stats.AddTypeMemoryUsage(type, size);
|
||||||
|
|
||||||
if (ClusterConfig::IsEnabled()) {
|
if (cluster::IsClusterEnabled()) {
|
||||||
db->slots_stats[ClusterConfig::KeySlot(key)].memory_bytes += size;
|
db->slots_stats[cluster::KeySlot(key)].memory_bytes += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ unsigned PrimeEvictionPolicy::Evict(const PrimeTable::HotspotBuckets& eb, PrimeT
|
||||||
// log the evicted keys to journal.
|
// log the evicted keys to journal.
|
||||||
if (auto journal = db_slice_->shard_owner()->journal(); journal) {
|
if (auto journal = db_slice_->shard_owner()->journal(); journal) {
|
||||||
ArgSlice delete_args(&key, 1);
|
ArgSlice delete_args(&key, 1);
|
||||||
journal->RecordEntry(0, journal::Op::EXPIRED, cntx_.db_index, 1, ClusterConfig::KeySlot(key),
|
journal->RecordEntry(0, journal::Op::EXPIRED, cntx_.db_index, 1, cluster::KeySlot(key),
|
||||||
make_pair("DEL", delete_args), false);
|
make_pair("DEL", delete_args), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +301,7 @@ auto DbSlice::GetStats() const -> Stats {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
SlotStats DbSlice::GetSlotStats(SlotId sid) const {
|
SlotStats DbSlice::GetSlotStats(cluster::SlotId sid) const {
|
||||||
CHECK(db_arr_[0]);
|
CHECK(db_arr_[0]);
|
||||||
return db_arr_[0]->slots_stats[sid];
|
return db_arr_[0]->slots_stats[sid];
|
||||||
}
|
}
|
||||||
|
@ -528,8 +528,8 @@ OpResult<DbSlice::PrimeItAndExp> DbSlice::FindInternal(const Context& cntx, std:
|
||||||
break;
|
break;
|
||||||
case UpdateStatsMode::kReadStats:
|
case UpdateStatsMode::kReadStats:
|
||||||
events_.hits++;
|
events_.hits++;
|
||||||
if (ClusterConfig::IsEnabled()) {
|
if (cluster::IsClusterEnabled()) {
|
||||||
db.slots_stats[ClusterConfig::KeySlot(key)].total_reads++;
|
db.slots_stats[cluster::KeySlot(key)].total_reads++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -661,8 +661,8 @@ OpResult<DbSlice::AddOrFindResult> DbSlice::AddOrFindInternal(const Context& cnt
|
||||||
events_.garbage_checked += evp.checked();
|
events_.garbage_checked += evp.checked();
|
||||||
|
|
||||||
memory_budget_ = evp.mem_budget() + evicted_obj_bytes;
|
memory_budget_ = evp.mem_budget() + evicted_obj_bytes;
|
||||||
if (ClusterConfig::IsEnabled()) {
|
if (cluster::IsClusterEnabled()) {
|
||||||
SlotId sid = ClusterConfig::KeySlot(key);
|
cluster::SlotId sid = cluster::KeySlot(key);
|
||||||
db.slots_stats[sid].key_count += 1;
|
db.slots_stats[sid].key_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,7 +703,7 @@ bool DbSlice::Del(DbIndex db_ind, Iterator it) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DbSlice::FlushSlotsFb(const SlotSet& slot_ids) {
|
void DbSlice::FlushSlotsFb(const cluster::SlotSet& slot_ids) {
|
||||||
// Slot deletion can take time as it traverses all the database, hence it runs in fiber.
|
// Slot deletion can take time as it traverses all the database, hence it runs in fiber.
|
||||||
// We want to flush all the data of a slot that was added till the time the call to FlushSlotsFb
|
// We want to flush all the data of a slot that was added till the time the call to FlushSlotsFb
|
||||||
// was made. Therefore we delete slots entries with version < next_version
|
// was made. Therefore we delete slots entries with version < next_version
|
||||||
|
@ -712,7 +712,7 @@ void DbSlice::FlushSlotsFb(const SlotSet& slot_ids) {
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
auto del_entry_cb = [&](PrimeTable::iterator it) {
|
auto del_entry_cb = [&](PrimeTable::iterator it) {
|
||||||
std::string_view key = it->first.GetSlice(&tmp);
|
std::string_view key = it->first.GetSlice(&tmp);
|
||||||
SlotId sid = ClusterConfig::KeySlot(key);
|
cluster::SlotId sid = cluster::KeySlot(key);
|
||||||
if (slot_ids.Contains(sid) && it.GetVersion() < next_version) {
|
if (slot_ids.Contains(sid) && it.GetVersion() < next_version) {
|
||||||
PerformDeletion(Iterator::FromPrime(it), db_arr_[0].get());
|
PerformDeletion(Iterator::FromPrime(it), db_arr_[0].get());
|
||||||
}
|
}
|
||||||
|
@ -765,8 +765,8 @@ void DbSlice::FlushSlotsFb(const SlotSet& slot_ids) {
|
||||||
etl.DecommitMemory(ServerState::kDataHeap);
|
etl.DecommitMemory(ServerState::kDataHeap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DbSlice::FlushSlots(SlotRanges slot_ranges) {
|
void DbSlice::FlushSlots(cluster::SlotRanges slot_ranges) {
|
||||||
SlotSet slot_set(slot_ranges);
|
cluster::SlotSet slot_set(slot_ranges);
|
||||||
InvalidateSlotWatches(slot_set);
|
InvalidateSlotWatches(slot_set);
|
||||||
fb2::Fiber("flush_slots", [this, slot_set = std::move(slot_set)]() mutable {
|
fb2::Fiber("flush_slots", [this, slot_set = std::move(slot_set)]() mutable {
|
||||||
FlushSlotsFb(slot_set);
|
FlushSlotsFb(slot_set);
|
||||||
|
@ -1075,8 +1075,8 @@ void DbSlice::PostUpdate(DbIndex db_ind, Iterator it, std::string_view key, size
|
||||||
|
|
||||||
++events_.update;
|
++events_.update;
|
||||||
|
|
||||||
if (ClusterConfig::IsEnabled()) {
|
if (cluster::IsClusterEnabled()) {
|
||||||
db.slots_stats[ClusterConfig::KeySlot(key)].total_writes += 1;
|
db.slots_stats[cluster::KeySlot(key)].total_writes += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SendInvalidationTrackingMessage(key);
|
SendInvalidationTrackingMessage(key);
|
||||||
|
@ -1333,7 +1333,7 @@ finish:
|
||||||
if (auto journal = owner_->journal(); journal) {
|
if (auto journal = owner_->journal(); journal) {
|
||||||
for (string_view key : keys_to_journal) {
|
for (string_view key : keys_to_journal) {
|
||||||
ArgSlice delete_args(&key, 1);
|
ArgSlice delete_args(&key, 1);
|
||||||
journal->RecordEntry(0, journal::Op::EXPIRED, db_ind, 1, ClusterConfig::KeySlot(key),
|
journal->RecordEntry(0, journal::Op::EXPIRED, db_ind, 1, cluster::KeySlot(key),
|
||||||
make_pair("DEL", delete_args), false);
|
make_pair("DEL", delete_args), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1466,9 +1466,9 @@ void DbSlice::InvalidateDbWatches(DbIndex db_indx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DbSlice::InvalidateSlotWatches(const SlotSet& slot_ids) {
|
void DbSlice::InvalidateSlotWatches(const cluster::SlotSet& slot_ids) {
|
||||||
for (const auto& [key, conn_list] : db_arr_[0]->watched_keys) {
|
for (const auto& [key, conn_list] : db_arr_[0]->watched_keys) {
|
||||||
SlotId sid = ClusterConfig::KeySlot(key);
|
cluster::SlotId sid = cluster::KeySlot(key);
|
||||||
if (!slot_ids.Contains(sid)) {
|
if (!slot_ids.Contains(sid)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1583,8 +1583,8 @@ void DbSlice::PerformDeletion(Iterator del_it, ExpIterator exp_it, DbTable* tabl
|
||||||
--stats.listpack_blob_cnt;
|
--stats.listpack_blob_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ClusterConfig::IsEnabled()) {
|
if (cluster::IsClusterEnabled()) {
|
||||||
SlotId sid = ClusterConfig::KeySlot(del_it.key());
|
cluster::SlotId sid = cluster::KeySlot(del_it.key());
|
||||||
table->slots_stats[sid].key_count -= 1;
|
table->slots_stats[sid].key_count -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -229,7 +229,7 @@ class DbSlice {
|
||||||
Stats GetStats() const;
|
Stats GetStats() const;
|
||||||
|
|
||||||
// Returns slot statistics for db 0.
|
// Returns slot statistics for db 0.
|
||||||
SlotStats GetSlotStats(SlotId sid) const;
|
SlotStats GetSlotStats(cluster::SlotId sid) const;
|
||||||
|
|
||||||
void UpdateExpireBase(uint64_t now, unsigned generation) {
|
void UpdateExpireBase(uint64_t now, unsigned generation) {
|
||||||
expire_base_[generation & 1] = now;
|
expire_base_[generation & 1] = now;
|
||||||
|
@ -349,7 +349,7 @@ class DbSlice {
|
||||||
void FlushDb(DbIndex db_ind);
|
void FlushDb(DbIndex db_ind);
|
||||||
|
|
||||||
// Flushes the data of given slot ranges.
|
// Flushes the data of given slot ranges.
|
||||||
void FlushSlots(SlotRanges slot_ranges);
|
void FlushSlots(cluster::SlotRanges slot_ranges);
|
||||||
|
|
||||||
EngineShard* shard_owner() const {
|
EngineShard* shard_owner() const {
|
||||||
return owner_;
|
return owner_;
|
||||||
|
@ -487,14 +487,14 @@ class DbSlice {
|
||||||
PrimeValue obj, uint64_t expire_at_ms,
|
PrimeValue obj, uint64_t expire_at_ms,
|
||||||
bool force_update);
|
bool force_update);
|
||||||
|
|
||||||
void FlushSlotsFb(const SlotSet& slot_ids);
|
void FlushSlotsFb(const cluster::SlotSet& slot_ids);
|
||||||
void FlushDbIndexes(const std::vector<DbIndex>& indexes);
|
void FlushDbIndexes(const std::vector<DbIndex>& indexes);
|
||||||
|
|
||||||
// Invalidate all watched keys in database. Used on FLUSH.
|
// Invalidate all watched keys in database. Used on FLUSH.
|
||||||
void InvalidateDbWatches(DbIndex db_indx);
|
void InvalidateDbWatches(DbIndex db_indx);
|
||||||
|
|
||||||
// Invalidate all watched keys for given slots. Used on FlushSlots.
|
// Invalidate all watched keys for given slots. Used on FlushSlots.
|
||||||
void InvalidateSlotWatches(const SlotSet& slot_ids);
|
void InvalidateSlotWatches(const cluster::SlotSet& slot_ids);
|
||||||
|
|
||||||
void PerformDeletion(Iterator del_it, ExpIterator exp_it, DbTable* table);
|
void PerformDeletion(Iterator del_it, ExpIterator exp_it, DbTable* table);
|
||||||
|
|
||||||
|
|
|
@ -627,7 +627,7 @@ optional<DebugCmd::PopulateOptions> DebugCmd::ParsePopulateArgs(CmdArgList args)
|
||||||
if (!absl::SimpleAtoi(slot_str, &slot_id)) {
|
if (!absl::SimpleAtoi(slot_str, &slot_id)) {
|
||||||
return facade::OpStatus::INVALID_INT;
|
return facade::OpStatus::INVALID_INT;
|
||||||
}
|
}
|
||||||
if (slot_id > ClusterConfig::kMaxSlotNum) {
|
if (slot_id > cluster::kMaxSlotNum) {
|
||||||
return facade::OpStatus::INVALID_VALUE;
|
return facade::OpStatus::INVALID_VALUE;
|
||||||
}
|
}
|
||||||
return slot_id;
|
return slot_id;
|
||||||
|
@ -643,8 +643,8 @@ optional<DebugCmd::PopulateOptions> DebugCmd::ParsePopulateArgs(CmdArgList args)
|
||||||
cntx_->SendError(end.status());
|
cntx_->SendError(end.status());
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
options.slot_range = SlotRange{.start = static_cast<SlotId>(start.value()),
|
options.slot_range = cluster::SlotRange{.start = static_cast<cluster::SlotId>(start.value()),
|
||||||
.end = static_cast<SlotId>(end.value())};
|
.end = static_cast<cluster::SlotId>(end.value())};
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
cntx_->SendError(kSyntaxErr);
|
cntx_->SendError(kSyntaxErr);
|
||||||
|
@ -716,7 +716,7 @@ void DebugCmd::PopulateRangeFiber(uint64_t from, uint64_t num_of_keys,
|
||||||
// <key_prefix>:<from+total_count+num_of_keys-1> and continue until num_of_keys are added.
|
// <key_prefix>:<from+total_count+num_of_keys-1> and continue until num_of_keys are added.
|
||||||
|
|
||||||
// Add keys only in slot range.
|
// Add keys only in slot range.
|
||||||
SlotId sid = ClusterConfig::KeySlot(key);
|
cluster::SlotId sid = cluster::KeySlot(key);
|
||||||
if (sid < options.slot_range->start || sid > options.slot_range->end) {
|
if (sid < options.slot_range->start || sid > options.slot_range->end) {
|
||||||
++index;
|
++index;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "server/cluster/slot_set.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
#include "server/conn_context.h"
|
#include "server/conn_context.h"
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly {
|
||||||
|
@ -22,7 +22,7 @@ class DebugCmd {
|
||||||
std::string_view type{"STRING"};
|
std::string_view type{"STRING"};
|
||||||
uint32_t elements = 1;
|
uint32_t elements = 1;
|
||||||
|
|
||||||
std::optional<SlotRange> slot_range;
|
std::optional<cluster::SlotRange> slot_range;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -17,7 +17,7 @@ extern "C" {
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "io/proc_reader.h"
|
#include "io/proc_reader.h"
|
||||||
#include "server/blocking_controller.h"
|
#include "server/blocking_controller.h"
|
||||||
#include "server/cluster/cluster_config.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
#include "server/search/doc_index.h"
|
#include "server/search/doc_index.h"
|
||||||
#include "server/server_state.h"
|
#include "server/server_state.h"
|
||||||
#include "server/tiered_storage.h"
|
#include "server/tiered_storage.h"
|
||||||
|
@ -865,7 +865,7 @@ void EngineShardSet::TEST_EnableCacheMode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ShardId Shard(string_view v, ShardId shard_num) {
|
ShardId Shard(string_view v, ShardId shard_num) {
|
||||||
if (ClusterConfig::IsShardedByTag()) {
|
if (cluster::IsClusterShardedByTag()) {
|
||||||
v = LockTagOptions::instance().Tag(v);
|
v = LockTagOptions::instance().Tag(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ extern "C" {
|
||||||
#include "redis/rdb.h"
|
#include "redis/rdb.h"
|
||||||
#include "server/acl/acl_commands_def.h"
|
#include "server/acl/acl_commands_def.h"
|
||||||
#include "server/blocking_controller.h"
|
#include "server/blocking_controller.h"
|
||||||
#include "server/cluster/cluster_config.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
#include "server/command_registry.h"
|
#include "server/command_registry.h"
|
||||||
#include "server/conn_context.h"
|
#include "server/conn_context.h"
|
||||||
#include "server/container_utils.h"
|
#include "server/container_utils.h"
|
||||||
|
@ -1231,7 +1231,7 @@ void GenericFamily::Select(CmdArgList args, ConnectionContext* cntx) {
|
||||||
if (!absl::SimpleAtoi(key, &index)) {
|
if (!absl::SimpleAtoi(key, &index)) {
|
||||||
return cntx->SendError(kInvalidDbIndErr);
|
return cntx->SendError(kInvalidDbIndErr);
|
||||||
}
|
}
|
||||||
if (ClusterConfig::IsEnabled() && index != 0) {
|
if (cluster::IsClusterEnabled() && index != 0) {
|
||||||
return cntx->SendError("SELECT is not allowed in cluster mode");
|
return cntx->SendError("SELECT is not allowed in cluster mode");
|
||||||
}
|
}
|
||||||
if (index < 0 || index >= absl::GetFlag(FLAGS_dbnum)) {
|
if (index < 0 || index >= absl::GetFlag(FLAGS_dbnum)) {
|
||||||
|
|
|
@ -67,7 +67,7 @@ void JournalExecutor::FlushAll() {
|
||||||
Execute(cmd);
|
Execute(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JournalExecutor::FlushSlots(const SlotRange& slot_range) {
|
void JournalExecutor::FlushSlots(const cluster::SlotRange& slot_range) {
|
||||||
auto cmd = BuildFromParts("DFLYCLUSTER", "FLUSHSLOTS", slot_range.start, slot_range.end);
|
auto cmd = BuildFromParts("DFLYCLUSTER", "FLUSHSLOTS", slot_range.start, slot_range.end);
|
||||||
Execute(cmd);
|
Execute(cmd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <absl/types/span.h>
|
#include <absl/types/span.h>
|
||||||
|
|
||||||
#include "facade/reply_capture.h"
|
#include "facade/reply_capture.h"
|
||||||
#include "server/cluster/slot_set.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
#include "server/journal/types.h"
|
#include "server/journal/types.h"
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly {
|
||||||
|
@ -26,7 +26,7 @@ class JournalExecutor {
|
||||||
void Execute(DbIndex dbid, journal::ParsedEntry::CmdData& cmd);
|
void Execute(DbIndex dbid, journal::ParsedEntry::CmdData& cmd);
|
||||||
|
|
||||||
void FlushAll(); // Execute FLUSHALL.
|
void FlushAll(); // Execute FLUSHALL.
|
||||||
void FlushSlots(const SlotRange& slot_range);
|
void FlushSlots(const cluster::SlotRange& slot_range);
|
||||||
|
|
||||||
ConnectionContext* connection_context() {
|
ConnectionContext* connection_context() {
|
||||||
return &conn_context_;
|
return &conn_context_;
|
||||||
|
|
|
@ -84,7 +84,7 @@ LSN Journal::GetLsn() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Journal::RecordEntry(TxId txid, Op opcode, DbIndex dbid, unsigned shard_cnt,
|
void Journal::RecordEntry(TxId txid, Op opcode, DbIndex dbid, unsigned shard_cnt,
|
||||||
std::optional<SlotId> slot, Entry::Payload payload, bool await) {
|
std::optional<cluster::SlotId> slot, Entry::Payload payload, bool await) {
|
||||||
journal_slice.AddLogRecord(Entry{txid, opcode, dbid, shard_cnt, slot, std::move(payload)}, await);
|
journal_slice.AddLogRecord(Entry{txid, opcode, dbid, shard_cnt, slot, std::move(payload)}, await);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ class Journal {
|
||||||
LSN GetLsn() const;
|
LSN GetLsn() const;
|
||||||
|
|
||||||
void RecordEntry(TxId txid, Op opcode, DbIndex dbid, unsigned shard_cnt,
|
void RecordEntry(TxId txid, Op opcode, DbIndex dbid, unsigned shard_cnt,
|
||||||
std::optional<SlotId> slot, Entry::Payload payload, bool await);
|
std::optional<cluster::SlotId> slot, Entry::Payload payload, bool await);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable util::fb2::Mutex state_mu_;
|
mutable util::fb2::Mutex state_mu_;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <absl/functional/bind_front.h>
|
#include <absl/functional/bind_front.h>
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "server/cluster/cluster_config.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly {
|
||||||
using namespace util;
|
using namespace util;
|
||||||
|
@ -60,7 +60,7 @@ void JournalStreamer::WriterFb(io::Sink* dest) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RestoreStreamer::RestoreStreamer(DbSlice* slice, SlotSet slots, journal::Journal* journal,
|
RestoreStreamer::RestoreStreamer(DbSlice* slice, cluster::SlotSet slots, journal::Journal* journal,
|
||||||
Context* cntx)
|
Context* cntx)
|
||||||
: JournalStreamer(journal, cntx), db_slice_(slice), my_slots_(std::move(slots)) {
|
: JournalStreamer(journal, cntx), db_slice_(slice), my_slots_(std::move(slots)) {
|
||||||
DCHECK(slice != nullptr);
|
DCHECK(slice != nullptr);
|
||||||
|
@ -130,10 +130,10 @@ bool RestoreStreamer::ShouldWrite(const journal::JournalItem& item) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RestoreStreamer::ShouldWrite(std::string_view key) const {
|
bool RestoreStreamer::ShouldWrite(std::string_view key) const {
|
||||||
return ShouldWrite(ClusterConfig::KeySlot(key));
|
return ShouldWrite(cluster::KeySlot(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RestoreStreamer::ShouldWrite(SlotId slot_id) const {
|
bool RestoreStreamer::ShouldWrite(cluster::SlotId slot_id) const {
|
||||||
return my_slots_.Contains(slot_id);
|
return my_slots_.Contains(slot_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ class JournalStreamer : protected BufferedStreamerBase {
|
||||||
// Only handles relevant slots, while ignoring all others.
|
// Only handles relevant slots, while ignoring all others.
|
||||||
class RestoreStreamer : public JournalStreamer {
|
class RestoreStreamer : public JournalStreamer {
|
||||||
public:
|
public:
|
||||||
RestoreStreamer(DbSlice* slice, SlotSet slots, journal::Journal* journal, Context* cntx);
|
RestoreStreamer(DbSlice* slice, cluster::SlotSet slots, journal::Journal* journal, Context* cntx);
|
||||||
~RestoreStreamer() override;
|
~RestoreStreamer() override;
|
||||||
|
|
||||||
void Start(io::Sink* dest, bool send_lsn = false) override;
|
void Start(io::Sink* dest, bool send_lsn = false) override;
|
||||||
|
@ -70,7 +70,7 @@ class RestoreStreamer : public JournalStreamer {
|
||||||
void OnDbChange(DbIndex db_index, const DbSlice::ChangeReq& req);
|
void OnDbChange(DbIndex db_index, const DbSlice::ChangeReq& req);
|
||||||
bool ShouldWrite(const journal::JournalItem& item) const override;
|
bool ShouldWrite(const journal::JournalItem& item) const override;
|
||||||
bool ShouldWrite(std::string_view key) const;
|
bool ShouldWrite(std::string_view key) const;
|
||||||
bool ShouldWrite(SlotId slot_id) const;
|
bool ShouldWrite(cluster::SlotId slot_id) const;
|
||||||
|
|
||||||
// Returns whether anything was written
|
// Returns whether anything was written
|
||||||
bool WriteBucket(PrimeTable::bucket_iterator it);
|
bool WriteBucket(PrimeTable::bucket_iterator it);
|
||||||
|
@ -79,7 +79,7 @@ class RestoreStreamer : public JournalStreamer {
|
||||||
|
|
||||||
DbSlice* db_slice_;
|
DbSlice* db_slice_;
|
||||||
uint64_t snapshot_version_ = 0;
|
uint64_t snapshot_version_ = 0;
|
||||||
SlotSet my_slots_;
|
cluster::SlotSet my_slots_;
|
||||||
Cancellation fiber_cancellation_;
|
Cancellation fiber_cancellation_;
|
||||||
bool snapshot_finished_ = false;
|
bool snapshot_finished_ = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#include "server/journal/types.h"
|
#include "server/journal/types.h"
|
||||||
|
|
||||||
#include "server/cluster/cluster_config.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
|
|
||||||
namespace dfly::journal {
|
namespace dfly::journal {
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
#include "server/cluster/slot_set.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
#include "server/common.h"
|
#include "server/common.h"
|
||||||
#include "server/table.h"
|
#include "server/table.h"
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ struct EntryBase {
|
||||||
Op opcode;
|
Op opcode;
|
||||||
DbIndex dbid;
|
DbIndex dbid;
|
||||||
uint32_t shard_cnt;
|
uint32_t shard_cnt;
|
||||||
std::optional<SlotId> slot;
|
std::optional<cluster::SlotId> slot;
|
||||||
LSN lsn{0};
|
LSN lsn{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -45,12 +45,12 @@ struct Entry : public EntryBase {
|
||||||
std::pair<std::string_view, ArgSlice> // Command and its shard parts.
|
std::pair<std::string_view, ArgSlice> // Command and its shard parts.
|
||||||
>;
|
>;
|
||||||
|
|
||||||
Entry(TxId txid, Op opcode, DbIndex dbid, uint32_t shard_cnt, std::optional<SlotId> slot_id,
|
Entry(TxId txid, Op opcode, DbIndex dbid, uint32_t shard_cnt,
|
||||||
Payload pl)
|
std::optional<cluster::SlotId> slot_id, Payload pl)
|
||||||
: EntryBase{txid, opcode, dbid, shard_cnt, slot_id}, payload{pl} {
|
: EntryBase{txid, opcode, dbid, shard_cnt, slot_id}, payload{pl} {
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry(journal::Op opcode, DbIndex dbid, std::optional<SlotId> slot_id)
|
Entry(journal::Op opcode, DbIndex dbid, std::optional<cluster::SlotId> slot_id)
|
||||||
: EntryBase{0, opcode, dbid, 0, slot_id, 0} {
|
: EntryBase{0, opcode, dbid, 0, slot_id, 0} {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ struct Entry : public EntryBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry(TxId txid, journal::Op opcode, DbIndex dbid, uint32_t shard_cnt,
|
Entry(TxId txid, journal::Op opcode, DbIndex dbid, uint32_t shard_cnt,
|
||||||
std::optional<SlotId> slot_id)
|
std::optional<cluster::SlotId> slot_id)
|
||||||
: EntryBase{txid, opcode, dbid, shard_cnt, slot_id, 0} {
|
: EntryBase{txid, opcode, dbid, shard_cnt, slot_id, 0} {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ struct JournalItem {
|
||||||
LSN lsn;
|
LSN lsn;
|
||||||
Op opcode;
|
Op opcode;
|
||||||
std::string data;
|
std::string data;
|
||||||
std::optional<SlotId> slot;
|
std::optional<cluster::SlotId> slot;
|
||||||
};
|
};
|
||||||
|
|
||||||
using ChangeCallback = std::function<void(const JournalItem&, bool await)>;
|
using ChangeCallback = std::function<void(const JournalItem&, bool await)>;
|
||||||
|
|
|
@ -575,7 +575,8 @@ void TxTable(const http::QueryArgs& args, HttpContext* send) {
|
||||||
send->Invoke(std::move(resp));
|
send->Invoke(std::move(resp));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClusterHtmlPage(const http::QueryArgs& args, HttpContext* send, ClusterFamily* cluster) {
|
void ClusterHtmlPage(const http::QueryArgs& args, HttpContext* send,
|
||||||
|
cluster::ClusterFamily* cluster_family) {
|
||||||
http::StringResponse resp = http::MakeStringResponse(h2::status::ok);
|
http::StringResponse resp = http::MakeStringResponse(h2::status::ok);
|
||||||
resp.body() = R"(
|
resp.body() = R"(
|
||||||
<html>
|
<html>
|
||||||
|
@ -616,19 +617,19 @@ void ClusterHtmlPage(const http::QueryArgs& args, HttpContext* send, ClusterFami
|
||||||
|
|
||||||
auto print_kb = [&](string_view k, bool v) { print_kv(k, v ? "True" : "False"); };
|
auto print_kb = [&](string_view k, bool v) { print_kv(k, v ? "True" : "False"); };
|
||||||
|
|
||||||
print_kv("Mode", ClusterConfig::IsEmulated() ? "Emulated"
|
print_kv("Mode", cluster::IsClusterEmulated() ? "Emulated"
|
||||||
: ClusterConfig::IsEnabled() ? "Enabled"
|
: cluster::IsClusterEnabled() ? "Enabled"
|
||||||
: "Disabled");
|
: "Disabled");
|
||||||
|
|
||||||
if (ClusterConfig::IsEnabledOrEmulated()) {
|
if (cluster::IsClusterEnabledOrEmulated()) {
|
||||||
print_kb("Lock on hashtags", LockTagOptions::instance().enabled);
|
print_kb("Lock on hashtags", LockTagOptions::instance().enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ClusterConfig::IsEnabled()) {
|
if (cluster::IsClusterEnabled()) {
|
||||||
if (cluster->cluster_config() == nullptr) {
|
if (cluster_family->cluster_config() == nullptr) {
|
||||||
resp.body() += "<h2>Not yet configured.</h2>\n";
|
resp.body() += "<h2>Not yet configured.</h2>\n";
|
||||||
} else {
|
} else {
|
||||||
auto config = cluster->cluster_config()->GetConfig();
|
auto config = cluster_family->cluster_config()->GetConfig();
|
||||||
for (const auto& shard : config) {
|
for (const auto& shard : config) {
|
||||||
resp.body() += "<div class='master'>\n";
|
resp.body() += "<div class='master'>\n";
|
||||||
resp.body() += "<h3>Master</h3>\n";
|
resp.body() += "<h3>Master</h3>\n";
|
||||||
|
@ -922,12 +923,12 @@ optional<ErrorReply> Service::CheckKeysOwnership(const CommandId* cid, CmdArgLis
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& key_index = *key_index_res;
|
const auto& key_index = *key_index_res;
|
||||||
optional<SlotId> keys_slot;
|
optional<cluster::SlotId> keys_slot;
|
||||||
bool cross_slot = false;
|
bool cross_slot = false;
|
||||||
// Iterate keys and check to which slot they belong.
|
// Iterate keys and check to which slot they belong.
|
||||||
for (unsigned i = key_index.start; i < key_index.end; i += key_index.step) {
|
for (unsigned i = key_index.start; i < key_index.end; i += key_index.step) {
|
||||||
string_view key = ArgS(args, i);
|
string_view key = ArgS(args, i);
|
||||||
SlotId slot = ClusterConfig::KeySlot(key);
|
cluster::SlotId slot = cluster::KeySlot(key);
|
||||||
if (keys_slot && slot != *keys_slot) {
|
if (keys_slot && slot != *keys_slot) {
|
||||||
cross_slot = true; // keys belong to different slots
|
cross_slot = true; // keys belong to different slots
|
||||||
break;
|
break;
|
||||||
|
@ -941,14 +942,14 @@ optional<ErrorReply> Service::CheckKeysOwnership(const CommandId* cid, CmdArgLis
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check keys slot is in my ownership
|
// Check keys slot is in my ownership
|
||||||
const ClusterConfig* cluster_config = cluster_family_.cluster_config();
|
const cluster::ClusterConfig* cluster_config = cluster_family_.cluster_config();
|
||||||
if (cluster_config == nullptr) {
|
if (cluster_config == nullptr) {
|
||||||
return ErrorReply{kClusterNotConfigured};
|
return ErrorReply{kClusterNotConfigured};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keys_slot.has_value() && !cluster_config->IsMySlot(*keys_slot)) {
|
if (keys_slot.has_value() && !cluster_config->IsMySlot(*keys_slot)) {
|
||||||
// See more details here: https://redis.io/docs/reference/cluster-spec/#moved-redirection
|
// See more details here: https://redis.io/docs/reference/cluster-spec/#moved-redirection
|
||||||
ClusterNodeInfo master = cluster_config->GetMasterNodeForSlot(*keys_slot);
|
cluster::ClusterNodeInfo master = cluster_config->GetMasterNodeForSlot(*keys_slot);
|
||||||
return ErrorReply{absl::StrCat("-MOVED ", *keys_slot, " ", master.ip, ":", master.port)};
|
return ErrorReply{absl::StrCat("-MOVED ", *keys_slot, " ", master.ip, ":", master.port)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1094,7 +1095,7 @@ std::optional<ErrorReply> Service::VerifyCommandState(const CommandId* cid, CmdA
|
||||||
return ErrorReply{absl::StrCat("'", cmd_name, "' inside MULTI is not allowed")};
|
return ErrorReply{absl::StrCat("'", cmd_name, "' inside MULTI is not allowed")};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ClusterConfig::IsEnabled()) {
|
if (cluster::IsClusterEnabled()) {
|
||||||
if (auto err = CheckKeysOwnership(cid, tail_args, dfly_cntx); err)
|
if (auto err = CheckKeysOwnership(cid, tail_args, dfly_cntx); err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1897,7 +1898,7 @@ void Service::EvalInternal(CmdArgList args, const EvalArgs& eval_args, Interpret
|
||||||
|
|
||||||
optional<ShardId> sid;
|
optional<ShardId> sid;
|
||||||
|
|
||||||
UniqueSlotChecker slot_checker;
|
cluster::UniqueSlotChecker slot_checker;
|
||||||
for (size_t i = 0; i < eval_args.keys.size(); ++i) {
|
for (size_t i = 0; i < eval_args.keys.size(); ++i) {
|
||||||
string_view key = ArgS(eval_args.keys, i);
|
string_view key = ArgS(eval_args.keys, i);
|
||||||
slot_checker.Add(key);
|
slot_checker.Add(key);
|
||||||
|
|
|
@ -181,7 +181,7 @@ class Service : public facade::ServiceInterface {
|
||||||
acl::UserRegistry user_registry_;
|
acl::UserRegistry user_registry_;
|
||||||
acl::AclFamily acl_family_;
|
acl::AclFamily acl_family_;
|
||||||
ServerFamily server_family_;
|
ServerFamily server_family_;
|
||||||
ClusterFamily cluster_family_;
|
cluster::ClusterFamily cluster_family_;
|
||||||
CommandRegistry registry_;
|
CommandRegistry registry_;
|
||||||
absl::flat_hash_map<std::string, unsigned> unknown_cmds_;
|
absl::flat_hash_map<std::string, unsigned> unknown_cmds_;
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ MultiCommandSquasher::MultiCommandSquasher(absl::Span<StoredCmd> cmds, Connectio
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiCommandSquasher::ShardExecInfo& MultiCommandSquasher::PrepareShardInfo(
|
MultiCommandSquasher::ShardExecInfo& MultiCommandSquasher::PrepareShardInfo(
|
||||||
ShardId sid, optional<SlotId> slot_id) {
|
ShardId sid, optional<cluster::SlotId> slot_id) {
|
||||||
if (sharded_.empty())
|
if (sharded_.empty())
|
||||||
sharded_.resize(shard_set->size());
|
sharded_.resize(shard_set->size());
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ MultiCommandSquasher::SquashResult MultiCommandSquasher::TrySquash(StoredCmd* cm
|
||||||
|
|
||||||
// Check if all commands belong to one shard
|
// Check if all commands belong to one shard
|
||||||
bool found_more = false;
|
bool found_more = false;
|
||||||
UniqueSlotChecker slot_checker;
|
cluster::UniqueSlotChecker slot_checker;
|
||||||
ShardId last_sid = kInvalidSid;
|
ShardId last_sid = kInvalidSid;
|
||||||
IterateKeys(args, *keys, [&last_sid, &found_more, &slot_checker](MutableSlice key) {
|
IterateKeys(args, *keys, [&last_sid, &found_more, &slot_checker](MutableSlice key) {
|
||||||
if (found_more)
|
if (found_more)
|
||||||
|
|
|
@ -48,7 +48,7 @@ class MultiCommandSquasher {
|
||||||
bool verify_commands, bool error_abort);
|
bool verify_commands, bool error_abort);
|
||||||
|
|
||||||
// Lazy initialize shard info.
|
// Lazy initialize shard info.
|
||||||
ShardExecInfo& PrepareShardInfo(ShardId sid, std::optional<SlotId> slot_id);
|
ShardExecInfo& PrepareShardInfo(ShardId sid, std::optional<cluster::SlotId> slot_id);
|
||||||
|
|
||||||
// Retrun squash flags
|
// Retrun squash flags
|
||||||
SquashResult TrySquash(StoredCmd* cmd);
|
SquashResult TrySquash(StoredCmd* cmd);
|
||||||
|
|
|
@ -3,10 +3,8 @@
|
||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <absl/container/inlined_vector.h>
|
|
||||||
#include <absl/strings/escaping.h>
|
#include <absl/strings/escaping.h>
|
||||||
|
|
||||||
#include <boost/fiber/barrier.hpp>
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ vector<vector<unsigned>> Partition(unsigned num_flows) {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Replica::Replica(string host, uint16_t port, Service* se, std::string_view id,
|
Replica::Replica(string host, uint16_t port, Service* se, std::string_view id,
|
||||||
std::optional<SlotRange> slot_range)
|
std::optional<cluster::SlotRange> slot_range)
|
||||||
: ProtocolClient(std::move(host), port), service_(*se), id_{id}, slot_range_(slot_range) {
|
: ProtocolClient(std::move(host), port), service_(*se), id_{id}, slot_range_(slot_range) {
|
||||||
proactor_ = ProactorBase::me();
|
proactor_ = ProactorBase::me();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "base/io_buf.h"
|
#include "base/io_buf.h"
|
||||||
#include "facade/facade_types.h"
|
#include "facade/facade_types.h"
|
||||||
#include "facade/redis_parser.h"
|
#include "facade/redis_parser.h"
|
||||||
#include "server/cluster/slot_set.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
#include "server/common.h"
|
#include "server/common.h"
|
||||||
#include "server/journal/tx_executor.h"
|
#include "server/journal/tx_executor.h"
|
||||||
#include "server/journal/types.h"
|
#include "server/journal/types.h"
|
||||||
|
@ -55,7 +55,7 @@ class Replica : ProtocolClient {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Replica(std::string master_host, uint16_t port, Service* se, std::string_view id,
|
Replica(std::string master_host, uint16_t port, Service* se, std::string_view id,
|
||||||
std::optional<SlotRange> slot_range);
|
std::optional<cluster::SlotRange> slot_range);
|
||||||
~Replica();
|
~Replica();
|
||||||
|
|
||||||
// Spawns a fiber that runs until link with master is broken or the replication is stopped.
|
// Spawns a fiber that runs until link with master is broken or the replication is stopped.
|
||||||
|
@ -173,7 +173,7 @@ class Replica : ProtocolClient {
|
||||||
bool is_paused_ = false;
|
bool is_paused_ = false;
|
||||||
std::string id_;
|
std::string id_;
|
||||||
|
|
||||||
std::optional<SlotRange> slot_range_;
|
std::optional<cluster::SlotRange> slot_range_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This class implements a single shard replication flow from a Dragonfly master instance.
|
// This class implements a single shard replication flow from a Dragonfly master instance.
|
||||||
|
|
|
@ -549,13 +549,13 @@ std::string_view GetOSString() {
|
||||||
}
|
}
|
||||||
|
|
||||||
string_view GetRedisMode() {
|
string_view GetRedisMode() {
|
||||||
return ClusterConfig::IsEnabledOrEmulated() ? "cluster"sv : "standalone"sv;
|
return cluster::IsClusterEnabledOrEmulated() ? "cluster"sv : "standalone"sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ReplicaOfArgs {
|
struct ReplicaOfArgs {
|
||||||
string host;
|
string host;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
std::optional<SlotRange> slot_range;
|
std::optional<cluster::SlotRange> slot_range;
|
||||||
static optional<ReplicaOfArgs> FromCmdArgs(CmdArgList args, ConnectionContext* cntx);
|
static optional<ReplicaOfArgs> FromCmdArgs(CmdArgList args, ConnectionContext* cntx);
|
||||||
bool IsReplicaOfNoOne() const {
|
bool IsReplicaOfNoOne() const {
|
||||||
return port == 0;
|
return port == 0;
|
||||||
|
@ -588,8 +588,8 @@ optional<ReplicaOfArgs> ReplicaOfArgs::FromCmdArgs(CmdArgList args, ConnectionCo
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
if (parser.HasNext()) {
|
if (parser.HasNext()) {
|
||||||
auto [slot_start, slot_end] = parser.Next<SlotId, SlotId>();
|
auto [slot_start, slot_end] = parser.Next<cluster::SlotId, cluster::SlotId>();
|
||||||
replicaof_args.slot_range = SlotRange{slot_start, slot_end};
|
replicaof_args.slot_range = cluster::SlotRange{slot_start, slot_end};
|
||||||
if (auto err = parser.Error(); err || !replicaof_args.slot_range->IsValid()) {
|
if (auto err = parser.Error(); err || !replicaof_args.slot_range->IsValid()) {
|
||||||
cntx->SendError("Invalid slot range");
|
cntx->SendError("Invalid slot range");
|
||||||
return nullopt;
|
return nullopt;
|
||||||
|
@ -2259,7 +2259,7 @@ void ServerFamily::Info(CmdArgList args, ConnectionContext* cntx) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (should_enter("CLUSTER")) {
|
if (should_enter("CLUSTER")) {
|
||||||
append("cluster_enabled", ClusterConfig::IsEnabledOrEmulated());
|
append("cluster_enabled", cluster::IsClusterEnabledOrEmulated());
|
||||||
}
|
}
|
||||||
auto* rb = static_cast<RedisReplyBuilder*>(cntx->reply_builder());
|
auto* rb = static_cast<RedisReplyBuilder*>(cntx->reply_builder());
|
||||||
rb->SendVerbatimString(info);
|
rb->SendVerbatimString(info);
|
||||||
|
|
|
@ -43,8 +43,10 @@ std::string GetPassword();
|
||||||
namespace journal {
|
namespace journal {
|
||||||
class Journal;
|
class Journal;
|
||||||
} // namespace journal
|
} // namespace journal
|
||||||
|
namespace cluster {
|
||||||
class ClusterFamily;
|
class ClusterFamily;
|
||||||
|
}
|
||||||
|
|
||||||
class ConnectionContext;
|
class ConnectionContext;
|
||||||
class CommandRegistry;
|
class CommandRegistry;
|
||||||
class DflyCmd;
|
class DflyCmd;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include "base/flags.h"
|
#include "base/flags.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "server/cluster/cluster_config.h"
|
#include "server/cluster/cluster_defs.h"
|
||||||
#include "server/server_state.h"
|
#include "server/server_state.h"
|
||||||
|
|
||||||
ABSL_FLAG(bool, enable_top_keys_tracking, false,
|
ABSL_FLAG(bool, enable_top_keys_tracking, false,
|
||||||
|
@ -86,8 +86,8 @@ DbTable::DbTable(PMR_NS::memory_resource* mr, DbIndex db_index)
|
||||||
mcflag(0, detail::ExpireTablePolicy{}, mr),
|
mcflag(0, detail::ExpireTablePolicy{}, mr),
|
||||||
top_keys({.enabled = absl::GetFlag(FLAGS_enable_top_keys_tracking)}),
|
top_keys({.enabled = absl::GetFlag(FLAGS_enable_top_keys_tracking)}),
|
||||||
index(db_index) {
|
index(db_index) {
|
||||||
if (ClusterConfig::IsEnabled()) {
|
if (cluster::IsClusterEnabled()) {
|
||||||
slots_stats.resize(ClusterConfig::kMaxSlotNum + 1);
|
slots_stats.resize(cluster::kMaxSlotNum + 1);
|
||||||
}
|
}
|
||||||
thread_index = ServerState::tlocal()->thread_index();
|
thread_index = ServerState::tlocal()->thread_index();
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,8 @@ Transaction::Transaction(const CommandId* cid) : cid_{cid} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Transaction::Transaction(const Transaction* parent, ShardId shard_id, std::optional<SlotId> slot_id)
|
Transaction::Transaction(const Transaction* parent, ShardId shard_id,
|
||||||
|
std::optional<cluster::SlotId> slot_id)
|
||||||
: multi_{make_unique<MultiData>()},
|
: multi_{make_unique<MultiData>()},
|
||||||
txid_{parent->txid()},
|
txid_{parent->txid()},
|
||||||
unique_shard_cnt_{1},
|
unique_shard_cnt_{1},
|
||||||
|
@ -1008,7 +1009,7 @@ ShardId Transaction::GetUniqueShard() const {
|
||||||
return unique_shard_id_;
|
return unique_shard_id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<SlotId> Transaction::GetUniqueSlotId() const {
|
optional<cluster::SlotId> Transaction::GetUniqueSlotId() const {
|
||||||
return unique_slot_checker_.GetUniqueSlotId();
|
return unique_slot_checker_.GetUniqueSlotId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,8 @@ class Transaction {
|
||||||
explicit Transaction(const CommandId* cid);
|
explicit Transaction(const CommandId* cid);
|
||||||
|
|
||||||
// Initialize transaction for squashing placed on a specific shard with a given parent tx
|
// Initialize transaction for squashing placed on a specific shard with a given parent tx
|
||||||
explicit Transaction(const Transaction* parent, ShardId shard_id, std::optional<SlotId> slot_id);
|
explicit Transaction(const Transaction* parent, ShardId shard_id,
|
||||||
|
std::optional<cluster::SlotId> slot_id);
|
||||||
|
|
||||||
// Initialize from command (args) on specific db.
|
// Initialize from command (args) on specific db.
|
||||||
OpStatus InitByArgs(DbIndex index, CmdArgList args);
|
OpStatus InitByArgs(DbIndex index, CmdArgList args);
|
||||||
|
@ -280,7 +281,7 @@ class Transaction {
|
||||||
// This method is meaningless if GetUniqueShardCnt() != 1.
|
// This method is meaningless if GetUniqueShardCnt() != 1.
|
||||||
ShardId GetUniqueShard() const;
|
ShardId GetUniqueShard() const;
|
||||||
|
|
||||||
std::optional<SlotId> GetUniqueSlotId() const;
|
std::optional<cluster::SlotId> GetUniqueSlotId() const;
|
||||||
|
|
||||||
bool IsMulti() const {
|
bool IsMulti() const {
|
||||||
return bool(multi_);
|
return bool(multi_);
|
||||||
|
@ -616,7 +617,7 @@ class Transaction {
|
||||||
|
|
||||||
uint32_t unique_shard_cnt_{0}; // Number of unique shards active
|
uint32_t unique_shard_cnt_{0}; // Number of unique shards active
|
||||||
ShardId unique_shard_id_{kInvalidSid}; // Set if unique_shard_cnt_ = 1
|
ShardId unique_shard_id_{kInvalidSid}; // Set if unique_shard_cnt_ = 1
|
||||||
UniqueSlotChecker unique_slot_checker_;
|
cluster::UniqueSlotChecker unique_slot_checker_;
|
||||||
|
|
||||||
// Barrier for waking blocking transactions that ensures exclusivity of waking operation.
|
// Barrier for waking blocking transactions that ensures exclusivity of waking operation.
|
||||||
BatonBarrier blocking_barrier_{};
|
BatonBarrier blocking_barrier_{};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue