WIP: use expected<T, E> for passing on errors

This commit is contained in:
Konstantin Käfer
2018-08-13 16:29:14 -07:00
parent 89515de769
commit 6e06e55b95
19 changed files with 157 additions and 171 deletions

View File

@@ -176,8 +176,10 @@ if(WITH_NODEJS AND COMMAND mbgl_platform_node)
endif()
if(CMAKE_GENERATOR STREQUAL "Xcode")
write_xcconfig_target_properties(
mbgl-core
mbgl-filesource
set_xcconfig_target_properties(mbgl-core)
set_xcconfig_target_properties(mbgl-filesource)
file(GENERATE
OUTPUT "${CMAKE_BINARY_DIR}/config.xcconfig"
INPUT "${CMAKE_SOURCE_DIR}/scripts/config.xcconfig.in"
)
endif()

View File

@@ -136,9 +136,9 @@ int main(int argc, char *argv[]) {
std::signal(SIGINT, [] (int) { stop(); });
fileSource.createOfflineRegion(definition, metadata, [&] (std::exception_ptr error, optional<OfflineRegion> region_) {
if (error) {
std::cerr << "Error creating region: " << util::toString(error) << std::endl;
fileSource.createOfflineRegion(definition, metadata, [&] (mbgl::expected<OfflineRegion, std::exception_ptr> region_) {
if (!region_) {
std::cerr << "Error creating region: " << util::toString(region_.error()) << std::endl;
loop.stop();
exit(1);
} else {

View File

@@ -664,6 +664,7 @@ set(MBGL_CORE_FILES
include/mbgl/util/enum.hpp
include/mbgl/util/event.hpp
include/mbgl/util/exception.hpp
include/mbgl/util/expected.hpp
include/mbgl/util/feature.hpp
include/mbgl/util/font_stack.hpp
include/mbgl/util/geo.hpp

View File

@@ -1,3 +1,5 @@
add_vendor_target(expected INTERFACE)
add_library(mbgl-filesource STATIC
# File source
include/mbgl/storage/default_file_source.hpp
@@ -39,6 +41,7 @@ target_include_directories(mbgl-filesource
target_link_libraries(mbgl-filesource
PUBLIC mbgl-core
PUBLIC expected
)
mbgl_filesource()

View File

@@ -115,13 +115,15 @@ endfunction()
# Creates a library target for a vendored dependency
function(add_vendor_target NAME TYPE)
add_library(${NAME} ${TYPE} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/empty.cpp")
set(INCLUDE_TYPE "INTERFACE")
set(SOURCE_TYPE "INTERFACE")
if (TYPE STREQUAL "STATIC" OR TYPE STREQUAL "SHARED")
add_library(${NAME} ${TYPE} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/empty.cpp")
set(INCLUDE_TYPE "PUBLIC")
set(SOURCE_TYPE "PRIVATE")
set_target_properties(${NAME} PROPERTIES SOURCES "")
else()
add_library(${NAME} ${TYPE})
endif()
set_target_properties(${NAME} PROPERTIES INTERFACE_SOURCES "")
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/vendor/${NAME}/files.txt" FILES)
@@ -137,48 +139,25 @@ macro(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
endmacro (set_xcode_property)
function(_get_xcconfig_property target var)
get_property(result TARGET ${target} PROPERTY INTERFACE_${var} SET)
if (result)
get_property(result TARGET ${target} PROPERTY INTERFACE_${var})
if (var STREQUAL "LINK_LIBRARIES")
# Remove target names from the list of linker flags, since Xcode can't deal with them.
set(link_flags)
foreach(item IN LISTS result)
if (NOT TARGET ${item})
list(APPEND link_flags ${item})
endif()
endforeach()
set(result "${link_flags}")
function(set_xcconfig_target_properties target)
# Create a list of linked libraries for use in the xcconfig generation script.
get_property(result TARGET ${target} PROPERTY INTERFACE_LINK_LIBRARIES)
string(GENEX_STRIP "${result}" result)
# Remove target names from the list of linker flags, since Xcode can't deal with them.
set(link_flags)
foreach(item IN LISTS result)
if (NOT TARGET ${item})
list(APPEND link_flags ${item})
endif()
string(REPLACE ";-framework " ";-framework;" result "${result}")
string(REPLACE ";" "\" \"" result "${result}")
string(REPLACE "-" "_" target "${target}")
set(${target}_${var} "${result}" PARENT_SCOPE)
endif()
endfunction()
if(MBGL_PLATFORM STREQUAL "ios")
execute_process(
COMMAND git submodule update --init platform/ios/vendor/mapbox-events-ios
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
endif()
function(write_xcconfig_target_properties)
foreach(target ${ARGN})
_get_xcconfig_property(${target} INCLUDE_DIRECTORIES)
_get_xcconfig_property(${target} LINK_LIBRARIES)
endforeach()
configure_file(
"${CMAKE_SOURCE_DIR}/scripts/config.xcconfig.in"
"${CMAKE_BINARY_DIR}/config.xcconfig"
@ONLY
)
string(REPLACE ";-framework " ";-framework;" link_flags "${link_flags}")
string(REPLACE ";" "\" \"" link_flags "${link_flags}")
set_xcode_property(${target} XCCONFIG_LINK_LIBRARIES "${link_flags}")
endfunction()
# Set Xcode project build settings to be consistent with the CXX flags we're
# using. (Otherwise, Xcode's defaults may override some of these.)
macro(initialize_xcode_cxx_build_settings target)
function(initialize_xcode_cxx_build_settings target)
# -Wall
set_xcode_property(${target} GCC_WARN_SIGN_COMPARE YES)
set_xcode_property(${target} GCC_WARN_UNINITIALIZED_AUTOS YES)
@@ -206,7 +185,7 @@ macro(initialize_xcode_cxx_build_settings target)
# -flto
set_xcode_property(${target} LLVM_LTO $<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebugInfo>>:YES>)
endmacro(initialize_xcode_cxx_build_settings)
endfunction()
# CMake 3.1 does not have this yet.
set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std=c++14")

View File

@@ -5,6 +5,7 @@
#include <mbgl/storage/offline.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/expected.hpp>
#include <vector>
#include <mutex>
@@ -55,8 +56,7 @@ public:
* 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 (std::exception_ptr,
optional<std::vector<OfflineRegion>>)>);
void listOfflineRegions(std::function<void (expected<OfflineRegions, std::exception_ptr>)>);
/*
* Create an offline region in the database.
@@ -71,16 +71,14 @@ public:
*/
void createOfflineRegion(const OfflineRegionDefinition& definition,
const OfflineRegionMetadata& metadata,
std::function<void (std::exception_ptr,
optional<OfflineRegion>)>);
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 (std::exception_ptr,
optional<OfflineRegionMetadata>)>);
std::function<void (expected<OfflineRegionMetadata, std::exception_ptr>)>);
/*
* Register an observer to be notified when the state of the region changes.
*/
@@ -97,8 +95,9 @@ public:
* 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 (std::exception_ptr,
optional<OfflineRegionStatus>)>) const;
void getOfflineRegionStatus(
OfflineRegion&,
std::function<void (expected<OfflineRegionStatus, std::exception_ptr>)>) const;
/*
* Remove an offline region from the database and perform any resources evictions

View File

@@ -210,4 +210,6 @@ private:
const OfflineRegionMetadata metadata;
};
using OfflineRegions = std::vector<OfflineRegion>;
} // namespace mbgl

View File

@@ -97,6 +97,7 @@ macro(mbgl_platform_core)
target_link_libraries(mbgl-core
PRIVATE nunicode
PUBLIC expected
PUBLIC -llog
PUBLIC -landroid
PUBLIC -ljnigraphics

View File

@@ -26,15 +26,18 @@ void OfflineManager::listOfflineRegions(jni::JNIEnv& env_, jni::Object<FileSourc
//Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile
callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()),
jFileSource = std::shared_ptr<jni::jobject>(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter())
](std::exception_ptr error, mbgl::optional<std::vector<mbgl::OfflineRegion>> regions) mutable {
](mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> regions) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
if (error) {
OfflineManager::ListOfflineRegionsCallback::onError(*env, jni::Object<ListOfflineRegionsCallback>(*callback), error);
} else if (regions) {
OfflineManager::ListOfflineRegionsCallback::onList(*env, jni::Object<FileSource>(*jFileSource), jni::Object<ListOfflineRegionsCallback>(*callback), std::move(regions));
if (regions) {
OfflineManager::ListOfflineRegionsCallback::onList(
*env, jni::Object<FileSource>(*jFileSource),
jni::Object<ListOfflineRegionsCallback>(*callback), std::move(*regions));
} else {
OfflineManager::ListOfflineRegionsCallback::onError(
*env, jni::Object<ListOfflineRegionsCallback>(*callback), regions.error());
}
});
}
@@ -59,19 +62,19 @@ void OfflineManager::createOfflineRegion(jni::JNIEnv& env_,
//Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile
callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()),
jFileSource = std::shared_ptr<jni::jobject>(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter())
](std::exception_ptr error, mbgl::optional<mbgl::OfflineRegion> region) mutable {
](mbgl::expected<mbgl::OfflineRegion, std::exception_ptr> region) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
if (error) {
OfflineManager::CreateOfflineRegionCallback::onError(*env, jni::Object<CreateOfflineRegionCallback>(*callback), error);
} else if (region) {
if (region) {
OfflineManager::CreateOfflineRegionCallback::onCreate(
*env,
jni::Object<FileSource>(*jFileSource),
jni::Object<CreateOfflineRegionCallback>(*callback), std::move(region)
jni::Object<CreateOfflineRegionCallback>(*callback), std::move(*region)
);
} else {
OfflineManager::CreateOfflineRegionCallback::onError(*env, jni::Object<CreateOfflineRegionCallback>(*callback), region.error());
}
});
}

View File

@@ -107,14 +107,14 @@ void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, jni::Object<Offlin
fileSource.getOfflineRegionStatus(*region, [
//Ensure the object is not gc'd in the meanwhile
callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter())
](std::exception_ptr error, mbgl::optional<mbgl::OfflineRegionStatus> status) mutable {
](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> status) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
if (error) {
OfflineRegionStatusCallback::onError(*env, jni::Object<OfflineRegionStatusCallback>(*callback), error);
} else if (status) {
OfflineRegionStatusCallback::onStatus(*env, jni::Object<OfflineRegionStatusCallback>(*callback), std::move(status));
if (status) {
OfflineRegionStatusCallback::onStatus(*env, jni::Object<OfflineRegionStatusCallback>(*callback), std::move(*status));
} else {
OfflineRegionStatusCallback::onError(*env, jni::Object<OfflineRegionStatusCallback>(*callback), status.error());
}
});
}
@@ -144,14 +144,14 @@ void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, jni::Array<jn
fileSource.updateOfflineMetadata(region->getID(), metadata, [
//Ensure the object is not gc'd in the meanwhile
callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter())
](std::exception_ptr error, mbgl::optional<mbgl::OfflineRegionMetadata> data) mutable {
](mbgl::expected<mbgl::OfflineRegionMetadata, std::exception_ptr> data) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
if (error) {
OfflineRegionUpdateMetadataCallback::onError(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), error);
} else if (data) {
OfflineRegionUpdateMetadataCallback::onUpdate(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), std::move(data));
if (data) {
OfflineRegionUpdateMetadataCallback::onUpdate(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), std::move(*data));
} else {
OfflineRegionUpdateMetadataCallback::onError(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), data.error());
}
});
}

View File

@@ -141,7 +141,7 @@ private:
mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource];
__weak MGLOfflinePack *weakSelf = self;
mbglFileSource->getOfflineRegionStatus(*_mbglOfflineRegion, [&, weakSelf](__unused std::exception_ptr exception, mbgl::optional<mbgl::OfflineRegionStatus> status) {
mbglFileSource->getOfflineRegionStatus(*_mbglOfflineRegion, [&, weakSelf](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> status) {
if (status) {
mbgl::OfflineRegionStatus checkedStatus = *status;
dispatch_async(dispatch_get_main_queue(), ^{

View File

@@ -288,16 +288,16 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
const mbgl::OfflineTilePyramidRegionDefinition regionDefinition = [(id <MGLOfflineRegion_Private>)region offlineRegionDefinition];
mbgl::OfflineRegionMetadata metadata(context.length);
[context getBytes:&metadata[0] length:metadata.size()];
self.mbglFileSource->createOfflineRegion(regionDefinition, metadata, [&, completion](std::exception_ptr exception, mbgl::optional<mbgl::OfflineRegion> mbglOfflineRegion) {
self.mbglFileSource->createOfflineRegion(regionDefinition, metadata, [&, completion](mbgl::expected<mbgl::OfflineRegion, std::exception_ptr> mbglOfflineRegion) {
NSError *error;
if (exception) {
NSString *errorDescription = @(mbgl::util::toString(exception).c_str());
if (!mbglOfflineRegion) {
NSString *errorDescription = @(mbgl::util::toString(mbglOfflineRegion.error()).c_str());
error = [NSError errorWithDomain:MGLErrorDomain code:-1 userInfo:errorDescription ? @{
NSLocalizedDescriptionKey: errorDescription,
} : nil];
}
if (completion) {
MGLOfflinePack *pack = mbglOfflineRegion ? [[MGLOfflinePack alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(*mbglOfflineRegion))] : nil;
MGLOfflinePack *pack = mbglOfflineRegion ? [[MGLOfflinePack alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(mbglOfflineRegion.value()))] : nil;
dispatch_async(dispatch_get_main_queue(), [&, completion, error, pack](void) {
completion(pack, error);
});
@@ -347,17 +347,17 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
}
- (void)getPacksWithCompletionHandler:(void (^)(NSArray<MGLOfflinePack *> *packs, NSError * _Nullable error))completion {
self.mbglFileSource->listOfflineRegions([&, completion](std::exception_ptr exception, mbgl::optional<std::vector<mbgl::OfflineRegion>> regions) {
self.mbglFileSource->listOfflineRegions([&, completion](mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> result) {
NSError *error;
if (exception) {
error = [NSError errorWithDomain:MGLErrorDomain code:-1 userInfo:@{
NSLocalizedDescriptionKey: @(mbgl::util::toString(exception).c_str()),
}];
}
NSMutableArray *packs;
if (regions) {
packs = [NSMutableArray arrayWithCapacity:regions->size()];
for (mbgl::OfflineRegion &region : *regions) {
if (!result) {
error = [NSError errorWithDomain:MGLErrorDomain code:-1 userInfo:@{
NSLocalizedDescriptionKey: @(mbgl::util::toString(result.error()).c_str()),
}];
} else {
auto& regions = result.value();
packs = [NSMutableArray arrayWithCapacity:regions.size()];
for (auto &region : regions) {
MGLOfflinePack *pack = [[MGLOfflinePack alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(region))];
[packs addObject:pack];
}

View File

@@ -45,61 +45,44 @@ public:
onlineFileSource.setResourceTransform(std::move(transform));
}
void listRegions(std::function<void (std::exception_ptr, optional<std::vector<OfflineRegion>>)> callback) {
try {
callback({}, offlineDatabase->listRegions());
} catch (...) {
callback(std::current_exception(), {});
}
void listRegions(std::function<void (expected<OfflineRegions, std::exception_ptr>)> callback) {
callback(offlineDatabase->listRegions());
}
void createRegion(const OfflineRegionDefinition& definition,
const OfflineRegionMetadata& metadata,
std::function<void (std::exception_ptr, optional<OfflineRegion>)> callback) {
try {
callback({}, offlineDatabase->createRegion(definition, metadata));
} catch (...) {
callback(std::current_exception(), {});
}
std::function<void (expected<OfflineRegion, std::exception_ptr>)> callback) {
callback(offlineDatabase->createRegion(definition, metadata));
}
void updateMetadata(const int64_t regionID,
const OfflineRegionMetadata& metadata,
std::function<void (std::exception_ptr, optional<OfflineRegionMetadata>)> callback) {
try {
callback({}, offlineDatabase->updateMetadata(regionID, metadata));
} catch (...) {
callback(std::current_exception(), {});
}
std::function<void (expected<OfflineRegionMetadata, std::exception_ptr>)> callback) {
callback(offlineDatabase->updateMetadata(regionID, metadata));
}
void getRegionStatus(int64_t regionID, std::function<void (std::exception_ptr, optional<OfflineRegionStatus>)> callback) {
void getRegionStatus(int64_t regionID, std::function<void (expected<OfflineRegionStatus, std::exception_ptr>)> callback) {
if (auto download = getDownload(regionID)) {
callback({}, download->getStatus());
callback(download.value()->getStatus());
} else {
callback(std::current_exception(), {});
callback(unexpected<std::exception_ptr>(download.error()));
}
}
void deleteRegion(OfflineRegion&& region, std::function<void (std::exception_ptr)> callback) {
try {
downloads.erase(region.getID());
offlineDatabase->deleteRegion(std::move(region));
callback({});
} catch (...) {
callback(std::current_exception());
}
downloads.erase(region.getID());
callback(offlineDatabase->deleteRegion(std::move(region)));
}
void setRegionObserver(int64_t regionID, std::unique_ptr<OfflineRegionObserver> observer) {
if (auto download = getDownload(regionID)) {
download->setObserver(std::move(observer));
download.value()->setObserver(std::move(observer));
}
}
void setRegionDownloadState(int64_t regionID, OfflineRegionDownloadState state) {
if (auto download = getDownload(regionID)) {
download->setState(state);
download.value()->setState(state);
}
}
@@ -185,17 +168,16 @@ public:
}
private:
OfflineDownload* getDownload(int64_t regionID) {
expected<OfflineDownload*, std::exception_ptr> getDownload(int64_t regionID) {
auto it = downloads.find(regionID);
if (it != downloads.end()) {
return it->second.get();
}
auto definition = offlineDatabase->getRegionDefinition(regionID);
if (!definition) {
return nullptr;
return unexpected<std::exception_ptr>(definition.error());
}
auto download = std::make_unique<OfflineDownload>(regionID, std::move(*definition),
auto download = std::make_unique<OfflineDownload>(regionID, std::move(definition.value()),
*offlineDatabase, onlineFileSource);
return downloads.emplace(regionID, std::move(download)).first->second.get();
}
@@ -266,19 +248,19 @@ std::unique_ptr<AsyncRequest> DefaultFileSource::request(const Resource& resourc
return std::move(req);
}
void DefaultFileSource::listOfflineRegions(std::function<void (std::exception_ptr, optional<std::vector<OfflineRegion>>)> callback) {
void DefaultFileSource::listOfflineRegions(std::function<void (expected<OfflineRegions, std::exception_ptr>)> callback) {
impl->actor().invoke(&Impl::listRegions, callback);
}
void DefaultFileSource::createOfflineRegion(const OfflineRegionDefinition& definition,
const OfflineRegionMetadata& metadata,
std::function<void (std::exception_ptr, optional<OfflineRegion>)> callback) {
std::function<void (expected<OfflineRegion, std::exception_ptr>)> callback) {
impl->actor().invoke(&Impl::createRegion, definition, metadata, callback);
}
void DefaultFileSource::updateOfflineMetadata(const int64_t regionID,
const OfflineRegionMetadata& metadata,
std::function<void (std::exception_ptr, optional<OfflineRegionMetadata>)> callback) {
std::function<void (expected<OfflineRegionMetadata, std::exception_ptr>)> callback) {
impl->actor().invoke(&Impl::updateMetadata, regionID, metadata, callback);
}
@@ -294,7 +276,7 @@ void DefaultFileSource::setOfflineRegionDownloadState(OfflineRegion& region, Off
impl->actor().invoke(&Impl::setRegionDownloadState, region.getID(), state);
}
void DefaultFileSource::getOfflineRegionStatus(OfflineRegion& region, std::function<void (std::exception_ptr, optional<OfflineRegionStatus>)> callback) const {
void DefaultFileSource::getOfflineRegionStatus(OfflineRegion& region, std::function<void (expected<OfflineRegionStatus, std::exception_ptr>)> callback) const {
impl->actor().invoke(&Impl::getRegionStatus, region.getID(), callback);
}

View File

@@ -592,14 +592,15 @@ bool OfflineDatabase::putTile(const Resource::TileData& tile,
return true;
}
std::vector<OfflineRegion> OfflineDatabase::listRegions() try {
expected<OfflineRegions, std::exception_ptr> OfflineDatabase::listRegions() try {
mapbox::sqlite::Query query{ getStatement("SELECT id, definition, description FROM regions") };
std::vector<OfflineRegion> result;
OfflineRegions result;
while (query.run()) {
const auto id = query.get<int64_t>(0);
const auto definition = query.get<std::string>(1);
const auto description = query.get<std::vector<uint8_t>>(2);
try {
// Construct, then move because this constructor is private.
OfflineRegion region(id, decodeOfflineRegionDefinition(definition), description);
result.emplace_back(std::move(region));
} catch (const std::exception& ex) {
@@ -608,14 +609,16 @@ std::vector<OfflineRegion> OfflineDatabase::listRegions() try {
Log::Error(Event::General, "%s", ex.what());
}
}
return result;
// Explicit move to avoid triggering the copy constructor.
return { std::move(result) };
} catch (const mapbox::sqlite::Exception& ex) {
handleError(ex, "list regions");
return {};
return unexpected<std::exception_ptr>(std::current_exception());
}
optional<OfflineRegion> OfflineDatabase::createRegion(const OfflineRegionDefinition& definition,
const OfflineRegionMetadata& metadata) try {
expected<OfflineRegion, std::exception_ptr>
OfflineDatabase::createRegion(const OfflineRegionDefinition& definition,
const OfflineRegionMetadata& metadata) try {
// clang-format off
mapbox::sqlite::Query query{ getStatement(
"INSERT INTO regions (definition, description) "
@@ -628,10 +631,11 @@ optional<OfflineRegion> OfflineDatabase::createRegion(const OfflineRegionDefinit
return OfflineRegion(query.lastInsertRowId(), definition, metadata);
} catch (const mapbox::sqlite::Exception& ex) {
handleError(ex, "create region");
return nullopt;
return unexpected<std::exception_ptr>(std::current_exception());
}
optional<OfflineRegionMetadata> OfflineDatabase::updateMetadata(const int64_t regionID, const OfflineRegionMetadata& metadata) try {
expected<OfflineRegionMetadata, std::exception_ptr>
OfflineDatabase::updateMetadata(const int64_t regionID, const OfflineRegionMetadata& metadata) try {
// clang-format off
mapbox::sqlite::Query query{ getStatement(
"UPDATE regions SET description = ?1 "
@@ -644,10 +648,10 @@ optional<OfflineRegionMetadata> OfflineDatabase::updateMetadata(const int64_t re
return metadata;
} catch (const mapbox::sqlite::Exception& ex) {
handleError(ex, "update region metadata");
return nullopt;
return unexpected<std::exception_ptr>(std::current_exception());
}
void OfflineDatabase::deleteRegion(OfflineRegion&& region) try {
std::exception_ptr OfflineDatabase::deleteRegion(OfflineRegion&& region) try {
{
mapbox::sqlite::Query query{ getStatement("DELETE FROM regions WHERE id = ?") };
query.bind(1, region.getID());
@@ -660,9 +664,10 @@ void OfflineDatabase::deleteRegion(OfflineRegion&& region) try {
// Ensure that the cached offlineTileCount value is recalculated.
offlineMapboxTileCount = {};
return nullptr;
} catch (const mapbox::sqlite::Exception& ex) {
handleError(ex, "delete region");
return;
return std::current_exception();
}
optional<std::pair<Response, uint64_t>> OfflineDatabase::getRegionResource(int64_t regionID, const Resource& resource) try {
@@ -848,7 +853,7 @@ bool OfflineDatabase::markUsed(int64_t regionID, const Resource& resource) {
}
}
optional<OfflineRegionDefinition> OfflineDatabase::getRegionDefinition(int64_t regionID) try {
expected<OfflineRegionDefinition, std::exception_ptr> OfflineDatabase::getRegionDefinition(int64_t regionID) try {
mapbox::sqlite::Query query{ getStatement("SELECT definition FROM regions WHERE id = ?1") };
query.bind(1, regionID);
query.run();
@@ -856,10 +861,10 @@ optional<OfflineRegionDefinition> OfflineDatabase::getRegionDefinition(int64_t r
return decodeOfflineRegionDefinition(query.get<std::string>(0));
} catch (const mapbox::sqlite::Exception& ex) {
handleError(ex, "load region");
return nullopt;
return unexpected<std::exception_ptr>(std::current_exception());
}
optional<OfflineRegionStatus> OfflineDatabase::getRegionCompletedStatus(int64_t regionID) try {
expected<OfflineRegionStatus, std::exception_ptr> OfflineDatabase::getRegionCompletedStatus(int64_t regionID) try {
OfflineRegionStatus result;
std::tie(result.completedResourceCount, result.completedResourceSize)
@@ -873,7 +878,7 @@ optional<OfflineRegionStatus> OfflineDatabase::getRegionCompletedStatus(int64_t
return result;
} catch (const mapbox::sqlite::Exception& ex) {
handleError(ex, "get region status");
return nullopt;
return unexpected<std::exception_ptr>(std::current_exception());
}
std::pair<int64_t, int64_t> OfflineDatabase::getCompletedResourceCountAndSize(int64_t regionID) {

View File

@@ -7,6 +7,7 @@
#include <mbgl/util/optional.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/mapbox.hpp>
#include <mbgl/util/expected.hpp>
#include <unordered_map>
#include <memory>
@@ -47,14 +48,15 @@ public:
// Return value is (inserted, stored size)
std::pair<bool, uint64_t> put(const Resource&, const Response&);
std::vector<OfflineRegion> listRegions();
expected<OfflineRegions, std::exception_ptr> listRegions();
optional<OfflineRegion> createRegion(const OfflineRegionDefinition&,
const OfflineRegionMetadata&);
expected<OfflineRegion, std::exception_ptr> createRegion(const OfflineRegionDefinition&,
const OfflineRegionMetadata&);
optional<OfflineRegionMetadata> updateMetadata(const int64_t regionID, const OfflineRegionMetadata&);
expected<OfflineRegionMetadata, std::exception_ptr>
updateMetadata(const int64_t regionID, const OfflineRegionMetadata&);
void deleteRegion(OfflineRegion&&);
std::exception_ptr deleteRegion(OfflineRegion&&);
// Return value is (response, stored size)
optional<std::pair<Response, uint64_t>> getRegionResource(int64_t regionID, const Resource&);
@@ -62,8 +64,8 @@ public:
uint64_t putRegionResource(int64_t regionID, const Resource&, const Response&);
void putRegionResources(int64_t regionID, const std::list<std::tuple<Resource, Response>>&, OfflineRegionStatus&);
optional<OfflineRegionDefinition> getRegionDefinition(int64_t regionID);
optional<OfflineRegionStatus> getRegionCompletedStatus(int64_t regionID);
expected<OfflineRegionDefinition, std::exception_ptr> getRegionDefinition(int64_t regionID);
expected<OfflineRegionStatus, std::exception_ptr> getRegionCompletedStatus(int64_t regionID);
void setOfflineMapboxTileCountLimit(uint64_t);
uint64_t getOfflineMapboxTileCountLimit();

View File

@@ -3690,7 +3690,10 @@
baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
HEADER_SEARCH_PATHS = (
"$(mbgl_core_INCLUDE_DIRECTORIES)",
"$(mbgl_filesource_INCLUDE_DIRECTORIES)",
);
INFOPLIST_FILE = test/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
OTHER_CFLAGS = "-fvisibility=hidden";
@@ -3714,7 +3717,10 @@
baseConfigurationReference = 55D8C9941D0F133500F42F10 /* config.xcconfig */;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
HEADER_SEARCH_PATHS = "$(mbgl_core_INCLUDE_DIRECTORIES)";
HEADER_SEARCH_PATHS = (
"$(mbgl_core_INCLUDE_DIRECTORIES)",
"$(mbgl_filesource_INCLUDE_DIRECTORIES)",
);
INFOPLIST_FILE = test/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
OTHER_CFLAGS = "-fvisibility=hidden";

View File

@@ -1,9 +1,9 @@
// Do not edit -- generated by CMake
// mbgl-core
mbgl_core_INCLUDE_DIRECTORIES = "@mbgl_core_INCLUDE_DIRECTORIES@"
mbgl_core_LINK_LIBRARIES = "@mbgl_core_LINK_LIBRARIES@"
mbgl_core_INCLUDE_DIRECTORIES = "$<JOIN:$<TARGET_PROPERTY:mbgl-core,INTERFACE_INCLUDE_DIRECTORIES>," ">"
mbgl_core_LINK_LIBRARIES = "$<TARGET_PROPERTY:mbgl-core,XCODE_ATTRIBUTE_XCCONFIG_LINK_LIBRARIES>"
// mbgl-filesource
mbgl_filesource_INCLUDE_DIRECTORIES = "@mbgl_filesource_INCLUDE_DIRECTORIES@"
mbgl_filesource_LINK_LIBRARIES = "@mbgl_filesource_LINK_LIBRARIES@"
mbgl_filesource_INCLUDE_DIRECTORIES = "$<JOIN:$<TARGET_PROPERTY:mbgl-filesource,INTERFACE_INCLUDE_DIRECTORIES>," ">"
mbgl_filesource_LINK_LIBRARIES = "$<TARGET_PROPERTY:mbgl-filesource,XCODE_ATTRIBUTE_XCCONFIG_LINK_LIBRARIES>"

View File

@@ -436,7 +436,8 @@ TEST(OfflineDatabase, UpdateMetadata) {
OfflineRegionMetadata newmetadata {{ 4, 5, 6 }};
db.updateMetadata(region->getID(), newmetadata);
EXPECT_EQ(db.listRegions().at(0).getMetadata(), newmetadata);
auto regions = db.listRegions().value();
EXPECT_EQ(regions.at(0).getMetadata(), newmetadata);
EXPECT_EQ(0u, log.uncheckedCount());
}
@@ -449,7 +450,7 @@ TEST(OfflineDatabase, ListRegions) {
auto region = db.createRegion(definition, metadata);
ASSERT_TRUE(region);
std::vector<OfflineRegion> regions = db.listRegions();
auto regions = db.listRegions().value();
ASSERT_EQ(1u, regions.size());
EXPECT_EQ(region->getID(), regions.at(0).getID());
@@ -499,7 +500,8 @@ TEST(OfflineDatabase, DeleteRegion) {
db.deleteRegion(std::move(*region));
ASSERT_EQ(0u, db.listRegions().size());
auto regions = db.listRegions().value();
ASSERT_EQ(0u, regions.size());
EXPECT_EQ(0u, log.uncheckedCount());
}
@@ -841,10 +843,9 @@ TEST(OfflineDatabase, BatchInsertionMapboxTileCountExceeded) {
EXPECT_EQ(0u, status.completedTileCount);
EXPECT_EQ(0u, status.completedResourceCount);
const auto completedStatus = db.getRegionCompletedStatus(region->getID());
ASSERT_TRUE(completedStatus);
EXPECT_EQ(1u, completedStatus->completedTileCount);
EXPECT_EQ(2u, completedStatus->completedResourceCount);
const auto completedStatus = db.getRegionCompletedStatus(region->getID()).value();
EXPECT_EQ(1u, completedStatus.completedTileCount);
EXPECT_EQ(2u, completedStatus.completedResourceCount);
EXPECT_EQ(0u, log.uncheckedCount());
}
@@ -858,7 +859,8 @@ TEST(OfflineDatabase, MigrateFromV2Schema) {
{
OfflineDatabase db(filename, 0);
auto regions = db.listRegions();
for (auto& region : regions) {
ASSERT_TRUE(regions);
for (auto& region : regions.value()) {
db.deleteRegion(std::move(region));
}
}
@@ -878,7 +880,7 @@ TEST(OfflineDatabase, MigrateFromV3Schema) {
{
OfflineDatabase db(filename, 0);
auto regions = db.listRegions();
auto regions = db.listRegions().value();
for (auto& region : regions) {
db.deleteRegion(std::move(region));
}
@@ -897,7 +899,7 @@ TEST(OfflineDatabase, MigrateFromV4Schema) {
{
OfflineDatabase db(filename, 0);
auto regions = db.listRegions();
auto regions = db.listRegions().value();
for (auto& region : regions) {
db.deleteRegion(std::move(region));
}
@@ -923,7 +925,7 @@ TEST(OfflineDatabase, MigrateFromV5Schema) {
{
OfflineDatabase db(filename, 0);
auto regions = db.listRegions();
auto regions = db.listRegions().value();
for (auto& region : regions) {
db.deleteRegion(std::move(region));
}
@@ -1046,16 +1048,15 @@ TEST(OfflineDatabase, TEST_REQUIRES_WRITE(DisallowedIO)) {
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't write resource: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
const auto regions = db.listRegions();
EXPECT_TRUE(regions.empty());
EXPECT_FALSE(db.listRegions());
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't list regions: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
EXPECT_EQ(nullopt, db.createRegion(definition, {}));
EXPECT_FALSE(db.createRegion(definition, {}));
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't create region: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
EXPECT_EQ(nullopt, db.updateMetadata(region->getID(), {}));
EXPECT_FALSE(db.updateMetadata(region->getID(), {}));
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't update region metadata: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
@@ -1077,15 +1078,15 @@ TEST(OfflineDatabase, TEST_REQUIRES_WRITE(DisallowedIO)) {
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't write region resources: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
EXPECT_EQ(nullopt, db.getRegionDefinition(region->getID()));
EXPECT_FALSE(db.getRegionDefinition(region->getID()));
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't load region: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
EXPECT_EQ(nullopt, db.getRegionCompletedStatus(region->getID()));
EXPECT_FALSE(db.getRegionCompletedStatus(region->getID()));
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't get region status: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());
db.deleteRegion(std::move(*region));
EXPECT_TRUE(db.deleteRegion(std::move(*region)));
EXPECT_EQ(1u, log.count(warning(ResultCode::Auth, "Can't delete region: authorization denied")));
EXPECT_EQ(0u, log.uncheckedCount());

View File

@@ -65,7 +65,7 @@ public:
OfflineDatabase db;
std::size_t size = 0;
optional<OfflineRegion> createRegion() {
auto createRegion() {
OfflineRegionDefinition definition { "", LatLngBounds::hull({1, 2}, {3, 4}), 5, 6, 1.0 };
OfflineRegionMetadata metadata;
return db.createRegion(definition, metadata);