Skip to content

Commit 9544025

Browse files
committed
Refactor db package
Currently db will open when GetDBHandle method is invoked first time, so GetDBHandle method needs to use mutex. This patch makes db open and close in its lifecycle methods Start and Stop, invokes Start only when peer starts and invokes Stop when peer stops. After that, methods in db do not need to support concurrency. Change-Id: Id8612f2a846c5d626bd42c5cd4ae482076f6a975 Signed-off-by: grapebaba <[email protected]>
1 parent fb7da0d commit 9544025

File tree

8 files changed

+70
-61
lines changed

8 files changed

+70
-61
lines changed

core/chaincode/exectransaction_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/hyperledger/fabric/core/container"
3333
"github.com/hyperledger/fabric/core/container/ccintf"
3434
"github.com/hyperledger/fabric/core/crypto"
35+
"github.com/hyperledger/fabric/core/db"
3536
"github.com/hyperledger/fabric/core/ledger"
3637
"github.com/hyperledger/fabric/core/util"
3738
"github.com/hyperledger/fabric/membersrvc/ca"
@@ -46,6 +47,8 @@ import (
4647
// attributes to request in the batch of tcerts while deploying, invoking or querying
4748
var attributes = []string{"company", "position"}
4849

50+
var testDBWrapper = db.NewTestDBWrapper()
51+
4952
func getNowMillis() int64 {
5053
nanos := time.Now().UnixNano()
5154
return nanos / 1000000
@@ -355,6 +358,7 @@ func executeDeployTransaction(t *testing.T, url string) {
355358

356359
// Test deploy of a transaction
357360
func TestExecuteDeployTransaction(t *testing.T) {
361+
testDBWrapper.CleanDB(t)
358362
executeDeployTransaction(t, "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01")
359363
}
360364

@@ -364,6 +368,7 @@ func TestGopathExecuteDeployTransaction(t *testing.T) {
364368
// and a couple of elements - it doesn't matter what they are
365369
os.Setenv("GOPATH", os.Getenv("GOPATH")+string(os.PathSeparator)+string(os.PathListSeparator)+"/tmp/foo"+string(os.PathListSeparator)+"/tmp/bar")
366370
fmt.Printf("set GOPATH to: \"%s\"\n", os.Getenv("GOPATH"))
371+
testDBWrapper.CleanDB(t)
367372
executeDeployTransaction(t, "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01")
368373
}
369374

@@ -372,6 +377,7 @@ func TestHTTPExecuteDeployTransaction(t *testing.T) {
372377
// The chaincode used here cannot be from the fabric repo
373378
// itself or it won't be downloaded because it will be found
374379
// in GOPATH, which would defeat the test
380+
testDBWrapper.CleanDB(t)
375381
executeDeployTransaction(t, "http://github.com/hyperledger/fabric-test-resources/examples/chaincode/go/chaincode_example01")
376382
}
377383

@@ -465,6 +471,7 @@ func invokeExample02Transaction(ctxt context.Context, cID *pb.ChaincodeID, args
465471
}
466472

467473
func TestExecuteInvokeTransaction(t *testing.T) {
474+
testDBWrapper.CleanDB(t)
468475
var opts []grpc.ServerOption
469476

470477
//TLS is on by default. This is the ONLY test that does NOT use TLS
@@ -570,6 +577,7 @@ func exec(ctxt context.Context, chaincodeID string, numTrans int, numQueries int
570577

571578
// Test the execution of a query.
572579
func TestExecuteQuery(t *testing.T) {
580+
testDBWrapper.CleanDB(t)
573581
var opts []grpc.ServerOption
574582
if viper.GetBool("peer.tls.enabled") {
575583
creds, err := credentials.NewServerTLSFromFile(viper.GetString("peer.tls.cert.file"), viper.GetString("peer.tls.key.file"))
@@ -653,6 +661,7 @@ func TestExecuteQuery(t *testing.T) {
653661

654662
// Test the execution of an invalid transaction.
655663
func TestExecuteInvokeInvalidTransaction(t *testing.T) {
664+
testDBWrapper.CleanDB(t)
656665
var opts []grpc.ServerOption
657666
if viper.GetBool("peer.tls.enabled") {
658667
creds, err := credentials.NewServerTLSFromFile(viper.GetString("peer.tls.cert.file"), viper.GetString("peer.tls.key.file"))
@@ -714,6 +723,7 @@ func TestExecuteInvokeInvalidTransaction(t *testing.T) {
714723

715724
// Test the execution of an invalid query.
716725
func TestExecuteInvalidQuery(t *testing.T) {
726+
testDBWrapper.CleanDB(t)
717727
var opts []grpc.ServerOption
718728
if viper.GetBool("peer.tls.enabled") {
719729
creds, err := credentials.NewServerTLSFromFile(viper.GetString("peer.tls.cert.file"), viper.GetString("peer.tls.key.file"))
@@ -785,6 +795,7 @@ func TestExecuteInvalidQuery(t *testing.T) {
785795

786796
// Test the execution of a chaincode that invokes another chaincode.
787797
func TestChaincodeInvokeChaincode(t *testing.T) {
798+
testDBWrapper.CleanDB(t)
788799
var opts []grpc.ServerOption
789800
if viper.GetBool("peer.tls.enabled") {
790801
creds, err := credentials.NewServerTLSFromFile(viper.GetString("peer.tls.cert.file"), viper.GetString("peer.tls.key.file"))
@@ -898,6 +909,7 @@ func TestChaincodeInvokeChaincode(t *testing.T) {
898909
// Test the execution of a chaincode that invokes another chaincode with wrong parameters. Should receive error from
899910
// from the called chaincode
900911
func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) {
912+
testDBWrapper.CleanDB(t)
901913
var opts []grpc.ServerOption
902914
if viper.GetBool("peer.tls.enabled") {
903915
creds, err := credentials.NewServerTLSFromFile(viper.GetString("peer.tls.cert.file"), viper.GetString("peer.tls.key.file"))
@@ -1098,6 +1110,7 @@ func chaincodeQueryChaincode(user string) error {
10981110

10991111
// Test the execution of a chaincode query that queries another chaincode without security enabled
11001112
func TestChaincodeQueryChaincode(t *testing.T) {
1113+
testDBWrapper.CleanDB(t)
11011114
var peerLis net.Listener
11021115
var err error
11031116
if peerLis, err = initPeer(); err != nil {
@@ -1119,6 +1132,7 @@ func TestChaincodeQueryChaincode(t *testing.T) {
11191132
// Test the execution of a chaincode that queries another chaincode with invalid parameter. Should receive error from
11201133
// from the called chaincode
11211134
func TestChaincodeQueryChaincodeErrorCase(t *testing.T) {
1135+
testDBWrapper.CleanDB(t)
11221136
var opts []grpc.ServerOption
11231137
if viper.GetBool("peer.tls.enabled") {
11241138
creds, err := credentials.NewServerTLSFromFile(viper.GetString("peer.tls.cert.file"), viper.GetString("peer.tls.key.file"))
@@ -1229,6 +1243,7 @@ func TestChaincodeQueryChaincodeErrorCase(t *testing.T) {
12291243
// Test the execution of a chaincode query that queries another chaincode with security enabled
12301244
// NOTE: this really needs to be a behave test. Remove when we have support in behave for multiple chaincodes
12311245
func TestChaincodeQueryChaincodeWithSec(t *testing.T) {
1246+
testDBWrapper.CleanDB(t)
12321247
viper.Set("security.enabled", "true")
12331248

12341249
//Initialize crypto
@@ -1282,6 +1297,7 @@ func TestChaincodeQueryChaincodeWithSec(t *testing.T) {
12821297

12831298
// Test the invocation of a transaction.
12841299
func TestRangeQuery(t *testing.T) {
1300+
testDBWrapper.CleanDB(t)
12851301
var opts []grpc.ServerOption
12861302
if viper.GetBool("peer.tls.enabled") {
12871303
creds, err := credentials.NewServerTLSFromFile(viper.GetString("peer.tls.cert.file"), viper.GetString("peer.tls.key.file"))
@@ -1352,6 +1368,7 @@ func TestRangeQuery(t *testing.T) {
13521368
}
13531369

13541370
func TestGetEvent(t *testing.T) {
1371+
testDBWrapper.CleanDB(t)
13551372
var opts []grpc.ServerOption
13561373
if viper.GetBool("peer.tls.enabled") {
13571374
creds, err := credentials.NewServerTLSFromFile(viper.GetString("peer.tls.cert.file"), viper.GetString("peer.tls.key.file"))

core/db/db.go

+16-34
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"os"
2323
"path"
2424
"strings"
25-
"sync"
2625

2726
"github.com/op/go-logging"
2827
"github.com/spf13/viper"
@@ -45,13 +44,6 @@ var columnfamilies = []string{
4544
persistCF, // persistent per-peer state (consensus)
4645
}
4746

48-
type dbState int32
49-
50-
const (
51-
closed dbState = iota
52-
opened
53-
)
54-
5547
// OpenchainDB encapsulates rocksdb's structures
5648
type OpenchainDB struct {
5749
DB *gorocksdb.DB
@@ -60,23 +52,30 @@ type OpenchainDB struct {
6052
StateDeltaCF *gorocksdb.ColumnFamilyHandle
6153
IndexesCF *gorocksdb.ColumnFamilyHandle
6254
PersistCF *gorocksdb.ColumnFamilyHandle
63-
dbState dbState
64-
mux sync.Mutex
6555
}
6656

67-
var openchainDB = Create()
57+
var openchainDB = create()
6858

6959
// Create create an openchainDB instance
70-
func Create() *OpenchainDB {
71-
return &OpenchainDB{dbState: closed}
60+
func create() *OpenchainDB {
61+
return &OpenchainDB{}
7262
}
7363

74-
// GetDBHandle get an opened openchainDB singleton
64+
// GetDBHandle gets an opened openchainDB singleton. Note that method Start must always be invoked before this method.
7565
func GetDBHandle() *OpenchainDB {
76-
openchainDB.Open()
7766
return openchainDB
7867
}
7968

69+
// Start the db, init the openchainDB instance and open the db. Note this method has no guarantee correct behavior concurrent invocation.
70+
func Start() {
71+
openchainDB.open()
72+
}
73+
74+
// Stop the db. Note this method has no guarantee correct behavior concurrent invocation.
75+
func Stop() {
76+
openchainDB.close()
77+
}
78+
8079
// GetFromBlockchainCF get value for given key from column family - blockchainCF
8180
func (openchainDB *OpenchainDB) GetFromBlockchainCF(key []byte) ([]byte, error) {
8281
return openchainDB.Get(openchainDB.BlockchainCF, key)
@@ -142,15 +141,7 @@ func getDBPath() string {
142141
}
143142

144143
// Open open underlying rocksdb
145-
func (openchainDB *OpenchainDB) Open() {
146-
openchainDB.mux.Lock()
147-
if openchainDB.dbState == opened {
148-
openchainDB.mux.Unlock()
149-
return
150-
}
151-
152-
defer openchainDB.mux.Unlock()
153-
144+
func (openchainDB *OpenchainDB) open() {
154145
dbPath := getDBPath()
155146
missing, err := dirMissingOrEmpty(dbPath)
156147
if err != nil {
@@ -190,25 +181,16 @@ func (openchainDB *OpenchainDB) Open() {
190181
openchainDB.StateDeltaCF = cfHandlers[3]
191182
openchainDB.IndexesCF = cfHandlers[4]
192183
openchainDB.PersistCF = cfHandlers[5]
193-
openchainDB.dbState = opened
194184
}
195185

196186
// Close releases all column family handles and closes rocksdb
197-
func (openchainDB *OpenchainDB) Close() {
198-
openchainDB.mux.Lock()
199-
if openchainDB.dbState == closed {
200-
openchainDB.mux.Unlock()
201-
return
202-
}
203-
204-
defer openchainDB.mux.Unlock()
187+
func (openchainDB *OpenchainDB) close() {
205188
openchainDB.BlockchainCF.Destroy()
206189
openchainDB.StateCF.Destroy()
207190
openchainDB.StateDeltaCF.Destroy()
208191
openchainDB.IndexesCF.Destroy()
209192
openchainDB.PersistCF.Destroy()
210193
openchainDB.DB.Close()
211-
openchainDB.dbState = closed
212194
}
213195

214196
// DeleteState delets ALL state keys/values from the DB. This is generally

core/db/db_test.go

+14-22
Original file line numberDiff line numberDiff line change
@@ -41,72 +41,64 @@ func TestGetDBPathEmptyPath(t *testing.T) {
4141
}
4242
}()
4343
defer viper.Set("peer.fileSystemPath", originalSetting)
44+
Start()
4445
GetDBHandle()
4546
}
4647

47-
func TestCreateDB(t *testing.T) {
48-
openchainDB := Create()
49-
openchainDB.Open()
50-
defer deleteTestDBPath()
51-
defer openchainDB.Close()
52-
}
53-
54-
func TestOpenDB_DirDoesNotExist(t *testing.T) {
55-
openchainDB := Create()
48+
func TestStartDB_DirDoesNotExist(t *testing.T) {
5649
deleteTestDBPath()
5750

5851
defer deleteTestDBPath()
59-
defer openchainDB.Close()
52+
defer Stop()
6053
defer func() {
6154
if r := recover(); r != nil {
6255
t.Fatalf("Failed to open DB: %s", r)
6356
}
6457
}()
65-
openchainDB.Open()
58+
Start()
6659
}
6760

68-
func TestOpenDB_NonEmptyDirExists(t *testing.T) {
69-
openchainDB := Create()
61+
func TestStartDB_NonEmptyDirExists(t *testing.T) {
7062
deleteTestDBPath()
7163
createNonEmptyTestDBPath()
7264

73-
defer deleteTestDBPath()
74-
defer openchainDB.Close()
7565
defer func() {
7666
if r := recover(); r == nil {
7767
t.Fatalf("dbPath is already exists. DB open should throw error")
7868
}
7969
}()
80-
openchainDB.Open()
70+
Start()
8171
}
8272

8373
func TestWriteAndRead(t *testing.T) {
84-
openchainDB := GetDBHandle()
74+
deleteTestDBPath()
75+
Start()
8576
defer deleteTestDBPath()
86-
defer openchainDB.Close()
77+
defer Stop()
8778
performBasicReadWrite(openchainDB, t)
8879
}
8980

9081
// This test verifies that when a new column family is added to the DB
9182
// users at an older level of the DB will still be able to open it with new code
9283
func TestDBColumnUpgrade(t *testing.T) {
93-
openchainDB := GetDBHandle()
94-
openchainDB.Close()
84+
deleteTestDBPath()
85+
Start()
86+
Stop()
9587

9688
oldcfs := columnfamilies
9789
columnfamilies = append([]string{"Testing"}, columnfamilies...)
9890
defer func() {
9991
columnfamilies = oldcfs
10092
}()
101-
openchainDB = GetDBHandle()
10293

10394
defer deleteTestDBPath()
104-
defer openchainDB.Close()
95+
defer Stop()
10596
defer func() {
10697
if r := recover(); r != nil {
10798
t.Fatalf("Error re-opening DB with upgraded columnFamilies")
10899
}
109100
}()
101+
Start()
110102
}
111103

112104
func TestDeleteState(t *testing.T) {

core/db/db_test_exports.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ func (testDB *TestDBWrapper) CleanDB(t testing.TB) {
4646
testDB.removeDBPath()
4747
t.Logf("Creating testDB")
4848

49+
Start()
4950
testDB.performCleanup = true
5051
}
5152

@@ -55,12 +56,13 @@ func (testDB *TestDBWrapper) CreateFreshDBGinkgo() {
5556
// at the end of the test
5657
testDB.cleanup()
5758
testDB.removeDBPath()
59+
Start()
5860
testDB.performCleanup = true
5961
}
6062

6163
func (testDB *TestDBWrapper) cleanup() {
6264
if testDB.performCleanup {
63-
GetDBHandle().Close()
65+
Stop()
6466
testDB.performCleanup = false
6567
}
6668
}
@@ -116,8 +118,12 @@ func (testDB *TestDBWrapper) GetFromStateDeltaCF(t testing.TB, key []byte) []byt
116118

117119
// CloseDB closes the db
118120
func (testDB *TestDBWrapper) CloseDB(t testing.TB) {
119-
openchainDB := GetDBHandle()
120-
openchainDB.Close()
121+
Stop()
122+
}
123+
124+
// OpenDB opens the db
125+
func (testDB *TestDBWrapper) OpenDB(t testing.TB) {
126+
Start()
121127
}
122128

123129
// GetEstimatedNumKeys returns estimated number of key-values in db. This is not accurate in all the cases

core/ledger/blockchain_indexes_async_test.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,11 @@ func TestIndexesAsync_IndexPendingBlocks(t *testing.T) {
187187
t.Fatalf("Error populating block chain with sample data: %s", err)
188188
}
189189

190-
// close the db and create new instance of blockchain (and the associated async indexer) - the indexer should index the pending blocks
190+
// close the db
191191
testDBWrapper.CloseDB(t)
192+
// open the db again and create new instance of blockchain (and the associated async indexer)
193+
// the indexer should index the pending blocks
194+
testDBWrapper.OpenDB(t)
192195
testBlockchainWrapper = newTestBlockchainWrapper(t)
193196
defer chain.indexer.stop()
194197

core/system_chaincode/systemchaincode_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"time"
2525

2626
"github.com/hyperledger/fabric/core/chaincode"
27+
"github.com/hyperledger/fabric/core/db"
2728
"github.com/hyperledger/fabric/core/ledger"
2829
"github.com/hyperledger/fabric/core/system_chaincode/api"
2930
"github.com/hyperledger/fabric/core/system_chaincode/samplesyscc"
@@ -34,6 +35,8 @@ import (
3435
"google.golang.org/grpc"
3536
)
3637

38+
var testDBWrapper = db.NewTestDBWrapper()
39+
3740
// Invoke or query a chaincode.
3841
func invoke(ctx context.Context, spec *pb.ChaincodeSpec, typ pb.Transaction_Type) (*pb.ChaincodeEvent, string, []byte, error) {
3942
chaincodeInvocationSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec}
@@ -75,6 +78,7 @@ func closeListenerAndSleep(l net.Listener) {
7578

7679
// Test deploy of a transaction.
7780
func TestExecuteDeploySysChaincode(t *testing.T) {
81+
testDBWrapper.CleanDB(t)
7882
var opts []grpc.ServerOption
7983
grpcServer := grpc.NewServer(opts...)
8084
viper.Set("peer.fileSystemPath", "/var/hyperledger/test/tmpdb")

0 commit comments

Comments
 (0)