Skip to content

Commit

Permalink
Merge "[FAB-2976] Server shouldn't create dup affiliations"
Browse files Browse the repository at this point in the history
  • Loading branch information
mastersingh24 authored and Gerrit Code Review committed May 19, 2017
2 parents 6eec8f5 + 01d2dd0 commit 8206d83
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 24 deletions.
4 changes: 4 additions & 0 deletions lib/client_whitebox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ func getServer(port int, home, parentURL string, maxEnroll int, t *testing.T) *S
},
"org2": nil,
}
affiliations[affiliationName] = map[string]interface{}{
"department1": nil,
"department2": nil,
}
srv := &Server{
Config: &ServerConfig{
Port: port,
Expand Down
35 changes: 19 additions & 16 deletions lib/dbutil/dbutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,29 +35,32 @@ func NewUserRegistrySQLLite3(datasource string) (*sqlx.DB, bool, error) {
log.Debugf("Using sqlite database, connect to database in home (%s) directory", datasource)

datasource = filepath.Join(datasource)
var exists bool
exists := false

if datasource != "" {
// Check if database exists if not create it and bootstrap it based on the config file
if _, err := os.Stat(datasource); err != nil {
if os.IsNotExist(err) {
log.Debugf("Database (%s) does not exist", datasource)
exists = false
err2 := createSQLiteDBTables(datasource)
if err2 != nil {
return nil, false, err2
}
} else {
log.Debug("Database (%s) exists", datasource)
exists = true
// Check if database exists if not create it and bootstrap it based
// on the config file
_, err := os.Stat(datasource)
if err != nil && os.IsNotExist(err) {
log.Debugf("Database (%s) does not exist", datasource)
err2 := createSQLiteDBTables(datasource)
if err2 != nil {
return nil, false, err2
}
} else {
// database file exists. If os.Stat returned an error
// other than IsNotExist error, which still means
// file exists
log.Debugf("Database (%s) exists", datasource)
exists = true
}
}

db, err := sqlx.Open("sqlite3", datasource+"?_busy_timeout=5000")
if err != nil {
return nil, false, err
}

// Set maximum open connections to one. This is to share one connection
// across multiple go routines. This will serialize database operations
// with in a single server there by preventing "database is locked"
Expand Down Expand Up @@ -89,7 +92,7 @@ func createSQLiteDBTables(datasource string) error {
}
log.Debug("Created users table")

if _, err := db.Exec("CREATE TABLE IF NOT EXISTS affiliations (name VARCHAR(64), prekey VARCHAR(64))"); err != nil {
if _, err := db.Exec("CREATE TABLE IF NOT EXISTS affiliations (name VARCHAR(64) NOT NULL UNIQUE, prekey VARCHAR(64))"); err != nil {
return err
}
log.Debug("Created affiliation table")
Expand Down Expand Up @@ -187,7 +190,7 @@ func createPostgresDBTables(datasource string, dbName string, db *sqlx.DB) error
log.Errorf("Error creating users table [error: %s] ", err)
return err
}
if _, err := database.Exec("CREATE TABLE affiliations (name VARCHAR(64), prekey VARCHAR(64))"); err != nil {
if _, err := database.Exec("CREATE TABLE affiliations (name VARCHAR(64) NOT NULL UNIQUE, prekey VARCHAR(64))"); err != nil {
log.Errorf("Error creating affiliations table [error: %s] ", err)
return err
}
Expand Down Expand Up @@ -273,7 +276,7 @@ func createMySQLTables(datasource string, dbName string, db *sqlx.DB) error {
log.Errorf("Error creating users table [error: %s] ", err)
return err
}
if _, err := database.Exec("CREATE TABLE affiliations (name VARCHAR(64), prekey VARCHAR(64))"); err != nil {
if _, err := database.Exec("CREATE TABLE affiliations (name VARCHAR(64) NOT NULL UNIQUE, prekey VARCHAR(64))"); err != nil {
log.Errorf("Error creating affiliations table [error: %s] ", err)
return err
}
Expand Down
28 changes: 27 additions & 1 deletion lib/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"path/filepath"
"strconv"
"strings"
"time"

"github.com/cloudflare/cfssl/log"
stls "github.com/hyperledger/fabric-ca/lib/tls"
Expand Down Expand Up @@ -68,6 +69,9 @@ type Server struct {

// A map of CA configs stored by CA file as key
caConfigMap map[string]*CAConfig

// channel for communication between http.serve and main threads.
wait chan bool
}

// Init initializes a fabric-ca server
Expand Down Expand Up @@ -458,6 +462,7 @@ func (s *Server) listenAndServe() (err error) {
if s.BlockingStart {
return s.serve()
}
s.wait = make(chan bool)
go s.serve()

return nil
Expand All @@ -477,6 +482,9 @@ func (s *Server) serve() error {
}
s.serveError = http.Serve(listener, s.mux)
log.Errorf("Server has stopped serving: %s", s.serveError)
if s.wait != nil {
s.wait <- true
}
s.closeListener()
return s.serveError
}
Expand Down Expand Up @@ -529,7 +537,25 @@ func (s *Server) closeListener() error {
log.Info("The server closed its listener endpoint")
} else {
log.Errorf("The server failed to close its listener endpoint; err=%s", err)
return err
}
s.listener = nil
return err
if s.wait == nil {
return nil
}
// Wait for message on wait channel from the http.serve thread. If message
// is not recevied in three seconds, return
for i := 0; i < 3; i++ {
select {
case <-s.wait:
log.Debugf("Received server stopped message")
close(s.wait)
return nil
default:
log.Debugf("Waiting for server to stop")
time.Sleep(time.Second)
}
}
log.Debugf("Stopped waiting for server to stop")
return nil
}
13 changes: 7 additions & 6 deletions lib/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"strconv"
"strings"
"testing"
"time"

"github.com/hyperledger/fabric-ca/api"
. "github.com/hyperledger/fabric-ca/lib"
Expand All @@ -36,9 +37,9 @@ import (
)

const (
rootPort = 7055
rootPort = 7075
rootDir = "rootDir"
intermediatePort = 7056
intermediatePort = 7076
intermediateDir = "intDir"
testdataDir = "../testdata"
pportEnvVar = "FABRIC_CA_SERVER_PROFILE_PORT"
Expand Down Expand Up @@ -384,8 +385,8 @@ func invalidTokenAuthorization(t *testing.T) {
client := getRootClient()

emptyByte := make([]byte, 0)

req, err := http.NewRequest("POST", "http://localhost:7055/enroll", bytes.NewReader(emptyByte))
url := fmt.Sprintf("http://localhost:%d/enroll", rootPort)
req, err := http.NewRequest("POST", url, bytes.NewReader(emptyByte))
if err != nil {
t.Error(err)
}
Expand Down Expand Up @@ -419,8 +420,8 @@ func invalidBasicAuthorization(t *testing.T) {
client := getRootClient()

emptyByte := make([]byte, 0)

req, err := http.NewRequest("POST", "http://localhost:7055/register", bytes.NewReader(emptyByte))
url := fmt.Sprintf("http://localhost:%d/register", rootPort)
req, err := http.NewRequest("POST", url, bytes.NewReader(emptyByte))
if err != nil {
t.Error(err)
}
Expand Down
63 changes: 63 additions & 0 deletions lib/server_whitebox_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
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 lib

import (
"testing"

"github.com/hyperledger/fabric-ca/lib/spi"
)

const (
serverPort = 7060
affiliationName = "org1"
)

// TestGetAffliation checks if there is one record for the
// affilition 'org1' in the database after starting the server
// two times. This test is to make sure server does not create
// duplicate affiliations in the database every time it is
// started.
func TestGetAffliation(t *testing.T) {
// Start the server at an available port (using port 0 will make OS to
// pick an available port)
srv := getServer(serverPort, testdataDir, "", 0, t)

err := srv.Start()
if err != nil {
t.Fatalf("Server start failed: %v", err)
}
err = srv.Stop()
if err != nil {
t.Fatalf("Server stop failed: %v", err)
}

err = srv.Start()
if err != nil {
t.Fatalf("Server start failed: %v", err)
}
defer srv.Stop()

afs := []spi.AffiliationImpl{}
err = srv.db.Select(&afs, srv.db.Rebind(getAffiliation), affiliationName)
t.Logf("Retrieved %+v for the affiliation %s", afs, affiliationName)
if err != nil {
t.Fatalf("Failed to get affiliation %s: %v", affiliationName, err)
}
if len(afs) != 1 {
t.Fatalf("Found 0 or more than one record for the affiliation %s in the database, expected 1 record", affiliationName)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ csr:

intermediate:
parentserver:
url: http://admin:adminpw@localhost:7055
url: http://admin:adminpw@localhost:7075
caname: rootca2

0 comments on commit 8206d83

Please sign in to comment.