#pragma once #include #include #include #include #include #include #include #include #include #include #include namespace mapbox { namespace sqlite { class Database; class Statement; class Query; class Exception; } // namespace sqlite } // namespace mapbox namespace mbgl { class Response; class TileID; namespace util { struct IOException; } // namespace util struct MapboxTileLimitExceededException : util::Exception { MapboxTileLimitExceededException() : util::Exception("Mapbox tile limit exceeded") {} }; class OfflineDatabase { public: OfflineDatabase(std::string path); ~OfflineDatabase(); void changePath(const std::string&); std::exception_ptr resetDatabase(); optional get(const Resource&); // Return value is (inserted, stored size) std::pair put(const Resource&, const Response&); // Force Mapbox GL Native to revalidate tiles 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 tile is considered valid after the server // lookup, it will not get downloaded again. std::exception_ptr invalidateAmbientCache(); // Clear the tile 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. std::exception_ptr clearAmbientCache(); expected listRegions(); expected createRegion(const OfflineRegionDefinition&, const OfflineRegionMetadata&); expected mergeDatabase(const std::string& sideDatabasePath); expected updateMetadata(const int64_t regionID, const OfflineRegionMetadata&); std::exception_ptr deleteRegion(OfflineRegion&&); std::exception_ptr invalidateRegion(int64_t regionID); // Return value is (response, stored size) optional> getRegionResource(const Resource&); optional hasRegionResource(const Resource&); uint64_t putRegionResource(int64_t regionID, const Resource&, const Response&); void putRegionResources(int64_t regionID, const std::list>&, OfflineRegionStatus&); expected getRegionDefinition(int64_t regionID); expected getRegionCompletedStatus(int64_t regionID); std::exception_ptr setMaximumAmbientCacheSize(uint64_t); void setOfflineMapboxTileCountLimit(uint64_t); uint64_t getOfflineMapboxTileCountLimit(); bool offlineMapboxTileCountLimitExceeded(); uint64_t getOfflineMapboxTileCount(); bool exceedsOfflineMapboxTileCountLimit(const Resource&); void markUsedResources(int64_t regionID, const std::list&); std::exception_ptr pack(); void runPackDatabaseAutomatically(bool autopack_) { autopack = autopack_; } void reopenDatabaseReadOnly(bool readOnly); private: class DatabaseSizeChangeStats; void initialize(); void handleError(const mapbox::sqlite::Exception&, const char* action); void handleError(const util::IOException&, const char* action); void handleError(const std::runtime_error& ex, const char* action); void handleError(const char* action); void removeExisting(); void removeOldCacheTable(); void createSchema(); void migrateToVersion5(); void migrateToVersion3(); void migrateToVersion6(); void cleanup(); bool disabled(); void vacuum(); void checkFlags(); mapbox::sqlite::Statement& getStatement(const char *); optional> getTile(const Resource::TileData&); optional hasTile(const Resource::TileData&); bool putTile(const Resource::TileData&, const Response&, const std::string&, bool compressed); optional> getResource(const Resource&); optional hasResource(const Resource&); bool putResource(const Resource&, const Response&, const std::string&, bool compressed); uint64_t putRegionResourceInternal(int64_t regionID, const Resource&, const Response&); optional> getInternal(const Resource&); optional hasInternal(const Resource&); std::pair putInternal(const Resource&, const Response&, bool evict); // 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); std::string path; std::unique_ptr db; std::map> statements; template T getPragma(const char *); uint64_t maximumAmbientCacheSize = util::DEFAULT_MAX_CACHE_SIZE; uint64_t offlineMapboxTileCountLimit = util::mapbox::DEFAULT_OFFLINE_TILE_COUNT_LIMIT; optional offlineMapboxTileCount; bool evict(uint64_t neededFreeSize, DatabaseSizeChangeStats& stats); class DatabaseSizeChangeStats { public: explicit DatabaseSizeChangeStats(OfflineDatabase*); // Returns difference between current database size and // database size at the time of creation of this object. int64_t diff() const; // Returns how many bytes were released comparing to a database // size at the time of creation of this object. uint64_t bytesReleased() const; // Returns page size for the database. uint64_t pageSize() const; private: uint64_t pageSize_ = 0u; uint64_t pageCount_ = 0u; uint64_t initialSize_ = 0u; OfflineDatabase* db = nullptr; }; friend class DatabaseSizeChangeStats; // Lazily initializes currentAmbientCacheSize. std::exception_ptr initAmbientCacheSize(); optional currentAmbientCacheSize; void updateAmbientCacheSize(DatabaseSizeChangeStats&); bool autopack = true; bool readOnly = false; }; } // namespace mbgl