Skip to content

Commit

Permalink
Merge branch 'master' into ct/capi_propagate_log_category
Browse files Browse the repository at this point in the history
# Conflicts:
#	CHANGELOG.md
  • Loading branch information
clementetb committed Mar 15, 2024
2 parents ec3babe + be38196 commit 6491844
Show file tree
Hide file tree
Showing 16 changed files with 147 additions and 45 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
### Enhancements
* Add support to synchronize collections embedded in Mixed properties and other collections (except sets) ([PR #7353](https://github.com/realm/realm-core/pull/7353)).
* Improve performance of change notifications on nested collections somewhat ([PR #7402](https://github.com/realm/realm-core/pull/7402)).
* Improve performance of aggregate operations on Dictionaries of objects, particularly when the dictionaries are empty ([PR #7418](https://github.com/realm/realm-core/pull/7418))
* Added Resumption delay configuration to SyncClientTimeouts. ([PR #7441](https://github.com/realm/realm-core/pull/7441))
* Update C-API log callback signature to include the log category. ([RCORE-2027](https://jira.mongodb.org/browse/RCORE-2027)

### Fixed
Expand Down
18 changes: 18 additions & 0 deletions bindgen/spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,21 @@ records:
before_notify: 'Nullable<util::UniqueFunction<(r: SharedRealm)>>'
schema_did_change: 'Nullable<util::UniqueFunction<(r: SharedRealm)>>' # new schema available as r.schema

ResumptionDelayInfo:
fields:
max_resumption_delay_interval:
type: std::chrono::milliseconds
default: 3000000
resumption_delay_interval:
type: std::chrono::milliseconds
default: 1000
resumption_delay_backoff_multiplier:
type: int
default: 2
delay_jitter_divisor:
type: int
default: 4

SyncClientTimeouts:
fields:
connect_timeout:
Expand All @@ -570,6 +585,9 @@ records:
fast_reconnect_limit:
type: uint64_t
default: 60000
reconnect_backoff_info:
type: ResumptionDelayInfo
default: {}

SyncClientConfig:
fields:
Expand Down
6 changes: 6 additions & 0 deletions src/realm.h
Original file line number Diff line number Diff line change
Expand Up @@ -3644,6 +3644,12 @@ RLM_API void realm_sync_client_config_set_pong_keepalive_timeout(realm_sync_clie
uint64_t) RLM_API_NOEXCEPT;
RLM_API void realm_sync_client_config_set_fast_reconnect_limit(realm_sync_client_config_t*,
uint64_t) RLM_API_NOEXCEPT;
RLM_API void realm_sync_client_config_set_resumption_delay_interval(realm_sync_client_config_t*,
uint64_t) RLM_API_NOEXCEPT;
RLM_API void realm_sync_client_config_set_max_resumption_delay_interval(realm_sync_client_config_t*,
uint64_t) RLM_API_NOEXCEPT;
RLM_API void realm_sync_client_config_set_resumption_delay_backoff_multiplier(realm_sync_client_config_t*,
int) RLM_API_NOEXCEPT;
RLM_API void realm_sync_client_config_set_sync_socket(realm_sync_client_config_t*,
realm_sync_socket_t*) RLM_API_NOEXCEPT;
RLM_API void realm_sync_client_config_set_default_binding_thread_observer(
Expand Down
36 changes: 17 additions & 19 deletions src/realm/collection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,12 @@ class CollectionBase : public Collection {
return PathElement(ndx);
}

// Clone this collection if it contains objects, and return nullptr otherwise
virtual LinkCollectionPtr clone_as_obj_list() const
{
return nullptr;
}

/// Return true if the collection has changed since the last call to
/// `has_changed()`. Note that this function is not idempotent and updates
/// the internal state of the accessor if it has changed.
Expand Down Expand Up @@ -202,7 +208,7 @@ class CollectionBase : public Collection {
}

/// If this is a collection of links, get the target table.
virtual TableRef get_target_table() const final
TableRef get_target_table() const
{
return get_obj().get_target_table(get_col_key());
}
Expand Down Expand Up @@ -815,24 +821,12 @@ void update_unresolved(std::vector<size_t>& vec, const BPlusTree<ObjKey>* tree);

/// Clear the context flag on the tree if there are no more unresolved links.
void check_for_last_unresolved(BPlusTree<ObjKey>* tree);

/// Proxy class needed because the ObjList interface clobbers method names from
/// CollectionBase.
struct ObjListProxy : ObjList {
virtual TableRef proxy_get_target_table() const = 0;

TableRef get_target_table() const final
{
return proxy_get_target_table();
}
};

} // namespace _impl

/// Base class for collections of objects, where unresolved links (tombstones)
/// can occur.
template <class Interface>
class ObjCollectionBase : public Interface, public _impl::ObjListProxy {
class ObjCollectionBase : public Interface, public ObjList {
public:
static_assert(std::is_base_of_v<CollectionBase, Interface>);

Expand Down Expand Up @@ -868,7 +862,15 @@ class ObjCollectionBase : public Interface, public _impl::ObjListProxy {
return m_unresolved.size() != 0;
}

using Interface::get_target_table;
LinkCollectionPtr clone_as_obj_list() const final
{
return clone_obj_list();
}

TableRef get_target_table() const final
{
return Interface::get_target_table();
}

protected:
ObjCollectionBase() = default;
Expand Down Expand Up @@ -956,10 +958,6 @@ class ObjCollectionBase : public Interface, public _impl::ObjListProxy {
// Sorted set of indices containing unresolved links.
mutable std::vector<size_t> m_unresolved;

TableRef proxy_get_target_table() const final
{
return Interface::get_target_table();
}
bool matches(const ObjList& other) const final
{
return get_owning_obj().get_key() == other.get_owning_obj().get_key() &&
Expand Down
8 changes: 8 additions & 0 deletions src/realm/dictionary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,14 @@ void Dictionary::set_collection_ref(Index index, ref_type ref, CollectionType ty
m_values->set(ndx, Mixed(ref, type));
}

LinkCollectionPtr Dictionary::clone_as_obj_list() const
{
if (get_value_data_type() == type_Link) {
return std::make_unique<DictionaryLinkValues>(*this);
}
return nullptr;
}

/************************* DictionaryLinkValues *************************/

DictionaryLinkValues::DictionaryLinkValues(const Obj& obj, ColKey col_key)
Expand Down
2 changes: 2 additions & 0 deletions src/realm/dictionary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ class Dictionary final : public CollectionBaseImpl<DictionaryBase>, public Colle

void to_json(std::ostream&, JSONOutputMode, util::FunctionRef<void(const Mixed&)>) const override;

LinkCollectionPtr clone_as_obj_list() const final;

private:
using Base::set_collection;

Expand Down
18 changes: 18 additions & 0 deletions src/realm/object-store/c_api/sync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,24 @@ RLM_API void realm_sync_client_config_set_fast_reconnect_limit(realm_sync_client
config->timeouts.fast_reconnect_limit = limit;
}

RLM_API void realm_sync_client_config_set_resumption_delay_interval(realm_sync_client_config_t* config,
uint64_t interval) noexcept
{
config->timeouts.reconnect_backoff_info.resumption_delay_interval = std::chrono::milliseconds{interval};
}

RLM_API void realm_sync_client_config_set_max_resumption_delay_interval(realm_sync_client_config_t* config,
uint64_t interval) noexcept
{
config->timeouts.reconnect_backoff_info.max_resumption_delay_interval = std::chrono::milliseconds{interval};
}

RLM_API void realm_sync_client_config_set_resumption_delay_backoff_multiplier(realm_sync_client_config_t* config,
int multiplier) noexcept
{
config->timeouts.reconnect_backoff_info.resumption_delay_backoff_multiplier = multiplier;
}

/// Register an app local callback handler for bindings interested in registering callbacks before/after
/// the ObjectStore thread runs for this app. This only works for the default socket provider implementation.
/// IMPORTANT: If a function is supplied that handles the exception, it must call abort() or cause the
Expand Down
9 changes: 2 additions & 7 deletions src/realm/object-store/results.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -810,13 +810,8 @@ Query Results::do_get_query() const
return Query(m_table, std::make_unique<TableView>(m_table_view));
}
case Mode::Collection:
if (auto list = dynamic_cast<ObjList*>(m_collection.get())) {
return m_table->where(*list);
}
if (auto dict = dynamic_cast<Dictionary*>(m_collection.get())) {
if (dict->get_value_data_type() == type_Link) {
return m_table->where(*dict);
}
if (auto objlist = m_collection->clone_as_obj_list()) {
return m_table->where(std::move(objlist));
}
return m_query;
case Mode::Table:
Expand Down
11 changes: 10 additions & 1 deletion src/realm/object-store/sync/impl/sync_client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,16 @@ struct SyncClient {
c.pong_keepalive_timeout = config.timeouts.pong_keepalive_timeout;
if (config.timeouts.fast_reconnect_limit > 1000)
c.fast_reconnect_limit = config.timeouts.fast_reconnect_limit;

c.reconnect_backoff_info.resumption_delay_interval =
config.timeouts.reconnect_backoff_info.resumption_delay_interval;
c.reconnect_backoff_info.max_resumption_delay_interval =
config.timeouts.reconnect_backoff_info.max_resumption_delay_interval;
c.reconnect_backoff_info.resumption_delay_backoff_multiplier =
config.timeouts.reconnect_backoff_info.resumption_delay_backoff_multiplier;
if (c.reconnect_backoff_info.resumption_delay_interval.count() < 1000)
logger->warn("A resumption delay interval less than 1000 (1 second) is not recommended");
if (c.reconnect_backoff_info.resumption_delay_backoff_multiplier < 1)
throw InvalidArgument("Delay backoff multiplier in reconnect backoff info cannot be less than 1");
return c;
}())
, m_logger_ptr(logger)
Expand Down
10 changes: 5 additions & 5 deletions src/realm/object-store/sync/sync_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ using namespace realm;
using namespace realm::_impl;

SyncClientTimeouts::SyncClientTimeouts()
: connect_timeout(sync::Client::default_connect_timeout)
, connection_linger_time(sync::Client::default_connection_linger_time)
, ping_keepalive_period(sync::Client::default_ping_keepalive_period)
, pong_keepalive_timeout(sync::Client::default_pong_keepalive_timeout)
, fast_reconnect_limit(sync::Client::default_fast_reconnect_limit)
: connect_timeout(sync::default_connect_timeout)
, connection_linger_time(sync::default_connection_linger_time)
, ping_keepalive_period(sync::default_ping_keepalive_period)
, pong_keepalive_timeout(sync::default_pong_keepalive_timeout)
, fast_reconnect_limit(sync::default_fast_reconnect_limit)
{
}

Expand Down
3 changes: 3 additions & 0 deletions src/realm/object-store/sync/sync_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ struct SyncClientTimeouts {
uint64_t ping_keepalive_period;
uint64_t pong_keepalive_timeout;
uint64_t fast_reconnect_limit;
// Used for requesting location metadata at startup and reconnecting sync connections.
// NOTE: delay_jitter_divisor is not configurable
sync::ResumptionDelayInfo reconnect_backoff_info;
};

struct SyncClientConfig {
Expand Down
6 changes: 0 additions & 6 deletions src/realm/sync/client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ class Client {
public:
using port_type = sync::port_type;

static constexpr milliseconds_type default_connect_timeout = sync::default_connect_timeout;
static constexpr milliseconds_type default_connection_linger_time = sync::default_connection_linger_time;
static constexpr milliseconds_type default_ping_keepalive_period = sync::default_ping_keepalive_period;
static constexpr milliseconds_type default_pong_keepalive_timeout = sync::default_pong_keepalive_timeout;
static constexpr milliseconds_type default_fast_reconnect_limit = sync::default_fast_reconnect_limit;

using Config = ClientConfig;

/// \throw util::EventLoop::Implementation::NotAvailable if no event loop
Expand Down
9 changes: 5 additions & 4 deletions src/realm/sync/noinst/client_impl_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,11 @@ ClientImpl::ClientImpl(ClientConfig config)
config.disable_upload_compaction); // Throws
logger.debug("Config param: disable_sync_to_disk = %1",
config.disable_sync_to_disk); // Throws
logger.debug("Config param: reconnect backoff info: max_delay: %1 ms, initial_delay: %2 ms, multiplier: %3",
m_reconnect_backoff_info.max_resumption_delay_interval.count(),
m_reconnect_backoff_info.resumption_delay_interval.count(),
m_reconnect_backoff_info.resumption_delay_backoff_multiplier);
logger.debug(
"Config param: reconnect backoff info: max_delay: %1 ms, initial_delay: %2 ms, multiplier: %3, jitter: 1/%4",
m_reconnect_backoff_info.max_resumption_delay_interval.count(),
m_reconnect_backoff_info.resumption_delay_interval.count(),
m_reconnect_backoff_info.resumption_delay_backoff_multiplier, m_reconnect_backoff_info.delay_jitter_divisor);

if (config.reconnect_mode != ReconnectMode::normal) {
logger.warn("Testing/debugging feature 'nonnormal reconnect mode' enabled - "
Expand Down
4 changes: 2 additions & 2 deletions src/realm/table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1082,9 +1082,9 @@ void Table::do_erase_root_column(ColKey col_key)
bump_storage_version();
}

Query Table::where(const DictionaryLinkValues& dictionary_of_links) const
Query Table::where(const Dictionary& dict) const
{
return Query(m_own_ref, dictionary_of_links);
return Query(m_own_ref, dict.clone_as_obj_list());
}

void Table::set_table_type(Type table_type, bool handle_backlinks)
Expand Down
6 changes: 5 additions & 1 deletion src/realm/table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,11 @@ class Table {
{
return Query(m_own_ref, list);
}
Query where(const DictionaryLinkValues& dictionary_of_links) const;
Query where(const Dictionary& dict) const;
Query where(LinkCollectionPtr&& list) const
{
return Query(m_own_ref, std::move(list));
}

Query query(const std::string& query_string,
const std::vector<mpark::variant<Mixed, std::vector<Mixed>>>& arguments = {}) const;
Expand Down
44 changes: 44 additions & 0 deletions test/object-store/c_api/c_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,50 @@ TEST_CASE("C API (non-database)", "[c_api]") {
}

#if REALM_ENABLE_SYNC
SECTION("sync_client_config_t") {
auto test_sync_client_config = cptr(realm_sync_client_config_new());
realm_sync_client_config_set_base_file_path(test_sync_client_config.get(), "some string");
CHECK(test_sync_client_config->base_file_path == "some string");
realm_sync_client_config_set_metadata_mode(test_sync_client_config.get(),
RLM_SYNC_CLIENT_METADATA_MODE_ENCRYPTED);
CHECK(test_sync_client_config->metadata_mode ==
static_cast<realm::SyncClientConfig::MetadataMode>(RLM_SYNC_CLIENT_METADATA_MODE_ENCRYPTED));
auto enc_key = make_test_encryption_key(123);
realm_sync_client_config_set_metadata_encryption_key(test_sync_client_config.get(),
reinterpret_cast<uint8_t*>(enc_key.data()));
CHECK(test_sync_client_config->custom_encryption_key);
CHECK(std::equal(enc_key.begin(), enc_key.end(), test_sync_client_config->custom_encryption_key->begin()));
realm_sync_client_config_set_reconnect_mode(test_sync_client_config.get(),
RLM_SYNC_CLIENT_RECONNECT_MODE_TESTING);
CHECK(test_sync_client_config->reconnect_mode ==
static_cast<ReconnectMode>(RLM_SYNC_CLIENT_RECONNECT_MODE_TESTING));
realm_sync_client_config_set_multiplex_sessions(test_sync_client_config.get(), true);
CHECK(test_sync_client_config->multiplex_sessions);
realm_sync_client_config_set_multiplex_sessions(test_sync_client_config.get(), false);
CHECK_FALSE(test_sync_client_config->multiplex_sessions);
realm_sync_client_config_set_user_agent_binding_info(test_sync_client_config.get(), "some user agent stg");
CHECK(test_sync_client_config->user_agent_binding_info == "some user agent stg");
realm_sync_client_config_set_user_agent_application_info(test_sync_client_config.get(), "some application");
CHECK(test_sync_client_config->user_agent_application_info == "some application");
realm_sync_client_config_set_connect_timeout(test_sync_client_config.get(), 666);
CHECK(test_sync_client_config->timeouts.connect_timeout == 666);
realm_sync_client_config_set_connection_linger_time(test_sync_client_config.get(), 999);
CHECK(test_sync_client_config->timeouts.connection_linger_time == 999);
realm_sync_client_config_set_ping_keepalive_period(test_sync_client_config.get(), 555);
CHECK(test_sync_client_config->timeouts.ping_keepalive_period == 555);
realm_sync_client_config_set_pong_keepalive_timeout(test_sync_client_config.get(), 100000);
CHECK(test_sync_client_config->timeouts.pong_keepalive_timeout == 100000);
realm_sync_client_config_set_fast_reconnect_limit(test_sync_client_config.get(), 1099);
CHECK(test_sync_client_config->timeouts.fast_reconnect_limit == 1099);
realm_sync_client_config_set_resumption_delay_interval(test_sync_client_config.get(), 1024);
CHECK(test_sync_client_config->timeouts.reconnect_backoff_info.resumption_delay_interval.count() == 1024);
realm_sync_client_config_set_max_resumption_delay_interval(test_sync_client_config.get(), 600024);
CHECK(test_sync_client_config->timeouts.reconnect_backoff_info.max_resumption_delay_interval.count() ==
600024);
realm_sync_client_config_set_resumption_delay_backoff_multiplier(test_sync_client_config.get(), 1010);
CHECK(test_sync_client_config->timeouts.reconnect_backoff_info.resumption_delay_backoff_multiplier == 1010);
}

SECTION("realm_app_config_t") {
const uint64_t request_timeout = 2500;
std::string base_url = "https://path/to/app";
Expand Down

0 comments on commit 6491844

Please sign in to comment.