Prevent head of line blocking and track server resource download progress
This commit is contained in:
parent
344ef4093a
commit
2aab3e9e60
14 changed files with 179 additions and 83 deletions
|
|
@ -40,9 +40,18 @@ bool ConnectionManager::is_host_disconnected() {
|
|||
return localServer && localServer->netServer->is_disconnected();
|
||||
}
|
||||
|
||||
std::pair<uint64_t, uint64_t> ConnectionManager::client_get_resource_retrieval_progress() {
|
||||
if(client)
|
||||
return client->get_progress_into_fragmented_message(RESOURCE_COMMAND_CHANNEL);
|
||||
else
|
||||
return {0, 0};
|
||||
bool ConnectionManager::host_exists() {
|
||||
return localServer != nullptr;
|
||||
}
|
||||
|
||||
bool ConnectionManager::client_exists() {
|
||||
return client != nullptr;
|
||||
}
|
||||
|
||||
std::unordered_map<ServerClientID, NetLibrary::DownloadProgress> ConnectionManager::server_get_resource_retrieval_progress() {
|
||||
return localServer->resource_download_progress();
|
||||
}
|
||||
|
||||
NetLibrary::DownloadProgress ConnectionManager::client_get_resource_retrieval_progress() {
|
||||
return client->get_progress_into_fragmented_message(RESOURCE_COMMAND_CHANNEL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,10 @@ class ConnectionManager {
|
|||
}
|
||||
bool is_client_disconnected();
|
||||
bool is_host_disconnected();
|
||||
std::pair<uint64_t, uint64_t> client_get_resource_retrieval_progress();
|
||||
bool host_exists();
|
||||
bool client_exists();
|
||||
std::unordered_map<ServerClientID, NetLibrary::DownloadProgress> server_get_resource_retrieval_progress();
|
||||
NetLibrary::DownloadProgress client_get_resource_retrieval_progress();
|
||||
private:
|
||||
std::shared_ptr<NetClient> client;
|
||||
std::unique_ptr<MainServer> localServer;
|
||||
|
|
|
|||
|
|
@ -725,8 +725,8 @@ void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) {
|
|||
for(auto& c : updateableComponents) {
|
||||
if(c->get_type() == DRAWCOMPONENT_IMAGE) {
|
||||
auto img = std::static_pointer_cast<DrawImage>(c);
|
||||
if(img->d.imageID == drawData.main->world->rMan.get_resource_being_retrieved() && img->d.imageID != ServerClientID{0, 0})
|
||||
img->draw_download_progress_bar(canvas, drawData, drawData.main->world->rMan.get_resource_retrieval_progress());
|
||||
float progress = drawData.main->world->rMan.get_resource_retrieval_progress(img->d.imageID);
|
||||
img->draw_download_progress_bar(canvas, drawData, progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,28 +19,48 @@ ResourceManager::ResourceManager(World& initWorld):
|
|||
|
||||
void ResourceManager::init_client_callbacks() {
|
||||
world.con.client_add_recv_callback(CLIENT_NEW_RESOURCE_ID, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
message(resourceBeingRetrieved);
|
||||
message(resourceBeingRetrievedClient);
|
||||
});
|
||||
world.con.client_add_recv_callback(CLIENT_NEW_RESOURCE_DATA, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
message(resources[resourceBeingRetrieved]);
|
||||
Logger::get().log("INFO", "Received new resource with id: " + std::to_string(resourceBeingRetrieved.first) + " " + std::to_string(resourceBeingRetrieved.second) + " of size " + std::to_string(resources[resourceBeingRetrieved].data->size()));
|
||||
resourceBeingRetrieved = {0, 0};
|
||||
message(resources[resourceBeingRetrievedClient]);
|
||||
Logger::get().log("INFO", "Received new resource with id: " + std::to_string(resourceBeingRetrievedClient.first) + " " + std::to_string(resourceBeingRetrievedClient.second) + " of size " + std::to_string(resources[resourceBeingRetrievedClient].data->size()));
|
||||
resourceBeingRetrievedClient = {0, 0};
|
||||
});
|
||||
}
|
||||
|
||||
ServerClientID ResourceManager::get_resource_being_retrieved() {
|
||||
return resourceBeingRetrieved;
|
||||
}
|
||||
|
||||
float ResourceManager::get_resource_retrieval_progress() {
|
||||
std::pair<uint64_t, uint64_t> progressBytes = world.con.client_get_resource_retrieval_progress();
|
||||
if(progressBytes.second == 0)
|
||||
float ResourceManager::get_resource_retrieval_progress(const ServerClientID& id) {
|
||||
if(id == ServerClientID{0, 0})
|
||||
return 0.0f;
|
||||
else
|
||||
return static_cast<float>(progressBytes.first) / static_cast<float>(progressBytes.second);
|
||||
if(world.con.host_exists() && !world.con.is_host_disconnected()) {
|
||||
auto it = serverDownloadProgress.find(id);
|
||||
if(it == serverDownloadProgress.end())
|
||||
return 0.0f;
|
||||
else {
|
||||
auto& progressBytes = it->second;
|
||||
if(progressBytes.totalBytes == 0)
|
||||
return 0.0f;
|
||||
return static_cast<float>(progressBytes.downloadedBytes) / static_cast<float>(progressBytes.totalBytes);
|
||||
}
|
||||
}
|
||||
else if(world.con.client_exists() && !world.con.is_client_disconnected()) {
|
||||
if(id != resourceBeingRetrievedClient)
|
||||
return 0.0f;
|
||||
else {
|
||||
NetLibrary::DownloadProgress progressBytes = world.con.client_get_resource_retrieval_progress();
|
||||
if(progressBytes.totalBytes == 0)
|
||||
return 0.0f;
|
||||
return static_cast<float>(progressBytes.downloadedBytes) / static_cast<float>(progressBytes.totalBytes);
|
||||
}
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void ResourceManager::update() {
|
||||
if(!world.con.host_exists() || world.con.is_host_disconnected())
|
||||
serverDownloadProgress.clear();
|
||||
else
|
||||
serverDownloadProgress = world.con.server_get_resource_retrieval_progress();
|
||||
|
||||
for(auto& [k, v] : displays)
|
||||
v->update(world);
|
||||
}
|
||||
|
|
@ -92,8 +112,8 @@ ServerClientID ResourceManager::add_resource(const ResourceData& resource) {
|
|||
}
|
||||
ServerClientID newID = world.get_new_id();
|
||||
resources[newID] = resource;
|
||||
world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_RESOURCE_INIT, newID);
|
||||
world.con.client_send_items_to_server(RESOURCE_COMMAND_CHANNEL, SERVER_RESOURCE_DATA, resource);
|
||||
world.con.client_send_items_to_server(RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_ID, newID);
|
||||
world.con.client_send_items_to_server(RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_DATA, resource);
|
||||
return newID;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <cereal/types/string.hpp>
|
||||
#include <cereal/types/unordered_map.hpp>
|
||||
#include <queue>
|
||||
#include <Helpers/Networking/NetLibrary.hpp>
|
||||
|
||||
class World;
|
||||
|
||||
|
|
@ -44,12 +45,12 @@ class ResourceManager {
|
|||
std::optional<ResourceData> get_resource(const ServerClientID& id) const;
|
||||
ClientPortionID get_max_id(ServerPortionID serverID) const;
|
||||
const std::unordered_map<ServerClientID, ResourceData>& resource_list();
|
||||
ServerClientID get_resource_being_retrieved();
|
||||
float get_resource_retrieval_progress();
|
||||
float get_resource_retrieval_progress(const ServerClientID& id);
|
||||
|
||||
World& world;
|
||||
private:
|
||||
ServerClientID resourceBeingRetrieved = {0, 0};
|
||||
std::unordered_map<ServerClientID, NetLibrary::DownloadProgress> serverDownloadProgress;
|
||||
ServerClientID resourceBeingRetrievedClient = {0, 0};
|
||||
|
||||
std::unordered_map<ServerClientID, ResourceData> resources;
|
||||
std::unordered_map<ServerClientID, std::shared_ptr<ResourceDisplay>> displays;
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ class ClientData {
|
|||
|
||||
uint64_t canvasScale = 0;
|
||||
|
||||
std::queue<ResourceData> pendingResourceData;
|
||||
std::queue<ServerClientID> pendingResourceID;
|
||||
ServerClientID pendingResourceID = {0, 0};
|
||||
|
||||
template <typename Archive> void serialize(Archive& a) {
|
||||
a(camCoords, windowSize, cursorPos, cursorColor, displayName);
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ enum ServerCommands : MessageCommandType {
|
|||
SERVER_ERASE_SINGLE_COMPONENT,
|
||||
SERVER_ERASE_MANY_COMPONENTS,
|
||||
SERVER_UPDATE_COMPONENT,
|
||||
SERVER_RESOURCE_INIT,
|
||||
SERVER_RESOURCE_DATA,
|
||||
SERVER_NEW_RESOURCE_ID,
|
||||
SERVER_NEW_RESOURCE_DATA,
|
||||
SERVER_CHAT_MESSAGE,
|
||||
SERVER_NEW_BOOKMARK,
|
||||
SERVER_REMOVE_BOOKMARK,
|
||||
|
|
|
|||
|
|
@ -185,33 +185,22 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID):
|
|||
comp->server_send_update(*this, isFinalUpdate);
|
||||
}
|
||||
});
|
||||
netServer->add_recv_callback(SERVER_RESOURCE_INIT, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
netServer->add_recv_callback(SERVER_NEW_RESOURCE_ID, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
auto& c = clients[client->customID];
|
||||
ServerClientID newID;
|
||||
message(newID);
|
||||
if(c.pendingResourceData.empty())
|
||||
c.pendingResourceID.emplace(newID);
|
||||
else {
|
||||
netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_ID, newID);
|
||||
netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_DATA, c.pendingResourceData.front());
|
||||
data.resources.emplace(newID, c.pendingResourceData.front());
|
||||
c.pendingResourceData.pop();
|
||||
}
|
||||
message(c.pendingResourceID);
|
||||
if(c.pendingResourceID == ServerClientID{0, 0})
|
||||
throw std::runtime_error("[MainServer::MainServer] Received a null resource ID");
|
||||
});
|
||||
netServer->add_recv_callback(SERVER_RESOURCE_DATA, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
netServer->add_recv_callback(SERVER_NEW_RESOURCE_DATA, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
ResourceData resourceData;
|
||||
message(resourceData);
|
||||
auto& c = clients[client->customID];
|
||||
if(c.pendingResourceID.empty()) {
|
||||
c.pendingResourceData.emplace();
|
||||
c.pendingResourceData.back() = std::move(resourceData);
|
||||
}
|
||||
else {
|
||||
netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_ID, c.pendingResourceID.front());
|
||||
netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_DATA, resourceData);
|
||||
data.resources.emplace(c.pendingResourceID.front(), resourceData);
|
||||
c.pendingResourceID.pop();
|
||||
}
|
||||
if(c.pendingResourceID == ServerClientID{0, 0})
|
||||
throw std::runtime_error("[MainServer::MainServer] Received data for a null resource ID");
|
||||
netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_ID, c.pendingResourceID);
|
||||
netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_DATA, resourceData);
|
||||
data.resources.emplace(c.pendingResourceID, resourceData);
|
||||
c.pendingResourceID = ServerClientID{0, 0};
|
||||
});
|
||||
netServer->add_recv_callback(SERVER_CHAT_MESSAGE, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
std::string chatMessage;
|
||||
|
|
@ -326,6 +315,28 @@ void MainServer::update() {
|
|||
}
|
||||
}
|
||||
|
||||
std::unordered_map<ServerClientID, NetLibrary::DownloadProgress> MainServer::resource_download_progress() {
|
||||
std::unordered_map<ServerClientID, NetLibrary::DownloadProgress> toRet;
|
||||
|
||||
if(!netServer)
|
||||
return toRet;
|
||||
|
||||
for(auto& [serverID, c] : clients) {
|
||||
if(c.pendingResourceID != ServerClientID{0, 0}) {
|
||||
const std::vector<std::shared_ptr<NetServer::ClientData>>& clientListInNetServer = netServer->get_client_list();
|
||||
auto netClientIt = std::find_if(clientListInNetServer.begin(), clientListInNetServer.end(), [&serverID](auto& nC) {
|
||||
return nC->customID == serverID;
|
||||
});
|
||||
if(netClientIt != clientListInNetServer.end()) {
|
||||
auto& netClient = *netClientIt;
|
||||
toRet.emplace(c.pendingResourceID, netClient->get_progress_into_fragmented_message(RESOURCE_COMMAND_CHANNEL));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return toRet;
|
||||
}
|
||||
|
||||
MainServer::~MainServer() {
|
||||
//netServer->close_server();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class MainServer {
|
|||
~MainServer();
|
||||
std::shared_ptr<NetServer> netServer;
|
||||
std::unordered_map<ServerPortionID, ClientData> clients;
|
||||
std::unordered_map<ServerClientID, NetLibrary::DownloadProgress> resource_download_progress();
|
||||
private:
|
||||
World& world;
|
||||
void ensure_display_name_unique(std::string& displayName);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue