• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

realm / realm-core / github_pull_request_281750

30 Oct 2023 03:37PM UTC coverage: 90.528% (-1.0%) from 91.571%
github_pull_request_281750

Pull #6073

Evergreen

jedelbo
Log free space and history sizes when opening file
Pull Request #6073: Merge next-major

95488 of 175952 branches covered (0.0%)

8973 of 12277 new or added lines in 149 files covered. (73.09%)

622 existing lines in 51 files now uncovered.

233503 of 257934 relevant lines covered (90.53%)

6533720.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.57
/src/realm/array_blobs_small.cpp
1
/*************************************************************************
2
 *
3
 * Copyright 2016 Realm Inc.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 **************************************************************************/
18

19
#include <utility> // pair
20

21
#include <realm/array_blobs_small.hpp>
22
#include <realm/array_blob.hpp>
23
#include <realm/impl/destroy_guard.hpp>
24

25
using namespace realm;
26

27
void ArraySmallBlobs::init_from_mem(MemRef mem) noexcept
28
{
2,288,592✔
29
    Array::init_from_mem(mem);
2,288,592✔
30
    ref_type offsets_ref = get_as_ref(0);
2,288,592✔
31
    ref_type blob_ref = get_as_ref(1);
2,288,592✔
32

1,196,310✔
33
    m_offsets.init_from_ref(offsets_ref);
2,288,592✔
34
    m_blob.init_from_ref(blob_ref);
2,288,592✔
35

1,196,310✔
36
    // In theory you could have an array that survived from ancient days where this array was not present
1,196,310✔
37
    if (Array::size() > 2) {
2,288,592✔
38
        ref_type nulls_ref = get_as_ref(2);
2,287,605✔
39
        m_nulls.init_from_ref(nulls_ref);
2,287,605✔
40
    }
2,287,605✔
41
}
2,288,592✔
42

43
void ArraySmallBlobs::add(BinaryData value, bool add_zero_term)
44
{
78,561✔
45
    REALM_ASSERT_7(value.size(), ==, 0, ||, value.data(), !=, 0);
78,561✔
46

39,729✔
47
    m_blob.add(value.data(), value.size(), add_zero_term);
78,561✔
48
    size_t end = value.size();
78,561✔
49
    if (add_zero_term)
78,561✔
50
        ++end;
62,193✔
51
    if (!m_offsets.is_empty())
78,561✔
52
        end += to_size_t(m_offsets.back());
50,031✔
53
    m_offsets.add(end);
78,561✔
54
    m_nulls.add(value.is_null());
78,561✔
55
}
78,561✔
56

57
void ArraySmallBlobs::set(size_t ndx, BinaryData value, bool add_zero_term)
58
{
320,175✔
59
    REALM_ASSERT_3(ndx, <, m_offsets.size());
320,175✔
60
    REALM_ASSERT_3(value.size(), == 0 ||, value.data());
320,175✔
61

159,465✔
62
    int_fast64_t start = ndx ? m_offsets.get(ndx - 1) : 0;
303,141✔
63
    int_fast64_t current_end = m_offsets.get(ndx);
320,175✔
64
    size_t stored_size = value.size();
320,175✔
65
    if (add_zero_term)
320,175✔
66
        ++stored_size;
246,249✔
67
    int_fast64_t diff = (start + stored_size) - current_end;
320,175✔
68
    m_blob.replace(to_size_t(start), to_size_t(current_end), value.data(), value.size(), add_zero_term);
320,175✔
69
    m_offsets.adjust(ndx, m_offsets.size(), diff);
320,175✔
70
    m_nulls.set(ndx, value.is_null());
320,175✔
71
}
320,175✔
72

73
void ArraySmallBlobs::insert(size_t ndx, BinaryData value, bool add_zero_term)
74
{
1,225,065✔
75
    REALM_ASSERT_3(ndx, <=, m_offsets.size());
1,225,065✔
76
    REALM_ASSERT_3(value.size(), == 0 ||, value.data());
1,225,065✔
77

638,700✔
78
    size_t pos = ndx ? to_size_t(m_offsets.get(ndx - 1)) : 0;
1,147,830✔
79
    m_blob.insert(pos, value.data(), value.size(), add_zero_term);
1,225,065✔
80

638,700✔
81
    size_t stored_size = value.size();
1,225,065✔
82
    if (add_zero_term)
1,225,065✔
83
        ++stored_size;
281,364✔
84
    m_offsets.insert(ndx, pos + stored_size);
1,225,065✔
85
    m_offsets.adjust(ndx + 1, m_offsets.size(), stored_size);
1,225,065✔
86
    m_nulls.insert(ndx, value.is_null());
1,225,065✔
87
}
1,225,065✔
88

89
void ArraySmallBlobs::erase(size_t ndx)
90
{
746,574✔
91
    REALM_ASSERT_3(ndx, <, m_offsets.size());
746,574✔
92

403,818✔
93
    size_t start = ndx ? to_size_t(m_offsets.get(ndx - 1)) : 0;
645,408✔
94
    size_t end = to_size_t(m_offsets.get(ndx));
746,574✔
95

403,818✔
96
    m_blob.erase(start, end);
746,574✔
97
    m_offsets.erase(ndx);
746,574✔
98
    m_offsets.adjust(ndx, m_offsets.size(), int64_t(start) - end);
746,574✔
99
    m_nulls.erase(ndx);
746,574✔
100
}
746,574✔
101

102
BinaryData ArraySmallBlobs::get(const char* header, size_t ndx, Allocator& alloc) noexcept
103
{
320,775✔
104
    int64_t ref_val = Array::get(header, 2);
320,775✔
105
    const char* nulls_header = alloc.translate(to_ref(ref_val));
320,775✔
106
    int64_t n = Array::get(nulls_header, ndx);
320,775✔
107
    // 0 or 1 is all that is ever written to m_nulls; any other content would be a bug
160,128✔
108
    REALM_ASSERT_3(n == 1, ||, n == 0);
320,775✔
109
    bool null = (n != 0);
320,775✔
110
    if (null)
320,775✔
111
        return BinaryData{};
18,111✔
112

150,891✔
113
    std::pair<int64_t, int64_t> p = Array::get_two(header, 0);
302,664✔
114
    const char* offsets_header = alloc.translate(to_ref(p.first));
302,664✔
115
    const char* blob_header = alloc.translate(to_ref(p.second));
302,664✔
116
    size_t begin, end;
302,664✔
117
    if (ndx) {
302,664✔
118
        p = get_two(offsets_header, ndx - 1);
287,184✔
119
        begin = to_size_t(p.first);
287,184✔
120
        end = to_size_t(p.second);
287,184✔
121
    }
287,184✔
122
    else {
15,480✔
123
        begin = 0;
15,480✔
124
        end = to_size_t(Array::get(offsets_header, ndx));
15,480✔
125
    }
15,480✔
126
    BinaryData bd = BinaryData(ArrayBlob::get(blob_header, begin), end - begin);
302,664✔
127
    return bd;
302,664✔
128
}
302,664✔
129

130
MemRef ArraySmallBlobs::create_array(size_t size, Allocator& alloc, BinaryData values)
131
{
162,753✔
132
    // Only null and zero-length non-null allowed as initialization value
79,836✔
133
    REALM_ASSERT(values.size() == 0);
162,753✔
134
    Array top(alloc);
162,753✔
135
    _impl::DeepArrayDestroyGuard dg(&top);
162,753✔
136
    top.create(type_HasRefs); // Throws
162,753✔
137

79,836✔
138
    _impl::DeepArrayRefDestroyGuard dg_2(alloc);
162,753✔
139
    {
162,753✔
140
        bool context_flag = false;
162,753✔
141
        int64_t value = 0;
162,753✔
142
        MemRef mem = Array::create_array(type_Normal, context_flag, size, value, alloc); // Throws
162,753✔
143
        dg_2.reset(mem.get_ref());
162,753✔
144
        int64_t v = from_ref(mem.get_ref());
162,753✔
145
        top.add(v); // Throws
162,753✔
146
        dg_2.release();
162,753✔
147
    }
162,753✔
148
    {
162,753✔
149
        size_t blobs_size = 0;
162,753✔
150
        MemRef mem = ArrayBlob::create_array(blobs_size, alloc); // Throws
162,753✔
151
        dg_2.reset(mem.get_ref());
162,753✔
152
        int64_t v = from_ref(mem.get_ref());
162,753✔
153
        top.add(v); // Throws
162,753✔
154
        dg_2.release();
162,753✔
155
    }
162,753✔
156
    {
162,753✔
157
        // Always create a m_nulls array, regardless if its column is marked as nullable or not.
79,836✔
158
        bool context_flag = false;
162,753✔
159
        int64_t value = values.is_null() ? 1 : 0;
162,753✔
160
        MemRef mem = Array::create_array(type_Normal, context_flag, size, value, alloc); // Throws
162,753✔
161
        dg_2.reset(mem.get_ref());
162,753✔
162
        int64_t v = from_ref(mem.get_ref());
162,753✔
163
        top.add(v); // Throws
162,753✔
164
        dg_2.release();
162,753✔
165
    }
162,753✔
166

79,836✔
167
    dg.release();
162,753✔
168
    return top.get_mem();
162,753✔
169
}
162,753✔
170

171
size_t ArraySmallBlobs::find_first(BinaryData value, bool is_string, size_t begin, size_t end) const noexcept
172
{
105,738✔
173
    size_t sz = size();
105,738✔
174
    if (end == npos)
105,738✔
175
        end = sz;
×
176
    REALM_ASSERT_11(begin, <=, sz, &&, end, <=, sz, &&, begin, <=, end);
105,738✔
177

63,300✔
178
    if (value.is_null()) {
105,738✔
179
        for (size_t i = begin; i != end; ++i) {
2,415✔
180
            if (m_nulls.get(i))
2,409✔
181
                return i;
2,271✔
182
        }
2,409✔
183
    }
2,277✔
184
    else {
103,461✔
185
        // When strings are stored as blobs, they are always zero-terminated
62,238✔
186
        // but the value we get as input might not be.
62,238✔
187
        size_t value_size = value.size();
103,461✔
188
        size_t full_size = is_string ? value_size + 1 : value_size;
103,329✔
189

62,238✔
190
        size_t start_ofs = begin ? to_size_t(m_offsets.get(begin - 1)) : 0;
96,555✔
191
        for (size_t i = begin; i != end; ++i) {
380,397✔
192
            size_t end_ofs = to_size_t(m_offsets.get(i));
361,710✔
193
            size_t this_size = end_ofs - start_ofs;
361,710✔
194
            if (!m_nulls.get(i) && this_size == full_size) {
361,710✔
195
                const char* blob_value = m_blob.get(start_ofs);
126,816✔
196
                if (std::equal(blob_value, blob_value + value_size, value.data()))
126,816✔
197
                    return i;
84,774✔
198
            }
276,936✔
199
            start_ofs = end_ofs;
276,936✔
200
        }
276,936✔
201
    }
103,461✔
202

63,300✔
203
    return not_found;
70,440✔
204
}
105,738✔
205

206
StringData ArraySmallBlobs::get_string_legacy(size_t ndx) const
UNCOV
207
{
×
UNCOV
208
    REALM_ASSERT_3(ndx, <, m_offsets.size());
×
209

210
    // In file format versions prior to 10 a true value means that the element is not null
UNCOV
211
    if (Array::size() == 3 && !m_nulls.get(ndx)) {
×
UNCOV
212
        return {};
×
UNCOV
213
    }
×
UNCOV
214
    else {
×
UNCOV
215
        size_t begin = ndx ? to_size_t(m_offsets.get(ndx - 1)) : 0;
×
UNCOV
216
        size_t end = to_size_t(m_offsets.get(ndx));
×
UNCOV
217
        StringData str = StringData(m_blob.get(begin), (end - begin) - 1);
×
UNCOV
218
        return str;
×
UNCOV
219
    }
×
UNCOV
220
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc