Skip to content

Commit a6c5571

Browse files
author
Dominic Frei
authored
Fix TableKey / ObjKey conversion on Android x86 (#2477)
1 parent 4f2772a commit a6c5571

File tree

8 files changed

+46
-67
lines changed

8 files changed

+46
-67
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@
44
* \[Unity\] Fixed an issue where failing to weave an assembly due to modeling errors, would only show an error in the logs once and then fail opening a Realm with `No RealmObjects. Has linker stripped them?`. Now, the weaving errors will show up on every code change/weave attempt and the runtime error will explicitly suggest manually re-running the weaver. (Issue [#2310](https://github.com/realm/realm-dotnet/issues/2310))
55
* \[Unity\] Fixed an issue that would cause the app to hang on exit when using Sync. (PR [#2467](https://github.com/realm/realm-dotnet/pull/2467))
66
* \[Unity\] Fixed an issue that would cause the Unity editor on macOS to hang after assembly reload if the app uses Sync. (Issue [#2482](https://github.com/realm/realm-dotnet/issues/2482))
7+
* Fixed an issue where a crash could happen on Android x86 due to converting UInt32 into TableKey and Int64 into ObjKey incorrectly. (Issue [#2456](https://github.com/realm/realm-dotnet/issues/2456))
78

89
### Enhancements
910
* None
1011

1112
### Compatibility
12-
* Realm Studio: 11.0.0-alpha.0 or later.
13+
* Realm Studio: 11.0.0 or later.
1314

1415
### Internal
1516
* Using Core 11.0.3.
17+
* GetHashCode() on objects now uses the table key in addition to the object key. (Issue [#2473](https://github.com/realm/realm-dotnet/issues/2473))
1618

1719
## 10.2.0 (2021-06-15)
1820

Realm/Realm/DatabaseTypes/RealmObjectBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ internal void SetOwner(Realm realm, ObjectHandle objectHandle, Metadata metadata
195195
_realm = realm;
196196
_objectHandle = objectHandle;
197197
_metadata = metadata;
198-
_hashCode = new Lazy<int>(() => _objectHandle.GetObjKey().GetHashCode());
198+
_hashCode = new Lazy<int>(() => _objectHandle.GetObjHash());
199199

200200
if (_propertyChanged != null)
201201
{

Realm/Realm/Handles/ObjectHandle.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ internal class ObjectHandle : NotifiableObjectHandleBase
2929
private static class NativeMethods
3030
{
3131
#pragma warning disable IDE1006 // Naming Styles
32+
#pragma warning disable IDE0049 // Naming Styles
3233
#pragma warning disable SA1121 // Use built-in type alias
3334

3435
[DllImport(InteropConfig.DLL_NAME, EntryPoint = "object_get_is_valid", CallingConvention = CallingConvention.Cdecl)]
@@ -66,8 +67,8 @@ private static class NativeMethods
6667
[return: MarshalAs(UnmanagedType.U1)]
6768
public static extern bool equals_object(ObjectHandle handle, ObjectHandle otherHandle, out NativeException ex);
6869

69-
[DllImport(InteropConfig.DLL_NAME, EntryPoint = "object_get_obj_key", CallingConvention = CallingConvention.Cdecl)]
70-
public static extern ObjKey get_obj_key(ObjectHandle handle, out NativeException ex);
70+
[DllImport(InteropConfig.DLL_NAME, EntryPoint = "object_get_hashcode", CallingConvention = CallingConvention.Cdecl)]
71+
public static extern Int32 get_hashcode(ObjectHandle handle, out NativeException ex);
7172

7273
[DllImport(InteropConfig.DLL_NAME, EntryPoint = "object_get_backlinks", CallingConvention = CallingConvention.Cdecl)]
7374
public static extern IntPtr get_backlinks(ObjectHandle objectHandle, IntPtr property_index, out NativeException nativeException);
@@ -95,6 +96,7 @@ private static class NativeMethods
9596
public static extern void get_schema(ObjectHandle objectHandle, IntPtr callback, out NativeException ex);
9697

9798
#pragma warning restore SA1121 // Use built-in type alias
99+
#pragma warning restore IDE0049 // Naming Styles
98100
#pragma warning restore IDE1006 // Naming Styles
99101
}
100102

@@ -138,9 +140,9 @@ public override bool Equals(object obj)
138140
return result;
139141
}
140142

141-
public ObjKey GetObjKey()
143+
public int GetObjHash()
142144
{
143-
var result = NativeMethods.get_obj_key(this, out var nativeException);
145+
var result = NativeMethods.get_hashcode(this, out var nativeException);
144146
nativeException.ThrowIfNecessary();
145147

146148
return result;

Realm/Realm/Handles/SharedRealmHandle.cs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ internal class SharedRealmHandle : RealmHandle
3636
private static class NativeMethods
3737
{
3838
#pragma warning disable IDE1006 // Naming Styles
39+
#pragma warning disable SA1121 // Use built-in type alias
3940

4041
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
4142
public delegate void NotifyRealmCallback(IntPtr stateHandle);
@@ -118,7 +119,7 @@ public static extern IntPtr open_with_sync_async(Configuration configuration, Sy
118119
public static extern bool refresh(SharedRealmHandle sharedRealm, out NativeException ex);
119120

120121
[DllImport(InteropConfig.DLL_NAME, EntryPoint = "shared_realm_get_table_key", CallingConvention = CallingConvention.Cdecl)]
121-
public static extern TableKey get_table_key(SharedRealmHandle sharedRealm, [MarshalAs(UnmanagedType.LPWStr)] string tableName, IntPtr tableNameLength, out NativeException ex);
122+
public static extern UInt32 get_table_key(SharedRealmHandle sharedRealm, [MarshalAs(UnmanagedType.LPWStr)] string tableName, IntPtr tableNameLength, out NativeException ex);
122123

123124
[DllImport(InteropConfig.DLL_NAME, EntryPoint = "shared_realm_is_same_instance", CallingConvention = CallingConvention.Cdecl)]
124125
[return: MarshalAs(UnmanagedType.U1)]
@@ -141,10 +142,10 @@ public static extern IntPtr open_with_sync_async(Configuration configuration, Sy
141142
public static extern void write_copy(SharedRealmHandle sharedRealm, [MarshalAs(UnmanagedType.LPWStr)] string path, IntPtr path_len, byte[] encryptionKey, out NativeException ex);
142143

143144
[DllImport(InteropConfig.DLL_NAME, EntryPoint = "shared_realm_create_object", CallingConvention = CallingConvention.Cdecl)]
144-
public static extern IntPtr create_object(SharedRealmHandle sharedRealm, TableKey table_key, out NativeException ex);
145+
public static extern IntPtr create_object(SharedRealmHandle sharedRealm, UInt32 table_key, out NativeException ex);
145146

146147
[DllImport(InteropConfig.DLL_NAME, EntryPoint = "shared_realm_create_object_unique", CallingConvention = CallingConvention.Cdecl)]
147-
public static extern IntPtr create_object_unique(SharedRealmHandle sharedRealm, TableKey table_key, PrimitiveValue value,
148+
public static extern IntPtr create_object_unique(SharedRealmHandle sharedRealm, UInt32 table_key, PrimitiveValue value,
148149
[MarshalAs(UnmanagedType.U1)] bool update,
149150
[MarshalAs(UnmanagedType.U1)] out bool is_new, out NativeException ex);
150151

@@ -175,11 +176,12 @@ public static extern void install_callbacks(
175176
public static extern IntPtr freeze(SharedRealmHandle sharedRealm, out NativeException ex);
176177

177178
[DllImport(InteropConfig.DLL_NAME, EntryPoint = "shared_realm_get_object_for_primary_key", CallingConvention = CallingConvention.Cdecl)]
178-
public static extern IntPtr get_object_for_primary_key(SharedRealmHandle realmHandle, TableKey table_key, PrimitiveValue value, out NativeException ex);
179+
public static extern IntPtr get_object_for_primary_key(SharedRealmHandle realmHandle, UInt32 table_key, PrimitiveValue value, out NativeException ex);
179180

180181
[DllImport(InteropConfig.DLL_NAME, EntryPoint = "shared_realm_create_results", CallingConvention = CallingConvention.Cdecl)]
181-
public static extern IntPtr create_results(SharedRealmHandle sharedRealm, TableKey table_key, out NativeException ex);
182+
public static extern IntPtr create_results(SharedRealmHandle sharedRealm, UInt32 table_key, out NativeException ex);
182183

184+
#pragma warning restore SA1121 // Use built-in type alias
183185
#pragma warning restore IDE1006 // Naming Styles
184186
}
185187

@@ -340,7 +342,7 @@ public TableKey GetTableKey(string tableName)
340342
{
341343
var tableKey = NativeMethods.get_table_key(this, tableName, (IntPtr)tableName.Length, out var nativeException);
342344
nativeException.ThrowIfNecessary();
343-
return tableKey;
345+
return new TableKey(tableKey);
344346
}
345347

346348
public bool IsSameInstance(SharedRealmHandle other)
@@ -405,7 +407,7 @@ public RealmSchema GetSchema()
405407

406408
public ObjectHandle CreateObject(TableKey tableKey)
407409
{
408-
var result = NativeMethods.create_object(this, tableKey, out NativeException ex);
410+
var result = NativeMethods.create_object(this, tableKey.Value, out NativeException ex);
409411
ex.ThrowIfNecessary();
410412
return new ObjectHandle(this, result);
411413
}
@@ -427,7 +429,7 @@ public ObjectHandle CreateObjectWithPrimaryKey(Property pkProperty, object prima
427429
};
428430

429431
var (primitiveValue, handles) = pkValue.ToNative();
430-
var result = NativeMethods.create_object_unique(this, tableKey, primitiveValue, update, out isNew, out var ex);
432+
var result = NativeMethods.create_object_unique(this, tableKey.Value, primitiveValue, update, out isNew, out var ex);
431433
handles?.Dispose();
432434
ex.ThrowIfNecessary();
433435
return new ObjectHandle(this, result);
@@ -448,7 +450,7 @@ public SharedRealmHandle Freeze()
448450
public bool TryFindObject(TableKey tableKey, in RealmValue id, out ObjectHandle objectHandle)
449451
{
450452
var (primitiveValue, handles) = id.ToNative();
451-
var result = NativeMethods.get_object_for_primary_key(this, tableKey, primitiveValue, out var ex);
453+
var result = NativeMethods.get_object_for_primary_key(this, tableKey.Value, primitiveValue, out var ex);
452454
handles?.Dispose();
453455
ex.ThrowIfNecessary();
454456

@@ -464,7 +466,7 @@ public bool TryFindObject(TableKey tableKey, in RealmValue id, out ObjectHandle
464466

465467
public ResultsHandle CreateResults(TableKey tableKey)
466468
{
467-
var result = NativeMethods.create_results(this, tableKey, out var nativeException);
469+
var result = NativeMethods.create_results(this, tableKey.Value, out var nativeException);
468470
nativeException.ThrowIfNecessary();
469471
return new ResultsHandle(this, result);
470472
}

Realm/Realm/Handles/SortDescriptorHandle.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,18 @@ internal class SortDescriptorHandle : RealmHandle
2626
{
2727
private static class NativeMethods
2828
{
29+
#pragma warning disable SA1121 // Use built-in type alias
30+
2931
[DllImport(InteropConfig.DLL_NAME, EntryPoint = "sort_descriptor_destroy", CallingConvention = CallingConvention.Cdecl)]
3032
public static extern void destroy(IntPtr queryHandle);
3133

3234
[DllImport(InteropConfig.DLL_NAME, EntryPoint = "sort_descriptor_add_clause", CallingConvention = CallingConvention.Cdecl)]
33-
public static extern void add_clause(SortDescriptorHandle descriptor, TableKey table_key, SharedRealmHandle realm,
35+
public static extern void add_clause(SortDescriptorHandle descriptor, UInt32 table_key, SharedRealmHandle realm,
3436
[MarshalAs(UnmanagedType.LPArray), In] IntPtr[] property_index_chain, IntPtr column_keys_count,
3537
[MarshalAs(UnmanagedType.U1)] bool ascending, [MarshalAs(UnmanagedType.U1)] bool replacing,
3638
out NativeException ex);
39+
40+
#pragma warning restore SA1121 // Use built-in type alias
3741
}
3842

3943
public SortDescriptorHandle(RealmHandle root, IntPtr handle) : base(root, handle)
@@ -42,7 +46,7 @@ public SortDescriptorHandle(RealmHandle root, IntPtr handle) : base(root, handle
4246

4347
public void AddClause(SharedRealmHandle realm, TableKey tableKey, IntPtr[] propertyIndexChain, bool ascending, bool replacing)
4448
{
45-
NativeMethods.add_clause(this, tableKey, realm, propertyIndexChain, (IntPtr)propertyIndexChain.Length, ascending, replacing, out var nativeException);
49+
NativeMethods.add_clause(this, tableKey.Value, realm, propertyIndexChain, (IntPtr)propertyIndexChain.Length, ascending, replacing, out var nativeException);
4650
nativeException.ThrowIfNecessary();
4751
}
4852

Realm/Realm/Native/ObjKey.cs

Lines changed: 0 additions & 39 deletions
This file was deleted.

Realm/Realm/Native/TableKey.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,26 @@
1717
////////////////////////////////////////////////////////////////////////////
1818

1919
using System;
20-
using System.Runtime.InteropServices;
2120

2221
namespace Realms.Native
2322
{
24-
[StructLayout(LayoutKind.Sequential)]
2523
internal struct TableKey : IEquatable<TableKey>
2624
{
27-
private UInt32 value;
25+
public readonly UInt32 Value;
2826

29-
public bool Equals(TableKey other) => value.Equals(other.value);
27+
public TableKey(UInt32 value)
28+
{
29+
Value = value;
30+
}
31+
32+
public bool Equals(TableKey other) => Value.Equals(other.Value);
3033

3134
public override bool Equals(object obj) => obj is TableKey other && Equals(other);
3235

33-
public override int GetHashCode() => value.GetHashCode();
36+
public override int GetHashCode() => Value.GetHashCode();
3437

35-
public static bool operator ==(TableKey left, TableKey right) => left.value == right.value;
38+
public static bool operator ==(TableKey left, TableKey right) => left.Value == right.Value;
3639

37-
public static bool operator !=(TableKey left, TableKey right) => left.value != right.value;
40+
public static bool operator !=(TableKey left, TableKey right) => left.Value != right.Value;
3841
}
3942
}

wrappers/src/object_cs.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,16 @@ extern "C" {
241241
});
242242
}
243243

244-
REALM_EXPORT int64_t object_get_obj_key(const Object& object, NativeException::Marshallable& ex)
244+
REALM_EXPORT int32_t object_get_hashcode(const Object& object, NativeException::Marshallable& ex)
245245
{
246246
return handle_errors(ex, [&]() {
247-
// ObjKey is incompatible with C, so we return just the value.
248-
return object.obj().get_key().value;
247+
int32_t table_key_value = static_cast<int32_t>(object.obj().get_table()->get_key().value);
248+
int32_t object_key_value = static_cast<int32_t>(object.obj().get_key().value);
249+
250+
int32_t hashCode = -986587137;
251+
hashCode = (hashCode * -1521134295) + table_key_value;
252+
hashCode = (hashCode * -1521134295) + object_key_value;
253+
return hashCode;
249254
});
250255
}
251256

0 commit comments

Comments
 (0)