WIP: use expected<T, E> for passing on errors
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -210,4 +210,6 @@ private:
|
||||
const OfflineRegionMetadata metadata;
|
||||
};
|
||||
|
||||
using OfflineRegions = std::vector<OfflineRegion>;
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -97,6 +97,7 @@ macro(mbgl_platform_core)
|
||||
|
||||
target_link_libraries(mbgl-core
|
||||
PRIVATE nunicode
|
||||
PUBLIC expected
|
||||
PUBLIC -llog
|
||||
PUBLIC -landroid
|
||||
PUBLIC -ljnigraphics
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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(), ^{
|
||||
|
||||
@@ -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 ®ion : *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 ®ion : regions) {
|
||||
MGLOfflinePack *pack = [[MGLOfflinePack alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(region))];
|
||||
[packs addObject:pack];
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user