Skip to content

Commit ac22a23

Browse files
committed
Merge branch 'master' of github.com:realm/realm-core into next-major
2 parents 16c1441 + 7c31f5d commit ac22a23

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1212
-837
lines changed

evergreen/config.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,15 @@ buildvariants:
14481448
tasks:
14491449
- name: compile_local_tests
14501450

1451+
- name: ubuntu-2404-GCC
1452+
display_name: "Ubuntu 24.04 arm64 (native GCC)"
1453+
run_on: ubuntu2404-arm64-large
1454+
expansions:
1455+
fetch_missing_dependencies: On
1456+
disable_tests_against_baas: On
1457+
tasks:
1458+
- name: compile_local_tests
1459+
14511460
- name: ubuntu-encryption-tsan
14521461
display_name: "Ubuntu (Encryption Enabled w/TSAN)"
14531462
run_on: ubuntu2204-arm64-small
@@ -1496,7 +1505,7 @@ buildvariants:
14961505
- name: generate-sync-corpus
14971506

14981507
- name: ubuntu2004-arm64
1499-
display_name: "Ubuntu 20.04 ARM64 (Clang 11 release benchmarks)"
1508+
display_name: "Ubuntu 20.04 ARM64 (GCC 9 release benchmarks)"
15001509
run_on: ubuntu2004-arm64-large
15011510
expansions:
15021511
cmake_url: "https://s3.amazonaws.com/static.realm.io/evergreen-assets/cmake-3.26.3-linux-aarch64.tar.gz"

src/external/s2/s2polygonbuilder.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,8 @@ S2Loop* S2PolygonBuilder::AssembleLoop(S2Point const& v0, S2Point const& v1,
180180
path.push_back(v1);
181181
index[v1] = 1;
182182
while (path.size() >= 2) {
183-
// Note that "v0" and "v1" become invalid if "path" is modified.
184-
S2Point const& v0 = path.end()[-2];
185-
S2Point const& v1 = path.end()[-1];
183+
S2Point const v0 = path.end()[-2];
184+
S2Point const v1 = path.end()[-1];
186185
S2Point v2;
187186
bool v2_found = false;
188187
EdgeSet::const_iterator candidates = edges_->find(v1);

src/realm/array_mixed.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ void ArrayMixed::move(ArrayMixed& dst, size_t ndx)
246246
{
247247
auto sz = size();
248248
size_t i = ndx;
249+
const size_t original_dst_size = dst.size();
249250
while (i < sz) {
250251
auto val = get(i++);
251252
dst.add(val);
@@ -256,7 +257,7 @@ void ArrayMixed::move(ArrayMixed& dst, size_t ndx)
256257
Array keys(Array::get_alloc());
257258
keys.set_parent(const_cast<ArrayMixed*>(this), payload_idx_key);
258259
keys.init_from_ref(ref);
259-
for (size_t j = 0, i = ndx; i < sz; i++, j++) {
260+
for (size_t j = original_dst_size, i = ndx; i < sz; i++, j++) {
260261
dst.set_key(j, keys.get(i));
261262
}
262263
keys.truncate(ndx);

src/realm/chunked_binary.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ bool ChunkedBinaryData::is_null() const
4545
return chunk.is_null();
4646
}
4747

48+
bool ChunkedBinaryData::empty() const
49+
{
50+
BinaryIterator copy = m_begin;
51+
BinaryData chunk = copy.get_next();
52+
return chunk.size() == 0;
53+
}
54+
4855
char ChunkedBinaryData::operator[](size_t index) const
4956
{
5057
BinaryIterator copy = m_begin;

src/realm/chunked_binary.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ class ChunkedBinaryData {
5454
/// the first chunk points to the nullptr.
5555
bool is_null() const;
5656

57+
/// Equivalent to `size() == 0`, but O(1) rather than O(N).
58+
bool empty() const;
59+
5760
/// FIXME: O(n)
5861
char operator[](size_t index) const;
5962

src/realm/cluster.cpp

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ const Table* ClusterNode::get_owning_table() const noexcept
8989

9090
void ClusterNode::get(ObjKey k, ClusterNode::State& state) const
9191
{
92-
if (!k || !try_get(k, state)) {
92+
if (!k || !try_get(RowKey(k), state)) {
9393
throw KeyNotFound(util::format("No object with key '%1' in '%2'", k.value, get_owning_table()->get_name()));
9494
}
9595
}
@@ -225,7 +225,7 @@ void Cluster::update_from_parent() noexcept
225225
}
226226
}
227227

228-
MemRef Cluster::ensure_writeable(ObjKey)
228+
MemRef Cluster::ensure_writeable(RowKey)
229229
{
230230
// By specifying the minimum size, we ensure that the array has a capacity
231231
// to hold m_size 64 bit refs.
@@ -234,7 +234,7 @@ MemRef Cluster::ensure_writeable(ObjKey)
234234
return get_mem();
235235
}
236236

237-
void Cluster::update_ref_in_parent(ObjKey, ref_type)
237+
void Cluster::update_ref_in_parent(RowKey, ref_type)
238238
{
239239
REALM_UNREACHABLE();
240240
}
@@ -343,13 +343,13 @@ inline void Cluster::do_insert_link(size_t ndx, ColKey col_key, Mixed init_val,
343343
}
344344
}
345345

346-
void Cluster::insert_row(size_t ndx, ObjKey k, const FieldValues& init_values)
346+
void Cluster::insert_row(size_t ndx, RowKey row_key, const FieldValues& init_values)
347347
{
348348
// Ensure the cluster array is big enough to hold 64 bit values.
349349
copy_on_write(m_size * 8);
350350

351351
if (m_keys.is_attached()) {
352-
m_keys.insert(ndx, k.value);
352+
m_keys.insert(ndx, row_key.value);
353353
}
354354
else {
355355
Array::set(s_key_ref_or_size_index, Array::get(s_key_ref_or_size_index) + 2); // Increments size by 1
@@ -377,6 +377,7 @@ void Cluster::insert_row(size_t ndx, ObjKey k, const FieldValues& init_values)
377377
}
378378

379379
bool nullable = attr.test(col_attr_Nullable);
380+
ObjKey obj_key(int64_t(row_key.value + get_offset()));
380381
switch (type) {
381382
case col_type_Int:
382383
if (attr.test(col_attr_Nullable)) {
@@ -402,7 +403,7 @@ void Cluster::insert_row(size_t ndx, ObjKey k, const FieldValues& init_values)
402403
do_insert_row<ArrayBinary>(ndx, col_key, init_value, nullable);
403404
break;
404405
case col_type_Mixed: {
405-
do_insert_mixed(ndx, col_key, init_value, ObjKey(k.value + get_offset()));
406+
do_insert_mixed(ndx, col_key, init_value, obj_key);
406407
break;
407408
}
408409
case col_type_Timestamp:
@@ -418,10 +419,10 @@ void Cluster::insert_row(size_t ndx, ObjKey k, const FieldValues& init_values)
418419
do_insert_row<ArrayUUIDNull>(ndx, col_key, init_value, nullable);
419420
break;
420421
case col_type_Link:
421-
do_insert_key(ndx, col_key, init_value, ObjKey(k.value + get_offset()));
422+
do_insert_key(ndx, col_key, init_value, obj_key);
422423
break;
423424
case col_type_TypedLink:
424-
do_insert_link(ndx, col_key, init_value, ObjKey(k.value + get_offset()));
425+
do_insert_link(ndx, col_key, init_value, obj_key);
425426
break;
426427
case col_type_BackLink: {
427428
ArrayBacklink arr(m_alloc);
@@ -664,7 +665,7 @@ void Cluster::remove_column(ColKey col_key)
664665
Array::set(idx, 0);
665666
}
666667

667-
ref_type Cluster::insert(ObjKey k, const FieldValues& init_values, ClusterNode::State& state)
668+
ref_type Cluster::insert(RowKey row_key, const FieldValues& init_values, ClusterNode::State& state)
668669
{
669670
int64_t current_key_value = -1;
670671
size_t sz;
@@ -673,34 +674,34 @@ ref_type Cluster::insert(ObjKey k, const FieldValues& init_values, ClusterNode::
673674

674675
auto on_error = [&] {
675676
throw KeyAlreadyUsed(
676-
util::format("When inserting key '%1' in '%2'", k.value, get_owning_table()->get_name()));
677+
util::format("When inserting key '%1' in '%2'", row_key.value, get_owning_table()->get_name()));
677678
};
678679

679680
if (m_keys.is_attached()) {
680681
sz = m_keys.size();
681-
ndx = m_keys.lower_bound(uint64_t(k.value));
682+
ndx = m_keys.lower_bound(row_key.value);
682683
if (ndx < sz) {
683684
current_key_value = m_keys.get(ndx);
684-
if (k.value == current_key_value) {
685+
if (row_key.value == uint64_t(current_key_value)) {
685686
on_error();
686687
}
687688
}
688689
}
689690
else {
690691
sz = size_t(Array::get(s_key_ref_or_size_index)) >> 1; // Size is stored as tagged integer
691-
if (uint64_t(k.value) < sz) {
692+
if (row_key.value < sz) {
692693
on_error();
693694
}
694695
// Key value is bigger than all other values, should be put last
695696
ndx = sz;
696-
if (uint64_t(k.value) > sz && sz < cluster_node_size) {
697+
if (row_key.value > sz && sz < cluster_node_size) {
697698
ensure_general_form();
698699
}
699700
}
700701

701702
REALM_ASSERT_DEBUG(sz <= cluster_node_size);
702703
if (REALM_LIKELY(sz < cluster_node_size)) {
703-
insert_row(ndx, k, init_values); // Throws
704+
insert_row(ndx, row_key, init_values); // Throws
704705
state.mem = get_mem();
705706
state.index = ndx;
706707
}
@@ -709,8 +710,8 @@ ref_type Cluster::insert(ObjKey k, const FieldValues& init_values, ClusterNode::
709710
Cluster new_leaf(0, m_alloc, m_tree_top);
710711
new_leaf.create();
711712
if (ndx == sz) {
712-
new_leaf.insert_row(0, ObjKey(0), init_values); // Throws
713-
state.split_key = k.value;
713+
new_leaf.insert_row(0, RowKey(0), init_values); // Throws
714+
state.split_key = int64_t(row_key.value);
714715
state.mem = new_leaf.get_mem();
715716
state.index = 0;
716717
}
@@ -719,7 +720,7 @@ ref_type Cluster::insert(ObjKey k, const FieldValues& init_values, ClusterNode::
719720
REALM_ASSERT_DEBUG(m_keys.is_attached());
720721
new_leaf.ensure_general_form();
721722
move(ndx, &new_leaf, current_key_value);
722-
insert_row(ndx, k, init_values); // Throws
723+
insert_row(ndx, row_key, init_values); // Throws
723724
state.mem = get_mem();
724725
state.split_key = current_key_value;
725726
state.index = ndx;
@@ -730,15 +731,15 @@ ref_type Cluster::insert(ObjKey k, const FieldValues& init_values, ClusterNode::
730731
return ret;
731732
}
732733

733-
bool Cluster::try_get(ObjKey k, ClusterNode::State& state) const noexcept
734+
bool Cluster::try_get(RowKey k, ClusterNode::State& state) const noexcept
734735
{
735736
state.mem = get_mem();
736737
if (m_keys.is_attached()) {
737-
state.index = m_keys.lower_bound(uint64_t(k.value));
738-
return state.index != m_keys.size() && m_keys.get(state.index) == uint64_t(k.value);
738+
state.index = m_keys.lower_bound(k.value);
739+
return state.index != m_keys.size() && m_keys.get(state.index) == k.value;
739740
}
740741
else {
741-
if (uint64_t(k.value) < uint64_t(Array::get(s_key_ref_or_size_index) >> 1)) {
742+
if (k.value < uint64_t(Array::get(s_key_ref_or_size_index) >> 1)) {
742743
state.index = size_t(k.value);
743744
return true;
744745
}
@@ -776,7 +777,7 @@ inline void Cluster::do_erase(size_t ndx, ColKey col_key)
776777
values.erase(ndx);
777778
}
778779

779-
inline void Cluster::do_erase_mixed(size_t ndx, ColKey col_key, ObjKey key, CascadeState& state)
780+
inline void Cluster::do_erase_mixed(size_t ndx, ColKey col_key, CascadeState& state)
780781
{
781782
const Table* origin_table = m_tree_top.get_owning_table();
782783
auto col_ndx = col_key.get_index();
@@ -788,19 +789,16 @@ inline void Cluster::do_erase_mixed(size_t ndx, ColKey col_key, ObjKey key, Casc
788789
Mixed value = values.get(ndx);
789790
if (value.is_type(type_TypedLink)) {
790791
ObjLink link = value.get<ObjLink>();
791-
auto target_obj = origin_table->get_parent_group()->get_object(link);
792-
793-
ColKey backlink_col_key = target_obj.get_table()->find_backlink_column(col_key, origin_table->get_key());
794-
REALM_ASSERT(backlink_col_key);
795-
target_obj.remove_one_backlink(backlink_col_key, get_real_key(ndx)); // Throws
792+
Obj obj(origin_table->m_own_ref, get_mem(), get_real_key(ndx), ndx);
793+
obj.remove_backlink(col_key, link, state);
796794
}
797795
if (value.is_type(type_List)) {
798-
Obj obj(origin_table->m_own_ref, get_mem(), key, ndx);
796+
Obj obj(origin_table->m_own_ref, get_mem(), get_real_key(ndx), ndx);
799797
Lst<Mixed> list(obj, col_key);
800798
list.remove_backlinks(state);
801799
}
802800
if (value.is_type(type_Dictionary)) {
803-
Obj obj(origin_table->m_own_ref, get_mem(), key, ndx);
801+
Obj obj(origin_table->m_own_ref, get_mem(), get_real_key(ndx), ndx);
804802
Dictionary dict(obj, col_key);
805803
dict.remove_backlinks(state);
806804
}
@@ -821,12 +819,12 @@ inline void Cluster::do_erase_key(size_t ndx, ColKey col_key, CascadeState& stat
821819
values.erase(ndx);
822820
}
823821

824-
size_t Cluster::get_ndx(ObjKey k, size_t ndx) const noexcept
822+
size_t Cluster::get_ndx(RowKey k, size_t ndx) const noexcept
825823
{
826824
size_t index;
827825
if (m_keys.is_attached()) {
828-
index = m_keys.lower_bound(uint64_t(k.value));
829-
if (index == m_keys.size() || m_keys.get(index) != uint64_t(k.value)) {
826+
index = m_keys.lower_bound(k.value);
827+
if (index == m_keys.size() || m_keys.get(index) != k.value) {
830828
return realm::npos;
831829
}
832830
}
@@ -839,11 +837,14 @@ size_t Cluster::get_ndx(ObjKey k, size_t ndx) const noexcept
839837
return index + ndx;
840838
}
841839

842-
size_t Cluster::erase(ObjKey key, CascadeState& state)
840+
size_t Cluster::erase(RowKey row_key, CascadeState& state)
843841
{
844-
size_t ndx = get_ndx(key, 0);
842+
size_t ndx = get_ndx(row_key, 0);
845843
if (ndx == realm::npos)
846-
throw KeyNotFound(util::format("When erasing key '%1' in '%2'", key.value, get_owning_table()->get_name()));
844+
throw KeyNotFound(util::format("When erasing key '%1' (offset '%2') in '%3'", row_key.value, m_offset,
845+
get_owning_table()->get_name()));
846+
847+
ObjKey real_key = get_real_key(ndx);
847848
std::vector<ColKey> backlink_column_keys;
848849

849850
auto erase_in_column = [&](ColKey col_key) {
@@ -860,7 +861,7 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
860861
const Table* origin_table = m_tree_top.get_owning_table();
861862
if (attr.test(col_attr_Dictionary)) {
862863
if (col_type == col_type_Mixed || col_type == col_type_Link) {
863-
Obj obj(origin_table->m_own_ref, get_mem(), key, ndx);
864+
Obj obj(origin_table->m_own_ref, get_mem(), real_key, ndx);
864865
Dictionary dict(obj, col_key);
865866
dict.remove_backlinks(state);
866867
}
@@ -869,7 +870,7 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
869870
BPlusTree<ObjKey> links(m_alloc);
870871
links.init_from_ref(ref);
871872
if (links.size() > 0) {
872-
do_remove_backlinks(ObjKey(key.value + m_offset), col_key, links.get_all(), state);
873+
do_remove_backlinks(real_key, col_key, links.get_all(), state);
873874
}
874875
}
875876
else if (col_type == col_type_TypedLink) {
@@ -880,11 +881,11 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
880881
auto target_obj = origin_table->get_parent_group()->get_object(link);
881882
ColKey backlink_col_key =
882883
target_obj.get_table()->find_backlink_column(col_key, origin_table->get_key());
883-
target_obj.remove_one_backlink(backlink_col_key, ObjKey(key.value + m_offset));
884+
target_obj.remove_one_backlink(backlink_col_key, real_key);
884885
}
885886
}
886887
else if (col_type == col_type_Mixed) {
887-
Obj obj(origin_table->m_own_ref, get_mem(), key, ndx);
888+
Obj obj(origin_table->m_own_ref, get_mem(), real_key, ndx);
888889
Lst<Mixed> list(obj, col_key);
889890
list.remove_backlinks(state);
890891
}
@@ -921,7 +922,7 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
921922
do_erase<ArrayBinary>(ndx, col_key);
922923
break;
923924
case col_type_Mixed:
924-
do_erase_mixed(ndx, col_key, key, state);
925+
do_erase_mixed(ndx, col_key, state);
925926
break;
926927
case col_type_Timestamp:
927928
do_erase<ArrayTimestamp>(ndx, col_key);
@@ -983,7 +984,7 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
983984
return node_size();
984985
}
985986

986-
void Cluster::nullify_incoming_links(ObjKey key, CascadeState& state)
987+
void Cluster::nullify_incoming_links(RowKey key, CascadeState& state)
987988
{
988989
size_t ndx = get_ndx(key, 0);
989990
if (ndx == realm::npos)
@@ -1541,7 +1542,7 @@ void Cluster::remove_backlinks(const Table* origin_table, ObjKey origin_key, Col
15411542
bool last_removed = target_obj.remove_one_backlink(backlink_col_key, origin_key); // Throws
15421543
if (is_unres) {
15431544
if (last_removed) {
1544-
// Check is there are more backlinks
1545+
// Check if there are more backlinks
15451546
if (!target_obj.has_backlinks(false)) {
15461547
// Tombstones can be erased right away - there is no cascading effect
15471548
target_table->m_tombstones->erase(link.get_obj_key(), state);

0 commit comments

Comments
 (0)