mirror of https://github.com/OpenTTD/OpenTTD
(svn r21399) -Change/Feature/Fix [FS#4284]: perform the compression of savegames to send to the client asynchroniously. This will reduce the lag of the other clients to the time it takes to make the memory dump and it will speed up downloading the map as the download starts earlier (possibly with a slightly lower bandwidth due to slow compression). This should also fix the lag message people get when the savegame compression takes more than a few seconds.
parent
02b3bc57d5
commit
216e48cd07
|
@ -35,7 +35,7 @@ public:
|
||||||
bool IsConnected() const { return this->sock != INVALID_SOCKET; }
|
bool IsConnected() const { return this->sock != INVALID_SOCKET; }
|
||||||
|
|
||||||
virtual NetworkRecvStatus CloseConnection(bool error = true);
|
virtual NetworkRecvStatus CloseConnection(bool error = true);
|
||||||
void SendPacket(Packet *packet);
|
virtual void SendPacket(Packet *packet);
|
||||||
bool SendPackets(bool closing_down = false);
|
bool SendPackets(bool closing_down = false);
|
||||||
bool IsPacketQueueEmpty();
|
bool IsPacketQueueEmpty();
|
||||||
|
|
||||||
|
|
|
@ -67,13 +67,22 @@ struct PacketWriter : SaveFilter {
|
||||||
*/
|
*/
|
||||||
PacketWriter(ServerNetworkGameSocketHandler *cs) : SaveFilter(NULL), cs(cs), current(NULL), total_size(0)
|
PacketWriter(ServerNetworkGameSocketHandler *cs) : SaveFilter(NULL), cs(cs), current(NULL), total_size(0)
|
||||||
{
|
{
|
||||||
|
this->cs->savegame_mutex = ThreadMutex::New();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Make sure everything is cleaned up. */
|
/** Make sure everything is cleaned up. */
|
||||||
~PacketWriter()
|
~PacketWriter()
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Prevent double frees. */
|
/* Prevent double frees. */
|
||||||
this->cs->savegame = NULL;
|
if (this->cs != NULL) {
|
||||||
|
if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->BeginCritical();
|
||||||
|
this->cs->savegame = NULL;
|
||||||
|
if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->EndCritical();
|
||||||
|
|
||||||
|
delete this->cs->savegame_mutex;
|
||||||
|
this->cs->savegame_mutex = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
delete this->current;
|
delete this->current;
|
||||||
}
|
}
|
||||||
|
@ -94,10 +103,12 @@ struct PacketWriter : SaveFilter {
|
||||||
|
|
||||||
/* virtual */ void Write(byte *buf, size_t size)
|
/* virtual */ void Write(byte *buf, size_t size)
|
||||||
{
|
{
|
||||||
if (cs == NULL) return;
|
if (this->cs == NULL) return;
|
||||||
|
|
||||||
if (this->current == NULL) this->current = new Packet(PACKET_SERVER_MAP_DATA);
|
if (this->current == NULL) this->current = new Packet(PACKET_SERVER_MAP_DATA);
|
||||||
|
|
||||||
|
if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->BeginCritical();
|
||||||
|
|
||||||
byte *bufe = buf + size;
|
byte *bufe = buf + size;
|
||||||
while (buf != bufe) {
|
while (buf != bufe) {
|
||||||
size_t to_write = min(SEND_MTU - this->current->size, bufe - buf);
|
size_t to_write = min(SEND_MTU - this->current->size, bufe - buf);
|
||||||
|
@ -111,11 +122,17 @@ struct PacketWriter : SaveFilter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->EndCritical();
|
||||||
|
|
||||||
this->total_size += size;
|
this->total_size += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual */ void Finish()
|
/* virtual */ void Finish()
|
||||||
{
|
{
|
||||||
|
if (this->cs == NULL) return;
|
||||||
|
|
||||||
|
if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->BeginCritical();
|
||||||
|
|
||||||
/* Make sure the last packet is flushed. */
|
/* Make sure the last packet is flushed. */
|
||||||
this->AppendQueue();
|
this->AppendQueue();
|
||||||
|
|
||||||
|
@ -126,7 +143,9 @@ struct PacketWriter : SaveFilter {
|
||||||
/* Fast-track the size to the client. */
|
/* Fast-track the size to the client. */
|
||||||
Packet *p = new Packet(PACKET_SERVER_MAP_SIZE);
|
Packet *p = new Packet(PACKET_SERVER_MAP_SIZE);
|
||||||
p->Send_uint32(this->total_size);
|
p->Send_uint32(this->total_size);
|
||||||
this->cs->SendPacket(p);
|
this->cs->NetworkTCPSocketHandler::SendPacket(p);
|
||||||
|
|
||||||
|
if (this->cs->savegame_mutex != NULL) this->cs->savegame_mutex->EndCritical();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -153,7 +172,13 @@ ServerNetworkGameSocketHandler::~ServerNetworkGameSocketHandler()
|
||||||
{
|
{
|
||||||
if (_redirect_console_to_client == this->client_id) _redirect_console_to_client = INVALID_CLIENT_ID;
|
if (_redirect_console_to_client == this->client_id) _redirect_console_to_client = INVALID_CLIENT_ID;
|
||||||
OrderBackup::ResetUser(this->client_id);
|
OrderBackup::ResetUser(this->client_id);
|
||||||
|
|
||||||
|
if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical();
|
||||||
delete this->savegame_packets;
|
delete this->savegame_packets;
|
||||||
|
if (this->savegame != NULL) this->savegame->cs = NULL;
|
||||||
|
|
||||||
|
if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical();
|
||||||
|
delete this->savegame_mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet *ServerNetworkGameSocketHandler::ReceivePacket()
|
Packet *ServerNetworkGameSocketHandler::ReceivePacket()
|
||||||
|
@ -169,6 +194,13 @@ Packet *ServerNetworkGameSocketHandler::ReceivePacket()
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerNetworkGameSocketHandler::SendPacket(Packet *packet)
|
||||||
|
{
|
||||||
|
if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical();
|
||||||
|
this->NetworkTCPSocketHandler::SendPacket(packet);
|
||||||
|
if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical();
|
||||||
|
}
|
||||||
|
|
||||||
NetworkRecvStatus ServerNetworkGameSocketHandler::CloseConnection(NetworkRecvStatus status)
|
NetworkRecvStatus ServerNetworkGameSocketHandler::CloseConnection(NetworkRecvStatus status)
|
||||||
{
|
{
|
||||||
assert(status != NETWORK_RECV_STATUS_OKAY);
|
assert(status != NETWORK_RECV_STATUS_OKAY);
|
||||||
|
@ -479,10 +511,12 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap()
|
||||||
sent_packets = 4; // We start with trying 4 packets
|
sent_packets = 4; // We start with trying 4 packets
|
||||||
|
|
||||||
/* Make a dump of the current game */
|
/* Make a dump of the current game */
|
||||||
if (SaveWithFilter(this->savegame, false) != SL_OK) usererror("network savedump failed");
|
if (SaveWithFilter(this->savegame, true) != SL_OK) usererror("network savedump failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->status == STATUS_MAP) {
|
if (this->status == STATUS_MAP) {
|
||||||
|
if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical();
|
||||||
|
|
||||||
for (uint i = 0; i < sent_packets && this->savegame_packets != NULL; i++) {
|
for (uint i = 0; i < sent_packets && this->savegame_packets != NULL; i++) {
|
||||||
Packet *p = this->savegame_packets;
|
Packet *p = this->savegame_packets;
|
||||||
bool last_packet = p->buffer[2] == PACKET_SERVER_MAP_DONE;
|
bool last_packet = p->buffer[2] == PACKET_SERVER_MAP_DONE;
|
||||||
|
@ -490,7 +524,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap()
|
||||||
/* Remove the packet from the savegame queue and put it in the real queue. */
|
/* Remove the packet from the savegame queue and put it in the real queue. */
|
||||||
this->savegame_packets = p->next;
|
this->savegame_packets = p->next;
|
||||||
p->next = NULL;
|
p->next = NULL;
|
||||||
this->SendPacket(p);
|
this->NetworkTCPSocketHandler::SendPacket(p);
|
||||||
|
|
||||||
if (last_packet) {
|
if (last_packet) {
|
||||||
/* Done reading! */
|
/* Done reading! */
|
||||||
|
@ -531,6 +565,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap()
|
||||||
/* Not everything is sent, decrease the sent_packets */
|
/* Not everything is sent, decrease the sent_packets */
|
||||||
if (sent_packets > 1) sent_packets /= 2;
|
if (sent_packets > 1) sent_packets /= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical();
|
||||||
}
|
}
|
||||||
return NETWORK_RECV_STATUS_OKAY;
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "network_internal.h"
|
#include "network_internal.h"
|
||||||
#include "core/tcp_listen.h"
|
#include "core/tcp_listen.h"
|
||||||
|
#include "../thread/thread.h"
|
||||||
|
|
||||||
class ServerNetworkGameSocketHandler;
|
class ServerNetworkGameSocketHandler;
|
||||||
typedef ServerNetworkGameSocketHandler NetworkClientSocket;
|
typedef ServerNetworkGameSocketHandler NetworkClientSocket;
|
||||||
|
@ -74,11 +75,13 @@ public:
|
||||||
|
|
||||||
Packet *savegame_packets; ///< Packet queue of the savegame; send these "slowly" to the client.
|
Packet *savegame_packets; ///< Packet queue of the savegame; send these "slowly" to the client.
|
||||||
struct PacketWriter *savegame; ///< Writer used to write the savegame.
|
struct PacketWriter *savegame; ///< Writer used to write the savegame.
|
||||||
|
ThreadMutex *savegame_mutex; ///< Mutex for making threaded saving safe.
|
||||||
|
|
||||||
ServerNetworkGameSocketHandler(SOCKET s);
|
ServerNetworkGameSocketHandler(SOCKET s);
|
||||||
~ServerNetworkGameSocketHandler();
|
~ServerNetworkGameSocketHandler();
|
||||||
|
|
||||||
virtual Packet *ReceivePacket();
|
virtual Packet *ReceivePacket();
|
||||||
|
virtual void SendPacket(Packet *packet);
|
||||||
NetworkRecvStatus CloseConnection(NetworkRecvStatus status);
|
NetworkRecvStatus CloseConnection(NetworkRecvStatus status);
|
||||||
void GetClientName(char *client_name, size_t size) const;
|
void GetClientName(char *client_name, size_t size) const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue