forked from lix-project/lix
filetransfer: make two-arg download abstract
this lets each implementation of FileTransfer (of which currently only
the one exists at all) implement appropriate handling for its internal
behaviours that are not otherwise exposed. in curl this lets us switch
the buffer-full handling method from "block the entire curl thread" to
"pause just the one transfer", move the non-libcurl body decompression
out of the actual curl wrapper (which will let us eventually morph the
curl wrapper intto an actual source of Sources), and some other things
Change-Id: Id6d3593cde6b4915aab3e90a43b175c103cc3f18
This commit is contained in:
parent
ce76d3eab2
commit
dfe3baea12
|
@ -696,55 +696,9 @@ struct curlFileTransfer : public FileTransfer
|
||||||
|
|
||||||
enqueueItem(std::make_shared<TransferItem>(*this, request, std::move(callback)));
|
enqueueItem(std::make_shared<TransferItem>(*this, request, std::move(callback)));
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
ref<curlFileTransfer> makeCurlFileTransfer()
|
void download(FileTransferRequest && request, Sink & sink) override
|
||||||
{
|
{
|
||||||
return make_ref<curlFileTransfer>();
|
|
||||||
}
|
|
||||||
|
|
||||||
ref<FileTransfer> getFileTransfer()
|
|
||||||
{
|
|
||||||
static ref<curlFileTransfer> fileTransfer = makeCurlFileTransfer();
|
|
||||||
|
|
||||||
if (fileTransfer->state_.lock()->quit)
|
|
||||||
fileTransfer = makeCurlFileTransfer();
|
|
||||||
|
|
||||||
return fileTransfer;
|
|
||||||
}
|
|
||||||
|
|
||||||
ref<FileTransfer> makeFileTransfer()
|
|
||||||
{
|
|
||||||
return makeCurlFileTransfer();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::future<FileTransferResult> FileTransfer::enqueueFileTransfer(const FileTransferRequest & request)
|
|
||||||
{
|
|
||||||
auto promise = std::make_shared<std::promise<FileTransferResult>>();
|
|
||||||
enqueueFileTransfer(request,
|
|
||||||
{[promise](std::future<FileTransferResult> fut) {
|
|
||||||
try {
|
|
||||||
promise->set_value(fut.get());
|
|
||||||
} catch (...) {
|
|
||||||
promise->set_exception(std::current_exception());
|
|
||||||
}
|
|
||||||
}});
|
|
||||||
return promise->get_future();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileTransferResult FileTransfer::download(const FileTransferRequest & request)
|
|
||||||
{
|
|
||||||
return enqueueFileTransfer(request).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileTransferResult FileTransfer::upload(const FileTransferRequest & request)
|
|
||||||
{
|
|
||||||
/* Note: this method is the same as download, but helps in readability */
|
|
||||||
return enqueueFileTransfer(request).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileTransfer::download(FileTransferRequest && request, Sink & sink)
|
|
||||||
{
|
|
||||||
/* Note: we can't call 'sink' via request.dataCallback, because
|
/* Note: we can't call 'sink' via request.dataCallback, because
|
||||||
that would cause the sink to execute on the fileTransfer
|
that would cause the sink to execute on the fileTransfer
|
||||||
thread. If 'sink' is a coroutine, this will fail. Also, if the
|
thread. If 'sink' is a coroutine, this will fail. Also, if the
|
||||||
|
@ -840,6 +794,52 @@ void FileTransfer::download(FileTransferRequest && request, Sink & sink)
|
||||||
thread if sink() takes a long time. */
|
thread if sink() takes a long time. */
|
||||||
sink(chunk);
|
sink(chunk);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ref<curlFileTransfer> makeCurlFileTransfer()
|
||||||
|
{
|
||||||
|
return make_ref<curlFileTransfer>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ref<FileTransfer> getFileTransfer()
|
||||||
|
{
|
||||||
|
static ref<curlFileTransfer> fileTransfer = makeCurlFileTransfer();
|
||||||
|
|
||||||
|
if (fileTransfer->state_.lock()->quit)
|
||||||
|
fileTransfer = makeCurlFileTransfer();
|
||||||
|
|
||||||
|
return fileTransfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref<FileTransfer> makeFileTransfer()
|
||||||
|
{
|
||||||
|
return makeCurlFileTransfer();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::future<FileTransferResult> FileTransfer::enqueueFileTransfer(const FileTransferRequest & request)
|
||||||
|
{
|
||||||
|
auto promise = std::make_shared<std::promise<FileTransferResult>>();
|
||||||
|
enqueueFileTransfer(request,
|
||||||
|
{[promise](std::future<FileTransferResult> fut) {
|
||||||
|
try {
|
||||||
|
promise->set_value(fut.get());
|
||||||
|
} catch (...) {
|
||||||
|
promise->set_exception(std::current_exception());
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
return promise->get_future();
|
||||||
|
}
|
||||||
|
|
||||||
|
FileTransferResult FileTransfer::download(const FileTransferRequest & request)
|
||||||
|
{
|
||||||
|
return enqueueFileTransfer(request).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
FileTransferResult FileTransfer::upload(const FileTransferRequest & request)
|
||||||
|
{
|
||||||
|
/* Note: this method is the same as download, but helps in readability */
|
||||||
|
return enqueueFileTransfer(request).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
|
|
|
@ -115,7 +115,7 @@ struct FileTransfer
|
||||||
* Download a file, writing its data to a sink. The sink will be
|
* Download a file, writing its data to a sink. The sink will be
|
||||||
* invoked on the thread of the caller.
|
* invoked on the thread of the caller.
|
||||||
*/
|
*/
|
||||||
void download(FileTransferRequest && request, Sink & sink);
|
virtual void download(FileTransferRequest && request, Sink & sink) = 0;
|
||||||
|
|
||||||
enum Error { NotFound, Forbidden, Misc, Transient, Interrupted };
|
enum Error { NotFound, Forbidden, Misc, Transient, Interrupted };
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue