Improved the db info command performance

This commit is contained in:
WolverinDEV 2020-12-05 10:26:12 +01:00
parent 8ca58056d4
commit 1c99f093c8
3 changed files with 68 additions and 46 deletions

View File

@ -328,7 +328,7 @@ namespace ts {
std::deque<std::weak_ptr<ConnectedClient>> visibleClients{}; /* variable locked with channel_lock */
std::deque<std::weak_ptr<ConnectedClient>> mutedClients{}; /* variable locked with channel_lock */
std::deque<std::weak_ptr<ConnectedClient>> openChats{}; /* variable locked with channel_lock */
std::deque<std::weak_ptr<ConnectedClient>> open_private_conversations{}; /* variable locked with channel_lock */
std::chrono::system_clock::time_point lastNeededNotify;
std::shared_ptr<BasicChannel> lastNeededPermissionNotifyChannel = nullptr;

View File

@ -359,15 +359,15 @@ command_result ConnectedClient::handleCommandClientChatClosed(Command &cmd) {
if (!client) return command_result{error::client_invalid_id};
{
unique_lock channel_lock(this->channel_lock);
this->openChats.erase(remove_if(this->openChats.begin(), this->openChats.end(), [&](const weak_ptr<ConnectedClient>& weak) {
this->open_private_conversations.erase(remove_if(this->open_private_conversations.begin(), this->open_private_conversations.end(), [&](const weak_ptr<ConnectedClient>& weak) {
return weak.lock() == client;
}), this->openChats.end());
}), this->open_private_conversations.end());
}
{
unique_lock channel_lock(client->get_channel_lock());
client->openChats.erase(remove_if(client->openChats.begin(), client->openChats.end(), [&](const weak_ptr<ConnectedClient>& weak) {
client->open_private_conversations.erase(remove_if(client->open_private_conversations.begin(), client->open_private_conversations.end(), [&](const weak_ptr<ConnectedClient>& weak) {
return weak.lock().get() == this;
}), client->openChats.end());
}), client->open_private_conversations.end());
}
client->notifyClientChatClosed(_this.lock());
return command_result{error::ok};
@ -1047,51 +1047,64 @@ command_result ConnectedClient::handleCommandClientDbInfo(Command &cmd) {
CMD_CHK_AND_INC_FLOOD_POINTS(5);
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_client_dbinfo, 1);
deque<ClientDbId> cldbids;
for(int index = 0; index < cmd.bulkCount(); index++)
std::deque<ClientDbId> cldbids;
for(int index = 0; index < cmd.bulkCount(); index++) {
cldbids.push_back(cmd[index]["cldbid"]);
}
auto basic = serverInstance->databaseHelper()->queryDatabaseInfo(this->server, cldbids);
if (basic.empty()) return command_result{error::database_empty_result};
if (basic.empty()) {
return command_result{error::database_empty_result};
}
auto allow_ip = permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_remoteaddress_view, 0));
Command res(this->getExternalType() == ClientType::CLIENT_TEAMSPEAK ? "notifyclientdbinfo" : "");
ts::command_builder result{this->getExternalType() == ClientType::CLIENT_TEAMSPEAK ? "notifyclientdbinfo" : ""};
result.reserve_bulks(basic.size());
size_t index = 0;
for(const auto& info : basic) {
res[index]["client_base64HashClientUID"] = hex::hex(base64::validate(info->client_unique_id) ? base64::decode(info->client_unique_id) : info->client_unique_id, 'a', 'q');
res[index]["client_unique_identifier"] = info->client_unique_id;
res[index]["client_nickname"] = info->client_nickname;
res[index]["client_database_id"] = info->client_database_id;
res[index]["client_created"] = chrono::duration_cast<chrono::seconds>(info->client_created.time_since_epoch()).count();
res[index]["client_lastconnected"] = chrono::duration_cast<chrono::seconds>(info->client_last_connected.time_since_epoch()).count();
res[index]["client_totalconnections"] = info->client_total_connections;
res[index]["client_database_id"] = info->client_database_id;
auto bulk = result.bulk(index++);
bulk.reserve(800);
bulk.put_unchecked("client_base64HashClientUID", hex::hex(base64::validate(info->client_unique_id) ? base64::decode(info->client_unique_id) : info->client_unique_id, 'a', 'q'));
bulk.put_unchecked(property::CLIENT_UNIQUE_IDENTIFIER, info->client_unique_id);
bulk.put_unchecked(property::CLIENT_NICKNAME, info->client_nickname);
bulk.put_unchecked(property::CLIENT_DATABASE_ID, info->client_database_id);
bulk.put_unchecked(property::CLIENT_CREATED, chrono::duration_cast<chrono::seconds>(info->client_created.time_since_epoch()).count());
bulk.put_unchecked(property::CLIENT_LASTCONNECTED, chrono::duration_cast<chrono::seconds>(info->client_last_connected.time_since_epoch()).count());
bulk.put_unchecked(property::CLIENT_TOTALCONNECTIONS, info->client_total_connections);
bulk.put_unchecked(property::CLIENT_DATABASE_ID, info->client_database_id);
auto props = serverInstance->databaseHelper()->loadClientProperties(this->server, info->client_database_id, ClientType::CLIENT_TEAMSPEAK);
if (allow_ip)
res[index]["client_lastip"] = (*props)[property::CONNECTION_CLIENT_IP].as<string>();
else
res[index]["client_lastip"] = "hidden";
if(allow_ip) {
bulk.put_unchecked("client_lastip", (*props)[property::CONNECTION_CLIENT_IP].as<string>());
} else {
bulk.put_unchecked("client_lastip", "hidden");
}
res[index]["client_icon_id"] = (*props)[property::CLIENT_ICON_ID].as<string>();
res[index]["client_badges"] = (*props)[property::CLIENT_BADGES].as<string>();
res[index]["client_version"] = (*props)[property::CLIENT_VERSION].as<string>();
res[index]["client_platform"] = (*props)[property::CLIENT_PLATFORM].as<string>();
res[index]["client_hwid"] = (*props)[property::CLIENT_HARDWARE_ID].as<string>();
res[index]["client_total_bytes_downloaded"] = (*props)[property::CLIENT_TOTAL_BYTES_DOWNLOADED].as<string>();
res[index]["client_total_bytes_uploaded"] = (*props)[property::CLIENT_TOTAL_BYTES_UPLOADED].as<string>();
res[index]["client_month_bytes_downloaded"] = (*props)[property::CLIENT_MONTH_BYTES_DOWNLOADED].as<string>();
res[index]["client_month_bytes_uploaded"] = (*props)[property::CLIENT_MONTH_BYTES_DOWNLOADED].as<string>();
res[index]["client_description"] = (*props)[property::CLIENT_DESCRIPTION].as<string>();
res[index]["client_flag_avatar"] = (*props)[property::CLIENT_FLAG_AVATAR].as<string>();
#define ASSIGN_PROPERTY(property) \
bulk.put_unchecked(property, (*props)[property].as<string>());
ASSIGN_PROPERTY(property::CLIENT_ICON_ID);
ASSIGN_PROPERTY(property::CLIENT_BADGES);
ASSIGN_PROPERTY(property::CLIENT_VERSION);
ASSIGN_PROPERTY(property::CLIENT_PLATFORM);
ASSIGN_PROPERTY(property::CLIENT_HARDWARE_ID);
ASSIGN_PROPERTY(property::CLIENT_TOTAL_BYTES_DOWNLOADED);
ASSIGN_PROPERTY(property::CLIENT_TOTAL_BYTES_UPLOADED);
ASSIGN_PROPERTY(property::CLIENT_MONTH_BYTES_DOWNLOADED);
ASSIGN_PROPERTY(property::CLIENT_MONTH_BYTES_DOWNLOADED);
ASSIGN_PROPERTY(property::CLIENT_DESCRIPTION);
ASSIGN_PROPERTY(property::CLIENT_FLAG_AVATAR);
ASSIGN_PROPERTY(property::CLIENT_MONTH_ONLINE_TIME);
ASSIGN_PROPERTY(property::CLIENT_TOTAL_ONLINE_TIME);
#undef ASSIGN_PROPERTY
res[index]["client_month_online_time"] = (*props)[property::CLIENT_MONTH_ONLINE_TIME].as<string>();
res[index]["client_total_online_time"] = (*props)[property::CLIENT_TOTAL_ONLINE_TIME].as<string>();
index++;
}
this->sendCommand(res);
this->sendCommand(result);
return command_result{error::ok};
}

View File

@ -551,12 +551,15 @@ command_result ConnectedClient::handleCommandSendTextMessage(Command &cmd) {
ConnectedLockedClient target{this->server->find_client_by_id(cmd["target"].as<ClientId>())};
if (!target) return command_result{error::client_invalid_id};
bool chat_open = false;
bool chat_open{false};
{
shared_lock channel_lock(this->channel_lock);
this->openChats.erase(remove_if(this->openChats.begin(), this->openChats.end(), [](const weak_ptr<ConnectedClient>& weak) { return !weak.lock(); }), this->openChats.end());
for(const auto& entry : this->openChats) {
std::unique_lock self_channel_lock{this->channel_lock};
this->open_private_conversations.erase(std::remove_if(this->open_private_conversations.begin(), this->open_private_conversations.end(), [](const weak_ptr<ConnectedClient>& weak) {
return !weak.lock();
}), this->open_private_conversations.end());
for(const auto& entry : this->open_private_conversations) {
if(entry.lock() == target) {
chat_open = true;
break;
@ -565,24 +568,30 @@ command_result ConnectedClient::handleCommandSendTextMessage(Command &cmd) {
}
if(!chat_open) {
if (target.client == this)
if(target.client == this) {
ACTION_REQUIRES_PERMISSION(permission::b_client_even_textmessage_send, 1, this->getChannelId());
if(!permission::v2::permission_granted(target->calculate_permission(permission::i_client_needed_private_textmessage_power, target->getClientId()), this->calculate_permission(permission::i_client_private_textmessage_power, this->getClientId()), false))
}
if(!permission::v2::permission_granted(target->calculate_permission(permission::i_client_needed_private_textmessage_power, target->getClientId()), this->calculate_permission(permission::i_client_private_textmessage_power, this->getClientId()), false)) {
return command_result{permission::i_client_private_textmessage_power};
}
{
unique_lock channel_lock(target->get_channel_lock());
target->openChats.push_back(_this);
std::unique_lock target_channel_lock{target->get_channel_lock()};
target->open_private_conversations.push_back(_this);
}
{
unique_lock channel_lock(this->channel_lock);
this->openChats.push_back(target.client);
std::unique_lock self_channel_lock{this->channel_lock};
this->open_private_conversations.push_back(target.client);
}
}
if(this->handleTextMessage(ChatMessageMode::TEXTMODE_PRIVATE, cmd["msg"], target.client)) return command_result{error::ok};
if(this->handleTextMessage(ChatMessageMode::TEXTMODE_PRIVATE, cmd["msg"], target.client)) {
return command_result{error::ok};
}
target->notifyTextMessage(ChatMessageMode::TEXTMODE_PRIVATE, _this.lock(), target->getClientId(), 0, timestamp, cmd["msg"].string());
this->notifyTextMessage(ChatMessageMode::TEXTMODE_PRIVATE, _this.lock(), target->getClientId(), 0, timestamp, cmd["msg"].string());
} else if (cmd["targetmode"] == ChatMessageMode::TEXTMODE_CHANNEL) {