From cf8254c0457d6fb80eb195b2ef4e09d6aed62168 Mon Sep 17 00:00:00 2001 From: Faye Amacker <33205765+fxamacker@users.noreply.github.com> Date: Tue, 18 Jul 2023 14:54:24 -0500 Subject: [PATCH] Add ReadOnly iterators and refactor other iterators This change: - Adds ReadOnly iterators that match current iterator API (except for the "ReadOnly" suffix added to some function names). - Refactors API of non-Readonly iterators because register inlining will require more parameters for MapIterator. For ReadOnly iterators, the caller is responsible for preventing changes to child containers during iteration because mutations of child containers are not guaranteed to persist. For non-ReadOnly iterators, two additional parameters are needed to update child container in parent map when child container is modified. --- array.go | 87 +++++++++++++++++++++++++++++---------------- array_bench_test.go | 4 +-- array_test.go | 48 ++++++++++++------------- cmd/stress/utils.go | 12 +++---- map.go | 76 ++++++++++++++++++++++++--------------- map_test.go | 36 +++++++++---------- utils_test.go | 8 ++--- 7 files changed, 158 insertions(+), 113 deletions(-) diff --git a/array.go b/array.go index f033f940..4b73ca6d 100644 --- a/array.go +++ b/array.go @@ -2195,6 +2195,7 @@ type ArrayIterator struct { dataSlab *ArrayDataSlab index int remainingCount int + readOnly bool } func (i *ArrayIterator) Next() (Value, error) { @@ -2257,6 +2258,19 @@ func (a *Array) Iterator() (*ArrayIterator, error) { }, nil } +// ReadOnlyIterator returns readonly iterator for array elements. +// If elements of child containers are mutated, those changes +// are not guaranteed to persist. +func (a *Array) ReadOnlyIterator() (*ArrayIterator, error) { + iterator, err := a.Iterator() + if err != nil { + // Don't need to wrap error as external error because err is already categorized by Iterator(). + return nil, err + } + iterator.readOnly = true + return iterator, nil +} + func (a *Array) RangeIterator(startIndex uint64, endIndex uint64) (*ArrayIterator, error) { count := a.Count() @@ -2307,16 +2321,18 @@ func (a *Array) RangeIterator(startIndex uint64, endIndex uint64) (*ArrayIterato }, nil } -type ArrayIterationFunc func(element Value) (resume bool, err error) - -func (a *Array) Iterate(fn ArrayIterationFunc) error { - - iterator, err := a.Iterator() +func (a *Array) ReadOnlyRangeIterator(startIndex uint64, endIndex uint64) (*ArrayIterator, error) { + iterator, err := a.RangeIterator(startIndex, endIndex) if err != nil { - // Don't need to wrap error as external error because err is already categorized by Array.Iterator(). - return err + return nil, err } + iterator.readOnly = true + return iterator, nil +} + +type ArrayIterationFunc func(element Value) (resume bool, err error) +func iterate(iterator *ArrayIterator, fn ArrayIterationFunc) error { for { value, err := iterator.Next() if err != nil { @@ -2337,33 +2353,42 @@ func (a *Array) Iterate(fn ArrayIterationFunc) error { } } -func (a *Array) IterateRange(startIndex uint64, endIndex uint64, fn ArrayIterationFunc) error { +func (a *Array) Iterate(fn ArrayIterationFunc) error { + iterator, err := a.Iterator() + if err != nil { + // Don't need to wrap error as external error because err is already categorized by Array.Iterator(). + return err + } + return iterate(iterator, fn) +} + +func (a *Array) IterateReadOnly(fn ArrayIterationFunc) error { + iterator, err := a.ReadOnlyIterator() + if err != nil { + // Don't need to wrap error as external error because err is already categorized by Array.ReadOnlyIterator(). + return err + } + return iterate(iterator, fn) +} +func (a *Array) IterateRange(startIndex uint64, endIndex uint64, fn ArrayIterationFunc) error { iterator, err := a.RangeIterator(startIndex, endIndex) if err != nil { // Don't need to wrap error as external error because err is already categorized by Array.RangeIterator(). return err } + return iterate(iterator, fn) +} - for { - value, err := iterator.Next() - if err != nil { - // Don't need to wrap error as external error because err is already categorized by ArrayIterator.Next(). - return err - } - if value == nil { - return nil - } - resume, err := fn(value) - if err != nil { - // Wrap err as external error (if needed) because err is returned by ArrayIterationFunc callback. - return wrapErrorAsExternalErrorIfNeeded(err) - } - if !resume { - return nil - } +func (a *Array) IterateReadOnlyRange(startIndex uint64, endIndex uint64, fn ArrayIterationFunc) error { + iterator, err := a.ReadOnlyRangeIterator(startIndex, endIndex) + if err != nil { + // Don't need to wrap error as external error because err is already categorized by Array.ReadOnlyRangeIterator(). + return err } + return iterate(iterator, fn) } + func (a *Array) Count() uint64 { return uint64(a.root.Header().count) } @@ -2390,7 +2415,7 @@ func (a *Array) Type() TypeInfo { } func (a *Array) String() string { - iterator, err := a.Iterator() + iterator, err := a.ReadOnlyIterator() if err != nil { return err.Error() } @@ -2863,8 +2888,8 @@ func (i *ArrayLoadedValueIterator) Next() (Value, error) { return nil, nil } -// LoadedValueIterator returns iterator to iterate loaded array elements. -func (a *Array) LoadedValueIterator() (*ArrayLoadedValueIterator, error) { +// ReadOnlyLoadedValueIterator returns iterator to iterate loaded array elements. +func (a *Array) ReadOnlyLoadedValueIterator() (*ArrayLoadedValueIterator, error) { switch slab := a.root.(type) { case *ArrayDataSlab: @@ -2902,9 +2927,9 @@ func (a *Array) LoadedValueIterator() (*ArrayLoadedValueIterator, error) { } } -// IterateLoadedValues iterates loaded array values. -func (a *Array) IterateLoadedValues(fn ArrayIterationFunc) error { - iterator, err := a.LoadedValueIterator() +// IterateReadOnlyLoadedValues iterates loaded array values. +func (a *Array) IterateReadOnlyLoadedValues(fn ArrayIterationFunc) error { + iterator, err := a.ReadOnlyLoadedValueIterator() if err != nil { // Don't need to wrap error as external error because err is already categorized by Array.LoadedValueIterator(). return err diff --git a/array_bench_test.go b/array_bench_test.go index 572abff8..b8c06cd0 100644 --- a/array_bench_test.go +++ b/array_bench_test.go @@ -355,7 +355,7 @@ func benchmarkNewArrayFromAppend(b *testing.B, initialArraySize int) { for i := 0; i < b.N; i++ { copied, _ := NewArray(storage, array.Address(), array.Type()) - _ = array.Iterate(func(value Value) (bool, error) { + _ = array.IterateReadOnly(func(value Value) (bool, error) { _ = copied.Append(value) return true, nil }) @@ -379,7 +379,7 @@ func benchmarkNewArrayFromBatchData(b *testing.B, initialArraySize int) { b.StartTimer() for i := 0; i < b.N; i++ { - iter, err := array.Iterator() + iter, err := array.ReadOnlyIterator() require.NoError(b, err) copied, _ := NewArrayFromBatchData(storage, array.Address(), array.Type(), func() (Value, error) { diff --git a/array_test.go b/array_test.go index f3c20f06..80c7846e 100644 --- a/array_test.go +++ b/array_test.go @@ -65,7 +65,7 @@ func verifyArray( // Verify array elements by iterator i := 0 - err = array.Iterate(func(v Value) (bool, error) { + err = array.IterateReadOnly(func(v Value) (bool, error) { valueEqual(t, typeInfoComparator, values[i], v) i++ return true, nil @@ -644,7 +644,7 @@ func TestArrayIterate(t *testing.T) { require.NoError(t, err) i := uint64(0) - err = array.Iterate(func(v Value) (bool, error) { + err = array.IterateReadOnly(func(v Value) (bool, error) { i++ return true, nil }) @@ -671,7 +671,7 @@ func TestArrayIterate(t *testing.T) { } i := uint64(0) - err = array.Iterate(func(v Value) (bool, error) { + err = array.IterateReadOnly(func(v Value) (bool, error) { require.Equal(t, Uint64Value(i), v) i++ return true, nil @@ -708,7 +708,7 @@ func TestArrayIterate(t *testing.T) { } i := uint64(0) - err = array.Iterate(func(v Value) (bool, error) { + err = array.IterateReadOnly(func(v Value) (bool, error) { require.Equal(t, Uint64Value(i), v) i++ return true, nil @@ -741,7 +741,7 @@ func TestArrayIterate(t *testing.T) { } i := uint64(0) - err = array.Iterate(func(v Value) (bool, error) { + err = array.IterateReadOnly(func(v Value) (bool, error) { require.Equal(t, Uint64Value(i), v) i++ return true, nil @@ -777,7 +777,7 @@ func TestArrayIterate(t *testing.T) { i := uint64(0) j := uint64(1) - err = array.Iterate(func(v Value) (bool, error) { + err = array.IterateReadOnly(func(v Value) (bool, error) { require.Equal(t, Uint64Value(j), v) i++ j += 2 @@ -803,7 +803,7 @@ func TestArrayIterate(t *testing.T) { } i := 0 - err = array.Iterate(func(_ Value) (bool, error) { + err = array.IterateReadOnly(func(_ Value) (bool, error) { if i == count/2 { return false, nil } @@ -832,7 +832,7 @@ func TestArrayIterate(t *testing.T) { testErr := errors.New("test") i := 0 - err = array.Iterate(func(_ Value) (bool, error) { + err = array.IterateReadOnly(func(_ Value) (bool, error) { if i == count/2 { return false, testErr } @@ -858,7 +858,7 @@ func testArrayIterateRange(t *testing.T, array *Array, values []Value) { count := array.Count() // If startIndex > count, IterateRange returns SliceOutOfBoundsError - err = array.IterateRange(count+1, count+1, func(v Value) (bool, error) { + err = array.IterateReadOnlyRange(count+1, count+1, func(v Value) (bool, error) { i++ return true, nil }) @@ -871,7 +871,7 @@ func testArrayIterateRange(t *testing.T, array *Array, values []Value) { require.Equal(t, uint64(0), i) // If endIndex > count, IterateRange returns SliceOutOfBoundsError - err = array.IterateRange(0, count+1, func(v Value) (bool, error) { + err = array.IterateReadOnlyRange(0, count+1, func(v Value) (bool, error) { i++ return true, nil }) @@ -883,7 +883,7 @@ func testArrayIterateRange(t *testing.T, array *Array, values []Value) { // If startIndex > endIndex, IterateRange returns InvalidSliceIndexError if count > 0 { - err = array.IterateRange(1, 0, func(v Value) (bool, error) { + err = array.IterateReadOnlyRange(1, 0, func(v Value) (bool, error) { i++ return true, nil }) @@ -898,7 +898,7 @@ func testArrayIterateRange(t *testing.T, array *Array, values []Value) { for startIndex := uint64(0); startIndex <= count; startIndex++ { for endIndex := startIndex; endIndex <= count; endIndex++ { i = uint64(0) - err = array.IterateRange(startIndex, endIndex, func(v Value) (bool, error) { + err = array.IterateReadOnlyRange(startIndex, endIndex, func(v Value) (bool, error) { valueEqual(t, typeInfoComparator, v, values[int(startIndex+i)]) i++ return true, nil @@ -980,7 +980,7 @@ func TestArrayIterateRange(t *testing.T) { startIndex := uint64(1) endIndex := uint64(5) count := endIndex - startIndex - err = array.IterateRange(startIndex, endIndex, func(_ Value) (bool, error) { + err = array.IterateReadOnlyRange(startIndex, endIndex, func(_ Value) (bool, error) { if i == count/2 { return false, nil } @@ -1009,7 +1009,7 @@ func TestArrayIterateRange(t *testing.T) { startIndex := uint64(1) endIndex := uint64(5) count := endIndex - startIndex - err = array.IterateRange(startIndex, endIndex, func(_ Value) (bool, error) { + err = array.IterateReadOnlyRange(startIndex, endIndex, func(_ Value) (bool, error) { if i == count/2 { return false, testErr } @@ -1846,7 +1846,7 @@ func TestEmptyArray(t *testing.T) { t.Run("iterate", func(t *testing.T) { i := uint64(0) - err := array.Iterate(func(v Value) (bool, error) { + err := array.IterateReadOnly(func(v Value) (bool, error) { i++ return true, nil }) @@ -2088,7 +2088,7 @@ func TestArrayFromBatchData(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(0), array.Count()) - iter, err := array.Iterator() + iter, err := array.ReadOnlyIterator() require.NoError(t, err) // Create a new array with new storage, new address, and original array's elements. @@ -2128,7 +2128,7 @@ func TestArrayFromBatchData(t *testing.T) { require.Equal(t, uint64(arraySize), array.Count()) - iter, err := array.Iterator() + iter, err := array.ReadOnlyIterator() require.NoError(t, err) // Create a new array with new storage, new address, and original array's elements. @@ -2172,7 +2172,7 @@ func TestArrayFromBatchData(t *testing.T) { require.Equal(t, uint64(arraySize), array.Count()) - iter, err := array.Iterator() + iter, err := array.ReadOnlyIterator() require.NoError(t, err) address := Address{2, 3, 4, 5, 6, 7, 8, 9} @@ -2222,7 +2222,7 @@ func TestArrayFromBatchData(t *testing.T) { require.Equal(t, uint64(36), array.Count()) - iter, err := array.Iterator() + iter, err := array.ReadOnlyIterator() require.NoError(t, err) storage := newTestPersistentStorage(t) @@ -2272,7 +2272,7 @@ func TestArrayFromBatchData(t *testing.T) { require.Equal(t, uint64(36), array.Count()) - iter, err := array.Iterator() + iter, err := array.ReadOnlyIterator() require.NoError(t, err) storage := newTestPersistentStorage(t) @@ -2318,7 +2318,7 @@ func TestArrayFromBatchData(t *testing.T) { require.Equal(t, uint64(arraySize), array.Count()) - iter, err := array.Iterator() + iter, err := array.ReadOnlyIterator() require.NoError(t, err) storage := newTestPersistentStorage(t) @@ -2373,7 +2373,7 @@ func TestArrayFromBatchData(t *testing.T) { err = array.Append(v) require.NoError(t, err) - iter, err := array.Iterator() + iter, err := array.ReadOnlyIterator() require.NoError(t, err) storage := newTestPersistentStorage(t) @@ -2738,7 +2738,7 @@ func TestArrayLoadedValueIterator(t *testing.T) { verifyArrayLoadedElements(t, array, values) i := 0 - err := array.IterateLoadedValues(func(v Value) (bool, error) { + err := array.IterateReadOnlyLoadedValues(func(v Value) (bool, error) { // At this point, iterator returned first element (v). // Remove all other nested composite elements (except first element) from storage. @@ -3414,7 +3414,7 @@ func createArrayWithSimpleAndCompositeValues( func verifyArrayLoadedElements(t *testing.T, array *Array, expectedValues []Value) { i := 0 - err := array.IterateLoadedValues(func(v Value) (bool, error) { + err := array.IterateReadOnlyLoadedValues(func(v Value) (bool, error) { require.True(t, i < len(expectedValues)) valueEqual(t, typeInfoComparator, expectedValues[i], v) i++ diff --git a/cmd/stress/utils.go b/cmd/stress/utils.go index c75296fe..96f72584 100644 --- a/cmd/stress/utils.go +++ b/cmd/stress/utils.go @@ -132,7 +132,7 @@ func copyValue(storage *atree.PersistentSlabStorage, address atree.Address, valu } func copyArray(storage *atree.PersistentSlabStorage, address atree.Address, array *atree.Array) (*atree.Array, error) { - iterator, err := array.Iterator() + iterator, err := array.ReadOnlyIterator() if err != nil { return nil, err } @@ -149,7 +149,7 @@ func copyArray(storage *atree.PersistentSlabStorage, address atree.Address, arra } func copyMap(storage *atree.PersistentSlabStorage, address atree.Address, m *atree.OrderedMap) (*atree.OrderedMap, error) { - iterator, err := m.Iterator() + iterator, err := m.ReadOnlyIterator() if err != nil { return nil, err } @@ -260,12 +260,12 @@ func arrayEqual(a atree.Value, b atree.Value) error { return fmt.Errorf("array %s count %d != array %s count %d", array1, array1.Count(), array2, array2.Count()) } - iterator1, err := array1.Iterator() + iterator1, err := array1.ReadOnlyIterator() if err != nil { return fmt.Errorf("failed to get array1 iterator: %w", err) } - iterator2, err := array2.Iterator() + iterator2, err := array2.ReadOnlyIterator() if err != nil { return fmt.Errorf("failed to get array2 iterator: %w", err) } @@ -309,12 +309,12 @@ func mapEqual(a atree.Value, b atree.Value) error { return fmt.Errorf("map %s count %d != map %s count %d", m1, m1.Count(), m2, m2.Count()) } - iterator1, err := m1.Iterator() + iterator1, err := m1.ReadOnlyIterator() if err != nil { return fmt.Errorf("failed to get m1 iterator: %w", err) } - iterator2, err := m2.Iterator() + iterator2, err := m2.ReadOnlyIterator() if err != nil { return fmt.Errorf("failed to get m2 iterator: %w", err) } diff --git a/map.go b/map.go index 288d80b0..517192fe 100644 --- a/map.go +++ b/map.go @@ -3630,6 +3630,7 @@ func (m *OrderedMap) Get(comparator ValueComparator, hip HashInputProvider, key // Wrap err as external error (if needed) because err is returned by Storable interface. return nil, wrapErrorfAsExternalErrorIfNeeded(err, "failed to get storable's stored value") } + return v, nil } @@ -3895,7 +3896,7 @@ func (m *OrderedMap) Type() TypeInfo { } func (m *OrderedMap) String() string { - iterator, err := m.Iterator() + iterator, err := m.ReadOnlyIterator() if err != nil { return err.Error() } @@ -3954,19 +3955,19 @@ func (m *MapExtraData) decrementCount() { m.Count-- } -type MapElementIterator struct { +type mapElementIterator struct { storage SlabStorage elements elements index int - nestedIterator *MapElementIterator + nestedIterator *mapElementIterator } -func (i *MapElementIterator) Next() (key MapKey, value MapValue, err error) { +func (i *mapElementIterator) next() (key MapKey, value MapValue, err error) { if i.nestedIterator != nil { - key, value, err = i.nestedIterator.Next() + key, value, err = i.nestedIterator.next() if err != nil { - // Don't need to wrap error as external error because err is already categorized by MapElementIterator.Next(). + // Don't need to wrap error as external error because err is already categorized by mapElementIterator.next(). return nil, nil, err } if key != nil { @@ -3997,14 +3998,14 @@ func (i *MapElementIterator) Next() (key MapKey, value MapValue, err error) { return nil, nil, err } - i.nestedIterator = &MapElementIterator{ + i.nestedIterator = &mapElementIterator{ storage: i.storage, elements: elems, } i.index++ // Don't need to wrap error as external error because err is already categorized by MapElementIterator.Next(). - return i.nestedIterator.Next() + return i.nestedIterator.next() default: return nil, nil, NewSlabDataError(fmt.Errorf("unexpected element type %T during map iteration", e)) @@ -4016,8 +4017,10 @@ type MapElementIterationFunc func(Value) (resume bool, err error) type MapIterator struct { storage SlabStorage + comparator ValueComparator // TODO: use comparator and hip to update child element in parent map in register inlining. + hip HashInputProvider id SlabID - elemIterator *MapElementIterator + elemIterator *mapElementIterator } func (i *MapIterator) Next() (key Value, value Value, err error) { @@ -4034,7 +4037,7 @@ func (i *MapIterator) Next() (key Value, value Value, err error) { } var ks, vs Storable - ks, vs, err = i.elemIterator.Next() + ks, vs, err = i.elemIterator.next() if err != nil { // Don't need to wrap error as external error because err is already categorized by MapElementIterator.Next(). return nil, nil, err @@ -4075,7 +4078,7 @@ func (i *MapIterator) NextKey() (key Value, err error) { } var ks Storable - ks, _, err = i.elemIterator.Next() + ks, _, err = i.elemIterator.next() if err != nil { // Don't need to wrap error as external error because err is already categorized by MapElementIterator.Next(). return nil, err @@ -4110,7 +4113,7 @@ func (i *MapIterator) NextValue() (value Value, err error) { } var vs Storable - _, vs, err = i.elemIterator.Next() + _, vs, err = i.elemIterator.next() if err != nil { // Don't need to wrap error as external error because err is already categorized by MapElementIterator.Next(). return nil, err @@ -4148,7 +4151,7 @@ func (i *MapIterator) advance() error { i.id = dataSlab.next - i.elemIterator = &MapElementIterator{ + i.elemIterator = &mapElementIterator{ storage: i.storage, elements: dataSlab.elements, } @@ -4156,7 +4159,7 @@ func (i *MapIterator) advance() error { return nil } -func (m *OrderedMap) Iterator() (*MapIterator, error) { +func (m *OrderedMap) Iterator(comparator ValueComparator, hip HashInputProvider) (*MapIterator, error) { slab, err := firstMapDataSlab(m.Storage, m.root) if err != nil { // Don't need to wrap error as external error because err is already categorized by firstMapDataSlab(). @@ -4166,18 +4169,27 @@ func (m *OrderedMap) Iterator() (*MapIterator, error) { dataSlab := slab.(*MapDataSlab) return &MapIterator{ - storage: m.Storage, - id: dataSlab.next, - elemIterator: &MapElementIterator{ + storage: m.Storage, + comparator: comparator, + hip: hip, + id: dataSlab.next, + elemIterator: &mapElementIterator{ storage: m.Storage, elements: dataSlab.elements, }, }, nil } -func (m *OrderedMap) Iterate(fn MapEntryIterationFunc) error { +// ReadOnlyIterator returns readonly iterator for map elements. +// If elements of child containers are mutated, those changes +// are not guaranteed to persist. +func (m *OrderedMap) ReadOnlyIterator() (*MapIterator, error) { + return m.Iterator(nil, nil) +} + +func (m *OrderedMap) Iterate(comparator ValueComparator, hip HashInputProvider, fn MapEntryIterationFunc) error { - iterator, err := m.Iterator() + iterator, err := m.Iterator(comparator, hip) if err != nil { // Don't need to wrap error as external error because err is already categorized by OrderedMap.Iterator(). return err @@ -4204,9 +4216,13 @@ func (m *OrderedMap) Iterate(fn MapEntryIterationFunc) error { } } -func (m *OrderedMap) IterateKeys(fn MapElementIterationFunc) error { +func (m *OrderedMap) IterateReadOnly(fn MapEntryIterationFunc) error { + return m.Iterate(nil, nil, fn) +} - iterator, err := m.Iterator() +func (m *OrderedMap) IterateReadOnlyKeys(fn MapElementIterationFunc) error { + + iterator, err := m.ReadOnlyIterator() if err != nil { // Don't need to wrap error as external error because err is already categorized by OrderedMap.Iterator(). return err @@ -4233,9 +4249,9 @@ func (m *OrderedMap) IterateKeys(fn MapElementIterationFunc) error { } } -func (m *OrderedMap) IterateValues(fn MapElementIterationFunc) error { +func (m *OrderedMap) IterateValues(comparator ValueComparator, hip HashInputProvider, fn MapElementIterationFunc) error { - iterator, err := m.Iterator() + iterator, err := m.Iterator(comparator, hip) if err != nil { // Don't need to wrap error as external error because err is already categorized by OrderedMap.Iterator(). return err @@ -4262,6 +4278,10 @@ func (m *OrderedMap) IterateValues(fn MapElementIterationFunc) error { } } +func (m *OrderedMap) IterateReadOnlyValues(fn MapElementIterationFunc) error { + return m.IterateValues(nil, nil, fn) +} + type MapPopIterationFunc func(Storable, Storable) // PopIterate iterates and removes elements backward. @@ -4848,8 +4868,8 @@ func (i *MapLoadedValueIterator) Next() (Value, Value, error) { return nil, nil, nil } -// LoadedValueIterator returns iterator to iterate loaded map elements. -func (m *OrderedMap) LoadedValueIterator() (*MapLoadedValueIterator, error) { +// ReadOnlyLoadedValueIterator returns iterator to iterate loaded map elements. +func (m *OrderedMap) ReadOnlyLoadedValueIterator() (*MapLoadedValueIterator, error) { switch slab := m.root.(type) { case *MapDataSlab: @@ -4887,9 +4907,9 @@ func (m *OrderedMap) LoadedValueIterator() (*MapLoadedValueIterator, error) { } } -// IterateLoadedValues iterates loaded map values. -func (m *OrderedMap) IterateLoadedValues(fn MapEntryIterationFunc) error { - iterator, err := m.LoadedValueIterator() +// IterateReadOnlyLoadedValues iterates loaded map values. +func (m *OrderedMap) IterateReadOnlyLoadedValues(fn MapEntryIterationFunc) error { + iterator, err := m.ReadOnlyLoadedValueIterator() if err != nil { // Don't need to wrap error as external error because err is already categorized by OrderedMap.LoadedValueIterator(). return err diff --git a/map_test.go b/map_test.go index 0850ac12..3322570e 100644 --- a/map_test.go +++ b/map_test.go @@ -130,7 +130,7 @@ func verifyMap( require.Equal(t, len(keyValues), len(sortedKeys)) i := 0 - err = m.Iterate(func(k, v Value) (bool, error) { + err = m.IterateReadOnly(func(k, v Value) (bool, error) { expectedKey := sortedKeys[i] expectedValue := keyValues[expectedKey] @@ -1086,7 +1086,7 @@ func TestMapIterate(t *testing.T) { // Iterate key value pairs i = uint64(0) - err = m.Iterate(func(k Value, v Value) (resume bool, err error) { + err = m.IterateReadOnly(func(k Value, v Value) (resume bool, err error) { valueEqual(t, typeInfoComparator, sortedKeys[i], k) valueEqual(t, typeInfoComparator, keyValues[k], v) i++ @@ -1098,7 +1098,7 @@ func TestMapIterate(t *testing.T) { // Iterate keys i = uint64(0) - err = m.IterateKeys(func(k Value) (resume bool, err error) { + err = m.IterateReadOnlyKeys(func(k Value) (resume bool, err error) { valueEqual(t, typeInfoComparator, sortedKeys[i], k) i++ return true, nil @@ -1109,7 +1109,7 @@ func TestMapIterate(t *testing.T) { // Iterate values i = uint64(0) - err = m.IterateValues(func(v Value) (resume bool, err error) { + err = m.IterateReadOnlyValues(func(v Value) (resume bool, err error) { k := sortedKeys[i] valueEqual(t, typeInfoComparator, keyValues[k], v) i++ @@ -1172,7 +1172,7 @@ func TestMapIterate(t *testing.T) { // Iterate key value pairs i := uint64(0) - err = m.Iterate(func(k Value, v Value) (resume bool, err error) { + err = m.IterateReadOnly(func(k Value, v Value) (resume bool, err error) { valueEqual(t, typeInfoComparator, sortedKeys[i], k) valueEqual(t, typeInfoComparator, keyValues[k], v) i++ @@ -1185,7 +1185,7 @@ func TestMapIterate(t *testing.T) { // Iterate keys i = uint64(0) - err = m.IterateKeys(func(k Value) (resume bool, err error) { + err = m.IterateReadOnlyKeys(func(k Value) (resume bool, err error) { valueEqual(t, typeInfoComparator, sortedKeys[i], k) i++ return true, nil @@ -1197,7 +1197,7 @@ func TestMapIterate(t *testing.T) { // Iterate values i = uint64(0) - err = m.IterateValues(func(v Value) (resume bool, err error) { + err = m.IterateReadOnlyValues(func(v Value) (resume bool, err error) { valueEqual(t, typeInfoComparator, keyValues[sortedKeys[i]], v) i++ return true, nil @@ -3058,7 +3058,7 @@ func TestEmptyMap(t *testing.T) { t.Run("iterate", func(t *testing.T) { i := 0 - err := m.Iterate(func(k Value, v Value) (bool, error) { + err := m.IterateReadOnly(func(k Value, v Value) (bool, error) { i++ return true, nil }) @@ -3096,7 +3096,7 @@ func TestMapFromBatchData(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(0), m.Count()) - iter, err := m.Iterator() + iter, err := m.ReadOnlyIterator() require.NoError(t, err) storage := newTestPersistentStorage(t) @@ -3143,7 +3143,7 @@ func TestMapFromBatchData(t *testing.T) { require.Equal(t, uint64(mapSize), m.Count()) - iter, err := m.Iterator() + iter, err := m.ReadOnlyIterator() require.NoError(t, err) var sortedKeys []Value @@ -3205,7 +3205,7 @@ func TestMapFromBatchData(t *testing.T) { require.Equal(t, uint64(mapSize), m.Count()) - iter, err := m.Iterator() + iter, err := m.ReadOnlyIterator() require.NoError(t, err) var sortedKeys []Value @@ -3270,7 +3270,7 @@ func TestMapFromBatchData(t *testing.T) { require.Equal(t, uint64(mapSize+1), m.Count()) - iter, err := m.Iterator() + iter, err := m.ReadOnlyIterator() require.NoError(t, err) var sortedKeys []Value @@ -3339,7 +3339,7 @@ func TestMapFromBatchData(t *testing.T) { require.Equal(t, uint64(mapSize+1), m.Count()) require.Equal(t, typeInfo, m.Type()) - iter, err := m.Iterator() + iter, err := m.ReadOnlyIterator() require.NoError(t, err) var sortedKeys []Value @@ -3402,7 +3402,7 @@ func TestMapFromBatchData(t *testing.T) { require.Equal(t, uint64(mapSize), m.Count()) - iter, err := m.Iterator() + iter, err := m.ReadOnlyIterator() require.NoError(t, err) storage := newTestPersistentStorage(t) @@ -3483,7 +3483,7 @@ func TestMapFromBatchData(t *testing.T) { require.Equal(t, uint64(mapSize), m.Count()) - iter, err := m.Iterator() + iter, err := m.ReadOnlyIterator() require.NoError(t, err) var sortedKeys []Value @@ -3567,7 +3567,7 @@ func TestMapFromBatchData(t *testing.T) { require.NoError(t, err) require.Nil(t, storable) - iter, err := m.Iterator() + iter, err := m.ReadOnlyIterator() require.NoError(t, err) var sortedKeys []Value @@ -4844,7 +4844,7 @@ func TestMapLoadedValueIterator(t *testing.T) { verifyMapLoadedElements(t, m, values) i := 0 - err := m.IterateLoadedValues(func(k Value, v Value) (bool, error) { + err := m.IterateReadOnlyLoadedValues(func(k Value, v Value) (bool, error) { // At this point, iterator returned first element (v). // Remove all other nested composite elements (except first element) from storage. @@ -5746,7 +5746,7 @@ func createMapWithSimpleAndCompositeValues( func verifyMapLoadedElements(t *testing.T, m *OrderedMap, expectedValues [][2]Value) { i := 0 - err := m.IterateLoadedValues(func(k Value, v Value) (bool, error) { + err := m.IterateReadOnlyLoadedValues(func(k Value, v Value) (bool, error) { require.True(t, i < len(expectedValues)) valueEqual(t, typeInfoComparator, expectedValues[i][0], k) valueEqual(t, typeInfoComparator, expectedValues[i][1], v) diff --git a/utils_test.go b/utils_test.go index a40a3599..67b56471 100644 --- a/utils_test.go +++ b/utils_test.go @@ -287,10 +287,10 @@ func arrayEqual(t *testing.T, tic TypeInfoComparator, a Value, b Value) { require.Equal(t, array1.Count(), array2.Count()) require.Equal(t, array1.SlabID(), array2.SlabID()) - iterator1, err := array1.Iterator() + iterator1, err := array1.ReadOnlyIterator() require.NoError(t, err) - iterator2, err := array2.Iterator() + iterator2, err := array2.ReadOnlyIterator() require.NoError(t, err) for { @@ -320,10 +320,10 @@ func mapEqual(t *testing.T, tic TypeInfoComparator, a Value, b Value) { require.Equal(t, m1.Count(), m2.Count()) require.Equal(t, m1.SlabID(), m2.SlabID()) - iterator1, err := m1.Iterator() + iterator1, err := m1.ReadOnlyIterator() require.NoError(t, err) - iterator2, err := m2.Iterator() + iterator2, err := m2.ReadOnlyIterator() require.NoError(t, err) for {