Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
Expose READ_ONLY_MODE_KEY property for DatabaseFileSource
Browse files Browse the repository at this point in the history
  • Loading branch information
pozdnyakov committed Feb 6, 2020
1 parent c28ffe0 commit f505271
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 35 deletions.
6 changes: 6 additions & 0 deletions include/mbgl/storage/database_file_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@

namespace mbgl {

// Properties that may be supported by database file sources.

// Property to set database mode. When set, database opens in read-only mode; database opens in read-write-create mode otherwise.
// type: bool
constexpr const char* READ_ONLY_MODE_KEY = "read-only-mode";

class ResourceOptions;

// TODO: Split DatabaseFileSource into Ambient cache and Database interfaces.
Expand Down
4 changes: 2 additions & 2 deletions platform/default/include/mbgl/storage/offline_database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ class OfflineDatabase : private util::noncopyable {
std::exception_ptr pack();
void runPackDatabaseAutomatically(bool autopack_) { autopack = autopack_; }

// For testing only
void reopenDatabaseReadOnlyForTesting();
void reopenDatabaseReadOnly(bool readOnly);

private:
void initialize();
Expand All @@ -113,6 +112,7 @@ class OfflineDatabase : private util::noncopyable {
void cleanup();
bool disabled();
void vacuum();
void checkFlags();

mapbox::sqlite::Statement& getStatement(const char *);

Expand Down
10 changes: 2 additions & 8 deletions platform/default/src/mbgl/storage/database_file_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
#include <mbgl/util/thread.hpp>

namespace mbgl {

// For testing use only
constexpr const char* READ_ONLY_MODE_KEY = "read-only-mode";

class DatabaseFileSourceThread {
public:
DatabaseFileSourceThread(std::shared_ptr<FileSource> onlineFileSource_, std::string cachePath)
Expand Down Expand Up @@ -118,7 +114,7 @@ class DatabaseFileSourceThread {

void setOfflineMapboxTileCountLimit(uint64_t limit) { db->setOfflineMapboxTileCountLimit(limit); }

void reopenDatabaseReadOnlyForTesting() { db->reopenDatabaseReadOnlyForTesting(); }
void reopenDatabaseReadOnly(bool readOnly) { db->reopenDatabaseReadOnly(readOnly); }

private:
expected<OfflineDownload*, std::exception_ptr> getDownload(int64_t regionID) {
Expand Down Expand Up @@ -271,9 +267,7 @@ void DatabaseFileSource::setOfflineMapboxTileCountLimit(uint64_t limit) const {

void DatabaseFileSource::setProperty(const std::string& key, const mapbox::base::Value& value) {
if (key == READ_ONLY_MODE_KEY && value.getBool()) {
if (*value.getBool()) {
impl->actor().invoke(&DatabaseFileSourceThread::reopenDatabaseReadOnlyForTesting);
}
impl->actor().invoke(&DatabaseFileSourceThread::reopenDatabaseReadOnly, *value.getBool());
} else {
std::string message = "Resource provider does not support property " + key;
Log::Error(Event::General, message.c_str());
Expand Down
56 changes: 31 additions & 25 deletions platform/default/src/mbgl/storage/offline_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,15 @@ void OfflineDatabase::removeExisting() {

void OfflineDatabase::removeOldCacheTable() {
assert(db);
assert(!readOnly);
checkFlags();

db->exec("DROP TABLE IF EXISTS http_cache");
if (autopack) vacuum();
}

void OfflineDatabase::createSchema() {
assert(db);
assert(!readOnly);
checkFlags();

vacuum();
db->exec("PRAGMA journal_mode = DELETE");
Expand All @@ -183,7 +183,7 @@ void OfflineDatabase::createSchema() {

void OfflineDatabase::migrateToVersion3() {
assert(db);
assert(!readOnly);
checkFlags();

vacuum();
db->exec("PRAGMA user_version = 3");
Expand All @@ -197,7 +197,7 @@ void OfflineDatabase::migrateToVersion3() {

void OfflineDatabase::migrateToVersion5() {
assert(db);
assert(!readOnly);
checkFlags();

db->exec("PRAGMA journal_mode = DELETE");
db->exec("PRAGMA synchronous = FULL");
Expand All @@ -206,7 +206,7 @@ void OfflineDatabase::migrateToVersion5() {

void OfflineDatabase::migrateToVersion6() {
assert(db);
assert(!readOnly);
checkFlags();

mapbox::sqlite::Transaction transaction(*db);
db->exec("ALTER TABLE resources ADD COLUMN must_revalidate INTEGER NOT NULL DEFAULT 0");
Expand All @@ -217,7 +217,7 @@ void OfflineDatabase::migrateToVersion6() {

void OfflineDatabase::vacuum() {
assert(db);
assert(!readOnly);
checkFlags();

if (getPragma<int64_t>("PRAGMA auto_vacuum") != 2 /*INCREMENTAL*/) {
db->exec("PRAGMA auto_vacuum = INCREMENTAL");
Expand All @@ -227,6 +227,12 @@ void OfflineDatabase::vacuum() {
}
}

void OfflineDatabase::checkFlags() {
if (readOnly) {
throw std::runtime_error("Cannot modify database in read-only mode");
}
}

mapbox::sqlite::Statement& OfflineDatabase::getStatement(const char* sql) {
if (!db) {
initialize();
Expand Down Expand Up @@ -269,7 +275,7 @@ optional<int64_t> OfflineDatabase::hasInternal(const Resource& resource) {
}

std::pair<bool, uint64_t> OfflineDatabase::put(const Resource& resource, const Response& response) try {
assert(!readOnly);
if (readOnly) return { false, 0 };

if (!db) {
initialize();
Expand All @@ -289,7 +295,7 @@ std::pair<bool, uint64_t> OfflineDatabase::put(const Resource& resource, const R
}

std::pair<bool, uint64_t> OfflineDatabase::putInternal(const Resource& resource, const Response& response, bool evict_) {
assert(!readOnly);
checkFlags();

if (response.error) {
return { false, 0 };
Expand Down Expand Up @@ -394,7 +400,7 @@ bool OfflineDatabase::putResource(const Resource& resource,
const Response& response,
const std::string& data,
bool compressed) {
assert(!readOnly);
checkFlags();

if (response.notModified) {
// clang-format off
Expand Down Expand Up @@ -582,7 +588,7 @@ bool OfflineDatabase::putTile(const Resource::TileData& tile,
const Response& response,
const std::string& data,
bool compressed) {
assert(!readOnly);
checkFlags();

if (response.notModified) {
// clang-format off
Expand Down Expand Up @@ -684,7 +690,7 @@ bool OfflineDatabase::putTile(const Resource::TileData& tile,
}

std::exception_ptr OfflineDatabase::invalidateAmbientCache() try {
assert(!readOnly);
checkFlags();

// clang-format off
mapbox::sqlite::Query tileQuery{ getStatement(
Expand Down Expand Up @@ -717,7 +723,7 @@ std::exception_ptr OfflineDatabase::invalidateAmbientCache() try {
}

std::exception_ptr OfflineDatabase::clearAmbientCache() try {
assert(!readOnly);
checkFlags();

// clang-format off
mapbox::sqlite::Query tileQuery{ getStatement(
Expand Down Expand Up @@ -750,7 +756,7 @@ std::exception_ptr OfflineDatabase::clearAmbientCache() try {
}

std::exception_ptr OfflineDatabase::invalidateRegion(int64_t regionID) try {
assert(!readOnly);
checkFlags();

{
// clang-format off
Expand Down Expand Up @@ -814,7 +820,7 @@ expected<OfflineRegions, std::exception_ptr> OfflineDatabase::listRegions() try
expected<OfflineRegion, std::exception_ptr>
OfflineDatabase::createRegion(const OfflineRegionDefinition& definition,
const OfflineRegionMetadata& metadata) try {
assert(!readOnly);
checkFlags();

// clang-format off
mapbox::sqlite::Query query{ getStatement(
Expand All @@ -833,7 +839,7 @@ OfflineDatabase::createRegion(const OfflineRegionDefinition& definition,

expected<OfflineRegions, std::exception_ptr>
OfflineDatabase::mergeDatabase(const std::string& sideDatabasePath) {
assert(!readOnly);
checkFlags();

try {
// clang-format off
Expand Down Expand Up @@ -911,7 +917,7 @@ OfflineDatabase::mergeDatabase(const std::string& sideDatabasePath) {

expected<OfflineRegionMetadata, std::exception_ptr>
OfflineDatabase::updateMetadata(const int64_t regionID, const OfflineRegionMetadata& metadata) try {
assert(!readOnly);
checkFlags();

// clang-format off
mapbox::sqlite::Query query{ getStatement(
Expand All @@ -929,7 +935,7 @@ OfflineDatabase::updateMetadata(const int64_t regionID, const OfflineRegionMetad
}

std::exception_ptr OfflineDatabase::deleteRegion(OfflineRegion&& region) try {
assert(!readOnly);
checkFlags();

{
mapbox::sqlite::Query query{ getStatement("DELETE FROM regions WHERE id = ?") };
Expand Down Expand Up @@ -966,7 +972,7 @@ optional<int64_t> OfflineDatabase::hasRegionResource(const Resource& resource) t
uint64_t OfflineDatabase::putRegionResource(int64_t regionID,
const Resource& resource,
const Response& response) try {
assert(!readOnly);
checkFlags();

if (!db) {
initialize();
Expand All @@ -983,7 +989,7 @@ uint64_t OfflineDatabase::putRegionResource(int64_t regionID,
void OfflineDatabase::putRegionResources(int64_t regionID,
const std::list<std::tuple<Resource, Response>>& resources,
OfflineRegionStatus& status) try {
assert(!readOnly);
checkFlags();

if (!db) {
initialize();
Expand Down Expand Up @@ -1028,7 +1034,7 @@ void OfflineDatabase::putRegionResources(int64_t regionID,
}

uint64_t OfflineDatabase::putRegionResourceInternal(int64_t regionID, const Resource& resource, const Response& response) {
assert(!readOnly);
checkFlags();

uint64_t size = putInternal(resource, response, false).second;
bool previouslyUnused = markUsed(regionID, resource);
Expand All @@ -1048,7 +1054,7 @@ uint64_t OfflineDatabase::putRegionResourceInternal(int64_t regionID, const Reso
}

bool OfflineDatabase::markUsed(int64_t regionID, const Resource& resource) {
assert(!readOnly);
checkFlags();

if (resource.kind == Resource::Kind::Tile) {
// clang-format off
Expand Down Expand Up @@ -1202,7 +1208,7 @@ T OfflineDatabase::getPragma(const char* sql) {
// delete an arbitrary number of old cache entries. The free pages approach saves
// us from calling VACUUM or keeping a running total, which can be costly.
bool OfflineDatabase::evict(uint64_t neededFreeSize) {
assert(!readOnly);
checkFlags();

uint64_t pageSize = getPragma<int64_t>("PRAGMA page_size");
uint64_t pageCount = getPragma<int64_t>("PRAGMA page_count");
Expand Down Expand Up @@ -1378,11 +1384,11 @@ std::exception_ptr OfflineDatabase::resetDatabase() try {
return std::current_exception();
}

void OfflineDatabase::reopenDatabaseReadOnlyForTesting() {
readOnly = true;

void OfflineDatabase::reopenDatabaseReadOnly(bool readOnly_) {
if (readOnly == readOnly_) return;
try {
cleanup();
readOnly = readOnly_;
initialize();
} catch (...) {
handleError("reopen database read-only");
Expand Down

0 comments on commit f505271

Please sign in to comment.