Skip to content

Commit

Permalink
[FAB-3273] java cc get state by range
Browse files Browse the repository at this point in the history
- Introduced KeyValue type that maps to KV proto.
- New QueryResultsIterator.
- Re-arranged packages to keep public vs. internal
  code as separate as possible.
  * org.hyperledger.fabric.shim (public shim API)
  * org.hyperledger.fabric.impl (implementations)
  * org.hyperledger.fabric.shim.ledger (public
    ledger interfaces)

- ChaincodeStub:
 * QueryResultsIterator<KeyValue> getStateForRange(start, end)
 * QueryResultsIterator<KeyValue> getStateForPartialCompositeKey(key)

- Handler
 * QueryResponse handleGetStateForRange()
 * QueryResponse queryStateNext()
 * void queryStateClose()
 * Reduce the visibily of members in order to minimize the
   public API as much as possible.

Change-Id: Iea75e426e55ff2e482e0a751b2dbd540bdae6a03
Signed-off-by: Luis Sanchez <sanchezl@us.ibm.com>
  • Loading branch information
Luis Sanchez committed Apr 26, 2017
1 parent 708c3aa commit 5858fbb
Show file tree
Hide file tree
Showing 11 changed files with 499 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import org.hyperledger.fabric.protos.peer.ChaincodeSupportGrpc;
import org.hyperledger.fabric.protos.peer.ChaincodeSupportGrpc.ChaincodeSupportStub;
import org.hyperledger.fabric.protos.peer.ProposalResponsePackage.Response;
import org.hyperledger.fabric.shim.impl.Handler;
import org.hyperledger.fabric.shim.impl.NextStateInfo;

import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
Expand All @@ -49,15 +51,15 @@ public abstract class ChaincodeBase implements Chaincode {
*/
@Override
public abstract Response init(ChaincodeStub stub);

/* (non-Javadoc)
* @see org.hyperledger.fabric.shim.Chaincode#invoke(org.hyperledger.fabric.shim.ChaincodeStub)
*/
@Override
public abstract Response invoke(ChaincodeStub stub);

private static Log logger = LogFactory.getLog(ChaincodeBase.class);

public static final String DEFAULT_HOST = "127.0.0.1";
public static final int DEFAULT_PORT = 7051;

Expand Down Expand Up @@ -181,8 +183,8 @@ public void chatWithPeer(ManagedChannel connection) {
public void onNext(ChaincodeMessage message) {
logger.debug("Got message from peer: " + toJsonString(message));
try {
logger.debug(String.format("[%s]Received message %s from org.hyperledger.fabric.shim",
Handler.shortID(message.getTxid()), message.getType()));
logger.debug(String.format("[%-8s]Received message %s from org.hyperledger.fabric.shim",
message.getTxid(), message.getType()));
handler.handleMessage(message);
} catch (Exception e) {
e.printStackTrace();
Expand Down Expand Up @@ -233,8 +235,8 @@ public void onCompleted() {
if (message.getType() == Type.KEEPALIVE) {
logger.info("Sending KEEPALIVE response");
} else {
logger.info(
"[" + Handler.shortID(message.getTxid()) + "]Send state message " + message.getType());
logger.info(String.format(
"[%-8s]Send state message %s", message.getTxid(), message.getType()));
}
handler.serialSend(message);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import org.hyperledger.fabric.protos.peer.ChaincodeEventPackage.ChaincodeEvent;
import org.hyperledger.fabric.protos.peer.ProposalResponsePackage.Response;
import org.hyperledger.fabric.shim.ledger.CompositeKey;
import org.hyperledger.fabric.shim.ledger.KeyValue;
import org.hyperledger.fabric.shim.ledger.QueryResultsIterator;

public interface ChaincodeStub {

Expand All @@ -49,7 +51,7 @@ public interface ChaincodeStub {
* A convenience method that returns the first argument of the chaincode
* invocation for use as a function name.
*
* The bytes of the first argument are decoded as a UTF-8 string.
* The bytes of the first argument are decoded as a UTF-8 string.
*
* @return the function name
*/
Expand Down Expand Up @@ -77,9 +79,12 @@ public interface ChaincodeStub {
/**
* Invoke another chaincode using the same transaction context.
*
* @param chaincodeName Name of chaincode to be invoked.
* @param args Arguments to pass on to the called chaincode.
* @param channel If not specified, the caller's channel is assumed.
* @param chaincodeName
* Name of chaincode to be invoked.
* @param args
* Arguments to pass on to the called chaincode.
* @param channel
* If not specified, the caller's channel is assumed.
* @return
*/
Response invokeChaincode(String chaincodeName, List<byte[]> args, String channel);
Expand All @@ -89,8 +94,7 @@ public interface ChaincodeStub {
*
* @param key
* name of the value
* @return value
* the value read from the ledger
* @return value the value read from the ledger
*/
byte[] getState(String key);

Expand All @@ -112,20 +116,48 @@ public interface ChaincodeStub {
*/
void delState(String key);

/**
* Returns all existing keys, and their values, that are lexicographically
* between <code>startkey</code> (inclusive) and the <code>endKey</code>
* (exclusive).
*
* @param startKey
* @param endKey
* @return an {@link Iterable} of {@link KeyValue}
*/
QueryResultsIterator<KeyValue> getStateByRange(String startKey, String endKey);

/**
* Returns all existing keys, and their values, that are prefixed by the
* specified partial {@link CompositeKey}.
*
* If a full composite key is specified, it will not match itself, resulting
* in no keys being returned.
*
* @param compositeKey
* partial composite key
* @return an {@link Iterable} of {@link KeyValue}
*/
QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(String compositeKey);

/**
* Given a set of attributes, this method combines these attributes to
* return a composite key.
*
* @param objectType
* @param attributes
* @return a composite key
* @throws CompositeKeyFormatException
* if any parameter contains either a U+000000 or U+10FFFF code
* point.
*/
CompositeKey createCompositeKey(String objectType, String... attributes);

/**
* Parses a composite key from a string.
*
* @param compositeKey a composite key string
* @param compositeKey
* a composite key string
* @return a composite key
*/
CompositeKey splitCompositeKey(String compositeKey);
Expand All @@ -144,8 +176,10 @@ public interface ChaincodeStub {
/**
* Invoke another chaincode using the same transaction context.
*
* @param chaincodeName Name of chaincode to be invoked.
* @param args Arguments to pass on to the called chaincode.
* @param chaincodeName
* Name of chaincode to be invoked.
* @param args
* Arguments to pass on to the called chaincode.
* @return
*/
default Response invokeChaincode(String chaincodeName, List<byte[]> args) {
Expand All @@ -155,27 +189,33 @@ default Response invokeChaincode(String chaincodeName, List<byte[]> args) {
/**
* Invoke another chaincode using the same transaction context.
*
* This is a convenience version of {@link #invokeChaincode(String, List, String)}.
* The string args will be encoded into as UTF-8 bytes.
* This is a convenience version of
* {@link #invokeChaincode(String, List, String)}. The string args will be
* encoded into as UTF-8 bytes.
*
* @param chaincodeName Name of chaincode to be invoked.
* @param args Arguments to pass on to the called chaincode.
* @param channel If not specified, the caller's channel is assumed.
* @param chaincodeName
* Name of chaincode to be invoked.
* @param args
* Arguments to pass on to the called chaincode.
* @param channel
* If not specified, the caller's channel is assumed.
* @return
*/
default Response invokeChaincodeWithStringArgs(String chaincodeName, List<String> args, String channel) {
return invokeChaincode(chaincodeName, args.stream().map(x->x.getBytes(UTF_8)).collect(toList()), channel);
return invokeChaincode(chaincodeName, args.stream().map(x -> x.getBytes(UTF_8)).collect(toList()), channel);
}

/**
* Invoke another chaincode using the same transaction context.
*
* This is a convenience version of {@link #invokeChaincode(String, List)}.
* The string args will be encoded into as UTF-8 bytes.
* The string args will be encoded into as UTF-8 bytes.
*
*
* @param chaincodeName Name of chaincode to be invoked.
* @param args Arguments to pass on to the called chaincode.
* @param chaincodeName
* Name of chaincode to be invoked.
* @param args
* Arguments to pass on to the called chaincode.
* @return
*/
default Response invokeChaincodeWithStringArgs(String chaincodeName, List<String> args) {
Expand All @@ -186,11 +226,13 @@ default Response invokeChaincodeWithStringArgs(String chaincodeName, List<String
* Invoke another chaincode using the same transaction context.
*
* This is a convenience version of {@link #invokeChaincode(String, List)}.
* The string args will be encoded into as UTF-8 bytes.
* The string args will be encoded into as UTF-8 bytes.
*
*
* @param chaincodeName Name of chaincode to be invoked.
* @param args Arguments to pass on to the called chaincode.
* @param chaincodeName
* Name of chaincode to be invoked.
* @param args
* Arguments to pass on to the called chaincode.
* @return
*/
default Response invokeChaincodeWithStringArgs(final String chaincodeName, final String... args) {
Expand All @@ -203,8 +245,7 @@ default Response invokeChaincodeWithStringArgs(final String chaincodeName, final
*
* @param key
* name of the value
* @return value
* the value read from the ledger
* @return value the value read from the ledger
*/
default String getStringState(String key) {
return new String(getState(key), UTF_8);
Expand All @@ -225,6 +266,7 @@ default void putStringState(String key, String value) {
/**
* Returns the CHAINCODE type event that will be posted to interested
* clients when the chaincode's result is committed to the ledger.
*
* @return the chaincode event or null
*/
ChaincodeEvent getEvent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,28 @@
limitations under the License.
*/

package org.hyperledger.fabric.shim;
package org.hyperledger.fabric.shim.impl;

import static java.util.stream.Collectors.toList;

import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperledger.fabric.protos.ledger.queryresult.KvQueryResult.KV;
import org.hyperledger.fabric.protos.peer.ChaincodeEventPackage.ChaincodeEvent;
import org.hyperledger.fabric.protos.peer.ChaincodeShim.QueryResultBytes;
import org.hyperledger.fabric.protos.peer.ProposalResponsePackage.Response;
import org.hyperledger.fabric.shim.ChaincodeStub;
import org.hyperledger.fabric.shim.ledger.CompositeKey;
import org.hyperledger.fabric.shim.ledger.KeyValue;
import org.hyperledger.fabric.shim.ledger.QueryResultsIterator;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;

class ChaincodeStubImpl implements ChaincodeStub {

Expand All @@ -39,7 +46,7 @@ class ChaincodeStubImpl implements ChaincodeStub {
private final List<ByteString> args;
private ChaincodeEvent event;

public ChaincodeStubImpl(String uuid, Handler handler, List<ByteString> args) {
ChaincodeStubImpl(String uuid, Handler handler, List<ByteString> args) {
this.txid = uuid;
this.handler = handler;
this.args = Collections.unmodifiableList(args);
Expand Down Expand Up @@ -135,6 +142,35 @@ public void delState(String key) {
handler.handleDeleteState(key, txid);
}

/* (non-Javadoc)
* @see org.hyperledger.fabric.shim.ChaincodeStub#getStateByRange(java.lang.String, java.lang.String)
*/
@Override
public QueryResultsIterator<KeyValue> getStateByRange(String startKey, String endKey) {
return new QueryResultsIteratorImpl<KeyValue>(this.handler, getTxId(),
handler.handleGetStateByRange(getTxId(), startKey, endKey),
queryResultBytesToKv.andThen(KeyValueImpl::new)
);
}

private Function<QueryResultBytes, KV> queryResultBytesToKv = new Function<QueryResultBytes, KV>() {
public KV apply(QueryResultBytes queryResultBytes) {
try {
return KV.parseFrom(queryResultBytes.getResultBytes());
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException(e);
}
};
};

/* (non-Javadoc)
* @see org.hyperledger.fabric.shim.ChaincodeStub#getStateByPartialCompositeKey(java.lang.String)
*/
@Override
public QueryResultsIterator<KeyValue> getStateByPartialCompositeKey(String compositeKey) {
return getStateByRange(compositeKey, compositeKey + "\udbff\udfff");
}

/* (non-Javadoc)
* @see org.hyperledger.fabric.shim.ChaincodeStub#createCompositeKey(java.lang.String, java.lang.String[])
*/
Expand Down
Loading

0 comments on commit 5858fbb

Please sign in to comment.