diff --git a/include/mbgl/storage/offline.hpp b/include/mbgl/storage/offline.hpp index 2c6ca05ee..fc0bf7f01 100644 --- a/include/mbgl/storage/offline.hpp +++ b/include/mbgl/storage/offline.hpp @@ -93,12 +93,20 @@ public: uint64_t completedResourceCount = 0; /** - * The cumulative size, in bytes, of all resources (inclusive of tiles) that have been fully downloaded. + * The cumulative size, in bytes, of all resources (inclusive of tiles) that have + * been fully downloaded. */ uint64_t completedResourceSize = 0; - + + /** + * The number of tiles that are known to be required for this region. This is a + * subset of `completedResourceCount`. + */ + uint64_t completedTileCount = 0; + /** * The cumulative size, in bytes, of all tiles that have been fully downloaded. + * This is a subset of `completedResourceSize`. */ uint64_t completedTileSize = 0; diff --git a/platform/default/mbgl/storage/offline_database.cpp b/platform/default/mbgl/storage/offline_database.cpp index 9bd731df7..7826d140a 100644 --- a/platform/default/mbgl/storage/offline_database.cpp +++ b/platform/default/mbgl/storage/offline_database.cpp @@ -608,33 +608,39 @@ OfflineRegionDefinition OfflineDatabase::getRegionDefinition(int64_t regionID) { OfflineRegionStatus OfflineDatabase::getRegionCompletedStatus(int64_t regionID) { OfflineRegionStatus result; - Statement stmtRes = getStatement( - "SELECT COUNT(*), SUM(size) FROM ( " - " SELECT LENGTH(data) as size " - " FROM region_resources, resources " - " WHERE region_id = ?1 " - " AND resource_id = resources.id " - ") "); - stmtRes->bind(1, regionID); - stmtRes->run(); + std::tie(result.completedResourceCount, result.completedResourceSize) + = getCompletedResourceCountAndSize(regionID); + std::tie(result.completedTileCount, result.completedTileSize) + = getCompletedTileCountAndSize(regionID); - Statement stmtTile = getStatement( - "SELECT COUNT(*), SUM(size) FROM ( " - " SELECT LENGTH(data) as size " - " FROM region_tiles, tiles " - " WHERE region_id = ?1 " - " AND tile_id = tiles.id " - ") "); - stmtTile->bind(1, regionID); - stmtTile->run(); - - result.completedTileSize = stmtTile->get(1); - result.completedResourceCount = stmtTile->get(0) + stmtRes->get(0); - result.completedResourceSize = result.completedTileSize + stmtRes->get(1); + result.completedResourceCount += result.completedTileCount; + result.completedResourceSize += result.completedTileSize; return result; } +std::pair OfflineDatabase::getCompletedResourceCountAndSize(int64_t regionID) { + Statement stmt = getStatement( + "SELECT COUNT(*), SUM(LENGTH(data)) " + "FROM region_resources, resources " + "WHERE region_id = ?1 " + "AND resource_id = resources.id "); + stmt->bind(1, regionID); + stmt->run(); + return { stmt->get(0), stmt->get(1) }; +} + +std::pair OfflineDatabase::getCompletedTileCountAndSize(int64_t regionID) { + Statement stmt = getStatement( + "SELECT COUNT(*), SUM(LENGTH(data)) " + "FROM region_tiles, tiles " + "WHERE region_id = ?1 " + "AND tile_id = tiles.id "); + stmt->bind(1, regionID); + stmt->run(); + return { stmt->get(0), stmt->get(1) }; +} + template T OfflineDatabase::getPragma(const char * sql) { Statement stmt = getStatement(sql); diff --git a/platform/default/mbgl/storage/offline_database.hpp b/platform/default/mbgl/storage/offline_database.hpp index 1e77d560d..06c44c80b 100644 --- a/platform/default/mbgl/storage/offline_database.hpp +++ b/platform/default/mbgl/storage/offline_database.hpp @@ -92,6 +92,9 @@ private: // Return value is true iff the resource was previously unused by any other regions. bool markUsed(int64_t regionID, const Resource&); + std::pair getCompletedResourceCountAndSize(int64_t regionID); + std::pair getCompletedTileCountAndSize(int64_t regionID); + const std::string path; std::unique_ptr<::mapbox::sqlite::Database> db; std::unordered_map> statements; diff --git a/test/storage/offline_database.cpp b/test/storage/offline_database.cpp index 6833a058a..0f95e927d 100644 --- a/test/storage/offline_database.cpp +++ b/test/storage/offline_database.cpp @@ -449,6 +449,40 @@ TEST(OfflineDatabase, PutFailsWhenEvictionInsuffices) { EXPECT_FALSE(bool(db.get(Resource::style("http://example.com/big")))); } +TEST(OfflineDatabase, GetRegionCompletedStatus) { + using namespace mbgl; + + OfflineDatabase db(":memory:"); + OfflineRegionDefinition definition { "http://example.com/style", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 2.0 }; + OfflineRegionMetadata metadata; + OfflineRegion region = db.createRegion(definition, metadata); + + OfflineRegionStatus status1 = db.getRegionCompletedStatus(region.getID()); + EXPECT_EQ(0, status1.completedResourceCount); + EXPECT_EQ(0, status1.completedResourceSize); + EXPECT_EQ(0, status1.completedTileCount); + EXPECT_EQ(0, status1.completedTileSize); + + Response response; + response.data = std::make_shared("data"); + + uint64_t styleSize = db.putRegionResource(region.getID(), Resource::style("http://example.com/"), response); + + OfflineRegionStatus status2 = db.getRegionCompletedStatus(region.getID()); + EXPECT_EQ(1, status2.completedResourceCount); + EXPECT_EQ(styleSize, status2.completedResourceSize); + EXPECT_EQ(0, status2.completedTileCount); + EXPECT_EQ(0, status2.completedTileSize); + + uint64_t tileSize = db.putRegionResource(region.getID(), Resource::tile("http://example.com/", 1.0, 0, 0, 0), response); + + OfflineRegionStatus status3 = db.getRegionCompletedStatus(region.getID()); + EXPECT_EQ(2, status3.completedResourceCount); + EXPECT_EQ(styleSize + tileSize, status3.completedResourceSize); + EXPECT_EQ(1, status3.completedTileCount); + EXPECT_EQ(tileSize, status3.completedTileSize); +} + TEST(OfflineDatabase, OfflineMapboxTileCount) { using namespace mbgl;