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

Update realm-core to v13.12.0 #1288

Merged
merged 8 commits into from
May 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
34 changes: 32 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## vNext (TBD)

### Enhancements
* Support `Decimal128` datatype ([#1192](https://github.com/realm/realm-dart/pull/1192)).
* Realm logging is extended to support logging of all Realm storage level messages. (Core upgrade).
* Realm.logger now prints by default to the console from the first Isolate that initializes a Realm in the application. ([#1226](https://github.com/realm/realm-dart/pull/1226)).
Calling `Realm.logger.clearListeners()` or `Realm.logger.level = RealmLogLevel.off` will turn off logging. If that is the first isolate it will stop the default printing logger.
Expand All @@ -15,19 +16,49 @@
* Moderate (~25%) improvement when querying for an exact match on a Boolean property that has an index.
* Small (~5%) improvement when querying for a case insensitive match on a Mixed property that does not have an index.

* Enable multiple processes to operate on an encrypted Realm simultaneously. (Core upgrade)

* Improve performance of equality queries on a non-indexed mixed property by about 30%. (Core upgrade)

* Improve performance of rolling back write transactions after making changes. If no KVO observers are used this is now constant time rather than taking time proportional to the number of changes to be rolled back. Rollbacks with KVO observers are 10-20% faster. (Core upgrade)
* New notifiers can now be registered in write transactions until changes have actually been made in the write transaction. This makes it so that new notifications can be registered inside change notifications triggered by beginning a write transaction (unless a previous callback performed writes). (Core upgrade)

* Very slightly improve performance of runtime thread checking on the main thread on Apple platforms. (Core upgrade)

### Fixed
* Fixed a bug that may have resulted in arrays being in different orders on different devices (Core upgrade).
* Fixed a crash when querying a mixed property with a string operator (contains/like/beginswith/endswith) or with case insensitivity (Core upgrade).
* Querying for equality of a string on an indexed mixed property was returning case insensitive matches. For example querying for `myIndexedMixed == "Foo"` would incorrectly match on values of "foo" or "FOO" etc (Core upgrade).
* Adding an index to a Mixed property on a non-empty table would crash with an assertion (Core upgrade).
* `SyncSession.pause()` could hold a reference to the database open after shutting down the sync session, preventing users from being able to delete the realm (Core upgrade).

* Fix a stack overflow crash when using the query parser with long chains of AND/OR conditions. (Core upgrade)
* `SyncManager::immediately_run_file_actions()` no longer ignores the result of trying to remove a realm. This could have resulted in a client reset action being reported as successful when it actually failed on windows if the `Realm` was still open (Core upgrade).
* Fix a data race. If one thread committed a write transaction which increased the number of live versions above the previous highest seen during the current session at the same time as another thread began a read, the reading thread could read from a no-longer-valid memory mapping (Core upgrade).

* Fixed a crash or exception when doing a fulltext search for multiple keywords when the intersection of results is not equal. (Core upgrade).

* Don't report non ssl related errors during ssl handshake as fatal in default socket provider. (Core upgrade)

* Performing a query like "{1, 2, 3, ...} IN list" where the array is longer than 8 and all elements are smaller than some values in list, the program would crash (Core upgrade)
* Performing a large number of queries without ever performing a write resulted in steadily increasing memory usage, some of which was never fully freed due to an unbounded cache (Core upgrade)

* Exclusion of words in a full text search does not work (Core upgrade)

* Fixed a fatal error (reported to the sync error handler) during client reset (or automatic PBS to FLX migration) if the reset has been triggered during an async open and the schema being applied has added new classes. (Core upgrade), since automatic client resets were introduced in v11.5.0)
* Full text search would sometimes find words where the word only matches the beginning of the search token (Core upgrade)

* We could crash when removing backlinks in cases where forward links did not have a corresponding backlink due to corruption. We now silently ignore this inconsistency in release builds, allowing the app to continue. (Core upgrade)
* If you freeze a Results based on a collection of objects, the result would be invalid if you delete the collection (Core upgrade)

### Compatibility
* Fileformat: Generates files with format v23. Reads and automatically upgrade from fileformat v5.
* Realm Studio: 13.0.0 or later.
* Dart >=2.17.5 <4.0.0 (Flutter >=3.0.3) on Android, iOS, Linux, MacOS and Windows

### Internal
* Using Core 13.8.0.
* Using Core 13.12.0.
* Lock file format: New format introduced for multi-process encryption. All processes accessing the file must be upgraded to the new format.

## 1.0.3 (2023-03-20)

Expand All @@ -36,7 +67,6 @@
* Added `SyncWebSocketError` and `SyncWebSocketErrorCode` for web socket connection sync errors ([#1182](https://github.com/realm/realm-dart/pull/1182)).
* Added `FlexibleSyncConfiguration.shouldCompactCallback` support ([#1204](https://github.com/realm/realm-dart/pull/1204)).
* Added `RealmSet.asResults()` ([#1214](https://github.com/realm/realm-dart/pull/1214)).
* Support `Decimal128` datatype ([#1192](https://github.com/realm/realm-dart/pull/1192)).

### Fixed
* You may have a crash on Windows if you try to open a file with non-ASCII path (Core upgrade).
Expand Down
105 changes: 34 additions & 71 deletions lib/src/native/realm_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,15 @@ class RealmLibrary {
///
/// @param serialized_ejson_args The arguments array to invoke the function with,
/// serialized as an Extended JSON string.
/// @param service_name The name of the remote service whose system function to call. Can be null,
/// in which case the called function is expected to be a user function.
/// @return true, if no error occurred.
bool realm_app_call_function(
ffi.Pointer<realm_app_t> arg0,
ffi.Pointer<realm_user_t> arg1,
ffi.Pointer<ffi.Char> function_name,
ffi.Pointer<ffi.Char> serialized_ejson_args,
ffi.Pointer<ffi.Char> service_name,
realm_return_string_func_t callback,
ffi.Pointer<ffi.Void> userdata,
realm_free_userdata_func_t userdata_free,
Expand All @@ -138,6 +141,7 @@ class RealmLibrary {
arg1,
function_name,
serialized_ejson_args,
service_name,
callback,
userdata,
userdata_free,
Expand All @@ -151,6 +155,7 @@ class RealmLibrary {
ffi.Pointer<realm_user_t>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Char>,
realm_return_string_func_t,
ffi.Pointer<ffi.Void>,
realm_free_userdata_func_t)>>('realm_app_call_function');
Expand All @@ -160,6 +165,7 @@ class RealmLibrary {
ffi.Pointer<realm_user_t>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Char>,
realm_return_string_func_t,
ffi.Pointer<ffi.Void>,
realm_free_userdata_func_t)>();
Expand Down Expand Up @@ -205,22 +211,22 @@ class RealmLibrary {
void Function(
ffi.Pointer<realm_app_config_t>, ffi.Pointer<ffi.Char>)>();

void realm_app_config_set_cpu_arch(
void realm_app_config_set_bundle_id(
ffi.Pointer<realm_app_config_t> config,
ffi.Pointer<ffi.Char> cpu_arch,
ffi.Pointer<ffi.Char> bundle_id,
) {
return _realm_app_config_set_cpu_arch(
return _realm_app_config_set_bundle_id(
config,
cpu_arch,
bundle_id,
);
}

late final _realm_app_config_set_cpu_archPtr = _lookup<
late final _realm_app_config_set_bundle_idPtr = _lookup<
ffi.NativeFunction<
ffi.Void Function(ffi.Pointer<realm_app_config_t>,
ffi.Pointer<ffi.Char>)>>('realm_app_config_set_cpu_arch');
late final _realm_app_config_set_cpu_arch =
_realm_app_config_set_cpu_archPtr.asFunction<
ffi.Pointer<ffi.Char>)>>('realm_app_config_set_bundle_id');
late final _realm_app_config_set_bundle_id =
_realm_app_config_set_bundle_idPtr.asFunction<
void Function(
ffi.Pointer<realm_app_config_t>, ffi.Pointer<ffi.Char>)>();

Expand Down Expand Up @@ -358,25 +364,6 @@ class RealmLibrary {
void Function(
ffi.Pointer<realm_app_config_t>, ffi.Pointer<ffi.Char>)>();

void realm_app_config_set_platform(
ffi.Pointer<realm_app_config_t> arg0,
ffi.Pointer<ffi.Char> arg1,
) {
return _realm_app_config_set_platform(
arg0,
arg1,
);
}

late final _realm_app_config_set_platformPtr = _lookup<
ffi.NativeFunction<
ffi.Void Function(ffi.Pointer<realm_app_config_t>,
ffi.Pointer<ffi.Char>)>>('realm_app_config_set_platform');
late final _realm_app_config_set_platform =
_realm_app_config_set_platformPtr.asFunction<
void Function(
ffi.Pointer<realm_app_config_t>, ffi.Pointer<ffi.Char>)>();

void realm_app_config_set_platform_version(
ffi.Pointer<realm_app_config_t> arg0,
ffi.Pointer<ffi.Char> arg1,
Expand Down Expand Up @@ -1007,30 +994,6 @@ class RealmLibrary {
ffi.Pointer<ffi.Void>,
realm_free_userdata_func_t)>();

/// @note this API will be removed and it is now deprecated in favour of realm_app_create
///
/// Get an existing @a realm_app_t* instance with the same app id, or create it with the
/// configuration if it doesn't exist.
///
/// @return A non-null pointer if no error occurred.
ffi.Pointer<realm_app_t> realm_app_get(
ffi.Pointer<realm_app_config_t> arg0,
ffi.Pointer<realm_sync_client_config_t> arg1,
) {
return _realm_app_get(
arg0,
arg1,
);
}

late final _realm_app_getPtr = _lookup<
ffi.NativeFunction<
ffi.Pointer<realm_app_t> Function(ffi.Pointer<realm_app_config_t>,
ffi.Pointer<realm_sync_client_config_t>)>>('realm_app_get');
late final _realm_app_get = _realm_app_getPtr.asFunction<
ffi.Pointer<realm_app_t> Function(ffi.Pointer<realm_app_config_t>,
ffi.Pointer<realm_sync_client_config_t>)>();

/// Get the list of active users in this @a app.
/// In case of errors this function will return false (errors to be fetched via `realm_get_last_error()`).
/// If data is not copied the function will return true and set `out_n` with the capacity needed.
Expand Down Expand Up @@ -1086,26 +1049,6 @@ class RealmLibrary {
late final _realm_app_get_app_id = _realm_app_get_app_idPtr
.asFunction<ffi.Pointer<ffi.Char> Function(ffi.Pointer<realm_app_t>)>();

/// @note this API will be removed and it is now deprecated in favour of realm_app_create
///
/// Get an existing @a realm_app_t* instance from the cache.
///
/// @return Cached app instance, or null if no cached app exists for this @a app_id.
ffi.Pointer<realm_app_t> realm_app_get_cached(
ffi.Pointer<ffi.Char> app_id,
) {
return _realm_app_get_cached(
app_id,
);
}

late final _realm_app_get_cachedPtr = _lookup<
ffi.NativeFunction<
ffi.Pointer<realm_app_t> Function(
ffi.Pointer<ffi.Char>)>>('realm_app_get_cached');
late final _realm_app_get_cached = _realm_app_get_cachedPtr
.asFunction<ffi.Pointer<realm_app_t> Function(ffi.Pointer<ffi.Char>)>();

ffi.Pointer<realm_user_t> realm_app_get_current_user(
ffi.Pointer<realm_app_t> arg0,
) {
Expand Down Expand Up @@ -7786,6 +7729,25 @@ class RealmLibrary {
ffi.Pointer<realm_object_t> Function(
ffi.Pointer<realm_results_t>, int)>();

/// Return the query associated to the results passed as argument.
///
/// @param results the ptr to a valid results object.
/// @return a valid ptr to realm_query_t if no error has occured
ffi.Pointer<realm_query_t> realm_results_get_query(
ffi.Pointer<realm_results_t> results,
) {
return _realm_results_get_query(
results,
);
}

late final _realm_results_get_queryPtr = _lookup<
ffi.NativeFunction<
ffi.Pointer<realm_query_t> Function(
ffi.Pointer<realm_results_t>)>>('realm_results_get_query');
late final _realm_results_get_query = _realm_results_get_queryPtr.asFunction<
ffi.Pointer<realm_query_t> Function(ffi.Pointer<realm_results_t>)>();

/// Set the boolean passed as argument to true or false whether the realm_results passed is valid or not
/// @return true/false if no exception has occured.
bool realm_results_is_valid(
Expand Down Expand Up @@ -11406,6 +11368,7 @@ abstract class realm_errno {
static const int RLM_ERR_APP_UNKNOWN = 4351;
static const int RLM_ERR_MAINTENANCE_IN_PROGRESS = 4352;
static const int RLM_ERR_USERPASS_TOKEN_INVALID = 4353;
static const int RLM_ERR_INVALID_SERVER_RESPONSE = 4354;
static const int RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR = 4400;
static const int RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR = 4401;
static const int RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR = 4402;
Expand Down
8 changes: 5 additions & 3 deletions lib/src/native/realm_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1472,14 +1472,11 @@ class _RealmCore {
final app_id = configuration.appId.toCharPtr(arena);
final handle = AppConfigHandle._(_realmLib.realm_app_config_new(app_id, httpTransport._pointer));

_realmLib.realm_app_config_set_platform(handle._pointer, Platform.operatingSystem.toCharPtr(arena));
_realmLib.realm_app_config_set_platform_version(handle._pointer, Platform.operatingSystemVersion.toCharPtr(arena));

_realmLib.realm_app_config_set_sdk(handle._pointer, 'Dart'.toCharPtr(arena));
_realmLib.realm_app_config_set_sdk_version(handle._pointer, libraryVersion.toCharPtr(arena));

_realmLib.realm_app_config_set_cpu_arch(handle._pointer, getRealmLibraryCpuArchitecture().toCharPtr(arena));

final deviceName = getDeviceName();
_realmLib.realm_app_config_set_device_name(handle._pointer, deviceName.toCharPtr(arena));

Expand Down Expand Up @@ -1709,6 +1706,10 @@ class _RealmCore {
return using((arena) {
final handle = SyncClientConfigHandle._(_realmLib.realm_sync_client_config_new());

// TODO: Remove later
// Disable multiplexing for now due to: https://github.com/realm/realm-core/issues/6656
_realmLib.realm_sync_client_config_set_multiplex_sessions(handle._pointer, false);
// <-- end
_realmLib.realm_sync_client_config_set_base_file_path(handle._pointer, configuration.baseFilePath.path.toCharPtr(arena));
_realmLib.realm_sync_client_config_set_metadata_mode(handle._pointer, configuration.metadataPersistenceMode.index);
_realmLib.realm_sync_client_config_set_connect_timeout(handle._pointer, configuration.maxConnectionTimeout.inMilliseconds);
Expand Down Expand Up @@ -2473,6 +2474,7 @@ class _RealmCore {
user.handle._pointer,
functionName.toCharPtr(arena),
argsAsJSON?.toCharPtr(arena) ?? nullptr,
nullptr,
Pointer.fromFunction(_call_app_function_callback),
completer.toPersistentHandle(),
_realmLib.addresses.realm_dart_delete_persistent_handle,
Expand Down
2 changes: 1 addition & 1 deletion src/realm-core
Submodule realm-core updated 327 files
14 changes: 7 additions & 7 deletions test/realm_logger_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class LoggedMessage {

const LoggedMessage(this.level, this.message);

factory LoggedMessage.empty() => LoggedMessage(RealmLogLevel.off, "");
factory LoggedMessage.empty() => const LoggedMessage(RealmLogLevel.off, "");

@override
// ignore: hash_and_equals
Expand Down Expand Up @@ -107,7 +107,7 @@ Future<void> main([List<String>? args]) async {
openARealm();
result.add(await completer.future);

Realm.logger.level = RealmLogLevel.info;
Realm.logger.level = RealmLogLevel.trace;
completer = Completer<LoggedMessage>();
openARealm();
result.add(await completer.future);
Expand All @@ -123,7 +123,7 @@ Future<void> main([List<String>? args]) async {

expect(actual[0].level, RealmLogLevel.trace);
expect(actual[1].level, RealmLogLevel.debug);
expect(actual[2].level, RealmLogLevel.info);
expect(actual[2].level, RealmLogLevel.trace);
expect(actual[3].level, RealmLogLevel.debug);
});

Expand Down Expand Up @@ -213,9 +213,9 @@ Future<void> main([List<String>? args]) async {

//first isolate should have collected all the messages
expect(actual.length, 4);
expect(actual[0], LoggedMessage(RealmLogLevel.error, "2"));
expect(actual[1], LoggedMessage(RealmLogLevel.error, "2"));
expect(actual[2], LoggedMessage(RealmLogLevel.error, "first only"));
expect(actual[3], LoggedMessage(RealmLogLevel.trace, "3"));
expect(actual[0], const LoggedMessage(RealmLogLevel.error, "2"));
expect(actual[1], const LoggedMessage(RealmLogLevel.error, "2"));
expect(actual[2], const LoggedMessage(RealmLogLevel.error, "first only"));
expect(actual[3], const LoggedMessage(RealmLogLevel.trace, "3"));
});
}