Skip to content

Commit

Permalink
Fix TableKey / ObjKey conversion on Android x86 (#2477)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dominic Frei authored Jun 30, 2021
1 parent 4f2772a commit a6c5571
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 67 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@
* \[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))
* \[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))
* \[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))
* 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))

### Enhancements
* None

### Compatibility
* Realm Studio: 11.0.0-alpha.0 or later.
* Realm Studio: 11.0.0 or later.

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

## 10.2.0 (2021-06-15)

Expand Down
2 changes: 1 addition & 1 deletion Realm/Realm/DatabaseTypes/RealmObjectBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ internal void SetOwner(Realm realm, ObjectHandle objectHandle, Metadata metadata
_realm = realm;
_objectHandle = objectHandle;
_metadata = metadata;
_hashCode = new Lazy<int>(() => _objectHandle.GetObjKey().GetHashCode());
_hashCode = new Lazy<int>(() => _objectHandle.GetObjHash());

if (_propertyChanged != null)
{
Expand Down
10 changes: 6 additions & 4 deletions Realm/Realm/Handles/ObjectHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ internal class ObjectHandle : NotifiableObjectHandleBase
private static class NativeMethods
{
#pragma warning disable IDE1006 // Naming Styles
#pragma warning disable IDE0049 // Naming Styles
#pragma warning disable SA1121 // Use built-in type alias

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

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

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

#pragma warning restore SA1121 // Use built-in type alias
#pragma warning restore IDE0049 // Naming Styles
#pragma warning restore IDE1006 // Naming Styles
}

Expand Down Expand Up @@ -138,9 +140,9 @@ public override bool Equals(object obj)
return result;
}

public ObjKey GetObjKey()
public int GetObjHash()
{
var result = NativeMethods.get_obj_key(this, out var nativeException);
var result = NativeMethods.get_hashcode(this, out var nativeException);
nativeException.ThrowIfNecessary();

return result;
Expand Down
22 changes: 12 additions & 10 deletions Realm/Realm/Handles/SharedRealmHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ internal class SharedRealmHandle : RealmHandle
private static class NativeMethods
{
#pragma warning disable IDE1006 // Naming Styles
#pragma warning disable SA1121 // Use built-in type alias

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

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

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

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

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

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

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

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

#pragma warning restore SA1121 // Use built-in type alias
#pragma warning restore IDE1006 // Naming Styles
}

Expand Down Expand Up @@ -340,7 +342,7 @@ public TableKey GetTableKey(string tableName)
{
var tableKey = NativeMethods.get_table_key(this, tableName, (IntPtr)tableName.Length, out var nativeException);
nativeException.ThrowIfNecessary();
return tableKey;
return new TableKey(tableKey);
}

public bool IsSameInstance(SharedRealmHandle other)
Expand Down Expand Up @@ -405,7 +407,7 @@ public RealmSchema GetSchema()

public ObjectHandle CreateObject(TableKey tableKey)
{
var result = NativeMethods.create_object(this, tableKey, out NativeException ex);
var result = NativeMethods.create_object(this, tableKey.Value, out NativeException ex);
ex.ThrowIfNecessary();
return new ObjectHandle(this, result);
}
Expand All @@ -427,7 +429,7 @@ public ObjectHandle CreateObjectWithPrimaryKey(Property pkProperty, object prima
};

var (primitiveValue, handles) = pkValue.ToNative();
var result = NativeMethods.create_object_unique(this, tableKey, primitiveValue, update, out isNew, out var ex);
var result = NativeMethods.create_object_unique(this, tableKey.Value, primitiveValue, update, out isNew, out var ex);
handles?.Dispose();
ex.ThrowIfNecessary();
return new ObjectHandle(this, result);
Expand All @@ -448,7 +450,7 @@ public SharedRealmHandle Freeze()
public bool TryFindObject(TableKey tableKey, in RealmValue id, out ObjectHandle objectHandle)
{
var (primitiveValue, handles) = id.ToNative();
var result = NativeMethods.get_object_for_primary_key(this, tableKey, primitiveValue, out var ex);
var result = NativeMethods.get_object_for_primary_key(this, tableKey.Value, primitiveValue, out var ex);
handles?.Dispose();
ex.ThrowIfNecessary();

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

public ResultsHandle CreateResults(TableKey tableKey)
{
var result = NativeMethods.create_results(this, tableKey, out var nativeException);
var result = NativeMethods.create_results(this, tableKey.Value, out var nativeException);
nativeException.ThrowIfNecessary();
return new ResultsHandle(this, result);
}
Expand Down
8 changes: 6 additions & 2 deletions Realm/Realm/Handles/SortDescriptorHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,18 @@ internal class SortDescriptorHandle : RealmHandle
{
private static class NativeMethods
{
#pragma warning disable SA1121 // Use built-in type alias

[DllImport(InteropConfig.DLL_NAME, EntryPoint = "sort_descriptor_destroy", CallingConvention = CallingConvention.Cdecl)]
public static extern void destroy(IntPtr queryHandle);

[DllImport(InteropConfig.DLL_NAME, EntryPoint = "sort_descriptor_add_clause", CallingConvention = CallingConvention.Cdecl)]
public static extern void add_clause(SortDescriptorHandle descriptor, TableKey table_key, SharedRealmHandle realm,
public static extern void add_clause(SortDescriptorHandle descriptor, UInt32 table_key, SharedRealmHandle realm,
[MarshalAs(UnmanagedType.LPArray), In] IntPtr[] property_index_chain, IntPtr column_keys_count,
[MarshalAs(UnmanagedType.U1)] bool ascending, [MarshalAs(UnmanagedType.U1)] bool replacing,
out NativeException ex);

#pragma warning restore SA1121 // Use built-in type alias
}

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

public void AddClause(SharedRealmHandle realm, TableKey tableKey, IntPtr[] propertyIndexChain, bool ascending, bool replacing)
{
NativeMethods.add_clause(this, tableKey, realm, propertyIndexChain, (IntPtr)propertyIndexChain.Length, ascending, replacing, out var nativeException);
NativeMethods.add_clause(this, tableKey.Value, realm, propertyIndexChain, (IntPtr)propertyIndexChain.Length, ascending, replacing, out var nativeException);
nativeException.ThrowIfNecessary();
}

Expand Down
39 changes: 0 additions & 39 deletions Realm/Realm/Native/ObjKey.cs

This file was deleted.

17 changes: 10 additions & 7 deletions Realm/Realm/Native/TableKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,26 @@
////////////////////////////////////////////////////////////////////////////

using System;
using System.Runtime.InteropServices;

namespace Realms.Native
{
[StructLayout(LayoutKind.Sequential)]
internal struct TableKey : IEquatable<TableKey>
{
private UInt32 value;
public readonly UInt32 Value;

public bool Equals(TableKey other) => value.Equals(other.value);
public TableKey(UInt32 value)
{
Value = value;
}

public bool Equals(TableKey other) => Value.Equals(other.Value);

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

public override int GetHashCode() => value.GetHashCode();
public override int GetHashCode() => Value.GetHashCode();

public static bool operator ==(TableKey left, TableKey right) => left.value == right.value;
public static bool operator ==(TableKey left, TableKey right) => left.Value == right.Value;

public static bool operator !=(TableKey left, TableKey right) => left.value != right.value;
public static bool operator !=(TableKey left, TableKey right) => left.Value != right.Value;
}
}
11 changes: 8 additions & 3 deletions wrappers/src/object_cs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,16 @@ extern "C" {
});
}

REALM_EXPORT int64_t object_get_obj_key(const Object& object, NativeException::Marshallable& ex)
REALM_EXPORT int32_t object_get_hashcode(const Object& object, NativeException::Marshallable& ex)
{
return handle_errors(ex, [&]() {
// ObjKey is incompatible with C, so we return just the value.
return object.obj().get_key().value;
int32_t table_key_value = static_cast<int32_t>(object.obj().get_table()->get_key().value);
int32_t object_key_value = static_cast<int32_t>(object.obj().get_key().value);

int32_t hashCode = -986587137;
hashCode = (hashCode * -1521134295) + table_key_value;
hashCode = (hashCode * -1521134295) + object_key_value;
return hashCode;
});
}

Expand Down

0 comments on commit a6c5571

Please sign in to comment.