Skip to content

Commit

Permalink
FAB-1140 Move couchDB code to Util
Browse files Browse the repository at this point in the history
Move the couchDB common code to util directory
for use by both the state and history database functionality.

Change-Id: Ia6ce37a6ae576fdc9faf46666b4ff1a0269bc1f5
Signed-off-by: Mari Wade <mariwade@us.ibm.com>
  • Loading branch information
mariwade committed Dec 2, 2016
1 parent ed2d579 commit af6e1a6
Show file tree
Hide file tree
Showing 10 changed files with 289 additions and 31 deletions.
52 changes: 52 additions & 0 deletions core/ledger/history/couchdb_histmgr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package history

import (
"github.com/hyperledger/fabric/core/ledger/util/couchdb"
"github.com/hyperledger/fabric/protos/common"
logging "github.com/op/go-logging"
)

var logger = logging.MustGetLogger("txhistorymgmt")

// CouchDBHistMgr a simple implementation of interface `histmgmt.TxHistMgr'.
// TODO This implementation does not currently use a lock but may need one to insure query's are consistent
type CouchDBHistMgr struct {
couchDB *couchdb.CouchDBConnectionDef // COUCHDB new properties for CouchDB
}

// NewCouchDBHistMgr constructs a new `CouchDBTxHistMgr`
func NewCouchDBHistMgr(couchDBConnectURL string, dbName string, id string, pw string) *CouchDBHistMgr {

//TODO locking has not been implemented but may need some sort of locking to insure queries are valid data.

couchDB, err := couchdb.CreateCouchDBConnectionAndDB(couchDBConnectURL, dbName, id, pw)
if err != nil {
logger.Errorf("Error during NewCouchDBHistMgr(): %s\n", err.Error())
return nil
}

// db and stateIndexCF will not be used for CouchDB. TODO to cleanup
return &CouchDBHistMgr{couchDB: couchDB}
}

// Commit implements method in interface `txhistorymgmt.TxMgr`
func (histmgr *CouchDBHistMgr) Commit(block *common.Block) error {
logger.Debugf("===HISTORYDB=== Entering CouchDBTxHistMgr.Commit()")
return nil
}
102 changes: 102 additions & 0 deletions core/ledger/history/couchdb_histmgr_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package history

import (
"fmt"
"os"
"testing"

"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
"github.com/hyperledger/fabric/core/ledger/testutil"
"github.com/hyperledger/fabric/core/ledger/util/couchdb"
)

//Complex setup to test the use of couch in ledger
type testEnvCouch struct {
couchDBPath string
couchDBAddress string
couchDatabaseName string
couchUsername string
couchPassword string
}

func newTestEnvCouch(t testing.TB, dbPath string, dbName string) *testEnvCouch {

couchDBDef := ledgerconfig.GetCouchDBDefinition()
os.RemoveAll(dbPath)

return &testEnvCouch{
couchDBPath: dbPath,
couchDBAddress: couchDBDef.URL,
couchDatabaseName: dbName,
couchUsername: couchDBDef.Username,
couchPassword: couchDBDef.Password,
}
}

func (env *testEnvCouch) cleanup() {
os.RemoveAll(env.couchDBPath)
//create a new connection
couchDB, _ := couchdb.CreateConnectionDefinition(env.couchDBAddress, env.couchDatabaseName, env.couchUsername, env.couchPassword)
//drop the test database if it already existed
couchDB.DropDatabase()
}

// couchdb_test.go tests couchdb functions already. This test just tests that a CouchDB history database is auto-created
// upon creating a new history transaction manager
func TestHistoryDatabaseAutoCreate(t *testing.T) {

//call a helper method to load the core.yaml
testutil.SetupCoreYAMLConfig("./../../../peer")

//Only run the tests if CouchDB is explitily enabled in the code,
//otherwise CouchDB may not be installed and all the tests would fail
//TODO replace this with external config property rather than config within the code
if ledgerconfig.IsCouchDBEnabled() == true {

env := newTestEnvCouch(t, "/tmp/tests/ledger/history", "history-test")
env.cleanup() //cleanup at the beginning to ensure the database doesn't exist already
defer env.cleanup() //and cleanup at the end

histMgr := NewCouchDBHistMgr(
env.couchDBAddress, //couchDB Address
env.couchDatabaseName, //couchDB db name
env.couchUsername, //enter couchDB id
env.couchPassword) //enter couchDB pw

//NewCouchDBhistMgr should have automatically created the database, let's make sure it has been created
//Retrieve the info for the new database and make sure the name matches
dbResp, _, errdb := histMgr.couchDB.GetDatabaseInfo()
testutil.AssertNoError(t, errdb, fmt.Sprintf("Error when trying to retrieve database information"))
testutil.AssertEquals(t, dbResp.DbName, env.couchDatabaseName)

//Call NewCouchDBhistMgr again, this time the database will already exist from last time
histMgr2 := NewCouchDBHistMgr(
env.couchDBAddress, //couchDB Address
env.couchDatabaseName, //couchDB db name
env.couchUsername, //enter couchDB id
env.couchPassword) //enter couchDB pw

//Retrieve the info for the database again, and make sure the name still matches
dbResp2, _, errdb2 := histMgr2.couchDB.GetDatabaseInfo()
testutil.AssertNoError(t, errdb2, fmt.Sprintf("Error when trying to retrieve database information"))
testutil.AssertEquals(t, dbResp2.DbName, env.couchDatabaseName)

}

}
24 changes: 24 additions & 0 deletions core/ledger/history/histmgmt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package history

import "github.com/hyperledger/fabric/protos/common"

// TxHistMgr - an interface that a transaction history manager should implement
type TxHistMgr interface {
Commit(block *common.Block) error
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ import (
"os"
"testing"

"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/couchdbtxmgmt/couchdb"
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
"github.com/hyperledger/fabric/core/ledger/testutil"
"github.com/hyperledger/fabric/core/ledger/util/couchdb"
)

type testEnv struct {
Expand Down Expand Up @@ -97,7 +97,7 @@ func TestDatabaseAutoCreate(t *testing.T) {
env.couchPassword) //enter couchDB pw

//Retrieve the info for the database again, and make sure the name still matches
dbResp2, _, errdb2 := txMgr.couchDB.GetDatabaseInfo()
dbResp2, _, errdb2 := txMgr2.couchDB.GetDatabaseInfo()
testutil.AssertNoError(t, errdb2, fmt.Sprintf("Error when trying to retrieve database information"))
testutil.AssertEquals(t, dbResp2.DbName, env.couchDatabaseName)

Expand Down
17 changes: 5 additions & 12 deletions core/ledger/kvledger/txmgmt/couchdbtxmgmt/couchdb_txmgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/couchdbtxmgmt/couchdb"
"github.com/hyperledger/fabric/core/ledger/util/couchdb"
"github.com/hyperledger/fabric/core/ledger/util/db"
"github.com/op/go-logging"

Expand Down Expand Up @@ -74,6 +74,7 @@ type CouchDBTxMgr struct {
}

// CouchConnection provides connection info for CouchDB
//TODO not currently used
type CouchConnection struct {
host string
port int
Expand All @@ -89,18 +90,10 @@ func NewCouchDBTxMgr(conf *Conf, couchDBConnectURL string, dbName string, id str
db := db.CreateDB(&db.Conf{DBPath: conf.DBPath})
db.Open()

couchDB, err := couchdb.CreateConnectionDefinition(couchDBConnectURL,
dbName,
id,
pw)
couchDB, err := couchdb.CreateCouchDBConnectionAndDB(couchDBConnectURL, dbName, id, pw)
if err != nil {
logger.Errorf("===COUCHDB=== Error during CreateConnectionDefinition(): %s\n", err.Error())
}

// Create CouchDB database upon ledger startup, if it doesn't already exist
_, err = couchDB.CreateDatabaseIfNotExist()
if err != nil {
logger.Errorf("===COUCHDB=== Error during CreateDatabaseIfNotExist(): %s\n", err.Error())
logger.Errorf("Error during NewCouchDBTxMgr(): %s\n", err.Error())
return nil
}

// db and stateIndexCF will not be used for CouchDB. TODO to cleanup
Expand Down
8 changes: 8 additions & 0 deletions core/ledger/ledgerconfig/ledger_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ import (

func TestIsCouchDBEnabledDefault(t *testing.T) {
setUpCoreYAMLConfig()
// During a build the default values should be false.

// If the ledger test are run with CouchDb enabled, need to provide a mechanism
// To let this test run but still test default values.
if IsCouchDBEnabled() == true {
testutil.ResetConfigToDefaultValues()
defer viper.Set("ledger.state.stateDatabase", "CouchDB")
}
defaultValue := IsCouchDBEnabled()
testutil.AssertEquals(t, defaultValue, false) //test default config is false
}
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,20 @@ import (
"github.com/hyperledger/fabric/core/ledger/testutil"
)

//Basic setup to test couch
var connectURL = "localhost:5984"
var badConnectURL = "localhost:5990"
var database = "testdb1"
var username = ""
var password = ""

func cleanup() {
//create a new connection
db, _ := CreateConnectionDefinition(connectURL, database, username, password)
//drop the test database
db.DropDatabase()
}

type Asset struct {
ID string `json:"_id"`
Rev string `json:"_rev"`
Expand All @@ -34,18 +48,12 @@ type Asset struct {
Owner string `json:"owner"`
}

var connectURL = "localhost:5984"
var badConnectURL = "localhost:5990"
var database = "testdb1"
var username = ""
var password = ""

var assetJSON = []byte(`{"asset_name":"marble1","color":"blue","size":"35","owner":"jerry"}`)

func TestDBConnectionDef(t *testing.T) {

//call a helper method to load the core.yaml
testutil.SetupCoreYAMLConfig("./../../../../../../peer")
testutil.SetupCoreYAMLConfig("./../../../../peer")

//create a new connection
_, err := CreateConnectionDefinition(connectURL, "database", "", "")
Expand Down Expand Up @@ -317,13 +325,3 @@ func TestDBTestDropDatabaseBadConnection(t *testing.T) {
}

}

func cleanup() {

//create a new connection
db, _ := CreateConnectionDefinition(connectURL, database, username, password)

//drop the test database
db.DropDatabase()

}
39 changes: 39 additions & 0 deletions core/ledger/util/couchdb/couchdbutil.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package couchdb

//CreateCouchDBConnectionAndDB creates a CouchDB Connection and the database if it does not exist
func CreateCouchDBConnectionAndDB(couchDBConnectURL string, dbName string, id string, pw string) (*CouchDBConnectionDef, error) {
couchDB, err := CreateConnectionDefinition(couchDBConnectURL,
dbName,
id,
pw)
if err != nil {
logger.Errorf("Error during CouchDB CreateConnectionDefinition() to dbName: %s error: %s\n", dbName, err.Error())
return nil, err
}

// Create CouchDB database upon ledger startup, if it doesn't already exist
_, err = couchDB.CreateDatabaseIfNotExist()
if err != nil {
logger.Errorf("Error during CouchDB CreateDatabaseIfNotExist() to dbName: %s error: %s\n", dbName, err.Error())
return nil, err
}

//return the couch db connection
return couchDB, nil
}
42 changes: 42 additions & 0 deletions core/ledger/util/couchdb/couchdbutil_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package couchdb

import (
"fmt"
"testing"

"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
"github.com/hyperledger/fabric/core/ledger/testutil"
)

//Unit test of couch db util functionality
func TestCreateCouchDBConnectionAndDB(t *testing.T) {

//call a helper method to load the core.yaml
testutil.SetupCoreYAMLConfig("./../../../../peer")

if ledgerconfig.IsCouchDBEnabled() == true {

cleanup()
defer cleanup()
//create a new connection
_, err := CreateCouchDBConnectionAndDB(connectURL, database, "", "")
testutil.AssertNoError(t, err, fmt.Sprintf("Error when trying to CreateCouchDBConnectionAndDB"))
}

}

0 comments on commit af6e1a6

Please sign in to comment.