libstore: simplify TransferSource::read

things can be much simpler if the read loop knows whether the transfer
is done or not. this information is available, let's pass it back down

Change-Id: Idb99afeb06a0d7a0999c3f4a1c6ce5adeab5f054
This commit is contained in:
eldritch horrors 2024-11-15 16:15:11 +01:00
parent b22f2bc8e9
commit 3b1298efce

View file

@ -861,52 +861,41 @@ struct curlFileTransfer : public FileTransfer
return true; return true;
} }
void awaitData() bool awaitData()
{ {
withRetries([&] { return withRetries([&] {
/* Grab data if available, otherwise wait for the download /* Grab data if available, otherwise wait for the download
thread to wake us up. */ thread to wake us up. */
while (buffered.empty()) { while (buffered.empty()) {
auto state(transfer->downloadState.lock()); auto state(transfer->downloadState.lock());
if (state->data.empty()) { if (!state->data.empty()) {
if (state->exc) { chunk = std::move(state->data);
std::rethrow_exception(state->exc); buffered = chunk;
} else if (state->done) { totalReceived += chunk.size();
return; parent.unpause(transfer);
} } else if (state->exc) {
std::rethrow_exception(state->exc);
} else if (state->done) {
return false;
} else {
parent.unpause(transfer); parent.unpause(transfer);
state.wait(transfer->downloadEvent); state.wait(transfer->downloadEvent);
} }
chunk = std::move(state->data);
buffered = chunk;
totalReceived += chunk.size();
parent.unpause(transfer);
} }
return true;
}); });
} }
size_t read(char * data, size_t len) override size_t read(char * data, size_t len) override
{ {
auto readPartial = [this](char * data, size_t len) -> size_t { size_t total = 0;
const auto available = std::min(len, buffered.size()); while (total < len && awaitData()) {
if (available == 0u) return 0u; const auto available = std::min(len - total, buffered.size());
memcpy(data + total, buffered.data(), available);
memcpy(data, buffered.data(), available);
buffered.remove_prefix(available); buffered.remove_prefix(available);
return available; total += available;
};
size_t total = readPartial(data, len);
while (total < len) {
awaitData();
const auto current = readPartial(data + total, len - total);
total += current;
if (total == 0 || current == 0) {
break;
}
} }
if (total == 0) { if (total == 0) {