Skip to content

Commit

Permalink
feat: save restored snapshot locally (backport cosmos#16060) (cosmos#…
Browse files Browse the repository at this point in the history
…16262)

Co-authored-by: yihuang <huang@crypto.com>
Co-authored-by: marbar3778 <marbar3778@yahoo.com>
  • Loading branch information
3 people authored and JeancarloBarrios committed Sep 28, 2024
1 parent a2e83e2 commit 7c3652b
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ Ref: https://keepachangelog.com/en/1.0.0/

## [Unreleased]

## Features

* [#16060](https://github.com/cosmos/cosmos-sdk/pull/16060) Support saving restoring snapshot locally.

### Improvements

* (deps) [#15973](https://github.com/cosmos/cosmos-sdk/pull/15973) Bump CometBFT to [v0.34.28](https://github.com/cometbft/cometbft/blob/v0.34.28/CHANGELOG.md#v03428).
Expand Down
15 changes: 7 additions & 8 deletions store/snapshots/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ type Manager struct {
opts types.SnapshotOptions
// multistore is the store from which snapshots are taken.
multistore types.Snapshotter
logger storetypes.Logger
logger log.Logger

mtx sync.Mutex
operation operation
Expand Down Expand Up @@ -319,7 +319,7 @@ func (m *Manager) Restore(snapshot types.Snapshot) error {

dir := m.store.pathSnapshot(snapshot.Height, snapshot.Format)
if err := os.MkdirAll(dir, 0o750); err != nil {
return errorsmod.Wrapf(err, "failed to create snapshot directory %q", dir)
return sdkerrors.Wrapf(err, "failed to create snapshot directory %q", dir)
}

chChunks := m.loadChunkStream(snapshot.Height, snapshot.Format, chChunkIDs)
Expand Down Expand Up @@ -362,10 +362,9 @@ func (m *Manager) loadChunkStream(height uint64, format uint32, chunkIDs <-chan
func (m *Manager) doRestoreSnapshot(snapshot types.Snapshot, chChunks <-chan io.ReadCloser) error {
dir := m.store.pathSnapshot(snapshot.Height, snapshot.Format)
if err := os.MkdirAll(dir, 0o750); err != nil {
return errorsmod.Wrapf(err, "failed to create snapshot directory %q", dir)
return sdkerrors.Wrapf(err, "failed to create snapshot directory %q", dir)
}

var nextItem types.SnapshotItem
streamReader, err := NewStreamReader(chChunks)
if err != nil {
return err
Expand Down Expand Up @@ -431,7 +430,7 @@ func (m *Manager) RestoreChunk(chunk []byte) (bool, error) {
}

if int(m.restoreChunkIndex) >= len(m.restoreSnapshot.Metadata.ChunkHashes) {
return false, errorsmod.Wrap(storetypes.ErrLogic, "received unexpected chunk")
return false, sdkerrors.Wrap(sdkerrors.ErrLogic, "received unexpected chunk")
}

// Check if any errors have occurred yet.
Expand All @@ -454,7 +453,7 @@ func (m *Manager) RestoreChunk(chunk []byte) (bool, error) {
}

if err := m.store.saveChunkContent(chunk, m.restoreChunkIndex, m.restoreSnapshot); err != nil {
return false, errorsmod.Wrapf(err, "save chunk content %d", m.restoreChunkIndex)
return false, sdkerrors.Wrapf(err, "save chunk content %d", m.restoreChunkIndex)
}

// Pass the chunk to the restore, and wait for completion if it was the final one.
Expand All @@ -468,7 +467,7 @@ func (m *Manager) RestoreChunk(chunk []byte) (bool, error) {
// the chunks are all written into files, we can save the snapshot to the db,
// even if the restoration may not completed yet.
if err := m.store.saveSnapshot(m.restoreSnapshot); err != nil {
return false, errorsmod.Wrap(err, "save restoring snapshot")
return false, sdkerrors.Wrap(err, "save restoring snapshot")
}

done := <-m.chRestoreDone
Expand Down Expand Up @@ -505,7 +504,7 @@ func (m *Manager) RestoreLocalSnapshot(height uint64, format uint32) error {
}
defer m.endLocked()

return m.restoreSnapshot(*snapshot, ch)
return m.doRestoreSnapshot(*snapshot, ch)
}

// sortedExtensionNames sort extension names for deterministic iteration.
Expand Down
7 changes: 7 additions & 0 deletions store/snapshots/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,13 @@ func TestManager_Restore(t *testing.T) {
assert.Equal(t, expectItems, target.items)
assert.Equal(t, 10, len(extSnapshotter.state))

// The snapshot is saved in local snapshot store
snapshots, err := store.List()
require.NoError(t, err)
snapshot := snapshots[0]
require.Equal(t, uint64(3), snapshot.Height)
require.Equal(t, types.CurrentFormat, snapshot.Format)

// Starting a new restore should fail now, because the target already has contents.
err = manager.Restore(types.Snapshot{
Height: 3,
Expand Down
6 changes: 6 additions & 0 deletions store/snapshots/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,12 @@ func (s *Store) saveChunk(chunkBody io.ReadCloser, index uint32, snapshot *types
return nil
}

// saveChunkContent save the chunk to disk
func (s *Store) saveChunkContent(chunk []byte, index uint32, snapshot *types.Snapshot) error {
path := s.PathChunk(snapshot.Height, snapshot.Format, index)
return os.WriteFile(path, chunk, 0o600)
}

// saveSnapshot saves snapshot metadata to the database.
func (s *Store) saveSnapshot(snapshot *types.Snapshot) error {
value, err := proto.Marshal(snapshot)
Expand Down

0 comments on commit 7c3652b

Please sign in to comment.