latest object store

This commit is contained in:
Ari Lazier 2016-03-18 16:14:11 -07:00
commit 7fe2f69b8c
16 changed files with 80 additions and 80 deletions

View File

@ -7,7 +7,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake")
include(CompilerFlags) include(CompilerFlags)
include(RealmCore) include(RealmCore)
set(REALM_CORE_VERSION "0.96.2" CACHE STRING "") set(REALM_CORE_VERSION "0.97.0" CACHE STRING "")
use_realm_core(${REALM_CORE_VERSION}) use_realm_core(${REALM_CORE_VERSION})
include_directories(${REALM_CORE_INCLUDE_DIR} src external/pegtl) include_directories(${REALM_CORE_INCLUDE_DIR} src external/pegtl)

View File

@ -11,7 +11,7 @@ Cross-platform code used accross bindings. Binding developers can choose to use
The object store's build system currently only suports building for OS X. The object store itself can build for all Apple The object store's build system currently only suports building for OS X. The object store itself can build for all Apple
platforms when integrated into a binding. platforms when integrated into a binding.
1. Install CMake. You can download an installer for OS X from the [CMake download page], or install via [Homebrew](http://brew.sh): 1. Install CMake. You can download an installer for OS X from the [CMake download page](https://cmake.org/download/), or install via [Homebrew](http://brew.sh):
``` ```
brew install cmake brew install cmake
``` ```

View File

@ -159,7 +159,7 @@ void AsyncQuery::run()
if (m_initial_run_complete) { if (m_initial_run_complete) {
// Make an empty tableview from the query to get the table version, since // Make an empty tableview from the query to get the table version, since
// Query doesn't expose it // Query doesn't expose it
if (m_query->find_all(0, 0, 0).outside_version() == m_handed_over_table_version) { if (m_query->find_all(0, 0, 0).sync_if_needed() == m_handed_over_table_version) {
return; return;
} }
} }
@ -181,7 +181,7 @@ void AsyncQuery::prepare_handover()
REALM_ASSERT(m_tv.is_in_sync()); REALM_ASSERT(m_tv.is_in_sync());
m_initial_run_complete = true; m_initial_run_complete = true;
m_handed_over_table_version = m_tv.outside_version(); m_handed_over_table_version = m_tv.sync_if_needed();
m_tv_handover = m_sg->export_for_handover(m_tv, MutableSourcePayload::Move); m_tv_handover = m_sg->export_for_handover(m_tv, MutableSourcePayload::Move);
// detach the TableView as we won't need it again and keeping it around // detach the TableView as we won't need it again and keeping it around
@ -231,7 +231,7 @@ bool AsyncQuery::deliver(SharedGroup& sg, std::exception_ptr err)
m_tv_handover->version = m_sg_version; m_tv_handover->version = m_sg_version;
Results::Internal::set_table_view(*m_target_results, Results::Internal::set_table_view(*m_target_results,
std::move(*sg.import_from_handover(std::move(m_tv_handover)))); std::move(*sg.import_from_handover(std::move(m_tv_handover))));
m_delievered_table_version = m_handed_over_table_version; m_delivered_table_version = m_handed_over_table_version;
} }
REALM_ASSERT(!m_tv_handover); REALM_ASSERT(!m_tv_handover);
@ -259,8 +259,8 @@ std::function<void (std::exception_ptr)> AsyncQuery::next_callback()
std::lock_guard<std::mutex> callback_lock(m_callback_mutex); std::lock_guard<std::mutex> callback_lock(m_callback_mutex);
for (++m_callback_index; m_callback_index < m_callbacks.size(); ++m_callback_index) { for (++m_callback_index; m_callback_index < m_callbacks.size(); ++m_callback_index) {
auto& callback = m_callbacks[m_callback_index]; auto& callback = m_callbacks[m_callback_index];
if (m_error || callback.delivered_version != m_delievered_table_version) { if (m_error || callback.delivered_version != m_delivered_table_version) {
callback.delivered_version = m_delievered_table_version; callback.delivered_version = m_delivered_table_version;
return callback.fn; return callback.fn;
} }
} }

View File

@ -97,7 +97,7 @@ private:
SharedGroup* m_sg = nullptr; SharedGroup* m_sg = nullptr;
uint_fast64_t m_handed_over_table_version = -1; uint_fast64_t m_handed_over_table_version = -1;
uint_fast64_t m_delievered_table_version = -1; uint_fast64_t m_delivered_table_version = -1;
// Iteration variable for looping over callbacks // Iteration variable for looping over callbacks
// remove_callback() updates this when needed // remove_callback() updates this when needed

View File

@ -385,7 +385,7 @@ void RealmCoordinator::move_new_queries_to_main()
void RealmCoordinator::advance_helper_shared_group_to_latest() void RealmCoordinator::advance_helper_shared_group_to_latest()
{ {
if (m_new_queries.empty()) { if (m_new_queries.empty()) {
LangBindHelper::advance_read(*m_query_sg, *m_query_history); LangBindHelper::advance_read(*m_query_sg);
return; return;
} }
@ -397,14 +397,13 @@ void RealmCoordinator::advance_helper_shared_group_to_latest()
// Import all newly added queries to our helper SG // Import all newly added queries to our helper SG
for (auto& query : m_new_queries) { for (auto& query : m_new_queries) {
LangBindHelper::advance_read(*m_advancer_sg, *m_advancer_history, query->version()); LangBindHelper::advance_read(*m_advancer_sg, query->version());
query->attach_to(*m_advancer_sg); query->attach_to(*m_advancer_sg);
} }
// Advance both SGs to the newest version // Advance both SGs to the newest version
LangBindHelper::advance_read(*m_advancer_sg, *m_advancer_history); LangBindHelper::advance_read(*m_advancer_sg);
LangBindHelper::advance_read(*m_query_sg, *m_query_history, LangBindHelper::advance_read(*m_query_sg, m_advancer_sg->get_version_of_current_transaction());
m_advancer_sg->get_version_of_current_transaction());
// Transfer all new queries over to the main SG // Transfer all new queries over to the main SG
for (auto& query : m_new_queries) { for (auto& query : m_new_queries) {
@ -421,7 +420,6 @@ void RealmCoordinator::advance_to_ready(Realm& realm)
decltype(m_queries) queries; decltype(m_queries) queries;
auto& sg = Realm::Internal::get_shared_group(realm); auto& sg = Realm::Internal::get_shared_group(realm);
auto& history = Realm::Internal::get_history(realm);
auto get_query_version = [&] { auto get_query_version = [&] {
for (auto& query : m_queries) { for (auto& query : m_queries) {
@ -440,8 +438,8 @@ void RealmCoordinator::advance_to_ready(Realm& realm)
} }
// no async queries; just advance to latest // no async queries; just advance to latest
if (version.version == 0) { if (version.version == std::numeric_limits<uint_fast64_t>::max()) {
transaction::advance(sg, history, realm.m_binding_context.get()); transaction::advance(sg, realm.m_binding_context.get());
return; return;
} }
@ -453,14 +451,14 @@ void RealmCoordinator::advance_to_ready(Realm& realm)
while (true) { while (true) {
// Advance to the ready version without holding any locks because it // Advance to the ready version without holding any locks because it
// may end up calling user code (in did_change() notifications) // may end up calling user code (in did_change() notifications)
transaction::advance(sg, history, realm.m_binding_context.get(), version); transaction::advance(sg, realm.m_binding_context.get(), version);
// Reacquire the lock and recheck the query version, as the queries may // Reacquire the lock and recheck the query version, as the queries may
// have advanced to a later version while we didn't hold the lock. If // have advanced to a later version while we didn't hold the lock. If
// so, we need to release the lock and re-advance // so, we need to release the lock and re-advance
std::lock_guard<std::mutex> lock(m_query_mutex); std::lock_guard<std::mutex> lock(m_query_mutex);
version = get_query_version(); version = get_query_version();
if (version.version == 0) if (version.version == std::numeric_limits<uint_fast64_t>::max())
return; return;
if (version != sg.get_version_of_current_transaction()) if (version != sg.get_version_of_current_transaction())
continue; continue;

View File

@ -25,7 +25,7 @@
namespace realm { namespace realm {
class AsyncQueryCallback; class AsyncQueryCallback;
class ClientHistory; class Replication;
class Results; class Results;
class Schema; class Schema;
class SharedGroup; class SharedGroup;
@ -102,13 +102,13 @@ private:
// SharedGroup used for actually running async queries // SharedGroup used for actually running async queries
// Will have a read transaction iff m_queries is non-empty // Will have a read transaction iff m_queries is non-empty
std::unique_ptr<ClientHistory> m_query_history; std::unique_ptr<Replication> m_query_history;
std::unique_ptr<SharedGroup> m_query_sg; std::unique_ptr<SharedGroup> m_query_sg;
// SharedGroup used to advance queries in m_new_queries to the main shared // SharedGroup used to advance queries in m_new_queries to the main shared
// group's transaction version // group's transaction version
// Will have a read transaction iff m_new_queries is non-empty // Will have a read transaction iff m_new_queries is non-empty
std::unique_ptr<ClientHistory> m_advancer_history; std::unique_ptr<Replication> m_advancer_history;
std::unique_ptr<SharedGroup> m_advancer_sg; std::unique_ptr<SharedGroup> m_advancer_sg;
std::exception_ptr m_async_error; std::exception_ptr m_async_error;

View File

@ -432,23 +432,21 @@ public:
namespace realm { namespace realm {
namespace _impl { namespace _impl {
namespace transaction { namespace transaction {
void advance(SharedGroup& sg, ClientHistory& history, BindingContext* context, void advance(SharedGroup& sg, BindingContext* context, SharedGroup::VersionID version)
SharedGroup::VersionID version)
{ {
TransactLogObserver(context, sg, [&](auto&&... args) { TransactLogObserver(context, sg, [&](auto&&... args) {
LangBindHelper::advance_read(sg, history, std::move(args)...); LangBindHelper::advance_read(sg, std::move(args)...);
}, true); }, true);
} }
void begin(SharedGroup& sg, ClientHistory& history, BindingContext* context, void begin(SharedGroup& sg, BindingContext* context, bool validate_schema_changes)
bool validate_schema_changes)
{ {
TransactLogObserver(context, sg, [&](auto&&... args) { TransactLogObserver(context, sg, [&](auto&&... args) {
LangBindHelper::promote_to_write(sg, history, std::move(args)...); LangBindHelper::promote_to_write(sg, std::move(args)...);
}, validate_schema_changes); }, validate_schema_changes);
} }
void commit(SharedGroup& sg, ClientHistory&, BindingContext* context) void commit(SharedGroup& sg, BindingContext* context)
{ {
LangBindHelper::commit_and_continue_as_read(sg); LangBindHelper::commit_and_continue_as_read(sg);
@ -457,10 +455,10 @@ void commit(SharedGroup& sg, ClientHistory&, BindingContext* context)
} }
} }
void cancel(SharedGroup& sg, ClientHistory& history, BindingContext* context) void cancel(SharedGroup& sg, BindingContext* context)
{ {
TransactLogObserver(context, sg, [&](auto&&... args) { TransactLogObserver(context, sg, [&](auto&&... args) {
LangBindHelper::rollback_and_continue_as_read(sg, history, std::move(args)...); LangBindHelper::rollback_and_continue_as_read(sg, std::move(args)...);
}, false); }, false);
} }

View File

@ -24,27 +24,26 @@
namespace realm { namespace realm {
class BindingContext; class BindingContext;
class SharedGroup; class SharedGroup;
class ClientHistory;
namespace _impl { namespace _impl {
namespace transaction { namespace transaction {
// Advance the read transaction version, with change notifications sent to delegate // Advance the read transaction version, with change notifications sent to delegate
// Must not be called from within a write transaction. // Must not be called from within a write transaction.
void advance(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context, void advance(SharedGroup& sg, BindingContext* binding_context,
SharedGroup::VersionID version=SharedGroup::VersionID{}); SharedGroup::VersionID version=SharedGroup::VersionID{});
// Begin a write transaction // Begin a write transaction
// If the read transaction version is not up to date, will first advance to the // If the read transaction version is not up to date, will first advance to the
// most recent read transaction and sent notifications to delegate // most recent read transaction and sent notifications to delegate
void begin(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context, void begin(SharedGroup& sg, BindingContext* binding_context,
bool validate_schema_changes=true); bool validate_schema_changes=true);
// Commit a write transaction // Commit a write transaction
void commit(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context); void commit(SharedGroup& sg, BindingContext* binding_context);
// Cancel a write transaction and roll back all changes, with change notifications // Cancel a write transaction and roll back all changes, with change notifications
// for reverting to the old values sent to delegate // for reverting to the old values sent to delegate
void cancel(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context); void cancel(SharedGroup& sg, BindingContext* binding_context);
} // namespace transaction } // namespace transaction
} // namespace _impl } // namespace _impl
} // namespace realm } // namespace realm

View File

@ -55,6 +55,7 @@ namespace realm {
size_t table_column = -1; size_t table_column = -1;
bool requires_index() const { return is_primary || is_indexed; } bool requires_index() const { return is_primary || is_indexed; }
bool is_indexable() const { return type == PropertyTypeInt || type == PropertyTypeBool || type == PropertyTypeString || type == PropertyTypeDate; }
}; };
static inline const char *string_for_property_type(PropertyType type) { static inline const char *string_for_property_type(PropertyType type) {

View File

@ -89,7 +89,7 @@ void Schema::validate() const
// check indexable // check indexable
if (prop.is_indexed) { if (prop.is_indexed) {
if (prop.type != PropertyTypeString && prop.type != PropertyTypeInt) { if (!prop.is_indexable()) {
exceptions.emplace_back(PropertyTypeNotIndexableException(object.name, prop)); exceptions.emplace_back(PropertyTypeNotIndexableException(object.name, prop));
} }
} }

View File

@ -72,7 +72,7 @@ Realm::Realm(Config config)
} }
void Realm::open_with_config(const Config& config, void Realm::open_with_config(const Config& config,
std::unique_ptr<ClientHistory>& history, std::unique_ptr<Replication>& history,
std::unique_ptr<SharedGroup>& shared_group, std::unique_ptr<SharedGroup>& shared_group,
std::unique_ptr<Group>& read_only_group) std::unique_ptr<Group>& read_only_group)
{ {
@ -211,9 +211,8 @@ void Realm::update_schema(std::unique_ptr<Schema> schema, uint64_t version)
} }
read_group(); read_group();
transaction::begin(*m_shared_group, *m_history, m_binding_context.get(), transaction::begin(*m_shared_group, m_binding_context.get(),
/* error on schema changes */ false); /* error on schema changes */ false);
m_in_transaction = true;
struct WriteTransactionGuard { struct WriteTransactionGuard {
Realm& realm; Realm& realm;
@ -289,20 +288,27 @@ void Realm::verify_in_write() const
} }
} }
bool Realm::is_in_transaction() const noexcept
{
if (!m_shared_group) {
return false;
}
return m_shared_group->get_transact_stage() == SharedGroup::transact_Writing;
}
void Realm::begin_transaction() void Realm::begin_transaction()
{ {
check_read_write(this); check_read_write(this);
verify_thread(); verify_thread();
if (m_in_transaction) { if (is_in_transaction()) {
throw InvalidTransactionException("The Realm is already in a write transaction"); throw InvalidTransactionException("The Realm is already in a write transaction");
} }
// make sure we have a read transaction // make sure we have a read transaction
read_group(); read_group();
transaction::begin(*m_shared_group, *m_history, m_binding_context.get()); transaction::begin(*m_shared_group, m_binding_context.get());
m_in_transaction = true;
} }
void Realm::commit_transaction() void Realm::commit_transaction()
@ -310,12 +316,11 @@ void Realm::commit_transaction()
check_read_write(this); check_read_write(this);
verify_thread(); verify_thread();
if (!m_in_transaction) { if (!is_in_transaction()) {
throw InvalidTransactionException("Can't commit a non-existing write transaction"); throw InvalidTransactionException("Can't commit a non-existing write transaction");
} }
m_in_transaction = false; transaction::commit(*m_shared_group, m_binding_context.get());
transaction::commit(*m_shared_group, *m_history, m_binding_context.get());
m_coordinator->send_commit_notifications(); m_coordinator->send_commit_notifications();
} }
@ -324,18 +329,19 @@ void Realm::cancel_transaction()
check_read_write(this); check_read_write(this);
verify_thread(); verify_thread();
if (!m_in_transaction) { if (!is_in_transaction()) {
throw InvalidTransactionException("Can't cancel a non-existing write transaction"); throw InvalidTransactionException("Can't cancel a non-existing write transaction");
} }
m_in_transaction = false; transaction::cancel(*m_shared_group, m_binding_context.get());
transaction::cancel(*m_shared_group, *m_history, m_binding_context.get());
} }
void Realm::invalidate() void Realm::invalidate()
{ {
verify_thread(); verify_thread();
if (m_in_transaction) { check_read_write(this);
if (is_in_transaction()) {
cancel_transaction(); cancel_transaction();
} }
if (!m_group) { if (!m_group) {
@ -353,7 +359,7 @@ bool Realm::compact()
if (m_config.read_only) { if (m_config.read_only) {
throw InvalidTransactionException("Can't compact a read-only Realm"); throw InvalidTransactionException("Can't compact a read-only Realm");
} }
if (m_in_transaction) { if (is_in_transaction()) {
throw InvalidTransactionException("Can't compact a Realm within a write transaction"); throw InvalidTransactionException("Can't compact a Realm within a write transaction");
} }
@ -395,7 +401,7 @@ bool Realm::refresh()
check_read_write(this); check_read_write(this);
// can't be any new changes if we're in a write transaction // can't be any new changes if we're in a write transaction
if (m_in_transaction) { if (is_in_transaction()) {
return false; return false;
} }
@ -405,7 +411,7 @@ bool Realm::refresh()
} }
if (m_group) { if (m_group) {
transaction::advance(*m_shared_group, *m_history, m_binding_context.get()); transaction::advance(*m_shared_group, m_binding_context.get());
m_coordinator->process_available_async(*this); m_coordinator->process_available_async(*this);
} }
else { else {

View File

@ -32,7 +32,7 @@
namespace realm { namespace realm {
class BindingContext; class BindingContext;
class ClientHistory; class Replication;
class Group; class Group;
class Realm; class Realm;
class RealmDelegate; class RealmDelegate;
@ -114,7 +114,7 @@ namespace realm {
void begin_transaction(); void begin_transaction();
void commit_transaction(); void commit_transaction();
void cancel_transaction(); void cancel_transaction();
bool is_in_transaction() const { return m_in_transaction; } bool is_in_transaction() const noexcept;
bool is_in_read_transaction() const { return !!m_group; } bool is_in_read_transaction() const { return !!m_group; }
bool refresh(); bool refresh();
@ -149,7 +149,6 @@ namespace realm {
// AsyncQuery needs access to the SharedGroup to be able to call the // AsyncQuery needs access to the SharedGroup to be able to call the
// handover functions, which are not very wrappable // handover functions, which are not very wrappable
static SharedGroup& get_shared_group(Realm& realm) { return *realm.m_shared_group; } static SharedGroup& get_shared_group(Realm& realm) { return *realm.m_shared_group; }
static ClientHistory& get_history(Realm& realm) { return *realm.m_history; }
// AsyncQuery needs to be able to access the owning coordinator to // AsyncQuery needs to be able to access the owning coordinator to
// wake up the worker thread when a callback is added, and // wake up the worker thread when a callback is added, and
@ -158,17 +157,16 @@ namespace realm {
}; };
static void open_with_config(const Config& config, static void open_with_config(const Config& config,
std::unique_ptr<ClientHistory>& history, std::unique_ptr<Replication>& history,
std::unique_ptr<SharedGroup>& shared_group, std::unique_ptr<SharedGroup>& shared_group,
std::unique_ptr<Group>& read_only_group); std::unique_ptr<Group>& read_only_group);
private: private:
Config m_config; Config m_config;
std::thread::id m_thread_id = std::this_thread::get_id(); std::thread::id m_thread_id = std::this_thread::get_id();
bool m_in_transaction = false;
bool m_auto_refresh = true; bool m_auto_refresh = true;
std::unique_ptr<ClientHistory> m_history; std::unique_ptr<Replication> m_history;
std::unique_ptr<SharedGroup> m_shared_group; std::unique_ptr<SharedGroup> m_shared_group;
std::unique_ptr<Group> m_read_only_group; std::unique_ptr<Group> m_read_only_group;