realm-js/shared_realm.hpp

193 lines
6.8 KiB
C++
Raw Normal View History

2015-06-18 23:04:41 +00:00
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
#ifndef REALM_REALM_HPP
#define REALM_REALM_HPP
#include <memory>
#include <thread>
#include <vector>
#include <set>
#include <map>
2015-07-27 19:42:55 +00:00
2015-06-18 23:04:41 +00:00
#include "object_store.hpp"
namespace realm {
class RealmCache;
class Realm;
typedef std::shared_ptr<Realm> SharedRealm;
typedef std::weak_ptr<Realm> WeakRealm;
2015-07-20 18:53:21 +00:00
class ClientHistory;
2015-06-18 23:04:41 +00:00
2015-07-27 19:42:55 +00:00
class Realm : public std::enable_shared_from_this<Realm>
2015-06-18 23:04:41 +00:00
{
public:
2015-07-27 19:42:55 +00:00
typedef std::function<void(SharedRealm old_realm, SharedRealm realm)> MigrationFunction;
2015-06-18 23:04:41 +00:00
struct Config
{
std::string path;
bool read_only = false;
bool in_memory = false;
2015-09-04 18:51:19 +00:00
std::unique_ptr<char[]> encryption_key;
2015-06-18 23:04:41 +00:00
2015-07-27 19:42:55 +00:00
std::unique_ptr<Schema> schema;
uint64_t schema_version = ObjectStore::NotVersioned;
2015-06-18 23:04:41 +00:00
2015-07-27 19:42:55 +00:00
MigrationFunction migration_function;
Config() = default;
Config(Config&&) = default;
2015-06-18 23:04:41 +00:00
Config(const Config& c);
};
// Get a cached Realm or create a new one if no cached copies exists
// Caching is done by path - mismatches for inMemory and readOnly Config properties
// will raise an exception
// If schema/schema_version is specified, update_schema is called automatically on the realm
// and a migration is performed. If not specified, the schema version and schema are dynamically
// read from the the existing Realm.
2015-06-18 23:04:41 +00:00
static SharedRealm get_shared_realm(Config &config);
// Updates a Realm to a given target schema/version creating tables and updating indexes as necessary
// Uses the existing migration function on the Config, and the resulting Schema and version with updated
// column mappings are set on the realms config upon success.
// returns if any changes were made
2015-07-27 19:42:55 +00:00
bool update_schema(Schema &schema, uint64_t version);
2015-06-18 23:04:41 +00:00
const Config &config() const { return m_config; }
void begin_transaction();
void commit_transaction();
void cancel_transaction();
bool is_in_transaction() { return m_in_transaction; }
bool refresh();
void set_auto_refresh(bool auto_refresh) { m_auto_refresh = auto_refresh; }
bool auto_refresh() { return m_auto_refresh; }
void notify();
typedef std::shared_ptr<std::function<void(const std::string)>> NotificationFunction;
void add_notification(NotificationFunction &notification) { m_notifications.insert(notification); }
void remove_notification(NotificationFunction notification) { m_notifications.erase(notification); }
2015-07-27 22:15:18 +00:00
void remove_all_notifications() { m_notifications.clear(); }
2015-06-18 23:04:41 +00:00
void invalidate();
bool compact();
std::thread::id thread_id() const { return m_thread_id; }
void verify_thread();
const std::string RefreshRequiredNotification = "RefreshRequiredNotification";
const std::string DidChangeNotification = "DidChangeNotification";
private:
Realm(Config &config);
2015-06-18 23:04:41 +00:00
Config m_config;
std::thread::id m_thread_id;
bool m_in_transaction;
bool m_auto_refresh;
std::set<NotificationFunction> m_notifications;
void send_local_notifications(const std::string &notification);
typedef std::unique_ptr<std::function<void()>> ExternalNotificationFunction;
void send_external_notifications() { if (m_external_notifier) (*m_external_notifier)(); }
2015-07-20 18:53:21 +00:00
std::unique_ptr<ClientHistory> m_history;
2015-06-18 23:04:41 +00:00
std::unique_ptr<SharedGroup> m_shared_group;
std::unique_ptr<Group> m_read_only_group;
Group *m_group;
2015-07-27 19:42:55 +00:00
public:
2015-06-18 23:04:41 +00:00
ExternalNotificationFunction m_external_notifier;
2015-07-27 19:42:55 +00:00
// FIXME private
Group *read_group();
2015-08-12 19:02:56 +00:00
static RealmCache s_global_cache;
2015-06-18 23:04:41 +00:00
};
2015-07-27 19:42:55 +00:00
class RealmCache
{
public:
SharedRealm get_realm(const std::string &path, std::thread::id thread_id = std::this_thread::get_id());
SharedRealm get_any_realm(const std::string &path);
void remove(const std::string &path, std::thread::id thread_id);
void cache_realm(SharedRealm &realm, std::thread::id thread_id = std::this_thread::get_id());
2015-08-12 19:02:56 +00:00
void clear();
2015-07-27 19:42:55 +00:00
private:
std::map<std::string, std::map<std::thread::id, WeakRealm>> m_cache;
std::mutex m_mutex;
};
class RealmFileException : public std::runtime_error
2015-06-18 23:04:41 +00:00
{
public:
enum class Kind
{
/** Thrown for any I/O related exception scenarios when a realm is opened. */
2015-07-27 19:42:55 +00:00
AccessError,
2015-06-18 23:04:41 +00:00
/** Thrown if the user does not have permission to open or create
the specified file in the specified access mode when the realm is opened. */
2015-07-27 19:42:55 +00:00
PermissionDenied,
2015-06-18 23:04:41 +00:00
/** Thrown if no_create was specified and the file did already exist when the realm is opened. */
2015-07-27 19:42:55 +00:00
Exists,
2015-06-18 23:04:41 +00:00
/** Thrown if no_create was specified and the file was not found when the realm is opened. */
2015-07-27 19:42:55 +00:00
NotFound,
2015-06-18 23:04:41 +00:00
/** Thrown if the database file is currently open in another
process which cannot share with the current process due to an
architecture mismatch. */
IncompatibleLockFile,
};
2015-07-27 19:42:55 +00:00
RealmFileException(Kind kind, std::string message) : std::runtime_error(message), m_kind(kind) {}
2015-06-18 23:04:41 +00:00
Kind kind() const { return m_kind; }
private:
Kind m_kind;
};
2015-07-27 19:42:55 +00:00
class MismatchedConfigException : public std::runtime_error
2015-06-18 23:04:41 +00:00
{
public:
2015-07-27 19:42:55 +00:00
MismatchedConfigException(std::string message) : std::runtime_error(message) {}
};
2015-06-18 23:04:41 +00:00
2015-07-27 19:42:55 +00:00
class InvalidTransactionException : public std::runtime_error
{
public:
InvalidTransactionException(std::string message) : std::runtime_error(message) {}
};
class IncorrectThreadException : public std::runtime_error
{
public:
IncorrectThreadException(std::string message) : std::runtime_error(message) {}
2015-06-18 23:04:41 +00:00
};
2015-07-28 18:25:04 +00:00
class UnitializedRealmException : public std::runtime_error
{
public:
UnitializedRealmException(std::string message) : std::runtime_error(message) {}
};
2015-06-18 23:04:41 +00:00
}
#endif /* defined(REALM_REALM_HPP) */