-
Notifications
You must be signed in to change notification settings - Fork 169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow deletion of ephemeral objects before commit #7064
Changes from 3 commits
d8b9413
8b3028e
dbb928b
1042cef
2b8ba96
fc03907
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -883,8 +883,11 @@ MutableSubscriptionSet SubscriptionStore::get_mutable_by_version(int64_t version | |
{ | ||
auto tr = m_db->start_write(); | ||
auto sub_sets = tr->get_table(m_sub_set_table); | ||
return MutableSubscriptionSet(weak_from_this(), std::move(tr), | ||
sub_sets->get_object_with_primary_key(Mixed{version_id})); | ||
auto obj = sub_sets->get_object_with_primary_key(Mixed{version_id}); | ||
if (!obj) { | ||
throw KeyNotFound("Subscription set not found"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should include the version_id in the message |
||
} | ||
return MutableSubscriptionSet(weak_from_this(), std::move(tr), obj); | ||
} | ||
|
||
SubscriptionSet SubscriptionStore::get_by_version(int64_t version_id) const | ||
|
@@ -897,15 +900,16 @@ SubscriptionSet SubscriptionStore::get_by_version_impl(int64_t version_id, | |
{ | ||
auto tr = m_db->start_frozen(db_version.value_or(VersionID{})); | ||
auto sub_sets = tr->get_table(m_sub_set_table); | ||
try { | ||
return SubscriptionSet(weak_from_this(), *tr, sub_sets->get_object_with_primary_key(Mixed{version_id})); | ||
auto obj = sub_sets->get_object_with_primary_key(Mixed{version_id}); | ||
if (obj) { | ||
return SubscriptionSet(weak_from_this(), *tr, obj); | ||
} | ||
catch (const KeyNotFound&) { | ||
else { | ||
std::lock_guard<std::mutex> lk(m_pending_notifications_mutex); | ||
if (version_id < m_min_outstanding_version) { | ||
return SubscriptionSet(weak_from_this(), version_id, SubscriptionSet::SupersededTag{}); | ||
} | ||
throw; | ||
throw KeyNotFound("Subscription set not found"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -548,7 +548,7 @@ void Table::remove_recursive(CascadeState& cascade_state) | |
cascade_state.send_notifications(); | ||
|
||
for (auto& l : cascade_state.m_to_be_nullified) { | ||
Obj obj = group->get_table(l.origin_table)->try_get_object(l.origin_key); | ||
Obj obj = group->get_table_unchecked(l.origin_table)->try_get_object(l.origin_key); | ||
REALM_ASSERT_DEBUG(obj); | ||
if (obj) { | ||
std::move(obj).nullify_link(l.origin_col_key, l.old_target_link); | ||
|
@@ -558,7 +558,7 @@ void Table::remove_recursive(CascadeState& cascade_state) | |
|
||
auto to_delete = std::move(cascade_state.m_to_be_deleted); | ||
for (auto obj : to_delete) { | ||
auto table = group->get_table(obj.first); | ||
auto table = obj.first == m_key ? this : group->get_table_unchecked(obj.first); | ||
// This might add to the list of objects that should be deleted | ||
REALM_ASSERT(!obj.second.is_unresolved()); | ||
table->m_clusters.erase(obj.second, cascade_state); | ||
|
@@ -572,8 +572,9 @@ void Table::nullify_links(CascadeState& cascade_state) | |
Group* group = get_parent_group(); | ||
REALM_ASSERT(group); | ||
for (auto& to_delete : cascade_state.m_to_be_deleted) { | ||
auto table = group->get_table(to_delete.first); | ||
table->m_clusters.nullify_links(to_delete.second, cascade_state); | ||
auto table = to_delete.first == m_key ? this : group->get_table_unchecked(to_delete.first); | ||
if (!table->is_asymmetric()) | ||
table->m_clusters.nullify_incoming_links(to_delete.second, cascade_state); | ||
} | ||
} | ||
|
||
|
@@ -2178,20 +2179,22 @@ void Table::batch_erase_rows(const KeyColumn& keys) | |
void Table::batch_erase_objects(std::vector<ObjKey>& keys) | ||
{ | ||
Group* g = get_parent_group(); | ||
bool maybe_has_incoming_links = g && !is_asymmetric(); | ||
|
||
if (has_any_embedded_objects() || (g && g->has_cascade_notification_handler())) { | ||
CascadeState state(CascadeState::Mode::Strong, g); | ||
std::for_each(keys.begin(), keys.end(), [this, &state](ObjKey k) { | ||
state.m_to_be_deleted.emplace_back(m_key, k); | ||
}); | ||
nullify_links(state); | ||
if (maybe_has_incoming_links) | ||
nullify_links(state); | ||
remove_recursive(state); | ||
} | ||
else { | ||
CascadeState state(CascadeState::Mode::None, g); | ||
for (auto k : keys) { | ||
if (g) { | ||
m_clusters.nullify_links(k, state); | ||
if (maybe_has_incoming_links) { | ||
m_clusters.nullify_incoming_links(k, state); | ||
} | ||
m_clusters.erase(k, state); | ||
} | ||
|
@@ -3147,7 +3150,8 @@ Obj Table::get_object_with_primary_key(Mixed primary_key) const | |
DataType type = DataType(primary_key_col.get_type()); | ||
REALM_ASSERT((primary_key.is_null() && primary_key_col.get_attrs().test(col_attr_Nullable)) || | ||
primary_key.get_type() == type); | ||
return m_clusters.get(m_index_accessors[primary_key_col.get_index().val]->find_first(primary_key)); | ||
ObjKey k = m_index_accessors[primary_key_col.get_index().val]->find_first(primary_key); | ||
return k ? m_clusters.get(k) : Obj{}; | ||
} | ||
|
||
Mixed Table::get_primary_key(ObjKey key) const | ||
|
@@ -3385,16 +3389,27 @@ void Table::remove_object(ObjKey key) | |
{ | ||
Group* g = get_parent_group(); | ||
|
||
if (is_asymmetric()) { | ||
REALM_ASSERT(g); | ||
auto it = std::find_if(g->m_objects_to_delete.begin(), g->m_objects_to_delete.end(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: |
||
[&](const Group::ToDeleteRef& item) { | ||
return item.table_key == m_key && item.obj_key == key; | ||
}); | ||
if (it != g->m_objects_to_delete.end()) { | ||
g->m_objects_to_delete.erase(it); | ||
} | ||
} | ||
|
||
if (has_any_embedded_objects() || (g && g->has_cascade_notification_handler())) { | ||
CascadeState state(CascadeState::Mode::Strong, g); | ||
state.m_to_be_deleted.emplace_back(m_key, key); | ||
m_clusters.nullify_links(key, state); | ||
m_clusters.nullify_incoming_links(key, state); | ||
remove_recursive(state); | ||
} | ||
else { | ||
CascadeState state(CascadeState::Mode::None, g); | ||
if (g) { | ||
m_clusters.nullify_links(key, state); | ||
m_clusters.nullify_incoming_links(key, state); | ||
} | ||
m_clusters.erase(key, state); | ||
} | ||
|
@@ -3946,7 +3961,7 @@ bool Table::has_any_embedded_objects() | |
for_each_public_column([&](ColKey col_key) { | ||
auto target_table_key = get_opposite_table_key(col_key); | ||
if (target_table_key && is_link_type(col_key.get_type())) { | ||
auto target_table = get_parent_group()->get_table(target_table_key); | ||
auto target_table = get_parent_group()->get_table_unchecked(target_table_key); | ||
if (target_table->is_embedded()) { | ||
m_has_any_embedded_objects = true; | ||
return IteratorControl::Stop; // early out | ||
|
@@ -3984,7 +3999,7 @@ ColKey Table::find_or_add_backlink_column(ColKey origin_col_key, TableKey origin | |
set_opposite_column(backlink_col_key, origin_table, origin_col_key); | ||
|
||
if (Replication* repl = get_repl()) | ||
repl->typed_link_change(get_parent_group()->get_table(origin_table).unchecked_ptr(), origin_col_key, | ||
repl->typed_link_change(get_parent_group()->get_table_unchecked(origin_table), origin_col_key, | ||
m_key); // Throws | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this would be lazy checking
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I guess if we ever get this implemented, this would be the place to check which objects were due to be deleted. BTW if we skip recording the time the object was created, we can make this even more efficient. @danieltabacaru should we do that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not saying it's a bad place to check, it's just that we would be relying on other things being committed. I am not sure if it's the same idea, but we don't really need the object keys, the table keys is enough (we can then clear the tables). we can optimize it further by also skipping storing the table keys by iterating through the tables and clearing the asymmetric ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course - the table keys are sufficient. Even better!