Skip to content

Commit 20060d2

Browse files
committed
[FAB-16471] Add upgrade-dbs and rebuild-dbs cmds
- Defined constants for v1.x and v2.0 data formats - Added peer node command upgrade-dbs to upgrade ledgerProvider db and drop other dbs that will be rebuilt upon peer restart - Added peer node command rebuild-dbs to drop dbs so that they will be rebuilt upon peer restart Change-Id: I5b0a71fea2218827539a29571a8842b8f537b7d8 Signed-off-by: Wenjian Qiao <wenjianq@gmail.com>
1 parent caa8452 commit 20060d2

File tree

17 files changed

+351
-57
lines changed

17 files changed

+351
-57
lines changed

common/ledger/blkstorage/fsblkstorage/fs_blockstore_provider.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,18 @@ package fsblkstorage
1818

1919
import (
2020
"github.com/hyperledger/fabric/common/ledger/blkstorage"
21+
"github.com/hyperledger/fabric/common/ledger/dataformat"
2122
"github.com/hyperledger/fabric/common/ledger/util"
2223
"github.com/hyperledger/fabric/common/ledger/util/leveldbhelper"
2324
"github.com/hyperledger/fabric/common/metrics"
2425
)
2526

26-
const (
27-
dataFormatVersion20 = "2.0"
28-
)
29-
3027
func dataFormatVersion(indexConfig *blkstorage.IndexConfig) string {
3128
// in version 2.0 we merged three indexable into one `IndexableAttrTxID`
3229
if indexConfig.Contains(blkstorage.IndexableAttrTxID) {
33-
return dataFormatVersion20
30+
return dataformat.Version20
3431
}
35-
return ""
32+
return dataformat.Version1x
3633
}
3734

3835
// FsBlockstoreProvider provides handle to block storage - this is not thread-safe

common/ledger/blkstorage/fsblkstorage/reset.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,10 @@ import (
1717

1818
// ResetBlockStore drops the block storage index and truncates the blocks files for all channels/ledgers to genesis blocks
1919
func ResetBlockStore(blockStorageDir string) error {
20-
conf := &Conf{blockStorageDir: blockStorageDir}
21-
indexDir := conf.getIndexDir()
22-
logger.Infof("Dropping the index dir [%s]... if present", indexDir)
23-
if err := os.RemoveAll(indexDir); err != nil {
20+
if err := DeleteBlockStoreIndex(blockStorageDir); err != nil {
2421
return err
2522
}
23+
conf := &Conf{blockStorageDir: blockStorageDir}
2624
chainsDir := conf.getChainsDir()
2725
chainsDirExists, err := pathExists(chainsDir)
2826
if err != nil {
@@ -53,6 +51,14 @@ func ResetBlockStore(blockStorageDir string) error {
5351
return nil
5452
}
5553

54+
// DeleteBlockStoreIndex deletes block store index file
55+
func DeleteBlockStoreIndex(blockStorageDir string) error {
56+
conf := &Conf{blockStorageDir: blockStorageDir}
57+
indexDir := conf.getIndexDir()
58+
logger.Infof("Dropping the index dir [%s]... if present", indexDir)
59+
return os.RemoveAll(indexDir)
60+
}
61+
5662
func resetToGenesisBlk(ledgerDir string) error {
5763
logger.Infof("Resetting ledger [%s] to genesis block", ledgerDir)
5864
lastFileNum, err := retrieveLastFileSuffix(ledgerDir)

common/ledger/dataformat/constants.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package dataformat
8+
9+
const (
10+
// Version1x specifies the data format in version 1.x
11+
Version1x = ""
12+
13+
// Version20 specifies the data format in version 2.0
14+
Version20 = "2.0"
15+
)

common/ledger/util/leveldbhelper/leveldb_provider.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ func openDBAndCheckFormat(conf *Conf) (d *DB, e error) {
112112
logger.Debugf("Checking for db format at path [%s]", conf.DBPath)
113113

114114
if !bytes.Equal(formatVersion, []byte(conf.ExpectedFormatVersion)) {
115-
logger.Errorf("the db at path [%s] contains data in unexpected format. expected data format = [%s], data format = [%s]",
116-
conf.DBPath, conf.ExpectedFormatVersion, formatVersion)
115+
logger.Errorf("The db at path [%s] contains data in unexpected format. expected data format = [%s] (%#v), data format = [%s] (%#v).",
116+
conf.DBPath, conf.ExpectedFormatVersion, []byte(conf.ExpectedFormatVersion), formatVersion, formatVersion)
117117
return nil, &ErrFormatVersionMismatch{ExpectedFormatVersion: conf.ExpectedFormatVersion, DataFormatVersion: string(formatVersion), DBPath: conf.DBPath}
118118
}
119119

core/ledger/kvledger/history/db.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/hyperledger/fabric-protos-go/common"
1010
"github.com/hyperledger/fabric/common/flogging"
1111
"github.com/hyperledger/fabric/common/ledger/blkstorage"
12+
"github.com/hyperledger/fabric/common/ledger/dataformat"
1213
"github.com/hyperledger/fabric/common/ledger/util/leveldbhelper"
1314
"github.com/hyperledger/fabric/core/ledger"
1415
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
@@ -19,10 +20,6 @@ import (
1920

2021
var logger = flogging.MustGetLogger("history")
2122

22-
const (
23-
dataFormatVersion = "2.0"
24-
)
25-
2623
// DBProvider provides handle to HistoryDB for a given channel
2724
type DBProvider struct {
2825
leveldbProvider *leveldbhelper.Provider
@@ -34,7 +31,7 @@ func NewDBProvider(path string) (*DBProvider, error) {
3431
levelDBProvider, err := leveldbhelper.NewProvider(
3532
&leveldbhelper.Conf{
3633
DBPath: path,
37-
ExpectedFormatVersion: dataFormatVersion,
34+
ExpectedFormatVersion: dataformat.Version20,
3835
},
3936
)
4037
if err != nil {

core/ledger/kvledger/kv_ledger_provider.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/golang/protobuf/proto"
1414
"github.com/hyperledger/fabric-protos-go/common"
15+
"github.com/hyperledger/fabric/common/ledger/dataformat"
1516
"github.com/hyperledger/fabric/common/ledger/util/leveldbhelper"
1617
"github.com/hyperledger/fabric/core/ledger"
1718
"github.com/hyperledger/fabric/core/ledger/confighistory"
@@ -26,8 +27,6 @@ import (
2627
"github.com/syndtr/goleveldb/leveldb"
2728
)
2829

29-
const idStoreFormatVersion = "2.0"
30-
3130
var (
3231
// ErrLedgerIDExists is thrown by a CreateLedger call if a ledger with the given id already exists
3332
ErrLedgerIDExists = errors.New("LedgerID already exists")
@@ -79,6 +78,13 @@ func NewProvider(initializer *ledger.Initializer) (pr *Provider, e error) {
7978
defer func() {
8079
if e != nil {
8180
p.Close()
81+
if errFormatMismatch, ok := e.(*leveldbhelper.ErrFormatVersionMismatch); ok {
82+
if errFormatMismatch.DataFormatVersion == dataformat.Version1x && errFormatMismatch.ExpectedFormatVersion == dataformat.Version20 {
83+
logger.Errorf("Please execute the 'peer node upgrade-dbs' command to upgrade the database format: %s", errFormatMismatch)
84+
} else {
85+
logger.Errorf("Please check the Fabric version matches the ledger data format: %s", errFormatMismatch)
86+
}
87+
}
8288
}
8389
}()
8490

@@ -378,9 +384,10 @@ func openIDStore(path string) (s *idStore, e error) {
378384
return nil, err
379385
}
380386

387+
expectedFormatBytes := []byte(dataformat.Version20)
381388
if emptyDB {
382389
// add format key to a new db
383-
err := db.Put(formatKey, []byte(idStoreFormatVersion), true)
390+
err := db.Put(formatKey, expectedFormatBytes, true)
384391
if err != nil {
385392
return nil, err
386393
}
@@ -392,8 +399,10 @@ func openIDStore(path string) (s *idStore, e error) {
392399
if err != nil {
393400
return nil, err
394401
}
395-
if !bytes.Equal(formatVersion, []byte(idStoreFormatVersion)) {
396-
return nil, &leveldbhelper.ErrFormatVersionMismatch{ExpectedFormatVersion: idStoreFormatVersion, DataFormatVersion: string(formatVersion), DBPath: path}
402+
if !bytes.Equal(formatVersion, expectedFormatBytes) {
403+
logger.Errorf("The db at path [%s] contains data in unexpected format. expected data format = [%s] (%#v), data format = [%s] (%#v).",
404+
path, dataformat.Version20, expectedFormatBytes, formatVersion, formatVersion)
405+
return nil, &leveldbhelper.ErrFormatVersionMismatch{ExpectedFormatVersion: dataformat.Version20, DataFormatVersion: string(formatVersion), DBPath: path}
397406
}
398407
return &idStore{db, path}, nil
399408
}
@@ -403,7 +412,7 @@ func (s *idStore) upgradeFormat() error {
403412
if err != nil {
404413
return err
405414
}
406-
idStoreFormatBytes := []byte(idStoreFormatVersion)
415+
idStoreFormatBytes := []byte(dataformat.Version20)
407416
if bytes.Equal(format, idStoreFormatBytes) {
408417
logger.Debug("Format is current, nothing to do")
409418
return nil
@@ -414,7 +423,7 @@ func (s *idStore) upgradeFormat() error {
414423
return err
415424
}
416425

417-
logger.Infof("The ledgerProvider db format is old, upgrading to the new format %s", idStoreFormatVersion)
426+
logger.Infof("The ledgerProvider db format is old, upgrading to the new format %s", dataformat.Version20)
418427

419428
batch := &leveldb.Batch{}
420429
batch.Put(formatKey, idStoreFormatBytes)

core/ledger/kvledger/kv_ledger_provider_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/hyperledger/fabric/bccsp/sw"
2020
configtxtest "github.com/hyperledger/fabric/common/configtx/test"
2121
"github.com/hyperledger/fabric/common/ledger/blkstorage/fsblkstorage"
22+
"github.com/hyperledger/fabric/common/ledger/dataformat"
2223
"github.com/hyperledger/fabric/common/ledger/testutil"
2324
"github.com/hyperledger/fabric/common/metrics/disabled"
2425
"github.com/hyperledger/fabric/common/util"
@@ -53,7 +54,7 @@ func TestLedgerProvider(t *testing.T) {
5354
s := provider.idStore
5455
val, err := s.db.Get(formatKey)
5556
require.NoError(t, err)
56-
require.Equal(t, []byte(idStoreFormatVersion), val)
57+
require.Equal(t, []byte(dataformat.Version20), val)
5758

5859
provider.Close()
5960

core/ledger/kvledger/rebuild_dbs.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package kvledger
8+
9+
import (
10+
"github.com/hyperledger/fabric/common/ledger/blkstorage/fsblkstorage"
11+
"github.com/hyperledger/fabric/common/ledger/util/leveldbhelper"
12+
"github.com/pkg/errors"
13+
)
14+
15+
// RebuildDBs drops existing ledger databases.
16+
// Dropped database will be rebuilt upon server restart
17+
func RebuildDBs(rootFSPath string) error {
18+
fileLockPath := fileLockPath(rootFSPath)
19+
fileLock := leveldbhelper.NewFileLock(fileLockPath)
20+
if err := fileLock.Lock(); err != nil {
21+
return errors.Wrap(err, "as another peer node command is executing,"+
22+
" wait for that command to complete its execution or terminate it before retrying")
23+
}
24+
defer fileLock.Unlock()
25+
26+
if err := dropDBs(rootFSPath); err != nil {
27+
return err
28+
}
29+
30+
blockstorePath := BlockStorePath(rootFSPath)
31+
return fsblkstorage.DeleteBlockStoreIndex(blockstorePath)
32+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package kvledger
8+
9+
import (
10+
"os"
11+
"path/filepath"
12+
"testing"
13+
14+
configtxtest "github.com/hyperledger/fabric/common/configtx/test"
15+
"github.com/stretchr/testify/require"
16+
)
17+
18+
func TestRebuildDBs(t *testing.T) {
19+
conf, cleanup := testConfig(t)
20+
defer cleanup()
21+
provider := testutilNewProvider(conf, t)
22+
23+
numLedgers := 3
24+
for i := 0; i < numLedgers; i++ {
25+
genesisBlock, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(i))
26+
provider.Create(genesisBlock)
27+
}
28+
29+
// rebuild should fail when provider is still open
30+
err := RebuildDBs(conf.RootFSPath)
31+
require.Error(t, err, "as another peer node command is executing, wait for that command to complete its execution or terminate it before retrying")
32+
provider.Close()
33+
34+
rootFSPath := conf.RootFSPath
35+
err = RebuildDBs(rootFSPath)
36+
require.NoError(t, err)
37+
38+
// verify blockstoreIndex, configHistory, history, state, bookkeeper dbs are deleted
39+
_, err = os.Stat(filepath.Join(BlockStorePath(rootFSPath), "index"))
40+
require.Equal(t, os.IsNotExist(err), true)
41+
_, err = os.Stat(ConfigHistoryDBPath(rootFSPath))
42+
require.Equal(t, os.IsNotExist(err), true)
43+
_, err = os.Stat(HistoryDBPath(rootFSPath))
44+
require.Equal(t, os.IsNotExist(err), true)
45+
_, err = os.Stat(StateDBPath(rootFSPath))
46+
require.Equal(t, os.IsNotExist(err), true)
47+
_, err = os.Stat(BookkeeperDBPath(rootFSPath))
48+
require.Equal(t, os.IsNotExist(err), true)
49+
50+
// rebuild again should be successful
51+
err = RebuildDBs(rootFSPath)
52+
require.NoError(t, err)
53+
}

core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"bytes"
1111

1212
"github.com/hyperledger/fabric/common/flogging"
13+
"github.com/hyperledger/fabric/common/ledger/dataformat"
1314
"github.com/hyperledger/fabric/common/ledger/util/leveldbhelper"
1415
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb"
1516
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version"
@@ -26,10 +27,6 @@ var (
2627
savePointKey = []byte{'s'}
2728
)
2829

29-
const (
30-
dataFormatVersion20 = "2.0"
31-
)
32-
3330
// VersionedDBProvider implements interface VersionedDBProvider
3431
type VersionedDBProvider struct {
3532
dbProvider *leveldbhelper.Provider
@@ -41,7 +38,7 @@ func NewVersionedDBProvider(dbPath string) (*VersionedDBProvider, error) {
4138
dbProvider, err := leveldbhelper.NewProvider(
4239
&leveldbhelper.Conf{
4340
DBPath: dbPath,
44-
ExpectedFormatVersion: dataFormatVersion20,
41+
ExpectedFormatVersion: dataformat.Version20,
4542
})
4643
if err != nil {
4744
return nil, err

0 commit comments

Comments
 (0)