Skip to content

Commit

Permalink
Merge pull request #450 from onflow/fxamacker/add-HasDelta-by-address…
Browse files Browse the repository at this point in the history
…-to-storage

Add function to check if address has unsaved changes in storage
  • Loading branch information
fxamacker authored Oct 25, 2024
2 parents a038b0c + 8f811d3 commit 5941314
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
12 changes: 12 additions & 0 deletions storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,13 +594,24 @@ type PersistentSlabStorage struct {

var _ SlabStorage = &PersistentSlabStorage{}

// HasUnsavedChanges returns true if there are any modified and unsaved slabs in storage with given address.
func (s *PersistentSlabStorage) HasUnsavedChanges(address Address) bool {
for k := range s.deltas {
if k.address == address {
return true
}
}
return false
}

func (s *PersistentSlabStorage) SlabIterator() (SlabIterator, error) {

var slabs []struct {
SlabID
Slab
}

// Get slabs connected to slab from base storage and append those slabs to slabs slice.
appendChildStorables := func(slab Slab) error {
childStorables := slab.ChildStorables()

Expand Down Expand Up @@ -659,6 +670,7 @@ func (s *PersistentSlabStorage) SlabIterator() (SlabIterator, error) {
return nil
}

// Append slab and slabs connected to it to slabs slice.
appendSlab := func(id SlabID, slab Slab) error {
slabs = append(slabs, struct {
SlabID
Expand Down
36 changes: 28 additions & 8 deletions storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -618,15 +618,18 @@ func TestPersistentStorage(t *testing.T) {
decMode, err := cbor.DecOptions{}.DecMode()
require.NoError(t, err)

tempAddress := Address{}
permAddress := Address{1, 0, 0, 0, 0, 0, 0, 0}

t.Run("empty storage", func(t *testing.T) {
baseStorage := NewInMemBaseStorage()
storage := NewPersistentSlabStorage(baseStorage, encMode, decMode, nil, nil)

tempSlabID, err := NewSlabIDFromRawBytes([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
require.NoError(t, err)
slabIndex := SlabIndex{0, 0, 0, 0, 0, 0, 0, 1}

permSlabID, err := NewSlabIDFromRawBytes([]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
require.NoError(t, err)
tempSlabID := NewSlabID(tempAddress, slabIndex)

permSlabID := NewSlabID(permAddress, slabIndex)

_, found, err := storage.Retrieve(tempSlabID)
require.NoError(t, err)
Expand All @@ -639,6 +642,8 @@ func TestPersistentStorage(t *testing.T) {
require.Equal(t, uint(0), storage.DeltasWithoutTempAddresses())
require.Equal(t, uint(0), storage.Deltas())
require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses())
require.False(t, storage.HasUnsavedChanges(tempAddress))
require.False(t, storage.HasUnsavedChanges(permAddress))
})

t.Run("temp address", func(t *testing.T) {
Expand All @@ -648,19 +653,22 @@ func TestPersistentStorage(t *testing.T) {
baseStorage := NewInMemBaseStorage()
storage := NewPersistentSlabStorage(baseStorage, encMode, decMode, nil, nil)

tempSlabID, err := NewSlabIDFromRawBytes([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
require.NoError(t, err)
slabIndex := SlabIndex{0, 0, 0, 0, 0, 0, 0, 1}

permSlabID, err := NewSlabIDFromRawBytes([]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
require.NoError(t, err)
tempSlabID := NewSlabID(tempAddress, slabIndex)

permSlabID := NewSlabID(permAddress, slabIndex)

slab1 := generateRandomSlab(tempSlabID, r)
slab2 := generateRandomSlab(permSlabID, r)

// no temp ids should be in the base storage
err = storage.Store(tempSlabID, slab1)
require.NoError(t, err)

require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses())
require.True(t, storage.HasUnsavedChanges(tempAddress))
require.False(t, storage.HasUnsavedChanges(permAddress))

err = storage.Store(permSlabID, slab2)
require.NoError(t, err)
Expand All @@ -669,13 +677,17 @@ func TestPersistentStorage(t *testing.T) {
require.Equal(t, uint(2), storage.Deltas())
require.True(t, storage.DeltasSizeWithoutTempAddresses() > 0)
require.Equal(t, uint64(slab2.ByteSize()), storage.DeltasSizeWithoutTempAddresses())
require.True(t, storage.HasUnsavedChanges(tempAddress))
require.True(t, storage.HasUnsavedChanges(permAddress))

err = storage.Commit()
require.NoError(t, err)

require.Equal(t, uint(0), storage.DeltasWithoutTempAddresses())
require.Equal(t, uint(1), storage.Deltas())
require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses())
require.True(t, storage.HasUnsavedChanges(tempAddress)) // Temp slabs are still in deltas after commit.
require.False(t, storage.HasUnsavedChanges(permAddress))

// Slab with temp slab id is NOT persisted in base storage.
_, found, err := baseStorage.Retrieve(tempSlabID)
Expand All @@ -701,16 +713,24 @@ func TestPersistentStorage(t *testing.T) {
err = storage.Remove(permSlabID)
require.NoError(t, err)

require.True(t, storage.HasUnsavedChanges(tempAddress))
require.True(t, storage.HasUnsavedChanges(permAddress))

// Remove slab with temp slab id
err = storage.Remove(tempSlabID)
require.NoError(t, err)

require.Equal(t, uint(1), storage.DeltasWithoutTempAddresses())
require.Equal(t, uint64(0), storage.DeltasSizeWithoutTempAddresses())
require.True(t, storage.HasUnsavedChanges(tempAddress))
require.True(t, storage.HasUnsavedChanges(permAddress))

err = storage.Commit()
require.NoError(t, err)

require.True(t, storage.HasUnsavedChanges(tempAddress))
require.False(t, storage.HasUnsavedChanges(permAddress))

// Slab with perm slab id is removed from base storage.
_, found, err = baseStorage.Retrieve(permSlabID)
require.NoError(t, err)
Expand Down

0 comments on commit 5941314

Please sign in to comment.