summaryrefslogtreecommitdiff
path: root/platform/default/mbgl/storage/offline_database.cpp
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-02-23 18:25:36 -0800
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-02-24 13:38:14 -0800
commit065cda83fab02aea85573d9c2d78e9121296582d (patch)
tree8fab316922a052496e67aa49d968224ffbbf0fca /platform/default/mbgl/storage/offline_database.cpp
parent5cefaeb85716b21f2bbe57165a244844114b8dbe (diff)
downloadqtlocation-mapboxgl-065cda83fab02aea85573d9c2d78e9121296582d.tar.gz
[core] Limit total number of offline Mapbox tiles
Diffstat (limited to 'platform/default/mbgl/storage/offline_database.cpp')
-rw-r--r--platform/default/mbgl/storage/offline_database.cpp114
1 files changed, 100 insertions, 14 deletions
diff --git a/platform/default/mbgl/storage/offline_database.cpp b/platform/default/mbgl/storage/offline_database.cpp
index 983b84a3b4..df3e3f4dc3 100644
--- a/platform/default/mbgl/storage/offline_database.cpp
+++ b/platform/default/mbgl/storage/offline_database.cpp
@@ -447,6 +447,9 @@ void OfflineDatabase::deleteRegion(OfflineRegion&& region) {
stmt->run();
evict(0);
+
+ // Ensure that the cached offlineTileCount value is recalculated.
+ offlineMapboxTileCount = {};
}
optional<Response> OfflineDatabase::getRegionResource(int64_t regionID, const Resource& resource) {
@@ -461,13 +464,21 @@ optional<Response> OfflineDatabase::getRegionResource(int64_t regionID, const Re
uint64_t OfflineDatabase::putRegionResource(int64_t regionID, const Resource& resource, const Response& response) {
uint64_t size = putInternal(resource, response, false).second;
- markUsed(regionID, resource);
+ bool previouslyUnused = markUsed(regionID, resource);
+
+ if (offlineMapboxTileCount
+ && resource.kind == Resource::Kind::Tile
+ && util::mapbox::isMapboxURL(resource.url)
+ && previouslyUnused) {
+ *offlineMapboxTileCount += 1;
+ }
+
return size;
}
-void OfflineDatabase::markUsed(int64_t regionID, const Resource& resource) {
+bool OfflineDatabase::markUsed(int64_t regionID, const Resource& resource) {
if (resource.kind == Resource::Kind::Tile) {
- Statement stmt = getStatement(
+ Statement insert = getStatement(
"INSERT OR IGNORE INTO region_tiles (region_id, tile_id) "
"SELECT ?1, tiles.id "
"FROM tiles "
@@ -478,23 +489,61 @@ void OfflineDatabase::markUsed(int64_t regionID, const Resource& resource) {
" AND z = ?6 ");
const Resource::TileData& tile = *resource.tileData;
- stmt->bind(1, regionID);
- stmt->bind(2, tile.urlTemplate);
- stmt->bind(3, tile.pixelRatio);
- stmt->bind(4, tile.x);
- stmt->bind(5, tile.y);
- stmt->bind(6, tile.z);
- stmt->run();
+ insert->bind(1, regionID);
+ insert->bind(2, tile.urlTemplate);
+ insert->bind(3, tile.pixelRatio);
+ insert->bind(4, tile.x);
+ insert->bind(5, tile.y);
+ insert->bind(6, tile.z);
+ insert->run();
+
+ if (db->changes() == 0) {
+ return false;
+ }
+
+ Statement select = getStatement(
+ "SELECT region_id "
+ "FROM region_tiles, tiles "
+ "WHERE region_id != ?1 "
+ " AND url_template = ?2 "
+ " AND pixel_ratio = ?3 "
+ " AND x = ?4 "
+ " AND y = ?5 "
+ " AND z = ?6 "
+ "LIMIT 1 ");
+
+ select->bind(1, regionID);
+ select->bind(2, tile.urlTemplate);
+ select->bind(3, tile.pixelRatio);
+ select->bind(4, tile.x);
+ select->bind(5, tile.y);
+ select->bind(6, tile.z);
+ return !select->run();
} else {
- Statement stmt = getStatement(
+ Statement insert = getStatement(
"INSERT OR IGNORE INTO region_resources (region_id, resource_id) "
"SELECT ?1, resources.id "
"FROM resources "
"WHERE resources.url = ?2 ");
- stmt->bind(1, regionID);
- stmt->bind(2, resource.url);
- stmt->run();
+ insert->bind(1, regionID);
+ insert->bind(2, resource.url);
+ insert->run();
+
+ if (db->changes() == 0) {
+ return false;
+ }
+
+ Statement select = getStatement(
+ "SELECT region_id "
+ "FROM region_resources, resources "
+ "WHERE region_id != ?1 "
+ " AND resources.url = ?2 "
+ "LIMIT 1 ");
+
+ select->bind(1, regionID);
+ select->bind(2, resource.url);
+ return !select->run();
}
}
@@ -591,6 +640,9 @@ bool OfflineDatabase::evict(uint64_t neededFreeSize) {
stmt2->run();
uint64_t changes2 = db->changes();
+ // The cached value of offlineTileCount does not need to be updated
+ // here because only non-offline tiles can be removed by eviction.
+
if (changes1 == 0 && changes2 == 0) {
return false;
}
@@ -599,4 +651,38 @@ bool OfflineDatabase::evict(uint64_t neededFreeSize) {
return true;
}
+void OfflineDatabase::setOfflineMapboxTileCountLimit(uint64_t limit) {
+ offlineMapboxTileCountLimit = limit;
+}
+
+uint64_t OfflineDatabase::getOfflineMapboxTileCountLimit() {
+ return offlineMapboxTileCountLimit;
+}
+
+bool OfflineDatabase::offlineMapboxTileCountLimitExceeded() {
+ return getOfflineMapboxTileCount() >= offlineMapboxTileCountLimit;
+}
+
+uint64_t OfflineDatabase::getOfflineMapboxTileCount() {
+ // Calculating this on every call would be much simpler than caching and
+ // manually updating the value, but it would make offline downloads an O(n²)
+ // operation, because the database query below involves an index scan of
+ // region_tiles.
+
+ if (offlineMapboxTileCount) {
+ return *offlineMapboxTileCount;
+ }
+
+ Statement stmt = getStatement(
+ "SELECT COUNT(DISTINCT id) "
+ "FROM region_tiles, tiles "
+ "WHERE tile_id = tiles.id "
+ "AND url_template LIKE 'mapbox://%' ");
+
+ stmt->run();
+
+ offlineMapboxTileCount = stmt->get<int64_t>(0);
+ return *offlineMapboxTileCount;
+}
+
} // namespace mbgl