Skip to content

Commit 3e8a751

Browse files
committed
Merge branch 'next-major' into feature/string-compression
2 parents 1d89781 + ac22a23 commit 3e8a751

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
}
@@ -362,13 +362,13 @@ inline void Cluster::do_insert_link(size_t ndx, ColKey col_key, Mixed init_val,
362362
}
363363
}
364364

365-
void Cluster::insert_row(size_t ndx, ObjKey k, const FieldValues& init_values)
365+
void Cluster::insert_row(size_t ndx, RowKey row_key, const FieldValues& init_values)
366366
{
367367
// Ensure the cluster array is big enough to hold 64 bit values.
368368
copy_on_write(m_size * 8);
369369

370370
if (m_keys.is_attached()) {
371-
m_keys.insert(ndx, k.value);
371+
m_keys.insert(ndx, row_key.value);
372372
}
373373
else {
374374
Array::set(s_key_ref_or_size_index, Array::get(s_key_ref_or_size_index) + 2); // Increments size by 1
@@ -396,6 +396,7 @@ void Cluster::insert_row(size_t ndx, ObjKey k, const FieldValues& init_values)
396396
}
397397

398398
bool nullable = attr.test(col_attr_Nullable);
399+
ObjKey obj_key(int64_t(row_key.value + get_offset()));
399400
switch (type) {
400401
case col_type_Int:
401402
if (attr.test(col_attr_Nullable)) {
@@ -421,7 +422,7 @@ void Cluster::insert_row(size_t ndx, ObjKey k, const FieldValues& init_values)
421422
do_insert_row<ArrayBinary>(ndx, col_key, init_value, nullable);
422423
break;
423424
case col_type_Mixed: {
424-
do_insert_mixed(ndx, col_key, init_value, ObjKey(k.value + get_offset()));
425+
do_insert_mixed(ndx, col_key, init_value, obj_key);
425426
break;
426427
}
427428
case col_type_Timestamp:
@@ -437,10 +438,10 @@ void Cluster::insert_row(size_t ndx, ObjKey k, const FieldValues& init_values)
437438
do_insert_row<ArrayUUIDNull>(ndx, col_key, init_value, nullable);
438439
break;
439440
case col_type_Link:
440-
do_insert_key(ndx, col_key, init_value, ObjKey(k.value + get_offset()));
441+
do_insert_key(ndx, col_key, init_value, obj_key);
441442
break;
442443
case col_type_TypedLink:
443-
do_insert_link(ndx, col_key, init_value, ObjKey(k.value + get_offset()));
444+
do_insert_link(ndx, col_key, init_value, obj_key);
444445
break;
445446
case col_type_BackLink: {
446447
ArrayBacklink arr(m_alloc);
@@ -685,7 +686,7 @@ void Cluster::remove_column(ColKey col_key)
685686
Array::set(idx, 0);
686687
}
687688

688-
ref_type Cluster::insert(ObjKey k, const FieldValues& init_values, ClusterNode::State& state)
689+
ref_type Cluster::insert(RowKey row_key, const FieldValues& init_values, ClusterNode::State& state)
689690
{
690691
int64_t current_key_value = -1;
691692
size_t sz;
@@ -694,34 +695,34 @@ ref_type Cluster::insert(ObjKey k, const FieldValues& init_values, ClusterNode::
694695

695696
auto on_error = [&] {
696697
throw KeyAlreadyUsed(
697-
util::format("When inserting key '%1' in '%2'", k.value, get_owning_table()->get_name()));
698+
util::format("When inserting key '%1' in '%2'", row_key.value, get_owning_table()->get_name()));
698699
};
699700

700701
if (m_keys.is_attached()) {
701702
sz = m_keys.size();
702-
ndx = m_keys.lower_bound(uint64_t(k.value));
703+
ndx = m_keys.lower_bound(row_key.value);
703704
if (ndx < sz) {
704705
current_key_value = m_keys.get(ndx);
705-
if (k.value == current_key_value) {
706+
if (row_key.value == uint64_t(current_key_value)) {
706707
on_error();
707708
}
708709
}
709710
}
710711
else {
711712
sz = size_t(Array::get(s_key_ref_or_size_index)) >> 1; // Size is stored as tagged integer
712-
if (uint64_t(k.value) < sz) {
713+
if (row_key.value < sz) {
713714
on_error();
714715
}
715716
// Key value is bigger than all other values, should be put last
716717
ndx = sz;
717-
if (uint64_t(k.value) > sz && sz < cluster_node_size) {
718+
if (row_key.value > sz && sz < cluster_node_size) {
718719
ensure_general_form();
719720
}
720721
}
721722

722723
REALM_ASSERT_DEBUG(sz <= cluster_node_size);
723724
if (REALM_LIKELY(sz < cluster_node_size)) {
724-
insert_row(ndx, k, init_values); // Throws
725+
insert_row(ndx, row_key, init_values); // Throws
725726
state.mem = get_mem();
726727
state.index = ndx;
727728
}
@@ -730,8 +731,8 @@ ref_type Cluster::insert(ObjKey k, const FieldValues& init_values, ClusterNode::
730731
Cluster new_leaf(0, m_alloc, m_tree_top);
731732
new_leaf.create();
732733
if (ndx == sz) {
733-
new_leaf.insert_row(0, ObjKey(0), init_values); // Throws
734-
state.split_key = k.value;
734+
new_leaf.insert_row(0, RowKey(0), init_values); // Throws
735+
state.split_key = int64_t(row_key.value);
735736
state.mem = new_leaf.get_mem();
736737
state.index = 0;
737738
}
@@ -740,7 +741,7 @@ ref_type Cluster::insert(ObjKey k, const FieldValues& init_values, ClusterNode::
740741
REALM_ASSERT_DEBUG(m_keys.is_attached());
741742
new_leaf.ensure_general_form();
742743
move(ndx, &new_leaf, current_key_value);
743-
insert_row(ndx, k, init_values); // Throws
744+
insert_row(ndx, row_key, init_values); // Throws
744745
state.mem = get_mem();
745746
state.split_key = current_key_value;
746747
state.index = ndx;
@@ -751,15 +752,15 @@ ref_type Cluster::insert(ObjKey k, const FieldValues& init_values, ClusterNode::
751752
return ret;
752753
}
753754

754-
bool Cluster::try_get(ObjKey k, ClusterNode::State& state) const noexcept
755+
bool Cluster::try_get(RowKey k, ClusterNode::State& state) const noexcept
755756
{
756757
state.mem = get_mem();
757758
if (m_keys.is_attached()) {
758-
state.index = m_keys.lower_bound(uint64_t(k.value));
759-
return state.index != m_keys.size() && m_keys.get(state.index) == uint64_t(k.value);
759+
state.index = m_keys.lower_bound(k.value);
760+
return state.index != m_keys.size() && m_keys.get(state.index) == k.value;
760761
}
761762
else {
762-
if (uint64_t(k.value) < uint64_t(Array::get(s_key_ref_or_size_index) >> 1)) {
763+
if (k.value < uint64_t(Array::get(s_key_ref_or_size_index) >> 1)) {
763764
state.index = size_t(k.value);
764765
return true;
765766
}
@@ -798,7 +799,7 @@ inline void Cluster::do_erase(size_t ndx, ColKey col_key)
798799
values.erase(ndx);
799800
}
800801

801-
inline void Cluster::do_erase_mixed(size_t ndx, ColKey col_key, ObjKey key, CascadeState& state)
802+
inline void Cluster::do_erase_mixed(size_t ndx, ColKey col_key, CascadeState& state)
802803
{
803804
const Table* origin_table = m_tree_top.get_owning_table();
804805
auto col_ndx = col_key.get_index();
@@ -811,19 +812,16 @@ inline void Cluster::do_erase_mixed(size_t ndx, ColKey col_key, ObjKey key, Casc
811812
Mixed value = values.get(ndx);
812813
if (value.is_type(type_TypedLink)) {
813814
ObjLink link = value.get<ObjLink>();
814-
auto target_obj = origin_table->get_parent_group()->get_object(link);
815-
816-
ColKey backlink_col_key = target_obj.get_table()->find_backlink_column(col_key, origin_table->get_key());
817-
REALM_ASSERT(backlink_col_key);
818-
target_obj.remove_one_backlink(backlink_col_key, get_real_key(ndx)); // Throws
815+
Obj obj(origin_table->m_own_ref, get_mem(), get_real_key(ndx), ndx);
816+
obj.remove_backlink(col_key, link, state);
819817
}
820818
if (value.is_type(type_List)) {
821-
Obj obj(origin_table->m_own_ref, get_mem(), key, ndx);
819+
Obj obj(origin_table->m_own_ref, get_mem(), get_real_key(ndx), ndx);
822820
Lst<Mixed> list(obj, col_key);
823821
list.remove_backlinks(state);
824822
}
825823
if (value.is_type(type_Dictionary)) {
826-
Obj obj(origin_table->m_own_ref, get_mem(), key, ndx);
824+
Obj obj(origin_table->m_own_ref, get_mem(), get_real_key(ndx), ndx);
827825
Dictionary dict(obj, col_key);
828826
dict.remove_backlinks(state);
829827
}
@@ -844,12 +842,12 @@ inline void Cluster::do_erase_key(size_t ndx, ColKey col_key, CascadeState& stat
844842
values.erase(ndx);
845843
}
846844

847-
size_t Cluster::get_ndx(ObjKey k, size_t ndx) const noexcept
845+
size_t Cluster::get_ndx(RowKey k, size_t ndx) const noexcept
848846
{
849847
size_t index;
850848
if (m_keys.is_attached()) {
851-
index = m_keys.lower_bound(uint64_t(k.value));
852-
if (index == m_keys.size() || m_keys.get(index) != uint64_t(k.value)) {
849+
index = m_keys.lower_bound(k.value);
850+
if (index == m_keys.size() || m_keys.get(index) != k.value) {
853851
return realm::npos;
854852
}
855853
}
@@ -862,11 +860,14 @@ size_t Cluster::get_ndx(ObjKey k, size_t ndx) const noexcept
862860
return index + ndx;
863861
}
864862

865-
size_t Cluster::erase(ObjKey key, CascadeState& state)
863+
size_t Cluster::erase(RowKey row_key, CascadeState& state)
866864
{
867-
size_t ndx = get_ndx(key, 0);
865+
size_t ndx = get_ndx(row_key, 0);
868866
if (ndx == realm::npos)
869-
throw KeyNotFound(util::format("When erasing key '%1' in '%2'", key.value, get_owning_table()->get_name()));
867+
throw KeyNotFound(util::format("When erasing key '%1' (offset '%2') in '%3'", row_key.value, m_offset,
868+
get_owning_table()->get_name()));
869+
870+
ObjKey real_key = get_real_key(ndx);
870871
std::vector<ColKey> backlink_column_keys;
871872

872873
auto erase_in_column = [&](ColKey col_key) {
@@ -883,7 +884,7 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
883884
const Table* origin_table = m_tree_top.get_owning_table();
884885
if (attr.test(col_attr_Dictionary)) {
885886
if (col_type == col_type_Mixed || col_type == col_type_Link) {
886-
Obj obj(origin_table->m_own_ref, get_mem(), key, ndx);
887+
Obj obj(origin_table->m_own_ref, get_mem(), real_key, ndx);
887888
Dictionary dict(obj, col_key);
888889
dict.remove_backlinks(state);
889890
}
@@ -892,7 +893,7 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
892893
BPlusTree<ObjKey> links(m_alloc);
893894
links.init_from_ref(ref);
894895
if (links.size() > 0) {
895-
do_remove_backlinks(ObjKey(key.value + m_offset), col_key, links.get_all(), state);
896+
do_remove_backlinks(real_key, col_key, links.get_all(), state);
896897
}
897898
}
898899
else if (col_type == col_type_TypedLink) {
@@ -903,11 +904,11 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
903904
auto target_obj = origin_table->get_parent_group()->get_object(link);
904905
ColKey backlink_col_key =
905906
target_obj.get_table()->find_backlink_column(col_key, origin_table->get_key());
906-
target_obj.remove_one_backlink(backlink_col_key, ObjKey(key.value + m_offset));
907+
target_obj.remove_one_backlink(backlink_col_key, real_key);
907908
}
908909
}
909910
else if (col_type == col_type_Mixed) {
910-
Obj obj(origin_table->m_own_ref, get_mem(), key, ndx);
911+
Obj obj(origin_table->m_own_ref, get_mem(), real_key, ndx);
911912
Lst<Mixed> list(obj, col_key);
912913
list.remove_backlinks(state);
913914
}
@@ -944,7 +945,7 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
944945
do_erase<ArrayBinary>(ndx, col_key);
945946
break;
946947
case col_type_Mixed:
947-
do_erase_mixed(ndx, col_key, key, state);
948+
do_erase_mixed(ndx, col_key, state);
948949
break;
949950
case col_type_Timestamp:
950951
do_erase<ArrayTimestamp>(ndx, col_key);
@@ -1006,7 +1007,7 @@ size_t Cluster::erase(ObjKey key, CascadeState& state)
10061007
return node_size();
10071008
}
10081009

1009-
void Cluster::nullify_incoming_links(ObjKey key, CascadeState& state)
1010+
void Cluster::nullify_incoming_links(RowKey key, CascadeState& state)
10101011
{
10111012
size_t ndx = get_ndx(key, 0);
10121013
if (ndx == realm::npos)
@@ -1574,7 +1575,7 @@ void Cluster::remove_backlinks(const Table* origin_table, ObjKey origin_key, Col
15741575
bool last_removed = target_obj.remove_one_backlink(backlink_col_key, origin_key); // Throws
15751576
if (is_unres) {
15761577
if (last_removed) {
1577-
// Check is there are more backlinks
1578+
// Check if there are more backlinks
15781579
if (!target_obj.has_backlinks(false)) {
15791580
// Tombstones can be erased right away - there is no cascading effect
15801581
target_table->m_tombstones->erase(link.get_obj_key(), state);

0 commit comments

Comments
 (0)