Skip to content
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

Client Reset for collections in mixed / nested collections #6766

Merged
merged 22 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
545c72c
client reset for nested collections
nicola-cab Jul 4, 2023
12b91a2
Merge branch 'next-major' of github.com:realm/realm-core into nc/clie…
nicola-cab Jul 17, 2023
0fe0c1c
code review + some fixes in the client reset logic for handling mixed
nicola-cab Jul 18, 2023
6d2d308
add failing tests demonstrating incorrect behaviour
ironage Jul 19, 2023
fe33f4c
Merge branch 'next-major' of github.com:realm/realm-core into nc/clie…
nicola-cab Aug 17, 2023
bc472c9
Merge branch 'next-major' of github.com:realm/realm-core into nc/clie…
nicola-cab Aug 21, 2023
4d6e28d
merge next-major
nicola-cab Sep 5, 2023
6be68fa
Merge branch 'next-major' of github.com:realm/realm-core into nc/clie…
nicola-cab Sep 14, 2023
58b6546
client reset fix logic for nested collections
nicola-cab Sep 15, 2023
f6cd562
WIP collection in mixed client reset tests and algo
nicola-cab Sep 15, 2023
4e32d82
Merge branch 'next-major' of github.com:realm/realm-core into nc/clie…
nicola-cab Sep 18, 2023
27769a7
WIP new logic for client reset and collections in mixed
nicola-cab Sep 19, 2023
d1e96be
Merge branch 'next-major' of github.com:realm/realm-core into nc/clie…
nicola-cab Sep 25, 2023
f5c6650
several fixes and final client reset algo for collection in mixed
nicola-cab Sep 26, 2023
f7d4b05
Fix logic for dictionaries
nicola-cab Sep 27, 2023
4b3b4df
Small fixes
jedelbo Oct 6, 2023
e95c6f5
fix unit tests
nicola-cab Oct 9, 2023
162b504
missing logic for Sets
nicola-cab Oct 9, 2023
2627b28
Fix formatting
jedelbo Oct 10, 2023
9ff6d36
Merge branch 'next-major' of github.com:realm/realm-core into nc/clie…
nicola-cab Oct 10, 2023
396f21f
disable client reset tests as long as sync part is not ready
nicola-cab Oct 10, 2023
a128c18
Merge branch 'nc/client_reset_tests_nested_collections' of github.com…
nicola-cab Oct 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 21 additions & 25 deletions src/realm/dictionary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -800,23 +800,16 @@ bool Dictionary::replace_link(ObjLink old_link, ObjLink replace_link)
return false;
}

void Dictionary::remove_backlinks(CascadeState& state) const
bool Dictionary::remove_backlinks(CascadeState& state) const
{
size_t sz = size();
bool recurse = false;
for (size_t ndx = 0; ndx < sz; ndx++) {
auto val = m_values->get(ndx);
if (val.is_type(type_TypedLink)) {
Base::remove_backlink(m_col_key, val.get_link(), state);
}
else if (val.is_type(type_Dictionary)) {
auto key = do_get_key(ndx);
get_dictionary(key.get_string())->remove_backlinks(state);
}
else if (val.is_type(type_List)) {
auto key = do_get_key(ndx);
get_list(key.get_string())->remove_backlinks(state);
if (clear_backlink(ndx, state)) {
recurse = true;
}
}
return recurse;
}

size_t Dictionary::find_first(Mixed value) const
Expand All @@ -827,16 +820,12 @@ size_t Dictionary::find_first(Mixed value) const
void Dictionary::clear()
{
if (size() > 0) {
Replication* repl = get_replication();
bool recurse = false;
CascadeState cascade_state(CascadeState::Mode::Strong);
if (repl) {
if (Replication* repl = get_replication()) {
repl->dictionary_clear(*this);
}
for (auto&& elem : *this) {
if (clear_backlink(elem.second, cascade_state))
recurse = true;
}
CascadeState cascade_state(CascadeState::Mode::Strong);
bool recurse = remove_backlinks(cascade_state);

// Just destroy the whole cluster
m_dictionary_top->destroy_deep();
m_dictionary_top.reset();
Expand Down Expand Up @@ -958,10 +947,9 @@ Mixed Dictionary::do_get(size_t ndx) const

void Dictionary::do_erase(size_t ndx, Mixed key)
{
auto old_value = m_values->get(ndx);

CascadeState cascade_state(CascadeState::Mode::Strong);
bool recurse = clear_backlink(old_value, cascade_state);
bool recurse = clear_backlink(ndx, cascade_state);

if (recurse)
_impl::TableFriend::remove_recursive(*get_table_unchecked(), cascade_state); // Throws

Expand All @@ -971,7 +959,6 @@ void Dictionary::do_erase(size_t ndx, Mixed key)

m_keys->erase(ndx);
m_values->erase(ndx);

bump_content_version();
}

Expand All @@ -996,11 +983,20 @@ std::pair<Mixed, Mixed> Dictionary::do_get_pair(size_t ndx) const
return {do_get_key(ndx), do_get(ndx)};
}

bool Dictionary::clear_backlink(Mixed value, CascadeState& state) const
bool Dictionary::clear_backlink(size_t ndx, CascadeState& state) const
{
auto value = m_values->get(ndx);
if (value.is_type(type_TypedLink)) {
return Base::remove_backlink(m_col_key, value.get_link(), state);
}
if (value.is_type(type_Dictionary)) {
auto key = do_get_key(ndx);
return get_dictionary(key.get_string())->remove_backlinks(state);
}
if (value.is_type(type_List)) {
auto key = do_get_key(ndx);
return get_list(key.get_string())->remove_backlinks(state);
}
return false;
}

Expand Down
4 changes: 2 additions & 2 deletions src/realm/dictionary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ class Dictionary final : public CollectionBaseImpl<DictionaryBase>, public Colle
void nullify(size_t);
bool nullify(ObjLink target_link);
bool replace_link(ObjLink old_link, ObjLink replace_link);
void remove_backlinks(CascadeState& state) const;
bool remove_backlinks(CascadeState& state) const;
size_t find_first(Mixed value) const;

void clear() final;
Expand Down Expand Up @@ -242,7 +242,7 @@ class Dictionary final : public CollectionBaseImpl<DictionaryBase>, public Colle
size_t do_find_key(Mixed key) const noexcept;
std::pair<size_t, Mixed> find_impl(Mixed key) const noexcept;
std::pair<Mixed, Mixed> do_get_pair(size_t ndx) const;
bool clear_backlink(Mixed value, CascadeState& state) const;
bool clear_backlink(size_t ndx, CascadeState& state) const;
void align_indices(std::vector<size_t>& indices) const;
void swap_content(Array& fields1, Array& fields2, size_t index1, size_t index2);

Expand Down
79 changes: 40 additions & 39 deletions src/realm/list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,14 @@ void Lst<Mixed>::clear()
if (Replication* repl = Base::get_replication()) {
repl->list_clear(*this);
}
size_t ndx = size();
while (ndx--) {
do_remove(ndx);
CascadeState state;
bool recurse = remove_backlinks(state);

m_tree->clear();

if (recurse) {
auto table = get_table_unchecked();
_impl::TableFriend::remove_recursive(*table, state); // Throws
}
bump_content_version();
}
Expand Down Expand Up @@ -573,34 +578,14 @@ void Lst<Mixed>::do_insert(size_t ndx, Mixed value)

void Lst<Mixed>::do_remove(size_t ndx)
{
Mixed old_value = m_tree->get(ndx);
if (old_value.is_type(type_TypedLink, type_Dictionary, type_List)) {

bool recurse = false;
CascadeState state;
if (old_value.is_type(type_TypedLink)) {
auto old_link = old_value.get<ObjLink>();
if (old_link.get_obj_key().is_unresolved()) {
state.m_mode = CascadeState::Mode::All;
}
recurse = Base::remove_backlink(m_col_key, old_link, state);
}
else if (old_value.is_type(type_List)) {
get_list(ndx)->remove_backlinks(state);
}
else if (old_value.is_type(type_Dictionary)) {
get_dictionary(ndx)->remove_backlinks(state);
}
CascadeState state;
bool recurse = clear_backlink(ndx, state);

m_tree->erase(ndx);
m_tree->erase(ndx);

if (recurse) {
auto table = get_table_unchecked();
_impl::TableFriend::remove_recursive(*table, state); // Throws
}
}
else {
m_tree->erase(ndx);
if (recurse) {
auto table = get_table_unchecked();
_impl::TableFriend::remove_recursive(*table, state); // Throws
}
}

Expand Down Expand Up @@ -822,21 +807,37 @@ bool Lst<Mixed>::replace_link(ObjLink old_link, ObjLink replace_link)
return false;
}

void Lst<Mixed>::remove_backlinks(CascadeState& state) const
bool Lst<Mixed>::clear_backlink(size_t ndx, CascadeState& state) const
{
size_t sz = size();
for (size_t ndx = 0; ndx < sz; ndx++) {
Mixed val = m_tree->get(ndx);
if (val.is_type(type_TypedLink)) {
Base::remove_backlink(m_col_key, val.get_link(), state);
Mixed value = m_tree->get(ndx);
if (value.is_type(type_TypedLink, type_Dictionary, type_List)) {
if (value.is_type(type_TypedLink)) {
auto link = value.get<ObjLink>();
if (link.get_obj_key().is_unresolved()) {
state.m_mode = CascadeState::Mode::All;
}
return Base::remove_backlink(m_col_key, link, state);
}
else if (val.is_type(type_List)) {
get_list(ndx)->remove_backlinks(state);
else if (value.is_type(type_List)) {
return get_list(ndx)->remove_backlinks(state);
}
else if (val.is_type(type_Dictionary)) {
get_dictionary(ndx)->remove_backlinks(state);
else if (value.is_type(type_Dictionary)) {
return get_dictionary(ndx)->remove_backlinks(state);
}
}
return false;
}

bool Lst<Mixed>::remove_backlinks(CascadeState& state) const
{
size_t sz = size();
bool recurse = false;
for (size_t ndx = 0; ndx < sz; ndx++) {
if (clear_backlink(ndx, state)) {
recurse = true;
}
}
return recurse;
}

bool Lst<Mixed>::update_if_needed() const
Expand Down
3 changes: 2 additions & 1 deletion src/realm/list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ class Lst<Mixed> final : public CollectionBaseImpl<LstBase>, public CollectionPa

bool nullify(ObjLink);
bool replace_link(ObjLink old_link, ObjLink replace_link);
void remove_backlinks(CascadeState& state) const;
bool remove_backlinks(CascadeState& state) const;
TableRef get_table() const noexcept override
{
return get_obj().get_table();
Expand Down Expand Up @@ -548,6 +548,7 @@ class Lst<Mixed> final : public CollectionBaseImpl<LstBase>, public CollectionPa

return unresolved_to_null(m_tree->get(ndx));
}
bool clear_backlink(size_t ndx, CascadeState& state) const;
};

// Specialization of Lst<ObjKey>:
Expand Down
22 changes: 18 additions & 4 deletions src/realm/obj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ bool Obj::compare_values(Mixed val1, Mixed val2, ColKey ck, Obj other, StringDat
Lst<Mixed> lst2(other, other.get_column_key(col_name));
return compare_list_in_mixed(lst1, lst2, ck, other, col_name);
}
else if (type == type_Set) {
Set<Mixed> set1(*this, ck);
Set<Mixed> set2(other, other.get_column_key(col_name));
return set1 == set2;
}
else if (type == type_Dictionary) {
Dictionary dict1(*this, ck);
Dictionary dict2(other, other.get_column_key(col_name));
Expand Down Expand Up @@ -1145,11 +1150,11 @@ Obj& Obj::set<Mixed>(ColKey col_key, Mixed value, bool is_default)
}
else if (old_value.is_type(type_Dictionary)) {
Dictionary dict(*this, col_key);
dict.remove_backlinks(state);
recurse = dict.remove_backlinks(state);
}
else if (old_value.is_type(type_List)) {
Lst<Mixed> list(*this, col_key);
list.remove_backlinks(state);
recurse = list.remove_backlinks(state);
}

if (value.is_type(type_TypedLink)) {
Expand Down Expand Up @@ -2028,16 +2033,25 @@ CollectionPtr Obj::get_collection_by_stable_path(const StablePath& path) const
while (level < path.size()) {
auto& index = path[level];
auto get_ref = [&]() -> std::pair<Mixed, PathElement> {
Mixed ref;
PathElement path_elem;
if (collection->get_collection_type() == CollectionType::List) {
auto list_of_mixed = dynamic_cast<Lst<Mixed>*>(collection.get());
size_t ndx = list_of_mixed->find_index(index);
return {list_of_mixed->get(ndx), PathElement(ndx)};
if (ndx != realm::not_found) {
ref = list_of_mixed->get(ndx);
path_elem = ndx;
}
}
else {
auto dict = dynamic_cast<Dictionary*>(collection.get());
size_t ndx = dict->find_index(index);
return {dict->get_any(ndx), PathElement(dict->get_key(ndx).get_string())};
if (ndx != realm::not_found) {
ref = dict->get_any(ndx);
path_elem = dict->get_key(ndx).get_string();
}
}
return {ref, path_elem};
};
auto [ref, path_elem] = get_ref();
if (ref.is_type(type_List)) {
Expand Down
Loading