@@ -877,3 +877,84 @@ func (n *Node) ForEach(ctx context.Context, f func(k string, val *cbg.Deferred)
877
877
}
878
878
return nil
879
879
}
880
+
881
+ // ForEachTracked recursively calls function f on each k / val pair found in the HAMT.
882
+ // This performs a full traversal of the graph and for large HAMTs can cause
883
+ // a large number of loads from the underlying store.
884
+ // The values are returned as raw bytes, not decoded.
885
+ // This method also provides the trail of indices to the current node, which can be used to formulate a selector suffix
886
+ func (n * Node ) ForEachTracked (ctx context.Context , trail []int , f func (k string , val * cbg.Deferred , selectorSuffix []int ) error ) error {
887
+ idx := 0
888
+ for _ , p := range n .Pointers {
889
+ // Seek the next set bit in the bitfield to find the actual index for this pointer
890
+ for n .Bitfield .Bit (idx ) == 0 {
891
+ idx ++
892
+ }
893
+ trail = append (trail , idx )
894
+ if p .isShard () {
895
+ chnd , err := p .loadChild (ctx , n .store , n .bitWidth , n .hash )
896
+ if err != nil {
897
+ return err
898
+ }
899
+
900
+ if err := chnd .ForEachTracked (ctx , trail , f ); err != nil {
901
+ return err
902
+ }
903
+ } else {
904
+ for _ , kv := range p .KVs {
905
+ if err := f (string (kv .Key ), kv .Value , trail ); err != nil {
906
+ return err
907
+ }
908
+ }
909
+ }
910
+ idx ++
911
+ }
912
+ return nil
913
+ }
914
+
915
+ // ForEachTrackedWithNodeSink recursively calls function f on each k / val pair found in the HAMT.
916
+ // This performs a full traversal of the graph and for large HAMTs can cause
917
+ // a large number of loads from the underlying store.
918
+ // The values are returned as raw bytes, not decoded.
919
+ // This method also provides the trail of indices to the current node, which can be used to formulate a selector suffix
920
+ // This method also provides a callback to sink the current node
921
+ func (n * Node ) ForEachTrackedWithNodeSink (ctx context.Context , trail []int , b * bytes.Buffer , sink cbg.CBORUnmarshaler , f func (k string , val * cbg.Deferred , selectorSuffix []int ) error ) error {
922
+ if sink != nil {
923
+ if b == nil {
924
+ b = bytes .NewBuffer (nil )
925
+ }
926
+ b .Reset ()
927
+ if err := n .MarshalCBOR (b ); err != nil {
928
+ return err
929
+ }
930
+ if err := sink .UnmarshalCBOR (b ); err != nil {
931
+ return err
932
+ }
933
+ }
934
+ idx := 0
935
+ for _ , p := range n .Pointers {
936
+ // Seek the next set bit in the bitfield to find the actual index for this pointer
937
+ for n .Bitfield .Bit (idx ) == 0 {
938
+ idx ++
939
+ }
940
+ trail = append (trail , idx )
941
+ if p .isShard () {
942
+ chnd , err := p .loadChild (ctx , n .store , n .bitWidth , n .hash )
943
+ if err != nil {
944
+ return err
945
+ }
946
+
947
+ if err := chnd .ForEachTrackedWithNodeSink (ctx , trail , b , sink , f ); err != nil {
948
+ return err
949
+ }
950
+ } else {
951
+ for _ , kv := range p .KVs {
952
+ if err := f (string (kv .Key ), kv .Value , trail ); err != nil {
953
+ return err
954
+ }
955
+ }
956
+ }
957
+ idx ++
958
+ }
959
+ return nil
960
+ }
0 commit comments