From dbb8e58aea00a84716aafa6887b50c0186169f9e Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 13 Jan 2016 17:10:13 -0800 Subject: [core] Moving caching logic to DefaultFileSource This results in OnlineFileSource containing precisely the logic we want for reuse by OfflineFileSource, and no more. --- platform/default/online_file_source.cpp | 94 ++++++++++----------------------- 1 file changed, 29 insertions(+), 65 deletions(-) (limited to 'platform/default/online_file_source.cpp') diff --git a/platform/default/online_file_source.cpp b/platform/default/online_file_source.cpp index 988147a373..938c29d095 100644 --- a/platform/default/online_file_source.cpp +++ b/platform/default/online_file_source.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include @@ -45,13 +44,11 @@ public: void networkIsReachableAgain(OnlineFileSource::Impl&); private: - void scheduleCacheRequest(OnlineFileSource::Impl&); - void scheduleRealRequest(OnlineFileSource::Impl&, bool forceImmediate = false); + void schedule(OnlineFileSource::Impl&, bool forceImmediate = false); Resource resource; - std::unique_ptr cacheRequest; - HTTPRequestBase* realRequest = nullptr; - util::Timer realRequestTimer; + HTTPRequestBase* request = nullptr; + util::Timer timer; Callback callback; // Counts the number of subsequent failed requests. We're using this value for exponential @@ -64,7 +61,7 @@ class OnlineFileSource::Impl { public: using Callback = std::function; - Impl(SQLiteCache*); + Impl(int); ~Impl(); void networkIsReachableAgain(); @@ -76,15 +73,13 @@ private: friend OnlineFileRequestImpl; std::unordered_map> pending; - SQLiteCache* const cache; const std::unique_ptr httpContext; util::AsyncTask reachability; }; -OnlineFileSource::OnlineFileSource(SQLiteCache* cache) +OnlineFileSource::OnlineFileSource() : thread(std::make_unique>( - util::ThreadContext{ "OnlineFileSource", util::ThreadType::Unknown, util::ThreadPriority::Low }, - cache)) { + util::ThreadContext{ "OnlineFileSource", util::ThreadType::Unknown, util::ThreadPriority::Low }, 0)) { } OnlineFileSource::~OnlineFileSource() = default; @@ -94,31 +89,30 @@ std::unique_ptr OnlineFileSource::request(const Resource& resource, throw util::MisuseException("FileSource callback can't be empty"); } - std::string url; + Resource res = resource; switch (resource.kind) { case Resource::Kind::Style: - url = mbgl::util::mapbox::normalizeStyleURL(resource.url, accessToken); + res.url = mbgl::util::mapbox::normalizeStyleURL(resource.url, accessToken); break; case Resource::Kind::Source: - url = util::mapbox::normalizeSourceURL(resource.url, accessToken); + res.url = util::mapbox::normalizeSourceURL(resource.url, accessToken); break; case Resource::Kind::Glyphs: - url = util::mapbox::normalizeGlyphsURL(resource.url, accessToken); + res.url = util::mapbox::normalizeGlyphsURL(resource.url, accessToken); break; case Resource::Kind::SpriteImage: case Resource::Kind::SpriteJSON: - url = util::mapbox::normalizeSpriteURL(resource.url, accessToken); + res.url = util::mapbox::normalizeSpriteURL(resource.url, accessToken); break; default: - url = resource.url; + break; } - Resource res { resource.kind, url }; auto req = std::make_unique(*this); req->workRequest = thread->invokeWithCallback(&Impl::add, callback, res, req.get()); return std::move(req); @@ -130,13 +124,10 @@ void OnlineFileSource::cancel(FileRequest* req) { // ----- Impl ----- -OnlineFileSource::Impl::Impl(SQLiteCache* cache_) - : cache(cache_), - httpContext(HTTPContextBase::createContext()), +// Dummy parameter is a workaround for a gcc 4.9 bug. +OnlineFileSource::Impl::Impl(int) + : 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 - // loop alive; otherwise our app wouldn't terminate. After all, we only need status change - // notifications when our app is still running. NetworkStatus::Subscribe(&reachability); } @@ -163,39 +154,16 @@ void OnlineFileSource::Impl::cancel(FileRequest* req) { OnlineFileRequestImpl::OnlineFileRequestImpl(const Resource& resource_, Callback callback_, OnlineFileSource::Impl& impl) : resource(resource_), callback(callback_) { - if (impl.cache) { - scheduleCacheRequest(impl); - } else { - scheduleRealRequest(impl, true); - } + // Force an immediate first request if we don't have an expiration time. + schedule(impl, !resource.priorExpires); } OnlineFileRequestImpl::~OnlineFileRequestImpl() { - if (realRequest) { - realRequest->cancel(); - realRequest = nullptr; + if (request) { + request->cancel(); + request = nullptr; } - // realRequestTimer and cacheRequest are automatically canceled upon destruction. -} - -void OnlineFileRequestImpl::scheduleCacheRequest(OnlineFileSource::Impl& impl) { - // Check the cache for existing data so that we can potentially - // revalidate the information without having to redownload everything. - cacheRequest = impl.cache->get(resource, [this, &impl](std::shared_ptr response) { - cacheRequest = nullptr; - - if (response) { - resource.priorModified = response->modified; - resource.priorExpires = response->expires; - resource.priorEtag = response->etag; - callback(*response); - } - - // Force immediate revalidation if we don't have a cached response, or the cached - // response does not have an expiration time. Otherwise revalidation will happen in - // the normal scheduling flow. - scheduleRealRequest(impl, !response || !response->expires); - }); + // timer is automatically canceled upon destruction. } static Duration errorRetryTimeout(Response::Error::Reason failedRequestReason, uint32_t failedRequests) { @@ -220,8 +188,8 @@ static Duration expirationTimeout(optional expires) { } } -void OnlineFileRequestImpl::scheduleRealRequest(OnlineFileSource::Impl& impl, bool forceImmediate) { - if (realRequest) { +void OnlineFileRequestImpl::schedule(OnlineFileSource::Impl& impl, bool forceImmediate) { + if (request) { // There's already a request in progress; don't start another one. return; } @@ -237,10 +205,10 @@ void OnlineFileRequestImpl::scheduleRealRequest(OnlineFileSource::Impl& impl, bo return; } - realRequestTimer.start(timeout, Duration::zero(), [this, &impl] { - assert(!realRequest); - realRequest = impl.httpContext->createRequest(resource, [this, &impl](Response response) { - realRequest = nullptr; + timer.start(timeout, Duration::zero(), [this, &impl] { + assert(!request); + request = impl.httpContext->createRequest(resource, [this, &impl](Response response) { + request = nullptr; // If we didn't get various caching headers in the response, continue using the // previous values. Otherwise, update the previous values to the new values. @@ -263,10 +231,6 @@ void OnlineFileRequestImpl::scheduleRealRequest(OnlineFileSource::Impl& impl, bo resource.priorEtag = response.etag; } - if (impl.cache) { - impl.cache->put(resource, response); - } - if (response.error) { failedRequests++; failedRequestReason = response.error->reason; @@ -276,7 +240,7 @@ void OnlineFileRequestImpl::scheduleRealRequest(OnlineFileSource::Impl& impl, bo } callback(response); - scheduleRealRequest(impl); + schedule(impl); }); }); } @@ -285,7 +249,7 @@ void OnlineFileRequestImpl::networkIsReachableAgain(OnlineFileSource::Impl& impl // We need all requests to fail at least once before we are going to start retrying // them, and we only immediately restart request that failed due to connection issues. if (failedRequestReason == Response::Error::Reason::Connection) { - scheduleRealRequest(impl, true); + schedule(impl, true); } } -- cgit v1.2.1