Skip to content

Commit

Permalink
[FAB-3311] java cc get history for key
Browse files Browse the repository at this point in the history
- new KeyModification type
- QueryResultsIterator<KeyModification> ChaincodeStub.getHistoryForKey(key)
- QueryResultsIterator<KeyModification> Handler.handleGetHistoryForKey(key)

Change-Id: I3d4e8014d3c2dfa210483350968e439edbe756c7
Signed-off-by: Luis Sanchez <sanchezl@us.ibm.com>
  • Loading branch information
Luis Sanchez committed Apr 26, 2017
1 parent 6ad95f6 commit fe8d1da
Show file tree
Hide file tree
Showing 6 changed files with 279 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
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.KeyModification;
import org.hyperledger.fabric.shim.ledger.KeyValue;
import org.hyperledger.fabric.shim.ledger.QueryResultsIterator;

Expand Down Expand Up @@ -175,6 +176,14 @@ public interface ChaincodeStub {
*/
QueryResultsIterator<KeyValue> getQueryResult(String query);

/**
* Returns the history of the specified key's values across time.
*
* @param key
* @return an {@link Iterable} of {@link KeyModification}
*/
QueryResultsIterator<KeyModification> getHistoryForKey(String key);

/**
* Defines the CHAINCODE type event that will be posted to interested
* clients when the chaincode's result is committed to the ledger.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperledger.fabric.protos.ledger.queryresult.KvQueryResult;
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.KeyModification;
import org.hyperledger.fabric.shim.ledger.KeyValue;
import org.hyperledger.fabric.shim.ledger.QueryResultsIterator;

Expand Down Expand Up @@ -198,6 +200,24 @@ public QueryResultsIterator<KeyValue> getQueryResult(String query) {
);
}

@Override
public QueryResultsIterator<KeyModification> getHistoryForKey(String key) {
return new QueryResultsIteratorImpl<KeyModification>(this.handler, getTxId(),
handler.handleGetHistoryForKey(getTxId(), key),
queryResultBytesToKeyModification.andThen(KeyModificationImpl::new)
);
}

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

/* (non-Javadoc)
* @see org.hyperledger.fabric.shim.ChaincodeStub#invokeChaincode(java.lang.String, java.util.List, java.lang.String)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,12 @@ QueryResponse handleGetQueryResult(String txId, String query) {
.build().toByteString());
}

QueryResponse handleGetHistoryForKey(String txId, String key) {
return invokeQueryResponseMessage(txId, Type.GET_HISTORY_FOR_KEY, GetQueryResult.newBuilder()
.setQuery(key)
.build().toByteString());
}

private QueryResponse invokeQueryResponseMessage(String txId, ChaincodeMessage.Type type, ByteString payload) {
try {
return QueryResponse.parseFrom(invokeChaincodeSupport(txId, type, payload)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
Copyright IBM 2017 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 org.hyperledger.fabric.shim.impl;

import java.time.Instant;

import org.hyperledger.fabric.protos.ledger.queryresult.KvQueryResult;
import org.hyperledger.fabric.shim.ledger.KeyModification;

import com.google.protobuf.ByteString;

public class KeyModificationImpl implements KeyModification {

private final String txId;
private final ByteString value;
private final java.time.Instant timestamp;
private final boolean deleted;

KeyModificationImpl(KvQueryResult.KeyModification km) {
this.txId = km.getTxId();
this.value = km.getValue();
this.timestamp = Instant.ofEpochSecond(km.getTimestamp().getSeconds(), km.getTimestamp().getNanos());
this.deleted = km.getIsDelete();
}

/*
* (non-Javadoc)
*
* @see org.hyperledger.fabric.shim.impl.KeyModification#getTxId()
*/
@Override
public String getTxId() {
return txId;
}

/*
* (non-Javadoc)
*
* @see org.hyperledger.fabric.shim.impl.KeyModification#getValue()
*/
@Override
public byte[] getValue() {
return value.toByteArray();
}

/*
* (non-Javadoc)
*
* @see org.hyperledger.fabric.shim.impl.KeyModification#getStringValue()
*/
@Override
public String getStringValue() {
return value.toStringUtf8();
}

/*
* (non-Javadoc)
*
* @see org.hyperledger.fabric.shim.impl.KeyModification#getTimestamp()
*/
@Override
public java.time.Instant getTimestamp() {
return timestamp;
}

/*
* (non-Javadoc)
*
* @see org.hyperledger.fabric.shim.impl.KeyModification#isDeleted()
*/
@Override
public boolean isDeleted() {
return deleted;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Copyright IBM 2017 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 org.hyperledger.fabric.shim.ledger;

public interface KeyModification {

/**
* Returns the transaction id.
*
* @return
*/
String getTxId();

/**
* Returns the key's value at the time returned by {@link #getTimestamp()}.
*
* @return
*/
byte[] getValue();

/**
* Returns the key's value at the time returned by {@link #getTimestamp()},
* decoded as a UTF-8 string.
*
* @return
*/
String getStringValue();

/**
* Returns the timestamp of the key modification entry.
*
* @return
*/
java.time.Instant getTimestamp();

/**
* Returns the deletion marker.
*
* @return
*/
boolean isDeleted();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
Copyright IBM 2017 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 org.hyperledger.fabric.shim.impl;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

import java.util.stream.Stream;

import org.hyperledger.fabric.protos.ledger.queryresult.KvQueryResult;
import org.hyperledger.fabric.shim.ledger.KeyModification;
import org.junit.Test;

import com.google.protobuf.ByteString;
import com.google.protobuf.Timestamp;

public class KeyModificationImplTest {

@Test
public void testKeyModificationImpl() {
new KeyModificationImpl(KvQueryResult.KeyModification.newBuilder()
.setTxId("txid")
.setValue(ByteString.copyFromUtf8("value"))
.setTimestamp(Timestamp.newBuilder()
.setSeconds(1234567890)
.setNanos(123456789))
.setIsDelete(true)
.build()
);
}

@Test
public void testGetTxId() {
final KeyModification km = new KeyModificationImpl(KvQueryResult.KeyModification.newBuilder()
.setTxId("txid")
.build()
);
assertThat(km.getTxId(), is(equalTo("txid")));
}

@Test
public void testGetValue() {
final KeyModification km = new KeyModificationImpl(KvQueryResult.KeyModification.newBuilder()
.setValue(ByteString.copyFromUtf8("value"))
.build()
);
assertThat(km.getValue(), is(equalTo("value".getBytes(UTF_8))));
}

@Test
public void testGetStringValue() {
final KeyModification km = new KeyModificationImpl(KvQueryResult.KeyModification.newBuilder()
.setValue(ByteString.copyFromUtf8("value"))
.build()
);
assertThat(km.getStringValue(), is(equalTo("value")));
}

@Test
public void testGetTimestamp() {
final KeyModification km = new KeyModificationImpl(KvQueryResult.KeyModification.newBuilder()
.setTimestamp(Timestamp.newBuilder()
.setSeconds(1234567890L)
.setNanos(123456789))
.build()
);
assertThat(km.getTimestamp(), hasProperty("epochSecond", equalTo(1234567890L)));
assertThat(km.getTimestamp(), hasProperty("nano", equalTo(123456789)));
}

@Test
public void testIsDeleted() {
Stream.of(true, false)
.forEach(b -> {
final KeyModification km = new KeyModificationImpl(KvQueryResult.KeyModification.newBuilder()
.setIsDelete(b)
.build()
);
assertThat(km.isDeleted(), is(b));
});
}

}

0 comments on commit fe8d1da

Please sign in to comment.