Skip to content

Commit

Permalink
[FAB-16315] Improved Load Ability
Browse files Browse the repository at this point in the history
A fairly sizeable CR for improving the load handling
ability of the Java chaincode. This required a rework
of the threading model within the core shim layer.

Plus adding configuration and metrics to support this.
The configuration is a simple Java props file should
the need be to ever modify the default thread pool settings.

Metrics are basic stats on the thread pool are written to the
log

Change-Id: I31b05585a0aa650f7e2a7e2b0389799e90adc2c3
Signed-off-by: Matthew B. White <[email protected]>
(cherry picked from commit baaaef8)
  • Loading branch information
mbwhite authored and jt-nti committed Nov 4, 2019
1 parent 90ba345 commit 4eff463
Show file tree
Hide file tree
Showing 53 changed files with 2,488 additions and 2,072 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*.swp
.gradletasknamecache
.classpath
/bin/
**/bin/
/build/
build/*

Expand Down
25 changes: 10 additions & 15 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,7 @@

apply plugin: 'idea'
apply plugin: 'eclipse-wtp'
apply plugin: 'com.dorongold.task-tree'
version = '2.0.0-SNAPSHOT'

buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "gradle.plugin.com.dorongold.plugins:task-tree:1.4"
}
}


allprojects {
repositories {
mavenCentral()
Expand All @@ -44,11 +30,16 @@ subprojects {
dependencies {
compile 'commons-cli:commons-cli:1.4'
compile 'commons-logging:commons-logging:1.2'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1'

testCompile 'junit:junit:4.12'
testCompile 'org.hamcrest:hamcrest-library:1.3'
testCompile 'org.mockito:mockito-core:2.23.0'
testCompile 'com.github.stefanbirkner:system-rules:1.17.0'

testCompileOnly 'junit:junit:4.12'
testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.3.1'
testCompile 'org.assertj:assertj-core:3.9.1'
}

if (!it.name.equals('fabric-chaincode-protos')) {
Expand All @@ -57,6 +48,10 @@ subprojects {
}
}

test {
useJUnitPlatform()
}

}

task printVersionName() {
Expand Down
1 change: 1 addition & 0 deletions fabric-chaincode-docker/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/bin/
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public Response init(ChaincodeStub stub) {
if (args.size() != 2) {
ResponseUtils.newErrorResponse("Incorrect arguments. Expecting a key and a value");
}

// Set up any variables or assets here by calling stub.putState()
// We store the key and the value on the ledger
stub.putStringState(args.get(0), args.get(1));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package org.hyperleder.fabric.shim.integration;

import org.hyperleder.fabric.shim.integration.DockerCompose.DockerComposeBuilder;

public class FabricState {

private static FabricState state;

public static FabricState getState(){
if (state==null){
state = new FabricState();
}

return state;
}

private boolean started = false;

public synchronized void start(){
if (!this.started) {

// create the docker-compose command
DockerComposeBuilder composebuilder = DockerCompose.newBuilder()
.file("src/test/resources/first-network/docker-compose-cli.yaml");

// close down anything running...
composebuilder.duplicate().down().build().run();

// ...and bring up
DockerCompose compose = composebuilder.up().detach().build();
compose.run();

this.started = true;
} else {
System.out.println("Fabric already started....");
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,7 @@ public static void setUp() throws Exception {
String s = currentRelativePath.toAbsolutePath().toString();
System.out.println("Current relative path is: " + s);

// create the docker-compose command
DockerComposeBuilder composebuilder = DockerCompose.newBuilder()
.file("src/test/resources/first-network/docker-compose-cli.yaml");

// close down anything running...
composebuilder.duplicate().down().build().run();

// ...and bring up
DockerCompose compose = composebuilder.up().detach().build();
compose.run();
FabricState.getState().start();

// the cli container contains a script that does the channel create, joing
// and chaincode install/instantiate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public class SBECCIntegrationTest {
@BeforeClass
public static void setUp() throws Exception {

FabricState.getState().start();

// Call the inbuilt script to install/instantiate
DockerBuilder dockerBuilder = new Docker.DockerBuilder();
Docker docker = dockerBuilder.exec().container("cli").script("./scripts/script-sbe.sh").build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ services:
- CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
- CORE_CHAINCODE_JAVA_RUNTIME=hyperledger/fabric-javaenv:amd64-latest
- CORE_CHAINCODE_EXECUTETIMEOUT=300s
- CORE_CHAINCODE_EXECUTETIMEOUT=400s
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: peer node start
1 change: 0 additions & 1 deletion fabric-chaincode-protos/bin/.gitignore

This file was deleted.

3 changes: 0 additions & 3 deletions fabric-chaincode-shim/bin/.gitignore

This file was deleted.

21 changes: 17 additions & 4 deletions fabric-chaincode-shim/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,15 @@ jacocoTestCoverageVerification {
'org.hyperledger.fabric.contract.routing.RoutingRegistry',
'org.hyperledger.fabric.contract.execution.impl.ContractInvocationRequest',
'org.hyperledger.fabric.contract.routing.TransactionType',
'org.hyperledger.fabric.contract.metadata.MetadataBuilder']
'org.hyperledger.fabric.contract.metadata.MetadataBuilder',
'org.hyperledger.fabric.shim.ChaincodeBase*',
'org.hyperledger.fabric.shim.impl.InnvocationTaskManager',
'org.hyperledger.fabric.shim.impl.InnvocationStubImpl*',
'org.hyperledger.fabric.shim.impl.ChaincodeSupportClient*',
'org.hyperledger.fabric.shim.impl.InnvocationTaskExecutor',
'org.hyperledger.fabric.shim.impl.ChaincodeInnvocationTask',
'org.hyperledger.fabric.shim.impl.QueryResultsIteratorImpl*',
'org.hyperledger.fabric.shim.impl.ChaincodeMessageFactory']
limit {
minimum = 0.86
}
Expand All @@ -99,7 +107,12 @@ jacocoTestCoverageVerification {
'org.hyperledger.fabric.contract.routing.impl.ContractDefinitionImpl',
'org.hyperledger.fabric.contract.routing.RoutingRegistry',
'org.hyperledger.fabric.shim.impl.Handler',
'org.hyperledger.fabric.contract.metadata.MetadataBuilder']
'org.hyperledger.fabric.shim.ChaincodeBase',
'org.hyperledger.fabric.contract.metadata.MetadataBuilder',
'org.hyperledger.fabric.shim.impl.InnvocationTaskManager',
'org.hyperledger.fabric.shim.impl.InnvocationTaskExecutor',
'org.hyperledger.fabric.shim.impl.ChaincodeSupportClient',
'org.hyperledger.fabric.shim.impl.ChaincodeMessageFactory']
limit {
minimum = 0.71
}
Expand Down Expand Up @@ -169,15 +182,15 @@ task licenseCheck {


javadoc {
failOnError = true
failOnError = false
excludes = ['org/hyperledger/fabric/contract/ContextFactory.java',
'org/hyperledger/fabric/contract/ContractRouter.java',
'org/hyperledger/fabric/contract/ContractRuntimeException.java',
'org/hyperledger/fabric/contract/execution/**',
'org/hyperledger/fabric/contract/metadata/**',
'org/hyperledger/fabric/contract/routing/**',
'org/hyperledger/fabric/contract/systemcontract/**',
'org/hyperledger/fabric/shim/impl/**',
'org/hyperledger/fabric/**/impl/**',
'org/hyperledger/fabric/shim/helper/**',
'org/hyperledger/fabric/shim/ChaincodeBase.java']
source = sourceSets.main.allJava
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.LogManager;

/**
* Assistance class to use when logging.
*
* For chaincode/contract implementations please use java.util.logging or your
* own framework. All the Hyperledger Fabric code here is logged in loggers with
* names starting org.hyperledger
*
* Control of this is via the environment variables
* 'CORE_CHAINCODE_LOGGING_LEVEL' this takes a string that matches the following
* Java.util.logging levels (case insensitive)
*
* CRITICAL, ERROR == Level.SEVERE, WARNING == Level.WARNING, INFO == Level.INFO
* NOTICE == Level.CONFIG, DEBUG == Level.FINEST
*
*/
public class Logging {

public static final String PERFLOGGER = "org.hyperledger.Performance";

/**
* Formats a Throwable to a string with details of all the causes as well
*
* @param throwable Exception
* @return String formatted with all the details
*/
public static String formatError(final Throwable throwable) {
if (throwable == null) {
return null;
}
final StringWriter buffer = new StringWriter();
buffer.append(throwable.getMessage()).append(System.lineSeparator());

throwable.printStackTrace(new PrintWriter(buffer));

final Throwable cause = throwable.getCause();
if (cause != null) {
buffer.append(".. caused by ..").append(System.lineSeparator());
buffer.append(Logging.formatError(cause));
}

return buffer.toString();

}

/**
* Sets the log level to the the
* @param newLevel the new logging level
*/
public static void setLogLevel(String newLevel) {

Level l = mapLevel(newLevel);
LogManager logManager = LogManager.getLogManager();
// slightly cumbersome approach - but the loggers don't have a 'get children'
// so find those that have the correct stem.
final ArrayList<String> allLoggers = Collections.list(logManager.getLoggerNames());
allLoggers.add("org.hyperledger");
allLoggers.stream().filter(name -> name.startsWith("org.hyperledger")).map(name -> logManager.getLogger(name))
.forEach(logger -> {
if (logger != null) {
logger.setLevel(l);
}
});
}

private static Level mapLevel(final String level) {
if (level != null) {
switch (level.toUpperCase().trim()) {
case "ERROR":
case "CRITICAL":
return Level.SEVERE;
case "WARNING":
return Level.WARNING;
case "INFO":
return Level.INFO;
case "NOTICE":
return Level.CONFIG;
case "DEBUG":
return Level.FINEST;
}
}
return Level.INFO;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@

package org.hyperledger.fabric.contract;

import org.hyperledger.fabric.Logger;
import java.util.Properties;
import java.util.logging.Logger;

import org.hyperledger.fabric.Logging;
import org.hyperledger.fabric.contract.execution.ExecutionFactory;
import org.hyperledger.fabric.contract.execution.ExecutionService;
import org.hyperledger.fabric.contract.execution.InvocationRequest;
Expand All @@ -17,6 +20,7 @@
import org.hyperledger.fabric.contract.routing.TypeRegistry;
import org.hyperledger.fabric.contract.routing.impl.RoutingRegistryImpl;
import org.hyperledger.fabric.contract.routing.impl.TypeRegistryImpl;
import org.hyperledger.fabric.metrics.Metrics;
import org.hyperledger.fabric.shim.ChaincodeBase;
import org.hyperledger.fabric.shim.ChaincodeStub;
import org.hyperledger.fabric.shim.ResponseUtils;
Expand All @@ -40,16 +44,20 @@ public class ContractRouter extends ChaincodeBase {
*
* @param args
*/
public ContractRouter(String[] args) {
public ContractRouter(String[] args) {
super.initializeLogging();
super.processEnvironmentOptions();
super.processCommandLineOptions(args);

Properties props = super.getChaincodeConfig();
Metrics.initialize(props);

super.validateOptions();
logger.debug("ContractRouter<init>");
logger.fine("ContractRouter<init>");
registry = new RoutingRegistryImpl();
typeRegistry = new TypeRegistryImpl();
executor = ExecutionFactory.getInstance().createExecutionService(typeRegistry);

}

/**
Expand All @@ -70,7 +78,7 @@ void startRouting() {
super.connectToPeer();
} catch (Exception e) {
ContractRuntimeException cre = new ContractRuntimeException("Unable to start routing");
logger.error(() -> logger.formatError(cre));
logger.severe(()-> Logging.formatError(cre));
throw cre;
}
}
Expand Down Expand Up @@ -114,7 +122,7 @@ TxFunction getRouting(InvocationRequest request) {
if (registry.containsRoute(request)) {
return registry.getTxFn(request);
} else {
logger.debug(() -> "Namespace is " + request);
logger.fine(() -> "Namespace is " + request);
ContractDefinition contract = registry.getContract(request.getNamespace());
return contract.getUnknownRoute();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import org.hyperledger.fabric.Logger;
import org.hyperledger.fabric.contract.Context;
import org.hyperledger.fabric.contract.ContractInterface;
import org.hyperledger.fabric.contract.ContractRuntimeException;
Expand Down Expand Up @@ -42,7 +42,7 @@ public ContractExecutionService(TypeRegistry typeRegistry) {

@Override
public Chaincode.Response executeRequest(TxFunction txFn, InvocationRequest req, ChaincodeStub stub) {
logger.debug(() -> "Routing Request" + txFn);
logger.fine(() -> "Routing Request" + txFn);
TxFunction.Routing rd = txFn.getRouting();
Chaincode.Response response;

Expand Down Expand Up @@ -90,7 +90,7 @@ private byte[] convertReturn(Object obj, TxFunction txFn) {
private List<Object> convertArgs(List<byte[]> stubArgs, TxFunction txFn) {

List<ParameterDefinition> schemaParams = txFn.getParamsList();
List<Object> args = new ArrayList<>(stubArgs.size() + 1); // allow for context as the first arguement
List<Object> args = new ArrayList<>(stubArgs.size() + 1); // allow for context as the first argument
for (int i = 0; i < schemaParams.size(); i++) {
args.add(i, serializer.fromBuffer(stubArgs.get(i), schemaParams.get(i).getSchema()));
}
Expand Down
Loading

0 comments on commit 4eff463

Please sign in to comment.