summaryrefslogtreecommitdiff
path: root/src/mbgl/storage/default_file_source_impl.hpp
blob: e2136b49fd36b457680e2e6f20815f136be33934 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#ifndef MBGL_STORAGE_DEFAULT_DEFAULT_FILE_SOURCE_IMPL
#define MBGL_STORAGE_DEFAULT_DEFAULT_FILE_SOURCE_IMPL

#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/asset_context_base.hpp>
#include <mbgl/storage/http_context_base.hpp>
#include <mbgl/util/async_task.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/timer.hpp>

#include <set>
#include <unordered_map>

namespace mbgl {

class RequestBase;

class DefaultFileRequest : public FileRequest {
public:
    DefaultFileRequest(const Resource& resource_,
                       DefaultFileSource& fileSource_)
        : resource(resource_),
          fileSource(fileSource_) {
    }

    ~DefaultFileRequest() {
        fileSource.cancel(resource, this);
    }

    Resource resource;
    DefaultFileSource& fileSource;

    std::unique_ptr<WorkRequest> workRequest;
};

class DefaultFileRequestImpl : public util::noncopyable {
public:
    using Callback = std::function<void (Response)>;

    const Resource resource;
    std::unique_ptr<WorkRequest> cacheRequest;
    RequestBase* realRequest = nullptr;
    std::unique_ptr<util::Timer> timerRequest;

    inline DefaultFileRequestImpl(const Resource& resource_)
        : resource(resource_) {}

    ~DefaultFileRequestImpl();

    // Observer accessors.
    void addObserver(FileRequest*, Callback);
    void removeObserver(FileRequest*);
    bool hasObservers() const;

    // Updates/gets the response of this request object.
    void setResponse(const std::shared_ptr<const Response>&);
    const std::shared_ptr<const Response>& getResponse() const;

    // Returns the seconds we have to wait until we need to redo this request. A value of 0
    // means that we need to redo it immediately, and a negative value means that we're not setting
    // a timeout at all.
    Seconds getRetryTimeout() const;

    // Checks the currently stored response and replaces it with an idential one, except with the
    // stale flag set, if the response is expired.
    void checkResponseFreshness();

    // Notifies all observers.
    void notify();


private:
    // Stores a set of all observing Request objects.
    std::unordered_map<FileRequest*, Callback> observers;

    // The current response data. We're storing it because we can satisfy requests for the same
    // resource directly by returning this response object. We also need it to create conditional
    // HTTP requests, and to check whether new responses we got changed any data.
    std::shared_ptr<const Response> response;

    // Counts the number of subsequent failed requests. We're using this value for exponential
    // backoff when retrying requests.
    int failedRequests = 0;
};

class DefaultFileSource::Impl {
public:
    using Callback = std::function<void (Response)>;

    Impl(FileCache*, const std::string& = "");
    ~Impl();

    void networkIsReachableAgain();

    void add(Resource, FileRequest*, Callback);
    void cancel(Resource, FileRequest*);

private:
    void update(DefaultFileRequestImpl&);
    void startCacheRequest(DefaultFileRequestImpl&);
    void startRealRequest(DefaultFileRequestImpl&);
    void reschedule(DefaultFileRequestImpl&);

    std::unordered_map<Resource, std::unique_ptr<DefaultFileRequestImpl>, 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;
};

}

#endif