[CCF Archive] Store object type eviction policy submission #3

Closed
kancel wants to merge 382 commits from kancel:ccf-archive-pr2746 into main
15 changed files with 484 additions and 139 deletions
Showing only changes of commit a953dcb110 - Show all commits

View File

@ -1919,7 +1919,8 @@ PYBIND11_MODULE(store, m) {
const std::string &master_server_addr = "127.0.0.1:50051",
const py::object &engine = py::none(),
bool enable_ssd_offload = false,
const std::string &ssd_offload_path = "") {
const std::string &ssd_offload_path = "",
const std::string &tenant_id = "default") {
auto real_client = self.init_real_client();
std::shared_ptr<mooncake::TransferEngine> transfer_engine =
nullptr;
@ -1931,14 +1932,14 @@ PYBIND11_MODULE(store, m) {
local_hostname, metadata_server, global_segment_size,
local_buffer_size, protocol, rdma_devices,
master_server_addr, transfer_engine, "", enable_ssd_offload,
ssd_offload_path);
ssd_offload_path, tenant_id);
},
py::arg("local_hostname"), py::arg("metadata_server"),
py::arg("global_segment_size"), py::arg("local_buffer_size"),
py::arg("protocol"), py::arg("rdma_devices"),
py::arg("master_server_addr"), py::arg("engine") = py::none(),
py::arg("enable_ssd_offload") = false,
py::arg("ssd_offload_path") = "")
py::arg("ssd_offload_path") = "", py::arg("tenant_id") = "default")
.def(
"setup",
[](MooncakeStorePyWrapper &self, const py::dict &config_dict) {

View File

@ -86,7 +86,8 @@ class Client {
const std::optional<std::string>& device_names = std::nullopt,
const std::string& master_server_entry = kDefaultMasterAddress,
const std::shared_ptr<TransferEngine>& transfer_engine = nullptr,
std::map<std::string, std::string> labels = {});
std::map<std::string, std::string> labels = {},
const std::string& tenant_id = "default");
/**
* @brief Retrieves data for a given key
@ -627,7 +628,8 @@ class Client {
*/
Client(const std::string& local_hostname,
const std::string& metadata_connstring, const std::string& protocol,
const std::map<std::string, std::string>& labels = {});
const std::map<std::string, std::string>& labels = {},
const std::string& tenant_id = "default");
private:
/**

View File

@ -29,7 +29,8 @@ class DummyClient : public PyClient {
const std::shared_ptr<TransferEngine> &transfer_engine,
const std::string &ipc_socket_path,
bool enable_ssd_offload = false,
const std::string &ssd_offload_path = "") {
const std::string &ssd_offload_path = "",
const std::string &tenant_id = "default") {
// Dummy client does not support real setup
return -1;
};

View File

@ -52,8 +52,11 @@ inline void MaybeEnableRdmaSocketConfig(SocketConfigVariant& socket_config) {
*/
class MasterClient {
public:
MasterClient(const UUID& client_id, MasterClientMetric* metrics = nullptr)
: client_id_(client_id), metrics_(metrics) {
MasterClient(const UUID& client_id, MasterClientMetric* metrics = nullptr,
std::string tenant_id = "default")
: client_id_(client_id),
tenant_id_(NormalizeTenantId(std::move(tenant_id))),
metrics_(metrics) {
coro_io::client_pool<coro_rpc::coro_rpc_client>::pool_config
pool_conf{};
@ -635,6 +638,9 @@ class MasterClient {
// The client identification.
const UUID client_id_;
// Tenant identity for this client instance.
const std::string tenant_id_;
// Metrics for tracking RPC operations
MasterClientMetric* metrics_;
std::shared_ptr<coro_io::client_pools<coro_rpc::coro_rpc_client>>

View File

@ -318,6 +318,9 @@ class MasterService {
*/
auto PutRevoke(const UUID& client_id, const std::string& key,
ReplicaType replica_type) -> tl::expected<void, ErrorCode>;
auto PutRevoke(const UUID& client_id, const std::string& key,
const std::string& tenant_id, ReplicaType replica_type)
-> tl::expected<void, ErrorCode>;
/**
* @brief Complete a batch of put operations
@ -327,6 +330,10 @@ class MasterService {
std::vector<tl::expected<void, ErrorCode>> BatchPutEnd(
const UUID& client_id, const std::vector<std::string>& keys,
ReplicaType replica_type = ReplicaType::ALL);
std::vector<tl::expected<void, ErrorCode>> BatchPutEnd(
const UUID& client_id, const std::vector<std::string>& keys,
const std::string& tenant_id,
ReplicaType replica_type = ReplicaType::ALL);
/**
* @brief Revoke a batch of put operations
@ -336,6 +343,10 @@ class MasterService {
std::vector<tl::expected<void, ErrorCode>> BatchPutRevoke(
const UUID& client_id, const std::vector<std::string>& keys,
ReplicaType replica_type = ReplicaType::ALL);
std::vector<tl::expected<void, ErrorCode>> BatchPutRevoke(
const UUID& client_id, const std::vector<std::string>& keys,
const std::string& tenant_id,
ReplicaType replica_type = ReplicaType::ALL);
/**
* @brief Start an upsert operation. If the key does not exist, behaves
@ -359,6 +370,9 @@ class MasterService {
*/
auto UpsertEnd(const UUID& client_id, const std::string& key,
ReplicaType replica_type) -> tl::expected<void, ErrorCode>;
auto UpsertEnd(const UUID& client_id, const std::string& key,
const std::string& tenant_id, ReplicaType replica_type)
-> tl::expected<void, ErrorCode>;
/**
* @brief Revoke an upsert operation. Delegates to PutRevoke.
@ -366,6 +380,9 @@ class MasterService {
auto UpsertRevoke(const UUID& client_id, const std::string& key,
ReplicaType replica_type)
-> tl::expected<void, ErrorCode>;
auto UpsertRevoke(const UUID& client_id, const std::string& key,
const std::string& tenant_id, ReplicaType replica_type)
-> tl::expected<void, ErrorCode>;
/**
* @brief Start a batch of upsert operations.
@ -375,18 +392,30 @@ class MasterService {
const std::vector<std::string>& keys,
const std::vector<uint64_t>& slice_lengths,
const ReplicateConfig& config);
std::vector<tl::expected<std::vector<Replica::Descriptor>, ErrorCode>>
BatchUpsertStart(const UUID& client_id,
const std::vector<std::string>& keys,
const std::string& tenant_id,
const std::vector<uint64_t>& slice_lengths,
const ReplicateConfig& config);
/**
* @brief Complete a batch of upsert operations. Delegates to BatchPutEnd.
*/
std::vector<tl::expected<void, ErrorCode>> BatchUpsertEnd(
const UUID& client_id, const std::vector<std::string>& keys);
std::vector<tl::expected<void, ErrorCode>> BatchUpsertEnd(
const UUID& client_id, const std::vector<std::string>& keys,
const std::string& tenant_id);
/**
* @brief Revoke a batch of upsert operations. Delegates to BatchPutRevoke.
*/
std::vector<tl::expected<void, ErrorCode>> BatchUpsertRevoke(
const UUID& client_id, const std::vector<std::string>& keys);
std::vector<tl::expected<void, ErrorCode>> BatchUpsertRevoke(
const UUID& client_id, const std::vector<std::string>& keys,
const std::string& tenant_id);
/**
* @brief Evict a disk replica for a key (triggered by client-side disk
@ -483,12 +512,20 @@ class MasterService {
bool force = false) -> tl::expected<long, ErrorCode>;
/**
* @brief Remove all objects and their replicas
* @brief Remove all objects and their replicas across all tenants.
* @param force If true, skip lease and replication task checks.
* @return return the number of objects removed
*/
long RemoveAll(bool force = false);
/**
* @brief Remove all objects and their replicas for a single tenant.
* @param tenant_id The tenant whose objects should be removed.
* @param force If true, skip lease and replication task checks.
* @return return the number of objects removed
*/
long RemoveAll(const std::string& tenant_id, bool force = false);
/**
* @brief Batch remove objects and their replicas
* @param keys The list of keys to remove.
@ -497,6 +534,9 @@ class MasterService {
*/
auto BatchRemove(const std::vector<std::string>& keys, bool force = false)
-> std::vector<tl::expected<void, ErrorCode>>;
auto BatchRemove(const std::vector<std::string>& keys,
const std::string& tenant_id, bool force = false)
-> std::vector<tl::expected<void, ErrorCode>>;
/**
* @brief Get the count of keys

View File

@ -215,7 +215,8 @@ class PyClient {
const std::string &master_server_addr,
const std::shared_ptr<TransferEngine> &transfer_engine,
const std::string &ipc_socket_path, bool enable_ssd_offload = false,
const std::string &ssd_offload_path = "") = 0;
const std::string &ssd_offload_path = "",
const std::string &tenant_id = "default") = 0;
virtual int setup_dummy(size_t mem_pool_size, size_t local_buffer_size,
const std::string &server_address,

View File

@ -82,7 +82,8 @@ class RealClient : public PyClient {
const std::shared_ptr<TransferEngine> &transfer_engine = nullptr,
const std::string &ipc_socket_path = "",
bool enable_ssd_offload = false,
const std::string &ssd_offload_path = "");
const std::string &ssd_offload_path = "",
const std::string &tenant_id = "default");
int setup_dummy(size_t mem_pool_size, size_t local_buffer_size,
const std::string &server_address,
@ -503,7 +504,8 @@ class RealClient : public PyClient {
const std::shared_ptr<TransferEngine> &transfer_engine = nullptr,
const std::string &ipc_socket_path = "", int local_rpc_port = 50052,
bool enable_ssd_offload = false, bool start_offload_rpc_server = false,
const std::string &ssd_offload_path = "");
const std::string &ssd_offload_path = "",
const std::string &tenant_id = "default");
// Overload that accepts a configuration dictionary
tl::expected<void, ErrorCode> setup_internal(const ConfigDict &config);

View File

@ -30,13 +30,15 @@ class WrappedMasterService {
~WrappedMasterService();
tl::expected<bool, ErrorCode> ExistKey(const std::string& key);
tl::expected<bool, ErrorCode> ExistKey(
const std::string& key, const std::string& tenant_id = "default");
tl::expected<MasterMetricManager::CacheHitStatDict, ErrorCode>
CalcCacheStats();
std::vector<tl::expected<bool, ErrorCode>> BatchExistKey(
const std::vector<std::string>& keys);
const std::vector<std::string>& keys,
const std::string& tenant_id = "default");
tl::expected<
std::unordered_map<UUID, std::vector<std::string>, boost::hash<UUID>>,
@ -50,73 +52,91 @@ class WrappedMasterService {
tl::expected<
std::unordered_map<std::string, std::vector<Replica::Descriptor>>,
ErrorCode>
GetReplicaListByRegex(const std::string& str);
GetReplicaListByRegex(const std::string& str,
const std::string& tenant_id = "default");
tl::expected<GetReplicaListResponse, ErrorCode> GetReplicaList(
const std::string& key);
const std::string& key, const std::string& tenant_id = "default");
std::vector<tl::expected<GetReplicaListResponse, ErrorCode>>
BatchGetReplicaList(const std::vector<std::string>& keys);
BatchGetReplicaList(const std::vector<std::string>& keys,
const std::string& tenant_id = "default");
tl::expected<std::vector<Replica::Descriptor>, ErrorCode> PutStart(
const UUID& client_id, const std::string& key,
const uint64_t slice_length, const ReplicateConfig& config);
const uint64_t slice_length, const ReplicateConfig& config,
const std::string& tenant_id = "default");
tl::expected<void, ErrorCode> PutEnd(
const UUID& client_id, const std::string& key,
ReplicaType replica_type = ReplicaType::ALL);
ReplicaType replica_type = ReplicaType::ALL,
const std::string& tenant_id = "default");
tl::expected<void, ErrorCode> PutRevoke(
const UUID& client_id, const std::string& key,
ReplicaType replica_type = ReplicaType::ALL);
ReplicaType replica_type = ReplicaType::ALL,
const std::string& tenant_id = "default");
std::vector<tl::expected<std::vector<Replica::Descriptor>, ErrorCode>>
BatchPutStart(const UUID& client_id, const std::vector<std::string>& keys,
const std::vector<uint64_t>& slice_lengths,
const ReplicateConfig& config);
const ReplicateConfig& config,
const std::string& tenant_id = "default");
std::vector<tl::expected<void, ErrorCode>> BatchPutEnd(
const UUID& client_id, const std::vector<std::string>& keys,
ReplicaType replica_type = ReplicaType::ALL);
ReplicaType replica_type = ReplicaType::ALL,
const std::string& tenant_id = "default");
std::vector<tl::expected<void, ErrorCode>> BatchPutRevoke(
const UUID& client_id, const std::vector<std::string>& keys,
ReplicaType replica_type = ReplicaType::ALL);
ReplicaType replica_type = ReplicaType::ALL,
const std::string& tenant_id = "default");
tl::expected<std::vector<Replica::Descriptor>, ErrorCode> UpsertStart(
const UUID& client_id, const std::string& key,
const uint64_t slice_length, const ReplicateConfig& config);
const uint64_t slice_length, const ReplicateConfig& config,
const std::string& tenant_id = "default");
tl::expected<void, ErrorCode> UpsertEnd(const UUID& client_id,
const std::string& key,
ReplicaType replica_type);
tl::expected<void, ErrorCode> UpsertEnd(
const UUID& client_id, const std::string& key,
ReplicaType replica_type = ReplicaType::ALL,
const std::string& tenant_id = "default");
tl::expected<void, ErrorCode> UpsertRevoke(const UUID& client_id,
const std::string& key,
ReplicaType replica_type);
tl::expected<void, ErrorCode> UpsertRevoke(
const UUID& client_id, const std::string& key,
ReplicaType replica_type = ReplicaType::ALL,
const std::string& tenant_id = "default");
std::vector<tl::expected<std::vector<Replica::Descriptor>, ErrorCode>>
BatchUpsertStart(const UUID& client_id,
const std::vector<std::string>& keys,
const std::vector<uint64_t>& slice_lengths,
const ReplicateConfig& config);
const ReplicateConfig& config,
const std::string& tenant_id = "default");
std::vector<tl::expected<void, ErrorCode>> BatchUpsertEnd(
const UUID& client_id, const std::vector<std::string>& keys);
const UUID& client_id, const std::vector<std::string>& keys,
const std::string& tenant_id = "default");
std::vector<tl::expected<void, ErrorCode>> BatchUpsertRevoke(
const UUID& client_id, const std::vector<std::string>& keys);
const UUID& client_id, const std::vector<std::string>& keys,
const std::string& tenant_id = "default");
tl::expected<void, ErrorCode> Remove(const std::string& key,
bool force = false);
tl::expected<void, ErrorCode> Remove(
const std::string& key, bool force = false,
const std::string& tenant_id = "default");
tl::expected<long, ErrorCode> RemoveByRegex(const std::string& str,
bool force = false);
tl::expected<long, ErrorCode> RemoveByRegex(
const std::string& str, bool force = false,
const std::string& tenant_id = "default");
long RemoveAll(bool force = false);
long RemoveAll(bool force = false,
const std::string& tenant_id = "default");
std::vector<tl::expected<void, ErrorCode>> BatchRemove(
const std::vector<std::string>& keys, bool force = false);
const std::vector<std::string>& keys, bool force = false,
const std::string& tenant_id = "default");
tl::expected<void, ErrorCode> MountSegment(const Segment& segment,
const UUID& client_id);

View File

@ -215,6 +215,7 @@ constexpr const char* CONFIG_KEY_PROTOCOL = "protocol";
constexpr const char* CONFIG_KEY_RDMA_DEVICES = "rdma_devices";
constexpr const char* CONFIG_KEY_MASTER_SERVER_ADDR = "master_server_addr";
constexpr const char* CONFIG_KEY_IPC_SOCKET_PATH = "ipc_socket_path";
constexpr const char* CONFIG_KEY_TENANT_ID = "tenant_id";
// Store client configuration defaults
static constexpr size_t DEFAULT_GLOBAL_SEGMENT_SIZE = 1024 * 1024 * 16; // 16MB

View File

@ -272,11 +272,13 @@ FinalizeDecision DetermineFinalizeDecision(
Client::Client(const std::string& local_hostname,
const std::string& metadata_connstring,
const std::string& protocol,
const std::map<std::string, std::string>& labels)
const std::map<std::string, std::string>& labels,
const std::string& tenant_id)
: client_id_(generate_uuid()),
metrics_(ClientMetric::Create(merge_labels(labels))),
master_client_(client_id_,
metrics_ ? &metrics_->master_client_metric : nullptr),
metrics_ ? &metrics_->master_client_metric : nullptr,
tenant_id),
local_hostname_(local_hostname),
metadata_connstring_(metadata_connstring),
protocol_(protocol),
@ -832,9 +834,9 @@ std::optional<std::shared_ptr<Client>> Client::Create(
const std::string& protocol, const std::optional<std::string>& device_names,
const std::string& master_server_entry,
const std::shared_ptr<TransferEngine>& transfer_engine,
std::map<std::string, std::string> labels) {
auto client = std::shared_ptr<Client>(
new Client(local_hostname, metadata_connstring, protocol, labels));
std::map<std::string, std::string> labels, const std::string& tenant_id) {
auto client = std::shared_ptr<Client>(new Client(
local_hostname, metadata_connstring, protocol, labels, tenant_id));
ErrorCode err = client->ConnectToMaster(master_server_entry);
if (err != ErrorCode::OK) {

View File

@ -445,7 +445,8 @@ tl::expected<bool, ErrorCode> MasterClient::ExistKey(
ScopedVLogTimer timer(1, "MasterClient::ExistKey");
timer.LogRequest("object_key=", object_key);
auto result = invoke_rpc<&WrappedMasterService::ExistKey, bool>(object_key);
auto result = invoke_rpc<&WrappedMasterService::ExistKey, bool>(object_key,
tenant_id_);
timer.LogResponseExpected(result);
return result;
}
@ -456,7 +457,7 @@ std::vector<tl::expected<bool, ErrorCode>> MasterClient::BatchExistKey(
timer.LogRequest("keys_count=", object_keys.size());
auto result = invoke_batch_rpc<&WrappedMasterService::BatchExistKey, bool>(
object_keys.size(), object_keys);
object_keys.size(), object_keys, tenant_id_);
timer.LogResponse("result=", result.size(), " keys");
return result;
}
@ -506,7 +507,8 @@ MasterClient::GetReplicaListByRegex(const std::string& str) {
auto result = invoke_rpc<
&WrappedMasterService::GetReplicaListByRegex,
std::unordered_map<std::string, std::vector<Replica::Descriptor>>>(str);
std::unordered_map<std::string, std::vector<Replica::Descriptor>>>(
str, tenant_id_);
timer.LogResponseExpected(result);
return result;
@ -518,7 +520,7 @@ tl::expected<GetReplicaListResponse, ErrorCode> MasterClient::GetReplicaList(
timer.LogRequest("object_key=", object_key);
auto result = invoke_rpc<&WrappedMasterService::GetReplicaList,
GetReplicaListResponse>(object_key);
GetReplicaListResponse>(object_key, tenant_id_);
timer.LogResponseExpected(result);
return result;
}
@ -529,8 +531,8 @@ MasterClient::BatchGetReplicaList(const std::vector<std::string>& object_keys) {
timer.LogRequest("keys_count=", object_keys.size());
auto result = invoke_batch_rpc<&WrappedMasterService::BatchGetReplicaList,
GetReplicaListResponse>(object_keys.size(),
object_keys);
GetReplicaListResponse>(
object_keys.size(), object_keys, tenant_id_);
timer.LogResponse("result=", result.size(), " operations");
return result;
}
@ -549,7 +551,7 @@ MasterClient::PutStart(const std::string& key,
auto result = invoke_rpc<&WrappedMasterService::PutStart,
std::vector<Replica::Descriptor>>(
client_id_, key, total_slice_length, config);
client_id_, key, total_slice_length, config, tenant_id_);
timer.LogResponseExpected(result);
return result;
}
@ -574,7 +576,7 @@ MasterClient::BatchPutStart(
auto result = invoke_batch_rpc<&WrappedMasterService::BatchPutStart,
std::vector<Replica::Descriptor>>(
keys.size(), client_id_, keys, total_slice_lengths, config);
keys.size(), client_id_, keys, total_slice_lengths, config, tenant_id_);
timer.LogResponse("result=", result.size(), " operations");
return result;
}
@ -585,7 +587,7 @@ tl::expected<void, ErrorCode> MasterClient::PutEnd(const std::string& key,
timer.LogRequest("key=", key);
auto result = invoke_rpc<&WrappedMasterService::PutEnd, void>(
client_id_, key, replica_type);
client_id_, key, replica_type, tenant_id_);
timer.LogResponseExpected(result);
return result;
}
@ -596,7 +598,7 @@ std::vector<tl::expected<void, ErrorCode>> MasterClient::BatchPutEnd(
timer.LogRequest("keys_count=", keys.size());
auto result = invoke_batch_rpc<&WrappedMasterService::BatchPutEnd, void>(
keys.size(), client_id_, keys, replica_type);
keys.size(), client_id_, keys, replica_type, tenant_id_);
timer.LogResponse("result=", result.size(), " operations");
return result;
}
@ -607,7 +609,7 @@ tl::expected<void, ErrorCode> MasterClient::PutRevoke(
timer.LogRequest("key=", key);
auto result = invoke_rpc<&WrappedMasterService::PutRevoke, void>(
client_id_, key, replica_type);
client_id_, key, replica_type, tenant_id_);
timer.LogResponseExpected(result);
return result;
}
@ -618,7 +620,7 @@ std::vector<tl::expected<void, ErrorCode>> MasterClient::BatchPutRevoke(
timer.LogRequest("keys_count=", keys.size());
auto result = invoke_batch_rpc<&WrappedMasterService::BatchPutRevoke, void>(
keys.size(), client_id_, keys, replica_type);
keys.size(), client_id_, keys, replica_type, tenant_id_);
timer.LogResponse("result=", result.size(), " operations");
return result;
}
@ -637,7 +639,7 @@ MasterClient::UpsertStart(const std::string& key,
auto result = invoke_rpc<&WrappedMasterService::UpsertStart,
std::vector<Replica::Descriptor>>(
client_id_, key, total_slice_length, config);
client_id_, key, total_slice_length, config, tenant_id_);
timer.LogResponseExpected(result);
return result;
}
@ -662,7 +664,7 @@ MasterClient::BatchUpsertStart(
auto result = invoke_batch_rpc<&WrappedMasterService::BatchUpsertStart,
std::vector<Replica::Descriptor>>(
keys.size(), client_id_, keys, total_slice_lengths, config);
keys.size(), client_id_, keys, total_slice_lengths, config, tenant_id_);
timer.LogResponse("result=", result.size(), " operations");
return result;
}
@ -673,7 +675,7 @@ tl::expected<void, ErrorCode> MasterClient::UpsertEnd(
timer.LogRequest("key=", key);
auto result = invoke_rpc<&WrappedMasterService::UpsertEnd, void>(
client_id_, key, replica_type);
client_id_, key, replica_type, tenant_id_);
timer.LogResponseExpected(result);
return result;
}
@ -684,7 +686,7 @@ std::vector<tl::expected<void, ErrorCode>> MasterClient::BatchUpsertEnd(
timer.LogRequest("keys_count=", keys.size());
auto result = invoke_batch_rpc<&WrappedMasterService::BatchUpsertEnd, void>(
keys.size(), client_id_, keys);
keys.size(), client_id_, keys, tenant_id_);
timer.LogResponse("result=", result.size(), " operations");
return result;
}
@ -695,7 +697,7 @@ tl::expected<void, ErrorCode> MasterClient::UpsertRevoke(
timer.LogRequest("key=", key);
auto result = invoke_rpc<&WrappedMasterService::UpsertRevoke, void>(
client_id_, key, replica_type);
client_id_, key, replica_type, tenant_id_);
timer.LogResponseExpected(result);
return result;
}
@ -707,7 +709,7 @@ std::vector<tl::expected<void, ErrorCode>> MasterClient::BatchUpsertRevoke(
auto result =
invoke_batch_rpc<&WrappedMasterService::BatchUpsertRevoke, void>(
keys.size(), client_id_, keys);
keys.size(), client_id_, keys, tenant_id_);
timer.LogResponse("result=", result.size(), " operations");
return result;
}
@ -717,7 +719,8 @@ tl::expected<void, ErrorCode> MasterClient::Remove(const std::string& key,
ScopedVLogTimer timer(1, "MasterClient::Remove");
timer.LogRequest("key=", key, ", force=", force);
auto result = invoke_rpc<&WrappedMasterService::Remove, void>(key, force);
auto result =
invoke_rpc<&WrappedMasterService::Remove, void>(key, force, tenant_id_);
timer.LogResponseExpected(result);
return result;
}
@ -727,8 +730,8 @@ tl::expected<long, ErrorCode> MasterClient::RemoveByRegex(
ScopedVLogTimer timer(1, "MasterClient::RemoveByRegex");
timer.LogRequest("key=", str, ", force=", force);
auto result =
invoke_rpc<&WrappedMasterService::RemoveByRegex, long>(str, force);
auto result = invoke_rpc<&WrappedMasterService::RemoveByRegex, long>(
str, force, tenant_id_);
timer.LogResponseExpected(result);
return result;
}
@ -737,7 +740,8 @@ tl::expected<long, ErrorCode> MasterClient::RemoveAll(bool force) {
ScopedVLogTimer timer(1, "MasterClient::RemoveAll");
timer.LogRequest("action=remove_all_objects, force=", force);
auto result = invoke_rpc<&WrappedMasterService::RemoveAll, long>(force);
auto result =
invoke_rpc<&WrappedMasterService::RemoveAll, long>(force, tenant_id_);
timer.LogResponseExpected(result);
return result;
}
@ -748,7 +752,7 @@ std::vector<tl::expected<void, ErrorCode>> MasterClient::BatchRemove(
timer.LogRequest("keys_count=", keys.size(), ", force=", force);
auto result = invoke_batch_rpc<&WrappedMasterService::BatchRemove, void>(
keys.size(), keys, force);
keys.size(), keys, force, tenant_id_);
timer.LogResponse("result=", result.size(), " operations");
return result;
}

View File

@ -1773,8 +1773,15 @@ auto MasterService::AddReplica(const UUID& client_id, const std::string& key,
auto MasterService::PutRevoke(const UUID& client_id, const std::string& key,
ReplicaType replica_type)
-> tl::expected<void, ErrorCode> {
return PutRevoke(client_id, key, "default", replica_type);
}
auto MasterService::PutRevoke(const UUID& client_id, const std::string& key,
const std::string& tenant_id,
ReplicaType replica_type)
-> tl::expected<void, ErrorCode> {
std::shared_lock<std::shared_mutex> shared_lock(snapshot_mutex_);
MetadataAccessorRW accessor(this, key);
MetadataAccessorRW accessor(this, MakeObjectIdentity(key, tenant_id));
if (!accessor.Exists()) {
LOG(INFO) << "key=" << key << ", info=object_not_found";
return tl::make_unexpected(ErrorCode::OBJECT_NOT_FOUND);
@ -1830,10 +1837,16 @@ auto MasterService::PutRevoke(const UUID& client_id, const std::string& key,
std::vector<tl::expected<void, ErrorCode>> MasterService::BatchPutEnd(
const UUID& client_id, const std::vector<std::string>& keys,
ReplicaType replica_type) {
return BatchPutEnd(client_id, keys, "default", replica_type);
}
std::vector<tl::expected<void, ErrorCode>> MasterService::BatchPutEnd(
const UUID& client_id, const std::vector<std::string>& keys,
const std::string& tenant_id, ReplicaType replica_type) {
std::vector<tl::expected<void, ErrorCode>> results;
results.reserve(keys.size());
for (const auto& key : keys) {
results.emplace_back(PutEnd(client_id, key, replica_type));
results.emplace_back(PutEnd(client_id, key, tenant_id, replica_type));
}
return results;
}
@ -1841,10 +1854,17 @@ std::vector<tl::expected<void, ErrorCode>> MasterService::BatchPutEnd(
std::vector<tl::expected<void, ErrorCode>> MasterService::BatchPutRevoke(
const UUID& client_id, const std::vector<std::string>& keys,
ReplicaType replica_type) {
return BatchPutRevoke(client_id, keys, "default", replica_type);
}
std::vector<tl::expected<void, ErrorCode>> MasterService::BatchPutRevoke(
const UUID& client_id, const std::vector<std::string>& keys,
const std::string& tenant_id, ReplicaType replica_type) {
std::vector<tl::expected<void, ErrorCode>> results;
results.reserve(keys.size());
for (const auto& key : keys) {
results.emplace_back(PutRevoke(client_id, key, replica_type));
results.emplace_back(
PutRevoke(client_id, key, tenant_id, replica_type));
}
return results;
}
@ -2128,13 +2148,27 @@ auto MasterService::UpsertStart(const UUID& client_id, const std::string& key,
auto MasterService::UpsertEnd(const UUID& client_id, const std::string& key,
ReplicaType replica_type)
-> tl::expected<void, ErrorCode> {
return PutEnd(client_id, key, replica_type);
return UpsertEnd(client_id, key, "default", replica_type);
}
auto MasterService::UpsertEnd(const UUID& client_id, const std::string& key,
const std::string& tenant_id,
ReplicaType replica_type)
-> tl::expected<void, ErrorCode> {
return PutEnd(client_id, key, tenant_id, replica_type);
}
auto MasterService::UpsertRevoke(const UUID& client_id, const std::string& key,
ReplicaType replica_type)
-> tl::expected<void, ErrorCode> {
return PutRevoke(client_id, key, replica_type);
return UpsertRevoke(client_id, key, "default", replica_type);
}
auto MasterService::UpsertRevoke(const UUID& client_id, const std::string& key,
const std::string& tenant_id,
ReplicaType replica_type)
-> tl::expected<void, ErrorCode> {
return PutRevoke(client_id, key, tenant_id, replica_type);
}
std::vector<tl::expected<std::vector<Replica::Descriptor>, ErrorCode>>
@ -2142,6 +2176,15 @@ MasterService::BatchUpsertStart(const UUID& client_id,
const std::vector<std::string>& keys,
const std::vector<uint64_t>& slice_lengths,
const ReplicateConfig& config) {
return BatchUpsertStart(client_id, keys, "default", slice_lengths, config);
}
std::vector<tl::expected<std::vector<Replica::Descriptor>, ErrorCode>>
MasterService::BatchUpsertStart(const UUID& client_id,
const std::vector<std::string>& keys,
const std::string& tenant_id,
const std::vector<uint64_t>& slice_lengths,
const ReplicateConfig& config) {
if (keys.size() != slice_lengths.size()) {
LOG(ERROR) << "BatchUpsertStart: keys.size()=" << keys.size()
<< " != slice_lengths.size()=" << slice_lengths.size();
@ -2163,20 +2206,32 @@ MasterService::BatchUpsertStart(const UUID& client_id,
results.reserve(keys.size());
for (size_t i = 0; i < keys.size(); ++i) {
auto key_config = config.ForSingleKey(i);
results.emplace_back(
UpsertStart(client_id, keys[i], slice_lengths[i], key_config));
results.emplace_back(UpsertStart(client_id, keys[i], tenant_id,
slice_lengths[i], key_config));
}
return results;
}
std::vector<tl::expected<void, ErrorCode>> MasterService::BatchUpsertEnd(
const UUID& client_id, const std::vector<std::string>& keys) {
return BatchPutEnd(client_id, keys);
return BatchUpsertEnd(client_id, keys, "default");
}
std::vector<tl::expected<void, ErrorCode>> MasterService::BatchUpsertEnd(
const UUID& client_id, const std::vector<std::string>& keys,
const std::string& tenant_id) {
return BatchPutEnd(client_id, keys, tenant_id);
}
std::vector<tl::expected<void, ErrorCode>> MasterService::BatchUpsertRevoke(
const UUID& client_id, const std::vector<std::string>& keys) {
return BatchPutRevoke(client_id, keys);
return BatchUpsertRevoke(client_id, keys, "default");
}
std::vector<tl::expected<void, ErrorCode>> MasterService::BatchUpsertRevoke(
const UUID& client_id, const std::vector<std::string>& keys,
const std::string& tenant_id) {
return BatchPutRevoke(client_id, keys, tenant_id);
}
auto MasterService::EvictDiskReplica(const UUID& client_id,
@ -2802,8 +2857,6 @@ auto MasterService::RemoveByRegex(const std::string& regex_pattern,
long MasterService::RemoveAll(bool force) {
long removed_count = 0;
uint64_t total_freed_size = 0;
// Store the current time to avoid repeatedly
// calling std::chrono::steady_clock::now()
std::shared_lock<std::shared_mutex> shared_lock(snapshot_mutex_);
auto now = std::chrono::system_clock::now();
@ -2841,10 +2894,60 @@ long MasterService::RemoveAll(bool force) {
return removed_count;
}
long MasterService::RemoveAll(const std::string& tenant_id, bool force) {
long removed_count = 0;
uint64_t total_freed_size = 0;
// Store the current time to avoid repeatedly
// calling std::chrono::steady_clock::now()
std::shared_lock<std::shared_mutex> shared_lock(snapshot_mutex_);
auto now = std::chrono::system_clock::now();
const auto normalized_tenant = NormalizeTenantId(tenant_id);
for (size_t i = 0; i < kNumShards; i++) {
MetadataShardAccessorRW shard(this, i);
auto tenant_it = shard->tenants.find(normalized_tenant);
if (tenant_it == shard->tenants.end()) {
continue;
}
auto& tenant_state = tenant_it->second;
auto it = tenant_state.metadata.begin();
while (it != tenant_state.metadata.end()) {
if ((force || it->second.IsLeaseExpired(now)) &&
it->second.AllReplicas(&Replica::fn_is_completed) &&
!tenant_state.replication_tasks.contains(it->first)) {
auto mem_rep_count =
it->second.CountReplicas(&Replica::fn_is_memory_replica);
total_freed_size += it->second.size * mem_rep_count;
ErasePromotionTaskIfPresent(tenant_state, it->first);
it = EraseMetadata(tenant_state, it, normalized_tenant);
removed_count++;
} else {
++it;
}
}
if (tenant_state.Empty()) {
shard->tenants.erase(tenant_it);
}
}
VLOG(1) << "action=remove_all_objects"
<< ", tenant_id=" << normalized_tenant
<< ", removed_count=" << removed_count
<< ", total_freed_size=" << total_freed_size;
return removed_count;
}
auto MasterService::BatchRemove(const std::vector<std::string>& keys,
bool force)
-> std::vector<tl::expected<void, ErrorCode>> {
return BatchRemove(keys, "default", force);
}
auto MasterService::BatchRemove(const std::vector<std::string>& keys,
const std::string& tenant_id, bool force)
-> std::vector<tl::expected<void, ErrorCode>> {
std::vector<tl::expected<void, ErrorCode>> results(keys.size());
const auto normalized_tenant = NormalizeTenantId(tenant_id);
// Group keys by shard to reduce lock contention
std::unordered_map<size_t,
@ -2854,7 +2957,7 @@ auto MasterService::BatchRemove(const std::vector<std::string>& keys,
std::min(keys.size(), static_cast<size_t>(kNumShards)));
for (size_t i = 0; i < keys.size(); ++i) {
size_t shard_idx = getMetadataShardIndex(keys[i]);
size_t shard_idx = getMetadataShardIndex(normalized_tenant, keys[i]);
keys_by_shard[shard_idx].emplace_back(i, &keys[i]);
}
@ -2869,7 +2972,7 @@ auto MasterService::BatchRemove(const std::vector<std::string>& keys,
for (const auto& [original_idx, key_ptr] : key_group) {
const std::string& key = *key_ptr;
auto tenant_it = shard->tenants.find("default");
auto tenant_it = shard->tenants.find(normalized_tenant);
if (tenant_it == shard->tenants.end()) {
VLOG(1) << "key=" << key << ", error=object_not_found";
results[original_idx] =
@ -2892,7 +2995,10 @@ auto MasterService::BatchRemove(const std::vector<std::string>& keys,
tenant_state.replication_tasks.erase(key);
tenant_state.offloading_tasks.erase(key);
ErasePromotionTaskIfPresent(tenant_state, key);
EraseMetadata(tenant_state, it, "default");
EraseMetadata(tenant_state, it, normalized_tenant);
if (tenant_state.Empty()) {
shard->tenants.erase(tenant_it);
}
results[original_idx] =
tl::make_unexpected(ErrorCode::OBJECT_NOT_FOUND);
continue;
@ -2929,7 +3035,7 @@ auto MasterService::BatchRemove(const std::vector<std::string>& keys,
// Remove object metadata
ErasePromotionTaskIfPresent(tenant_state, key);
EraseMetadata(tenant_state, it, "default");
EraseMetadata(tenant_state, it, normalized_tenant);
if (tenant_state.Empty()) {
shard->tenants.erase(tenant_it);
}

View File

@ -633,7 +633,7 @@ tl::expected<void, ErrorCode> RealClient::setup_internal(
const std::shared_ptr<TransferEngine> &transfer_engine,
const std::string &ipc_socket_path, int local_rpc_port,
bool enable_ssd_offload, bool start_offload_rpc_server,
const std::string &ssd_offload_path) {
const std::string &ssd_offload_path, const std::string &tenant_id) {
this->protocol = protocol;
this->ipc_socket_path_ = ipc_socket_path;
const bool should_use_hugepage =
@ -677,7 +677,8 @@ tl::expected<void, ErrorCode> RealClient::setup_internal(
getHostNameWithoutPort(hostname), local_rpc_port);
auto client_opt = mooncake::Client::Create(
this->local_hostname, metadata_server, protocol, device_name,
master_server_addr, transfer_engine, {{"client_mode", "real"}});
master_server_addr, transfer_engine, {{"client_mode", "real"}},
tenant_id);
if (!client_opt) {
LOG(ERROR) << "Failed to create client";
return tl::unexpected(ErrorCode::INVALID_PARAMS);
@ -712,7 +713,8 @@ tl::expected<void, ErrorCode> RealClient::setup_internal(
buildHostNameWithPort(hostname, local_rpc_port);
auto client_opt = mooncake::Client::Create(
this->local_hostname, metadata_server, protocol, device_name,
master_server_addr, transfer_engine, {{"client_mode", "real"}});
master_server_addr, transfer_engine, {{"client_mode", "real"}},
tenant_id);
if (client_opt) {
client_ = *client_opt;
success = true;
@ -939,11 +941,12 @@ int RealClient::setup_real(
const std::string &master_server_addr,
const std::shared_ptr<TransferEngine> &transfer_engine,
const std::string &ipc_socket_path, bool enable_ssd_offload,
const std::string &ssd_offload_path) {
const std::string &ssd_offload_path, const std::string &tenant_id) {
return to_py_ret(setup_internal(
local_hostname, metadata_server, global_segment_size, local_buffer_size,
protocol, rdma_devices, master_server_addr, transfer_engine,
ipc_socket_path, 50052, enable_ssd_offload, true, ssd_offload_path));
ipc_socket_path, 50052, enable_ssd_offload, true, ssd_offload_path,
tenant_id));
}
namespace {
@ -1034,6 +1037,7 @@ tl::expected<void, ErrorCode> RealClient::setup_internal(
}
std::string ssd_offload_path = get_config(config, "ssd_offload_path");
std::string tenant_id = get_config(config, CONFIG_KEY_TENANT_ID, "default");
std::string enable_ssd_offload_str =
get_config(config, "enable_ssd_offload", "false");
@ -1043,10 +1047,10 @@ tl::expected<void, ErrorCode> RealClient::setup_internal(
bool enable_ssd_offload =
(enable_ssd_offload_str == "true" || enable_ssd_offload_str == "1");
return setup_internal(local_hostname, metadata_server, global_segment_size,
local_buffer_size, protocol, rdma_devices,
master_server_addr, nullptr, ipc_socket_path, 50052,
enable_ssd_offload, true, ssd_offload_path);
return setup_internal(
local_hostname, metadata_server, global_segment_size, local_buffer_size,
protocol, rdma_devices, master_server_addr, nullptr, ipc_socket_path,
50052, enable_ssd_offload, true, ssd_offload_path, tenant_id);
}
tl::expected<void, ErrorCode> RealClient::initAll_internal(

View File

@ -434,7 +434,8 @@ void MasterAdminServer::InitHttpServer() {
}
auto key = req.get_query_value("key");
auto get_result = service->GetReplicaList(std::string(key));
auto get_result =
service->GetReplicaList(std::string(key), "default");
resp.add_header("Content-Type", "text/plain; version=0.0.4");
if (get_result) {
std::string ss;
@ -696,7 +697,7 @@ void MasterAdminServer::InitHttpServer() {
return;
}
auto results = service->BatchGetReplicaList(keys);
auto results = service->BatchGetReplicaList(keys, "default");
const size_t n = std::min(keys.size(), results.size());
std::string body;
body.reserve(n * 512);
@ -754,22 +755,26 @@ WrappedMasterService::CalcCacheStats() {
}
tl::expected<bool, ErrorCode> WrappedMasterService::ExistKey(
const std::string& key) {
const std::string& key, const std::string& tenant_id) {
return execute_rpc(
"ExistKey", [&] { return master_service_.ExistKey(key); },
"ExistKey", [&] { return master_service_.ExistKey(key, tenant_id); },
[&](auto& timer) { timer.LogRequest("key=", key); },
[] { MasterMetricManager::instance().inc_exist_key_requests(); },
[] { MasterMetricManager::instance().inc_exist_key_failures(); });
}
std::vector<tl::expected<bool, ErrorCode>> WrappedMasterService::BatchExistKey(
const std::vector<std::string>& keys) {
const std::vector<std::string>& keys, const std::string& tenant_id) {
ScopedVLogTimer timer(1, "BatchExistKey");
const size_t total_keys = keys.size();
timer.LogRequest("keys_count=", total_keys);
MasterMetricManager::instance().inc_batch_exist_key_requests(total_keys);
auto result = master_service_.BatchExistKey(keys);
std::vector<tl::expected<bool, ErrorCode>> result;
result.reserve(keys.size());
for (const auto& key : keys) {
result.emplace_back(master_service_.ExistKey(key, tenant_id));
}
size_t failure_count = 0;
for (size_t i = 0; i < result.size(); ++i) {
@ -876,10 +881,11 @@ WrappedMasterService::BatchReplicaClear(
tl::expected<std::unordered_map<std::string, std::vector<Replica::Descriptor>>,
ErrorCode>
WrappedMasterService::GetReplicaListByRegex(const std::string& str) {
WrappedMasterService::GetReplicaListByRegex(const std::string& str,
const std::string& tenant_id) {
return execute_rpc(
"GetReplicaListByRegex",
[&] { return master_service_.GetReplicaListByRegex(str); },
[&] { return master_service_.GetReplicaListByRegex(str, tenant_id); },
[&](auto& timer) { timer.LogRequest("Regex=", str); },
[] {
MasterMetricManager::instance()
@ -892,9 +898,11 @@ WrappedMasterService::GetReplicaListByRegex(const std::string& str) {
}
tl::expected<GetReplicaListResponse, ErrorCode>
WrappedMasterService::GetReplicaList(const std::string& key) {
WrappedMasterService::GetReplicaList(const std::string& key,
const std::string& tenant_id) {
return execute_rpc(
"GetReplicaList", [&] { return master_service_.GetReplicaList(key); },
"GetReplicaList",
[&] { return master_service_.GetReplicaList(key, tenant_id); },
[&](auto& timer) { timer.LogRequest("key=", key); },
[] { MasterMetricManager::instance().inc_get_replica_list_requests(); },
[] {
@ -903,8 +911,8 @@ WrappedMasterService::GetReplicaList(const std::string& key) {
}
std::vector<tl::expected<GetReplicaListResponse, ErrorCode>>
WrappedMasterService::BatchGetReplicaList(
const std::vector<std::string>& keys) {
WrappedMasterService::BatchGetReplicaList(const std::vector<std::string>& keys,
const std::string& tenant_id) {
ScopedVLogTimer timer(1, "BatchGetReplicaList");
const size_t total_keys = keys.size();
timer.LogRequest("keys_count=", total_keys);
@ -915,7 +923,7 @@ WrappedMasterService::BatchGetReplicaList(
results.reserve(keys.size());
for (const auto& key : keys) {
results.emplace_back(master_service_.GetReplicaList(key));
results.emplace_back(master_service_.GetReplicaList(key, tenant_id));
}
size_t failure_count = 0;
@ -951,12 +959,13 @@ WrappedMasterService::BatchGetReplicaList(
tl::expected<std::vector<Replica::Descriptor>, ErrorCode>
WrappedMasterService::PutStart(const UUID& client_id, const std::string& key,
const uint64_t slice_length,
const ReplicateConfig& config) {
const ReplicateConfig& config,
const std::string& tenant_id) {
return execute_rpc(
"PutStart",
[&] {
return master_service_.PutStart(client_id, key, slice_length,
config);
return master_service_.PutStart(client_id, key, tenant_id,
slice_length, config);
},
[&](auto& timer) {
timer.LogRequest("client_id=", client_id, ", key=", key,
@ -967,10 +976,14 @@ WrappedMasterService::PutStart(const UUID& client_id, const std::string& key,
}
tl::expected<void, ErrorCode> WrappedMasterService::PutEnd(
const UUID& client_id, const std::string& key, ReplicaType replica_type) {
const UUID& client_id, const std::string& key, ReplicaType replica_type,
const std::string& tenant_id) {
return execute_rpc(
"PutEnd",
[&] { return master_service_.PutEnd(client_id, key, replica_type); },
[&] {
return master_service_.PutEnd(client_id, key, tenant_id,
replica_type);
},
[&](auto& timer) {
timer.LogRequest("client_id=", client_id, ", key=", key,
", replica_type=", replica_type);
@ -980,10 +993,14 @@ tl::expected<void, ErrorCode> WrappedMasterService::PutEnd(
}
tl::expected<void, ErrorCode> WrappedMasterService::PutRevoke(
const UUID& client_id, const std::string& key, ReplicaType replica_type) {
const UUID& client_id, const std::string& key, ReplicaType replica_type,
const std::string& tenant_id) {
return execute_rpc(
"PutRevoke",
[&] { return master_service_.PutRevoke(client_id, key, replica_type); },
[&] {
return master_service_.PutRevoke(client_id, key, tenant_id,
replica_type);
},
[&](auto& timer) {
timer.LogRequest("client_id=", client_id, ", key=", key,
", replica_type=", replica_type);
@ -996,7 +1013,8 @@ std::vector<tl::expected<std::vector<Replica::Descriptor>, ErrorCode>>
WrappedMasterService::BatchPutStart(const UUID& client_id,
const std::vector<std::string>& keys,
const std::vector<uint64_t>& slice_lengths,
const ReplicateConfig& config) {
const ReplicateConfig& config,
const std::string& tenant_id) {
ScopedVLogTimer timer(1, "BatchPutStart");
const size_t total_keys = keys.size();
timer.LogRequest("client_id=", client_id, ", keys_count=", total_keys);
@ -1023,7 +1041,7 @@ WrappedMasterService::BatchPutStart(const UUID& client_id,
for (size_t i = 0; i < keys.size(); ++i) {
auto key_config = new_config.ForSingleKey(i);
auto result = master_service_.PutStart(
client_id, keys[i], slice_lengths[i], key_config);
client_id, keys[i], tenant_id, slice_lengths[i], key_config);
results.emplace_back(result);
if ((i == 0) && result.has_value()) {
std::string preferred_segment;
@ -1045,7 +1063,7 @@ WrappedMasterService::BatchPutStart(const UUID& client_id,
for (size_t i = 0; i < keys.size(); ++i) {
auto key_config = config.ForSingleKey(i);
results.emplace_back(master_service_.PutStart(
client_id, keys[i], slice_lengths[i], key_config));
client_id, keys[i], tenant_id, slice_lengths[i], key_config));
}
}
@ -1088,7 +1106,7 @@ WrappedMasterService::BatchPutStart(const UUID& client_id,
std::vector<tl::expected<void, ErrorCode>> WrappedMasterService::BatchPutEnd(
const UUID& client_id, const std::vector<std::string>& keys,
ReplicaType replica_type) {
ReplicaType replica_type, const std::string& tenant_id) {
ScopedVLogTimer timer(1, "BatchPutEnd");
const size_t total_keys = keys.size();
timer.LogRequest("client_id=", client_id, ", keys_count=", total_keys);
@ -1099,7 +1117,7 @@ std::vector<tl::expected<void, ErrorCode>> WrappedMasterService::BatchPutEnd(
for (const auto& key : keys) {
results.emplace_back(
master_service_.PutEnd(client_id, key, replica_type));
master_service_.PutEnd(client_id, key, tenant_id, replica_type));
}
size_t failure_count = 0;
@ -1128,7 +1146,7 @@ std::vector<tl::expected<void, ErrorCode>> WrappedMasterService::BatchPutEnd(
std::vector<tl::expected<void, ErrorCode>> WrappedMasterService::BatchPutRevoke(
const UUID& client_id, const std::vector<std::string>& keys,
ReplicaType replica_type) {
ReplicaType replica_type, const std::string& tenant_id) {
ScopedVLogTimer timer(1, "BatchPutRevoke");
const size_t total_keys = keys.size();
timer.LogRequest("client_id=", client_id, ", keys_count=", total_keys);
@ -1139,7 +1157,7 @@ std::vector<tl::expected<void, ErrorCode>> WrappedMasterService::BatchPutRevoke(
for (const auto& key : keys) {
results.emplace_back(
master_service_.PutRevoke(client_id, key, replica_type));
master_service_.PutRevoke(client_id, key, tenant_id, replica_type));
}
size_t failure_count = 0;
@ -1169,12 +1187,13 @@ std::vector<tl::expected<void, ErrorCode>> WrappedMasterService::BatchPutRevoke(
tl::expected<std::vector<Replica::Descriptor>, ErrorCode>
WrappedMasterService::UpsertStart(const UUID& client_id, const std::string& key,
const uint64_t slice_length,
const ReplicateConfig& config) {
const ReplicateConfig& config,
const std::string& tenant_id) {
return execute_rpc(
"UpsertStart",
[&] {
return master_service_.UpsertStart(client_id, key, slice_length,
config);
return master_service_.UpsertStart(client_id, key, tenant_id,
slice_length, config);
},
[&](auto& timer) {
timer.LogRequest("client_id=", client_id, ", key=", key,
@ -1185,10 +1204,14 @@ WrappedMasterService::UpsertStart(const UUID& client_id, const std::string& key,
}
tl::expected<void, ErrorCode> WrappedMasterService::UpsertEnd(
const UUID& client_id, const std::string& key, ReplicaType replica_type) {
const UUID& client_id, const std::string& key, ReplicaType replica_type,
const std::string& tenant_id) {
return execute_rpc(
"UpsertEnd",
[&] { return master_service_.UpsertEnd(client_id, key, replica_type); },
[&] {
return master_service_.UpsertEnd(client_id, key, tenant_id,
replica_type);
},
[&](auto& timer) {
timer.LogRequest("client_id=", client_id, ", key=", key,
", replica_type=", replica_type);
@ -1198,11 +1221,13 @@ tl::expected<void, ErrorCode> WrappedMasterService::UpsertEnd(
}
tl::expected<void, ErrorCode> WrappedMasterService::UpsertRevoke(
const UUID& client_id, const std::string& key, ReplicaType replica_type) {
const UUID& client_id, const std::string& key, ReplicaType replica_type,
const std::string& tenant_id) {
return execute_rpc(
"UpsertRevoke",
[&] {
return master_service_.UpsertRevoke(client_id, key, replica_type);
return master_service_.UpsertRevoke(client_id, key, tenant_id,
replica_type);
},
[&](auto& timer) {
timer.LogRequest("client_id=", client_id, ", key=", key,
@ -1215,13 +1240,14 @@ tl::expected<void, ErrorCode> WrappedMasterService::UpsertRevoke(
std::vector<tl::expected<std::vector<Replica::Descriptor>, ErrorCode>>
WrappedMasterService::BatchUpsertStart(
const UUID& client_id, const std::vector<std::string>& keys,
const std::vector<uint64_t>& slice_lengths, const ReplicateConfig& config) {
const std::vector<uint64_t>& slice_lengths, const ReplicateConfig& config,
const std::string& tenant_id) {
ScopedVLogTimer timer(1, "BatchUpsertStart");
const size_t total_keys = keys.size();
timer.LogRequest("client_id=", client_id, ", keys_count=", total_keys);
MasterMetricManager::instance().inc_batch_put_start_requests(total_keys);
auto results = master_service_.BatchUpsertStart(client_id, keys,
auto results = master_service_.BatchUpsertStart(client_id, keys, tenant_id,
slice_lengths, config);
size_t failure_count = 0;
@ -1249,13 +1275,14 @@ WrappedMasterService::BatchUpsertStart(
}
std::vector<tl::expected<void, ErrorCode>> WrappedMasterService::BatchUpsertEnd(
const UUID& client_id, const std::vector<std::string>& keys) {
const UUID& client_id, const std::vector<std::string>& keys,
const std::string& tenant_id) {
ScopedVLogTimer timer(1, "BatchUpsertEnd");
const size_t total_keys = keys.size();
timer.LogRequest("client_id=", client_id, ", keys_count=", total_keys);
MasterMetricManager::instance().inc_batch_put_end_requests(total_keys);
auto results = master_service_.BatchUpsertEnd(client_id, keys);
auto results = master_service_.BatchUpsertEnd(client_id, keys, tenant_id);
size_t failure_count = 0;
for (size_t i = 0; i < results.size(); ++i) {
@ -1283,13 +1310,15 @@ std::vector<tl::expected<void, ErrorCode>> WrappedMasterService::BatchUpsertEnd(
std::vector<tl::expected<void, ErrorCode>>
WrappedMasterService::BatchUpsertRevoke(const UUID& client_id,
const std::vector<std::string>& keys) {
const std::vector<std::string>& keys,
const std::string& tenant_id) {
ScopedVLogTimer timer(1, "BatchUpsertRevoke");
const size_t total_keys = keys.size();
timer.LogRequest("client_id=", client_id, ", keys_count=", total_keys);
MasterMetricManager::instance().inc_batch_put_revoke_requests(total_keys);
auto results = master_service_.BatchUpsertRevoke(client_id, keys);
auto results =
master_service_.BatchUpsertRevoke(client_id, keys, tenant_id);
size_t failure_count = 0;
for (size_t i = 0; i < results.size(); ++i) {
@ -1316,19 +1345,19 @@ WrappedMasterService::BatchUpsertRevoke(const UUID& client_id,
}
tl::expected<void, ErrorCode> WrappedMasterService::Remove(
const std::string& key, bool force) {
const std::string& key, bool force, const std::string& tenant_id) {
return execute_rpc(
"Remove", [&] { return master_service_.Remove(key, force); },
"Remove", [&] { return master_service_.Remove(key, tenant_id, force); },
[&](auto& timer) { timer.LogRequest("key=", key, ", force=", force); },
[] { MasterMetricManager::instance().inc_remove_requests(); },
[] { MasterMetricManager::instance().inc_remove_failures(); });
}
tl::expected<long, ErrorCode> WrappedMasterService::RemoveByRegex(
const std::string& str, bool force) {
const std::string& str, bool force, const std::string& tenant_id) {
return execute_rpc(
"RemoveByRegex",
[&] { return master_service_.RemoveByRegex(str, force); },
[&] { return master_service_.RemoveByRegex(str, tenant_id, force); },
[&](auto& timer) {
timer.LogRequest("regex=", str, ", force=", force);
},
@ -1336,23 +1365,24 @@ tl::expected<long, ErrorCode> WrappedMasterService::RemoveByRegex(
[] { MasterMetricManager::instance().inc_remove_by_regex_failures(); });
}
long WrappedMasterService::RemoveAll(bool force) {
long WrappedMasterService::RemoveAll(bool force, const std::string& tenant_id) {
ScopedVLogTimer timer(1, "RemoveAll");
timer.LogRequest("action=remove_all_objects, force=", force);
MasterMetricManager::instance().inc_remove_all_requests();
long result = master_service_.RemoveAll(force);
long result = master_service_.RemoveAll(tenant_id, force);
timer.LogResponse("items_removed=", result);
return result;
}
std::vector<tl::expected<void, ErrorCode>> WrappedMasterService::BatchRemove(
const std::vector<std::string>& keys, bool force) {
const std::vector<std::string>& keys, bool force,
const std::string& tenant_id) {
ScopedVLogTimer timer(1, "BatchRemove");
const size_t total_keys = keys.size();
timer.LogRequest("keys_count=", total_keys, ", force=", force);
MasterMetricManager::instance().inc_remove_requests(total_keys);
auto results = master_service_.BatchRemove(keys, force);
auto results = master_service_.BatchRemove(keys, tenant_id, force);
size_t failure_count = 0;
for (const auto& result : results) {

View File

@ -1404,6 +1404,131 @@ TEST_F(MasterServiceTest, RegexOperationsAreTenantScoped) {
EXPECT_TRUE(service_->GetReplicaList(key, tenant_b).has_value());
}
TEST_F(MasterServiceTest, TenantBatchUpsertAndRevokeAreScoped) {
auto svc = std::make_unique<MasterService>();
[[maybe_unused]] const auto context = PrepareSimpleSegment(*svc);
const UUID client_id = generate_uuid();
const std::vector<std::string> keys = {"tenant_batch_upsert_key_a",
"tenant_batch_upsert_key_b"};
const std::vector<uint64_t> sizes = {1024, 2048};
const std::string tenant_a = "tenant_batch_upsert_a";
const std::string tenant_b = "tenant_batch_upsert_b";
ReplicateConfig config;
config.replica_num = 1;
auto tenant_a_results =
svc->BatchUpsertStart(client_id, keys, tenant_a, sizes, config);
ASSERT_EQ(tenant_a_results.size(), keys.size());
for (const auto& result : tenant_a_results) {
ASSERT_TRUE(result.has_value());
}
auto tenant_a_end = svc->BatchUpsertEnd(client_id, keys, tenant_a);
ASSERT_EQ(tenant_a_end.size(), keys.size());
for (const auto& result : tenant_a_end) {
ASSERT_TRUE(result.has_value());
}
auto tenant_b_results =
svc->BatchUpsertStart(client_id, keys, tenant_b, sizes, config);
ASSERT_EQ(tenant_b_results.size(), keys.size());
for (const auto& result : tenant_b_results) {
ASSERT_TRUE(result.has_value());
}
auto tenant_b_end = svc->BatchUpsertEnd(client_id, keys, tenant_b);
ASSERT_EQ(tenant_b_end.size(), keys.size());
for (const auto& result : tenant_b_end) {
ASSERT_TRUE(result.has_value());
}
for (const auto& key : keys) {
EXPECT_FALSE(svc->GetReplicaList(key).has_value());
EXPECT_TRUE(svc->GetReplicaList(key, tenant_a).has_value());
EXPECT_TRUE(svc->GetReplicaList(key, tenant_b).has_value());
}
const std::string revoke_key = "tenant_batch_upsert_revoke_key";
auto revoke_start =
svc->UpsertStart(client_id, revoke_key, tenant_a, 1024, config);
ASSERT_TRUE(revoke_start.has_value());
ASSERT_TRUE(
svc->UpsertRevoke(client_id, revoke_key, tenant_a, ReplicaType::MEMORY)
.has_value());
EXPECT_FALSE(svc->GetReplicaList(revoke_key, tenant_a).has_value());
}
TEST_F(MasterServiceTest, TenantBatchRemoveAndRemoveAllAreScoped) {
auto svc = std::make_unique<MasterService>();
[[maybe_unused]] const auto context = PrepareSimpleSegment(*svc);
const UUID client_id = generate_uuid();
const std::string shared_key = "tenant_batch_remove_shared_key";
const std::string tenant_a = "tenant_batch_remove_a";
const std::string tenant_b = "tenant_batch_remove_b";
ReplicateConfig config;
config.replica_num = 1;
ASSERT_TRUE(svc->PutStart(client_id, shared_key, 1024, config).has_value());
ASSERT_TRUE(
svc->PutEnd(client_id, shared_key, ReplicaType::MEMORY).has_value());
ASSERT_TRUE(svc->PutStart(client_id, shared_key, tenant_a, 1024, config)
.has_value());
ASSERT_TRUE(
svc->PutEnd(client_id, shared_key, tenant_a, ReplicaType::MEMORY)
.has_value());
ASSERT_TRUE(svc->PutStart(client_id, shared_key, tenant_b, 1024, config)
.has_value());
ASSERT_TRUE(
svc->PutEnd(client_id, shared_key, tenant_b, ReplicaType::MEMORY)
.has_value());
auto remove_a = svc->BatchRemove({shared_key}, tenant_a, /*force=*/true);
ASSERT_EQ(remove_a.size(), 1u);
ASSERT_TRUE(remove_a[0].has_value());
EXPECT_FALSE(svc->GetReplicaList(shared_key, tenant_a).has_value());
EXPECT_TRUE(svc->GetReplicaList(shared_key).has_value());
EXPECT_TRUE(svc->GetReplicaList(shared_key, tenant_b).has_value());
EXPECT_EQ(svc->RemoveAll(tenant_b, /*force=*/true), 1);
EXPECT_FALSE(svc->GetReplicaList(shared_key, tenant_b).has_value());
EXPECT_TRUE(svc->GetReplicaList(shared_key).has_value());
EXPECT_EQ(svc->RemoveAll(/*force=*/true), 1);
EXPECT_FALSE(svc->GetReplicaList(shared_key).has_value());
}
TEST_F(MasterServiceTest, LegacyRemoveAllRemovesAllTenants) {
auto svc = std::make_unique<MasterService>();
[[maybe_unused]] const auto context = PrepareSimpleSegment(*svc);
const UUID client_id = generate_uuid();
const std::string key = "legacy_remove_all_shared_key";
const std::string tenant_a = "legacy_remove_all_a";
const std::string tenant_b = "legacy_remove_all_b";
ReplicateConfig config;
config.replica_num = 1;
ASSERT_TRUE(svc->PutStart(client_id, key, 1024, config).has_value());
ASSERT_TRUE(svc->PutEnd(client_id, key, ReplicaType::MEMORY).has_value());
ASSERT_TRUE(
svc->PutStart(client_id, key, tenant_a, 1024, config).has_value());
ASSERT_TRUE(
svc->PutEnd(client_id, key, tenant_a, ReplicaType::MEMORY).has_value());
ASSERT_TRUE(
svc->PutStart(client_id, key, tenant_b, 1024, config).has_value());
ASSERT_TRUE(
svc->PutEnd(client_id, key, tenant_b, ReplicaType::MEMORY).has_value());
EXPECT_EQ(svc->RemoveAll(/*force=*/true), 3);
EXPECT_FALSE(svc->GetReplicaList(key).has_value());
EXPECT_FALSE(svc->GetReplicaList(key, tenant_a).has_value());
EXPECT_FALSE(svc->GetReplicaList(key, tenant_b).has_value());
EXPECT_EQ(svc->RemoveAll(/*force=*/true), 0);
}
TEST_F(MasterServiceTest, PutWithPreferredSegment) {
// For backward compatibility, test the deprecated single preferred_segment
std::unique_ptr<MasterService> service_(new MasterService());