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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
|
#pragma once
#include <mbgl/actor/actor_ref.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/storage/offline.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/expected.hpp>
#include <vector>
#include <mutex>
namespace mbgl {
namespace util {
template <typename T> class Thread;
} // namespace util
class ResourceTransform;
// TODO: the callback should include a potential error info when https://github.com/mapbox/mapbox-gl-native/issues/14759 is resolved
using PathChangeCallback = std::function<void ()>;
class DefaultFileSource : public FileSource {
public:
DefaultFileSource(const std::string& cachePath, const std::string& assetPath, bool supportCacheOnlyRequests = true);
DefaultFileSource(const std::string& cachePath, std::unique_ptr<FileSource>&& assetFileSource, bool supportCacheOnlyRequests = true);
~DefaultFileSource() override;
bool supportsCacheOnlyRequests() const override;
void setAPIBaseURL(const std::string&);
std::string getAPIBaseURL();
void setAccessToken(const std::string&);
std::string getAccessToken();
void setResourceTransform(optional<ActorRef<ResourceTransform>>&&);
void setResourceCachePath(const std::string&, optional<ActorRef<PathChangeCallback>>&&);
std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override;
/*
* Retrieve all regions in the offline database.
*
* The query will be executed asynchronously and the results passed to the given
* callback, which will be executed on the database thread; it is the responsibility
* of the SDK bindings to re-execute a user-provided callback on the main thread.
*/
void listOfflineRegions(std::function<void (expected<OfflineRegions, std::exception_ptr>)>);
/*
* Create an offline region in the database.
*
* When the initial database queries have completed, the provided callback will be
* executed on the database thread; it is the responsibility of the SDK bindings
* to re-execute a user-provided callback on the main thread.
*
* Note that the resulting region will be in an inactive download state; to begin
* downloading resources, call `setOfflineRegionDownloadState(OfflineRegionDownloadState::Active)`,
* optionally registering an `OfflineRegionObserver` beforehand.
*/
void createOfflineRegion(const OfflineRegionDefinition& definition,
const OfflineRegionMetadata& metadata,
std::function<void (expected<OfflineRegion, std::exception_ptr>)>);
/*
* Update an offline region metadata in the database.
*/
void updateOfflineMetadata(const int64_t regionID,
const OfflineRegionMetadata& metadata,
std::function<void (expected<OfflineRegionMetadata, std::exception_ptr>)>);
/*
* Register an observer to be notified when the state of the region changes.
*/
void setOfflineRegionObserver(OfflineRegion&, std::unique_ptr<OfflineRegionObserver>);
/*
* Pause or resume downloading of regional resources.
*/
void setOfflineRegionDownloadState(OfflineRegion&, OfflineRegionDownloadState);
/*
* Retrieve the current status of the region. The query will be executed
* asynchronously and the results passed to the given callback, which will be
* executed on the database thread; it is the responsibility of the SDK bindings
* to re-execute a user-provided callback on the main thread.
*/
void getOfflineRegionStatus(
OfflineRegion&,
std::function<void (expected<OfflineRegionStatus, std::exception_ptr>)>) const;
/*
* Merge offline regions from a secondary database into the main offline database.
*
* When the database merge is completed, the provided callback will be
* executed on the database thread; it is the responsibility of the SDK bindings
* to re-execute a user-provided callback on the main thread.
*
* The secondary database may need to be upgraded to the latest schema. This is done
* in-place and requires write-access to `sideDatabasePath`; it is the
* responsibility of the SDK bindings to ensure that this path is writeable.
*
* Only resources and tiles that belong to a region will be copied over. Identical
* regions will be flattened into a single new region in the main database.
*
* Invokes the callback with a `MapboxOfflineTileCountExceededException` error if
* the merge operation would result in the offline tile count limit being exceeded.
*
* Merged regions may not be in a completed status if the secondary database
* does not contain all the tiles or resources required by the region definition.
*/
void mergeOfflineRegions(const std::string& sideDatabasePath,
std::function<void (expected<OfflineRegions, std::exception_ptr>)>);
/*
* Remove an offline region from the database and perform any resources evictions
* necessary as a result.
*
* Eviction works by removing the least-recently requested resources not also required
* by other regions, until the database shrinks below a certain size.
*
* Note that this method takes ownership of the input, reflecting the fact that once
* region deletion is initiated, it is not legal to perform further actions with the
* region.
*
* When the operation is complete or encounters an error, the given callback will be
* executed on the database thread; it is the responsibility of the SDK bindings
* to re-execute a user-provided callback on the main thread.
*/
void deleteOfflineRegion(OfflineRegion&&, std::function<void (std::exception_ptr)>);
/*
* Invalidate all the tiles from an offline region forcing Mapbox GL to revalidate
* the tiles with the server before using. This is more efficient than deleting the
* offline region and downloading it again because if the data on the cache matches
* the server, no new data gets transmitted.
*/
void invalidateOfflineRegion(OfflineRegion&, std::function<void (std::exception_ptr)>);
/*
* Changing or bypassing this limit without permission from Mapbox is prohibited
* by the Mapbox Terms of Service.
*/
void setOfflineMapboxTileCountLimit(uint64_t) const;
/*
* Pause file request activity.
*
* If pause is called then no revalidation or network request activity
* will occur.
*/
void pause();
/*
* Resume file request activity.
*
* Calling resume will unpause the file source and process any tasks that
* expired while the file source was paused.
*/
void resume();
/*
* Insert the provided resource into the ambient cache
*
* Consumers of the resource will expect the uncompressed version; the
* OfflineDatabase will determine whether to compress the data on disk.
* This call is asynchronous: the data may not be immediately available
* for in-progress requests, although subsequent requests should have
* access to the cached data.
*/
void put(const Resource&, const Response&);
/*
* Delete existing database and re-initialize.
*
* When the operation is complete or encounters an error, the given callback will be
* executed on the database thread; it is the responsibility of the SDK bindings
* to re-execute a user-provided callback on the main thread.
*/
void resetDatabase(std::function<void (std::exception_ptr)>);
/*
* Forces revalidation of the ambient cache.
*
* Forces Mapbox GL Native to revalidate resources stored in the ambient
* cache with the tile server before using them, making sure they
* are the latest version. This is more efficient than cleaning the
* cache because if the resource is considered valid after the server
* lookup, it will not get downloaded again.
*
* Resources overlapping with offline regions will not be affected
* by this call.
*/
void invalidateAmbientCache(std::function<void (std::exception_ptr)>);
/*
* Erase resources from the ambient cache, freeing storage space.
*
* Erases the ambient cache, freeing resources. This operation can be
* potentially slow because it will trigger a VACUUM on SQLite,
* forcing the database to move pages on the filesystem.
*
* Resources overlapping with offline regions will not be affected
* by this call.
*/
void clearAmbientCache(std::function<void (std::exception_ptr)>);
/*
* Sets the maximum size in bytes for the ambient cache.
*
* This call is potentially expensive because it will try
* to trim the data in case the database is larger than the
* size defined. The size of offline regions are not affected
* by this settings, but the ambient cache will always try
* to not exceed the maximum size defined, taking into account
* the current size for the offline regions.
*
* If the maximum size is set to 50 MB and 40 MB are already
* used by offline regions, the cache size will be effectively
* 10 MB.
*
* Setting the size to 0 will disable the cache if there is no
* offline region on the database.
*
* This method should always be called before using the database,
* otherwise the default maximum size will be used.
*/
void setMaximumAmbientCacheSize(uint64_t size, std::function<void (std::exception_ptr)> callback);
// For testing only.
void setOnlineStatus(bool);
class Impl;
private:
// Shared so destruction is done on this thread
const std::shared_ptr<FileSource> assetFileSource;
const std::unique_ptr<util::Thread<Impl>> impl;
std::mutex cachedBaseURLMutex;
std::string cachedBaseURL = mbgl::util::API_BASE_URL;
std::mutex cachedAccessTokenMutex;
std::string cachedAccessToken;
const bool supportCacheOnlyRequests;
};
} // namespace mbgl
|