diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2016-01-11 12:52:41 -0800 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2016-01-13 13:40:31 -0800 |
commit | 86c8446d3a4390ff6577d070ac8b5fa3ad3c5cd1 (patch) | |
tree | ef10190d3fca34ff72b2473816901088b0b85ac2 /platform | |
parent | 2126e34e52dc5dd94c5a3907b240e62ee17d1e70 (diff) | |
download | qtlocation-mapboxgl-86c8446d3a4390ff6577d070ac8b5fa3ad3c5cd1.tar.gz |
[core] Simplify asset:// implementation
* Move asset:// URL handling to DefaultFileSource.
* AssetFileSource implements FileSource interface and follows familiar implementation patterns.
* Move default implementation to platform/default, zip implementation to platform/android.
* Don't bother with modified / expires / etag -- assets are not cached so it doesn't matter.
* Don't bother with interleaving individual IO calls on the implementation thread. That adds a lot of complexity for very little benefit.
Diffstat (limited to 'platform')
-rw-r--r-- | platform/android/src/asset_file_source.cpp | 111 | ||||
-rw-r--r-- | platform/default/asset_file_source.cpp | 79 | ||||
-rw-r--r-- | platform/default/asset_request_fs.cpp | 234 | ||||
-rw-r--r-- | platform/default/asset_request_zip.cpp | 319 | ||||
-rw-r--r-- | platform/default/default_file_source.cpp | 28 | ||||
-rw-r--r-- | platform/default/online_file_source.cpp | 26 |
6 files changed, 221 insertions, 576 deletions
diff --git a/platform/android/src/asset_file_source.cpp b/platform/android/src/asset_file_source.cpp new file mode 100644 index 0000000000..1f02f9cf4a --- /dev/null +++ b/platform/android/src/asset_file_source.cpp @@ -0,0 +1,111 @@ +#include <mbgl/storage/asset_file_source.hpp> +#include <mbgl/storage/response.hpp> +#include <mbgl/util/util.hpp> +#include <mbgl/util/thread.hpp> + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#include <zip.h> +#pragma GCC diagnostic pop + +namespace { + +struct ZipHolder { + ZipHolder(struct zip* archive_) : archive(archive_) {} + + ~ZipHolder() { + if (archive) ::zip_close(archive); + } + + struct zip* archive; +}; + +struct ZipFileHolder { + ZipFileHolder(struct zip_file* file_) : file(file_) {} + + ~ZipFileHolder() { + if (file) ::zip_fclose(file); + } + + struct zip_file* file; +}; + +} + +namespace mbgl { + +class AssetFileRequest : public FileRequest { +public: + AssetFileRequest(std::unique_ptr<WorkRequest> workRequest_) + : workRequest(std::move(workRequest_)) { + } + + std::unique_ptr<WorkRequest> workRequest; +}; + +class AssetFileSource::Impl { +public: + Impl(const std::string& root_) + : root(root_) { + } + + void request(const std::string& url, FileSource::Callback callback) { + ZipHolder archive = ::zip_open(root.c_str(), 0, nullptr); + if (!archive.archive) { + reportError(Response::Error::Reason::Other, "Could not open zip archive", callback); + return; + } + + struct zip_stat stat; + ::zip_stat_init(&stat); + + std::string path = std::string("assets/") + url.substr(8); + int ret = ::zip_stat(archive.archive, path.c_str(), 0, &stat); + if (ret < 0 || !(stat.valid & ZIP_STAT_SIZE)) { + reportError(Response::Error::Reason::NotFound, "Could not stat file in zip archive", callback); + return; + } + + ZipFileHolder file = ::zip_fopen(archive.archive, path.c_str(), 0); + if (!file.file) { + reportError(Response::Error::Reason::NotFound, "Could not open file in zip archive", callback); + return; + } + + std::shared_ptr<std::string> buf = std::make_shared<std::string>(); + buf->resize(stat.size); + + ret = ::zip_fread(file.file, &buf->front(), stat.size); + if (ret < 0) { + reportError(Response::Error::Reason::Other, "Could not read file in zip archive", callback); + return; + } + + Response response; + response.data = buf; + callback(response); + } + + void reportError(Response::Error::Reason reason, const char * message, FileSource::Callback callback) { + Response response; + response.error = std::make_unique<Response::Error>(reason, message); + callback(response); + } + +private: + std::string root; +}; + +AssetFileSource::AssetFileSource(const std::string& root) + : thread(std::make_unique<util::Thread<Impl>>( + util::ThreadContext{"AssetFileSource", util::ThreadType::Worker, util::ThreadPriority::Regular}, + root.empty() ? platform::assetRoot() : root)) { +} + +AssetFileSource::~AssetFileSource() = default; + +std::unique_ptr<FileRequest> AssetFileSource::request(const Resource& resource, Callback callback) { + return std::make_unique<AssetFileRequest>(thread->invokeWithCallback(&Impl::request, callback, resource.url)); +} + +} diff --git a/platform/default/asset_file_source.cpp b/platform/default/asset_file_source.cpp new file mode 100644 index 0000000000..5aa5730c94 --- /dev/null +++ b/platform/default/asset_file_source.cpp @@ -0,0 +1,79 @@ +#include <mbgl/storage/asset_file_source.hpp> +#include <mbgl/storage/response.hpp> +#include <mbgl/util/string.hpp> +#include <mbgl/util/thread.hpp> +#include <mbgl/util/url.hpp> +#include <mbgl/util/util.hpp> +#include <mbgl/util/io.hpp> + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +namespace mbgl { + +class AssetFileRequest : public FileRequest { +public: + AssetFileRequest(std::unique_ptr<WorkRequest> workRequest_) + : workRequest(std::move(workRequest_)) { + } + + std::unique_ptr<WorkRequest> workRequest; +}; + +class AssetFileSource::Impl { +public: + Impl(const std::string& root_) + : root(root_) { + } + + void request(const std::string& url, FileSource::Callback callback) { + std::string path; + + if (url.size() <= 8 || url[8] == '/') { + // This is an empty or absolute path. + path = mbgl::util::percentDecode(url.substr(8)); + } else { + // This is a relative path. Prefix with the application root. + path = root + "/" + mbgl::util::percentDecode(url.substr(8)); + } + + Response response; + + struct stat buf; + int result = stat(path.c_str(), &buf); + + if (result == 0 && S_ISDIR(buf.st_mode)) { + response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound); + } else if (result == -1 && errno == ENOENT) { + response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound); + } else { + try { + response.data = std::make_shared<std::string>(util::read_file(path)); + } catch (...) { + response.error = std::make_unique<Response::Error>( + Response::Error::Reason::Other, + util::toString(std::current_exception())); + } + } + + callback(response); + } + +private: + std::string root; +}; + +AssetFileSource::AssetFileSource(const std::string& root) + : thread(std::make_unique<util::Thread<Impl>>( + util::ThreadContext{"AssetFileSource", util::ThreadType::Worker, util::ThreadPriority::Regular}, + root.empty() ? platform::assetRoot() : root)) { +} + +AssetFileSource::~AssetFileSource() = default; + +std::unique_ptr<FileRequest> AssetFileSource::request(const Resource& resource, Callback callback) { + return std::make_unique<AssetFileRequest>(thread->invokeWithCallback(&Impl::request, callback, resource.url)); +} + +} // namespace mbgl diff --git a/platform/default/asset_request_fs.cpp b/platform/default/asset_request_fs.cpp deleted file mode 100644 index 2ef22f9586..0000000000 --- a/platform/default/asset_request_fs.cpp +++ /dev/null @@ -1,234 +0,0 @@ -#include <mbgl/storage/asset_context_base.hpp> -#include <mbgl/storage/response.hpp> -#include <mbgl/util/string.hpp> -#include <mbgl/util/thread.hpp> -#include <mbgl/util/url.hpp> -#include <mbgl/util/util.hpp> - -#include <errno.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -namespace { - -struct FDHolder { - FDHolder(int fd_) : fd(fd_) {} - - ~FDHolder() { - if (fd >= 0) ::close(fd); - } - - int fd; -}; - -class FileIOWorker { -public: - FileIOWorker() = default; - - void open(const std::string& path, int flags, mode_t mode, - std::function<void(std::unique_ptr<FDHolder>)> cb) { - // FDHolder is needed because if the request gets canceled - // we would otherwise end up with a fd leaking. - int ret = ::open(path.c_str(), flags, mode); - cb(std::make_unique<FDHolder>(ret < 0 ? -errno : ret)); - } - - void fstat(int fd, std::function<void (int, std::unique_ptr<struct stat>)> cb) { - std::unique_ptr<struct stat> buf = std::make_unique<struct stat>(); - int ret = ::fstat(fd, buf.get()); - cb(ret < 0 ? -errno : ret, std::move(buf)); - } - - void read(int fd, size_t size, - std::function<void (ssize_t, std::shared_ptr<std::string>)> cb) { - std::shared_ptr<std::string> buf = std::make_shared<std::string>(); - buf->resize(size); - - ssize_t ret = ::read(fd, &buf->front(), size); - cb(ret < 0 ? -errno : ret, std::move(buf)); - } - - void close(int fd, std::function<void (void)> cb) { - ::close(fd); - cb(); - } -}; - -} // namespace - -namespace mbgl { - -using namespace std::placeholders; - -class AssetRequest : public RequestBase { - MBGL_STORE_THREAD(tid) - -public: - AssetRequest(const std::string& url, Callback, const std::string& assetRoot, - util::Thread<FileIOWorker> *worker); - ~AssetRequest(); - - // RequestBase implementation. - void cancel() final; - -private: - void fileOpened(std::unique_ptr<FDHolder>); - void fileStated(int result, std::unique_ptr<struct stat>); - void fileRead(int result, std::shared_ptr<std::string>); - void fileClosed(); - - void notifyError(int result); - - void close(); - void cleanup(); - - std::string assetRoot; - std::unique_ptr<Response> response; - - int fd = -1; - - util::Thread<FileIOWorker> *worker; - std::unique_ptr<WorkRequest> request; -}; - -class AssetFSContext : public AssetContextBase { -public: - AssetFSContext() - : worker({"FileIOWorker", util::ThreadType::Worker, util::ThreadPriority::Regular}) {} - -private: - RequestBase* createRequest(const std::string& url, - RequestBase::Callback callback, - const std::string& assetRoot) final { - return new AssetRequest(url, callback, assetRoot, &worker); - } - - util::Thread<FileIOWorker> worker; -}; - -AssetRequest::~AssetRequest() { - MBGL_VERIFY_THREAD(tid); -} - -AssetRequest::AssetRequest(const std::string& url_, Callback callback_, - const std::string& assetRoot_, util::Thread<FileIOWorker> *worker_) - : RequestBase(url_, callback_), - assetRoot(assetRoot_), - worker(worker_) { - std::string path; - if (url.size() <= 8 || url[8] == '/') { - // This is an empty or absolute path. - path = mbgl::util::percentDecode(url.substr(8)); - } else { - // This is a relative path. Prefix with the application root. - path = assetRoot + "/" + mbgl::util::percentDecode(url.substr(8)); - } - - request = worker->invokeWithCallback(&FileIOWorker::open, - std::bind(&AssetRequest::fileOpened, this, _1), path, O_RDONLY, S_IRUSR); -} - -void AssetRequest::cancel() { - MBGL_VERIFY_THREAD(tid); - - request.reset(); - close(); -} - -void AssetRequest::fileOpened(std::unique_ptr<FDHolder> holder) { - MBGL_VERIFY_THREAD(tid); - - std::swap(fd, holder->fd); - - if (fd < 0) { - // Opening failed. There isn't much left we can do. - notifyError(fd); - cleanup(); - - return; - } - - request = worker->invokeWithCallback(&FileIOWorker::fstat, - std::bind(&AssetRequest::fileStated, this, _1, _2), fd); -} - -void AssetRequest::fileStated(int result, std::unique_ptr<struct stat> stat) { - MBGL_VERIFY_THREAD(tid); - - if (result != 0) { - // Stating failed. We already have an open file handle - // though, which we'll have to close. - notifyError(result); - close(); - } else { - response = std::make_unique<Response>(); - response->modified = Seconds(stat->st_mtime); - response->etag = util::toString(stat->st_ino); - - request = worker->invokeWithCallback(&FileIOWorker::read, - std::bind(&AssetRequest::fileRead, this, _1, _2), fd, stat->st_size); - } -} - -void AssetRequest::fileRead(int result, std::shared_ptr<std::string> data) { - MBGL_VERIFY_THREAD(tid); - - if (result < 0) { - // Reading failed. We already have an open file handle - // though, which we'll have to close. - notifyError(result); - } else { - response->data = data; - notify(std::move(response)); - } - - close(); -} - -void AssetRequest::fileClosed() { - MBGL_VERIFY_THREAD(tid); - - cleanup(); -} - -void AssetRequest::close() { - MBGL_VERIFY_THREAD(tid); - - if (fd >= 0) { - request = worker->invokeWithCallback(&FileIOWorker::close, - std::bind(&AssetRequest::fileClosed, this), fd); - fd = -1; - } else { - cleanup(); - } -} - -void AssetRequest::cleanup() { - MBGL_VERIFY_THREAD(tid); - - delete this; -} - -void AssetRequest::notifyError(int result) { - MBGL_VERIFY_THREAD(tid); - - result = std::abs(result); - Response::Error::Reason reason = Response::Error::Reason::Other; - - if (result == ENOENT || result == EISDIR) { - reason = Response::Error::Reason::NotFound; - } - - response = std::make_unique<Response>(); - response->error = std::make_unique<Response::Error>(reason, ::strerror(result)); - - notify(std::move(response)); -} - -std::unique_ptr<AssetContextBase> AssetContextBase::createContext() { - return std::make_unique<AssetFSContext>(); -} - -} // namespace mbgl diff --git a/platform/default/asset_request_zip.cpp b/platform/default/asset_request_zip.cpp deleted file mode 100644 index 76bf8bba14..0000000000 --- a/platform/default/asset_request_zip.cpp +++ /dev/null @@ -1,319 +0,0 @@ -#include <mbgl/storage/asset_context_base.hpp> -#include <mbgl/storage/response.hpp> -#include <mbgl/util/chrono.hpp> -#include <mbgl/util/util.hpp> -#include <mbgl/util/thread.hpp> - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#include <zip.h> -#pragma GCC diagnostic pop - -#include <cassert> -#include <forward_list> -#include <map> - -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> - -namespace { - -struct ZipHolder { - ZipHolder(struct zip* archive_) : archive(archive_) {} - - ~ZipHolder() { - if (archive) ::zip_discard(archive); - } - - struct zip* archive; -}; - -struct ZipFileHolder { - ZipFileHolder(struct zip_file* file_) : file(file_) {} - - ~ZipFileHolder() { - if (file) ::zip_fclose(file); - } - - struct zip_file* file; -}; - -class ZipIOWorker { -public: - ZipIOWorker() = default; - - void zip_fdopen(const std::string& path, - std::function<void(std::unique_ptr<ZipHolder>)> cb) { - int fd = ::open(path.c_str(), O_RDONLY, S_IRUSR); - if (fd < 0) { - cb(std::make_unique<ZipHolder>(nullptr)); - } else { - int errorp; - struct zip* archive = ::zip_fdopen(fd, 0, &errorp); - cb(std::make_unique<ZipHolder>(archive)); - } - } - - void zip_stat(struct zip* archive, const std::string& path, - std::function<void (int, std::unique_ptr<struct zip_stat>)> cb) { - std::unique_ptr<struct zip_stat> buf = std::make_unique<struct zip_stat>(); - ::zip_stat_init(buf.get()); - - int ret = ::zip_stat(archive, path.c_str(), 0, buf.get()); - cb(ret, std::move(buf)); - } - - void zip_fopen(struct zip* archive, const std::string& path, - std::function<void (std::unique_ptr<ZipFileHolder>)> cb) { - struct zip_file* file = ::zip_fopen(archive, path.c_str(), 0); - cb(std::make_unique<ZipFileHolder>(file)); - } - - void zip_fread(struct zip_file* file, size_t size, - std::function<void (int, std::shared_ptr<std::string>)> cb) { - std::shared_ptr<std::string> buf = std::make_shared<std::string>(); - buf->resize(size); - - int ret = ::zip_fread(file, &buf->front(), size); - cb(ret, std::move(buf)); - } - - void zip_fclose(struct zip_file* file, std::function<void (int)> cb) { - cb(::zip_fclose(file)); - } -}; - -} - -namespace mbgl { - -using namespace std::placeholders; - -class AssetZipContext; - -class AssetRequest : public RequestBase { - MBGL_STORE_THREAD(tid) - -public: - AssetRequest(const std::string& url, Callback, const std::string& assetRoot, - AssetZipContext* context, util::Thread<ZipIOWorker>* worker); - ~AssetRequest(); - - // RequestBase implementation. - void cancel() final; - -private: - void openArchive(); - void archiveOpened(std::unique_ptr<ZipHolder>); - void fileStated(int result, std::unique_ptr<struct zip_stat>); - void fileOpened(std::unique_ptr<ZipFileHolder>); - void fileRead(int result, std::shared_ptr<std::string>); - void fileClosed(); - - void close(); - void cleanup(); - - void notifyError(Response::Error::Reason, const char *message); - - const std::string root; - const std::string path; - std::unique_ptr<Response> response; - - struct zip* archive = nullptr; - struct zip_file* file = nullptr; - size_t size = 0; - - AssetZipContext *context; - - util::Thread<ZipIOWorker> *worker; - std::unique_ptr<WorkRequest> request; -}; - -class AssetZipContext : public AssetContextBase { -public: - AssetZipContext(); - ~AssetZipContext(); - - RequestBase* createRequest(const std::string& url, - RequestBase::Callback callback, - const std::string& assetRoot) final { - return new AssetRequest(url, callback, assetRoot, this, &worker); - } - - struct zip *getHandle(const std::string &path); - void returnHandle(const std::string &path, struct zip *zip); - - // A list of resuable zip handles to avoid creating - // and destroying them all the time. - std::map<std::string, std::forward_list<struct zip*>> handles; - - util::Thread<ZipIOWorker> worker; - std::unique_ptr<WorkRequest> request; -}; - -AssetZipContext::AssetZipContext() - : worker({"ZipIOWorker", util::ThreadType::Worker, util::ThreadPriority::Regular}) {} - -AssetZipContext::~AssetZipContext() { - // Close all zip handles - for (auto &list : handles) { - for (auto archive : list.second) { - zip_discard(archive); - } - } - - handles.clear(); -} - -struct zip* AssetZipContext::getHandle(const std::string &path) { - auto &list = handles[path]; - if (!list.empty()) { - auto archive = list.front(); - list.pop_front(); - return archive; - } else { - return nullptr; - } -} - -void AssetZipContext::returnHandle(const std::string &path, struct zip* archive) { - handles[path].push_front(archive); -} - -AssetRequest::AssetRequest(const std::string& url_, Callback callback_, - const std::string& assetRoot, AssetZipContext* context_, util::Thread<ZipIOWorker>* worker_) - : RequestBase(url_, callback_), - root(assetRoot), - path(std::string("assets/") + url.substr(8)), - context(context_), - worker(worker_) { - archive = context->getHandle(root); - if (archive) { - request = worker->invokeWithCallback(&ZipIOWorker::zip_stat, - std::bind(&AssetRequest::fileStated, this, _1, _2), archive, path); - } else { - request = worker->invokeWithCallback(&ZipIOWorker::zip_fdopen, - std::bind(&AssetRequest::archiveOpened, this, _1), root); - } -} - -AssetRequest::~AssetRequest() { - MBGL_VERIFY_THREAD(tid); -} - -void AssetRequest::cancel() { - MBGL_VERIFY_THREAD(tid); - - request.reset(); - close(); -} - -void AssetRequest::archiveOpened(std::unique_ptr<ZipHolder> holder) { - MBGL_VERIFY_THREAD(tid); - - std::swap(archive, holder->archive); - - if (!archive) { - notifyError(Response::Error::Reason::Other, "Could not open zip archive"); - cleanup(); - } else { - request = worker->invokeWithCallback(&ZipIOWorker::zip_stat, - std::bind(&AssetRequest::fileStated, this, _1, _2), archive, path); - } -} - -void AssetRequest::fileStated(int result, std::unique_ptr<struct zip_stat> stat) { - MBGL_VERIFY_THREAD(tid); - - if (result < 0 || !(stat->valid & ZIP_STAT_SIZE)) { - notifyError(Response::Error::Reason::NotFound, "Could not stat file in zip archive"); - cleanup(); - } else { - response = std::make_unique<Response>(); - - if (stat->valid & ZIP_STAT_MTIME) { - response->modified = Seconds(stat->mtime); - } - - if (stat->valid & ZIP_STAT_INDEX) { - response->etag = std::to_string(stat->index); - } - - size = stat->size; - - request = worker->invokeWithCallback(&ZipIOWorker::zip_fopen, - std::bind(&AssetRequest::fileOpened, this, _1), archive, path); - } -} - -void AssetRequest::fileOpened(std::unique_ptr<ZipFileHolder> holder) { - MBGL_VERIFY_THREAD(tid); - - std::swap(file, holder->file); - - if (!file) { - notifyError(Response::Error::Reason::NotFound, "Could not open file in zip archive"), - cleanup(); - } else { - request = worker->invokeWithCallback(&ZipIOWorker::zip_fread, - std::bind(&AssetRequest::fileRead, this, _1, _2), file, size); - } -} - -void AssetRequest::fileRead(int result, std::shared_ptr<std::string> data) { - MBGL_VERIFY_THREAD(tid); - - if (result < 0) { - notifyError(Response::Error::Reason::Other, "Could not read file in zip archive"); - } else { - response->data = data; - notify(std::move(response)); - } - - close(); -} - -void AssetRequest::fileClosed() { - MBGL_VERIFY_THREAD(tid); - - cleanup(); -} - - -void AssetRequest::close() { - MBGL_VERIFY_THREAD(tid); - - if (file) { - request = worker->invokeWithCallback(&ZipIOWorker::zip_fclose, - std::bind(&AssetRequest::fileClosed, this), file); - file = nullptr; - } else { - cleanup(); - } -} - -void AssetRequest::cleanup() { - MBGL_VERIFY_THREAD(tid); - - if (archive) { - context->returnHandle(root, archive); - } - - delete this; -} - -void AssetRequest::notifyError(Response::Error::Reason reason, const char *message) { - MBGL_VERIFY_THREAD(tid); - - response = std::make_unique<Response>(); - response->error = std::make_unique<Response::Error>(reason, message); - - notify(std::move(response)); -} - -std::unique_ptr<AssetContextBase> AssetContextBase::createContext() { - return std::make_unique<AssetZipContext>(); -} - -} diff --git a/platform/default/default_file_source.cpp b/platform/default/default_file_source.cpp index d2bbce6002..8f2f024a11 100644 --- a/platform/default/default_file_source.cpp +++ b/platform/default/default_file_source.cpp @@ -1,16 +1,32 @@ #include <mbgl/storage/default_file_source.hpp> +#include <mbgl/storage/asset_file_source.hpp> #include <mbgl/storage/online_file_source.hpp> #include <mbgl/storage/sqlite_cache.hpp> +#include <mbgl/platform/platform.hpp> +#include <mbgl/util/url.hpp> + +namespace { + +const std::string assetProtocol = "asset://"; + +bool isAssetURL(const std::string& url) { + return std::equal(assetProtocol.begin(), assetProtocol.end(), url.begin()); +} + +} // namespace + namespace mbgl { class DefaultFileSource::Impl { public: - Impl(const std::string& cachePath, const std::string& root) - : cache(SharedSQLiteCache::get(cachePath)), - onlineFileSource(cache.get(), root) { + Impl(const std::string& cachePath, const std::string& assetRoot) + : assetFileSource(assetRoot), + cache(SharedSQLiteCache::get(cachePath)), + onlineFileSource(cache.get()) { } + AssetFileSource assetFileSource; std::shared_ptr<SQLiteCache> cache; OnlineFileSource onlineFileSource; }; @@ -38,7 +54,11 @@ void DefaultFileSource::setMaximumCacheEntrySize(uint64_t size) { } std::unique_ptr<FileRequest> DefaultFileSource::request(const Resource& resource, Callback callback) { - return impl->onlineFileSource.request(resource, callback); + if (isAssetURL(resource.url)) { + return impl->assetFileSource.request(resource, callback); + } else { + return impl->onlineFileSource.request(resource, callback); + } } } // namespace mbgl diff --git a/platform/default/online_file_source.cpp b/platform/default/online_file_source.cpp index 480d2a8276..84be64a22f 100644 --- a/platform/default/online_file_source.cpp +++ b/platform/default/online_file_source.cpp @@ -1,10 +1,8 @@ #include <mbgl/storage/online_file_source.hpp> -#include <mbgl/storage/asset_context_base.hpp> #include <mbgl/storage/http_context_base.hpp> #include <mbgl/storage/network_status.hpp> #include <mbgl/storage/response.hpp> -#include <mbgl/platform/platform.hpp> #include <mbgl/platform/log.hpp> #include <mbgl/util/thread.hpp> @@ -14,7 +12,6 @@ #include <mbgl/util/async_task.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/timer.hpp> -#include <mbgl/util/url.hpp> #include <algorithm> #include <cassert> @@ -83,7 +80,7 @@ class OnlineFileSource::Impl { public: using Callback = std::function<void (Response)>; - Impl(FileCache*, const std::string& = ""); + Impl(FileCache*); ~Impl(); void networkIsReachableAgain(); @@ -96,17 +93,14 @@ private: std::unordered_map<Resource, std::unique_ptr<OnlineFileRequestImpl>, Resource::Hash> pending; FileCache* const cache; - const std::string assetRoot; - const std::unique_ptr<AssetContextBase> assetContext; const std::unique_ptr<HTTPContextBase> httpContext; util::AsyncTask reachability; }; -OnlineFileSource::OnlineFileSource(FileCache* cache, const std::string& root) +OnlineFileSource::OnlineFileSource(FileCache* cache) : thread(std::make_unique<util::Thread<Impl>>( util::ThreadContext{ "OnlineFileSource", util::ThreadType::Unknown, util::ThreadPriority::Low }, - cache, - root)) { + cache)) { } OnlineFileSource::~OnlineFileSource() = default; @@ -152,10 +146,8 @@ void OnlineFileSource::cancel(const Resource& res, FileRequest* req) { // ----- Impl ----- -OnlineFileSource::Impl::Impl(FileCache* cache_, const std::string& root) +OnlineFileSource::Impl::Impl(FileCache* cache_) : cache(cache_), - assetRoot(root.empty() ? platform::assetRoot() : root), - assetContext(AssetContextBase::createContext()), httpContext(HTTPContextBase::createContext()), reachability(std::bind(&Impl::networkIsReachableAgain, this)) { // Subscribe to network status changes, but make sure that this async handle doesn't keep the @@ -242,7 +234,7 @@ void OnlineFileRequestImpl::addObserver(FileRequest* req, Callback callback, Onl } else if (!cacheRequest && !realRequest) { // There is no request in progress, and we don't have a response yet. This means we'll have // to start the request ourselves. - if (impl.cache && !util::isAssetURL(resource.url)) { + if (impl.cache) { scheduleCacheRequest(impl); } else { scheduleRealRequest(impl); @@ -330,7 +322,7 @@ void OnlineFileRequestImpl::scheduleRealRequest(OnlineFileSource::Impl& impl, bo // In particular, we don't want to write a Canceled request, or one that failed due to // connection errors to the cache. Server errors are hopefully also temporary, so we're not // caching them either. - if (impl.cache && !util::isAssetURL(resource.url) && + if (impl.cache && (!response_->error || (response_->error->reason == Response::Error::Reason::NotFound))) { // Store response in database. Make sure we only refresh the expires column if the data // didn't change. @@ -357,11 +349,7 @@ void OnlineFileRequestImpl::scheduleRealRequest(OnlineFileSource::Impl& impl, bo scheduleRealRequest(impl); }; - if (util::isAssetURL(resource.url)) { - realRequest = impl.assetContext->createRequest(resource.url, callback, impl.assetRoot); - } else { - realRequest = impl.httpContext->createRequest(resource.url, callback, response); - } + realRequest = impl.httpContext->createRequest(resource.url, callback, response); }); } |