Skip to content

Commit

Permalink
FAB-9729 Make VMCProcess non-package scoped
Browse files Browse the repository at this point in the history
The chaincode package has already been reworked to reference the
VMCProcess function as an interface method.  This CR simply modifies the
container package to make the VMCProcess function a method of
VMController and exposes a constructor for creating the VMController.

Change-Id: Ib08e77ece59b30d2564db065197782513c18d6d6
Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
  • Loading branch information
Jason Yellick committed May 8, 2018
1 parent acf93e7 commit 143d35a
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 194 deletions.
4 changes: 2 additions & 2 deletions core/chaincode/chaincode_support.go
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/core/common/ccprovider"
"github.com/hyperledger/fabric/core/common/sysccprovider"
"github.com/hyperledger/fabric/core/container"
"github.com/hyperledger/fabric/core/container/ccintf"
pb "github.com/hyperledger/fabric/protos/peer"
"github.com/pkg/errors"
Expand Down Expand Up @@ -47,6 +46,7 @@ func NewChaincodeSupport(
certGenerator CertGenerator,
packageProvider PackageProvider,
aclProvider ACLProvider,
processor Processor,
) *ChaincodeSupport {
cs := &ChaincodeSupport{
UserRunsCC: userRunsCC,
Expand All @@ -63,7 +63,7 @@ func NewChaincodeSupport(

cs.Runtime = &ContainerRuntime{
CertGenerator: certGenerator,
Processor: ProcessFunc(container.VMCProcess),
Processor: processor,
CACert: caCert,
PeerAddress: peerAddress,
PeerID: config.PeerID,
Expand Down
1 change: 1 addition & 0 deletions core/chaincode/chaincode_support_test.go
Expand Up @@ -177,6 +177,7 @@ func initMockPeer(chainIDs ...string) (*ChaincodeSupport, error) {
certGenerator,
&ccprovider.CCInfoFSImpl{},
aclmgmt.GetACLProvider(),
container.NewVMController(),
)
SideEffectInitialize(chaincodeSupport)
chaincodeSupport.SetSysCCProvider(sccp)
Expand Down
8 changes: 0 additions & 8 deletions core/chaincode/container_runtime.go
Expand Up @@ -28,14 +28,6 @@ type Processor interface {
Process(ctxt context.Context, vmtype string, req container.VMCReqIntf) (container.VMCResp, error)
}

// ProcessFunc adapts a function to satisfy the Processor interface.
type ProcessFunc func(ctxt context.Context, vmtype string, req container.VMCReqIntf) (container.VMCResp, error)

// Process processes vm and container requests.
func (v ProcessFunc) Process(ctxt context.Context, vmtype string, req container.VMCReqIntf) (container.VMCResp, error) {
return v(ctxt, vmtype, req)
}

// CertGenerator generates client certificates for chaincode.
type CertGenerator interface {
// Generate returns a certificate and private key and associates
Expand Down
20 changes: 0 additions & 20 deletions core/chaincode/container_runtime_test.go
Expand Up @@ -322,23 +322,3 @@ func TestContainerRuntimeStopErrors(t *testing.T) {
assert.NoError(t, err)
}
}

func TestProcessFunc(t *testing.T) {
var c context.Context
var v string
var r container.VMCReqIntf

processFunc := func(ctxt context.Context, vmtype string, req container.VMCReqIntf) (container.VMCResp, error) {
c = ctxt
v = vmtype
r = req
return container.VMCResp{Err: errors.New("response-error")}, errors.New("func-error")
}

resp, err := chaincode.ProcessFunc(processFunc).Process(context.Background(), "vm-type", container.StartContainerReq{})
assert.EqualError(t, resp.Err, "response-error")
assert.EqualError(t, err, "func-error")
assert.Equal(t, c, context.Background())
assert.Equal(t, v, "vm-type")
assert.Equal(t, r, container.StartContainerReq{})
}
1 change: 1 addition & 0 deletions core/chaincode/exectransaction_test.go
Expand Up @@ -125,6 +125,7 @@ func initPeer(chainIDs ...string) (net.Listener, *ChaincodeSupport, func(), erro
certGenerator,
&ccprovider.CCInfoFSImpl{},
aclmgmt.GetACLProvider(),
container.NewVMController(),
)
chaincodeSupport.SetSysCCProvider(sccp)
SideEffectInitialize(chaincodeSupport)
Expand Down
2 changes: 2 additions & 0 deletions core/chaincode/systemchaincode_test.go
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/core/common/ccprovider"
"github.com/hyperledger/fabric/core/common/sysccprovider"
"github.com/hyperledger/fabric/core/container"
"github.com/hyperledger/fabric/core/peer"
"github.com/hyperledger/fabric/core/scc"
pb "github.com/hyperledger/fabric/protos/peer"
Expand Down Expand Up @@ -131,6 +132,7 @@ func initSysCCTests() (*oldSysCCInfo, net.Listener, *ChaincodeSupport, error) {
certGenerator,
&ccprovider.CCInfoFSImpl{},
aclmgmt.GetACLProvider(),
container.NewVMController(),
)
pb.RegisterChaincodeSupportServer(grpcServer, chaincodeSupport)

Expand Down
33 changes: 18 additions & 15 deletions core/container/controller.go
Expand Up @@ -38,8 +38,11 @@ type VMController struct {

var vmLogger = flogging.MustGetLogger("container")

var vmcontroller = &VMController{
containerLocks: make(map[string]*refCountedLock),
// NewVMController creates a new instance of VMController
func NewVMController() *VMController {
return &VMController{
containerLocks: make(map[string]*refCountedLock),
}
}

//constants for supported containers
Expand All @@ -64,37 +67,37 @@ func (vmc *VMController) newVM(typ string) api.VM {

func (vmc *VMController) lockContainer(id string) {
//get the container lock under global lock
vmcontroller.Lock()
vmc.Lock()
var refLck *refCountedLock
var ok bool
if refLck, ok = vmcontroller.containerLocks[id]; !ok {
if refLck, ok = vmc.containerLocks[id]; !ok {
refLck = &refCountedLock{refCount: 1, lock: &sync.RWMutex{}}
vmcontroller.containerLocks[id] = refLck
vmc.containerLocks[id] = refLck
} else {
refLck.refCount++
vmLogger.Debugf("refcount %d (%s)", refLck.refCount, id)
}
vmcontroller.Unlock()
vmc.Unlock()
vmLogger.Debugf("waiting for container(%s) lock", id)
refLck.lock.Lock()
vmLogger.Debugf("got container (%s) lock", id)
}

func (vmc *VMController) unlockContainer(id string) {
vmcontroller.Lock()
if refLck, ok := vmcontroller.containerLocks[id]; ok {
vmc.Lock()
if refLck, ok := vmc.containerLocks[id]; ok {
if refLck.refCount <= 0 {
panic("refcnt <= 0")
}
refLck.lock.Unlock()
if refLck.refCount--; refLck.refCount == 0 {
vmLogger.Debugf("container lock deleted(%s)", id)
delete(vmcontroller.containerLocks, id)
delete(vmc.containerLocks, id)
}
} else {
vmLogger.Debugf("no lock to unlock(%s)!!", id)
}
vmcontroller.Unlock()
vmc.Unlock()
}

//VMCReqIntf - all requests should implement this interface.
Expand Down Expand Up @@ -165,16 +168,16 @@ func (si StopContainerReq) getCCID() ccintf.CCID {
return si.CCID
}

//VMCProcess should be used as follows
//Process should be used as follows
// . construct a context
// . construct req of the right type (e.g., CreateImageReq)
// . call it in a go routine
// . process response in the go routing
//context can be cancelled. VMCProcess will try to cancel calling functions if it can
//For instance docker clients api's such as BuildImage are not cancelable.
//In all cases VMCProcess will wait for the called go routine to return
func VMCProcess(ctxt context.Context, vmtype string, req VMCReqIntf) (VMCResp, error) {
v := vmcontroller.newVM(vmtype)
func (vmc *VMController) Process(ctxt context.Context, vmtype string, req VMCReqIntf) (VMCResp, error) {
v := vmc.newVM(vmtype)
if v == nil {
return VMCResp{}, fmt.Errorf("Unknown VM type %s", vmtype)
}
Expand All @@ -189,9 +192,9 @@ func VMCProcess(ctxt context.Context, vmtype string, req VMCReqIntf) (VMCResp, e
resp = VMCResp{Err: err}
return
}
vmcontroller.lockContainer(id)
vmc.lockContainer(id)
resp = req.do(ctxt, v)
vmcontroller.unlockContainer(id)
vmc.unlockContainer(id)
}()

select {
Expand Down

0 comments on commit 143d35a

Please sign in to comment.