mirror of
https://github.com/status-im/realm-js.git
synced 2025-02-02 17:53:55 +00:00
Upgrade to core 1.0.0 and update the file exception translation to match
File::AccessError is now thrown for all file-related exceptions which don't have more specific types (rather than std::runtime_error), which requires some changes to how exception messages are built when translating them to get nice results. Also add `Realm::write_copy()` which just wraps `Group::write()` with error translation.
This commit is contained in:
parent
1d34e785e7
commit
840c46f8f3
@ -69,7 +69,7 @@ std::shared_ptr<Realm> RealmCoordinator::get_realm(Realm::Config config)
|
||||
m_notifier = std::make_unique<ExternalCommitHelper>(*this);
|
||||
}
|
||||
catch (std::system_error const& ex) {
|
||||
throw RealmFileException(RealmFileException::Kind::AccessError, config.path, ex.code().message());
|
||||
throw RealmFileException(RealmFileException::Kind::AccessError, config.path, ex.code().message(), "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,51 +68,76 @@ Realm::Realm(Config config)
|
||||
}
|
||||
}
|
||||
|
||||
REALM_NOINLINE static void translate_file_exception(StringData path, bool read_only=false)
|
||||
{
|
||||
try {
|
||||
throw;
|
||||
}
|
||||
catch (util::File::PermissionDenied const& ex) {
|
||||
throw RealmFileException(RealmFileException::Kind::PermissionDenied, ex.get_path(),
|
||||
"Unable to open a realm at path '" + ex.get_path() +
|
||||
"'. Please use a path where your app has " + (read_only ? "read" : "read-write") + " permissions.",
|
||||
ex.what());
|
||||
}
|
||||
catch (util::File::Exists const& ex) {
|
||||
throw RealmFileException(RealmFileException::Kind::Exists, ex.get_path(),
|
||||
"File at path '" + ex.get_path() + "' already exists.",
|
||||
ex.what());
|
||||
}
|
||||
catch (util::File::NotFound const& ex) {
|
||||
throw RealmFileException(RealmFileException::Kind::NotFound, ex.get_path(),
|
||||
"Directory at path '" + ex.get_path() + "' does not exist.",
|
||||
ex.what());
|
||||
}
|
||||
catch (util::File::AccessError const& ex) {
|
||||
// Errors for `open()` include the path, but other errors don't. We
|
||||
// don't want two copies of the path in the error, so strip it out if it
|
||||
// appears, and then include it in our prefix.
|
||||
std::string underlying = ex.what();
|
||||
auto pos = underlying.find(ex.get_path());
|
||||
if (pos != std::string::npos && pos > 0) {
|
||||
// One extra char at each end for the quotes
|
||||
underlying.replace(pos - 1, ex.get_path().size() + 2, "");
|
||||
}
|
||||
throw RealmFileException(RealmFileException::Kind::AccessError, ex.get_path(),
|
||||
"Unable to open a realm at path '" + ex.get_path() + "': " + underlying,
|
||||
ex.what());
|
||||
}
|
||||
catch (IncompatibleLockFile const& ex) {
|
||||
throw RealmFileException(RealmFileException::Kind::IncompatibleLockFile, path,
|
||||
"Realm file is currently open in another process "
|
||||
"which cannot share access with this process. All processes sharing a single file must be the same architecture.",
|
||||
ex.what());
|
||||
}
|
||||
catch (FileFormatUpgradeRequired const& ex) {
|
||||
throw RealmFileException(RealmFileException::Kind::FormatUpgradeRequired, path,
|
||||
"The Realm file format must be allowed to be upgraded "
|
||||
"in order to proceed.",
|
||||
ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
void Realm::open_with_config(const Config& config,
|
||||
std::unique_ptr<Replication>& history,
|
||||
std::unique_ptr<SharedGroup>& shared_group,
|
||||
std::unique_ptr<Group>& read_only_group)
|
||||
{
|
||||
if (config.encryption_key.data() && config.encryption_key.size() != 64) {
|
||||
throw InvalidEncryptionKeyException();
|
||||
}
|
||||
try {
|
||||
if (config.read_only) {
|
||||
read_only_group = std::make_unique<Group>(config.path, config.encryption_key.data(), Group::mode_ReadOnly);
|
||||
}
|
||||
else {
|
||||
if (config.encryption_key.data() && config.encryption_key.size() != 64) {
|
||||
throw InvalidEncryptionKeyException();
|
||||
}
|
||||
history = realm::make_client_history(config.path, config.encryption_key.data());
|
||||
SharedGroup::DurabilityLevel durability = config.in_memory ? SharedGroup::durability_MemOnly :
|
||||
SharedGroup::durability_Full;
|
||||
shared_group = std::make_unique<SharedGroup>(*history, durability, config.encryption_key.data(), !config.disable_format_upgrade);
|
||||
}
|
||||
}
|
||||
catch (util::File::PermissionDenied const& ex) {
|
||||
throw RealmFileException(RealmFileException::Kind::PermissionDenied, ex.get_path(),
|
||||
"Unable to open a realm at path '" + ex.get_path() +
|
||||
"'. Please use a path where your app has " + (config.read_only ? "read" : "read-write") + " permissions.");
|
||||
}
|
||||
catch (util::File::Exists const& ex) {
|
||||
throw RealmFileException(RealmFileException::Kind::Exists, ex.get_path(),
|
||||
"File at path '" + ex.get_path() + "' already exists.");
|
||||
}
|
||||
catch (util::File::NotFound const& ex) {
|
||||
throw RealmFileException(RealmFileException::Kind::NotFound, ex.get_path(),
|
||||
"File at path '" + ex.get_path() + "' does not exist.");
|
||||
}
|
||||
catch (util::File::AccessError const& ex) {
|
||||
throw RealmFileException(RealmFileException::Kind::AccessError, ex.get_path(),
|
||||
"Unable to open a realm at path '" + ex.get_path() + "'");
|
||||
}
|
||||
catch (IncompatibleLockFile const& ex) {
|
||||
throw RealmFileException(RealmFileException::Kind::IncompatibleLockFile, config.path,
|
||||
"Realm file is currently open in another process "
|
||||
"which cannot share access with this process. All processes sharing a single file must be the same architecture.");
|
||||
}
|
||||
catch (FileFormatUpgradeRequired const& ex) {
|
||||
throw RealmFileException(RealmFileException::Kind::FormatUpgradeRequired, config.path,
|
||||
"The Realm file format must be allowed to be upgraded "
|
||||
"in order to proceed.");
|
||||
catch (...) {
|
||||
translate_file_exception(config.path, config.read_only);
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +163,7 @@ void Realm::init(std::shared_ptr<RealmCoordinator> coordinator)
|
||||
if (target_schema) {
|
||||
if (m_config.read_only) {
|
||||
if (m_config.schema_version == ObjectStore::NotVersioned) {
|
||||
throw UnitializedRealmException("Can't open an un-initialized Realm without a Schema");
|
||||
throw UninitializedRealmException("Can't open an un-initialized Realm without a Schema");
|
||||
}
|
||||
target_schema->validate();
|
||||
ObjectStore::verify_schema(*m_config.schema, *target_schema, true);
|
||||
@ -370,6 +395,18 @@ bool Realm::compact()
|
||||
return m_shared_group->compact();
|
||||
}
|
||||
|
||||
void Realm::write_copy(StringData path, BinaryData key)
|
||||
{
|
||||
REALM_ASSERT(!key.data() || key.size() == 64);
|
||||
verify_thread();
|
||||
try {
|
||||
read_group()->write(path, key.data());
|
||||
}
|
||||
catch (...) {
|
||||
translate_file_exception(path);
|
||||
}
|
||||
}
|
||||
|
||||
void Realm::notify()
|
||||
{
|
||||
verify_thread();
|
||||
|
@ -19,19 +19,20 @@
|
||||
#ifndef REALM_REALM_HPP
|
||||
#define REALM_REALM_HPP
|
||||
|
||||
#include "schema.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace realm {
|
||||
class BinaryData;
|
||||
class BindingContext;
|
||||
class Group;
|
||||
class Realm;
|
||||
class Replication;
|
||||
class Schema;
|
||||
class SharedGroup;
|
||||
class StringData;
|
||||
typedef std::shared_ptr<Realm> SharedRealm;
|
||||
typedef std::weak_ptr<Realm> WeakRealm;
|
||||
|
||||
@ -121,6 +122,7 @@ namespace realm {
|
||||
|
||||
void invalidate();
|
||||
bool compact();
|
||||
void write_copy(StringData path, BinaryData encryption_key);
|
||||
|
||||
std::thread::id thread_id() const { return m_thread_id; }
|
||||
void verify_thread() const;
|
||||
@ -199,14 +201,16 @@ namespace realm {
|
||||
/** Thrown if the file needs to be upgraded to a new format, but upgrades have been explicitly disabled. */
|
||||
FormatUpgradeRequired,
|
||||
};
|
||||
RealmFileException(Kind kind, std::string path, std::string message) :
|
||||
std::runtime_error(std::move(message)), m_kind(kind), m_path(std::move(path)) {}
|
||||
RealmFileException(Kind kind, std::string path, std::string message, std::string underlying) :
|
||||
std::runtime_error(std::move(message)), m_kind(kind), m_path(std::move(path)), m_underlying(std::move(underlying)) {}
|
||||
Kind kind() const { return m_kind; }
|
||||
const std::string& path() const { return m_path; }
|
||||
const std::string& underlying() const { return m_underlying; }
|
||||
|
||||
private:
|
||||
Kind m_kind;
|
||||
std::string m_path;
|
||||
std::string m_underlying;
|
||||
};
|
||||
|
||||
class MismatchedConfigException : public std::runtime_error {
|
||||
@ -224,9 +228,9 @@ namespace realm {
|
||||
IncorrectThreadException() : std::runtime_error("Realm accessed from incorrect thread.") {}
|
||||
};
|
||||
|
||||
class UnitializedRealmException : public std::runtime_error {
|
||||
class UninitializedRealmException : public std::runtime_error {
|
||||
public:
|
||||
UnitializedRealmException(std::string message) : std::runtime_error(message) {}
|
||||
UninitializedRealmException(std::string message) : std::runtime_error(message) {}
|
||||
};
|
||||
|
||||
class InvalidEncryptionKeyException : public std::runtime_error {
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "impl/realm_coordinator.hpp"
|
||||
|
||||
#include <realm/disable_sync_to_disk.hpp>
|
||||
#include <realm/string_data.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
|
Loading…
x
Reference in New Issue
Block a user