Skip to content

Commit

Permalink
Refactor link tracing code (#5796)
Browse files Browse the repository at this point in the history
* refactor link tracing code

* LinkTranslator gets a separate file

* update changelog

* review feedback
  • Loading branch information
ironage authored Sep 14, 2022
1 parent 78bd122 commit 267fa66
Show file tree
Hide file tree
Showing 10 changed files with 560 additions and 199 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

### Fixed
* <How do the end-user experience this issue? what was the impact?> ([#????](https://github.com/realm/realm-core/issues/????), since v?.?.?)
* Prevent migrations to an embedded object type when there are incoming links from Mixed/TypedLink properties until we can support them. ([#5796](https://github.com/realm/realm-core/pull/5796))
* Fix a data race on RealmCoordinator::m_sync_session which could occur if multiple threads performed the initial open of a Realm at once. (since v11.8.0).
* If a SyncSession outlived the parent Realm and then was adopted by a new Realm for the same file, other processes would not get notified for sync writes on that file.
* Fix one cause of QoS inversion warnings when performing writes on the main thread on Apple platforms. Waiting for async notifications to be ready is now done in a QoS-aware ways.
Expand Down
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ let notSyncServerSources: [String] = [
"realm/history.cpp",
"realm/impl",
"realm/index_string.cpp",
"realm/link_translator.cpp",
"realm/list.cpp",
"realm/mixed.cpp",
"realm/node.cpp",
Expand Down
1 change: 1 addition & 0 deletions src/realm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ set(REALM_SOURCES
impl/simulated_failure.cpp
impl/transact_log.cpp
index_string.cpp
link_translator.cpp
list.cpp
node.cpp
mixed.cpp
Expand Down
94 changes: 94 additions & 0 deletions src/realm/link_translator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*************************************************************************
*
* Copyright 2022 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.
*
**************************************************************************/

#include "realm/link_translator.hpp"

#include <realm/dictionary.hpp>
#include <realm/list.hpp>
#include <realm/set.hpp>

namespace realm {

LinkTranslator::LinkTranslator(Obj origin, ColKey origin_col_key)
: m_origin_obj(origin)
, m_origin_col_key(origin_col_key)
{
}

void LinkTranslator::run()
{
ColumnAttrMask attr = m_origin_col_key.get_attrs();
if (attr.test(col_attr_List)) {
if (m_origin_col_key.get_type() == col_type_LinkList) {
LnkLst link_list = m_origin_obj.get_linklist(m_origin_col_key);
on_list_of_links(link_list);
}
else if (m_origin_col_key.get_type() == col_type_Mixed) {
Lst<Mixed> list = m_origin_obj.get_list<Mixed>(m_origin_col_key);
on_list_of_mixed(list);
}
else if (m_origin_col_key.get_type() == col_type_TypedLink) {
Lst<ObjLink> list = m_origin_obj.get_list<ObjLink>(m_origin_col_key);
on_list_of_typedlink(list);
}
else {
throw std::runtime_error(
util::format("LinkTranslator unhandled list type: %1", m_origin_col_key.get_type()));
}
}
else if (attr.test(col_attr_Set)) {
if (m_origin_col_key.get_type() == col_type_Link) {
LnkSet set = m_origin_obj.get_linkset(m_origin_col_key);
on_set_of_links(set);
}
else if (m_origin_col_key.get_type() == col_type_Mixed) {
Set<Mixed> set = m_origin_obj.get_set<Mixed>(m_origin_col_key);
on_set_of_mixed(set);
}
else if (m_origin_col_key.get_type() == col_type_TypedLink) {
Set<ObjLink> set = m_origin_obj.get_set<ObjLink>(m_origin_col_key);
on_set_of_typedlink(set);
}
else {
throw std::runtime_error(
util::format("LinkTranslator unhandled set type: %1", m_origin_col_key.get_type()));
}
}
else if (attr.test(col_attr_Dictionary)) {
auto dict = m_origin_obj.get_dictionary(m_origin_col_key);
on_dictionary(dict);
}
else {
REALM_ASSERT_EX(!m_origin_col_key.is_collection(), m_origin_col_key);
if (m_origin_col_key.get_type() == col_type_Link) {
on_link_property(m_origin_col_key);
}
else if (m_origin_col_key.get_type() == col_type_Mixed) {
on_mixed_property(m_origin_col_key);
}
else if (m_origin_col_key.get_type() == col_type_TypedLink) {
on_typedlink_property(m_origin_col_key);
}
else {
throw std::runtime_error(
util::format("LinkTranslator unhandled property type: %1", m_origin_col_key.get_type()));
}
}
}

} // namespace realm
54 changes: 54 additions & 0 deletions src/realm/link_translator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*************************************************************************
*
* Copyright 2022 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_LINK_TRANSLATOR_HPP
#define REALM_LINK_TRANSLATOR_HPP

#include <realm/obj.hpp>

namespace realm {

// This construct is used when code needs to handle all
// possible link column types. Subclass and override all
// methods to handle each type. A good example of where
// this is useful is when following a backlink to its
// origin column and modifying the outgoing link from
// whatever container it came from.
class LinkTranslator {
public:
LinkTranslator(Obj origin, ColKey origin_col_key);
void run();
virtual void on_list_of_links(LnkLst& list) = 0;
virtual void on_list_of_mixed(Lst<Mixed>& list) = 0;
virtual void on_list_of_typedlink(Lst<ObjLink>& list) = 0;
virtual void on_set_of_links(LnkSet& set) = 0;
virtual void on_set_of_mixed(Set<Mixed>& set) = 0;
virtual void on_set_of_typedlink(Set<ObjLink>& set) = 0;
virtual void on_dictionary(Dictionary& dict) = 0;
virtual void on_link_property(ColKey col) = 0;
virtual void on_mixed_property(ColKey col) = 0;
virtual void on_typedlink_property(ColKey col) = 0;

protected:
Obj m_origin_obj;
ColKey m_origin_col_key;
};

} // namespace realm

#endif // REALM_LINK_TRANSLATOR_HPP
7 changes: 3 additions & 4 deletions src/realm/list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,10 +278,9 @@ void Lst<ObjKey>::do_clear()
ObjKey target_key = m_tree->get(ndx);
Obj target_obj = target_table->get_object(target_key);
target_obj.remove_one_backlink(backlink_col, m_obj.get_key()); // Throws
size_t num_remaining = target_obj.get_backlink_count(*origin_table, m_col_key);
if (num_remaining == 0) {
state.m_to_be_deleted.emplace_back(target_table_key, target_key);
}
// embedded objects should only have one incoming link
REALM_ASSERT_EX(target_obj.get_backlink_count() == 0, target_obj.get_backlink_count());
state.m_to_be_deleted.emplace_back(target_table_key, target_key);
}

m_tree->clear();
Expand Down
Loading

0 comments on commit 267fa66

Please sign in to comment.