Fixed networking flush algorithm for the file transfer

This commit is contained in:
WolverinDEV
2020-06-11 13:08:45 +02:00
parent 6e1323cc23
commit cbb0bd6864
5 changed files with 136 additions and 129 deletions
+37 -29
View File
@@ -107,13 +107,37 @@ bool FileClient::enqueue_disk_buffer_bytes(const void *snd_buffer, size_t size)
size_t buffer_size;
{
std::lock_guard block{this->disk_buffer.mutex};
if(this->disk_buffer.write_disconnected)
goto write_disconnected;
*this->disk_buffer.buffer_tail = tbuffer;
this->disk_buffer.buffer_tail = &tbuffer->next;
buffer_size = (this->disk_buffer.bytes += size);
}
return buffer_size > TRANSFER_MAX_CACHED_BYTES;
write_disconnected:
free_buffer(tbuffer);
return false;
}
void FileClient::flush_disk_buffer() {
Buffer* current_head;
{
std::lock_guard block{this->disk_buffer.mutex};
this->disk_buffer.write_disconnected = true;
this->disk_buffer.bytes = 0;
current_head = std::exchange(this->disk_buffer.buffer_head, nullptr);
this->disk_buffer.buffer_tail = &this->disk_buffer.buffer_head;
}
while(current_head) {
auto next = current_head->next;
free_buffer(current_head);
current_head = next;
}
}
FileInitializeResult LocalFileTransfer::initialize_file_io(const std::shared_ptr<FileClient> &transfer) {
@@ -226,8 +250,6 @@ FileInitializeResult LocalFileTransfer::initialize_file_io(const std::shared_ptr
}
}
} else if(transfer->transfer->direction == Transfer::DIRECTION_DOWNLOAD) {
transfer->disk_buffer.flushed = true; /* we're not using this buffer, so it will be flushed all the times */
auto file_size = lseek(file_data.file_descriptor, 0, SEEK_END);
if(file_size != transfer->transfer->expected_file_size) {
logWarning(LOG_FT, "{} Expected target file to be of size {}, but file is actually of size {}", transfer->log_prefix(), transfer->transfer->expected_file_size, file_size);
@@ -387,6 +409,8 @@ void LocalFileTransfer::execute_disk_io(const std::shared_ptr<FileClient> &clien
this->invoke_aborted_callback(client, { TransferError::UNEXPECTED_DISK_EOF, strerror(errno) });
client->flush_disk_buffer();
{
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client, slock, true);
@@ -404,6 +428,8 @@ void LocalFileTransfer::execute_disk_io(const std::shared_ptr<FileClient> &clien
client->log_prefix(), offset_written, client->transfer->expected_file_size, aoffset);
this->invoke_aborted_callback(client, { TransferError::DISK_IO_ERROR, strerror(errno) });
client->flush_disk_buffer();
{
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client, slock, true);
@@ -442,22 +468,7 @@ void LocalFileTransfer::execute_disk_io(const std::shared_ptr<FileClient> &clien
if(buffer_left_size > 0) {
this->enqueue_disk_io(client);
} else if(client->state == FileClient::STATE_DISCONNECTING) {
{
std::lock_guard nb_lock{client->network_buffer.mutex};
{
std::lock_guard db_lock{client->disk_buffer.mutex};
if(std::exchange(client->disk_buffer.flushed, true))
return;
}
if(!client->network_buffer.flushed) {
logTrace(LOG_FT, "{} Disk IO has been flushed, awaiting network buffer flush.", client->log_prefix());
return;
}
logTrace(LOG_FT, "{} Disk IO and network buffer have been flushed.", client->log_prefix());
}
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client->shared_from_this(), slock, false);
this->test_disconnecting_state(client);
}
if(client->state == FileClient::STATE_TRANSFERRING && buffer_left_size < TRANSFER_MAX_CACHED_BYTES / 2) {
@@ -466,7 +477,10 @@ void LocalFileTransfer::execute_disk_io(const std::shared_ptr<FileClient> &clien
client->add_network_read_event(false);
}
} else if(client->transfer->direction == Transfer::DIRECTION_DOWNLOAD) {
if(client->state == FileClient::STATE_DISCONNECTING) return;
if(client->state == FileClient::STATE_DISCONNECTING) {
client->flush_disk_buffer(); /* just in case */
return;
}
while(true) {
constexpr auto buffer_capacity{4096};
@@ -487,11 +501,6 @@ void LocalFileTransfer::execute_disk_io(const std::shared_ptr<FileClient> &clien
this->invoke_aborted_callback(client, { TransferError::UNEXPECTED_DISK_EOF, "" });
}
{
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client, slock, true);
}
} else {
if(errno == EAGAIN) {
this->enqueue_disk_io(client);
@@ -501,11 +510,10 @@ void LocalFileTransfer::execute_disk_io(const std::shared_ptr<FileClient> &clien
logWarning(LOG_FT, "{} Failed to read from file {} ({}/{}). Aborting transfer.", client->log_prefix(), client->transfer->absolute_file_path, errno, strerror(errno));
this->invoke_aborted_callback(client, { TransferError::DISK_IO_ERROR, strerror(errno) });
{
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client, slock, true);
}
}
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client, slock, true);
return;
} else {
auto buffer_full = client->send_file_bytes(buffer, read);