242 void update(std::string_view
key, std::uint64_t row,
const std::string& directory, Reader& reader) {
244 recover(work.snapshot, directory);
246 std::uint64_t ref = root_, depth = 0;
248 work.snapshot.ref = ref;
249 read_node(ref, work.snapshot.bytes.data());
251 undo_.write(depth, &work.snapshot, directory);
253 undo_rows_ = std::max(undo_rows_, depth);
255 std::memcpy(&work.leaf, work.snapshot.bytes.data(),
sizeof(Leaf));
258 std::memcpy(&work.branch, work.snapshot.bytes.data(),
sizeof(Branch));
259 ref = work.branch.child[(
symbol(
key, work.branch.pivot.byte) & work.branch.pivot.mask) != 0];
261 const std::uint64_t ancestors = depth == 0 ? 0 : depth - 1;
262 std::uint64_t parents = ancestors;
263 bool present =
false;
264 for (std::uint64_t i = 0; i < work.leaf.count; ++i)
265 present = present || work.leaf.rows[i] == row;
270 if (!present && work.leaf.count != 0) {
271 divergence = reader.difference(work.leaf.rows[0],
key);
272 for (std::uint64_t i = 0; i < ancestors; ++i) {
273 read_snapshot(i, work.snapshot);
274 std::memcpy(&work.branch, work.snapshot.bytes.data(),
sizeof(Branch));
275 if (
before(divergence, work.branch.pivot)) { parents = i;
break; }
283 auto next_leaves = leaf_count_, next_branches = branch_count_;
284 if (parents < ancestors) {
285 read_snapshot(parents, work.snapshot);
286 const auto old_subtree = work.snapshot.ref;
288 work.left.rows[0] = row;
289 const auto new_leaf = append_node(work.left, next_leaves,
true, directory);
290 leaf_fold(work.left, reader, work.fold);
291 load_fold(old_subtree, reader, work.other);
293 if (side == 0) work.fold.then(work.other);
294 else { work.other.then(work.fold); work.fold = work.other; }
295 work.branch.pivot = divergence;
296 work.branch.child[side] = new_leaf;
297 work.branch.child[1 - side] = old_subtree;
298 work.branch.fold = work.fold;
299 ref = append_node(work.branch, next_branches,
false, directory);
301 std::size_t count = 0;
302 bool inserted = present;
303 for (std::uint64_t i = 0; i < work.leaf.count; ++i) {
304 if (!inserted && reader.compare(work.leaf.rows[i],
key) > 0) {
305 work.rows[count++] = row;
308 work.rows[count++] = work.leaf.rows[i];
310 if (!inserted) work.rows[count++] = row;
311 if (count <= kBucket) {
312 work.left.count = count;
313 std::copy_n(work.rows.begin(), count, work.left.rows.begin());
314 if (ref == 0) ref = append_node(work.left, next_leaves,
true, directory);
315 else write_node(ref, &work.left, directory);
316 leaf_fold(work.left, reader, work.fold);
318 const auto pivot = reader.difference(work.rows[0], work.rows[count - 1]);
319 std::size_t split = 0;
320 while (split < count && (reader.symbol(work.rows[split], pivot.byte) & pivot.mask) == 0)
322 work.left.count = split; work.right.count = count - split;
323 std::copy_n(work.rows.begin(), split, work.left.rows.begin());
324 std::copy_n(work.rows.begin() + split, count - split, work.right.rows.begin());
325 write_node(ref, &work.left, directory);
326 const auto right = append_node(work.right, next_leaves,
true, directory);
327 leaf_fold(work.left, reader, work.fold);
328 leaf_fold(work.right, reader, work.other);
329 work.fold.then(work.other);
330 work.branch.pivot = pivot; work.branch.child = {ref, right};
331 work.branch.fold = work.fold;
332 ref = append_node(work.branch, next_branches,
false, directory);
335 while (parents != 0) {
336 read_snapshot(--parents, work.snapshot);
337 std::memcpy(&work.branch, work.snapshot.bytes.data(),
sizeof(Branch));
338 const unsigned side = (
symbol(
key, work.branch.pivot.byte) & work.branch.pivot.mask) != 0;
339 work.branch.child[side] = ref;
340 load_fold(work.branch.child[1 - side], reader, work.other);
341 if (side == 0) work.fold.then(work.other);
342 else { work.other.then(work.fold); work.fold = work.other; }
343 work.branch.fold = work.fold;
344 write_node(work.snapshot.ref, &work.branch, directory);
345 ref = work.snapshot.ref;
349 root_ = ref; root_fold_ = work.fold;
350 leaf_count_ = next_leaves; branch_count_ = next_branches;