Coverage Report

Created: 2025-03-04 07:22

/src/serenity/Userland/Libraries/LibSQL/TreeNode.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include <AK/Debug.h>
8
#include <AK/Format.h>
9
#include <AK/StringBuilder.h>
10
#include <LibSQL/BTree.h>
11
#include <LibSQL/Serializer.h>
12
13
namespace SQL {
14
15
DownPointer::DownPointer(TreeNode* owner, Block::Index block_index)
16
0
    : m_owner(owner)
17
0
    , m_block_index(block_index)
18
0
    , m_node(nullptr)
19
0
{
20
0
}
21
22
DownPointer::DownPointer(TreeNode* owner, TreeNode* node)
23
0
    : m_owner(owner)
24
0
    , m_block_index((node) ? node->block_index() : 0)
25
0
    , m_node(adopt_own_if_nonnull(node))
26
0
{
27
0
}
28
29
DownPointer::DownPointer(TreeNode* owner, DownPointer& down)
30
0
    : m_owner(owner)
31
0
    , m_block_index(down.m_block_index)
32
0
    , m_node(move(down.m_node))
33
0
{
34
0
}
35
36
DownPointer::DownPointer(DownPointer&& other)
37
0
    : m_owner(other.m_owner)
38
0
    , m_block_index(other.block_index())
39
0
    , m_node(other.m_node ? move(other.m_node) : nullptr)
40
0
{
41
0
}
42
43
TreeNode* DownPointer::node()
44
0
{
45
0
    if (!m_node)
46
0
        deserialize(m_owner->tree().serializer());
47
0
    return m_node;
48
0
}
49
50
void DownPointer::deserialize(Serializer& serializer)
51
0
{
52
0
    if (m_node || !m_block_index)
53
0
        return;
54
0
    serializer.read_storage(m_block_index);
55
0
    m_node = serializer.make_and_deserialize<TreeNode>(m_owner->tree(), m_owner, m_block_index);
56
0
}
57
58
TreeNode::TreeNode(BTree& tree, Block::Index block_index)
59
0
    : IndexNode(block_index)
60
0
    , m_tree(tree)
61
0
    , m_up(nullptr)
62
0
    , m_entries()
63
0
    , m_down()
64
0
{
65
0
}
66
67
TreeNode::TreeNode(BTree& tree, TreeNode* up, Block::Index block_index)
68
0
    : IndexNode(block_index)
69
0
    , m_tree(tree)
70
0
    , m_up(up)
71
0
    , m_entries()
72
0
    , m_down()
73
0
{
74
0
    m_down.append(DownPointer(this, nullptr));
75
0
    m_is_leaf = true;
76
0
}
77
78
TreeNode::TreeNode(BTree& tree, TreeNode* up, DownPointer& left, Block::Index block_index)
79
0
    : IndexNode(block_index)
80
0
    , m_tree(tree)
81
0
    , m_up(up)
82
0
    , m_entries()
83
0
    , m_down()
84
0
{
85
0
    if (left.m_node != nullptr)
86
0
        left.m_node->m_up = this;
87
0
    m_down.append(DownPointer(this, left));
88
0
    m_is_leaf = left.block_index() == 0;
89
0
    if (!block_index)
90
0
        set_block_index(m_tree.request_new_block_index());
91
0
}
92
93
TreeNode::TreeNode(BTree& tree, TreeNode* up, TreeNode* left, Block::Index block_index)
94
0
    : IndexNode(block_index)
95
0
    , m_tree(tree)
96
0
    , m_up(up)
97
0
    , m_entries()
98
0
    , m_down()
99
0
{
100
0
    m_down.append(DownPointer(this, left));
101
0
    m_is_leaf = left->block_index() == 0;
102
0
}
103
104
void TreeNode::deserialize(Serializer& serializer)
105
0
{
106
0
    auto nodes = serializer.deserialize<u32>();
107
0
    dbgln_if(SQL_DEBUG, "Deserializing node. Size {}", nodes);
108
0
    if (nodes > 0) {
109
0
        for (u32 i = 0; i < nodes; i++) {
110
0
            auto left = serializer.deserialize<u32>();
111
0
            dbgln_if(SQL_DEBUG, "Down[{}] {}", i, left);
112
0
            if (!m_down.is_empty())
113
0
                VERIFY((left == 0) == m_is_leaf);
114
0
            else
115
0
                m_is_leaf = (left == 0);
116
0
            m_entries.append(serializer.deserialize<Key>(m_tree.descriptor()));
117
0
            m_down.empend(this, left);
118
0
        }
119
0
        auto right = serializer.deserialize<u32>();
120
0
        dbgln_if(SQL_DEBUG, "Right {}", right);
121
0
        VERIFY((right == 0) == m_is_leaf);
122
0
        m_down.empend(this, right);
123
0
    }
124
0
}
125
126
void TreeNode::serialize(Serializer& serializer) const
127
0
{
128
0
    u32 sz = size();
129
0
    serializer.serialize<u32>(sz);
130
0
    if (sz > 0) {
131
0
        for (auto ix = 0u; ix < size(); ix++) {
132
0
            auto& entry = m_entries[ix];
133
0
            dbgln_if(SQL_DEBUG, "Serializing Left[{}] = {}", ix, m_down[ix].block_index());
134
0
            serializer.serialize<u32>(is_leaf() ? 0u : m_down[ix].block_index());
135
0
            serializer.serialize<Key>(entry);
136
0
        }
137
0
        dbgln_if(SQL_DEBUG, "Serializing Right = {}", m_down[size()].block_index());
138
0
        serializer.serialize<u32>(is_leaf() ? 0u : m_down[size()].block_index());
139
0
    }
140
0
}
141
142
size_t TreeNode::length() const
143
0
{
144
0
    if (!size())
145
0
        return 0;
146
0
    size_t len = sizeof(u32);
147
0
    for (auto& key : m_entries)
148
0
        len += sizeof(u32) + key.length();
149
0
    return len;
150
0
}
151
152
bool TreeNode::insert(Key const& key)
153
0
{
154
0
    dbgln_if(SQL_DEBUG, "[#{}] INSERT({})", block_index(), key.to_byte_string());
155
0
    if (!is_leaf())
156
0
        return node_for(key)->insert_in_leaf(key);
157
0
    return insert_in_leaf(key);
158
0
}
159
160
bool TreeNode::update_key_pointer(Key const& key)
161
0
{
162
0
    dbgln_if(SQL_DEBUG, "[#{}] UPDATE({}, {})", block_index(), key.to_byte_string(), key.block_index());
163
0
    if (!is_leaf())
164
0
        return node_for(key)->update_key_pointer(key);
165
166
0
    for (auto ix = 0u; ix < size(); ix++) {
167
0
        if (key == m_entries[ix]) {
168
0
            dbgln_if(SQL_DEBUG, "[#{}] {} == {}",
169
0
                block_index(), key.to_byte_string(), m_entries[ix].to_byte_string());
170
0
            if (m_entries[ix].block_index() != key.block_index()) {
171
0
                m_entries[ix].set_block_index(key.block_index());
172
0
                dump_if(SQL_DEBUG, "To WAL");
173
0
                tree().serializer().serialize_and_write<TreeNode>(*this);
174
0
            }
175
0
            return true;
176
0
        }
177
0
    }
178
0
    return false;
179
0
}
180
181
bool TreeNode::insert_in_leaf(Key const& key)
182
0
{
183
0
    VERIFY(is_leaf());
184
0
    if (!m_tree.duplicates_allowed()) {
185
0
        for (auto& entry : m_entries) {
186
0
            if (key == entry) {
187
0
                dbgln_if(SQL_DEBUG, "[#{}] duplicate key {}", block_index(), key.to_byte_string());
188
0
                return false;
189
0
            }
190
0
        }
191
0
    }
192
193
0
    dbgln_if(SQL_DEBUG, "[#{}] insert_in_leaf({})", block_index(), key.to_byte_string());
194
0
    just_insert(key, nullptr);
195
0
    return true;
196
0
}
197
198
Block::Index TreeNode::down_pointer(size_t ix) const
199
0
{
200
0
    return m_down[ix].block_index();
201
0
}
202
203
TreeNode* TreeNode::down_node(size_t ix)
204
0
{
205
0
    return m_down[ix].node();
206
0
}
207
208
TreeNode* TreeNode::node_for(Key const& key)
209
0
{
210
0
    dump_if(SQL_DEBUG, ByteString::formatted("node_for(Key {})", key.to_byte_string()));
211
0
    if (is_leaf())
212
0
        return this;
213
0
    for (size_t ix = 0; ix < size(); ix++) {
214
0
        if (key < m_entries[ix]) {
215
0
            dbgln_if(SQL_DEBUG, "[{}] {} < {} v{}",
216
0
                block_index(), (ByteString)key, (ByteString)m_entries[ix], m_down[ix].block_index());
217
0
            return down_node(ix)->node_for(key);
218
0
        }
219
0
    }
220
0
    dbgln_if(SQL_DEBUG, "[#{}] {} >= {} v{}",
221
0
        block_index(), key.to_byte_string(), (ByteString)m_entries[size() - 1], m_down[size()].block_index());
222
0
    return down_node(size())->node_for(key);
223
0
}
224
225
Optional<u32> TreeNode::get(Key& key)
226
0
{
227
0
    dump_if(SQL_DEBUG, ByteString::formatted("get({})", key.to_byte_string()));
228
0
    for (auto ix = 0u; ix < size(); ix++) {
229
0
        if (key < m_entries[ix]) {
230
0
            if (is_leaf()) {
231
0
                dbgln_if(SQL_DEBUG, "[#{}] {} < {} -> 0",
232
0
                    block_index(), key.to_byte_string(), (ByteString)m_entries[ix]);
233
0
                return {};
234
0
            } else {
235
0
                dbgln_if(SQL_DEBUG, "[{}] {} < {} ({} -> {})",
236
0
                    block_index(), key.to_byte_string(), (ByteString)m_entries[ix],
237
0
                    ix, m_down[ix].block_index());
238
0
                return down_node(ix)->get(key);
239
0
            }
240
0
        }
241
0
        if (key == m_entries[ix]) {
242
0
            dbgln_if(SQL_DEBUG, "[#{}] {} == {} -> {}",
243
0
                block_index(), key.to_byte_string(), (ByteString)m_entries[ix],
244
0
                m_entries[ix].block_index());
245
0
            key.set_block_index(m_entries[ix].block_index());
246
0
            return m_entries[ix].block_index();
247
0
        }
248
0
    }
249
0
    if (m_entries.is_empty()) {
250
0
        dbgln_if(SQL_DEBUG, "[#{}] {} Empty node??", block_index(), key.to_byte_string());
251
0
        VERIFY_NOT_REACHED();
252
0
    }
253
0
    if (is_leaf()) {
254
0
        dbgln_if(SQL_DEBUG, "[#{}] {} > {} -> 0",
255
0
            block_index(), key.to_byte_string(), (ByteString)m_entries[size() - 1]);
256
0
        return {};
257
0
    }
258
0
    dbgln_if(SQL_DEBUG, "[#{}] {} > {} ({} -> {})",
259
0
        block_index(), key.to_byte_string(), (ByteString)m_entries[size() - 1],
260
0
        size(), m_down[size()].block_index());
261
0
    return down_node(size())->get(key);
262
0
}
263
264
void TreeNode::just_insert(Key const& key, TreeNode* right)
265
0
{
266
0
    dbgln_if(SQL_DEBUG, "[#{}] just_insert({}, right = {})",
267
0
        block_index(), (ByteString)key, (right) ? right->block_index() : 0);
268
0
    dump_if(SQL_DEBUG, "Before");
269
0
    for (auto ix = 0u; ix < size(); ix++) {
270
0
        if (key < m_entries[ix]) {
271
0
            m_entries.insert(ix, key);
272
0
            VERIFY(is_leaf() == (right == nullptr));
273
0
            m_down.insert(ix + 1, DownPointer(this, right));
274
0
            if (length() > Block::DATA_SIZE) {
275
0
                split();
276
0
            } else {
277
0
                dump_if(SQL_DEBUG, "To WAL");
278
0
                tree().serializer().serialize_and_write(*this);
279
0
            }
280
0
            return;
281
0
        }
282
0
    }
283
0
    m_entries.append(key);
284
0
    m_down.empend(this, right);
285
286
0
    if (length() > Block::DATA_SIZE) {
287
0
        split();
288
0
    } else {
289
0
        dump_if(SQL_DEBUG, "To WAL");
290
0
        tree().serializer().serialize_and_write(*this);
291
0
    }
292
0
}
293
294
void TreeNode::split()
295
0
{
296
0
    dump_if(SQL_DEBUG, "Splitting node");
297
0
    if (!m_up)
298
        // Make new m_up. This is the new root node.
299
0
        m_up = m_tree.new_root();
300
301
    // Take the left pointer for the new node:
302
0
    auto median_index = size() / 2;
303
0
    if (!(size() % 2))
304
0
        ++median_index;
305
0
    DownPointer left = m_down.take(median_index);
306
307
    // Create the new right node:
308
0
    auto* new_node = new TreeNode(tree(), m_up, left);
309
310
    // Move the rightmost keys from this node to the new right node:
311
0
    while (m_entries.size() > median_index) {
312
0
        auto entry = m_entries.take(median_index);
313
0
        auto down = m_down.take(median_index);
314
315
        // Reparent to new right node:
316
0
        if (down.m_node != nullptr)
317
0
            down.m_node->m_up = new_node;
318
0
        new_node->m_entries.append(entry);
319
0
        new_node->m_down.append(move(down));
320
0
    }
321
322
    // Move the median key in the node one level up. Its right node will
323
    // be the new node:
324
0
    auto median = m_entries.take_last();
325
326
0
    dump_if(SQL_DEBUG, "Split Left To WAL");
327
0
    tree().serializer().serialize_and_write(*this);
328
0
    new_node->dump_if(SQL_DEBUG, "Split Right to WAL");
329
0
    tree().serializer().serialize_and_write(*new_node);
330
331
0
    m_up->just_insert(median, new_node);
332
0
}
333
334
void TreeNode::dump_if(int flag, ByteString&& msg)
335
0
{
336
0
    if (!flag)
337
0
        return;
338
0
    StringBuilder builder;
339
0
    builder.appendff("[#{}] ", block_index());
340
0
    if (!msg.is_empty())
341
0
        builder.appendff("{}", msg);
342
0
    builder.append(": "sv);
343
0
    if (m_up)
344
0
        builder.appendff("[^{}] -> ", m_up->block_index());
345
0
    else
346
0
        builder.append("* -> "sv);
347
0
    for (size_t ix = 0; ix < m_entries.size(); ix++) {
348
0
        if (!is_leaf())
349
0
            builder.appendff("[v{}] ", m_down[ix].block_index());
350
0
        else
351
0
            VERIFY(m_down[ix].block_index() == 0);
352
0
        builder.appendff("'{}' ", (ByteString)m_entries[ix]);
353
0
    }
354
0
    if (!is_leaf())
355
0
        builder.appendff("[v{}]", m_down[size()].block_index());
356
0
    else
357
0
        VERIFY(m_down[size()].block_index() == 0);
358
0
    builder.appendff(" (size {}", (int)size());
359
0
    if (is_leaf())
360
0
        builder.append(", leaf"sv);
361
0
    builder.append(')');
362
0
    dbgln(builder.to_byte_string());
363
0
}
364
365
void TreeNode::list_node(int indent)
366
0
{
367
0
    auto do_indent = [&]() {
368
0
        for (int i = 0; i < indent; ++i)
369
0
            warn(" ");
370
0
    };
371
0
    do_indent();
372
0
    warnln("--> #{}", block_index());
373
0
    for (auto ix = 0u; ix < size(); ix++) {
374
0
        if (!is_leaf())
375
0
            down_node(ix)->list_node(indent + 2);
376
0
        do_indent();
377
0
        warnln("{}", m_entries[ix].to_byte_string());
378
0
    }
379
0
    if (!is_leaf())
380
0
        down_node(size())->list_node(indent + 2);
381
0
}
382
383
}