-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lens, metabase: save last epoch when metabase was resynchronized
Add new key `last_resync_epoch` to `shardInfoBucket` in metabase `boltDB` and new field in `Info` that contains last epoch when metabase was resynchronized. Update this value in db when the metabase is `Reset` and read on `init`. Also make `lens` command `meta last-resync-epoch` to read this value from metabase path. Add test. Update VERSION.md. Closes #2887. Signed-off-by: Andrey Butusov <[email protected]>
- Loading branch information
Showing
8 changed files
with
168 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package meta | ||
|
||
import ( | ||
common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var lastResyncEpochCMD = &cobra.Command{ | ||
Use: "last-resync-epoch", | ||
Short: "Read last epoch when metabase was resynchronized", | ||
Args: cobra.NoArgs, | ||
RunE: lastResyncEpochFunc, | ||
} | ||
|
||
func init() { | ||
common.AddComponentPathFlag(lastResyncEpochCMD, &vPath) | ||
} | ||
|
||
func lastResyncEpochFunc(cmd *cobra.Command, _ []string) error { | ||
db, err := openMeta(true) | ||
if err != nil { | ||
return err | ||
} | ||
defer db.Close() | ||
|
||
epoch, err := db.ReadLastResyncEpoch() | ||
if err != nil { | ||
return err | ||
} | ||
cmd.Println(epoch) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ func init() { | |
writeObjectCMD, | ||
getCMD, | ||
statCMD, | ||
lastResyncEpochCMD, | ||
) | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package meta | ||
|
||
import ( | ||
"encoding/binary" | ||
"fmt" | ||
|
||
"go.etcd.io/bbolt" | ||
) | ||
|
||
var lastResyncEpochKey = []byte("last_resync_epoch") | ||
|
||
// ReadLastResyncEpoch reads from db last epoch when metabase was resynchronized. | ||
// If id is missing, returns 0, nil. | ||
func (db *DB) ReadLastResyncEpoch() (epoch uint64, err error) { | ||
db.modeMtx.RLock() | ||
defer db.modeMtx.RUnlock() | ||
|
||
if db.mode.NoMetabase() { | ||
return 0, ErrDegradedMode | ||
} | ||
|
||
err = db.boltDB.View(func(tx *bbolt.Tx) error { | ||
epoch = getLastResyncEpoch(tx) | ||
return nil | ||
}) | ||
|
||
return | ||
} | ||
|
||
// updateLastResyncEpoch updates db value of last epoch when metabase was resynchronized. | ||
func updateLastResyncEpoch(tx *bbolt.Tx, epoch uint64) error { | ||
data := make([]byte, 8) | ||
binary.LittleEndian.PutUint64(data, epoch) | ||
|
||
b, err := tx.CreateBucketIfNotExists(shardInfoBucket) | ||
if err != nil { | ||
return fmt.Errorf("can't create auxiliary bucket: %w", err) | ||
} | ||
return b.Put(lastResyncEpochKey, data) | ||
} | ||
|
||
func getLastResyncEpoch(tx *bbolt.Tx) uint64 { | ||
b := tx.Bucket(shardInfoBucket) | ||
if b != nil { | ||
data := b.Get(lastResyncEpochKey) | ||
if len(data) == 8 { | ||
return binary.LittleEndian.Uint64(data) | ||
} | ||
} | ||
|
||
return 0 | ||
} |
55 changes: 55 additions & 0 deletions
55
pkg/local_object_storage/metabase/last_resync_epoch_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package meta_test | ||
|
||
import ( | ||
"path/filepath" | ||
"testing" | ||
|
||
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestDB_ReadLastResyncEpoch(t *testing.T) { | ||
es := &epochState{ | ||
e: currEpoch, | ||
} | ||
|
||
db := meta.New([]meta.Option{ | ||
meta.WithPath(filepath.Join(t.TempDir(), "meta")), | ||
meta.WithPermissions(0o600), | ||
meta.WithEpochState(es), | ||
}...) | ||
|
||
require.NoError(t, db.Open(false)) | ||
require.NoError(t, db.Init()) | ||
|
||
t.Cleanup(func() { | ||
db.Close() | ||
}) | ||
|
||
checkEpoch := func(t *testing.T, epoch uint64) { | ||
gotEpoch, err := db.ReadLastResyncEpoch() | ||
require.NoError(t, err) | ||
require.Equal(t, epoch, gotEpoch) | ||
require.Equal(t, epoch, db.DumpInfo().LastResyncEpoch) | ||
} | ||
|
||
// Clean db without resynchronizations, so it is 0. | ||
checkEpoch(t, 0) | ||
|
||
// After Reset, last resync epoch == current epoch. | ||
require.NoError(t, db.Reset()) | ||
|
||
checkEpoch(t, currEpoch) | ||
|
||
// Two epochs tick, last resync epoch the same. | ||
es.e = currEpoch + 2 | ||
|
||
checkEpoch(t, currEpoch) | ||
|
||
// After reload, last resync epoch the same. | ||
require.NoError(t, db.Close()) | ||
require.NoError(t, db.Open(false)) | ||
require.NoError(t, db.Init()) | ||
|
||
checkEpoch(t, currEpoch) | ||
} |