From 431511dd2904e56821657026beebdfeefda91a3b Mon Sep 17 00:00:00 2001 From: Faye Amacker <33205765+fxamacker@users.noreply.github.com> Date: Tue, 5 Mar 2024 13:44:00 -0600 Subject: [PATCH 1/2] Add Array.SetType() to allow updating TypeInfo --- array.go | 16 +++++++ array_test.go | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) diff --git a/array.go b/array.go index 7774f851..e07600d4 100644 --- a/array.go +++ b/array.go @@ -2371,6 +2371,22 @@ func (a *Array) Type() TypeInfo { return nil } +func (a *Array) SetType(typeInfo TypeInfo) error { + extraData := a.root.ExtraData() + extraData.TypeInfo = typeInfo + + a.root.SetExtraData(extraData) + + // Store modified root slab in storage since typeInfo is part of extraData stored in root slab. + err := a.Storage.Store(a.root.Header().id, a.root) + if err != nil { + // Wrap err as external error (if needed) because err is returned by SlabStorage interface. + return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.root.Header().id)) + } + + return nil +} + func (a *Array) String() string { iterator, err := a.Iterator() if err != nil { diff --git a/array_test.go b/array_test.go index c2a733b7..57896ecb 100644 --- a/array_test.go +++ b/array_test.go @@ -23,6 +23,7 @@ import ( "math" "math/rand" "reflect" + "runtime" "strings" "testing" @@ -3436,3 +3437,125 @@ func getArrayMetaDataSlabCount(storage *PersistentSlabStorage) int { } return counter } + +func TestArraySetType(t *testing.T) { + typeInfo := testTypeInfo{42} + newTypeInfo := testTypeInfo{43} + address := Address{1, 2, 3, 4, 5, 6, 7, 8} + + t.Run("empty", func(t *testing.T) { + storage := newTestPersistentStorage(t) + + // Create a new array in memory + array, err := NewArray(storage, address, typeInfo) + require.NoError(t, err) + require.Equal(t, uint64(0), array.Count()) + require.Equal(t, typeInfo, array.Type()) + require.True(t, array.root.IsData()) + + // Modify type info of new array + err = array.SetType(newTypeInfo) + require.NoError(t, err) + require.Equal(t, newTypeInfo, array.Type()) + + // Commit new array to storage + err = storage.FastCommit(runtime.NumCPU()) + require.NoError(t, err) + + testExistingArraySetType(t, array.StorageID(), storage.baseStorage, newTypeInfo, array.Count()) + }) + + t.Run("data slab root", func(t *testing.T) { + storage := newTestPersistentStorage(t) + + array, err := NewArray(storage, address, typeInfo) + require.NoError(t, err) + + arraySize := 10 + for i := 0; i < arraySize; i++ { + v := Uint64Value(i) + err := array.Append(v) + require.NoError(t, err) + } + + require.Equal(t, uint64(arraySize), array.Count()) + require.Equal(t, typeInfo, array.Type()) + require.True(t, array.root.IsData()) + + err = array.SetType(newTypeInfo) + require.NoError(t, err) + require.Equal(t, newTypeInfo, array.Type()) + + // Commit modified slabs in storage + err = storage.FastCommit(runtime.NumCPU()) + require.NoError(t, err) + + testExistingArraySetType(t, array.StorageID(), storage.baseStorage, newTypeInfo, array.Count()) + }) + + t.Run("metadata slab root", func(t *testing.T) { + storage := newTestPersistentStorage(t) + + array, err := NewArray(storage, address, typeInfo) + require.NoError(t, err) + + arraySize := 10_000 + for i := 0; i < arraySize; i++ { + v := Uint64Value(i) + err := array.Append(v) + require.NoError(t, err) + } + + require.Equal(t, uint64(arraySize), array.Count()) + require.Equal(t, typeInfo, array.Type()) + require.False(t, array.root.IsData()) + + err = array.SetType(newTypeInfo) + require.NoError(t, err) + require.Equal(t, newTypeInfo, array.Type()) + + // Commit modified slabs in storage + err = storage.FastCommit(runtime.NumCPU()) + require.NoError(t, err) + + testExistingArraySetType(t, array.StorageID(), storage.baseStorage, newTypeInfo, array.Count()) + }) +} + +func testExistingArraySetType( + t *testing.T, + id StorageID, + baseStorage BaseStorage, + expectedTypeInfo testTypeInfo, + expectedCount uint64, +) { + newTypeInfo := testTypeInfo{value: expectedTypeInfo.value + 1} + + // Create storage from existing data + storage := newTestPersistentStorageWithBaseStorage(t, baseStorage) + + // Load existing array by ID + array, err := NewArrayWithRootID(storage, id) + require.NoError(t, err) + require.Equal(t, expectedCount, array.Count()) + require.Equal(t, expectedTypeInfo, array.Type()) + + // Modify type info of existing array + err = array.SetType(newTypeInfo) + require.NoError(t, err) + require.Equal(t, expectedCount, array.Count()) + require.Equal(t, newTypeInfo, array.Type()) + + // Commit data in storage + err = storage.FastCommit(runtime.NumCPU()) + require.NoError(t, err) + + // Create storage from existing data + storage2 := newTestPersistentStorageWithBaseStorage(t, storage.baseStorage) + + // Load existing array again from storage + array2, err := NewArrayWithRootID(storage2, id) + require.NoError(t, err) + require.Equal(t, expectedCount, array2.Count()) + require.Equal(t, newTypeInfo, array2.Type()) +} From d8eaa1fd6e5a5bee23c47306d9e20f610c50f538 Mon Sep 17 00:00:00 2001 From: Faye Amacker <33205765+fxamacker@users.noreply.github.com> Date: Fri, 8 Mar 2024 09:12:58 -0600 Subject: [PATCH 2/2] Extract functionality of storeSlab for reuse --- array.go | 221 +++++++++++++++-------------------------------- basicarray.go | 21 +---- map.go | 201 +++++++++++++++--------------------------- storable_test.go | 2 +- storage.go | 10 +++ 5 files changed, 155 insertions(+), 300 deletions(-) diff --git a/array.go b/array.go index e07600d4..ffd640f0 100644 --- a/array.go +++ b/array.go @@ -489,10 +489,9 @@ func (a *ArrayDataSlab) Set(storage SlabStorage, address Address, index uint64, a.elements[index] = storable a.header.size = a.header.size - oldSize + storable.ByteSize() - err = storage.Store(a.header.id, a) + err = storeSlab(storage, a) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) + return nil, err } return oldElem, nil @@ -520,13 +519,7 @@ func (a *ArrayDataSlab) Insert(storage SlabStorage, address Address, index uint6 a.header.count++ a.header.size += storable.ByteSize() - err = storage.Store(a.header.id, a) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) - } - - return nil + return storeSlab(storage, a) } func (a *ArrayDataSlab) Remove(storage SlabStorage, index uint64) (Storable, error) { @@ -550,10 +543,9 @@ func (a *ArrayDataSlab) Remove(storage SlabStorage, index uint64) (Storable, err a.header.count-- a.header.size -= v.ByteSize() - err := storage.Store(a.header.id, a) + err := storeSlab(storage, a) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) + return nil, err } return v, nil @@ -1145,11 +1137,11 @@ func (a *ArrayMetaDataSlab) Set(storage SlabStorage, address Address, index uint return existingElem, nil } - err = storage.Store(a.header.id, a) + err = storeSlab(storage, a) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) + return nil, err } + return existingElem, nil } @@ -1210,13 +1202,7 @@ func (a *ArrayMetaDataSlab) Insert(storage SlabStorage, address Address, index u // Insertion always increases the size, // so there is no need to check underflow - err = storage.Store(a.header.id, a) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) - } - - return nil + return storeSlab(storage, a) } func (a *ArrayMetaDataSlab) Remove(storage SlabStorage, index uint64) (Storable, error) { @@ -1266,10 +1252,9 @@ func (a *ArrayMetaDataSlab) Remove(storage SlabStorage, index uint64) (Storable, // Removal always decreases the size, // so there is no need to check isFull - err = storage.Store(a.header.id, a) + err = storeSlab(storage, a) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) + return nil, err } return v, nil @@ -1302,25 +1287,17 @@ func (a *ArrayMetaDataSlab) SplitChildSlab(storage SlabStorage, child ArraySlab, a.header.size += arraySlabHeaderSize // Store modified slabs - err = storage.Store(left.ID(), left) + err = storeSlab(storage, left) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", left.ID())) - } - - err = storage.Store(right.ID(), right) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", right.ID())) + return err } - err = storage.Store(a.header.id, a) + err = storeSlab(storage, right) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) + return err } - return nil + return storeSlab(storage, a) } // MergeOrRebalanceChildSlab merges or rebalances child slab. @@ -1388,22 +1365,15 @@ func (a *ArrayMetaDataSlab) MergeOrRebalanceChildSlab( a.childrenCountSum[childHeaderIndex] = baseCountSum + child.Header().count // Store modified slabs - err = storage.Store(child.ID(), child) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", child.ID())) - } - err = storage.Store(rightSib.ID(), rightSib) + err = storeSlab(storage, child) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", rightSib.ID())) + return err } - err = storage.Store(a.header.id, a) + err = storeSlab(storage, rightSib) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) + return err } - return nil + return storeSlab(storage, a) } // Rebalance with left sib @@ -1423,22 +1393,15 @@ func (a *ArrayMetaDataSlab) MergeOrRebalanceChildSlab( a.childrenCountSum[childHeaderIndex-1] = baseCountSum + leftSib.Header().count // Store modified slabs - err = storage.Store(leftSib.ID(), leftSib) + err = storeSlab(storage, leftSib) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", leftSib.ID())) - } - err = storage.Store(child.ID(), child) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", child.ID())) + return err } - err = storage.Store(a.header.id, a) + err = storeSlab(storage, child) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) + return err } - return nil + return storeSlab(storage, a) } // Rebalance with bigger sib @@ -1458,22 +1421,16 @@ func (a *ArrayMetaDataSlab) MergeOrRebalanceChildSlab( a.childrenCountSum[childHeaderIndex-1] = baseCountSum + leftSib.Header().count // Store modified slabs - err = storage.Store(leftSib.ID(), leftSib) + err = storeSlab(storage, leftSib) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", leftSib.ID())) - } - err = storage.Store(child.ID(), child) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", child.ID())) + return err } - err = storage.Store(a.header.id, a) + err = storeSlab(storage, child) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) + return err } - return nil + return storeSlab(storage, a) + } else { // leftSib.ByteSize() <= rightSib.ByteSize @@ -1492,22 +1449,15 @@ func (a *ArrayMetaDataSlab) MergeOrRebalanceChildSlab( a.childrenCountSum[childHeaderIndex] = baseCountSum + child.Header().count // Store modified slabs - err = storage.Store(child.ID(), child) + err = storeSlab(storage, child) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", child.ID())) - } - err = storage.Store(rightSib.ID(), rightSib) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", rightSib.ID())) + return err } - err = storage.Store(a.header.id, a) + err = storeSlab(storage, rightSib) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) + return err } - return nil + return storeSlab(storage, a) } } @@ -1535,16 +1485,14 @@ func (a *ArrayMetaDataSlab) MergeOrRebalanceChildSlab( a.header.size -= arraySlabHeaderSize // Store modified slabs in storage - err = storage.Store(child.ID(), child) + err = storeSlab(storage, child) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", child.ID())) + return err } - err = storage.Store(a.header.id, a) + err = storeSlab(storage, a) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) + return err } // Remove right sib from storage @@ -1579,16 +1527,14 @@ func (a *ArrayMetaDataSlab) MergeOrRebalanceChildSlab( a.header.size -= arraySlabHeaderSize // Store modified slabs in storage - err = storage.Store(leftSib.ID(), leftSib) + err = storeSlab(storage, leftSib) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", leftSib.ID())) + return err } - err = storage.Store(a.header.id, a) + err = storeSlab(storage, a) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) + return err } // Remove child from storage @@ -1622,15 +1568,14 @@ func (a *ArrayMetaDataSlab) MergeOrRebalanceChildSlab( a.header.size -= arraySlabHeaderSize // Store modified slabs in storage - err = storage.Store(leftSib.ID(), leftSib) + err = storeSlab(storage, leftSib) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", leftSib.ID())) + return err } - err = storage.Store(a.header.id, a) + + err = storeSlab(storage, a) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) + return err } // Remove child from storage @@ -1663,15 +1608,13 @@ func (a *ArrayMetaDataSlab) MergeOrRebalanceChildSlab( a.header.size -= arraySlabHeaderSize // Store modified slabs in storage - err = storage.Store(child.ID(), child) + err = storeSlab(storage, child) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", child.ID())) + return err } - err = storage.Store(a.header.id, a) + err = storeSlab(storage, a) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) + return err } // Remove rightSib from storage @@ -1961,10 +1904,9 @@ func NewArray(storage SlabStorage, address Address, typeInfo TypeInfo) (*Array, extraData: extraData, } - err = storage.Store(root.header.id, root) + err = storeSlab(storage, root) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", root.header.id)) + return nil, err } return &Array{ @@ -2122,23 +2064,15 @@ func (a *Array) splitRoot() error { a.root = newRoot - err = a.Storage.Store(left.ID(), left) + err = storeSlab(a.Storage, left) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", left.ID())) - } - err = a.Storage.Store(right.ID(), right) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", right.ID())) + return err } - err = a.Storage.Store(a.root.ID(), a.root) + err = storeSlab(a.Storage, right) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.root.ID())) + return err } - - return nil + return storeSlab(a.Storage, a.root) } func (a *Array) promoteChildAsNewRoot(childID StorageID) error { @@ -2165,10 +2099,9 @@ func (a *Array) promoteChildAsNewRoot(childID StorageID) error { a.root.SetExtraData(extraData) - err = a.Storage.Store(rootID, a.root) + err = storeSlab(a.Storage, a.root) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", rootID)) + return err } err = a.Storage.Remove(childID) if err != nil { @@ -2378,13 +2311,7 @@ func (a *Array) SetType(typeInfo TypeInfo) error { a.root.SetExtraData(extraData) // Store modified root slab in storage since typeInfo is part of extraData stored in root slab. - err := a.Storage.Store(a.root.Header().id, a.root) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.root.Header().id)) - } - - return nil + return storeSlab(a.Storage, a.root) } func (a *Array) String() string { @@ -2492,13 +2419,7 @@ func (a *Array) PopIterate(fn ArrayPopIterationFunc) error { } // Save root slab - err = a.Storage.Store(a.root.ID(), a.root) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.root.ID())) - } - - return nil + return storeSlab(a.Storage, a.root) } type ArrayElementProvider func() (Value, error) @@ -2619,12 +2540,9 @@ func NewArrayFromBatchData(storage SlabStorage, address Address, typeInfo TypeIn // Store all slabs for _, slab := range slabs { - err = storage.Store(slab.ID(), slab) + err = storeSlab(storage, slab) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, wrapErrorfAsExternalErrorIfNeeded( - err, - fmt.Sprintf("failed to store slab %s", slab.ID())) + return nil, err } } @@ -2651,10 +2569,9 @@ func NewArrayFromBatchData(storage SlabStorage, address Address, typeInfo TypeIn root.SetExtraData(extraData) // Store root - err = storage.Store(root.ID(), root) + err = storeSlab(storage, root) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", root.ID())) + return nil, err } return &Array{ diff --git a/basicarray.go b/basicarray.go index fbf9a2bf..ea26edc7 100644 --- a/basicarray.go +++ b/basicarray.go @@ -155,13 +155,7 @@ func (a *BasicArrayDataSlab) Set(storage SlabStorage, index uint64, v Storable) oldElem.ByteSize() + v.ByteSize() - err := storage.Store(a.header.id, a) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) - } - - return nil + return storeSlab(storage, a) } func (a *BasicArrayDataSlab) Insert(storage SlabStorage, index uint64, v Storable) error { @@ -180,13 +174,7 @@ func (a *BasicArrayDataSlab) Insert(storage SlabStorage, index uint64, v Storabl a.header.count++ a.header.size += v.ByteSize() - err := storage.Store(a.header.id, a) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) - } - - return nil + return storeSlab(storage, a) } func (a *BasicArrayDataSlab) Remove(storage SlabStorage, index uint64) (Storable, error) { @@ -209,10 +197,9 @@ func (a *BasicArrayDataSlab) Remove(storage SlabStorage, index uint64) (Storable a.header.count-- a.header.size -= v.ByteSize() - err := storage.Store(a.header.id, a) + err := storeSlab(storage, a) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", a.header.id)) + return nil, err } return v, nil diff --git a/map.go b/map.go index c1633038..9415d591 100644 --- a/map.go +++ b/map.go @@ -801,10 +801,9 @@ func (e *inlineCollisionGroup) Set( collisionGroup: true, } - err = storage.Store(id, slab) + err = storeSlab(storage, slab) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", id)) + return nil, nil, err } // Create and return externalCollisionGroup (wrapper of newly created MapDataSlab) @@ -2334,10 +2333,9 @@ func (m *MapDataSlab) Set(storage SlabStorage, b DigesterBuilder, digester Diges } // Store modified slab - err = storage.Store(m.header.id, m) + err = storeSlab(storage, m) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.header.id)) + return nil, err } return existingValue, nil @@ -2362,10 +2360,9 @@ func (m *MapDataSlab) Remove(storage SlabStorage, digester Digester, level uint, } // Store modified slab - err = storage.Store(m.header.id, m) + err = storeSlab(storage, m) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.header.id)) + return nil, nil, err } return k, v, nil @@ -2857,10 +2854,9 @@ func (m *MapMetaDataSlab) Set(storage SlabStorage, b DigesterBuilder, digester D return existingValue, nil } - err = storage.Store(m.header.id, m) + err = storeSlab(storage, m) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.header.id)) + return nil, err } return existingValue, nil } @@ -2924,10 +2920,9 @@ func (m *MapMetaDataSlab) Remove(storage SlabStorage, digester Digester, level u return k, v, nil } - err = storage.Store(m.header.id, m) + err = storeSlab(storage, m) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.header.id)) + return nil, nil, err } return k, v, nil } @@ -2954,25 +2949,17 @@ func (m *MapMetaDataSlab) SplitChildSlab(storage SlabStorage, child MapSlab, chi m.header.size += mapSlabHeaderSize // Store modified slabs - err = storage.Store(left.ID(), left) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", left.ID())) - } - - err = storage.Store(right.ID(), right) + err = storeSlab(storage, left) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", right.ID())) + return err } - err = storage.Store(m.header.id, m) + err = storeSlab(storage, right) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.header.id)) + return err } - return nil + return storeSlab(storage, m) } // MergeOrRebalanceChildSlab merges or rebalances child slab. @@ -3045,24 +3032,17 @@ func (m *MapMetaDataSlab) MergeOrRebalanceChildSlab( } // Store modified slabs - err = storage.Store(child.ID(), child) + err = storeSlab(storage, child) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", child.ID())) + return err } - err = storage.Store(rightSib.ID(), rightSib) + err = storeSlab(storage, rightSib) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", rightSib.ID())) + return err } - err = storage.Store(m.header.id, m) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.header.id)) - } - return nil + return storeSlab(storage, m) } // Rebalance with left sib @@ -3078,24 +3058,17 @@ func (m *MapMetaDataSlab) MergeOrRebalanceChildSlab( m.childrenHeaders[childHeaderIndex] = child.Header() // Store modified slabs - err = storage.Store(leftSib.ID(), leftSib) + err = storeSlab(storage, leftSib) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", leftSib.ID())) + return err } - err = storage.Store(child.ID(), child) + err = storeSlab(storage, child) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", child.ID())) + return err } - err = storage.Store(m.header.id, m) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.header.id)) - } - return nil + return storeSlab(storage, m) } // Rebalance with bigger sib @@ -3111,24 +3084,17 @@ func (m *MapMetaDataSlab) MergeOrRebalanceChildSlab( m.childrenHeaders[childHeaderIndex] = child.Header() // Store modified slabs - err = storage.Store(leftSib.ID(), leftSib) + err = storeSlab(storage, leftSib) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", leftSib.ID())) + return err } - err = storage.Store(child.ID(), child) + err = storeSlab(storage, child) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", child.ID())) + return err } - err = storage.Store(m.header.id, m) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.header.id)) - } - return nil + return storeSlab(storage, m) } else { // leftSib.ByteSize() <= rightSib.ByteSize @@ -3147,24 +3113,17 @@ func (m *MapMetaDataSlab) MergeOrRebalanceChildSlab( } // Store modified slabs - err = storage.Store(child.ID(), child) + err = storeSlab(storage, child) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", child.ID())) + return err } - err = storage.Store(rightSib.ID(), rightSib) + err = storeSlab(storage, rightSib) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", rightSib.ID())) + return err } - err = storage.Store(m.header.id, m) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.header.id)) - } - return nil + return storeSlab(storage, m) } } @@ -3193,15 +3152,14 @@ func (m *MapMetaDataSlab) MergeOrRebalanceChildSlab( } // Store modified slabs in storage - err = storage.Store(child.ID(), child) + err = storeSlab(storage, child) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", child.ID())) + return err } - err = storage.Store(m.header.id, m) + + err = storeSlab(storage, m) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.header.id)) + return err } // Remove right sib from storage @@ -3210,6 +3168,7 @@ func (m *MapMetaDataSlab) MergeOrRebalanceChildSlab( // Wrap err as external error (if needed) because err is returned by SlabStorage interface. return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to remove slab %s", rightSib.ID())) } + return nil } @@ -3231,15 +3190,14 @@ func (m *MapMetaDataSlab) MergeOrRebalanceChildSlab( m.header.size -= mapSlabHeaderSize // Store modified slabs in storage - err = storage.Store(leftSib.ID(), leftSib) + err = storeSlab(storage, leftSib) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", leftSib.ID())) + return err } - err = storage.Store(m.header.id, m) + + err = storeSlab(storage, m) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.header.id)) + return err } // Remove child from storage @@ -3248,6 +3206,7 @@ func (m *MapMetaDataSlab) MergeOrRebalanceChildSlab( // Wrap err as external error (if needed) because err is returned by SlabStorage interface. return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to remove slab %s", child.ID())) } + return nil } @@ -3268,15 +3227,14 @@ func (m *MapMetaDataSlab) MergeOrRebalanceChildSlab( m.header.size -= mapSlabHeaderSize // Store modified slabs in storage - err = storage.Store(leftSib.ID(), leftSib) + err = storeSlab(storage, leftSib) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", leftSib.ID())) + return err } - err = storage.Store(m.header.id, m) + + err = storeSlab(storage, m) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.header.id)) + return err } // Remove child from storage @@ -3309,15 +3267,14 @@ func (m *MapMetaDataSlab) MergeOrRebalanceChildSlab( } // Store modified slabs in storage - err = storage.Store(child.ID(), child) + err = storeSlab(storage, child) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", child.ID())) + return err } - err = storage.Store(m.header.id, m) + + err = storeSlab(storage, m) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.header.id)) + return err } // Remove rightSib from storage @@ -3567,10 +3524,9 @@ func NewMap(storage SlabStorage, address Address, digestBuilder DigesterBuilder, extraData: extraData, } - err = storage.Store(root.header.id, root) + err = storeSlab(storage, root) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", root.header.id)) + return nil, err } return &OrderedMap{ @@ -3786,22 +3742,15 @@ func (m *OrderedMap) splitRoot() error { m.root = newRoot - err = m.Storage.Store(left.ID(), left) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", left.ID())) - } - err = m.Storage.Store(right.ID(), right) + err = storeSlab(m.Storage, left) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", right.ID())) + return err } - err = m.Storage.Store(m.root.ID(), m.root) + err = storeSlab(m.Storage, right) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.root.ID())) + return err } - return nil + return storeSlab(m.Storage, m.root) } func (m *OrderedMap) promoteChildAsNewRoot(childID StorageID) error { @@ -3828,10 +3777,9 @@ func (m *OrderedMap) promoteChildAsNewRoot(childID StorageID) error { m.root.SetExtraData(extraData) - err = m.Storage.Store(rootID, m.root) + err = storeSlab(m.Storage, m.root) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", rootID)) + return err } err = m.Storage.Remove(childID) @@ -4266,12 +4214,7 @@ func (m *OrderedMap) PopIterate(fn MapPopIterationFunc) error { } // Save root slab - err = m.Storage.Store(m.root.ID(), m.root) - if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", m.root.ID())) - } - return nil + return storeSlab(m.Storage, m.root) } func (m *OrderedMap) Seed() uint64 { @@ -4496,10 +4439,9 @@ func NewMapFromBatchData( // Store all slabs for _, slab := range slabs { - err = storage.Store(slab.ID(), slab) + err = storeSlab(storage, slab) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", slab.ID())) + return nil, err } } @@ -4526,10 +4468,9 @@ func NewMapFromBatchData( root.SetExtraData(extraData) // Store root - err = storage.Store(root.ID(), root) + err = storeSlab(storage, root) if err != nil { - // Wrap err as external error (if needed) because err is returned by SlabStorage interface. - return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", root.ID())) + return nil, err } return &OrderedMap{ diff --git a/storable_test.go b/storable_test.go index 6fe3ef05..615bc837 100644 --- a/storable_test.go +++ b/storable_test.go @@ -360,7 +360,7 @@ func (v StringValue) Storable(storage SlabStorage, address Address, maxInlineSiz } // Store StorableSlab in storage - err = storage.Store(id, slab) + err = storeSlab(storage, slab) if err != nil { return nil, err } diff --git a/storage.go b/storage.go index 3d0824a2..9dfbecb1 100644 --- a/storage.go +++ b/storage.go @@ -1017,3 +1017,13 @@ func (s *PersistentSlabStorage) DeltasSizeWithoutTempAddresses() uint64 { } return size } + +func storeSlab(storage SlabStorage, slab Slab) error { + id := slab.ID() + err := storage.Store(id, slab) + if err != nil { + // Wrap err as external error (if needed) because err is returned by SlabStorage interface. + return wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to store slab %s", id)) + } + return nil +}