//////////////////////////////////////////////////////////////////////////// // // 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 #include #include #include #include #include "object_store.hpp" namespace realm { class RealmCache; class Realm; typedef std::shared_ptr SharedRealm; typedef std::weak_ptr WeakRealm; class ClientHistory; class Realm : public std::enable_shared_from_this { public: typedef std::function MigrationFunction; struct Config { std::string path; bool read_only = false; bool in_memory = false; bool cache = true; std::vector encryption_key; std::unique_ptr schema; uint64_t schema_version = ObjectStore::NotVersioned; MigrationFunction migration_function; Config() = default; Config(Config&&) = default; Config(const Config& c); Config& operator=(Config const&); Config& operator=(Config&&) = default; }; // Get a cached Realm or create a new one if no cached copies exists // Caching is done by path - mismatches for in_memory and read_only // 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. 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 bool update_schema(Schema &schema, uint64_t version); 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> NotificationFunction; void add_notification(NotificationFunction ¬ification) { m_notifications.insert(notification); } void remove_notification(NotificationFunction notification) { m_notifications.erase(notification); } void remove_all_notifications() { m_notifications.clear(); } 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); Config m_config; std::thread::id m_thread_id = std::this_thread::get_id(); bool m_in_transaction = false; bool m_auto_refresh = true; std::set m_notifications; void send_local_notifications(const std::string ¬ification); typedef std::unique_ptr> ExternalNotificationFunction; void send_external_notifications() { if (m_external_notifier) (*m_external_notifier)(); } std::unique_ptr m_history; std::unique_ptr m_shared_group; std::unique_ptr m_read_only_group; Group *m_group = nullptr; public: ExternalNotificationFunction m_external_notifier; // FIXME private Group *read_group(); static RealmCache s_global_cache; }; 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()); void clear(); private: std::map> m_cache; std::mutex m_mutex; }; class RealmFileException : public std::runtime_error { public: enum class Kind { /** Thrown for any I/O related exception scenarios when a realm is opened. */ AccessError, /** 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. */ PermissionDenied, /** Thrown if no_create was specified and the file did already exist when the realm is opened. */ Exists, /** Thrown if no_create was specified and the file was not found when the realm is opened. */ NotFound, /** Thrown if the database file is currently open in another process which cannot share with the current process due to an architecture mismatch. */ IncompatibleLockFile, }; RealmFileException(Kind kind, std::string message) : std::runtime_error(message), m_kind(kind) {} Kind kind() const { return m_kind; } private: Kind m_kind; }; class MismatchedConfigException : public std::runtime_error { public: MismatchedConfigException(std::string message) : std::runtime_error(message) {} }; 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) {} }; class UnitializedRealmException : public std::runtime_error { public: UnitializedRealmException(std::string message) : std::runtime_error(message) {} }; } #endif /* defined(REALM_REALM_HPP) */