Skip to content

Commit 555e3c7

Browse files
committed
[MemoryBTree]: Add rangeKeys(), rangeVals(), scanKeys(), scanVals() for more efficient range request
1 parent 3b2e292 commit 555e3c7

File tree

5 files changed

+246
-11
lines changed

5 files changed

+246
-11
lines changed

mops.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "memory-collection"
3-
version = "0.0.3"
3+
version = "0.0.4"
44
description = "A collection of data structures that store their data in stable memory"
55
repository = "https://github.com/NatLabs/memory-collection"
66
keywords = ["region", "sorted", "persistent", "map", "encoding"]

src/MemoryBTree/Base.mo

Lines changed: 98 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -934,21 +934,64 @@ module {
934934

935935
};
936936

937-
public func range<K, V>(btree : MemoryBTree, btree_utils : BTreeUtils<K, V>, start : Nat, end : Nat) : RevIter<(K, V)> {
937+
func process_range_request<ReturnValue>(
938+
btree : MemoryBTree,
939+
start : Nat,
940+
end : Nat,
941+
kv_address_to_result_mapper : (Address) -> ReturnValue,
942+
) : RevIter<ReturnValue> {
943+
938944
let (start_node, start_node_index) = Methods.get_leaf_node_by_index(btree, start);
939945
let (end_node, end_node_index) = Methods.get_leaf_node_by_index(btree, end);
940946

941947
let start_index = start_node_index : Nat;
942948
let end_index = end_node_index : Nat;
943949

944-
RevIter.map<(Blob, Blob), (K, V)>(
945-
Methods.new_blobs_iterator(btree, start_node, start_index, end_node, end_index),
946-
func((key_blob, val_blob) : (Blob, Blob)) : (K, V) {
950+
RevIter.map<Address, ReturnValue>(
951+
Methods.new_kv_block_address_iterator(btree, start_node, start_index, end_node, end_index),
952+
kv_address_to_result_mapper,
953+
);
954+
};
955+
956+
public func range<K, V>(btree : MemoryBTree, btree_utils : BTreeUtils<K, V>, start : Nat, end : Nat) : RevIter<(K, V)> {
957+
process_range_request<(K, V)>(
958+
btree,
959+
start,
960+
end,
961+
func(kv_address : Address) : (K, V) {
962+
let key_blob = MemoryBlock.get_key_blob(btree, kv_address);
963+
let val_blob = MemoryBlock.get_val_blob(btree, kv_address);
947964
Methods.deserialize_kv_blobs<K, V>(btree_utils, key_blob, val_blob);
948965
},
949966
);
950967
};
951968

969+
public func rangeKeys<K, V>(btree : MemoryBTree, btree_utils : BTreeUtils<K, V>, start : Nat, end : Nat) : RevIter<K> {
970+
971+
process_range_request(
972+
btree,
973+
start,
974+
end,
975+
func(kv_address : Address) : K {
976+
let key_blob = MemoryBlock.get_key_blob(btree, kv_address);
977+
btree_utils.key.blobify.from_blob(key_blob);
978+
},
979+
);
980+
981+
};
982+
983+
public func rangeVals<K, V>(btree : MemoryBTree, btree_utils : BTreeUtils<K, V>, start : Nat, end : Nat) : RevIter<V> {
984+
process_range_request(
985+
btree,
986+
start,
987+
end,
988+
func(kv_address : Address) : V {
989+
let val_blob = MemoryBlock.get_val_blob(btree, kv_address);
990+
btree_utils.value.blobify.from_blob(val_blob);
991+
},
992+
);
993+
};
994+
952995
public func getInterval<K, V>(btree : MemoryBTree, btree_utils : BTreeUtils<K, V>, start : ?K, end : ?K) : (Nat, Nat) {
953996
let start_rank = switch (start) {
954997
case (?key) getIndex(btree, btree_utils, key);
@@ -963,7 +1006,14 @@ module {
9631006
(start_rank, end_rank);
9641007
};
9651008

966-
public func scan<K, V>(btree : MemoryBTree, btree_utils : BTreeUtils<K, V>, start : ?K, end : ?K) : RevIter<(K, V)> {
1009+
func process_scan_request<K, V, ReturnValue>(
1010+
btree : MemoryBTree,
1011+
btree_utils : BTreeUtils<K, V>,
1012+
start : ?K,
1013+
end : ?K,
1014+
kv_address_to_result_mapper : (Address) -> ReturnValue,
1015+
) : RevIter<ReturnValue> {
1016+
9671017
let start_address = switch (start) {
9681018
case (?key) {
9691019
let key_blob = btree_utils.key.blobify.to_blob(key);
@@ -1008,11 +1058,51 @@ module {
10081058

10091059
var j = if (end_index >= 0) Int.abs(end_index) + 1 else Int.abs(end_index) - 1 : Nat;
10101060

1011-
RevIter.map<(Blob, Blob), (K, V)>(
1012-
Methods.new_blobs_iterator(btree, start_address, i, end_address, j),
1013-
func((key_blob, val_blob) : (Blob, Blob)) : (K, V) {
1061+
RevIter.map<Address, ReturnValue>(
1062+
Methods.new_kv_block_address_iterator(btree, start_address, i, end_address, j),
1063+
kv_address_to_result_mapper,
1064+
);
1065+
1066+
};
1067+
1068+
public func scan<K, V>(btree : MemoryBTree, btree_utils : BTreeUtils<K, V>, start : ?K, end : ?K) : RevIter<(K, V)> {
1069+
process_scan_request<K, V, (K, V)>(
1070+
btree,
1071+
btree_utils,
1072+
start,
1073+
end,
1074+
func(kv_block_address : Address) : (K, V) {
1075+
let key_blob = MemoryBlock.get_key_blob(btree, kv_block_address);
1076+
let val_blob = MemoryBlock.get_val_blob(btree, kv_block_address);
1077+
10141078
Methods.deserialize_kv_blobs<K, V>(btree_utils, key_blob, val_blob);
10151079
},
10161080
);
10171081
};
1082+
1083+
public func scanKeys<K, V>(btree : MemoryBTree, btree_utils : BTreeUtils<K, V>, start : ?K, end : ?K) : RevIter<K> {
1084+
process_scan_request<K, V, K>(
1085+
btree,
1086+
btree_utils,
1087+
start,
1088+
end,
1089+
func(kv_block_address : Address) : K {
1090+
let key_blob = MemoryBlock.get_key_blob(btree, kv_block_address);
1091+
btree_utils.key.blobify.from_blob(key_blob);
1092+
},
1093+
);
1094+
};
1095+
1096+
public func scanVals<K, V>(btree : MemoryBTree, btree_utils : BTreeUtils<K, V>, start : ?K, end : ?K) : RevIter<V> {
1097+
process_scan_request<K, V, V>(
1098+
btree,
1099+
btree_utils,
1100+
start,
1101+
end,
1102+
func(kv_block_address : Address) : V {
1103+
let val_blob = MemoryBlock.get_val_blob(btree, kv_block_address);
1104+
btree_utils.value.blobify.from_blob(val_blob);
1105+
},
1106+
);
1107+
};
10181108
};

src/MemoryBTree/Stable.mo

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,31 @@ module StableMemoryBTree {
138138
MemoryBTree.scan(state, btree_utils, start, end);
139139
};
140140

141+
public func scanKeys<K, V>(btree : StableMemoryBTree, btree_utils : BTreeUtils<K, V>, start : ?K, end : ?K) : RevIter<K> {
142+
let state = Migrations.getCurrentVersion(btree);
143+
MemoryBTree.scanKeys(state, btree_utils, start, end);
144+
};
145+
146+
public func scanVals<K, V>(btree : StableMemoryBTree, btree_utils : BTreeUtils<K, V>, start : ?K, end : ?K) : RevIter<V> {
147+
let state = Migrations.getCurrentVersion(btree);
148+
MemoryBTree.scanVals(state, btree_utils, start, end);
149+
};
150+
141151
public func range<K, V>(btree : StableMemoryBTree, btree_utils : BTreeUtils<K, V>, start : Nat, end : Nat) : RevIter<(K, V)> {
142152
let state = Migrations.getCurrentVersion(btree);
143153
MemoryBTree.range(state, btree_utils, start, end);
144154
};
145155

156+
public func rangeKeys<K, V>(btree : StableMemoryBTree, btree_utils : BTreeUtils<K, V>, start : Nat, end : Nat) : RevIter<K> {
157+
let state = Migrations.getCurrentVersion(btree);
158+
MemoryBTree.rangeKeys(state, btree_utils, start, end);
159+
};
160+
161+
public func rangeVals<K, V>(btree : StableMemoryBTree, btree_utils : BTreeUtils<K, V>, start : Nat, end : Nat) : RevIter<V> {
162+
let state = Migrations.getCurrentVersion(btree);
163+
MemoryBTree.rangeVals(state, btree_utils, start, end);
164+
};
165+
146166
public func size(btree : StableMemoryBTree) : Nat {
147167
let state = Migrations.getCurrentVersion(btree);
148168
MemoryBTree.size(state);

src/MemoryBTree/lib.mo

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,21 @@ module {
139139
/// Returns a reversible iterator over the entries in the given range
140140
public func range(i : Nat, j : Nat) : RevIter<(K, V)> = BaseMemoryBTree.range(state, btree_utils, i, j);
141141

142-
/// Returns a reversible iterator over the entries in the given range
142+
/// Returns a reversible iterator over the keys in the given range
143+
public func rangeKeys(i : Nat, j : Nat) : RevIter<K> = BaseMemoryBTree.rangeKeys(state, btree_utils, i, j);
144+
145+
/// Returns a reversible iterator over the values in the given range
146+
public func rangeVals(i : Nat, j : Nat) : RevIter<V> = BaseMemoryBTree.rangeVals(state, btree_utils, i, j);
147+
148+
/// Returns a reversible iterator over the entries between the given keys
143149
public func scan(start : ?K, end : ?K) : RevIter<(K, V)> = BaseMemoryBTree.scan(state, btree_utils, start, end);
144150

151+
/// Returns a reversible iterator over the keys between the given ones
152+
public func scanKeys(start : ?K, end : ?K) : RevIter<K> = BaseMemoryBTree.scanKeys(state, btree_utils, start, end);
153+
154+
/// Returns a reversible iterator over the values between the given keys
155+
public func scanVals(start : ?K, end : ?K) : RevIter<V> = BaseMemoryBTree.scanVals(state, btree_utils, start, end);
156+
145157
/// Returns the number of entries in the BTree
146158
public func size() : Nat = BaseMemoryBTree.size(state);
147159

src/MemoryBTree/modules/Methods.mo

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ import T "Types";
1414
import Leaf "Leaf";
1515
import Branch "Branch";
1616
import Migrations "../Migrations";
17+
import MemoryBlock "MemoryBlock";
1718

18-
module {
19+
module Methods {
1920
type MemoryBTree = Migrations.MemoryBTree;
2021
type MemoryBlock = T.MemoryBlock;
2122

@@ -312,6 +313,110 @@ module {
312313
(get_node(root), search_index);
313314
};
314315

316+
public func new_kv_block_address_iterator(
317+
btree : MemoryBTree,
318+
start_leaf : Nat,
319+
start_index : Nat,
320+
end_leaf : Nat,
321+
end_index : Nat // exclusive
322+
) : RevIter<Address> {
323+
324+
var start = start_leaf;
325+
var i = start_index;
326+
var start_count = Leaf.get_count(btree, start_leaf);
327+
328+
var end = end_leaf;
329+
var j = end_index;
330+
331+
var terminate = false;
332+
333+
func next() : ?Address {
334+
if (terminate) return null;
335+
336+
if (start == end and i >= j) {
337+
return null;
338+
};
339+
340+
if (i >= start_count) {
341+
switch (Leaf.get_next(btree, start)) {
342+
case (null) {
343+
terminate := true;
344+
};
345+
case (?next_address) {
346+
start := next_address;
347+
start_count := Leaf.get_count(btree, next_address);
348+
};
349+
};
350+
351+
i := 0;
352+
return next();
353+
};
354+
355+
let opt_kv_block_address = Leaf.get_kv_address(btree, start, i);
356+
357+
i += 1;
358+
return opt_kv_block_address;
359+
};
360+
361+
func nextFromEnd() : ?Address {
362+
if (terminate) return null;
363+
364+
if (start == end and i >= j) return null;
365+
366+
if (j == 0) {
367+
switch (Leaf.get_prev(btree, end)) {
368+
case (null) terminate := true;
369+
case (?prev_address) {
370+
end := prev_address;
371+
j := Leaf.get_count(btree, prev_address);
372+
};
373+
};
374+
375+
return nextFromEnd();
376+
};
377+
378+
let opt_kv_block_address = Leaf.get_kv_address(btree, end, j - 1);
379+
380+
j -= 1;
381+
382+
return opt_kv_block_address;
383+
};
384+
385+
RevIter.new(next, nextFromEnd);
386+
};
387+
388+
public func KeyBlobIterator(
389+
btree : MemoryBTree,
390+
start_leaf : Nat,
391+
start_index : Nat,
392+
end_leaf : Nat,
393+
end_index : Nat,
394+
) : RevIter<Blob> {
395+
RevIter.map(
396+
new_kv_block_address_iterator(btree, start_leaf, start_index, end_leaf, end_index),
397+
func(kv_block_address : Address) : Blob {
398+
MemoryBlock.get_key_blob(btree, kv_block_address);
399+
},
400+
);
401+
};
402+
403+
public func ValueBlobIterator(
404+
btree : MemoryBTree,
405+
start_leaf : Nat,
406+
start_index : Nat,
407+
end_leaf : Nat,
408+
end_index : Nat,
409+
) : RevIter<Blob> {
410+
411+
RevIter.map(
412+
Methods.new_kv_block_address_iterator(btree, start_leaf, start_index, end_leaf, end_index),
413+
func(kv_block_address : Address) : Blob {
414+
MemoryBlock.get_val_blob(btree, kv_block_address);
415+
},
416+
)
417+
418+
};
419+
315420
public func new_blobs_iterator(
316421
btree : MemoryBTree,
317422
start_leaf : Nat,
@@ -424,6 +529,14 @@ module {
424529

425530
};
426531

532+
public func deserialize_key_blob<K>(btree_utils : BTreeUtils<K, Nat>, key_blob : Blob) : K {
533+
btree_utils.key.blobify.from_blob(key_blob);
534+
};
535+
536+
public func deserialize_val_blob<V>(btree_utils : BTreeUtils<Nat, V>, val_blob : Blob) : V {
537+
btree_utils.value.blobify.from_blob(val_blob);
538+
};
539+
427540
public func deserialize_kv_blobs<K, V>(btree_utils : BTreeUtils<K, V>, key_blob : Blob, val_blob : Blob) : (K, V) {
428541
let key = btree_utils.key.blobify.from_blob(key_blob);
429542
let value = btree_utils.value.blobify.from_blob(val_blob);

0 commit comments

Comments
 (0)