Skip to content

Commit c9e206a

Browse files
authored
Make sure we replicate instructions unconditionally (#7523)
Eg. List::clear should replicate even though the list is already empty. Obj::set should replicate even though old and new values are equal. This has influence on OT. If you want to assign new values to an empty list and does not replicate the clear instruction you could end up having your values added to some content added by another client.
1 parent 6b07299 commit c9e206a

File tree

6 files changed

+168
-221
lines changed

6 files changed

+168
-221
lines changed

src/realm/dictionary.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -433,16 +433,8 @@ void Dictionary::insert_collection(const PathElement& path_elem, CollectionType
433433
if (dict_or_list == CollectionType::Set) {
434434
throw IllegalOperation("Set nested in Dictionary is not supported");
435435
}
436-
437436
check_level();
438-
ensure_created();
439-
Mixed new_val(0, dict_or_list);
440-
auto old_val = try_get(path_elem.get_key());
441-
if (!old_val || *old_val != new_val) {
442-
m_values->ensure_keys();
443-
auto [it, inserted] = insert(path_elem.get_key(), new_val);
444-
set_key(*m_values, it.index());
445-
}
437+
insert(path_elem.get_key(), Mixed(0, dict_or_list));
446438
}
447439

448440
DictionaryPtr Dictionary::get_dictionary(const PathElement& path_elem) const
@@ -549,6 +541,7 @@ std::pair<Dictionary::Iterator, bool> Dictionary::insert(Mixed key, Mixed value)
549541
throw StaleAccessor("Stale dictionary");
550542
}
551543

544+
bool set_nested_collection_key = value.is_type(type_Dictionary, type_List);
552545
bool old_entry = false;
553546
auto [ndx, actual_key] = find_impl(key);
554547
if (actual_key != key) {
@@ -577,16 +570,25 @@ std::pair<Dictionary::Iterator, bool> Dictionary::insert(Mixed key, Mixed value)
577570
repl->dictionary_insert(*this, ndx, key, value);
578571
}
579572
}
580-
581573
bump_content_version();
582574

583575
ObjLink old_link;
584576
if (old_entry) {
585577
Mixed old_value = m_values->get(ndx);
586-
if (old_value.is_type(type_TypedLink)) {
587-
old_link = old_value.get<ObjLink>();
578+
if (!value.is_same_type(old_value) || value != old_value) {
579+
if (old_value.is_type(type_TypedLink)) {
580+
old_link = old_value.get<ObjLink>();
581+
}
582+
m_values->set(ndx, value);
588583
}
589-
m_values->set(ndx, value);
584+
else {
585+
set_nested_collection_key = false;
586+
}
587+
}
588+
589+
if (set_nested_collection_key) {
590+
m_values->ensure_keys();
591+
set_key(*m_values, ndx);
590592
}
591593

592594
if (new_link != old_link) {

src/realm/list.cpp

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -408,8 +408,12 @@ Mixed Lst<Mixed>::set(size_t ndx, Mixed value)
408408
if (Replication* repl = Base::get_replication()) {
409409
repl->list_set(*this, ndx, value);
410410
}
411-
if (!(old.is_same_type(value) && old == value)) {
411+
if (!value.is_same_type(old) || value != old) {
412412
do_set(ndx, value);
413+
if (value.is_type(type_Dictionary, type_List)) {
414+
m_tree->ensure_keys();
415+
set_key(*m_tree, ndx);
416+
}
413417
bump_content_version();
414418
}
415419
return old;
@@ -427,6 +431,10 @@ void Lst<Mixed>::insert(size_t ndx, Mixed value)
427431
repl->list_insert(*this, ndx, value, sz);
428432
}
429433
do_insert(ndx, value);
434+
if (value.is_type(type_Dictionary, type_List)) {
435+
m_tree->ensure_keys();
436+
set_key(*m_tree, ndx);
437+
}
430438
bump_content_version();
431439
}
432440

@@ -529,37 +537,17 @@ void Lst<Mixed>::insert_collection(const PathElement& path_elem, CollectionType
529537
if (dict_or_list == CollectionType::Set) {
530538
throw IllegalOperation("Set nested in List<Mixed> is not supported");
531539
}
532-
533-
ensure_created();
534540
check_level();
535-
m_tree->ensure_keys();
536541
insert(path_elem.get_ndx(), Mixed(0, dict_or_list));
537-
set_key(*m_tree, path_elem.get_ndx());
538-
bump_content_version();
539542
}
540543

541544
void Lst<Mixed>::set_collection(const PathElement& path_elem, CollectionType dict_or_list)
542545
{
543546
if (dict_or_list == CollectionType::Set) {
544547
throw IllegalOperation("Set nested in List<Mixed> is not supported");
545548
}
546-
547-
auto ndx = path_elem.get_ndx();
548-
// get will check for ndx out of bounds
549-
Mixed old_val = do_get(ndx, "set_collection()");
550-
Mixed new_val(0, dict_or_list);
551-
552549
check_level();
553-
554-
if (old_val != new_val) {
555-
m_tree->ensure_keys();
556-
set(ndx, new_val);
557-
int64_t key = m_tree->get_key(ndx);
558-
if (key == 0) {
559-
set_key(*m_tree, path_elem.get_ndx());
560-
}
561-
bump_content_version();
562-
}
550+
set(path_elem.get_ndx(), Mixed(0, dict_or_list));
563551
}
564552

565553
DictionaryPtr Lst<Mixed>::get_dictionary(const PathElement& path_elem) const

src/realm/list.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -928,10 +928,11 @@ inline LnkLst Obj::get_linklist(StringData col_name) const
928928
template <class T>
929929
void Lst<T>::clear()
930930
{
931-
if (size() > 0) {
932-
if (Replication* repl = Base::get_replication()) {
933-
repl->list_clear(*this);
934-
}
931+
auto sz = size();
932+
if (Replication* repl = Base::get_replication()) {
933+
repl->list_clear(*this);
934+
}
935+
if (sz > 0) {
935936
do_clear();
936937
bump_content_version();
937938
}

0 commit comments

Comments
 (0)